Files
boilerplate/apps/backend/src/auth/guards/permissions.guard.ts
Bastian Wagner 543e8273a7 initial
2026-07-16 09:49:22 +02:00

69 lines
2.1 KiB
TypeScript

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { ApiError } from '../../common/errors/api-error';
import { ErrorCode } from '../../common/errors/error-codes';
import { AppConfigService } from '../../config/config.service';
import { SessionsService } from '../../sessions/sessions.service';
import type { Permission } from '../../roles/permissions';
import { IS_PUBLIC_KEY } from './public.decorator';
import { REQUIRED_PERMISSIONS_KEY } from './require-permissions.decorator';
import type { AuthenticatedRequest } from '../authenticated-request';
@Injectable()
export class PermissionsGuard implements CanActivate {
constructor(
private readonly reflector: Reflector,
private readonly sessions: SessionsService,
private readonly config: AppConfigService,
) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
context.getHandler(),
context.getClass(),
]);
const required = this.reflector.getAllAndOverride<Permission[]>(
REQUIRED_PERMISSIONS_KEY,
[context.getHandler(), context.getClass()],
);
if (isPublic || !required?.length) {
return true;
}
const request = context.switchToHttp().getRequest<AuthenticatedRequest>();
const sessionId = request.signedCookies?.[
this.config.session.cookieName
] as string | undefined;
if (!sessionId) {
throw new ApiError(
ErrorCode.Unauthorized,
'Bitte melden Sie sich an.',
401,
);
}
const session = await this.sessions.resolveSession(
sessionId,
request.ip,
request.get('user-agent'),
);
request.user = {
id: session.user.id,
sessionId,
permissions: session.permissions,
};
const allowed = required.every((permission) =>
session.permissions.includes(permission),
);
if (!allowed) {
throw new ApiError(
ErrorCode.PermissionDenied,
'Keine Berechtigung fuer diese Aktion.',
403,
);
}
return true;
}
}