From b8809eeaa200aa2f30c9dfbf13cf5f83637a7577 Mon Sep 17 00:00:00 2001 From: Nick Szaunig Date: Tue, 22 Sep 2026 02:12:56 +0200 Subject: [PATCH] fix: restore the authorization decorators three new routes displaced Inserting the new PATCH handlers directly above an existing route put them between that route's @RequirePermission decorator and its method, so the decorator bound to the new handler instead: - DELETE /documents/:id lost documents:delete - POST /honey-batches/:id/measurements lost honey-batches:measure - POST /queens/:id/evaluations lost queens:evaluate and each new PATCH ended up carrying two @RequirePermission decorators, of which only one takes effect. This did not open anything up. PermissionsGuard fails closed by decorator absence: a non-public route with neither @RequirePermission nor @AnyAuthenticatedUser is denied outright, so the three routes would have returned 403 for every caller including an administrator. The effect was a broken endpoint, not a bypass. Each decorator is back on the route it belongs to, and the duplicates are gone. test/authorization-coverage.e2e-spec.ts asserts exactly this contract across every route and is the check that should run before a route change ships. Co-Authored-By: Claude Opus 5 (1M context) --- ApiCore-Backend/src/documents/documents.controller.ts | 2 +- ApiCore-Backend/src/honey-batches/honey-batches.controller.ts | 2 +- ApiCore-Backend/src/queens/queens.controller.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ApiCore-Backend/src/documents/documents.controller.ts b/ApiCore-Backend/src/documents/documents.controller.ts index 64acc39..8df2598 100644 --- a/ApiCore-Backend/src/documents/documents.controller.ts +++ b/ApiCore-Backend/src/documents/documents.controller.ts @@ -106,7 +106,6 @@ export class DocumentsController { res.send(buffer); } - @RequirePermission('documents:delete') @RequirePermission('documents:update') @Patch(':id') update( @@ -117,6 +116,7 @@ export class DocumentsController { return this.documentsService.update(id, dto, actor.id); } + @RequirePermission('documents:delete') @Delete(':id') @HttpCode(204) delete(@Param('id') id: string, @CurrentUser() actor: AuthenticatedUser) { diff --git a/ApiCore-Backend/src/honey-batches/honey-batches.controller.ts b/ApiCore-Backend/src/honey-batches/honey-batches.controller.ts index 8b015db..481e979 100644 --- a/ApiCore-Backend/src/honey-batches/honey-batches.controller.ts +++ b/ApiCore-Backend/src/honey-batches/honey-batches.controller.ts @@ -117,7 +117,6 @@ export class HoneyBatchesController { return this.honeyBatchesService.update(id, dto, actor.id); } - @RequirePermission('honey-batches:measure') @RequirePermission('honey-batches:measure') @Patch('measurements/:measurementId') updateMeasurement( @@ -132,6 +131,7 @@ export class HoneyBatchesController { ); } + @RequirePermission('honey-batches:measure') @Post(':id/measurements') addMeasurement( @Param('id') id: string, diff --git a/ApiCore-Backend/src/queens/queens.controller.ts b/ApiCore-Backend/src/queens/queens.controller.ts index 5d66406..35a5f29 100644 --- a/ApiCore-Backend/src/queens/queens.controller.ts +++ b/ApiCore-Backend/src/queens/queens.controller.ts @@ -81,7 +81,6 @@ export class QueensController { return this.queensService.getEvaluations(id); } - @RequirePermission('queens:evaluate') @RequirePermission('queens:evaluate') @Patch('evaluations/:evaluationId') updateEvaluation( @@ -92,6 +91,7 @@ export class QueensController { return this.queensService.updateEvaluation(evaluationId, dto, actor.id); } + @RequirePermission('queens:evaluate') @Post(':id/evaluations') addEvaluation( @Param('id') id: string,