From 04c5d066f8e41e811af79dd7f3b7d1ae84004da6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20M?= Date: Mon, 25 Mar 2024 16:58:58 +0100 Subject: [PATCH] fix: create deterministic uuids for standards relation on custom object (#4642) * fix: create deterministic uuids for standards relation on custom object * fix: remove check if standardId already exist to override old ones --- .../object-metadata.service.ts | 49 ++++++++++++++----- .../commands/add-standard-id.command.ts | 7 +-- .../utils/compute-standard-object.util.ts | 16 +++++- .../utils/create-deterministic-uuid.util.ts | 29 ++++++++++- 4 files changed, 79 insertions(+), 22 deletions(-) diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.service.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.service.ts index 1547da5921..0ba6b0a7ad 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.service.ts @@ -43,7 +43,10 @@ import { eventStandardFieldIds, favoriteStandardFieldIds, } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; -import { createDeterministicUuid } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util'; +import { + createForeignKeyDeterministicUuid, + createRelationDeterministicUuid, +} from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util'; import { ObjectMetadataEntity } from './object-metadata.entity'; @@ -662,7 +665,10 @@ export class ObjectMetadataService extends TypeOrmQueryService field.name === fieldMetadata.name && !field.isCustom, ); - if (!standardFieldMetadata || fieldMetadata.standardId) { + if (!standardFieldMetadata) { continue; } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-object.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-object.util.ts index 3356023f26..44baf83f4f 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-object.util.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-object.util.ts @@ -7,7 +7,10 @@ import { ComputedPartialFieldMetadata } from 'src/engine/workspace-manager/works import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { generateTargetColumnMap } from 'src/engine/metadata-modules/field-metadata/utils/generate-target-column-map.util'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; -import { createDeterministicUuid } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util'; +import { + createForeignKeyDeterministicUuid, + createRelationDeterministicUuid, +} from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util'; export const computeStandardObject = ( standardObjectMetadata: Omit & { @@ -24,11 +27,20 @@ export const computeStandardObject = ( for (const customObjectMetadata of customObjectMetadataCollection) { const { paramsFactory, ...rest } = partialFieldMetadata; const { joinColumn, ...data } = paramsFactory(customObjectMetadata); + const relationStandardId = createRelationDeterministicUuid({ + objectId: customObjectMetadata.id, + standardId: data.standardId, + }); + const foreignKeyStandardId = createForeignKeyDeterministicUuid({ + objectId: customObjectMetadata.id, + standardId: data.standardId, + }); // Relation fields.push({ ...data, ...rest, + standardId: relationStandardId, defaultValue: null, targetColumnMap: {}, }); @@ -36,7 +48,7 @@ export const computeStandardObject = ( // Foreign key fields.push({ ...rest, - standardId: createDeterministicUuid(data.standardId), + standardId: foreignKeyStandardId, name: joinColumn, type: FieldMetadataType.UUID, label: `${data.label} ID (foreign key)`, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util.ts index 39bca87807..0efddfc12a 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util.ts @@ -1,10 +1,35 @@ import { createHash } from 'crypto'; -export const createDeterministicUuid = (inputUuid: string): string => { - const hash = createHash('sha256').update(inputUuid).digest('hex'); +export function createDeterministicUuid(uuid: string): string; +export function createDeterministicUuid(uuids: string[]): string; + +export function createDeterministicUuid( + uuidOrUuids: string[] | string, +): string { + const inputForHash = Array.isArray(uuidOrUuids) + ? uuidOrUuids.join('-') + : uuidOrUuids; + const hash = createHash('sha256').update(inputForHash).digest('hex'); return `20202020-${hash.substring(0, 4)}-4${hash.substring( 4, 7, )}-8${hash.substring(7, 10)}-${hash.substring(10, 22)}`; +} + +type UuidPair = { + objectId: string; + standardId: string; +}; + +export const createRelationDeterministicUuid = (uuidPair: UuidPair): string => { + // Chaging the order in the array will result in different UUIDs + return createDeterministicUuid([uuidPair.objectId, uuidPair.standardId]); +}; + +export const createForeignKeyDeterministicUuid = ( + uuidPair: UuidPair, +): string => { + // Chaging the order in the array will result in different UUIDs + return createDeterministicUuid([uuidPair.standardId, uuidPair.objectId]); };