Add sourceHeaders and conditional OIDC groups

Add support for passing sourceHeaders when fetching NZB/torrent files: extend AddDownloadOptions and SABnzbd AddNZBOptions, forward headers in sabnzbd and nzbget clients, and populate sourceHeaders in download-torrent.processor (injecting Prowlarr API key as X-Api-Key for proxy URLs). Make OIDC request scope conditional: only include the 'groups' scope when group-based access control or admin-claim is enabled (update provider logic, add tests, and update setup UI text). Also remove explicit take:100 in Plex processors and add CLAUDE guidance about requesting approval before implementing code changes.
This commit is contained in:
kikootwo
2026-03-09 10:33:52 -04:00
parent 9cb9d06144
commit 789a2e50ef
10 changed files with 92 additions and 4 deletions
@@ -128,6 +128,64 @@ describe('OIDCAuthProvider', () => {
expect(result.state).toBe('state-1');
});
it('omits groups scope when access control does not need it', async () => {
setConfig({
'oidc.issuer_url': 'https://issuer',
'oidc.client_id': 'client',
'oidc.client_secret': 'secret',
'oidc.access_control_method': 'open',
});
clientMock.authorizationUrl.mockReturnValue('https://issuer/auth');
const { OIDCAuthProvider } = await import('@/lib/services/auth/OIDCAuthProvider');
const provider = new OIDCAuthProvider();
await provider.initiateLogin();
expect(clientMock.authorizationUrl).toHaveBeenCalledWith(
expect.objectContaining({ scope: 'openid profile email' })
);
});
it('includes groups scope when access control uses group_claim', async () => {
setConfig({
'oidc.issuer_url': 'https://issuer',
'oidc.client_id': 'client',
'oidc.client_secret': 'secret',
'oidc.access_control_method': 'group_claim',
});
clientMock.authorizationUrl.mockReturnValue('https://issuer/auth');
const { OIDCAuthProvider } = await import('@/lib/services/auth/OIDCAuthProvider');
const provider = new OIDCAuthProvider();
await provider.initiateLogin();
expect(clientMock.authorizationUrl).toHaveBeenCalledWith(
expect.objectContaining({ scope: 'openid profile email groups' })
);
});
it('includes groups scope when admin claim is enabled', async () => {
setConfig({
'oidc.issuer_url': 'https://issuer',
'oidc.client_id': 'client',
'oidc.client_secret': 'secret',
'oidc.access_control_method': 'allowed_list',
'oidc.admin_claim_enabled': 'true',
});
clientMock.authorizationUrl.mockReturnValue('https://issuer/auth');
const { OIDCAuthProvider } = await import('@/lib/services/auth/OIDCAuthProvider');
const provider = new OIDCAuthProvider();
await provider.initiateLogin();
expect(clientMock.authorizationUrl).toHaveBeenCalledWith(
expect.objectContaining({ scope: 'openid profile email groups' })
);
});
it('throws when OIDC is not fully configured', async () => {
setConfig({
'oidc.issuer_url': null,