Unify auth context → role permission config resolution into a single pure utility (#18927)
## Summary - Consolidates duplicated auth-context-to-role-ID resolution logic (previously in `PermissionsService.resolveRolePermissionConfigFromAuthContext` and `CommonBaseQueryRunnerService.getRoleIdOrThrow`) into a single pure utility function `resolveRolePermissionConfig` in the ORM layer - The utility is synchronous and operates on cached data (`userWorkspaceRoleMap`, `apiKeyRoleMap`) already loaded into the workspace context — no async calls, no service dependencies - Adds `apiKeyRoleMap` to `ORMWorkspaceContext` (it was already in the workspace cache, just not loaded into the ORM context) - Removes `PermissionsService` dependency from `NavigationMenuItemRecordIdentifierService` - Removes `UserRoleService` and `ApiKeyRoleService` injections from `CommonBaseQueryRunnerService` ## Test plan - [ ] Existing typecheck passes (`npx nx typecheck twenty-server`) - [ ] Verify record identifier resolution still works for navigation menu items (user, system, API key, and application auth contexts) - [ ] Verify GraphQL CRUD queries still enforce correct role-based permissions - [ ] Verify API key authenticated requests resolve permissions correctly Made with [Cursor](https://cursor.com)
This commit is contained in:
+1
@@ -321,6 +321,7 @@ describe('WorkspaceEntityManager', () => {
|
||||
userWorkspaceRoleMap: {
|
||||
'user-workspace-id': 'role-id',
|
||||
},
|
||||
apiKeyRoleMap: {},
|
||||
};
|
||||
|
||||
setWorkspaceContext(mockWorkspaceContext);
|
||||
|
||||
+4
@@ -93,6 +93,7 @@ export class GlobalWorkspaceOrmManager {
|
||||
rolesPermissions: permissionsPerRoleId,
|
||||
ORMEntityMetadatas: entityMetadatas,
|
||||
userWorkspaceRoleMap,
|
||||
apiKeyRoleMap,
|
||||
flatRowLevelPermissionPredicateMaps,
|
||||
flatRowLevelPermissionPredicateGroupMaps,
|
||||
} = await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
@@ -103,6 +104,7 @@ export class GlobalWorkspaceOrmManager {
|
||||
'rolesPermissions',
|
||||
'ORMEntityMetadatas',
|
||||
'userWorkspaceRoleMap',
|
||||
'apiKeyRoleMap',
|
||||
'flatRowLevelPermissionPredicateMaps',
|
||||
'flatRowLevelPermissionPredicateGroupMaps',
|
||||
]);
|
||||
@@ -122,6 +124,7 @@ export class GlobalWorkspaceOrmManager {
|
||||
permissionsPerRoleId,
|
||||
entityMetadatas,
|
||||
userWorkspaceRoleMap,
|
||||
apiKeyRoleMap,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -167,6 +170,7 @@ export class GlobalWorkspaceOrmManager {
|
||||
permissionsPerRoleId: {},
|
||||
entityMetadatas,
|
||||
userWorkspaceRoleMap: {},
|
||||
apiKeyRoleMap: {},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ export type ORMWorkspaceContext = {
|
||||
permissionsPerRoleId: ObjectsPermissionsByRoleId;
|
||||
entityMetadatas: EntityMetadata[];
|
||||
userWorkspaceRoleMap: UserWorkspaceRoleMap;
|
||||
apiKeyRoleMap: Record<string, string>;
|
||||
flatRowLevelPermissionPredicateMaps: FlatRowLevelPermissionPredicateMaps;
|
||||
flatRowLevelPermissionPredicateGroupMaps: FlatRowLevelPermissionPredicateGroupMaps;
|
||||
};
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { isApiKeyAuthContext } from 'src/engine/core-modules/auth/guards/is-api-key-auth-context.guard';
|
||||
import { isApplicationAuthContext } from 'src/engine/core-modules/auth/guards/is-application-auth-context.guard';
|
||||
import { isSystemAuthContext } from 'src/engine/core-modules/auth/guards/is-system-auth-context.guard';
|
||||
import { isUserAuthContext } from 'src/engine/core-modules/auth/guards/is-user-auth-context.guard';
|
||||
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
|
||||
import { type UserWorkspaceRoleMap } from 'src/engine/metadata-modules/role-target/types/user-workspace-role-map';
|
||||
import { type RolePermissionConfig } from 'src/engine/twenty-orm/types/role-permission-config';
|
||||
|
||||
export const resolveRolePermissionConfig = ({
|
||||
authContext,
|
||||
userWorkspaceRoleMap,
|
||||
apiKeyRoleMap,
|
||||
}: {
|
||||
authContext: WorkspaceAuthContext;
|
||||
userWorkspaceRoleMap: UserWorkspaceRoleMap;
|
||||
apiKeyRoleMap: Record<string, string>;
|
||||
}): RolePermissionConfig | null => {
|
||||
if (isSystemAuthContext(authContext)) {
|
||||
return { shouldBypassPermissionChecks: true };
|
||||
}
|
||||
|
||||
if (isApiKeyAuthContext(authContext)) {
|
||||
const roleId = apiKeyRoleMap[authContext.apiKey.id];
|
||||
|
||||
if (!isDefined(roleId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return { intersectionOf: [roleId] };
|
||||
}
|
||||
|
||||
if (
|
||||
isApplicationAuthContext(authContext) &&
|
||||
isDefined(authContext.application.defaultRoleId)
|
||||
) {
|
||||
return { intersectionOf: [authContext.application.defaultRoleId] };
|
||||
}
|
||||
|
||||
if (isUserAuthContext(authContext)) {
|
||||
const roleId = userWorkspaceRoleMap[authContext.userWorkspaceId];
|
||||
|
||||
if (!isDefined(roleId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return { intersectionOf: [roleId] };
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
Reference in New Issue
Block a user