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 @@
+
+
+