WIP - field level permission

This commit is contained in:
Francisco Gaona
2025-12-30 05:54:56 +01:00
parent 56c0c3838d
commit d15fc918d1
8 changed files with 357 additions and 18 deletions

View File

@@ -156,7 +156,20 @@ export class AbilityFactory {
return false;
}
// Check all roles for field permission
// Collect all field permissions from all roles
const allFieldPermissions: RoleFieldPermission[] = [];
for (const role of user.roles) {
if (role.fieldPermissions) {
allFieldPermissions.push(...role.fieldPermissions);
}
}
// If there are NO field permissions configured at all, allow by default
if (allFieldPermissions.length === 0) {
return true;
}
// If field permissions exist, check for explicit grants (union of all roles)
for (const role of user.roles) {
if (role.fieldPermissions) {
const fieldPerm = role.fieldPermissions.find(fp => fp.fieldDefinitionId === fieldDefinitionId);
@@ -167,8 +180,8 @@ export class AbilityFactory {
}
}
// Default: allow if no explicit restriction
return true;
// Field permissions exist but this field is not explicitly granted → deny
return false;
}
/**

View File

@@ -2,8 +2,12 @@ import { Module } from '@nestjs/common';
import { RbacService } from './rbac.service';
import { AbilityFactory } from './ability.factory';
import { AuthorizationService } from './authorization.service';
import { SetupRolesController } from './setup-roles.controller';
import { TenantModule } from '../tenant/tenant.module';
@Module({
imports: [TenantModule],
controllers: [SetupRolesController],
providers: [RbacService, AbilityFactory, AuthorizationService],
exports: [RbacService, AbilityFactory, AuthorizationService],
})

View File

@@ -0,0 +1,23 @@
import {
Controller,
Get,
UseGuards,
} from '@nestjs/common';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
import { TenantId } from '../tenant/tenant.decorator';
import { TenantDatabaseService } from '../tenant/tenant-database.service';
import { Role } from '../models/role.model';
@Controller('setup/roles')
@UseGuards(JwtAuthGuard)
export class SetupRolesController {
constructor(private tenantDbService: TenantDatabaseService) {}
@Get()
async getRoles(@TenantId() tenantId: string) {
const resolvedTenantId = await this.tenantDbService.resolveTenantId(tenantId);
const knex = await this.tenantDbService.getTenantKnexById(resolvedTenantId);
return await Role.query(knex).select('*').orderBy('name', 'asc');
}
}