Fix webhook issue (#6711)
Fix [#web](https://github.com/orgs/twentyhq/projects/1/views/3?pane=issue&itemId=75329194) This PR does 2 things: - migrate webhooks to TwentyORM - Fix inversion between objectNameSingular and operation in webhook eventName. It is stored as {objectNameSingular}.{operation} and we were querying {operation}.{objectNameSingular}
This commit is contained in:
@ -45,4 +45,4 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"extends": "../../tsconfig.base.json"
|
"extends": "../../tsconfig.base.json"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +1,20 @@
|
|||||||
import { Logger } from '@nestjs/common';
|
import { Logger } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { Like } from 'typeorm';
|
||||||
|
|
||||||
import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface';
|
import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface';
|
||||||
|
|
||||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
|
||||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
|
||||||
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
|
||||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
|
||||||
import {
|
import {
|
||||||
CallWebhookJob,
|
CallWebhookJob,
|
||||||
CallWebhookJobData,
|
CallWebhookJobData,
|
||||||
} from 'src/engine/api/graphql/workspace-query-runner/jobs/call-webhook.job';
|
} from 'src/engine/api/graphql/workspace-query-runner/jobs/call-webhook.job';
|
||||||
import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator';
|
import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator';
|
||||||
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
|
||||||
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
|
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
|
||||||
|
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
||||||
|
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||||
|
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
||||||
|
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||||
|
import { WebhookWorkspaceEntity } from 'src/modules/webhook/standard-objects/webhook.workspace-entity';
|
||||||
|
|
||||||
export enum CallWebhookJobsJobOperation {
|
export enum CallWebhookJobsJobOperation {
|
||||||
create = 'create',
|
create = 'create',
|
||||||
@ -32,42 +34,38 @@ export class CallWebhookJobsJob {
|
|||||||
private readonly logger = new Logger(CallWebhookJobsJob.name);
|
private readonly logger = new Logger(CallWebhookJobsJob.name);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
|
||||||
private readonly dataSourceService: DataSourceService,
|
|
||||||
@InjectMessageQueue(MessageQueue.webhookQueue)
|
@InjectMessageQueue(MessageQueue.webhookQueue)
|
||||||
private readonly messageQueueService: MessageQueueService,
|
private readonly messageQueueService: MessageQueueService,
|
||||||
|
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Process(CallWebhookJobsJob.name)
|
@Process(CallWebhookJobsJob.name)
|
||||||
async handle(data: CallWebhookJobsJobData): Promise<void> {
|
async handle(data: CallWebhookJobsJobData): Promise<void> {
|
||||||
const dataSourceMetadata =
|
const webhookRepository =
|
||||||
await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceIdOrFail(
|
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WebhookWorkspaceEntity>(
|
||||||
data.workspaceId,
|
|
||||||
);
|
|
||||||
const workspaceDataSource =
|
|
||||||
await this.workspaceDataSourceService.connectToWorkspaceDataSource(
|
|
||||||
data.workspaceId,
|
data.workspaceId,
|
||||||
|
'webhook',
|
||||||
);
|
);
|
||||||
|
|
||||||
const nameSingular = data.objectMetadataItem.nameSingular;
|
const nameSingular = data.objectMetadataItem.nameSingular;
|
||||||
const operation = data.operation;
|
const operation = data.operation;
|
||||||
const eventType = `${operation}.${nameSingular}`;
|
const eventName = `${nameSingular}.${operation}`;
|
||||||
const webhooks: { id: string; targetUrl: string }[] =
|
|
||||||
await workspaceDataSource?.query(
|
const webhooks = await webhookRepository.find({
|
||||||
`
|
where: [
|
||||||
SELECT * FROM ${dataSourceMetadata.schema}."webhook"
|
{ operation: Like(`%${eventName}%`) },
|
||||||
WHERE operation LIKE '%${eventType}%'
|
{ operation: Like(`%*.${operation}%`) },
|
||||||
OR operation LIKE '%*.${nameSingular}%'
|
{ operation: Like(`%${nameSingular}.*%`) },
|
||||||
OR operation LIKE '%${operation}.*%'
|
{ operation: Like('%*.*%') },
|
||||||
OR operation LIKE '%*.*%'
|
],
|
||||||
`,
|
});
|
||||||
);
|
|
||||||
|
|
||||||
webhooks.forEach((webhook) => {
|
webhooks.forEach((webhook) => {
|
||||||
this.messageQueueService.add<CallWebhookJobData>(
|
this.messageQueueService.add<CallWebhookJobData>(
|
||||||
CallWebhookJob.name,
|
CallWebhookJob.name,
|
||||||
{
|
{
|
||||||
targetUrl: webhook.targetUrl,
|
targetUrl: webhook.targetUrl,
|
||||||
eventType,
|
eventName,
|
||||||
objectMetadata: {
|
objectMetadata: {
|
||||||
id: data.objectMetadataItem.id,
|
id: data.objectMetadataItem.id,
|
||||||
nameSingular: data.objectMetadataItem.nameSingular,
|
nameSingular: data.objectMetadataItem.nameSingular,
|
||||||
@ -83,7 +81,7 @@ export class CallWebhookJobsJob {
|
|||||||
|
|
||||||
if (webhooks.length) {
|
if (webhooks.length) {
|
||||||
this.logger.log(
|
this.logger.log(
|
||||||
`CallWebhookJobsJob on eventType '${eventType}' called on webhooks ids [\n"${webhooks
|
`CallWebhookJobsJob on eventName '${event}' called on webhooks ids [\n"${webhooks
|
||||||
.map((webhook) => webhook.id)
|
.map((webhook) => webhook.id)
|
||||||
.join('",\n"')}"\n]`,
|
.join('",\n"')}"\n]`,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
import { Logger } from '@nestjs/common';
|
|
||||||
import { HttpService } from '@nestjs/axios';
|
import { HttpService } from '@nestjs/axios';
|
||||||
|
import { Logger } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
|
||||||
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
||||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||||
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
|
|
||||||
|
|
||||||
export type CallWebhookJobData = {
|
export type CallWebhookJobData = {
|
||||||
targetUrl: string;
|
targetUrl: string;
|
||||||
eventType: string;
|
eventName: string;
|
||||||
objectMetadata: { id: string; nameSingular: string };
|
objectMetadata: { id: string; nameSingular: string };
|
||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
webhookId: string;
|
webhookId: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user