Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,6 @@ tsconfig.tsbuildinfo

# Config Cache Directory
config/cache

# Allow server directory for Telescope find_files
!/server
4 changes: 1 addition & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
"files.associations": {
"globals.css": "tailwindcss"
},
"i18n-ally.localesPaths": [
"src/i18n/locale"
],
"i18n-ally.localesPaths": ["src/i18n/locale"],
"yaml.format.singleQuote": true
}
6 changes: 3 additions & 3 deletions seerr-api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6843,7 +6843,7 @@ paths:
/media/{mediaId}:
delete:
summary: Delete media item
description: Removes a media item. The `MANAGE_REQUESTS` permission is required to perform this action.
description: Removes a media item. The `MANAGE_REQUESTS` or `DELETE_MEDIA` permission is required to perform this action.
tags:
- media
parameters:
Expand All @@ -6860,7 +6860,7 @@ paths:
/media/{mediaId}/file:
delete:
summary: Delete media file
description: Removes a media file from radarr/sonarr. The `ADMIN` permission is required to perform this action.
description: Removes a media file from radarr/sonarr. The `ADMIN` or `DELETE_MEDIA` permission is required to perform this action.
tags:
- media
parameters:
Expand Down Expand Up @@ -6929,7 +6929,7 @@ paths:
description: |
Returns play count, play duration, and users who have watched the media.

Requires the `ADMIN` permission.
Requires the `ADMIN` or `DELETE_MEDIA` permission.
tags:
- media
parameters:
Expand Down
1 change: 1 addition & 0 deletions server/lib/permissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export enum Permission {
RECENT_VIEW = 67108864,
WATCHLIST_VIEW = 134217728,
MANAGE_BLACKLIST = 268435456,
DELETE_MEDIA = 536870912,
VIEW_BLACKLIST = 1073741824,
}

Expand Down
18 changes: 18 additions & 0 deletions server/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,24 @@ router.get(
}
}
);

router.get(
'/settings/radarr',
isAuthenticated([Permission.ADMIN, Permission.DELETE_MEDIA], { type: 'or' }),
(_req, res) => {
const settings = getSettings();
return res.status(200).json(settings.radarr);
}
);

router.get(
'/settings/sonarr',
isAuthenticated([Permission.ADMIN, Permission.DELETE_MEDIA], { type: 'or' }),
(_req, res) => {
const settings = getSettings();
return res.status(200).json(settings.sonarr);
}
);
router.use('/settings', isAuthenticated(Permission.ADMIN), settingsRoutes);
router.use('/search', isAuthenticated(), searchRoutes);
router.use('/discover', isAuthenticated(), discoverRoutes);
Expand Down
10 changes: 7 additions & 3 deletions server/routes/media.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,9 @@ mediaRoutes.post<

