feat(acl): deep data access by section for roles and users
Role default + user override with OR rules; covers customers, leads, sales, activities, notes, routines, projects, and tickets.
This commit is contained in:
@@ -3,6 +3,7 @@ import {
|
||||
ArrayUnique,
|
||||
IsArray,
|
||||
IsIn,
|
||||
IsObject,
|
||||
IsOptional,
|
||||
IsString,
|
||||
MaxLength,
|
||||
@@ -36,6 +37,10 @@ export class CreateOrgRoleDto {
|
||||
@IsIn(PERMISSION_KEYS, { each: true })
|
||||
permissions?: RolePermissionKey[];
|
||||
|
||||
@IsOptional()
|
||||
@IsObject()
|
||||
dataAccessPolicy?: Record<string, unknown>;
|
||||
|
||||
@IsOptional()
|
||||
@ValidateIf((_, v) => v !== null)
|
||||
@IsString()
|
||||
@@ -64,6 +69,10 @@ export class UpdateOrgRoleDto {
|
||||
@IsIn(PERMISSION_KEYS, { each: true })
|
||||
permissions?: RolePermissionKey[];
|
||||
|
||||
@IsOptional()
|
||||
@IsObject()
|
||||
dataAccessPolicy?: Record<string, unknown>;
|
||||
|
||||
@IsOptional()
|
||||
@ValidateIf((_, v) => v !== null)
|
||||
@IsString()
|
||||
|
||||
@@ -5,7 +5,13 @@ import {
|
||||
Injectable,
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import type { OrgRoleDto, RolePermissionKey, UserRole } from '@mento/shared';
|
||||
import type {
|
||||
DataAccessPolicy,
|
||||
OrgRoleDto,
|
||||
RolePermissionKey,
|
||||
UserRole,
|
||||
} from '@mento/shared';
|
||||
import { parseDataAccessPolicy } from '@mento/shared';
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import {
|
||||
@@ -25,6 +31,7 @@ type RoleRow = {
|
||||
description: string;
|
||||
color: string;
|
||||
permissions: string[];
|
||||
dataAccessPolicy?: unknown;
|
||||
systemKey: string | null;
|
||||
parentId: string | null;
|
||||
createdAt: Date;
|
||||
@@ -70,6 +77,7 @@ export class OrgRolesService {
|
||||
description?: string;
|
||||
color?: string;
|
||||
permissions?: RolePermissionKey[];
|
||||
dataAccessPolicy?: DataAccessPolicy;
|
||||
parentId?: string | null;
|
||||
},
|
||||
): Promise<OrgRoleDto> {
|
||||
@@ -101,6 +109,9 @@ export class OrgRolesService {
|
||||
color: dto.color ?? parent?.color ?? 'teal',
|
||||
permissions,
|
||||
parentId,
|
||||
...(dto.dataAccessPolicy
|
||||
? { dataAccessPolicy: parseDataAccessPolicy(dto.dataAccessPolicy) }
|
||||
: {}),
|
||||
},
|
||||
include: ROLE_MEMBERS_INCLUDE,
|
||||
});
|
||||
@@ -122,6 +133,7 @@ export class OrgRolesService {
|
||||
description?: string;
|
||||
color?: string;
|
||||
permissions?: RolePermissionKey[];
|
||||
dataAccessPolicy?: DataAccessPolicy;
|
||||
parentId?: string | null;
|
||||
},
|
||||
): Promise<OrgRoleDto> {
|
||||
@@ -144,6 +156,9 @@ export class OrgRolesService {
|
||||
if (dto.permissions !== undefined) {
|
||||
data.permissions = sanitizePermissions(dto.permissions);
|
||||
}
|
||||
if (dto.dataAccessPolicy !== undefined) {
|
||||
data.dataAccessPolicy = parseDataAccessPolicy(dto.dataAccessPolicy);
|
||||
}
|
||||
|
||||
if (dto.parentId !== undefined) {
|
||||
const nextParentId =
|
||||
@@ -410,6 +425,7 @@ export class OrgRolesService {
|
||||
description: row.description,
|
||||
color: row.color,
|
||||
permissions: sanitizePermissions(row.permissions),
|
||||
dataAccessPolicy: parseDataAccessPolicy(row.dataAccessPolicy),
|
||||
systemKey,
|
||||
parentId: row.parentId,
|
||||
parentName: row.parentId ? (nameById.get(row.parentId) ?? null) : null,
|
||||
|
||||
Reference in New Issue
Block a user