feat(API): Exclude pinned data from workflows (#12261)

This commit is contained in:
Marc Littlemore
2024-12-19 08:13:17 +00:00
committed by GitHub
parent 878b41904d
commit e0dc385f8b
6 changed files with 98 additions and 3 deletions

View File

@@ -80,7 +80,7 @@ export class WorkflowEntity extends WithTimestampsAndStringId implements IWorkfl
nullable: true, nullable: true,
transformer: sqlite.jsonColumn, transformer: sqlite.jsonColumn,
}) })
pinData: ISimplifiedPinData; pinData?: ISimplifiedPinData;
@Column({ length: 36 }) @Column({ length: 36 })
versionId: string; versionId: string;

View File

@@ -74,11 +74,12 @@ export declare namespace WorkflowRequest {
active: boolean; active: boolean;
name?: string; name?: string;
projectId?: string; projectId?: string;
excludePinnedData?: boolean;
} }
>; >;
type Create = AuthenticatedRequest<{}, {}, WorkflowEntity, {}>; type Create = AuthenticatedRequest<{}, {}, WorkflowEntity, {}>;
type Get = AuthenticatedRequest<{ id: string }, {}, {}, {}>; type Get = AuthenticatedRequest<{ id: string }, {}, {}, { excludePinnedData?: boolean }>;
type Delete = Get; type Delete = Get;
type Update = AuthenticatedRequest<{ id: string }, {}, WorkflowEntity, {}>; type Update = AuthenticatedRequest<{ id: string }, {}, WorkflowEntity, {}>;
type Activate = Get; type Activate = Get;

View File

@@ -6,6 +6,13 @@ get:
summary: Retrieves a workflow summary: Retrieves a workflow
description: Retrieves a workflow. description: Retrieves a workflow.
parameters: 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' - $ref: '../schemas/parameters/workflowId.yml'
responses: responses:
'200': '200':

View File

@@ -60,6 +60,13 @@ get:
schema: schema:
type: string type: string
example: VmwOO9HeTEj20kxM 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/limit.yml'
- $ref: '../../../../shared/spec/parameters/cursor.yml' - $ref: '../../../../shared/spec/parameters/cursor.yml'
responses: responses:

View File

@@ -105,6 +105,7 @@ export = {
projectScope('workflow:read', 'workflow'), projectScope('workflow:read', 'workflow'),
async (req: WorkflowRequest.Get, res: express.Response): Promise<express.Response> => { async (req: WorkflowRequest.Get, res: express.Response): Promise<express.Response> => {
const { id } = req.params; const { id } = req.params;
const { excludePinnedData = false } = req.query;
const workflow = await Container.get(SharedWorkflowRepository).findWorkflowForUser( const workflow = await Container.get(SharedWorkflowRepository).findWorkflowForUser(
id, id,
@@ -120,6 +121,10 @@ export = {
return res.status(404).json({ message: 'Not Found' }); return res.status(404).json({ message: 'Not Found' });
} }
if (excludePinnedData) {
delete workflow.pinData;
}
Container.get(EventService).emit('user-retrieved-workflow', { Container.get(EventService).emit('user-retrieved-workflow', {
userId: req.user.id, userId: req.user.id,
publicApi: true, publicApi: true,
@@ -131,7 +136,15 @@ export = {
getWorkflows: [ getWorkflows: [
validCursor, validCursor,
async (req: WorkflowRequest.GetAll, res: express.Response): Promise<express.Response> => { async (req: WorkflowRequest.GetAll, res: express.Response): Promise<express.Response> => {
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<WorkflowEntity> = { const where: FindOptionsWhere<WorkflowEntity> = {
...(active !== undefined && { active }), ...(active !== undefined && { active }),
@@ -199,6 +212,12 @@ export = {
...(!config.getEnv('workflowTagsDisabled') && { relations: ['tags'] }), ...(!config.getEnv('workflowTagsDisabled') && { relations: ['tags'] }),
}); });
if (excludePinnedData) {
workflows.forEach((workflow) => {
delete workflow.pinData;
});
}
Container.get(EventService).emit('user-retrieved-all-workflows', { Container.get(EventService).emit('user-retrieved-all-workflows', {
userId: req.user.id, userId: req.user.id,
publicApi: true, publicApi: true,

View File

@@ -378,6 +378,47 @@ describe('GET /workflows', () => {
expect(updatedAt).toBeDefined(); 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', () => { describe('GET /workflows/:id', () => {
@@ -444,6 +485,26 @@ describe('GET /workflows/:id', () => {
expect(createdAt).toEqual(workflow.createdAt.toISOString()); expect(createdAt).toEqual(workflow.createdAt.toISOString());
expect(updatedAt).toEqual(workflow.updatedAt.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', () => { describe('DELETE /workflows/:id', () => {