From e0dc385f8bc8ee13fbc5bbf35e07654e52b193e9 Mon Sep 17 00:00:00 2001 From: Marc Littlemore Date: Thu, 19 Dec 2024 08:13:17 +0000 Subject: [PATCH] feat(API): Exclude pinned data from workflows (#12261) --- .../src/databases/entities/workflow-entity.ts | 2 +- packages/cli/src/public-api/types.ts | 3 +- .../workflows/spec/paths/workflows.id.yml | 7 +++ .../workflows/spec/paths/workflows.yml | 7 +++ .../handlers/workflows/workflows.handler.ts | 21 ++++++- .../integration/public-api/workflows.test.ts | 61 +++++++++++++++++++ 6 files changed, 98 insertions(+), 3 deletions(-) diff --git a/packages/cli/src/databases/entities/workflow-entity.ts b/packages/cli/src/databases/entities/workflow-entity.ts index b03cf2c28d..67d0f0e345 100644 --- a/packages/cli/src/databases/entities/workflow-entity.ts +++ b/packages/cli/src/databases/entities/workflow-entity.ts @@ -80,7 +80,7 @@ export class WorkflowEntity extends WithTimestampsAndStringId implements IWorkfl nullable: true, transformer: sqlite.jsonColumn, }) - pinData: ISimplifiedPinData; + pinData?: ISimplifiedPinData; @Column({ length: 36 }) versionId: string; diff --git a/packages/cli/src/public-api/types.ts b/packages/cli/src/public-api/types.ts index 327d363073..b10d2f81bd 100644 --- a/packages/cli/src/public-api/types.ts +++ b/packages/cli/src/public-api/types.ts @@ -74,11 +74,12 @@ export declare namespace WorkflowRequest { active: boolean; name?: string; projectId?: string; + excludePinnedData?: boolean; } >; type Create = AuthenticatedRequest<{}, {}, WorkflowEntity, {}>; - type Get = AuthenticatedRequest<{ id: string }, {}, {}, {}>; + type Get = AuthenticatedRequest<{ id: string }, {}, {}, { excludePinnedData?: boolean }>; type Delete = Get; type Update = AuthenticatedRequest<{ id: string }, {}, WorkflowEntity, {}>; type Activate = Get; diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/workflows.id.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/workflows.id.yml index 37cad74c86..c8b2bf51cd 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/workflows.id.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/workflows.id.yml @@ -6,6 +6,13 @@ get: summary: Retrieves a workflow description: Retrieves a workflow. parameters: + - name: excludePinnedData + in: query + required: false + description: Set this to avoid retrieving pinned data + schema: + type: boolean + example: true - $ref: '../schemas/parameters/workflowId.yml' responses: '200': diff --git a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/workflows.yml b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/workflows.yml index 1024e36cb5..4b3bc5e069 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/workflows.yml +++ b/packages/cli/src/public-api/v1/handlers/workflows/spec/paths/workflows.yml @@ -60,6 +60,13 @@ get: schema: type: string example: VmwOO9HeTEj20kxM + - name: excludePinnedData + in: query + required: false + description: Set this to avoid retrieving pinned data + schema: + type: boolean + example: true - $ref: '../../../../shared/spec/parameters/limit.yml' - $ref: '../../../../shared/spec/parameters/cursor.yml' responses: diff --git a/packages/cli/src/public-api/v1/handlers/workflows/workflows.handler.ts b/packages/cli/src/public-api/v1/handlers/workflows/workflows.handler.ts index b0956a15c1..7a9003dc28 100644 --- a/packages/cli/src/public-api/v1/handlers/workflows/workflows.handler.ts +++ b/packages/cli/src/public-api/v1/handlers/workflows/workflows.handler.ts @@ -105,6 +105,7 @@ export = { projectScope('workflow:read', 'workflow'), async (req: WorkflowRequest.Get, res: express.Response): Promise => { const { id } = req.params; + const { excludePinnedData = false } = req.query; const workflow = await Container.get(SharedWorkflowRepository).findWorkflowForUser( id, @@ -120,6 +121,10 @@ export = { return res.status(404).json({ message: 'Not Found' }); } + if (excludePinnedData) { + delete workflow.pinData; + } + Container.get(EventService).emit('user-retrieved-workflow', { userId: req.user.id, publicApi: true, @@ -131,7 +136,15 @@ export = { getWorkflows: [ validCursor, async (req: WorkflowRequest.GetAll, res: express.Response): Promise => { - const { offset = 0, limit = 100, active, tags, name, projectId } = req.query; + const { + offset = 0, + limit = 100, + excludePinnedData = false, + active, + tags, + name, + projectId, + } = req.query; const where: FindOptionsWhere = { ...(active !== undefined && { active }), @@ -199,6 +212,12 @@ export = { ...(!config.getEnv('workflowTagsDisabled') && { relations: ['tags'] }), }); + if (excludePinnedData) { + workflows.forEach((workflow) => { + delete workflow.pinData; + }); + } + Container.get(EventService).emit('user-retrieved-all-workflows', { userId: req.user.id, publicApi: true, diff --git a/packages/cli/test/integration/public-api/workflows.test.ts b/packages/cli/test/integration/public-api/workflows.test.ts index 5425455aca..28f9d444da 100644 --- a/packages/cli/test/integration/public-api/workflows.test.ts +++ b/packages/cli/test/integration/public-api/workflows.test.ts @@ -378,6 +378,47 @@ describe('GET /workflows', () => { expect(updatedAt).toBeDefined(); } }); + + test('should return all owned workflows without pinned data', async () => { + await Promise.all([ + createWorkflow( + { + pinData: { + Webhook1: [{ json: { first: 'first' } }], + }, + }, + member, + ), + createWorkflow( + { + pinData: { + Webhook2: [{ json: { second: 'second' } }], + }, + }, + member, + ), + createWorkflow( + { + pinData: { + Webhook3: [{ json: { third: 'third' } }], + }, + }, + member, + ), + ]); + + const response = await authMemberAgent.get('/workflows?excludePinnedData=true'); + + expect(response.statusCode).toBe(200); + expect(response.body.data.length).toBe(3); + expect(response.body.nextCursor).toBeNull(); + + for (const workflow of response.body.data) { + const { pinData } = workflow; + + expect(pinData).not.toBeDefined(); + } + }); }); describe('GET /workflows/:id', () => { @@ -444,6 +485,26 @@ describe('GET /workflows/:id', () => { expect(createdAt).toEqual(workflow.createdAt.toISOString()); expect(updatedAt).toEqual(workflow.updatedAt.toISOString()); }); + + test('should retrieve workflow without pinned data', async () => { + // create and assign workflow to owner + const workflow = await createWorkflow( + { + pinData: { + Webhook1: [{ json: { first: 'first' } }], + }, + }, + member, + ); + + const response = await authMemberAgent.get(`/workflows/${workflow.id}?excludePinnedData=true`); + + expect(response.statusCode).toBe(200); + + const { pinData } = response.body; + + expect(pinData).not.toBeDefined(); + }); }); describe('DELETE /workflows/:id', () => {