mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-14 16:44:07 -08:00
wip: evaluation/tests endpoint CRUD
This commit is contained in:
parent
961d42fd51
commit
de4d486223
|
@ -1,4 +1,4 @@
|
|||
import type { FindManyOptions, FindOptionsSelect, FindOptionsWhere } from '@n8n/typeorm';
|
||||
import type { FindManyOptions, FindOptionsWhere } from '@n8n/typeorm';
|
||||
import { DataSource, In, Repository } from '@n8n/typeorm';
|
||||
import { Service } from 'typedi';
|
||||
|
||||
|
@ -21,32 +21,12 @@ export class TestRepository extends Repository<TestEntity> {
|
|||
},
|
||||
};
|
||||
|
||||
type Select = FindOptionsSelect<TestEntity>;
|
||||
|
||||
const select: Select = {
|
||||
id: true,
|
||||
name: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
};
|
||||
|
||||
const relations: string[] = ['workflow', 'evaluationWorkflow', 'annotationTag'];
|
||||
|
||||
const isDefaultSelect = options?.select === undefined;
|
||||
|
||||
const findManyOptions: FindManyOptions<TestEntity> = {
|
||||
select: { ...select, id: true },
|
||||
where,
|
||||
relations: ['annotationTag'],
|
||||
order: { createdAt: 'DESC' },
|
||||
};
|
||||
|
||||
if (isDefaultSelect || options?.select?.updatedAt === true) {
|
||||
findManyOptions.order = { updatedAt: 'ASC' };
|
||||
}
|
||||
|
||||
if (relations.length > 0) {
|
||||
findManyOptions.relations = relations;
|
||||
}
|
||||
|
||||
if (options?.take) {
|
||||
findManyOptions.skip = options.skip;
|
||||
findManyOptions.take = options.take;
|
||||
|
@ -56,4 +36,25 @@ export class TestRepository extends Repository<TestEntity> {
|
|||
|
||||
return { tests, count };
|
||||
}
|
||||
|
||||
async getOne(id: number, sharedWorkflowIds: string[]) {
|
||||
return await this.findOne({
|
||||
where: {
|
||||
id,
|
||||
workflow: {
|
||||
id: In(sharedWorkflowIds),
|
||||
},
|
||||
},
|
||||
relations: ['annotationTag'],
|
||||
});
|
||||
}
|
||||
|
||||
async deleteById(id: number, sharedWorkflowIds: string[]) {
|
||||
return await this.delete({
|
||||
id,
|
||||
workflow: {
|
||||
id: In(sharedWorkflowIds),
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
import { Get, /*Patch, Post,*/ RestController } from '@/decorators';
|
||||
import { Get, Post, Patch, RestController, Delete } from '@/decorators';
|
||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||
import { listQueryMiddleware } from '@/middlewares';
|
||||
import { getSharedWorkflowIds } from '@/public-api/v1/handlers/workflows/workflows.service';
|
||||
import { isPositiveInteger } from '@/utils';
|
||||
|
||||
import { TestsService } from './tests.service';
|
||||
import { TestsRequest } from './tests.types';
|
||||
|
@ -8,62 +12,61 @@ import { TestsRequest } from './tests.types';
|
|||
export class TestsController {
|
||||
constructor(private readonly testsService: TestsService) {}
|
||||
|
||||
// private async getAccessibleWorkflowIds(user: User, scope: Scope) {
|
||||
// if (this.license.isSharingEnabled()) {
|
||||
// return await this.workflowSharingService.getSharedWorkflowIds(user, { scopes: [scope] });
|
||||
// } else {
|
||||
// return await this.workflowSharingService.getSharedWorkflowIds(user, {
|
||||
// workflowRoles: ['workflow:owner'],
|
||||
// projectRoles: ['project:personalOwner'],
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
@Get('/', { middlewares: listQueryMiddleware })
|
||||
async getMany(req: TestsRequest.GetMany) {
|
||||
return await this.testsService.getMany(req.user, req.listQueryOptions);
|
||||
const workflowIds = await getSharedWorkflowIds(req.user, ['workflow:read']);
|
||||
|
||||
return await this.testsService.getMany(req.user, req.listQueryOptions, workflowIds);
|
||||
}
|
||||
|
||||
// @Get('/:id')
|
||||
// async getOne(req: ExecutionRequest.GetOne) {
|
||||
// if (!isPositiveInteger(req.params.id)) {
|
||||
// throw new BadRequestError('Execution ID is not a number');
|
||||
// }
|
||||
//
|
||||
// const workflowIds = await this.getAccessibleWorkflowIds(req.user, 'workflow:read');
|
||||
//
|
||||
// if (workflowIds.length === 0) throw new NotFoundError('Execution not found');
|
||||
//
|
||||
// return this.license.isSharingEnabled()
|
||||
// ? await this.enterpriseExecutionService.findOne(req, workflowIds)
|
||||
// : await this.executionService.findOne(req, workflowIds);
|
||||
// }
|
||||
//
|
||||
// @Post('/delete')
|
||||
// async delete(req: ExecutionRequest.Delete) {
|
||||
// const workflowIds = await this.getAccessibleWorkflowIds(req.user, 'workflow:execute');
|
||||
//
|
||||
// if (workflowIds.length === 0) throw new NotFoundError('Execution not found');
|
||||
//
|
||||
// return await this.executionService.delete(req, workflowIds);
|
||||
// }
|
||||
//
|
||||
// @Patch('/:id')
|
||||
// async update(req: ExecutionRequest.Update) {
|
||||
// if (!isPositiveInteger(req.params.id)) {
|
||||
// throw new BadRequestError('Execution ID is not a number');
|
||||
// }
|
||||
//
|
||||
// const workflowIds = await this.getAccessibleWorkflowIds(req.user, 'workflow:read');
|
||||
//
|
||||
// // Fail fast if no workflows are accessible
|
||||
// if (workflowIds.length === 0) throw new NotFoundError('Execution not found');
|
||||
//
|
||||
// const { body: payload } = req;
|
||||
// const validatedPayload = validateExecutionUpdatePayload(payload);
|
||||
//
|
||||
// await this.executionService.annotate(req.params.id, validatedPayload, workflowIds);
|
||||
//
|
||||
// return await this.executionService.findOne(req, workflowIds);
|
||||
// }
|
||||
@Get('/:id')
|
||||
async getOne(req: TestsRequest.GetOne) {
|
||||
if (!isPositiveInteger(req.params.id)) {
|
||||
throw new BadRequestError('Test ID is not a number');
|
||||
}
|
||||
|
||||
const workflowIds = await getSharedWorkflowIds(req.user, ['workflow:read']);
|
||||
|
||||
return await this.testsService.findOne(Number(req.params.id), workflowIds);
|
||||
}
|
||||
|
||||
@Post('/')
|
||||
async create(req: TestsRequest.Create) {
|
||||
const workflowIds = await getSharedWorkflowIds(req.user, ['workflow:read']);
|
||||
|
||||
if (!workflowIds.includes(req.body.workflowId)) {
|
||||
throw new BadRequestError('User does not have access to the workflow');
|
||||
}
|
||||
|
||||
return await this.testsService.save(this.testsService.toEntity(req.body));
|
||||
}
|
||||
|
||||
@Delete('/:id')
|
||||
async delete(req: TestsRequest.Delete) {
|
||||
if (!isPositiveInteger(req.params.id)) {
|
||||
throw new BadRequestError('Test ID is not a number');
|
||||
}
|
||||
|
||||
const workflowIds = await getSharedWorkflowIds(req.user, ['workflow:read']);
|
||||
|
||||
if (workflowIds.length === 0) throw new NotFoundError('Test not found');
|
||||
|
||||
return await this.testsService.delete(Number(req.params.id), workflowIds);
|
||||
}
|
||||
|
||||
@Patch('/:id')
|
||||
async update(req: TestsRequest.Update) {
|
||||
if (!isPositiveInteger(req.params.id)) {
|
||||
throw new BadRequestError('Test ID is not a number');
|
||||
}
|
||||
|
||||
const workflowIds = await getSharedWorkflowIds(req.user, ['workflow:read']);
|
||||
|
||||
// Fail fast if no workflows are accessible
|
||||
if (workflowIds.length === 0) throw new NotFoundError('Workflow not found');
|
||||
|
||||
return await this.testsService.save(
|
||||
this.testsService.toEntity({ ...req.body, id: Number(req.params.id) }),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,11 +14,38 @@ export class TestsService {
|
|||
private readonly workflowSharingService: WorkflowSharingService,
|
||||
) {}
|
||||
|
||||
// toEntity(attrs: { name: string; id?: string }) {
|
||||
// attrs.name = attrs.name.trim();
|
||||
//
|
||||
// return this.testRepository.create(attrs);
|
||||
// }
|
||||
toEntity(attrs: {
|
||||
name?: string;
|
||||
workflowId?: string;
|
||||
evaluationWorkflowId?: string;
|
||||
id?: number;
|
||||
}) {
|
||||
const entity = {
|
||||
name: attrs.name?.trim(),
|
||||
};
|
||||
|
||||
if (attrs.id) {
|
||||
entity.id = attrs.id;
|
||||
}
|
||||
|
||||
if (attrs.workflowId) {
|
||||
entity.workflow = {
|
||||
id: attrs.workflowId,
|
||||
};
|
||||
}
|
||||
|
||||
if (attrs.evaluationWorkflowId) {
|
||||
entity.evaluationWorkflow = {
|
||||
id: attrs.evaluationWorkflowId,
|
||||
};
|
||||
}
|
||||
|
||||
return this.testRepository.create(entity);
|
||||
}
|
||||
|
||||
async findOne(id: number, accessibleWorkflowIds: string[]) {
|
||||
return await this.testRepository.getOne(id, accessibleWorkflowIds);
|
||||
}
|
||||
|
||||
async save(test: TestEntity) {
|
||||
await validateEntity(test);
|
||||
|
@ -26,15 +53,11 @@ export class TestsService {
|
|||
return await this.testRepository.save(test);
|
||||
}
|
||||
|
||||
async delete(id: string) {
|
||||
return await this.testRepository.delete(id);
|
||||
async delete(id: number, accessibleWorkflowIds: string[]) {
|
||||
return await this.testRepository.deleteById(id, accessibleWorkflowIds);
|
||||
}
|
||||
|
||||
async getMany(user: User, options: ListQuery.Options) {
|
||||
const sharedWorkflowIds = await this.workflowSharingService.getSharedWorkflowIds(user, {
|
||||
scopes: ['workflow:read'],
|
||||
});
|
||||
|
||||
return await this.testRepository.getMany(sharedWorkflowIds, options);
|
||||
async getMany(user: User, options: ListQuery.Options, accessibleWorkflowIds: string[] = []) {
|
||||
return await this.testRepository.getMany(accessibleWorkflowIds, options);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import type { TestEntity } from '@/databases/entities/test-entity';
|
||||
import type { AuthenticatedRequest, ListQuery } from '@/requests';
|
||||
|
||||
// ----------------------------------
|
||||
|
@ -8,7 +7,7 @@ import type { AuthenticatedRequest, ListQuery } from '@/requests';
|
|||
export declare namespace TestsRequest {
|
||||
namespace RouteParams {
|
||||
type TestId = {
|
||||
id: TestEntity['id'];
|
||||
id: string;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue