mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 20:24:05 -08:00
feat(core): Filter executions by project ID in internal API (#10976)
This commit is contained in:
parent
5a99e93f8d
commit
06d749ffa7
|
@ -54,6 +54,8 @@ import { ExecutionDataRepository } from './execution-data.repository';
|
||||||
import type { ExecutionData } from '../entities/execution-data';
|
import type { ExecutionData } from '../entities/execution-data';
|
||||||
import { ExecutionEntity } from '../entities/execution-entity';
|
import { ExecutionEntity } from '../entities/execution-entity';
|
||||||
import { ExecutionMetadata } from '../entities/execution-metadata';
|
import { ExecutionMetadata } from '../entities/execution-metadata';
|
||||||
|
import { SharedWorkflow } from '../entities/shared-workflow';
|
||||||
|
import { WorkflowEntity } from '../entities/workflow-entity';
|
||||||
|
|
||||||
export interface IGetExecutionsQueryFilter {
|
export interface IGetExecutionsQueryFilter {
|
||||||
id?: FindOperator<string> | string;
|
id?: FindOperator<string> | string;
|
||||||
|
@ -874,6 +876,7 @@ export class ExecutionRepository extends Repository<ExecutionEntity> {
|
||||||
metadata,
|
metadata,
|
||||||
annotationTags,
|
annotationTags,
|
||||||
vote,
|
vote,
|
||||||
|
projectId,
|
||||||
} = query;
|
} = query;
|
||||||
|
|
||||||
const fields = Object.keys(this.summaryFields)
|
const fields = Object.keys(this.summaryFields)
|
||||||
|
@ -945,6 +948,12 @@ export class ExecutionRepository extends Repository<ExecutionEntity> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (projectId) {
|
||||||
|
qb.innerJoin(WorkflowEntity, 'w', 'w.id = execution.workflowId')
|
||||||
|
.innerJoin(SharedWorkflow, 'sw', 'sw.workflowId = w.id')
|
||||||
|
.where('sw.projectId = :projectId', { projectId });
|
||||||
|
}
|
||||||
|
|
||||||
return qb;
|
return qb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,7 @@ export namespace ExecutionSummaries {
|
||||||
startedBefore: string;
|
startedBefore: string;
|
||||||
annotationTags: string[]; // tag IDs
|
annotationTags: string[]; // tag IDs
|
||||||
vote: AnnotationVote;
|
vote: AnnotationVote;
|
||||||
|
projectId: string;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
type AccessFields = {
|
type AccessFields = {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { ExecutionRepository } from '@/databases/repositories/execution.reposito
|
||||||
import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
|
import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
|
||||||
import { ExecutionService } from '@/executions/execution.service';
|
import { ExecutionService } from '@/executions/execution.service';
|
||||||
import type { ExecutionSummaries } from '@/executions/execution.types';
|
import type { ExecutionSummaries } from '@/executions/execution.types';
|
||||||
|
import { createTeamProject } from '@test-integration/db/projects';
|
||||||
|
|
||||||
import { annotateExecution, createAnnotationTags, createExecution } from './shared/db/executions';
|
import { annotateExecution, createAnnotationTags, createExecution } from './shared/db/executions';
|
||||||
import { createWorkflow } from './shared/db/workflows';
|
import { createWorkflow } from './shared/db/workflows';
|
||||||
|
@ -294,6 +295,37 @@ describe('ExecutionService', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should filter executions by `projectId`', async () => {
|
||||||
|
const firstProject = await createTeamProject();
|
||||||
|
const secondProject = await createTeamProject();
|
||||||
|
|
||||||
|
const firstWorkflow = await createWorkflow(undefined, firstProject);
|
||||||
|
const secondWorkflow = await createWorkflow(undefined, secondProject);
|
||||||
|
|
||||||
|
await createExecution({ status: 'success' }, firstWorkflow);
|
||||||
|
await createExecution({ status: 'success' }, firstWorkflow);
|
||||||
|
await createExecution({ status: 'success' }, secondWorkflow); // to filter out
|
||||||
|
|
||||||
|
const query: ExecutionSummaries.RangeQuery = {
|
||||||
|
kind: 'range',
|
||||||
|
range: { limit: 20 },
|
||||||
|
accessibleWorkflowIds: [firstWorkflow.id],
|
||||||
|
projectId: firstProject.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
const output = await executionService.findRangeWithCount(query);
|
||||||
|
|
||||||
|
expect(output).toEqual({
|
||||||
|
count: 2,
|
||||||
|
estimated: false,
|
||||||
|
results: expect.arrayContaining([
|
||||||
|
expect.objectContaining({ workflowId: firstWorkflow.id }),
|
||||||
|
expect.objectContaining({ workflowId: firstWorkflow.id }),
|
||||||
|
// execution for workflow in second project was filtered out
|
||||||
|
]),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test('should exclude executions by inaccessible `workflowId`', async () => {
|
test('should exclude executions by inaccessible `workflowId`', async () => {
|
||||||
const accessibleWorkflow = await createWorkflow();
|
const accessibleWorkflow = await createWorkflow();
|
||||||
const inaccessibleWorkflow = await createWorkflow();
|
const inaccessibleWorkflow = await createWorkflow();
|
||||||
|
|
Loading…
Reference in a new issue