This commit is contained in:
Weiko
2026-05-27 20:14:43 +02:00
parent 9842038f0f
commit e863318f1c
2 changed files with 74 additions and 109 deletions
@@ -6,7 +6,6 @@ import {
DEFAULT_API_URL_NAME,
DEFAULT_APP_ACCESS_TOKEN_NAME,
DEFAULT_PERMISSION_CONTEXT_NAME,
type LogicFunctionPermissionContext,
} from 'twenty-shared/application';
import { isDefined } from 'twenty-shared/utils';
import { Not, Repository } from 'typeorm';
@@ -266,10 +265,11 @@ export class LogicFunctionExecutorService {
this.secretEncryptionService,
);
const permissionContext = await this.buildPermissionContext({
workspaceId,
roleId,
});
const permissionContext =
await this.permissionsService.buildLogicFunctionPermissionContext({
workspaceId,
roleId,
});
return {
[DEFAULT_API_URL_NAME]: baseUrl ?? '',
@@ -284,86 +284,6 @@ export class LogicFunctionExecutorService {
};
}
private async buildPermissionContext({
workspaceId,
roleId,
}: {
workspaceId: string;
roleId?: string;
}): Promise<LogicFunctionPermissionContext> {
if (!isDefined(roleId)) {
return {
canReadAllObjectRecords: false,
canUpdateAllObjectRecords: false,
canSoftDeleteAllObjectRecords: false,
canDestroyAllObjectRecords: false,
canUpdateAllSettings: false,
canAccessAllTools: false,
permissionFlags: {},
objectsPermissions: {},
};
}
const { capabilities, permissionFlags, objectsPermissions } =
await this.permissionsService.getRolePermissionContext({
roleId,
workspaceId,
});
const { flatObjectMetadataMaps, flatFieldMetadataMaps } =
await this.workspaceCacheService.getOrRecompute(workspaceId, [
'flatObjectMetadataMaps',
'flatFieldMetadataMaps',
]);
const objectsPermissionsByUniversalIdentifier: LogicFunctionPermissionContext['objectsPermissions'] =
{};
for (const [objectMetadataId, objectPermissions] of Object.entries(
objectsPermissions,
)) {
const objectUniversalIdentifier =
flatObjectMetadataMaps.universalIdentifierById[objectMetadataId];
if (!isDefined(objectUniversalIdentifier)) {
continue;
}
const restrictedFields: LogicFunctionPermissionContext['objectsPermissions'][string]['restrictedFields'] =
{};
for (const [fieldMetadataId, fieldPermissions] of Object.entries(
objectPermissions.restrictedFields,
)) {
const fieldUniversalIdentifier =
flatFieldMetadataMaps.universalIdentifierById[fieldMetadataId];
if (!isDefined(fieldUniversalIdentifier)) {
continue;
}
restrictedFields[fieldUniversalIdentifier] = {
canRead: fieldPermissions.canRead,
canUpdate: fieldPermissions.canUpdate,
};
}
objectsPermissionsByUniversalIdentifier[objectUniversalIdentifier] = {
canRead: objectPermissions.canReadObjectRecords,
canUpdate: objectPermissions.canUpdateObjectRecords,
canSoftDelete: objectPermissions.canSoftDeleteObjectRecords,
canDestroy: objectPermissions.canDestroyObjectRecords,
restrictedFields,
};
}
return {
...capabilities,
permissionFlags,
objectsPermissions: objectsPermissionsByUniversalIdentifier,
};
}
// Resolves encrypted server-level variables (ApplicationRegistrationVariable)
// for the application's registration. Returns an empty object when the
// application isn't linked to a registration (legacy LOCAL apps).
@@ -2,11 +2,11 @@ import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { msg } from '@lingui/core/macro';
import { type LogicFunctionPermissionContext } from 'twenty-shared/application';
import {
PermissionFlagType,
SystemPermissionFlag,
} from 'twenty-shared/constants';
import { type ObjectsPermissions } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { In, Repository } from 'typeorm';
@@ -100,34 +100,40 @@ export class PermissionsService {
};
}
public async getRolePermissionContext({
public async buildLogicFunctionPermissionContext({
roleId,
workspaceId,
}: {
roleId: string;
roleId?: string;
workspaceId: string;
}): Promise<{
capabilities: {
canReadAllObjectRecords: boolean;
canUpdateAllObjectRecords: boolean;
canSoftDeleteAllObjectRecords: boolean;
canDestroyAllObjectRecords: boolean;
canUpdateAllSettings: boolean;
canAccessAllTools: boolean;
};
permissionFlags: Record<string, boolean>;
objectsPermissions: ObjectsPermissions;
}> {
}): Promise<LogicFunctionPermissionContext> {
if (!isDefined(roleId)) {
return {
canReadAllObjectRecords: false,
canUpdateAllObjectRecords: false,
canSoftDeleteAllObjectRecords: false,
canDestroyAllObjectRecords: false,
canUpdateAllSettings: false,
canAccessAllTools: false,
permissionFlags: {},
objectsPermissions: {},
};
}
const {
rolesPermissions,
flatRoleMaps,
flatRolePermissionFlagMaps,
flatPermissionFlagMaps,
flatObjectMetadataMaps,
flatFieldMetadataMaps,
} = await this.workspaceCacheService.getOrRecompute(workspaceId, [
'rolesPermissions',
'flatRoleMaps',
'flatRolePermissionFlagMaps',
'flatPermissionFlagMaps',
'flatObjectMetadataMaps',
'flatFieldMetadataMaps',
]);
const flatRole = findFlatEntityByIdInFlatEntityMaps({
@@ -173,17 +179,56 @@ export class PermissionsService {
grantedPermissionFlagIds.has(flatPermissionFlag.id);
}
const objectsPermissions: LogicFunctionPermissionContext['objectsPermissions'] =
{};
for (const [objectMetadataId, objectPermissions] of Object.entries(
rolesPermissions[roleId] ?? {},
)) {
const objectUniversalIdentifier =
flatObjectMetadataMaps.universalIdentifierById[objectMetadataId];
if (!isDefined(objectUniversalIdentifier)) {
continue;
}
const restrictedFields: LogicFunctionPermissionContext['objectsPermissions'][string]['restrictedFields'] =
{};
for (const [fieldMetadataId, fieldPermissions] of Object.entries(
objectPermissions.restrictedFields,
)) {
const fieldUniversalIdentifier =
flatFieldMetadataMaps.universalIdentifierById[fieldMetadataId];
if (!isDefined(fieldUniversalIdentifier)) {
continue;
}
restrictedFields[fieldUniversalIdentifier] = {
canRead: fieldPermissions.canRead,
canUpdate: fieldPermissions.canUpdate,
};
}
objectsPermissions[objectUniversalIdentifier] = {
canRead: objectPermissions.canReadObjectRecords,
canUpdate: objectPermissions.canUpdateObjectRecords,
canSoftDelete: objectPermissions.canSoftDeleteObjectRecords,
canDestroy: objectPermissions.canDestroyObjectRecords,
restrictedFields,
};
}
return {
capabilities: {
canReadAllObjectRecords: flatRole.canReadAllObjectRecords,
canUpdateAllObjectRecords: flatRole.canUpdateAllObjectRecords,
canSoftDeleteAllObjectRecords: flatRole.canSoftDeleteAllObjectRecords,
canDestroyAllObjectRecords: flatRole.canDestroyAllObjectRecords,
canUpdateAllSettings: flatRole.canUpdateAllSettings,
canAccessAllTools: flatRole.canAccessAllTools,
},
canReadAllObjectRecords: flatRole.canReadAllObjectRecords,
canUpdateAllObjectRecords: flatRole.canUpdateAllObjectRecords,
canSoftDeleteAllObjectRecords: flatRole.canSoftDeleteAllObjectRecords,
canDestroyAllObjectRecords: flatRole.canDestroyAllObjectRecords,
canUpdateAllSettings: flatRole.canUpdateAllSettings,
canAccessAllTools: flatRole.canAccessAllTools,
permissionFlags,
objectsPermissions: rolesPermissions[roleId] ?? {},
objectsPermissions,
};
}