Fix role synchronisation (#19469)
As title solves https://discord.com/channels/1130383047699738754/1491167098398052503
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import { CoreApiClient } from 'twenty-client-sdk/core';
|
||||
import { definePostInstallLogicFunction } from 'twenty-sdk';
|
||||
|
||||
const POST_CARDS_TO_SEED = [
|
||||
{
|
||||
name: 'Greetings from Paris',
|
||||
content:
|
||||
'Wish you were here! The Eiffel Tower looks even better in person. - Alex',
|
||||
},
|
||||
{
|
||||
name: 'Hello from Tokyo',
|
||||
content:
|
||||
'The cherry blossoms are amazing this time of year. See you soon! - Sam',
|
||||
},
|
||||
];
|
||||
|
||||
const handler = async (): Promise<{
|
||||
message: string;
|
||||
createdIds: string[];
|
||||
}> => {
|
||||
console.log('Seeding 2 post cards...');
|
||||
const client = new CoreApiClient();
|
||||
|
||||
const createdIds: string[] = [];
|
||||
|
||||
for (const postCard of POST_CARDS_TO_SEED) {
|
||||
const { createPostCard } = await client.mutation({
|
||||
createPostCard: {
|
||||
__args: {
|
||||
data: {
|
||||
name: postCard.name,
|
||||
content: postCard.content,
|
||||
},
|
||||
},
|
||||
id: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!createPostCard?.id) {
|
||||
throw new Error(`Failed to create post card "${postCard.name}"`);
|
||||
}
|
||||
|
||||
createdIds.push(createPostCard.id);
|
||||
}
|
||||
|
||||
console.log('Seeding complete!');
|
||||
return {
|
||||
message: `Seeded ${createdIds.length} post cards`,
|
||||
createdIds,
|
||||
};
|
||||
};
|
||||
|
||||
export default definePostInstallLogicFunction({
|
||||
universalIdentifier: '9f3d8c21-b471-4a82-8e5c-6f3a7b8c9d01',
|
||||
name: 'seed-post-cards',
|
||||
description: 'Seeds the workspace with 2 sample post card records.',
|
||||
timeoutSeconds: 10,
|
||||
handler,
|
||||
});
|
||||
@@ -33,7 +33,7 @@ export default defineRole({
|
||||
objectUniversalIdentifier: POST_CARD_UNIVERSAL_IDENTIFIER,
|
||||
fieldUniversalIdentifier: CONTENT_FIELD_UNIVERSAL_IDENTIFIER,
|
||||
canReadFieldValue: false,
|
||||
canUpdateFieldValue: false,
|
||||
canUpdateFieldValue: true,
|
||||
},
|
||||
],
|
||||
permissionFlags: [PermissionFlag.APPLICATIONS],
|
||||
|
||||
+8
-6
@@ -153,12 +153,14 @@ const buildSyntheticRole = (
|
||||
canReadFieldValue: permission.canReadFieldValue,
|
||||
canUpdateFieldValue: permission.canUpdateFieldValue,
|
||||
})),
|
||||
permissionFlags: (defaultRole.permissionFlags ?? []).map((flag) => ({
|
||||
__typename: 'PermissionFlag' as const,
|
||||
id: uuidv4(),
|
||||
roleId: defaultRole.universalIdentifier,
|
||||
flag: flag as PermissionFlagType,
|
||||
})),
|
||||
permissionFlags: (defaultRole.permissionFlags ?? []).map(
|
||||
(permissionFlag) => ({
|
||||
__typename: 'PermissionFlag' as const,
|
||||
id: uuidv4(),
|
||||
roleId: defaultRole.universalIdentifier,
|
||||
flag: permissionFlag.flag,
|
||||
}),
|
||||
),
|
||||
});
|
||||
|
||||
const buildFieldMetadataItemFromMarketplaceField = (
|
||||
|
||||
+3
@@ -363,6 +363,9 @@ export const EXPECTED_MANIFEST: Manifest = {
|
||||
canBeAssignedToAgents: false,
|
||||
canBeAssignedToUsers: true,
|
||||
canBeAssignedToApiKeys: false,
|
||||
fieldPermissions: [],
|
||||
objectPermissions: [],
|
||||
permissionFlags: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
+11
-1
@@ -1499,6 +1499,9 @@ export const EXPECTED_MANIFEST: Manifest = {
|
||||
description: 'A simple root-level role',
|
||||
label: 'Root role',
|
||||
universalIdentifier: 'c0c1c2c3-c4c5-4000-8000-000000000001',
|
||||
fieldPermissions: [],
|
||||
objectPermissions: [],
|
||||
permissionFlags: [],
|
||||
},
|
||||
{
|
||||
canBeAssignedToAgents: false,
|
||||
@@ -1512,6 +1515,7 @@ export const EXPECTED_MANIFEST: Manifest = {
|
||||
description: 'Default role for function Twenty client',
|
||||
fieldPermissions: [
|
||||
{
|
||||
universalIdentifier: 'dbc86ced-bd2c-5874-93f1-1f72c5111991',
|
||||
canReadFieldValue: false,
|
||||
canUpdateFieldValue: false,
|
||||
fieldUniversalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
|
||||
@@ -1521,6 +1525,7 @@ export const EXPECTED_MANIFEST: Manifest = {
|
||||
label: 'Default function role',
|
||||
objectPermissions: [
|
||||
{
|
||||
universalIdentifier: '99c7c326-04ca-5c8b-ad11-da6c5b819813',
|
||||
canDestroyObjectRecords: false,
|
||||
canReadObjectRecords: true,
|
||||
canSoftDeleteObjectRecords: false,
|
||||
@@ -1528,7 +1533,12 @@ export const EXPECTED_MANIFEST: Manifest = {
|
||||
objectUniversalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
|
||||
},
|
||||
],
|
||||
permissionFlags: [PermissionFlagType.APPLICATIONS],
|
||||
permissionFlags: [
|
||||
{
|
||||
universalIdentifier: '01d7865a-7700-5d49-b2aa-62623c2cbac7',
|
||||
flag: PermissionFlagType.APPLICATIONS,
|
||||
},
|
||||
],
|
||||
universalIdentifier: 'b648f87b-1d26-4961-b974-0908fd991061',
|
||||
},
|
||||
],
|
||||
|
||||
@@ -38,6 +38,8 @@ import {
|
||||
import { getInputSchemaFromSourceCode } from 'twenty-shared/logic-function';
|
||||
import { assertUnreachable } from 'twenty-shared/utils';
|
||||
import { addMissingFieldOptionIds } from '@/cli/utilities/build/manifest/utils/add-missing-field-option-ids';
|
||||
import { fromRoleConfigToRoleManifest } from '@/cli/utilities/build/manifest/utils/from-role-config-to-role-manifest';
|
||||
import { type RoleConfig } from '@/sdk/roles/role-config';
|
||||
|
||||
const loadSources = async (appPath: string): Promise<string[]> => {
|
||||
return await glob(['**/*.ts', '**/*.tsx'], {
|
||||
@@ -170,11 +172,12 @@ export const buildManifest = async (
|
||||
break;
|
||||
}
|
||||
case ManifestEntityKey.Roles: {
|
||||
const extract = await extractManifestFromFile<RoleManifest>({
|
||||
const extract = await extractManifestFromFile<RoleConfig>({
|
||||
appPath,
|
||||
filePath,
|
||||
});
|
||||
roles.push(extract.config);
|
||||
const roleConfig = fromRoleConfigToRoleManifest(extract.config);
|
||||
roles.push(roleConfig);
|
||||
errors.push(...extract.errors);
|
||||
rolesFilePaths.push(relativePath);
|
||||
break;
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
import { type RoleConfig } from '@/sdk/roles/role-config';
|
||||
import { type RoleManifest } from 'twenty-shared/application';
|
||||
import { v5 as uuidv5 } from 'uuid';
|
||||
|
||||
const ROLE_UNIVERSAL_IDENTIFIER_NAMESPACE =
|
||||
'b403ec59-4d80-4f22-85e6-717a192dc9cb';
|
||||
|
||||
export const fromRoleConfigToRoleManifest = (
|
||||
roleConfig: RoleConfig,
|
||||
): RoleManifest => {
|
||||
return {
|
||||
...roleConfig,
|
||||
objectPermissions: (roleConfig.objectPermissions ?? []).map(
|
||||
(objectPermission) => ({
|
||||
...objectPermission,
|
||||
universalIdentifier: uuidv5(
|
||||
`${roleConfig.universalIdentifier}:${objectPermission.objectUniversalIdentifier}`,
|
||||
ROLE_UNIVERSAL_IDENTIFIER_NAMESPACE,
|
||||
),
|
||||
}),
|
||||
),
|
||||
fieldPermissions: (roleConfig.fieldPermissions ?? []).map(
|
||||
(fieldPermission) => ({
|
||||
...fieldPermission,
|
||||
universalIdentifier: uuidv5(
|
||||
`${roleConfig.universalIdentifier}:${fieldPermission.objectUniversalIdentifier}:${fieldPermission.fieldUniversalIdentifier}`,
|
||||
ROLE_UNIVERSAL_IDENTIFIER_NAMESPACE,
|
||||
),
|
||||
}),
|
||||
),
|
||||
permissionFlags: (roleConfig.permissionFlags ?? []).map(
|
||||
(permissionFlag) => ({
|
||||
universalIdentifier: uuidv5(
|
||||
`${roleConfig.universalIdentifier}:${permissionFlag}`,
|
||||
ROLE_UNIVERSAL_IDENTIFIER_NAMESPACE,
|
||||
),
|
||||
flag: permissionFlag,
|
||||
}),
|
||||
),
|
||||
};
|
||||
};
|
||||
@@ -4,10 +4,10 @@ import { type LogicFunctionConfig } from '@/sdk/logic-functions/logic-function-c
|
||||
import { type ObjectConfig } from '@/sdk/objects/object-config';
|
||||
import { type PageLayoutConfig } from '@/sdk/page-layouts/page-layout-config';
|
||||
import { type ViewConfig } from '@/sdk/views/view-config';
|
||||
import { type RoleConfig } from '@/sdk/roles/role-config';
|
||||
import {
|
||||
type FieldManifest,
|
||||
type NavigationMenuItemManifest,
|
||||
type RoleManifest,
|
||||
type SkillManifest,
|
||||
} from 'twenty-shared/application';
|
||||
|
||||
@@ -23,7 +23,7 @@ export type DefinableEntity =
|
||||
| FieldManifest
|
||||
| FrontComponentConfig
|
||||
| LogicFunctionConfig
|
||||
| RoleManifest
|
||||
| RoleConfig
|
||||
| SkillManifest
|
||||
| ViewConfig
|
||||
| NavigationMenuItemManifest
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { createValidationResult } from '@/sdk/common/utils/create-validation-result';
|
||||
import { type RoleManifest } from 'twenty-shared/application';
|
||||
import { type DefineEntity } from '@/sdk/common/types/define-entity.type';
|
||||
import { type RoleConfig } from '@/sdk/roles/role-config';
|
||||
|
||||
export const defineRole: DefineEntity<RoleManifest> = (config) => {
|
||||
export const defineRole: DefineEntity<RoleConfig> = (config) => {
|
||||
const errors = [];
|
||||
|
||||
if (!config.universalIdentifier) {
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import type {
|
||||
FieldPermissionManifest,
|
||||
ObjectPermissionManifest,
|
||||
RoleManifest,
|
||||
} from 'twenty-shared/application';
|
||||
import { type PermissionFlagType } from 'twenty-shared/constants';
|
||||
|
||||
export type RoleConfig = Omit<
|
||||
RoleManifest,
|
||||
'objectPermissions' | 'fieldPermissions' | 'permissionFlags'
|
||||
> & {
|
||||
objectPermissions?: Omit<ObjectPermissionManifest, 'universalIdentifier'>[];
|
||||
fieldPermissions?: Omit<FieldPermissionManifest, 'universalIdentifier'>[];
|
||||
permissionFlags?: PermissionFlagType[];
|
||||
};
|
||||
+3
-149
@@ -1,6 +1,6 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { type Manifest, type RoleManifest } from 'twenty-shared/application';
|
||||
import { type Manifest } from 'twenty-shared/application';
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
@@ -15,9 +15,6 @@ import { computeApplicationManifestAllUniversalFlatEntityMaps } from 'src/engine
|
||||
import { getApplicationSubAllFlatEntityMaps } from 'src/engine/core-modules/application/application-manifest/utils/get-application-sub-all-flat-entity-maps.util';
|
||||
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
|
||||
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
|
||||
import { FieldPermissionService } from 'src/engine/metadata-modules/object-permission/field-permission/field-permission.service';
|
||||
import { ObjectPermissionService } from 'src/engine/metadata-modules/object-permission/object-permission.service';
|
||||
import { PermissionFlagService } from 'src/engine/metadata-modules/permission-flag/permission-flag.service';
|
||||
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
|
||||
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications';
|
||||
import { WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
|
||||
@@ -34,9 +31,6 @@ export class ApplicationManifestMigrationService {
|
||||
private readonly workspaceCacheService: WorkspaceCacheService,
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
private readonly objectPermissionService: ObjectPermissionService,
|
||||
private readonly fieldPermissionService: FieldPermissionService,
|
||||
private readonly permissionFlagService: PermissionFlagService,
|
||||
) {}
|
||||
|
||||
async syncMetadataFromManifest({
|
||||
@@ -119,7 +113,7 @@ export class ApplicationManifestMigrationService {
|
||||
`Metadata migration completed for application ${ownerFlatApplication.universalIdentifier}`,
|
||||
);
|
||||
|
||||
await this.syncRolePermissionsAndDefaultRole({
|
||||
await this.syncDefaultRoleAndSettingsCustomTab({
|
||||
manifest,
|
||||
workspaceId,
|
||||
ownerFlatApplication,
|
||||
@@ -131,13 +125,7 @@ export class ApplicationManifestMigrationService {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated should be remove once below issues are resolved:
|
||||
* - [objectPermission](https://github.com/twentyhq/core-team-issues/issues/2223)
|
||||
* - [fieldPermission](https://github.com/twentyhq/core-team-issues/issues/2224)
|
||||
* - [permissionFlag](https://github.com/twentyhq/core-team-issues/issues/2225)
|
||||
*/
|
||||
private async syncRolePermissionsAndDefaultRole({
|
||||
private async syncDefaultRoleAndSettingsCustomTab({
|
||||
manifest,
|
||||
workspaceId,
|
||||
ownerFlatApplication,
|
||||
@@ -148,13 +136,9 @@ export class ApplicationManifestMigrationService {
|
||||
}) {
|
||||
const {
|
||||
flatRoleMaps: refreshedFlatRoleMaps,
|
||||
flatObjectMetadataMaps: refreshedFlatObjectMetadataMaps,
|
||||
flatFieldMetadataMaps: refreshedFlatFieldMetadataMaps,
|
||||
flatFrontComponentMaps: refreshedFlatFrontComponentMaps,
|
||||
} = await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
'flatRoleMaps',
|
||||
'flatObjectMetadataMaps',
|
||||
'flatFieldMetadataMaps',
|
||||
'flatFrontComponentMaps',
|
||||
]);
|
||||
|
||||
@@ -173,14 +157,6 @@ export class ApplicationManifestMigrationService {
|
||||
);
|
||||
}
|
||||
|
||||
await this.syncApplicationRolePermissions({
|
||||
role,
|
||||
workspaceId,
|
||||
roleId: flatRole.id,
|
||||
refreshedFlatObjectMetadataMaps,
|
||||
refreshedFlatFieldMetadataMaps,
|
||||
});
|
||||
|
||||
if (
|
||||
role.universalIdentifier ===
|
||||
manifest.application.defaultRoleUniversalIdentifier
|
||||
@@ -216,126 +192,4 @@ export class ApplicationManifestMigrationService {
|
||||
...(isDefined(defaultRoleId) ? { defaultRoleId } : {}),
|
||||
});
|
||||
}
|
||||
|
||||
private async syncApplicationRolePermissions({
|
||||
role,
|
||||
workspaceId,
|
||||
roleId,
|
||||
refreshedFlatObjectMetadataMaps,
|
||||
refreshedFlatFieldMetadataMaps,
|
||||
}: {
|
||||
role: RoleManifest;
|
||||
workspaceId: string;
|
||||
roleId: string;
|
||||
refreshedFlatObjectMetadataMaps: Awaited<
|
||||
ReturnType<WorkspaceCacheService['getOrRecompute']>
|
||||
>['flatObjectMetadataMaps'];
|
||||
refreshedFlatFieldMetadataMaps: Awaited<
|
||||
ReturnType<WorkspaceCacheService['getOrRecompute']>
|
||||
>['flatFieldMetadataMaps'];
|
||||
}) {
|
||||
if (
|
||||
(role.objectPermissions ?? []).length > 0 ||
|
||||
(role.fieldPermissions ?? []).length > 0
|
||||
) {
|
||||
const formattedObjectPermissions = role.objectPermissions
|
||||
?.map((permission) => {
|
||||
const flatObjectMetadata = findFlatEntityByUniversalIdentifier({
|
||||
flatEntityMaps: refreshedFlatObjectMetadataMaps,
|
||||
universalIdentifier: permission.objectUniversalIdentifier,
|
||||
});
|
||||
|
||||
if (!isDefined(flatObjectMetadata)) {
|
||||
throw new ApplicationException(
|
||||
`Failed to find object with universalIdentifier ${permission.objectUniversalIdentifier}`,
|
||||
ApplicationExceptionCode.OBJECT_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...permission,
|
||||
objectMetadataId: flatObjectMetadata.id,
|
||||
};
|
||||
})
|
||||
.filter(
|
||||
(
|
||||
permission,
|
||||
): permission is typeof permission & { objectMetadataId: string } =>
|
||||
isDefined(permission.objectMetadataId),
|
||||
);
|
||||
|
||||
if (isDefined(formattedObjectPermissions)) {
|
||||
await this.objectPermissionService.upsertObjectPermissions({
|
||||
workspaceId,
|
||||
input: {
|
||||
roleId,
|
||||
objectPermissions: formattedObjectPermissions,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const formattedFieldPermissions = role.fieldPermissions
|
||||
?.map((permission) => {
|
||||
const flatObjectMetadata = findFlatEntityByUniversalIdentifier({
|
||||
flatEntityMaps: refreshedFlatObjectMetadataMaps,
|
||||
universalIdentifier: permission.objectUniversalIdentifier,
|
||||
});
|
||||
|
||||
if (!isDefined(flatObjectMetadata)) {
|
||||
throw new ApplicationException(
|
||||
`Failed to find object with universalIdentifier ${permission.objectUniversalIdentifier}`,
|
||||
ApplicationExceptionCode.OBJECT_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const flatFieldMetadata = findFlatEntityByUniversalIdentifier({
|
||||
flatEntityMaps: refreshedFlatFieldMetadataMaps,
|
||||
universalIdentifier: permission.fieldUniversalIdentifier,
|
||||
});
|
||||
|
||||
if (!isDefined(flatFieldMetadata)) {
|
||||
throw new ApplicationException(
|
||||
`Failed to find field with universalIdentifier ${permission.fieldUniversalIdentifier}`,
|
||||
ApplicationExceptionCode.FIELD_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...permission,
|
||||
objectMetadataId: flatObjectMetadata.id,
|
||||
fieldMetadataId: flatFieldMetadata.id,
|
||||
};
|
||||
})
|
||||
.filter(
|
||||
(
|
||||
permission,
|
||||
): permission is typeof permission & {
|
||||
objectMetadataId: string;
|
||||
fieldMetadataId: string;
|
||||
} =>
|
||||
isDefined(permission.objectMetadataId) &&
|
||||
isDefined(permission.fieldMetadataId),
|
||||
);
|
||||
|
||||
if (isDefined(formattedFieldPermissions)) {
|
||||
await this.fieldPermissionService.upsertFieldPermissions({
|
||||
workspaceId,
|
||||
input: {
|
||||
roleId,
|
||||
fieldPermissions: formattedFieldPermissions,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (isDefined(role.permissionFlags) && role.permissionFlags.length > 0) {
|
||||
await this.permissionFlagService.upsertPermissionFlags({
|
||||
workspaceId,
|
||||
input: {
|
||||
roleId,
|
||||
permissionFlagKeys: role.permissionFlags,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-4
@@ -7,8 +7,6 @@ import { ApplicationSyncService } from 'src/engine/core-modules/application/appl
|
||||
import { ApplicationVariableEntityModule } from 'src/engine/core-modules/application/application-variable/application-variable.module';
|
||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||
import { FileStorageModule } from 'src/engine/core-modules/file-storage/file-storage.module';
|
||||
import { ObjectPermissionModule } from 'src/engine/metadata-modules/object-permission/object-permission.module';
|
||||
import { PermissionFlagModule } from 'src/engine/metadata-modules/permission-flag/permission-flag.module';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
|
||||
import { WorkspaceMigrationGraphqlApiExceptionInterceptor } from 'src/engine/workspace-manager/workspace-migration/interceptors/workspace-migration-graphql-api-exception.interceptor';
|
||||
@@ -21,8 +19,6 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
|
||||
ApplicationVariableEntityModule,
|
||||
FeatureFlagModule,
|
||||
FileStorageModule,
|
||||
ObjectPermissionModule,
|
||||
PermissionFlagModule,
|
||||
PermissionsModule,
|
||||
WorkspaceCacheModule,
|
||||
WorkspaceMigrationModule,
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
import { type FieldPermissionManifest } from 'twenty-shared/application';
|
||||
import { type UniversalFlatFieldPermission } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-field-permission.type';
|
||||
|
||||
export const fromFieldPermissionManifestToUniversalFlatFieldPermission = ({
|
||||
fieldPermissionManifest,
|
||||
roleUniversalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
now,
|
||||
}: {
|
||||
fieldPermissionManifest: FieldPermissionManifest;
|
||||
roleUniversalIdentifier: string;
|
||||
applicationUniversalIdentifier: string;
|
||||
now: string;
|
||||
}): UniversalFlatFieldPermission => {
|
||||
return {
|
||||
universalIdentifier: fieldPermissionManifest.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
roleUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier:
|
||||
fieldPermissionManifest.objectUniversalIdentifier,
|
||||
fieldMetadataUniversalIdentifier:
|
||||
fieldPermissionManifest.fieldUniversalIdentifier,
|
||||
canReadFieldValue: fieldPermissionManifest.canReadFieldValue ?? null,
|
||||
canUpdateFieldValue: fieldPermissionManifest.canUpdateFieldValue ?? null,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
};
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
import { type ObjectPermissionManifest } from 'twenty-shared/application';
|
||||
import { type UniversalFlatObjectPermission } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-object-permission.type';
|
||||
|
||||
export const fromObjectPermissionManifestToUniversalFlatObjectPermission = ({
|
||||
objectPermissionManifest,
|
||||
roleUniversalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
now,
|
||||
}: {
|
||||
objectPermissionManifest: ObjectPermissionManifest;
|
||||
roleUniversalIdentifier: string;
|
||||
applicationUniversalIdentifier: string;
|
||||
now: string;
|
||||
}): UniversalFlatObjectPermission => {
|
||||
return {
|
||||
universalIdentifier: objectPermissionManifest.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
roleUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier:
|
||||
objectPermissionManifest.objectUniversalIdentifier,
|
||||
canReadObjectRecords: objectPermissionManifest.canReadObjectRecords,
|
||||
canUpdateObjectRecords: objectPermissionManifest.canUpdateObjectRecords,
|
||||
canSoftDeleteObjectRecords:
|
||||
objectPermissionManifest.canSoftDeleteObjectRecords,
|
||||
canDestroyObjectRecords: objectPermissionManifest.canDestroyObjectRecords,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
};
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { type UniversalFlatPermissionFlag } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-permission-flag.type';
|
||||
import { PermissionFlagManifest } from 'twenty-shared/application';
|
||||
|
||||
export const fromPermissionFlagToUniversalFlatPermissionFlag = ({
|
||||
permissionFlag,
|
||||
roleUniversalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
now,
|
||||
}: {
|
||||
permissionFlag: PermissionFlagManifest;
|
||||
roleUniversalIdentifier: string;
|
||||
applicationUniversalIdentifier: string;
|
||||
now: string;
|
||||
}): UniversalFlatPermissionFlag => {
|
||||
return {
|
||||
universalIdentifier: permissionFlag.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
roleUniversalIdentifier,
|
||||
flag: permissionFlag.flag,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
};
|
||||
+44
@@ -4,13 +4,16 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { fromCommandMenuItemManifestToUniversalFlatCommandMenuItem } from 'src/engine/core-modules/application/application-manifest/converters/from-command-menu-item-manifest-to-universal-flat-command-menu-item.util';
|
||||
import { fromFieldManifestToUniversalFlatFieldMetadata } from 'src/engine/core-modules/application/application-manifest/converters/from-field-manifest-to-universal-flat-field-metadata.util';
|
||||
import { fromFieldPermissionManifestToUniversalFlatFieldPermission } from 'src/engine/core-modules/application/application-manifest/converters/from-field-permission-manifest-to-universal-flat-field-permission.util';
|
||||
import { fromFrontComponentManifestToUniversalFlatFrontComponent } from 'src/engine/core-modules/application/application-manifest/converters/from-front-component-manifest-to-universal-flat-front-component.util';
|
||||
import { fromLogicFunctionManifestToUniversalFlatLogicFunction } from 'src/engine/core-modules/application/application-manifest/converters/from-logic-function-manifest-to-universal-flat-logic-function.util';
|
||||
import { fromNavigationMenuItemManifestToUniversalFlatNavigationMenuItem } from 'src/engine/core-modules/application/application-manifest/converters/from-navigation-menu-item-manifest-to-universal-flat-navigation-menu-item.util';
|
||||
import { fromObjectManifestToUniversalFlatObjectMetadata } from 'src/engine/core-modules/application/application-manifest/converters/from-object-manifest-to-universal-flat-object-metadata.util';
|
||||
import { fromObjectPermissionManifestToUniversalFlatObjectPermission } from 'src/engine/core-modules/application/application-manifest/converters/from-object-permission-manifest-to-universal-flat-object-permission.util';
|
||||
import { fromPageLayoutManifestToUniversalFlatPageLayout } from 'src/engine/core-modules/application/application-manifest/converters/from-page-layout-manifest-to-universal-flat-page-layout.util';
|
||||
import { fromPageLayoutTabManifestToUniversalFlatPageLayoutTab } from 'src/engine/core-modules/application/application-manifest/converters/from-page-layout-tab-manifest-to-universal-flat-page-layout-tab.util';
|
||||
import { fromPageLayoutWidgetManifestToUniversalFlatPageLayoutWidget } from 'src/engine/core-modules/application/application-manifest/converters/from-page-layout-widget-manifest-to-universal-flat-page-layout-widget.util';
|
||||
import { fromPermissionFlagToUniversalFlatPermissionFlag } from 'src/engine/core-modules/application/application-manifest/converters/from-permission-flag-to-universal-flat-permission-flag.util';
|
||||
import { fromRoleManifestToUniversalFlatRole } from 'src/engine/core-modules/application/application-manifest/converters/from-role-manifest-to-universal-flat-role.util';
|
||||
import { fromSkillManifestToUniversalFlatSkill } from 'src/engine/core-modules/application/application-manifest/converters/from-skill-manifest-to-universal-flat-skill.util';
|
||||
import { computeSearchVectorUniversalSettingsFromObjectManifest } from 'src/engine/core-modules/application/application-manifest/utils/compute-search-vector-universal-settings-from-object-manifest.util';
|
||||
@@ -144,6 +147,47 @@ export const computeApplicationManifestAllUniversalFlatEntityMaps = ({
|
||||
}),
|
||||
universalFlatEntityMapsToMutate: allUniversalFlatEntityMaps.flatRoleMaps,
|
||||
});
|
||||
for (const objectPermissionManifest of roleManifest.objectPermissions ??
|
||||
[]) {
|
||||
addUniversalFlatEntityToUniversalFlatEntityMapsThroughMutationOrThrow({
|
||||
universalFlatEntity:
|
||||
fromObjectPermissionManifestToUniversalFlatObjectPermission({
|
||||
objectPermissionManifest,
|
||||
roleUniversalIdentifier: roleManifest.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
now,
|
||||
}),
|
||||
universalFlatEntityMapsToMutate:
|
||||
allUniversalFlatEntityMaps.flatObjectPermissionMaps,
|
||||
});
|
||||
}
|
||||
|
||||
for (const fieldPermissionManifest of roleManifest.fieldPermissions ?? []) {
|
||||
addUniversalFlatEntityToUniversalFlatEntityMapsThroughMutationOrThrow({
|
||||
universalFlatEntity:
|
||||
fromFieldPermissionManifestToUniversalFlatFieldPermission({
|
||||
fieldPermissionManifest,
|
||||
roleUniversalIdentifier: roleManifest.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
now,
|
||||
}),
|
||||
universalFlatEntityMapsToMutate:
|
||||
allUniversalFlatEntityMaps.flatFieldPermissionMaps,
|
||||
});
|
||||
}
|
||||
|
||||
for (const permissionFlag of roleManifest.permissionFlags ?? []) {
|
||||
addUniversalFlatEntityToUniversalFlatEntityMapsThroughMutationOrThrow({
|
||||
universalFlatEntity: fromPermissionFlagToUniversalFlatPermissionFlag({
|
||||
permissionFlag,
|
||||
roleUniversalIdentifier: roleManifest.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
now,
|
||||
}),
|
||||
universalFlatEntityMapsToMutate:
|
||||
allUniversalFlatEntityMaps.flatPermissionFlagMaps,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (const skillManifest of manifest.skills ?? []) {
|
||||
|
||||
@@ -47,6 +47,7 @@ export type {
|
||||
export type {
|
||||
ObjectPermissionManifest,
|
||||
FieldPermissionManifest,
|
||||
PermissionFlagManifest,
|
||||
RoleManifest,
|
||||
} from './roleManifestType';
|
||||
export type { ServerVariables } from './server-variables.type';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { type PermissionFlagType } from '@/constants';
|
||||
import { type SyncableEntityOptions } from '@/application/syncableEntityOptionsType';
|
||||
|
||||
export type ObjectPermissionManifest = {
|
||||
export type ObjectPermissionManifest = SyncableEntityOptions & {
|
||||
objectUniversalIdentifier: string;
|
||||
canReadObjectRecords?: boolean;
|
||||
canUpdateObjectRecords?: boolean;
|
||||
@@ -9,13 +9,17 @@ export type ObjectPermissionManifest = {
|
||||
canDestroyObjectRecords?: boolean;
|
||||
};
|
||||
|
||||
export type FieldPermissionManifest = {
|
||||
export type FieldPermissionManifest = SyncableEntityOptions & {
|
||||
objectUniversalIdentifier: string;
|
||||
fieldUniversalIdentifier: string;
|
||||
canReadFieldValue?: boolean;
|
||||
canUpdateFieldValue?: boolean;
|
||||
};
|
||||
|
||||
export type PermissionFlagManifest = SyncableEntityOptions & {
|
||||
flag: PermissionFlagType;
|
||||
};
|
||||
|
||||
export type RoleManifest = SyncableEntityOptions & {
|
||||
label: string;
|
||||
description?: string;
|
||||
@@ -31,5 +35,5 @@ export type RoleManifest = SyncableEntityOptions & {
|
||||
canBeAssignedToApiKeys?: boolean;
|
||||
objectPermissions?: ObjectPermissionManifest[];
|
||||
fieldPermissions?: FieldPermissionManifest[];
|
||||
permissionFlags?: PermissionFlagType[];
|
||||
permissionFlags?: PermissionFlagManifest[];
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user