Skip to content

Commit

Permalink
wip: Add workflowId filter to the test-definitions endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
burivuhster committed Nov 26, 2024
1 parent 75e2b6f commit 0b94403
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { DataSource, In, Repository } from '@n8n/typeorm';
import { Service } from 'typedi';

import { TestDefinition } from '@/databases/entities/test-definition.ee';
import { ForbiddenError } from '@/errors/response-errors/forbidden.error';
import type { ListQuery } from '@/requests';

@Service()
Expand All @@ -14,12 +15,21 @@ export class TestDefinitionRepository extends Repository<TestDefinition> {
async getMany(accessibleWorkflowIds: string[], options?: ListQuery.Options) {
if (accessibleWorkflowIds.length === 0) return { tests: [], count: 0 };

const where: FindOptionsWhere<TestDefinition> = {
...options?.filter,
workflow: {
const where: FindOptionsWhere<TestDefinition> = {};

if (options?.filter?.workflowId) {
if (!accessibleWorkflowIds.includes(options.filter.workflowId as string)) {
throw new ForbiddenError('User does not have access to the workflow');
}

where.workflow = {
id: options.filter.workflowId as string,
};
} else {
where.workflow = {
id: In(accessibleWorkflowIds),
},
};
};
}

const findManyOptions: FindManyOptions<TestDefinition> = {
where,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Expose } from 'class-transformer';
import { IsOptional, IsString } from 'class-validator';

import { BaseFilter } from './base.filter.dto';

export class TestDefinitionsFilter extends BaseFilter {
@IsString()
@IsOptional()
@Expose()
workflowId?: string;

static async fromString(rawFilter: string) {
return await this.toFilter(rawFilter, TestDefinitionsFilter);
}
}
3 changes: 3 additions & 0 deletions packages/cli/src/middlewares/list-query/filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as ResponseHelper from '@/response-helper';
import { toError } from '@/utils';

import { CredentialsFilter } from './dtos/credentials.filter.dto';
import { TestDefinitionsFilter } from './dtos/test-definitions.filter.dto';
import { UserFilter } from './dtos/user.filter.dto';
import { WorkflowFilter } from './dtos/workflow.filter.dto';

Expand All @@ -25,6 +26,8 @@ export const filterListQueryMiddleware = async (
Filter = CredentialsFilter;
} else if (req.baseUrl.endsWith('users')) {
Filter = UserFilter;
} else if (req.baseUrl.endsWith('test-definitions')) {
Filter = TestDefinitionsFilter;
} else {
return next();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import * as utils from './../shared/utils/';

let authOwnerAgent: SuperAgentTest;
let workflowUnderTest: WorkflowEntity;
let workflowUnderTest2: WorkflowEntity;
let evaluationWorkflow: WorkflowEntity;
let otherWorkflow: WorkflowEntity;
let ownerShell: User;
Expand All @@ -29,6 +30,7 @@ beforeEach(async () => {
await testDb.truncate(['TestDefinition', 'Workflow', 'AnnotationTag']);

workflowUnderTest = await createWorkflow({ name: 'workflow-under-test' }, ownerShell);
workflowUnderTest2 = await createWorkflow({ name: 'workflow-under-test-2' }, ownerShell);
evaluationWorkflow = await createWorkflow({ name: 'evaluation-workflow' }, ownerShell);
otherWorkflow = await createWorkflow({ name: 'other-workflow' });
annotationTag = (await createAnnotationTags(['test-tag']))[0];
Expand Down Expand Up @@ -90,6 +92,44 @@ describe('GET /evaluation/test-definitions', () => {
expect(resp.body.data.count).toBe(15);
expect(resp.body.data.testDefinitions).toHaveLength(5);
});

test('should retrieve test definitions list for a workflow', async () => {
// Add a bunch of test definitions for two different workflows
const testDefinitions = [];

for (let i = 0; i < 15; i++) {
const newTest = Container.get(TestDefinitionRepository).create({
name: `test-${i}`,
workflow: { id: workflowUnderTest.id },
});

const newTest2 = Container.get(TestDefinitionRepository).create({
name: `test-${i * 2}`,
workflow: { id: workflowUnderTest2.id },
});

testDefinitions.push(newTest, newTest2);
}

await Container.get(TestDefinitionRepository).save(testDefinitions);

// Fetch test definitions of a second workflow
let resp = await authOwnerAgent.get(
`/evaluation/test-definitions?filter=${JSON.stringify({ workflowId: workflowUnderTest2.id })}`,
);

expect(resp.statusCode).toBe(200);
expect(resp.body.data.count).toBe(15);
});

test('should return error if user has no access to the workflowId specified in filter', async () => {
let resp = await authOwnerAgent.get(
`/evaluation/test-definitions?filter=${JSON.stringify({ workflowId: otherWorkflow.id })}`,
);

expect(resp.statusCode).toBe(403);
expect(resp.body.message).toBe('User does not have access to the workflow');
});
});

describe('GET /evaluation/test-definitions/:id', () => {
Expand Down

0 comments on commit 0b94403

Please sign in to comment.