Fix #34: Allow non-admins to use blocklist-search under qualifying conditions
Build and Push Docker Image / build (push) Successful in 46s
Licence Check / Licence compatibility and copyright header verification (push) Failing after 1m40s
CI / Security audit (push) Successful in 2m4s
CI / Swagger Validation & Coverage (push) Successful in 2m10s
CI / Tests & coverage (push) Successful in 2m23s

- Expose ARR ID fields (arrQueueId, arrType, arrInstanceUrl, arrContentId, arrContentType) to non-admins in DownloadMatcher.js for blocklist functionality
- Replace blanket admin check in dashboard.js with canBlocklist() validation and server-side API key lookup
- Update integration tests to reflect new permission model
- Non-admins can now blocklist downloads with import issues or stale low-availability torrents
This commit is contained in:
2026-05-22 22:13:24 +01:00
parent b77c0d6ec0
commit 614af9eb44
3 changed files with 144 additions and 32 deletions
+24 -20
View File
@@ -204,16 +204,17 @@ async function matchSabSlots(slots, context) {
};
const issues = DownloadAssembler.getImportIssues(sonarrMatch);
if (issues) dlObj.importIssues = issues;
// Expose ARR IDs to non-admins for blocklist functionality
dlObj.arrQueueId = sonarrMatch.id;
dlObj.arrType = 'sonarr';
dlObj.arrInstanceUrl = sonarrMatch._instanceUrl || null;
dlObj.arrContentId = sonarrMatch.episodeId || null;
dlObj.arrContentType = 'episode';
if (isAdmin) {
dlObj.downloadPath = slot.storage || null;
dlObj.targetPath = series.path || null;
dlObj.arrLink = DownloadAssembler.getSonarrLink(series);
dlObj.arrQueueId = sonarrMatch.id;
dlObj.arrType = 'sonarr';
dlObj.arrInstanceUrl = sonarrMatch._instanceUrl || null;
dlObj.arrInstanceKey = sonarrMatch._instanceKey || null;
dlObj.arrContentId = sonarrMatch.episodeId || null;
dlObj.arrContentType = 'episode';
}
dlObj.canBlocklist = DownloadAssembler.canBlocklist(dlObj, isAdmin);
addOmbiMatching(dlObj, series, context);
@@ -257,16 +258,17 @@ async function matchSabSlots(slots, context) {
};
const issues = DownloadAssembler.getImportIssues(radarrMatch);
if (issues) dlObj.importIssues = issues;
// Expose ARR IDs to non-admins for blocklist functionality
dlObj.arrQueueId = radarrMatch.id;
dlObj.arrType = 'radarr';
dlObj.arrInstanceUrl = radarrMatch._instanceUrl || null;
dlObj.arrContentId = radarrMatch.movieId || null;
dlObj.arrContentType = 'movie';
if (isAdmin) {
dlObj.downloadPath = slot.storage || null;
dlObj.targetPath = movie.path || null;
dlObj.arrLink = DownloadAssembler.getRadarrLink(movie);
dlObj.arrQueueId = radarrMatch.id;
dlObj.arrType = 'radarr';
dlObj.arrInstanceUrl = radarrMatch._instanceUrl || null;
dlObj.arrInstanceKey = radarrMatch._instanceKey || null;
dlObj.arrContentId = radarrMatch.movieId || null;
dlObj.arrContentType = 'movie';
}
dlObj.canBlocklist = DownloadAssembler.canBlocklist(dlObj, isAdmin);
addOmbiMatching(dlObj, movie, context);
@@ -444,16 +446,17 @@ async function matchTorrents(torrents, context) {
});
const issues = DownloadAssembler.getImportIssues(sonarrMatch);
if (issues) download.importIssues = issues;
// Expose ARR IDs to non-admins for blocklist functionality
download.arrQueueId = sonarrMatch.id;
download.arrType = 'sonarr';
download.arrInstanceUrl = sonarrMatch._instanceUrl || null;
download.arrContentId = sonarrMatch.episodeId || null;
download.arrContentType = 'episode';
if (isAdmin) {
download.downloadPath = download.savePath || null;
download.targetPath = series.path || null;
download.arrLink = DownloadAssembler.getSonarrLink(series);
download.arrQueueId = sonarrMatch.id;
download.arrType = 'sonarr';
download.arrInstanceUrl = sonarrMatch._instanceUrl || null;
download.arrInstanceKey = sonarrMatch._instanceKey || null;
download.arrContentId = sonarrMatch.episodeId || null;
download.arrContentType = 'episode';
}
download.canBlocklist = DownloadAssembler.canBlocklist(download, isAdmin);
addOmbiMatching(download, series, context);
@@ -489,16 +492,17 @@ async function matchTorrents(torrents, context) {
});
const issues = DownloadAssembler.getImportIssues(radarrMatch);
if (issues) download.importIssues = issues;
// Expose ARR IDs to non-admins for blocklist functionality
download.arrQueueId = radarrMatch.id;
download.arrType = 'radarr';
download.arrInstanceUrl = radarrMatch._instanceUrl || null;
download.arrContentId = radarrMatch.movieId || null;
download.arrContentType = 'movie';
if (isAdmin) {
download.downloadPath = download.savePath || null;
download.targetPath = movie.path || null;
download.arrLink = DownloadAssembler.getRadarrLink(movie);
download.arrQueueId = radarrMatch.id;
download.arrType = 'radarr';
download.arrInstanceUrl = radarrMatch._instanceUrl || null;
download.arrInstanceKey = radarrMatch._instanceKey || null;
download.arrContentId = radarrMatch.movieId || null;
download.arrContentType = 'movie';
}
download.canBlocklist = DownloadAssembler.canBlocklist(download, isAdmin);
addOmbiMatching(download, movie, context);