first commit
This commit is contained in:
78
apps/api-gateway/src/guards/admin.guard.ts
Normal file
78
apps/api-gateway/src/guards/admin.guard.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { CanActivate, ExecutionContext, ForbiddenException, Injectable, UnauthorizedException } from '@nestjs/common';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { CoreGrpcService } from '../core-grpc.service';
|
||||
import { assertSessionUnlocked, verifyAccessToken } from '../session-auth';
|
||||
|
||||
export interface AdminRequestUser {
|
||||
id: string;
|
||||
isSuperAdmin: boolean;
|
||||
canAccessAdmin: boolean;
|
||||
canManageRoles: boolean;
|
||||
canManageOAuth: boolean;
|
||||
canManageUsers: boolean;
|
||||
canViewUsers: boolean;
|
||||
canManageSettings: boolean;
|
||||
roles: string[];
|
||||
permissions: string[];
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class AdminGuard implements CanActivate {
|
||||
constructor(
|
||||
private readonly jwt: JwtService,
|
||||
private readonly core: CoreGrpcService
|
||||
) {}
|
||||
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
const request = context.switchToHttp().getRequest<{ headers: { authorization?: string }; adminUser?: AdminRequestUser }>();
|
||||
|
||||
let payload;
|
||||
try {
|
||||
payload = await verifyAccessToken(this.jwt, request.headers.authorization);
|
||||
await assertSessionUnlocked(this.core, payload);
|
||||
} catch (error) {
|
||||
if (error instanceof UnauthorizedException || error instanceof ForbiddenException) {
|
||||
throw error;
|
||||
}
|
||||
throw new UnauthorizedException('Недействительный токен доступа');
|
||||
}
|
||||
|
||||
const profile = (await firstValueFrom(this.core.auth.GetMe({ userId: payload.sub }))) as AdminRequestUser & { id: string };
|
||||
if (!profile.canAccessAdmin) {
|
||||
throw new ForbiddenException('Доступ к админ-панели запрещён');
|
||||
}
|
||||
|
||||
request.adminUser = {
|
||||
id: profile.id,
|
||||
isSuperAdmin: profile.isSuperAdmin,
|
||||
canAccessAdmin: Boolean(profile.canAccessAdmin),
|
||||
canManageRoles: Boolean(profile.canManageRoles),
|
||||
canManageOAuth: Boolean(profile.canManageOAuth),
|
||||
canManageUsers: Boolean(profile.canManageUsers),
|
||||
canManageSettings: Boolean(profile.canManageSettings),
|
||||
canViewUsers: Boolean(profile.canViewUsers),
|
||||
roles: profile.roles ?? [],
|
||||
permissions: profile.permissions ?? []
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class SuperAdminGuard implements CanActivate {
|
||||
canActivate(context: ExecutionContext): boolean {
|
||||
const request = context.switchToHttp().getRequest<{ adminUser?: AdminRequestUser }>();
|
||||
if (!request.adminUser?.isSuperAdmin) {
|
||||
throw new ForbiddenException('Только супер-администратор может выполнять это действие');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export function assertAdminPermission(user: AdminRequestUser | undefined, permission: keyof Pick<AdminRequestUser, 'canManageOAuth' | 'canManageUsers' | 'canManageSettings'>) {
|
||||
if (!user?.[permission]) {
|
||||
throw new ForbiddenException('Недостаточно прав для выполнения действия');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user