diff --git a/PlexRequests.Helpers/Permissions/Permissions.cs b/PlexRequests.Helpers/Permissions/Permissions.cs index 1afd34edb..f36f4fcb2 100644 --- a/PlexRequests.Helpers/Permissions/Permissions.cs +++ b/PlexRequests.Helpers/Permissions/Permissions.cs @@ -58,6 +58,9 @@ namespace PlexRequests.Helpers.Permissions AutoApproveTv = 128, [Display(Name = "Auto Approve Album Requests")] - AutoApproveAlbum = 256 + AutoApproveAlbum = 256, + + [Display(Name = "Manage Requests")] + ManageRequests = 512 } } \ No newline at end of file diff --git a/PlexRequests.UI/Helpers/SecurityExtensions.cs b/PlexRequests.UI/Helpers/SecurityExtensions.cs index 3505cf7e0..a5dcf61de 100644 --- a/PlexRequests.UI/Helpers/SecurityExtensions.cs +++ b/PlexRequests.UI/Helpers/SecurityExtensions.cs @@ -127,7 +127,7 @@ namespace PlexRequests.UI.Helpers public bool HasPermissions(IUserIdentity user, Permissions perm) { - if (user == null) return false; + if (user == null) return false; var dbUser = UserRepository.GetUserByUsername(user.UserName); @@ -138,6 +138,27 @@ namespace PlexRequests.UI.Helpers return result; } + public bool HasAnyPermissions(IUserIdentity user, params Permissions[] perm) + { + if (user == null) return false; + + var dbUser = UserRepository.GetUserByUsername(user.UserName); + + if (dbUser == null) return false; + + var permissions = (Permissions)dbUser.Permissions; + foreach (var p in perm) + { + var result = permissions.HasFlag(p); + if (result) + { + return true; + } + } + + return false; + } + public Response HasPermissionsRedirect(Permissions perm, NancyContext context, string routeName, HttpStatusCode code) { var url = Linker.BuildRelativeUri(context, routeName); diff --git a/PlexRequests.UI/Modules/ApprovalModule.cs b/PlexRequests.UI/Modules/ApprovalModule.cs index 5105b929a..8d3cf0c87 100644 --- a/PlexRequests.UI/Modules/ApprovalModule.cs +++ b/PlexRequests.UI/Modules/ApprovalModule.cs @@ -40,6 +40,7 @@ using PlexRequests.Core; using PlexRequests.Core.Queue; using PlexRequests.Core.SettingModels; using PlexRequests.Helpers; +using PlexRequests.Helpers.Permissions; using PlexRequests.Store; using PlexRequests.UI.Helpers; using PlexRequests.UI.Models; @@ -55,6 +56,9 @@ namespace PlexRequests.UI.Modules { this.RequiresAnyClaim(UserClaims.Admin, UserClaims.PowerUser); + Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx); + Before += (ctx) => Security.AdminLoginRedirect(Permissions.ManageRequests, ctx); + Service = service; CpService = cpService; CpApi = cpApi; diff --git a/PlexRequests.UI/Modules/BaseModule.cs b/PlexRequests.UI/Modules/BaseModule.cs index 2c2fb7467..7dc91ccca 100644 --- a/PlexRequests.UI/Modules/BaseModule.cs +++ b/PlexRequests.UI/Modules/BaseModule.cs @@ -140,7 +140,6 @@ namespace PlexRequests.UI.Modules var permissions = (Permissions) user.Permissions; return permissions.HasFlag(Permissions.Administrator); - // TODO: Check admin role } } diff --git a/PlexRequests.UI/Modules/IssuesModule.cs b/PlexRequests.UI/Modules/IssuesModule.cs index 864764f9f..e3352c08a 100644 --- a/PlexRequests.UI/Modules/IssuesModule.cs +++ b/PlexRequests.UI/Modules/IssuesModule.cs @@ -15,6 +15,7 @@ using PlexRequests.Core; using PlexRequests.Core.Models; using PlexRequests.Core.SettingModels; using PlexRequests.Helpers; +using PlexRequests.Helpers.Permissions; using PlexRequests.Services.Interfaces; using PlexRequests.Services.Notification; using PlexRequests.Store; @@ -78,7 +79,8 @@ namespace PlexRequests.UI.Modules foreach (var i in issuesModels) { - var model = new IssuesViewModel { Id = i.Id, RequestId = i.RequestId, Title = i.Title, Type = i.Type.ToString().ToCamelCaseWords(), Admin = IsAdmin }; + var model = new IssuesViewModel { Id = i.Id, RequestId = i.RequestId, Title = i.Title, Type = i.Type.ToString().ToCamelCaseWords(), Admin = Security.HasAnyPermissions(User, Permissions.Administrator, Permissions.ManageRequests) + }; // Create a string with all of the current issue states with a "," delimiter in e.g. Wrong Content, Playback Issues var state = i.Issues.Select(x => x.Issue).ToArray(); @@ -366,7 +368,11 @@ namespace PlexRequests.UI.Modules { try { - this.RequiresAnyClaim(UserClaims.Admin, UserClaims.PowerUser); + if (!Security.HasAnyPermissions(User, Permissions.Administrator, Permissions.ManageRequests)) + { + return Response.AsJson(new JsonResponseModel { Result = false, Message = "Sorry, you do not have the correct permissions to remove an issue." }); + } + var issue = await IssuesService.GetAsync(issueId); var request = await RequestService.GetAsync(issue.RequestId); if (request.Id > 0) @@ -399,7 +405,11 @@ namespace PlexRequests.UI.Modules { try { - this.RequiresAnyClaim(UserClaims.Admin, UserClaims.PowerUser); + if (!Security.HasAnyPermissions(User, Permissions.Administrator, Permissions.ManageRequests)) + { + return View["Index"]; + } + var issue = await IssuesService.GetAsync(issueId); issue.IssueStatus = status; @@ -417,7 +427,11 @@ namespace PlexRequests.UI.Modules private async Task ClearIssue(int issueId, IssueState state) { - this.RequiresAnyClaim(UserClaims.Admin, UserClaims.PowerUser); + if (!Security.HasAnyPermissions(User, Permissions.Administrator, Permissions.ManageRequests)) + { + return View["Index"]; + } + var issue = await IssuesService.GetAsync(issueId); var toRemove = issue.Issues.FirstOrDefault(x => x.Issue == state); @@ -430,7 +444,11 @@ namespace PlexRequests.UI.Modules private async Task AddNote(int requestId, string noteArea, IssueState state) { - this.RequiresAnyClaim(UserClaims.Admin, UserClaims.PowerUser); + if (!Security.HasAnyPermissions(User, Permissions.Administrator, Permissions.ManageRequests)) + { + return Response.AsJson(new JsonResponseModel { Result = false, Message = "Sorry, you do not have the correct permissions to add a note." }); + } + var issue = await IssuesService.GetAsync(requestId); if (issue == null) { diff --git a/PlexRequests.UI/Modules/RequestsModule.cs b/PlexRequests.UI/Modules/RequestsModule.cs index 068c3de16..1b95841e6 100644 --- a/PlexRequests.UI/Modules/RequestsModule.cs +++ b/PlexRequests.UI/Modules/RequestsModule.cs @@ -39,7 +39,6 @@ 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; @@ -48,7 +47,7 @@ using NLog; using PlexRequests.Core.Models; using PlexRequests.Helpers.Analytics; - +using PlexRequests.Helpers.Permissions; using Action = PlexRequests.Helpers.Analytics.Action; namespace PlexRequests.UI.Modules @@ -157,6 +156,8 @@ namespace PlexRequests.UI.Modules } } + + var canManageRequest = Security.HasAnyPermissions(User, Permissions.Administrator, Permissions.ManageRequests); var viewModel = dbMovies.Select(movie => new RequestViewModel { ProviderId = movie.ProviderId, @@ -173,10 +174,10 @@ namespace PlexRequests.UI.Modules Approved = movie.Available || movie.Approved, Title = movie.Title, Overview = movie.Overview, - RequestedUsers = IsAdmin ? movie.AllUsers.ToArray() : new string[] { }, + RequestedUsers = canManageRequest ? movie.AllUsers.ToArray() : new string[] { }, ReleaseYear = movie.ReleaseDate.Year.ToString(), Available = movie.Available, - Admin = IsAdmin, + Admin = canManageRequest, IssueId = movie.IssueId, Denied = movie.Denied, DeniedReason = movie.DeniedReason, @@ -230,6 +231,7 @@ namespace PlexRequests.UI.Modules } + var canManageRequest = Security.HasAnyPermissions(User, Permissions.Administrator, Permissions.ManageRequests); var viewModel = dbTv.Select(tv => new RequestViewModel { ProviderId = tv.ProviderId, @@ -246,10 +248,10 @@ namespace PlexRequests.UI.Modules Approved = tv.Available || tv.Approved, Title = tv.Title, Overview = tv.Overview, - RequestedUsers = IsAdmin ? tv.AllUsers.ToArray() : new string[] { }, + RequestedUsers = canManageRequest ? tv.AllUsers.ToArray() : new string[] { }, ReleaseYear = tv.ReleaseDate.Year.ToString(), Available = tv.Available, - Admin = IsAdmin, + Admin = canManageRequest, IssueId = tv.IssueId, Denied = tv.Denied, DeniedReason = tv.DeniedReason, @@ -270,7 +272,7 @@ namespace PlexRequests.UI.Modules { dbAlbum = dbAlbum.Where(x => x.UserHasRequested(Username)); } - + var canManageRequest = Security.HasAnyPermissions(User, Permissions.Administrator, Permissions.ManageRequests); var viewModel = dbAlbum.Select(album => { return new RequestViewModel @@ -289,10 +291,10 @@ namespace PlexRequests.UI.Modules Approved = album.Available || album.Approved, Title = album.Title, Overview = album.Overview, - RequestedUsers = IsAdmin ? album.AllUsers.ToArray() : new string[] { }, + RequestedUsers = canManageRequest ? album.AllUsers.ToArray() : new string[] { }, ReleaseYear = album.ReleaseDate.Year.ToString(), Available = album.Available, - Admin = IsAdmin, + Admin = canManageRequest, IssueId = album.IssueId, Denied = album.Denied, DeniedReason = album.DeniedReason, @@ -308,7 +310,12 @@ namespace PlexRequests.UI.Modules private async Task DeleteRequest(int requestid) { - this.RequiresAnyClaim(UserClaims.Admin, UserClaims.PowerUser); + if (!Security.HasAnyPermissions(User, Permissions.Administrator, Permissions.ManageRequests)) + { + return Response.AsJson(new JsonResponseModel { Result = true }); + } + + Analytics.TrackEventAsync(Category.Requests, Action.Delete, "Delete Request", Username, CookieHelper.GetAnalyticClientId(Cookies)); var currentEntity = await Service.GetAsync(requestid); @@ -326,6 +333,10 @@ namespace PlexRequests.UI.Modules /// private async Task ReportIssue(int requestId, IssueState issue, string comment) { + if (!Security.HasPermissions(User, Permissions.ReportIssue)) + { + return Response.AsJson(new JsonResponseModel { Result = false, Message = "Sorry, you do not have the correct permissions to report an issue." }); + } var originalRequest = await Service.GetAsync(requestId); if (originalRequest == null) { @@ -356,7 +367,10 @@ namespace PlexRequests.UI.Modules private async Task ClearIssue(int requestId) { - this.RequiresAnyClaim(UserClaims.Admin, UserClaims.PowerUser); + if (!Security.HasAnyPermissions(User, Permissions.Administrator, Permissions.ManageRequests)) + { + return Response.AsJson(new JsonResponseModel { Result = false, Message = "Sorry, you do not have the correct permissions to clear an issue." }); + } var originalRequest = await Service.GetAsync(requestId); if (originalRequest == null) @@ -374,7 +388,11 @@ namespace PlexRequests.UI.Modules private async Task ChangeRequestAvailability(int requestId, bool available) { - this.RequiresAnyClaim(UserClaims.Admin, UserClaims.PowerUser); + if (!Security.HasAnyPermissions(User, Permissions.Administrator, Permissions.ManageRequests)) + { + return Response.AsJson(new JsonResponseModel { Result = false, Message = "Sorry, you do not have the correct permissions to change a request." }); + } + 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) diff --git a/PlexRequests.UI/Modules/SearchModule.cs b/PlexRequests.UI/Modules/SearchModule.cs index 8d398d1f3..304ebadc2 100644 --- a/PlexRequests.UI/Modules/SearchModule.cs +++ b/PlexRequests.UI/Modules/SearchModule.cs @@ -465,7 +465,7 @@ namespace PlexRequests.UI.Modules private async Task RequestMovie(int movieId) { - if (Security.DoesNotHavePermissions(Permissions.ReadOnlyUser, User)) + if (Security.HasPermissions(User, Permissions.ReadOnlyUser) || !Security.HasPermissions(User, Permissions.RequestMovie)) { return Response.AsJson(new JsonResponseModel @@ -616,7 +616,7 @@ namespace PlexRequests.UI.Modules /// private async Task RequestTvShow(int showId, string seasons) { - if (Security.HasPermissions(User, Permissions.ReadOnlyUser)) + if (Security.HasPermissions(User, Permissions.ReadOnlyUser) || !Security.HasPermissions(User, Permissions.RequestTvShow)) { return Response.AsJson(new JsonResponseModel() @@ -977,14 +977,11 @@ namespace PlexRequests.UI.Modules var sendNotification = type.ShouldAutoApprove(prSettings, IsAdmin, Username) ? !prSettings.IgnoreNotifyForAutoApprovedRequests : true; - var claims = Context.CurrentUser?.Claims; - if (claims != null) + + if (IsAdmin) { - var enumerable = claims as string[] ?? claims.ToArray(); - if (enumerable.Contains(UserClaims.Admin) || enumerable.Contains(UserClaims.PowerUser)) - { - sendNotification = false; // Don't bother sending a notification if the user is an admin - } + sendNotification = false; // Don't bother sending a notification if the user is an admin + } return sendNotification; } @@ -992,6 +989,16 @@ namespace PlexRequests.UI.Modules private async Task RequestAlbum(string releaseId) { + if (Security.HasPermissions(User, Permissions.ReadOnlyUser) || !Security.HasPermissions(User, Permissions.RequestMusic)) + { + return + Response.AsJson(new JsonResponseModel + { + Result = false, + Message = "Sorry, you do not have the correct permissions to request music!" + }); + } + var settings = await PrService.GetSettingsAsync(); if (!await CheckRequestLimit(settings, RequestType.Album)) { diff --git a/PlexRequests.UI/Views/Issues/Details.cshtml b/PlexRequests.UI/Views/Issues/Details.cshtml index 6bdd4f4ce..21ca56637 100644 --- a/PlexRequests.UI/Views/Issues/Details.cshtml +++ b/PlexRequests.UI/Views/Issues/Details.cshtml @@ -1,6 +1,7 @@ @using System.Linq @using PlexRequests.Core.Models @using PlexRequests.Helpers +@using PlexRequests.Helpers.Permissions @using PlexRequests.UI.Helpers @{ var baseUrl = Html.GetBaseUrl(); @@ -10,16 +11,8 @@ formAction = "/" + baseUrl.ToHtmlString(); } - var isAdmin = false; + var isAdmin = Html.HasAnyPermission((int)Permissions.Administrator) || Html.HasAnyPermission((int)Permissions.ManageRequests); - if (Context.CurrentUser != null) - { - var claims = Context.CurrentUser.Claims.ToList(); - if (claims.Contains("Admin") || claims.Contains("PowerUser")) - { - isAdmin = true; - } - } }

Details