400 workflows webhooks trigger (#11041)
https://github.com/user-attachments/assets/dc0ece22-4d87-417f-b9e1-a11c3fd52ce8
This commit is contained in:
@ -190,6 +190,7 @@ describe('computeSchemaComponents', () => {
|
||||
'IMPORT',
|
||||
'MANUAL',
|
||||
'SYSTEM',
|
||||
'WEBHOOK',
|
||||
],
|
||||
},
|
||||
},
|
||||
@ -378,6 +379,7 @@ describe('computeSchemaComponents', () => {
|
||||
'IMPORT',
|
||||
'MANUAL',
|
||||
'SYSTEM',
|
||||
'WEBHOOK',
|
||||
],
|
||||
},
|
||||
},
|
||||
@ -565,6 +567,7 @@ describe('computeSchemaComponents', () => {
|
||||
'IMPORT',
|
||||
'MANUAL',
|
||||
'SYSTEM',
|
||||
'WEBHOOK',
|
||||
],
|
||||
},
|
||||
workspaceMemberId: {
|
||||
|
||||
@ -211,6 +211,7 @@ const getSchemaComponentsProperties = ({
|
||||
'IMPORT',
|
||||
'MANUAL',
|
||||
'SYSTEM',
|
||||
'WEBHOOK',
|
||||
],
|
||||
},
|
||||
...(forResponse
|
||||
|
||||
@ -0,0 +1,96 @@
|
||||
import { Controller, Get, Param, UseFilters } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared';
|
||||
|
||||
import { WorkflowTriggerWorkspaceService } from 'src/modules/workflow/workflow-trigger/workspace-services/workflow-trigger.workspace-service';
|
||||
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||
import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
|
||||
import { FieldActorSource } from 'src/engine/metadata-modules/field-metadata/composite-types/actor.composite-type';
|
||||
import { WorkflowTriggerRestApiExceptionFilter } from 'src/engine/core-modules/workflow/filters/workflow-trigger-rest-api-exception.filter';
|
||||
import {
|
||||
WorkflowTriggerException,
|
||||
WorkflowTriggerExceptionCode,
|
||||
} from 'src/modules/workflow/workflow-trigger/exceptions/workflow-trigger.exception';
|
||||
import { WorkflowTriggerType } from 'src/modules/workflow/workflow-trigger/types/workflow-trigger.type';
|
||||
import { WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity';
|
||||
|
||||
@Controller('webhooks')
|
||||
@UseFilters(WorkflowTriggerRestApiExceptionFilter)
|
||||
export class WorkflowTriggerController {
|
||||
constructor(
|
||||
private readonly twentyORMManager: TwentyORMManager,
|
||||
private readonly workflowTriggerWorkspaceService: WorkflowTriggerWorkspaceService,
|
||||
) {}
|
||||
|
||||
@Get('workflows/:workspaceId/:workflowId')
|
||||
async runWorkflow(
|
||||
@Param('workspaceId') workspaceId: string,
|
||||
@Param('workflowId') workflowId: string,
|
||||
) {
|
||||
const workflowRepository =
|
||||
await this.twentyORMManager.getRepository<WorkflowWorkspaceEntity>(
|
||||
'workflow',
|
||||
);
|
||||
|
||||
const workflow = await workflowRepository.findOne({
|
||||
where: { id: workflowId },
|
||||
});
|
||||
|
||||
if (!isDefined(workflow)) {
|
||||
throw new WorkflowTriggerException(
|
||||
'Workflow not found',
|
||||
WorkflowTriggerExceptionCode.NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!isDefined(workflow.lastPublishedVersionId) ||
|
||||
workflow.lastPublishedVersionId === ''
|
||||
) {
|
||||
throw new WorkflowTriggerException(
|
||||
'Workflow not activated',
|
||||
WorkflowTriggerExceptionCode.INVALID_WORKFLOW_STATUS,
|
||||
);
|
||||
}
|
||||
|
||||
const workflowVersionRepository =
|
||||
await this.twentyORMManager.getRepository<WorkflowVersionWorkspaceEntity>(
|
||||
'workflowVersion',
|
||||
);
|
||||
const workflowVersion = await workflowVersionRepository.findOne({
|
||||
where: { id: workflow.lastPublishedVersionId },
|
||||
});
|
||||
|
||||
if (!isDefined(workflowVersion)) {
|
||||
throw new WorkflowTriggerException(
|
||||
'Workflow version not found',
|
||||
WorkflowTriggerExceptionCode.INVALID_WORKFLOW_VERSION,
|
||||
);
|
||||
}
|
||||
|
||||
if (workflowVersion.trigger?.type !== WorkflowTriggerType.WEBHOOK) {
|
||||
throw new WorkflowTriggerException(
|
||||
'Workflow does not have a Webhook trigger',
|
||||
WorkflowTriggerExceptionCode.INVALID_WORKFLOW_TRIGGER,
|
||||
);
|
||||
}
|
||||
|
||||
const { workflowRunId } =
|
||||
await this.workflowTriggerWorkspaceService.runWorkflowVersion({
|
||||
workflowVersionId: workflow.lastPublishedVersionId,
|
||||
payload: {},
|
||||
createdBy: {
|
||||
source: FieldActorSource.WEBHOOK,
|
||||
workspaceMemberId: null,
|
||||
name: 'Webhook',
|
||||
context: {},
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
workflowName: workflow.name,
|
||||
success: true,
|
||||
workflowRunId,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,7 @@ import { Catch, ExceptionFilter } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
InternalServerError,
|
||||
NotFoundError,
|
||||
UserInputError,
|
||||
} from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
import {
|
||||
@ -19,8 +20,11 @@ export class WorkflowTriggerGraphqlApiExceptionFilter
|
||||
case WorkflowTriggerExceptionCode.INVALID_WORKFLOW_VERSION:
|
||||
case WorkflowTriggerExceptionCode.INVALID_ACTION_TYPE:
|
||||
case WorkflowTriggerExceptionCode.INVALID_WORKFLOW_TRIGGER:
|
||||
case WorkflowTriggerExceptionCode.INVALID_WORKFLOW_STATUS:
|
||||
case WorkflowTriggerExceptionCode.FORBIDDEN:
|
||||
throw new UserInputError(exception.message);
|
||||
case WorkflowTriggerExceptionCode.NOT_FOUND:
|
||||
throw new NotFoundError(exception.message);
|
||||
default:
|
||||
throw new InternalServerError(exception.message);
|
||||
}
|
||||
|
||||
@ -0,0 +1,54 @@
|
||||
import { ArgumentsHost, Catch, ExceptionFilter } from '@nestjs/common';
|
||||
|
||||
import { Response } from 'express';
|
||||
|
||||
import { HttpExceptionHandlerService } from 'src/engine/core-modules/exception-handler/http-exception-handler.service';
|
||||
import { CustomException } from 'src/utils/custom-exception';
|
||||
import {
|
||||
WorkflowTriggerException,
|
||||
WorkflowTriggerExceptionCode,
|
||||
} from 'src/modules/workflow/workflow-trigger/exceptions/workflow-trigger.exception';
|
||||
|
||||
@Catch()
|
||||
export class WorkflowTriggerRestApiExceptionFilter implements ExceptionFilter {
|
||||
constructor(
|
||||
private readonly httpExceptionHandlerService: HttpExceptionHandlerService,
|
||||
) {}
|
||||
|
||||
catch(exception: WorkflowTriggerException, host: ArgumentsHost) {
|
||||
const ctx = host.switchToHttp();
|
||||
const response = ctx.getResponse<Response>();
|
||||
|
||||
switch (exception.code) {
|
||||
case WorkflowTriggerExceptionCode.INVALID_INPUT:
|
||||
case WorkflowTriggerExceptionCode.INVALID_WORKFLOW_TRIGGER:
|
||||
case WorkflowTriggerExceptionCode.INVALID_WORKFLOW_VERSION:
|
||||
case WorkflowTriggerExceptionCode.INVALID_ACTION_TYPE:
|
||||
case WorkflowTriggerExceptionCode.INVALID_WORKFLOW_STATUS:
|
||||
return this.httpExceptionHandlerService.handleError(
|
||||
exception as CustomException,
|
||||
response,
|
||||
400,
|
||||
);
|
||||
case WorkflowTriggerExceptionCode.FORBIDDEN:
|
||||
return this.httpExceptionHandlerService.handleError(
|
||||
exception as CustomException,
|
||||
response,
|
||||
403,
|
||||
);
|
||||
case WorkflowTriggerExceptionCode.NOT_FOUND:
|
||||
return this.httpExceptionHandlerService.handleError(
|
||||
exception as CustomException,
|
||||
response,
|
||||
404,
|
||||
);
|
||||
case WorkflowTriggerExceptionCode.INTERNAL_ERROR:
|
||||
default:
|
||||
return this.httpExceptionHandlerService.handleError(
|
||||
exception as CustomException,
|
||||
response,
|
||||
500,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -10,6 +10,7 @@ import { AuthWorkspaceMemberId } from 'src/engine/decorators/auth/auth-workspace
|
||||
import { UserAuthGuard } from 'src/engine/guards/user-auth.guard';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { WorkflowTriggerWorkspaceService } from 'src/modules/workflow/workflow-trigger/workspace-services/workflow-trigger.workspace-service';
|
||||
import { buildCreatedByFromFullNameMetadata } from 'src/engine/core-modules/actor/utils/build-created-by-from-full-name-metadata.util';
|
||||
|
||||
@Resolver()
|
||||
@UseGuards(WorkspaceAuthGuard, UserAuthGuard)
|
||||
@ -43,11 +44,16 @@ export class WorkflowTriggerResolver {
|
||||
@AuthUser() user: User,
|
||||
@Args('input') { workflowVersionId, payload }: RunWorkflowVersionInput,
|
||||
) {
|
||||
return await this.workflowTriggerWorkspaceService.runWorkflowVersion(
|
||||
return await this.workflowTriggerWorkspaceService.runWorkflowVersion({
|
||||
workflowVersionId,
|
||||
payload ?? {},
|
||||
workspaceMemberId,
|
||||
user,
|
||||
);
|
||||
payload: payload ?? {},
|
||||
createdBy: buildCreatedByFromFullNameMetadata({
|
||||
fullNameMetadata: {
|
||||
firstName: user.firstName,
|
||||
lastName: user.lastName,
|
||||
},
|
||||
workspaceMemberId: workspaceMemberId,
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ import { WorkflowCommonModule } from 'src/modules/workflow/common/workflow-commo
|
||||
import { WorkflowBuilderModule } from 'src/modules/workflow/workflow-builder/workflow-builder.module';
|
||||
import { WorkflowVersionModule } from 'src/modules/workflow/workflow-builder/workflow-version/workflow-version.module';
|
||||
import { WorkflowTriggerModule } from 'src/modules/workflow/workflow-trigger/workflow-trigger.module';
|
||||
import { WorkflowTriggerController } from 'src/engine/core-modules/workflow/controllers/workflow-trigger.controller';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@ -16,6 +17,7 @@ import { WorkflowTriggerModule } from 'src/modules/workflow/workflow-trigger/wor
|
||||
WorkflowCommonModule,
|
||||
WorkflowVersionModule,
|
||||
],
|
||||
controllers: [WorkflowTriggerController],
|
||||
providers: [
|
||||
WorkflowTriggerResolver,
|
||||
WorkflowBuilderResolver,
|
||||
|
||||
@ -13,6 +13,7 @@ export enum FieldActorSource {
|
||||
IMPORT = 'IMPORT',
|
||||
MANUAL = 'MANUAL',
|
||||
SYSTEM = 'SYSTEM',
|
||||
WEBHOOK = 'WEBHOOK',
|
||||
}
|
||||
|
||||
export const actorCompositeType: CompositeType = {
|
||||
|
||||
@ -14,7 +14,8 @@ export class ScopedWorkspaceContextFactory {
|
||||
workspaceMetadataVersion: number | null;
|
||||
} {
|
||||
const workspaceId: string | undefined =
|
||||
this.request?.['req']?.['workspaceId'];
|
||||
this.request?.['req']?.['workspaceId'] ||
|
||||
this.request?.['params']?.['workspaceId'];
|
||||
const workspaceMetadataVersion: number | undefined =
|
||||
this.request?.['req']?.['workspaceMetadataVersion'];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user