Multiple operations on webhooks (#7807)

fixes #7792 

WIP :)



https://github.com/user-attachments/assets/91f16744-c002-4f24-9cdd-cff79743cab1

---------

Co-authored-by: martmull <martmull@hotmail.fr>
This commit is contained in:
nitin
2024-10-23 21:27:46 +05:30
committed by GitHub
parent 165dd87264
commit 18778c55ac
16 changed files with 257 additions and 68 deletions

View File

@ -0,0 +1,56 @@
import { InjectRepository } from '@nestjs/typeorm';
import { Command } from 'nest-commander';
import { Repository } from 'typeorm';
import chalk from 'chalk';
import { ActiveWorkspacesCommandRunner } from 'src/database/commands/active-workspaces.command';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { BaseCommandOptions } from 'src/database/commands/base.command';
@Command({
name: 'upgrade-0.32:copy-webhook-operation-into-operations',
description:
'Read, transform and copy webhook from deprecated column operation into newly created column operations',
})
export class CopyWebhookOperationIntoOperationsCommand extends ActiveWorkspacesCommandRunner {
constructor(
@InjectRepository(Workspace, 'core')
protected readonly workspaceRepository: Repository<Workspace>,
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
) {
super(workspaceRepository);
}
async executeActiveWorkspacesCommand(
passedParams: string[],
options: BaseCommandOptions,
activeWorkspaceIds: string[],
): Promise<void> {
this.logger.log('Running command to copy operation to operations');
for (const workspaceId of activeWorkspaceIds) {
this.logger.log(`Running command for workspace ${workspaceId}`);
const webhookRepository =
await this.twentyORMGlobalManager.getRepositoryForWorkspace(
workspaceId,
'webhook',
);
const webhooks = await webhookRepository.find();
for (const webhook of webhooks) {
if ('operation' in webhook) {
await webhookRepository.update(webhook.id, {
operations: [webhook.operation],
});
this.logger.log(
chalk.yellow(`Copied webhook operation to operations`),
);
}
}
}
}
}

View File

@ -10,6 +10,7 @@ import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadat
import { SearchModule } from 'src/engine/metadata-modules/search/search.module';
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
import { WorkspaceSyncMetadataCommandsModule } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/workspace-sync-metadata-commands.module';
import { CopyWebhookOperationIntoOperationsCommand } from 'src/database/commands/upgrade-version/0-32/0-32-copy-webhook-operation-into-operations-command';
@Module({
imports: [
@ -25,6 +26,7 @@ import { WorkspaceSyncMetadataCommandsModule } from 'src/engine/workspace-manage
providers: [
UpgradeTo0_32Command,
EnforceUniqueConstraintsCommand,
CopyWebhookOperationIntoOperationsCommand,
SimplifySearchVectorExpressionCommand,
],
})

View File

@ -1,6 +1,6 @@
import { Logger } from '@nestjs/common';
import { Like } from 'typeorm';
import { ArrayContains } from 'typeorm';
import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface';
@ -54,10 +54,10 @@ export class CallWebhookJobsJob {
const webhooks = await webhookRepository.find({
where: [
{ operation: Like(`%${eventName}%`) },
{ operation: Like(`%*.${operation}%`) },
{ operation: Like(`%${nameSingular}.*%`) },
{ operation: Like('%*.*%') },
{ operations: ArrayContains([eventName]) },
{ operations: ArrayContains([`*.${operation}`]) },
{ operations: ArrayContains([`${nameSingular}.*`]) },
{ operations: ArrayContains(['*.*']) },
],
});
@ -80,12 +80,9 @@ export class CallWebhookJobsJob {
);
});
if (webhooks.length) {
webhooks.length > 0 &&
this.logger.log(
`CallWebhookJobsJob on eventName '${eventName}' called on webhooks ids [\n"${webhooks
.map((webhook) => webhook.id)
.join('",\n"')}"\n]`,
`CallWebhookJobsJob on eventName '${eventName}' triggered webhooks with ids [\n"${webhooks.map((webhook) => webhook.id).join('",\n"')}"\n]`,
);
}
}
}

View File

@ -189,3 +189,9 @@ export class FieldMetadataDefaultValuePhones {
@IsObject()
additionalPhones: object | null;
}
export class FieldMetadataDefaultArray {
@ValidateIf((_object, value) => value !== null)
@IsArray()
value: string[] | null;
}

View File

@ -1,5 +1,6 @@
import {
FieldMetadataDefaultActor,
FieldMetadataDefaultArray,
FieldMetadataDefaultValueAddress,
FieldMetadataDefaultValueBoolean,
FieldMetadataDefaultValueCurrency,
@ -48,6 +49,7 @@ type FieldMetadataDefaultValueMapping = {
[FieldMetadataType.RAW_JSON]: FieldMetadataDefaultValueRawJson;
[FieldMetadataType.RICH_TEXT]: FieldMetadataDefaultValueRichText;
[FieldMetadataType.ACTOR]: FieldMetadataDefaultActor;
[FieldMetadataType.ARRAY]: FieldMetadataDefaultArray;
};
export type FieldMetadataClassValidation =

View File

@ -400,6 +400,7 @@ export const VIEW_STANDARD_FIELD_IDS = {
export const WEBHOOK_STANDARD_FIELD_IDS = {
targetUrl: '20202020-1229-45a8-8cf4-85c9172aae12',
operation: '20202020-15b7-458e-bf30-74770a54410c',
operations: '20202020-15b7-458e-bf30-74770a54411c',
description: '20202020-15b7-458e-bf30-74770a54410d',
};

View File

@ -7,6 +7,7 @@ import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WEBHOOK_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
import { WorkspaceIsDeprecated } from 'src/engine/twenty-orm/decorators/workspace-is-deprecated.decorator';
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.webhook,
@ -36,8 +37,19 @@ export class WebhookWorkspaceEntity extends BaseWorkspaceEntity {
description: 'Webhook operation',
icon: 'IconCheckbox',
})
@WorkspaceIsDeprecated()
operation: string;
@WorkspaceField({
standardId: WEBHOOK_STANDARD_FIELD_IDS.operations,
type: FieldMetadataType.ARRAY,
label: 'Operations',
description: 'Webhook operations',
icon: 'IconCheckbox',
defaultValue: ['*.*'],
})
operations: string[];
@WorkspaceField({
standardId: WEBHOOK_STANDARD_FIELD_IDS.description,
type: FieldMetadataType.TEXT,