initial: standalone repo from monorepo split

This commit is contained in:
kevin-asprec
2026-04-13 09:36:55 +08:00
commit 4a8f1e9318
157 changed files with 9198 additions and 0 deletions

View File

@@ -0,0 +1,53 @@
import { Injectable, CanActivate, ExecutionContext, ForbiddenException } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { ACCESS_KEY, AccessRequirement } from '../decorators/access.decorator';
import { PrismaService } from '../../prisma/prisma.service';
@Injectable()
export class AccessGuard implements CanActivate {
constructor(
private reflector: Reflector,
private prisma: PrismaService,
) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const requirement = this.reflector.getAllAndOverride<AccessRequirement>(ACCESS_KEY, [
context.getHandler(),
context.getClass(),
]);
// No @RequireAccess decorator → allow
if (!requirement) return true;
const request = context.switchToHttp().getRequest();
const user = request.user;
if (!user) return false;
// Super admin bypasses all access checks
if (user.roles?.includes('super_admin')) return true;
// Resolve user's tenant role permissions from DB
const assignments = await this.prisma.userTenantRole.findMany({
where: { userId: user.sub },
include: {
tenantRole: {
include: { permissions: true },
},
},
});
// Check if any assigned role grants the required module+action
for (const a of assignments) {
if (!a.tenantRole.isActive || a.tenantRole.deletedAt) continue;
for (const p of a.tenantRole.permissions) {
if (p.module === requirement.module && p[requirement.action]) {
return true;
}
}
}
throw new ForbiddenException(
`Access denied: requires ${requirement.action} on ${requirement.module}`,
);
}
}