Labels: backend auth nestjs
Area: backend/src/common/guards/roles.guard.ts, backend/src/common/decorators/roles.decorator.ts
Difficulty: Intermediate
Description
Some admin endpoints need finer-grained access control beyond "is authenticated" — for example, only SUPER_ADMIN can delete other users. This issue creates a RolesGuard and @Roles() decorator that work together to enforce role-based access.
Acceptance Criteria
Technical Notes
RolesGuard must be applied AFTER JwtAuthGuard so req.user is populated before the role check
- The audit interceptor is optional per-controller — not applied globally
Labels:
backendauthnestjsArea:
backend/src/common/guards/roles.guard.ts,backend/src/common/decorators/roles.decorator.tsDifficulty: Intermediate
Description
Some admin endpoints need finer-grained access control beyond "is authenticated" — for example, only
SUPER_ADMINcan delete other users. This issue creates aRolesGuardand@Roles()decorator that work together to enforce role-based access.Acceptance Criteria
backend/src/common/decorators/roles.decorator.tsexporting@Roles(...roles: AdminRole[])usingSetMetadata("roles", roles)backend/src/common/guards/roles.guard.tsimplementingCanActivate:Reflectorusing the"roles"metadata keyreq.user.roleand checks if it is included in the required roles listtrueor throwsForbiddenExceptionbackend/src/common/interceptors/audit.interceptor.ts— anNestInterceptorthat automatically callsAuditService.log()after mutating requests (POST,PUT,PATCH,DELETE) complete successfully; reads action label from custom@AuditAction("label")metadata decoratorbackend/src/common/index.ts@Injectable()Technical Notes
RolesGuardmust be applied AFTERJwtAuthGuardsoreq.useris populated before the role check