From 185abcb1a58de9320a920dd0bf67daf18f580d07 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Mon, 22 Aug 2016 13:11:03 +0100 Subject: [PATCH] Working on the beta releases page and also the user management --- PlexRequests.Core/PlexRequests.Core.csproj | 1 + .../SettingModels/RequestSettings.cs | 57 +++ PlexRequests.Core/UserMapper.cs | 8 +- .../app/requests/requestsController.js | 51 ++ .../Content/app/requests/requestsService.js | 49 ++ .../userManagement/userManagementService.js | 9 +- .../Models/UserManagementUsersViewModel.cs | 14 + PlexRequests.UI/Modules/RequestsBetaModule.cs | 453 ++++++++++++++++++ .../Modules/UserManagementModule.cs | 25 +- PlexRequests.UI/PlexRequests.UI.csproj | 7 + .../Views/UserManagement/Index.cshtml | 3 + 11 files changed, 657 insertions(+), 20 deletions(-) create mode 100644 PlexRequests.Core/SettingModels/RequestSettings.cs create mode 100644 PlexRequests.UI/Content/app/requests/requestsController.js create mode 100644 PlexRequests.UI/Content/app/requests/requestsService.js create mode 100644 PlexRequests.UI/Modules/RequestsBetaModule.cs diff --git a/PlexRequests.Core/PlexRequests.Core.csproj b/PlexRequests.Core/PlexRequests.Core.csproj index e4448d873..2e2d1b3a1 100644 --- a/PlexRequests.Core/PlexRequests.Core.csproj +++ b/PlexRequests.Core/PlexRequests.Core.csproj @@ -86,6 +86,7 @@ + diff --git a/PlexRequests.Core/SettingModels/RequestSettings.cs b/PlexRequests.Core/SettingModels/RequestSettings.cs new file mode 100644 index 000000000..5a9140947 --- /dev/null +++ b/PlexRequests.Core/SettingModels/RequestSettings.cs @@ -0,0 +1,57 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: RequestSettings.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion + +using System; +using System.Collections.Generic; + +namespace PlexRequests.Core.SettingModels +{ + public sealed class RequestSettings : Settings + { + public OrderType Order { get; set; } + public List Filters { get; set; } + } + + public enum OrderType + { + NewRequests, + OldRequests, + NewReleases, + OldReleases + } + + public enum FilterType + { + // ALL is not here, it's managed in the angular controller + Approved, + NotApproved, + Available, + NotAvailable, + Released, + NotReleased + } +} \ No newline at end of file diff --git a/PlexRequests.Core/UserMapper.cs b/PlexRequests.Core/UserMapper.cs index d4eca3e2a..3c15d548e 100644 --- a/PlexRequests.Core/UserMapper.cs +++ b/PlexRequests.Core/UserMapper.cs @@ -99,7 +99,7 @@ namespace PlexRequests.Core return users.Any(); } - private Guid? CreateUser(string username, string password, string[] claims = default(string[]), UserProperties properties = null) + public Guid? CreateUser(string username, string password, string[] claims = default(string[]), UserProperties properties = null) { var salt = PasswordHasher.GenerateSalt(); @@ -134,10 +134,6 @@ namespace PlexRequests.Core return CreateUser(username, password, new[] { UserClaims.User }, properties); } - public Guid? CreateUser(string username, string password, string[] claims) - { - return CreateUser(username, password, claims, null); - } public IEnumerable GetAllClaims() { @@ -186,7 +182,7 @@ namespace PlexRequests.Core public interface ICustomUserMapper { - Guid? CreateUser(string username, string password, string[] claims); + Guid? CreateUser(string username, string password, string[] claims, UserProperties props); IEnumerable GetAllClaims(); IEnumerable GetUsers(); Task> GetUsersAsync(); diff --git a/PlexRequests.UI/Content/app/requests/requestsController.js b/PlexRequests.UI/Content/app/requests/requestsController.js new file mode 100644 index 000000000..204dcf9a2 --- /dev/null +++ b/PlexRequests.UI/Content/app/requests/requestsController.js @@ -0,0 +1,51 @@ +(function () { + var controller = function($scope, requestsService) { + + $scope.requests = []; + $scope.selectedTab = {}; + $scope.currentPage = 1; + $scope.tabs = []; + + $scope.plexSettings = {}; + $scope.requestSettings = {}; + + // Search + $scope.searchTerm = ""; + + + // Called on page load + $scope.init = function() { + // Get the settings + $scope.plexSettings = requestsService.getPlexRequestSettings(getBaseUrl()); + $scope.requestSettings = requestsService.getRequestSettings(getBaseUrl()); + + if ($scope.plexSettings.SearchForMovies) { + $scope.selectedTab = "movies"; + + // Load the movie Requests + $scope.requests = requestsService.getRequests("movie", getBaseUrl()); + } + }; + + + $scope.changeTab = function(tab) { + // load the data from the tab + switch (tab) { + // Set the selected tab and load the appropriate data + } + + }; + + $scope.search = function() { + $scope.requests = requestsService.getRequests + }; + + function getBaseUrl() { + return $('#baseUrl').val(); + } + + + } + + angular.module('PlexRequests').controller('requestsController', ["$scope", "requestsService", controller]); +}()); \ No newline at end of file diff --git a/PlexRequests.UI/Content/app/requests/requestsService.js b/PlexRequests.UI/Content/app/requests/requestsService.js new file mode 100644 index 000000000..b702c0727 --- /dev/null +++ b/PlexRequests.UI/Content/app/requests/requestsService.js @@ -0,0 +1,49 @@ +(function () { + + var requestsService = function ($http) { + + $http.defaults.headers.common['Content-Type'] = 'application/json'; // Set default headers + + var getRequests = function (type, baseUrl) { + switch (type) { + case "movie": + return $http.get(createBaseUrl(baseUrl, "/requestsbeta/movies")); + case "tv": + return $http.get(createBaseUrl(baseUrl, "/requestsbeta/tvshows")); + case "album": + return $http.get(createBaseUrl(baseUrl, "/requestsbeta/albums")); + } + return null; + }; + + var getPlexRequestSettings = function (baseUrl) { + return $http.get(createBaseUrl(baseUrl, "/requestsbeta/plexrequestsettings")); + } + + var getRequestsSettings = function (baseUrl) { + return $http.get(createBaseUrl(baseUrl, "/requestsbeta/requestsettings")); + } + + var getRequestsSearch = function (type, baseUrl, searchTerm) { + switch (type) { + case "movie": + return $http.get(createBaseUrl(baseUrl, "/requestsbeta/movies/"+ searchTerm)); + case "tv": + return $http.get(createBaseUrl(baseUrl, "/requestsbeta/tvshows/" + searchTerm)); + case "album": + return $http.get(createBaseUrl(baseUrl, "/requestsbeta/albums/" + searchTerm)); + } + return null; + }; + + return { + getRequests: getRequests, + getRequestsSearch: getRequestsSearch, + getPlexRequestSettings: getPlexRequestSettings, + getRequestSettings: getRequestsSettings + }; + } + + angular.module('PlexRequests').factory('requestsService', ["$http", requestsService]); + +}()); \ No newline at end of file diff --git a/PlexRequests.UI/Content/app/userManagement/userManagementService.js b/PlexRequests.UI/Content/app/userManagement/userManagementService.js index b70d1fe26..e1640e3ea 100644 --- a/PlexRequests.UI/Content/app/userManagement/userManagementService.js +++ b/PlexRequests.UI/Content/app/userManagement/userManagementService.js @@ -2,7 +2,7 @@ var userManagementService = function ($http) { - //$http.defaults.headers.common['Content-Type'] = 'application/x-www-form-urlencoded'; // Set default headers + $http.defaults.headers.common['Content-Type'] = 'application/json'; // Set default headers var getUsers = function () { return $http.get('/usermanagement/users'); @@ -13,17 +13,14 @@ return null; } - var claimJson = angular.toJson(claims); - var objectToSerialize = { 'claims': claimJson }; - var data = $.param(user) +"&"+ $.param(objectToSerialize); return $http({ url: '/usermanagement/createuser', method: "POST", - data: data + data: { username: user.username, password: user.password, claims: claims, email: user.email } }); } - var getClaims = function() { + var getClaims = function () { return $http.get('/usermanagement/claims'); } diff --git a/PlexRequests.UI/Models/UserManagementUsersViewModel.cs b/PlexRequests.UI/Models/UserManagementUsersViewModel.cs index 57fcd1f5a..3fbc936ec 100644 --- a/PlexRequests.UI/Models/UserManagementUsersViewModel.cs +++ b/PlexRequests.UI/Models/UserManagementUsersViewModel.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Newtonsoft.Json; namespace PlexRequests.UI.Models { @@ -42,5 +43,18 @@ namespace PlexRequests.UI.Models PlexUser, LocalUser } + + public class UserManagementCreateModel + { + [JsonProperty("username")] + public string Username { get; set; } + [JsonProperty("password")] + public string Password { get; set; } + [JsonProperty("claims")] + public string[] Claims { get; set; } + + [JsonProperty("email")] + public string EmailAddress { get; set; } + } } diff --git a/PlexRequests.UI/Modules/RequestsBetaModule.cs b/PlexRequests.UI/Modules/RequestsBetaModule.cs new file mode 100644 index 000000000..a8a1a6e3f --- /dev/null +++ b/PlexRequests.UI/Modules/RequestsBetaModule.cs @@ -0,0 +1,453 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: RequestsModule.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion + +using System; +using System.Linq; + +using Nancy; +using Nancy.Responses.Negotiation; +using Nancy.Security; + +using PlexRequests.Core; +using PlexRequests.Core.SettingModels; +using PlexRequests.Services.Interfaces; +using PlexRequests.Services.Notification; +using PlexRequests.Store; +using PlexRequests.UI.Models; +using PlexRequests.Helpers; +using PlexRequests.UI.Helpers; +using System.Collections.Generic; +using PlexRequests.Api.Interfaces; +using System.Threading.Tasks; + +using NLog; + +using PlexRequests.Core.Models; +using PlexRequests.Helpers.Analytics; + +using Action = PlexRequests.Helpers.Analytics.Action; + +namespace PlexRequests.UI.Modules +{ + public class RequestsBetaModule : BaseAuthModule + { + public RequestsBetaModule( + IRequestService service, + ISettingsService prSettings, + ISettingsService requestSettings, + ISettingsService plex, + INotificationService notify, + ISettingsService sonarrSettings, + ISettingsService sickRageSettings, + ISettingsService cpSettings, + ICouchPotatoApi cpApi, + ISonarrApi sonarrApi, + ISickRageApi sickRageApi, + ICacheProvider cache, + IAnalytics an) : base("requestsbeta", prSettings) + { + Service = service; + PrSettings = prSettings; + PlexSettings = plex; + NotificationService = notify; + SonarrSettings = sonarrSettings; + SickRageSettings = sickRageSettings; + CpSettings = cpSettings; + SonarrApi = sonarrApi; + SickRageApi = sickRageApi; + CpApi = cpApi; + Cache = cache; + Analytics = an; + + Get["/"] = x => LoadRequests(); + Get["/plexrequestsettings", true] = async (x, ct) => await GetPlexRequestSettings(); + Get["/requestsettings", true] = async (x, ct) => await GetRequestSettings(); + Get["/movies", true] = async (x, ct) => await GetMovies(); + Get["/movies/{searchTerm}", true] = async (x, ct) => await GetMovies((string)x.searchTerm); + + + // Everything below is not being used in the beta page + Get["/tvshows", true] = async (c, ct) => await GetTvShows(); + Get["/albums", true] = async (x, ct) => await GetAlbumRequests(); + Post["/delete", true] = async (x, ct) => await DeleteRequest((int)Request.Form.id); + Post["/reportissue", true] = async (x, ct) => await ReportIssue((int)Request.Form.requestId, (IssueState)(int)Request.Form.issue, null); + Post["/reportissuecomment", true] = async (x, ct) => await ReportIssue((int)Request.Form.requestId, IssueState.Other, (string)Request.Form.commentArea); + + Post["/clearissues", true] = async (x, ct) => await ClearIssue((int)Request.Form.Id); + + Post["/changeavailability", true] = async (x, ct) => await ChangeRequestAvailability((int)Request.Form.Id, (bool)Request.Form.Available); + } + + private static Logger Log = LogManager.GetCurrentClassLogger(); + private IRequestService Service { get; } + private IAnalytics Analytics { get; } + private INotificationService NotificationService { get; } + private ISettingsService PrSettings { get; } + private ISettingsService PlexSettings { get; } + private ISettingsService RequestSettings { get; } + private ISettingsService SonarrSettings { get; } + private ISettingsService SickRageSettings { get; } + private ISettingsService CpSettings { get; } + private ISonarrApi SonarrApi { get; } + private ISickRageApi SickRageApi { get; } + private ICouchPotatoApi CpApi { get; } + private ICacheProvider Cache { get; } + + private Negotiator LoadRequests() + { + return View["Index"]; + } + + private async Task GetPlexRequestSettings() + { + return Response.AsJson(await PrSettings.GetSettingsAsync()); + } + + private async Task GetRequestSettings() + { + return Response.AsJson(await RequestSettings.GetSettingsAsync()); + } + + private async Task GetMovies(string searchTerm = null, bool approved = false, bool notApproved = false, + bool available = false, bool notAvailable = false, bool released = false, bool notReleased = false) + { + var dbMovies = await FilterMovies(searchTerm, approved, notApproved, available, notAvailable, released, notReleased); + var qualities = await GetQualityProfiles(); + var model = MapMoviesToView(dbMovies.ToList(), qualities); + + return Response.AsJson(model); + } + + private async Task GetTvShows() + { + var settingsTask = PrSettings.GetSettingsAsync(); + + var requests = await Service.GetAllAsync(); + requests = requests.Where(x => x.Type == RequestType.TvShow); + + var dbTv = requests; + var settings = await settingsTask; + if (settings.UsersCanViewOnlyOwnRequests && !IsAdmin) + { + dbTv = dbTv.Where(x => x.UserHasRequested(Username)).ToList(); + } + + IEnumerable qualities = new List(); + if (IsAdmin) + { + try + { + var sonarrSettings = await SonarrSettings.GetSettingsAsync(); + if (sonarrSettings.Enabled) + { + var result = Cache.GetOrSetAsync(CacheKeys.SonarrQualityProfiles, async () => + { + return await Task.Run(() => SonarrApi.GetProfiles(sonarrSettings.ApiKey, sonarrSettings.FullUri)); + }); + qualities = result.Result.Select(x => new QualityModel { Id = x.id.ToString(), Name = x.name }).ToList(); + } + else + { + var sickRageSettings = await SickRageSettings.GetSettingsAsync(); + if (sickRageSettings.Enabled) + { + qualities = sickRageSettings.Qualities.Select(x => new QualityModel { Id = x.Key, Name = x.Value }).ToList(); + } + } + } + catch (Exception e) + { + Log.Info(e); + } + + } + + var viewModel = dbTv.Select(tv => new RequestViewModel + { + ProviderId = tv.ProviderId, + Type = tv.Type, + Status = tv.Status, + ImdbId = tv.ImdbId, + Id = tv.Id, + PosterPath = tv.PosterPath, + ReleaseDate = tv.ReleaseDate, + ReleaseDateTicks = tv.ReleaseDate.Ticks, + RequestedDate = tv.RequestedDate, + RequestedDateTicks = DateTimeHelper.OffsetUTCDateTime(tv.RequestedDate, DateTimeOffset).Ticks, + Released = DateTime.Now > tv.ReleaseDate, + Approved = tv.Available || tv.Approved, + Title = tv.Title, + Overview = tv.Overview, + RequestedUsers = IsAdmin ? tv.AllUsers.ToArray() : new string[] { }, + ReleaseYear = tv.ReleaseDate.Year.ToString(), + Available = tv.Available, + Admin = IsAdmin, + IssueId = tv.IssueId, + TvSeriesRequestType = tv.SeasonsRequested, + Qualities = qualities.ToArray(), + Episodes = tv.Episodes.ToArray(), + }).ToList(); + + return Response.AsJson(viewModel); + } + + private async Task GetAlbumRequests() + { + var settings = PrSettings.GetSettings(); + var dbAlbum = await Service.GetAllAsync(); + dbAlbum = dbAlbum.Where(x => x.Type == RequestType.Album); + if (settings.UsersCanViewOnlyOwnRequests && !IsAdmin) + { + dbAlbum = dbAlbum.Where(x => x.UserHasRequested(Username)); + } + + var viewModel = dbAlbum.Select(album => + { + return new RequestViewModel + { + ProviderId = album.ProviderId, + Type = album.Type, + Status = album.Status, + ImdbId = album.ImdbId, + Id = album.Id, + PosterPath = album.PosterPath, + ReleaseDate = album.ReleaseDate, + ReleaseDateTicks = album.ReleaseDate.Ticks, + RequestedDate = album.RequestedDate, + RequestedDateTicks = DateTimeHelper.OffsetUTCDateTime(album.RequestedDate, DateTimeOffset).Ticks, + Released = DateTime.Now > album.ReleaseDate, + Approved = album.Available || album.Approved, + Title = album.Title, + Overview = album.Overview, + RequestedUsers = IsAdmin ? album.AllUsers.ToArray() : new string[] { }, + ReleaseYear = album.ReleaseDate.Year.ToString(), + Available = album.Available, + Admin = IsAdmin, + IssueId = album.IssueId, + TvSeriesRequestType = album.SeasonsRequested, + MusicBrainzId = album.MusicBrainzId, + ArtistName = album.ArtistName + + }; + }).ToList(); + + return Response.AsJson(viewModel); + } + + private async Task DeleteRequest(int requestid) + { + this.RequiresClaims(UserClaims.Admin); + Analytics.TrackEventAsync(Category.Requests, Action.Delete, "Delete Request", Username, CookieHelper.GetAnalyticClientId(Cookies)); + + var currentEntity = await Service.GetAsync(requestid); + await Service.DeleteRequestAsync(currentEntity); + return Response.AsJson(new JsonResponseModel { Result = true }); + } + + /// + /// Reports the issue. + /// Comment can be null if the IssueState != Other + /// + /// The request identifier. + /// The issue. + /// The comment. + /// + private async Task ReportIssue(int requestId, IssueState issue, string comment) + { + var originalRequest = await Service.GetAsync(requestId); + if (originalRequest == null) + { + return Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not add issue, please try again or contact the administrator!" }); + } + originalRequest.Issues = issue; + originalRequest.OtherMessage = !string.IsNullOrEmpty(comment) + ? $"{Username} - {comment}" + : string.Empty; + + + var result = await Service.UpdateRequestAsync(originalRequest); + + var model = new NotificationModel + { + User = Username, + NotificationType = NotificationType.Issue, + Title = originalRequest.Title, + DateTime = DateTime.Now, + Body = issue == IssueState.Other ? comment : issue.ToString().ToCamelCaseWords() + }; + await NotificationService.Publish(model); + + return Response.AsJson(result + ? new JsonResponseModel { Result = true } + : new JsonResponseModel { Result = false, Message = "Could not add issue, please try again or contact the administrator!" }); + } + + private async Task ClearIssue(int requestId) + { + this.RequiresClaims(UserClaims.Admin); + + var originalRequest = await Service.GetAsync(requestId); + if (originalRequest == null) + { + return Response.AsJson(new JsonResponseModel { Result = false, Message = "Request does not exist to clear it!" }); + } + originalRequest.Issues = IssueState.None; + originalRequest.OtherMessage = string.Empty; + + var result = await Service.UpdateRequestAsync(originalRequest); + return Response.AsJson(result + ? new JsonResponseModel { Result = true } + : new JsonResponseModel { Result = false, Message = "Could not clear issue, please try again or check the logs" }); + } + + private async Task ChangeRequestAvailability(int requestId, bool available) + { + this.RequiresClaims(UserClaims.Admin); + Analytics.TrackEventAsync(Category.Requests, Action.Update, available ? "Make request available" : "Make request unavailable", Username, CookieHelper.GetAnalyticClientId(Cookies)); + var originalRequest = await Service.GetAsync(requestId); + if (originalRequest == null) + { + return Response.AsJson(new JsonResponseModel { Result = false, Message = "Request does not exist to change the availability!" }); + } + + originalRequest.Available = available; + + var result = await Service.UpdateRequestAsync(originalRequest); + return Response.AsJson(result + ? new { Result = true, Available = available, Message = string.Empty } + : new { Result = false, Available = false, Message = "Could not update the availability, please try again or check the logs" }); + } + + private List MapMoviesToView(List dbMovies, List qualities) + { + return dbMovies.Select(movie => new RequestViewModel + { + ProviderId = movie.ProviderId, + Type = movie.Type, + Status = movie.Status, + ImdbId = movie.ImdbId, + Id = movie.Id, + PosterPath = movie.PosterPath, + ReleaseDate = movie.ReleaseDate, + ReleaseDateTicks = movie.ReleaseDate.Ticks, + RequestedDate = movie.RequestedDate, + Released = DateTime.Now > movie.ReleaseDate, + RequestedDateTicks = DateTimeHelper.OffsetUTCDateTime(movie.RequestedDate, DateTimeOffset).Ticks, + Approved = movie.Available || movie.Approved, + Title = movie.Title, + Overview = movie.Overview, + RequestedUsers = IsAdmin ? movie.AllUsers.ToArray() : new string[] { }, + ReleaseYear = movie.ReleaseDate.Year.ToString(), + Available = movie.Available, + Admin = IsAdmin, + IssueId = movie.IssueId, + Qualities = qualities.ToArray() + }).ToList(); + } + + private async Task> GetQualityProfiles() + { + var qualities = new List(); + if (IsAdmin) + { + var cpSettings = CpSettings.GetSettings(); + if (cpSettings.Enabled) + { + try + { + var result = await Cache.GetOrSetAsync(CacheKeys.CouchPotatoQualityProfiles, async () => + { + return await Task.Run(() => CpApi.GetProfiles(cpSettings.FullUri, cpSettings.ApiKey)).ConfigureAwait(false); + }); + if (result != null) + { + qualities = result.list.Select(x => new QualityModel { Id = x._id, Name = x.label }).ToList(); + } + } + catch (Exception e) + { + Log.Info(e); + } + } + } + return qualities; + } + + private async Task> FilterMovies(string searchTerm = null, bool approved = false, bool notApproved = false, + bool available = false, bool notAvailable = false, bool released = false, bool notReleased = false) + { + var settings = PrSettings.GetSettings(); + var allRequests = await Service.GetAllAsync(); + allRequests = allRequests.Where(x => x.Type == RequestType.Movie); + + var dbMovies = allRequests; + + if (settings.UsersCanViewOnlyOwnRequests && !IsAdmin) + { + dbMovies = dbMovies.Where(x => x.UserHasRequested(Username)); + } + + // Filter the movies on the search term + if (!string.IsNullOrEmpty(searchTerm)) + { + dbMovies = dbMovies.Where(x => x.Title.Contains(searchTerm)); + } + + if (approved) + { + dbMovies = dbMovies.Where(x => x.Approved); + } + + if (notApproved) + { + dbMovies = dbMovies.Where(x => !x.Approved); + } + + if (available) + { + dbMovies = dbMovies.Where(x => x.Available); + } + + if (notAvailable) + { + dbMovies = dbMovies.Where(x => !x.Available); + } + + if (released) + { + dbMovies = dbMovies.Where(x => DateTime.Now > x.ReleaseDate); + } + + if (notReleased) + { + dbMovies = dbMovies.Where(x => DateTime.Now < x.ReleaseDate); + } + + return dbMovies; + } + } +} diff --git a/PlexRequests.UI/Modules/UserManagementModule.cs b/PlexRequests.UI/Modules/UserManagementModule.cs index f364d9588..efcaeaa39 100644 --- a/PlexRequests.UI/Modules/UserManagementModule.cs +++ b/PlexRequests.UI/Modules/UserManagementModule.cs @@ -4,9 +4,10 @@ using System.Linq; using System.Threading.Tasks; using Nancy; +using Nancy.Extensions; using Nancy.Responses.Negotiation; using Nancy.Security; - +using Newtonsoft.Json; using PlexRequests.Api.Interfaces; using PlexRequests.Core; using PlexRequests.Core.Models; @@ -30,9 +31,9 @@ namespace PlexRequests.UI.Modules Get["/"] = x => Load(); Get["/users", true] = async (x, ct) => await LoadUsers(); - Post["/createuser"] = x => CreateUser(Request.Form["username"].ToString(), Request.Form["password"].ToString(), (string[])Request.Form["claims"]); + Post["/createuser"] = x => CreateUser(); Get["/local/{id}"] = x => LocalDetails((Guid)x.id); - Get["/plex/{id}", true] = async (x,ct) => await PlexDetails(x.id); + Get["/plex/{id}", true] = async (x, ct) => await PlexDetails(x.id); Get["/claims"] = x => GetClaims(); } @@ -58,7 +59,7 @@ namespace PlexRequests.UI.Modules model.Add(new UserManagementUsersViewModel { - Id= user.UserGuid, + Id = user.UserGuid, Claims = claimsString, Username = user.UserName, Type = UserType.LocalUser, @@ -92,9 +93,17 @@ namespace PlexRequests.UI.Modules return Response.AsJson(model); } - private Response CreateUser(string username, string password, string[] claims) + private Response CreateUser() { - if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password)) + var body = Request.Body.AsString(); + if (string.IsNullOrEmpty(body)) + { + return Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not save user, invalid JSON body" }); + } + + var model = JsonConvert.DeserializeObject(body); + + if (string.IsNullOrWhiteSpace(model.Username) || string.IsNullOrWhiteSpace(model.Password)) { return Response.AsJson(new JsonResponseModel { @@ -102,7 +111,7 @@ namespace PlexRequests.UI.Modules Message = "Please enter in a valid Username and Password" }); } - var user = UserMapper.Ce(username, password); + var user = UserMapper.CreateUser(model.Username, model.Password, model.Claims, new UserProperties { EmailAddress = model.EmailAddress }); if (user.HasValue) { return Response.AsJson(user); @@ -151,7 +160,7 @@ namespace PlexRequests.UI.Modules var claims = UserMapper.GetAllClaims(); foreach (var c in claims) { - retVal.Add(new {Name = c, Selected = false}); + retVal.Add(new { Name = c, Selected = false }); } return Response.AsJson(retVal); } diff --git a/PlexRequests.UI/PlexRequests.UI.csproj b/PlexRequests.UI/PlexRequests.UI.csproj index d178bbc92..1779f378b 100644 --- a/PlexRequests.UI/PlexRequests.UI.csproj +++ b/PlexRequests.UI/PlexRequests.UI.csproj @@ -250,6 +250,7 @@ + @@ -282,6 +283,12 @@ Always + + Always + + + Always + PreserveNewest diff --git a/PlexRequests.UI/Views/UserManagement/Index.cshtml b/PlexRequests.UI/Views/UserManagement/Index.cshtml index 561652eb0..8307ef491 100644 --- a/PlexRequests.UI/Views/UserManagement/Index.cshtml +++ b/PlexRequests.UI/Views/UserManagement/Index.cshtml @@ -19,6 +19,9 @@
+
+ +