From 1bf6f66b44c9fd1b38a1bac2daa9a8cb4a0ecc29 Mon Sep 17 00:00:00 2001 From: Marc Littlemore Date: Tue, 17 Dec 2024 12:04:54 +0000 Subject: [PATCH 1/3] feat: Exclude pinned data from workflows --- packages/cli/src/public-api/types.ts | 3 +- .../workflows/spec/paths/workflows.id.yml | 6 ++ .../workflows/spec/paths/workflows.yml | 6 ++ .../handlers/workflows/workflows.handler.ts | 21 ++++++- .../integration/public-api/workflows.test.ts | 61 +++++++++++++++++++ 5 files changed, 95 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/public-api/types.ts b/packages/cli/src/public-api/types.ts index 327d3630739b1..b10d2f81bda8b 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 37cad74c86e4d..546898ea1422e 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,12 @@ get: summary: Retrieves a workflow description: Retrieves a workflow. parameters: + - name: excludePinnedData + in: query + required: false + 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 1024e36cb5948..cfc6bc67a95fe 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,12 @@ get: schema: type: string example: VmwOO9HeTEj20kxM + - name: excludePinnedData + in: query + required: false + 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 b0956a15c1bd4..7a9003dc284c6 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 5425455aca790..28f9d444daa27 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', () => { From 21496a5eeaac47c2fb524f80c69db13d07bf7421 Mon Sep 17 00:00:00 2001 From: Marc Littlemore Date: Tue, 17 Dec 2024 12:20:20 +0000 Subject: [PATCH 2/3] chore: add description to workflow openAPI specs --- .../public-api/v1/handlers/workflows/spec/paths/workflows.id.yml | 1 + .../public-api/v1/handlers/workflows/spec/paths/workflows.yml | 1 + 2 files changed, 2 insertions(+) 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 546898ea1422e..c8b2bf51cdc29 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 @@ -9,6 +9,7 @@ get: - name: excludePinnedData in: query required: false + description: Set this to avoid retrieving pinned data schema: type: boolean example: true 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 cfc6bc67a95fe..4b3bc5e069efd 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 @@ -63,6 +63,7 @@ get: - name: excludePinnedData in: query required: false + description: Set this to avoid retrieving pinned data schema: type: boolean example: true From 6479520e673b8161fe6df68c522fb0f306b16e68 Mon Sep 17 00:00:00 2001 From: Marc Littlemore Date: Tue, 17 Dec 2024 13:40:18 +0000 Subject: [PATCH 3/3] fix: ensure pinData is optional if we want to delete it in API response to make TS happy --- packages/cli/src/databases/entities/workflow-entity.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/databases/entities/workflow-entity.ts b/packages/cli/src/databases/entities/workflow-entity.ts index b03cf2c28d9cb..67d0f0e345cc3 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;