From 53b7425f6711e250935e7bb024c38ff6c62e07d9 Mon Sep 17 00:00:00 2001 From: TheCatLady <52870424+TheCatLady@users.noreply.github.com> Date: Sun, 14 Feb 2021 07:40:18 -0500 Subject: [PATCH] feat(ui): Add separate permissions for 4K auto approval (#908) * Clarify & fix permission descriptions * Automatically check & disable auto-approve permission options when 'Manage Requests' permission is selected --- server/lib/permissions.ts | 3 + server/routes/request.ts | 60 +++++++++++++++---- src/components/PermissionEdit/index.tsx | 55 +++++++++++++---- src/components/PermissionOption/index.tsx | 17 +++++- .../RequestModal/MovieRequestModal.tsx | 20 +++++-- .../RequestModal/TvRequestModal.tsx | 8 ++- src/i18n/locale/en.json | 20 ++++--- 7 files changed, 148 insertions(+), 35 deletions(-) diff --git a/server/lib/permissions.ts b/server/lib/permissions.ts index f0d45acd..5006a004 100644 --- a/server/lib/permissions.ts +++ b/server/lib/permissions.ts @@ -14,6 +14,9 @@ export enum Permission { REQUEST_4K_TV = 4096, REQUEST_ADVANCED = 8192, REQUEST_VIEW = 16384, + AUTO_APPROVE_4K = 32768, + AUTO_APPROVE_4K_MOVIE = 65536, + AUTO_APPROVE_4K_TV = 131072, } export interface PermissionCheckOptions { diff --git a/server/routes/request.ts b/server/routes/request.ts index e63d7121..f81f3b28 100644 --- a/server/routes/request.ts +++ b/server/routes/request.ts @@ -213,13 +213,29 @@ requestRoutes.post( requestedBy: requestUser, // If the user is an admin or has the "auto approve" permission, automatically approve the request status: - req.user?.hasPermission(Permission.AUTO_APPROVE) || - req.user?.hasPermission(Permission.AUTO_APPROVE_MOVIE) + req.user?.hasPermission( + req.body.is4k + ? Permission.AUTO_APPROVE_4K + : Permission.AUTO_APPROVE + ) || + req.user?.hasPermission( + req.body.is4k + ? Permission.AUTO_APPROVE_4K_MOVIE + : Permission.AUTO_APPROVE_MOVIE + ) ? MediaRequestStatus.APPROVED : MediaRequestStatus.PENDING, modifiedBy: - req.user?.hasPermission(Permission.AUTO_APPROVE) || - req.user?.hasPermission(Permission.AUTO_APPROVE_MOVIE) + req.user?.hasPermission( + req.body.is4k + ? Permission.AUTO_APPROVE_4K + : Permission.AUTO_APPROVE + ) || + req.user?.hasPermission( + req.body.is4k + ? Permission.AUTO_APPROVE_4K_MOVIE + : Permission.AUTO_APPROVE_MOVIE + ) ? req.user : undefined, is4k: req.body.is4k, @@ -274,13 +290,29 @@ requestRoutes.post( requestedBy: requestUser, // If the user is an admin or has the "auto approve" permission, automatically approve the request status: - req.user?.hasPermission(Permission.AUTO_APPROVE) || - req.user?.hasPermission(Permission.AUTO_APPROVE_TV) + req.user?.hasPermission( + req.body.is4k + ? Permission.AUTO_APPROVE_4K + : Permission.AUTO_APPROVE + ) || + req.user?.hasPermission( + req.body.is4k + ? Permission.AUTO_APPROVE_4K_TV + : Permission.AUTO_APPROVE_TV + ) ? MediaRequestStatus.APPROVED : MediaRequestStatus.PENDING, modifiedBy: - req.user?.hasPermission(Permission.AUTO_APPROVE) || - req.user?.hasPermission(Permission.AUTO_APPROVE_TV) + req.user?.hasPermission( + req.body.is4k + ? Permission.AUTO_APPROVE_4K + : Permission.AUTO_APPROVE + ) || + req.user?.hasPermission( + req.body.is4k + ? Permission.AUTO_APPROVE_4K_TV + : Permission.AUTO_APPROVE_TV + ) ? req.user : undefined, is4k: req.body.is4k, @@ -293,8 +325,16 @@ requestRoutes.post( new SeasonRequest({ seasonNumber: sn, status: - req.user?.hasPermission(Permission.AUTO_APPROVE) || - req.user?.hasPermission(Permission.AUTO_APPROVE_TV) + req.user?.hasPermission( + req.body.is4k + ? Permission.AUTO_APPROVE_4K + : Permission.AUTO_APPROVE + ) || + req.user?.hasPermission( + req.body.is4k + ? Permission.AUTO_APPROVE_4K_TV + : Permission.AUTO_APPROVE_TV + ) ? MediaRequestStatus.APPROVED : MediaRequestStatus.PENDING, }) diff --git a/src/components/PermissionEdit/index.tsx b/src/components/PermissionEdit/index.tsx index 58428b75..68701a44 100644 --- a/src/components/PermissionEdit/index.tsx +++ b/src/components/PermissionEdit/index.tsx @@ -9,27 +9,36 @@ export const messages = defineMessages({ 'Full administrator access. Bypasses all permission checks.', users: 'Manage Users', usersDescription: - 'Grants permission to manage Overseerr users. Users with this permission cannot modify users with Administrator privilege, or grant it.', + 'Grants permission to manage Overseerr users. Users with this permission cannot modify users with or grant the Admin privilege.', settings: 'Manage Settings', settingsDescription: 'Grants permission to modify all Overseerr settings. A user must have this permission to grant it to others.', managerequests: 'Manage Requests', managerequestsDescription: - 'Grants permission to manage Overseerr requests. This includes approving and denying requests.', + 'Grants permission to manage Overseerr requests. This includes approving and denying requests. All requests made by a user with this permission will be automatically approved regardless of whether or not they have Auto-Approve permissions.', request: 'Request', requestDescription: 'Grants permission to request movies and series.', vote: 'Vote', voteDescription: - 'Grants permission to vote on requests (voting not yet implemented)', - autoapprove: 'Auto Approve', + 'Grants permission to vote on requests (voting not yet implemented).', + autoapprove: 'Auto-Approve', autoapproveDescription: - 'Grants auto approval for any requests made by this user.', - autoapproveMovies: 'Auto Approve Movies', + 'Grants automatic approval for all non-4K requests made by this user.', + autoapproveMovies: 'Auto-Approve Movies', autoapproveMoviesDescription: - 'Grants auto approve for movie requests made by this user.', - autoapproveSeries: 'Auto Approve Series', + 'Grants automatic approval for non-4K movie requests made by this user.', + autoapproveSeries: 'Auto-Approve Series', autoapproveSeriesDescription: - 'Grants auto approve for series requests made by this user.', + 'Grants automatic approval for non-4K series requests made by this user.', + autoapprove4k: 'Auto-Approve 4K', + autoapprove4kDescription: + 'Grants automatic approval for all 4K requests made by this user.', + autoapprove4kMovies: 'Auto-Approve 4K Movies', + autoapprove4kMoviesDescription: + 'Grants automatic approval for 4K movie requests made by this user.', + autoapprove4kSeries: 'Auto-Approve 4K Series', + autoapprove4kSeriesDescription: + 'Grants automatic approval for 4K series requests made by this user.', request4k: 'Request 4K', request4kDescription: 'Grants permission to request 4K movies and series.', request4kMovies: 'Request 4K Movies', @@ -38,9 +47,9 @@ export const messages = defineMessages({ request4kTvDescription: 'Grants permission to request 4K Series.', advancedrequest: 'Advanced Requests', advancedrequestDescription: - 'Grants permission to use advanced request options. (Ex. Changing servers/profiles/paths)', + 'Grants permission to use advanced request options (e.g., changing servers, profiles, or paths).', viewrequests: 'View Requests', - viewrequestsDescription: "Grants permission to view other user's requests.", + viewrequestsDescription: "Grants permission to view other users' requests.", }); interface PermissionEditProps { @@ -145,6 +154,30 @@ export const PermissionEdit: React.FC = ({ }, ], }, + { + id: 'autoapprove4k', + name: intl.formatMessage(messages.autoapprove4k), + description: intl.formatMessage(messages.autoapprove4kDescription), + permission: Permission.AUTO_APPROVE_4K, + children: [ + { + id: 'autoapprove4k-movies', + name: intl.formatMessage(messages.autoapprove4kMovies), + description: intl.formatMessage( + messages.autoapprove4kMoviesDescription + ), + permission: Permission.AUTO_APPROVE_4K_MOVIE, + }, + { + id: 'autoapprove4k-tv', + name: intl.formatMessage(messages.autoapprove4kSeries), + description: intl.formatMessage( + messages.autoapprove4kSeriesDescription + ), + permission: Permission.AUTO_APPROVE_4K_TV, + }, + ], + }, ]; return ( diff --git a/src/components/PermissionOption/index.tsx b/src/components/PermissionOption/index.tsx index b6de4e39..8bf64b3f 100644 --- a/src/components/PermissionOption/index.tsx +++ b/src/components/PermissionOption/index.tsx @@ -25,12 +25,23 @@ const PermissionOption: React.FC = ({ user, parent, }) => { + const autoApprovePermissions = [ + Permission.AUTO_APPROVE, + Permission.AUTO_APPROVE_MOVIE, + Permission.AUTO_APPROVE_TV, + Permission.AUTO_APPROVE_4K, + Permission.AUTO_APPROVE_4K_MOVIE, + Permission.AUTO_APPROVE_4K_TV, + ]; + return ( <>
= ({ disabled={ (option.permission !== Permission.ADMIN && hasPermission(Permission.ADMIN, currentPermission)) || + (autoApprovePermissions.includes(option.permission) && + hasPermission(Permission.MANAGE_REQUESTS, currentPermission)) || (!!parent?.permission && hasPermission(parent.permission, currentPermission)) || (user && @@ -68,7 +81,9 @@ const PermissionOption: React.FC = ({ checked={ hasPermission(option.permission, currentPermission) || (!!parent?.permission && - hasPermission(parent.permission, currentPermission)) + hasPermission(parent.permission, currentPermission)) || + (autoApprovePermissions.includes(option.permission) && + hasPermission(Permission.MANAGE_REQUESTS, currentPermission)) } />
diff --git a/src/components/RequestModal/MovieRequestModal.tsx b/src/components/RequestModal/MovieRequestModal.tsx index 16fc67d9..1f654634 100644 --- a/src/components/RequestModal/MovieRequestModal.tsx +++ b/src/components/RequestModal/MovieRequestModal.tsx @@ -100,8 +100,14 @@ const MovieRequestModal: React.FC = ({ if (response.data) { if (onComplete) { onComplete( - hasPermission(Permission.AUTO_APPROVE) || - hasPermission(Permission.AUTO_APPROVE_MOVIE) + hasPermission( + is4k ? Permission.AUTO_APPROVE_4K : Permission.AUTO_APPROVE + ) || + hasPermission( + is4k + ? Permission.AUTO_APPROVE_4K_MOVIE + : Permission.AUTO_APPROVE_MOVIE + ) ? MediaStatus.PROCESSING : MediaStatus.PENDING ); @@ -275,8 +281,14 @@ const MovieRequestModal: React.FC = ({ iconSvg={} > {(hasPermission(Permission.MANAGE_REQUESTS) || - hasPermission(Permission.AUTO_APPROVE) || - hasPermission(Permission.AUTO_APPROVE_MOVIE)) && ( + hasPermission( + is4k ? Permission.AUTO_APPROVE_4K : Permission.AUTO_APPROVE + ) || + hasPermission( + is4k + ? Permission.AUTO_APPROVE_4K_MOVIE + : Permission.AUTO_APPROVE_MOVIE + )) && (

{intl.formatMessage(messages.requestadmin)} diff --git a/src/components/RequestModal/TvRequestModal.tsx b/src/components/RequestModal/TvRequestModal.tsx index b29f1725..4582607a 100644 --- a/src/components/RequestModal/TvRequestModal.tsx +++ b/src/components/RequestModal/TvRequestModal.tsx @@ -365,8 +365,12 @@ const TvRequestModal: React.FC = ({ } > {(hasPermission(Permission.MANAGE_REQUESTS) || - hasPermission(Permission.AUTO_APPROVE) || - hasPermission(Permission.AUTO_APPROVE_TV)) && + hasPermission( + is4k ? Permission.AUTO_APPROVE_4K : Permission.AUTO_APPROVE + ) || + hasPermission( + is4k ? Permission.AUTO_APPROVE_4K_TV : Permission.AUTO_APPROVE_TV + )) && !editRequest && (