fix: support query parameter-based secret validation fallback to fix Ombi webhooks (#47)
Build and Push Docker Image / build (push) Successful in 2m4s
Docs Check / Markdown lint (push) Successful in 2m7s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 3m3s
CI / Security audit (push) Successful in 3m42s
Docs Check / Mermaid diagram parse check (push) Failing after 3m58s
CI / Tests & coverage (push) Successful in 4m21s
CI / Swagger Validation & Coverage (push) Successful in 4m33s

This commit is contained in:
2026-05-24 21:25:38 +01:00
parent b5b4862e15
commit 7b9c895888
10 changed files with 144 additions and 25 deletions
+69
View File
@@ -156,6 +156,24 @@ describe('POST /api/webhook/sonarr — secret validation', () => {
const res = await postSonarr(app, SONARR_GRAB, 'anything');
expect(res.status).toBe(401);
});
it('returns 200 when secret is provided as a query parameter instead of header', async () => {
const app = makeApp();
const res = await request(app)
.post(`/api/webhook/sonarr?secret=${VALID_SECRET}`)
.send(SONARR_GRAB);
expect(res.status).toBe(200);
expect(res.body.received).toBe(true);
});
it('returns 401 when secret is provided as an invalid query parameter', async () => {
const app = makeApp();
const res = await request(app)
.post('/api/webhook/sonarr?secret=wrong-query-secret')
.send(SONARR_GRAB);
expect(res.status).toBe(401);
expect(res.body.error).toBe('Unauthorized');
});
});
describe('POST /api/webhook/radarr — secret validation', () => {
@@ -171,6 +189,23 @@ describe('POST /api/webhook/radarr — secret validation', () => {
const res = await postRadarr(app, RADARR_GRAB, 'bad-secret');
expect(res.status).toBe(401);
});
it('returns 200 when secret is provided as a query parameter instead of header', async () => {
const app = makeApp();
const res = await request(app)
.post(`/api/webhook/radarr?secret=${VALID_SECRET}`)
.send(RADARR_GRAB);
expect(res.status).toBe(200);
expect(res.body.received).toBe(true);
});
it('returns 401 when secret is provided as an invalid query parameter', async () => {
const app = makeApp();
const res = await request(app)
.post('/api/webhook/radarr?secret=wrong-query-secret')
.send(RADARR_GRAB);
expect(res.status).toBe(401);
});
});
// ---------------------------------------------------------------------------
@@ -548,6 +583,40 @@ describe('POST /api/webhook/ombi', () => {
expect(res.body.error).toBe('Unauthorized');
});
it('returns 200 when secret is provided as a query parameter instead of header', async () => {
const app = makeApp();
nock('https://ombi.test')
.get('/api/v1/Request/movie')
.reply(200, []);
nock('https://ombi.test')
.get('/api/v1/Request/tv')
.reply(200, []);
const res = await request(app)
.post(`/api/webhook/ombi?secret=${VALID_SECRET}`)
.send({
notificationType: 'NewRequest',
requestId: 127,
requestedUser: 'gordon',
title: 'Query Movie',
type: 'Movie',
requestStatus: 'Pending',
applicationUrl: 'https://ombi.test',
requestedDate: '2026-05-23T20:40:00.000Z'
});
expect(res.status).toBe(200);
expect(res.body.received).toBe(true);
});
it('returns 401 when secret is provided as an invalid query parameter', async () => {
const app = makeApp();
const res = await request(app)
.post('/api/webhook/ombi?secret=wrong-query-secret')
.send({ notificationType: 'NewRequest', requestId: 1 });
expect(res.status).toBe(401);
expect(res.body.error).toBe('Unauthorized');
});
it('returns 400 when notificationType is missing or invalid', async () => {
const app = makeApp();
const res = await postOmbi(app, { requestId: 1 });