Refactor WorkspaceMemberDto transpilation (#12110)

# Introduction

In a nutshell this PR introduces a `workspaceMemberEntity` to
`workspaceMemberDto` transpilation which was not done but commented as
`// TODO` across the `user resolver`.
Also passed on the `Roles` and `UserWorkspacePermissions` transpilation
We now also compute the roles for the `workspaceMember` resolver ( not
only the `workspaceMembers` )
Some refactor

In the following days about to create a PR that introduces integration
testing on the user resolver

## Conclusion
As always any suggestions are more than welcomed ! Please let me know !

## Misc

Following https://github.com/twentyhq/twenty/pull/11914

closing https://github.com/twentyhq/core-team-issues/issues/1011
This commit is contained in:
Paul Rastoin
2025-06-13 11:01:25 +02:00
committed by GitHub
parent 7c4ddb9448
commit 4182a3d306
11 changed files with 407 additions and 252 deletions

View File

@ -1,7 +1,6 @@
import { Injectable } from '@nestjs/common';
import { PermissionsOnAllObjectRecords } from 'twenty-shared/constants';
import { ObjectRecordsPermissions } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import {
@ -16,6 +15,7 @@ import {
PermissionsExceptionCode,
PermissionsExceptionMessage,
} from 'src/engine/metadata-modules/permissions/permissions.exception';
import { UserWorkspacePermissions } from 'src/engine/metadata-modules/permissions/types/user-workspace-permissions';
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
import { WorkspacePermissionsCacheService } from 'src/engine/metadata-modules/workspace-permissions-cache/workspace-permissions-cache.service';
@ -33,11 +33,7 @@ export class PermissionsService {
}: {
userWorkspaceId: string;
workspaceId: string;
}): Promise<{
settingsPermissions: Record<SettingPermissionType, boolean>;
objectRecordsPermissions: Record<PermissionsOnAllObjectRecords, boolean>;
objectPermissions: ObjectRecordsPermissions;
}> {
}): Promise<UserWorkspacePermissions> {
const [roleOfUserWorkspace] = await this.userRoleService
.getRolesByUserWorkspaces({
userWorkspaceIds: [userWorkspaceId],
@ -60,7 +56,9 @@ export class PermissionsService {
const settingPermissions = roleOfUserWorkspace.settingPermissions ?? [];
const settingsPermissionsMap = Object.keys(SettingPermissionType).reduce(
const defaultSettingsPermissions =
this.getDefaultUserWorkspacePermissions().settingsPermissions;
const settingsPermissions = Object.keys(SettingPermissionType).reduce(
(acc, feature) => ({
...acc,
[feature]:
@ -69,7 +67,7 @@ export class PermissionsService {
(settingPermission) => settingPermission.setting === feature,
),
}),
{} as Record<SettingPermissionType, boolean>,
defaultSettingsPermissions,
);
const { data: rolesPermissions } =
@ -79,37 +77,53 @@ export class PermissionsService {
const objectPermissions = rolesPermissions[roleOfUserWorkspace.id] ?? {};
const objectRecordsPermissionsMap: Record<
PermissionsOnAllObjectRecords,
boolean
> = {
[PermissionsOnAllObjectRecords.READ_ALL_OBJECT_RECORDS]:
roleOfUserWorkspace.canReadAllObjectRecords ?? false,
[PermissionsOnAllObjectRecords.UPDATE_ALL_OBJECT_RECORDS]:
roleOfUserWorkspace.canUpdateAllObjectRecords ?? false,
[PermissionsOnAllObjectRecords.SOFT_DELETE_ALL_OBJECT_RECORDS]:
roleOfUserWorkspace.canSoftDeleteAllObjectRecords ?? false,
[PermissionsOnAllObjectRecords.DESTROY_ALL_OBJECT_RECORDS]:
roleOfUserWorkspace.canDestroyAllObjectRecords ?? false,
};
const objectRecordsPermissions: UserWorkspacePermissions['objectRecordsPermissions'] =
{
[PermissionsOnAllObjectRecords.READ_ALL_OBJECT_RECORDS]:
roleOfUserWorkspace.canReadAllObjectRecords ?? false,
[PermissionsOnAllObjectRecords.UPDATE_ALL_OBJECT_RECORDS]:
roleOfUserWorkspace.canUpdateAllObjectRecords ?? false,
[PermissionsOnAllObjectRecords.SOFT_DELETE_ALL_OBJECT_RECORDS]:
roleOfUserWorkspace.canSoftDeleteAllObjectRecords ?? false,
[PermissionsOnAllObjectRecords.DESTROY_ALL_OBJECT_RECORDS]:
roleOfUserWorkspace.canDestroyAllObjectRecords ?? false,
};
return {
settingsPermissions: settingsPermissionsMap,
objectRecordsPermissions: objectRecordsPermissionsMap,
settingsPermissions,
objectRecordsPermissions,
objectPermissions,
};
}
public getDefaultUserWorkspacePermissions = () =>
({
objectRecordsPermissions: {
[PermissionsOnAllObjectRecords.READ_ALL_OBJECT_RECORDS]: false,
[PermissionsOnAllObjectRecords.UPDATE_ALL_OBJECT_RECORDS]: false,
[PermissionsOnAllObjectRecords.SOFT_DELETE_ALL_OBJECT_RECORDS]: false,
[PermissionsOnAllObjectRecords.DESTROY_ALL_OBJECT_RECORDS]: false,
},
settingsPermissions: {
[SettingPermissionType.API_KEYS_AND_WEBHOOKS]: false,
[SettingPermissionType.WORKSPACE]: false,
[SettingPermissionType.WORKSPACE_MEMBERS]: false,
[SettingPermissionType.ROLES]: false,
[SettingPermissionType.DATA_MODEL]: false,
[SettingPermissionType.ADMIN_PANEL]: false,
[SettingPermissionType.SECURITY]: false,
[SettingPermissionType.WORKFLOWS]: false,
},
objectPermissions: {},
}) as const satisfies UserWorkspacePermissions;
public async getUserWorkspacePermissions({
userWorkspaceId,
workspaceId,
}: {
userWorkspaceId: string;
workspaceId: string;
}): Promise<{
settingsPermissions: Record<SettingPermissionType, boolean>;
objectRecordsPermissions: Record<PermissionsOnAllObjectRecords, boolean>;
}> {
}): Promise<UserWorkspacePermissions> {
const [roleOfUserWorkspace] = await this.userRoleService
.getRolesByUserWorkspaces({
userWorkspaceIds: [userWorkspaceId],
@ -132,7 +146,9 @@ export class PermissionsService {
const settingPermissions = roleOfUserWorkspace.settingPermissions ?? [];
const settingsPermissionsMap = Object.keys(SettingPermissionType).reduce(
const defaultSettingsPermissions =
this.getDefaultUserWorkspacePermissions().settingsPermissions;
const settingsPermissions = Object.keys(SettingPermissionType).reduce(
(acc, feature) => ({
...acc,
[feature]:
@ -141,26 +157,25 @@ export class PermissionsService {
(settingPermission) => settingPermission.setting === feature,
),
}),
{} as Record<SettingPermissionType, boolean>,
defaultSettingsPermissions,
);
const objectRecordsPermissionsMap: Record<
PermissionsOnAllObjectRecords,
boolean
> = {
[PermissionsOnAllObjectRecords.READ_ALL_OBJECT_RECORDS]:
roleOfUserWorkspace.canReadAllObjectRecords ?? false,
[PermissionsOnAllObjectRecords.UPDATE_ALL_OBJECT_RECORDS]:
roleOfUserWorkspace.canUpdateAllObjectRecords ?? false,
[PermissionsOnAllObjectRecords.SOFT_DELETE_ALL_OBJECT_RECORDS]:
roleOfUserWorkspace.canSoftDeleteAllObjectRecords ?? false,
[PermissionsOnAllObjectRecords.DESTROY_ALL_OBJECT_RECORDS]:
roleOfUserWorkspace.canDestroyAllObjectRecords ?? false,
};
const objectRecordsPermissions: UserWorkspacePermissions['objectRecordsPermissions'] =
{
[PermissionsOnAllObjectRecords.READ_ALL_OBJECT_RECORDS]:
roleOfUserWorkspace.canReadAllObjectRecords ?? false,
[PermissionsOnAllObjectRecords.UPDATE_ALL_OBJECT_RECORDS]:
roleOfUserWorkspace.canUpdateAllObjectRecords ?? false,
[PermissionsOnAllObjectRecords.SOFT_DELETE_ALL_OBJECT_RECORDS]:
roleOfUserWorkspace.canSoftDeleteAllObjectRecords ?? false,
[PermissionsOnAllObjectRecords.DESTROY_ALL_OBJECT_RECORDS]:
roleOfUserWorkspace.canDestroyAllObjectRecords ?? false,
};
return {
settingsPermissions: settingsPermissionsMap,
objectRecordsPermissions: objectRecordsPermissionsMap,
settingsPermissions,
objectRecordsPermissions,
objectPermissions: {},
};
}

View File

@ -0,0 +1,10 @@
import { PermissionsOnAllObjectRecords } from 'twenty-shared/constants';
import { ObjectRecordsPermissions } from 'twenty-shared/types';
import { SettingPermissionType } from 'src/engine/metadata-modules/permissions/constants/setting-permission-type.constants';
export type UserWorkspacePermissions = {
settingsPermissions: Record<SettingPermissionType, boolean>;
objectRecordsPermissions: Record<PermissionsOnAllObjectRecords, boolean>;
objectPermissions: ObjectRecordsPermissions;
};