Skip to content

Commit

Permalink
fix: create deterministic uuids for standards relation on custom obje…
Browse files Browse the repository at this point in the history
…ct (twentyhq#4642)

* fix: create deterministic uuids for standards relation on custom object

* fix: remove check if standardId already exist to override old ones
  • Loading branch information
magrinj authored Mar 25, 2024
1 parent 1925506 commit a327a76
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -662,7 +665,10 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
},
// TO
{
standardId: activityTargetStandardFieldIds.custom,
standardId: createRelationDeterministicUuid({
objectId: createdObjectMetadata.id,
standardId: activityTargetStandardFieldIds.custom,
}),
objectMetadataId: activityTargetObjectMetadata.id,
workspaceId: workspaceId,
isCustom: false,
Expand All @@ -677,9 +683,10 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
},
// Foreign key
{
standardId: createDeterministicUuid(
activityTargetStandardFieldIds.custom,
),
standardId: createForeignKeyDeterministicUuid({
objectId: createdObjectMetadata.id,
standardId: activityTargetStandardFieldIds.custom,
}),
objectMetadataId: activityTargetObjectMetadata.id,
workspaceId: workspaceId,
isCustom: false,
Expand Down Expand Up @@ -761,7 +768,10 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
},
// TO
{
standardId: attachmentStandardFieldIds.custom,
standardId: createRelationDeterministicUuid({
objectId: createdObjectMetadata.id,
standardId: attachmentStandardFieldIds.custom,
}),
objectMetadataId: attachmentObjectMetadata.id,
workspaceId: workspaceId,
isCustom: false,
Expand All @@ -776,9 +786,10 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
},
// Foreign key
{
standardId: createDeterministicUuid(
attachmentStandardFieldIds.custom,
),
standardId: createForeignKeyDeterministicUuid({
objectId: createdObjectMetadata.id,
standardId: attachmentStandardFieldIds.custom,
}),
objectMetadataId: attachmentObjectMetadata.id,
workspaceId: workspaceId,
isCustom: false,
Expand Down Expand Up @@ -857,7 +868,10 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
},
// TO
{
standardId: eventStandardFieldIds.custom,
standardId: createRelationDeterministicUuid({
objectId: createdObjectMetadata.id,
standardId: eventStandardFieldIds.custom,
}),
objectMetadataId: eventObjectMetadata.id,
workspaceId: workspaceId,
isCustom: false,
Expand All @@ -872,7 +886,10 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
},
// Foreign key
{
standardId: createDeterministicUuid(eventStandardFieldIds.custom),
standardId: createForeignKeyDeterministicUuid({
objectId: createdObjectMetadata.id,
standardId: eventStandardFieldIds.custom,
}),
objectMetadataId: eventObjectMetadata.id,
workspaceId: workspaceId,
isCustom: false,
Expand Down Expand Up @@ -952,7 +969,10 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
},
// TO
{
standardId: favoriteStandardFieldIds.custom,
standardId: createRelationDeterministicUuid({
objectId: createdObjectMetadata.id,
standardId: favoriteStandardFieldIds.custom,
}),
objectMetadataId: favoriteObjectMetadata.id,
workspaceId: workspaceId,
isCustom: false,
Expand All @@ -967,7 +987,10 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
},
// Foreign key
{
standardId: createDeterministicUuid(favoriteStandardFieldIds.custom),
standardId: createForeignKeyDeterministicUuid({
objectId: createdObjectMetadata.id,
standardId: favoriteStandardFieldIds.custom,
}),
objectMetadataId: favoriteObjectMetadata.id,
workspaceId: workspaceId,
isCustom: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,7 @@ export class AddStandardIdCommand extends CommandRunner {
customObjectMetadataCollection,
);

if (
!originalObjectMetadata.isCustom &&
!originalObjectMetadata.standardId
) {
if (!originalObjectMetadata.isCustom) {
updateObjectMetadataCollection.push({
id: originalObjectMetadata.id,
standardId: computedStandardObjectMetadata.standardId,
Expand All @@ -136,7 +133,7 @@ export class AddStandardIdCommand extends CommandRunner {
(field) => field.name === fieldMetadata.name && !field.isCustom,
);

if (!standardFieldMetadata || fieldMetadata.standardId) {
if (!standardFieldMetadata) {
continue;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<PartialObjectMetadata, 'standardId'> & {
Expand All @@ -24,19 +27,28 @@ 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: {},
});

// Foreign key
fields.push({
...rest,
standardId: createDeterministicUuid(data.standardId),
standardId: foreignKeyStandardId,
name: joinColumn,
type: FieldMetadataType.UUID,
label: `${data.label} ID (foreign key)`,
Expand Down
Original file line number Diff line number Diff line change
@@ -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]);
};

0 comments on commit a327a76

Please sign in to comment.