feat: implement public route support and elevate auth guard log levels to info
Build and Push Multi-Platform Images / build-and-push (push) Successful in 35s

This commit is contained in:
2026-05-09 10:03:34 +02:00
parent 367c8fe002
commit 86d3c062d6
3 changed files with 14 additions and 5 deletions
+2 -2
View File
@@ -31,7 +31,7 @@ export class ApiKeyGuard implements CanActivate {
} }
} }
this.logger.debug( this.logger.log(
`[${method} ${url}] key source: ${apiKey ? source : 'NONE'} | ` + `[${method} ${url}] key source: ${apiKey ? source : 'NONE'} | ` +
`headers: ${JSON.stringify(Object.keys(request.headers))} | ` + `headers: ${JSON.stringify(Object.keys(request.headers))} | ` +
`key prefix: ${apiKey ? String(apiKey).slice(0, 8) + '…' : 'n/a'}`, `key prefix: ${apiKey ? String(apiKey).slice(0, 8) + '…' : 'n/a'}`,
@@ -44,7 +44,7 @@ export class ApiKeyGuard implements CanActivate {
try { try {
const keyEntry = await this.apiKeysService.validateKey(apiKey as string); const keyEntry = await this.apiKeysService.validateKey(apiKey as string);
this.logger.debug(`[${method} ${url}] accepted key "${keyEntry.name}" (id=${keyEntry.id})`); this.logger.log(`[${method} ${url}] accepted key "${keyEntry.name}" (id=${keyEntry.id})`);
request.apiKeyMetadata = { id: keyEntry.id, name: keyEntry.name }; request.apiKeyMetadata = { id: keyEntry.id, name: keyEntry.name };
return true; return true;
} catch (err) { } catch (err) {
+1 -1
View File
@@ -26,7 +26,7 @@ import { PermissionsGuard } from './permissions.guard';
PermissionsGuard, PermissionsGuard,
{ {
provide: APP_GUARD, provide: APP_GUARD,
useClass: JwtAuthGuard, useClass: JwtOrApiKeyGuard,
}, },
{ {
provide: APP_GUARD, provide: APP_GUARD,
@@ -1,6 +1,8 @@
import { CanActivate, ExecutionContext, Injectable, Logger } from '@nestjs/common'; import { CanActivate, ExecutionContext, Injectable, Logger } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { JwtAuthGuard } from './jwt-auth.guard'; import { JwtAuthGuard } from './jwt-auth.guard';
import { ApiKeyGuard } from './api-key.guard'; import { ApiKeyGuard } from './api-key.guard';
import { IS_PUBLIC_KEY } from './public.decorator';
import { lastValueFrom, isObservable } from 'rxjs'; import { lastValueFrom, isObservable } from 'rxjs';
@Injectable() @Injectable()
@@ -10,9 +12,16 @@ export class JwtOrApiKeyGuard implements CanActivate {
constructor( constructor(
private readonly jwtGuard: JwtAuthGuard, private readonly jwtGuard: JwtAuthGuard,
private readonly apiKeyGuard: ApiKeyGuard, private readonly apiKeyGuard: ApiKeyGuard,
private readonly reflector: Reflector,
) {} ) {}
async canActivate(context: ExecutionContext): Promise<boolean> { async canActivate(context: ExecutionContext): Promise<boolean> {
const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
context.getHandler(),
context.getClass(),
]);
if (isPublic) return true;
const req = context.switchToHttp().getRequest(); const req = context.switchToHttp().getRequest();
const tag = `[${req.method} ${req.url}]`; const tag = `[${req.method} ${req.url}]`;
@@ -21,11 +30,11 @@ export class JwtOrApiKeyGuard implements CanActivate {
const result = this.jwtGuard.canActivate(context); const result = this.jwtGuard.canActivate(context);
const jwtOk = isObservable(result) ? await lastValueFrom(result) : await result; const jwtOk = isObservable(result) ? await lastValueFrom(result) : await result;
if (jwtOk) { if (jwtOk) {
this.logger.debug(`${tag} authenticated via JWT`); this.logger.log(`${tag} authenticated via JWT`);
return true; return true;
} }
} catch (err) { } catch (err) {
this.logger.debug(`${tag} JWT failed (${err.message}), trying API key…`); this.logger.log(`${tag} JWT failed (${err.message}), trying API key…`);
} }
// Fall back to API key // Fall back to API key