feat(core): Filter executions by project ID in internal API (#10976)

This commit is contained in:
Iván Ovejero 2024-09-26 13:31:34 +02:00 committed by GitHub
parent 5a99e93f8d
commit 06d749ffa7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 42 additions and 0 deletions

View file

@ -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;
} }

View file

@ -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 = {

View file

@ -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();