mediaRoutes.delete(
'/:id',
isAuthenticated(Permission.MANAGE_REQUESTS),
isAuthenticated([Permission.MANAGE_REQUESTS, Permission.DELETE_MEDIA], {
type: 'or',
}),
async (req, res, next) => {
try {
const mediaRepository = getRepository(Media);
Expand All @@ -189,7 +191,9 @@ mediaRoutes.delete(

mediaRoutes.delete(
'/:id/file',
isAuthenticated(Permission.MANAGE_REQUESTS),
isAuthenticated([Permission.ADMIN, Permission.DELETE_MEDIA], {
type: 'or',
}),
async (req, res, next) => {
try {
const settings = getSettings();
Expand Down Expand Up @@ -282,7 +286,7 @@ mediaRoutes.delete(

mediaRoutes.get<{ id: string }, MediaWatchDataResponse>(
'/:id/watch_data',
isAuthenticated(Permission.ADMIN),
isAuthenticated([Permission.ADMIN, Permission.DELETE_MEDIA], { type: 'or' }),
async (req, res, next) => {
const settings = getSettings().tautulli;

Expand Down
6 changes: 0 additions & 6 deletions server/routes/settings/radarr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,6 @@ import { Router } from 'express';

const radarrRoutes = Router();

radarrRoutes.get('/', (_req, res) => {
const settings = getSettings();

res.status(200).json(settings.radarr);
});

radarrRoutes.post('/', async (req, res) => {
const settings = getSettings();

Expand Down
6 changes: 0 additions & 6 deletions server/routes/settings/sonarr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,6 @@ import { Router } from 'express';

const sonarrRoutes = Router();

sonarrRoutes.get('/', (_req, res) => {
const settings = getSettings();

res.status(200).json(settings.sonarr);
});

sonarrRoutes.post('/', async (req, res) => {
const settings = getSettings();

Expand Down
19 changes: 13 additions & 6 deletions src/components/ManageSlideOver/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,19 @@ const ManageSlideOver = ({
const { data: watchData } = useSWR<MediaWatchDataResponse>(
settings.currentSettings.mediaServerType === MediaServerType.PLEX &&
data.mediaInfo &&
hasPermission(Permission.ADMIN)
hasPermission([Permission.ADMIN, Permission.DELETE_MEDIA], { type: 'or' })
? `/api/v1/media/${data.mediaInfo.id}/watch_data`
: null
);
const { data: radarrData } = useSWR<RadarrSettings[]>(
hasPermission(Permission.ADMIN) ? '/api/v1/settings/radarr' : null
hasPermission([Permission.ADMIN, Permission.DELETE_MEDIA], { type: 'or' })
? '/api/v1/settings/radarr'
: null
);
const { data: sonarrData } = useSWR<SonarrSettings[]>(
hasPermission(Permission.ADMIN) ? '/api/v1/settings/sonarr' : null
hasPermission([Permission.ADMIN, Permission.DELETE_MEDIA], { type: 'or' })
? '/api/v1/settings/sonarr'
: null
);

const deleteMedia = async () => {
Expand Down Expand Up @@ -312,7 +316,9 @@ const ManageSlideOver = ({
</div>
</div>
)}
{hasPermission(Permission.ADMIN) &&
{hasPermission([Permission.ADMIN, Permission.DELETE_MEDIA], {
type: 'or',
}) &&
(data.mediaInfo?.serviceUrl ||
data.mediaInfo?.tautulliUrl ||
watchData?.data) && (
Expand Down Expand Up @@ -435,8 +441,9 @@ const ManageSlideOver = ({
</Button>
</a>
)}

{hasPermission(Permission.ADMIN) &&
{hasPermission([Permission.ADMIN, Permission.DELETE_MEDIA], {
type: 'or',
}) &&
data?.mediaInfo?.serviceUrl &&
isDefaultService() && (
<div>
Expand Down
5 changes: 4 additions & 1 deletion src/components/MovieDetails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,10 @@ const MovieDetails = ({ movie }: MovieDetailsProps) => {
</Button>
</Tooltip>
)}
{hasPermission(Permission.MANAGE_REQUESTS) &&
{hasPermission(
[Permission.MANAGE_REQUESTS, Permission.DELETE_MEDIA],
{ type: 'or' }
) &&
data.mediaInfo &&
(data.mediaInfo.jellyfinMediaId ||
data.mediaInfo.jellyfinMediaId4k ||
Expand Down
9 changes: 9 additions & 0 deletions src/components/PermissionEdit/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ export const messages = defineMessages('components.PermissionEdit', {
managerequests: 'Manage Requests',
managerequestsDescription:
'Grant permission to manage media requests. All requests made by a user with this permission will be automatically approved.',
deletemedia: 'Delete Media',
deletemediaDescription:
'Grant permission to delete media from Sonarr and Radarr.',
request: 'Request',
requestDescription: 'Grant permission to submit requests for non-4K media.',
requestMovies: 'Request Movies',
Expand Down Expand Up @@ -164,6 +167,12 @@ export const PermissionEdit = ({
},
],
},
{
id: 'deletemedia',
name: intl.formatMessage(messages.deletemedia),
description: intl.formatMessage(messages.deletemediaDescription),
permission: Permission.DELETE_MEDIA,
},
{
id: 'request',
name: intl.formatMessage(messages.request),
Expand Down
58 changes: 31 additions & 27 deletions src/components/TvDetails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -692,33 +692,37 @@ const TvDetails = ({ tv }: TvDetailsProps) => {
</Button>
</Tooltip>
)}
{hasPermission(Permission.MANAGE_REQUESTS) && data.mediaInfo && (
<Tooltip content={intl.formatMessage(messages.manageseries)}>
<Button
buttonType="ghost"
onClick={() => setShowManager(true)}
className="relative ml-2 first:ml-0"
>
<CogIcon className="!mr-0" />
{hasPermission(
[Permission.MANAGE_ISSUES, Permission.VIEW_ISSUES],
{
type: 'or',
}
) &&
(
data.mediaInfo?.issues.filter(
(issue) => issue.status === IssueStatus.OPEN
) ?? []
).length > 0 && (
<>
<div className="absolute -right-1 -top-1 h-3 w-3 rounded-full bg-red-600" />
<div className="absolute -right-1 -top-1 h-3 w-3 animate-ping rounded-full bg-red-600" />
</>
)}
</Button>
</Tooltip>
)}
{hasPermission(
[Permission.MANAGE_REQUESTS, Permission.DELETE_MEDIA],
{ type: 'or' }
) &&
data.mediaInfo && (
<Tooltip content={intl.formatMessage(messages.manageseries)}>
<Button
buttonType="ghost"
onClick={() => setShowManager(true)}
className="relative ml-2 first:ml-0"
>
<CogIcon className="!mr-0" />
{hasPermission(
[Permission.MANAGE_ISSUES, Permission.VIEW_ISSUES],
{
type: 'or',
}
) &&
(
data.mediaInfo?.issues.filter(
(issue) => issue.status === IssueStatus.OPEN
) ?? []
).length > 0 && (
<>
<div className="absolute -right-1 -top-1 h-3 w-3 rounded-full bg-red-600" />
<div className="absolute -right-1 -top-1 h-3 w-3 animate-ping rounded-full bg-red-600" />
</>
)}
</Button>
</Tooltip>
)}
</div>
</div>
<div className="media-overview">
Expand Down
2 changes: 2 additions & 0 deletions src/i18n/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,8 @@
"components.PermissionEdit.blacklistedItemsDescription": "Grant permission to blacklist media.",
"components.PermissionEdit.createissues": "Report Issues",
"components.PermissionEdit.createissuesDescription": "Grant permission to report media issues.",
"components.PermissionEdit.deletemedia": "Delete Media",
"components.PermissionEdit.deletemediaDescription": "Grant permission to delete media from Sonarr and Radarr.",
"components.PermissionEdit.manageblacklist": "Manage Blacklist",
"components.PermissionEdit.manageblacklistDescription": "Grant permission to manage blacklisted media.",
"components.PermissionEdit.manageissues": "Manage Issues",
Expand Down
Loading