fix: Fix executions bulk deletion (#5074)

since QueryBuilder api doesn't use entity field transforms, we should remove the usage of QueryBuilder wherever there is a filter on a transformed column.
This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™ 2023-01-03 10:58:34 +01:00 committed by GitHub
parent ee28213538
commit 3754c5c734
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -12,10 +12,11 @@ import {
jsonParse, jsonParse,
Workflow, Workflow,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { FindOperator, In, IsNull, LessThanOrEqual, Not, Raw } from 'typeorm'; import { FindConditions, FindOperator, In, IsNull, LessThanOrEqual, Not, Raw } from 'typeorm';
import * as ActiveExecutions from '@/ActiveExecutions'; import * as ActiveExecutions from '@/ActiveExecutions';
import config from '@/config'; import config from '@/config';
import { User } from '@/databases/entities/User'; import type { User } from '@/databases/entities/User';
import type { ExecutionEntity } from '@db/entities/ExecutionEntity';
import { import {
IExecutionFlattedResponse, IExecutionFlattedResponse,
IExecutionResponse, IExecutionResponse,
@ -199,7 +200,7 @@ export class ExecutionsService {
.map(({ id }) => id), .map(({ id }) => id),
); );
const findWhere = { workflowId: In(sharedWorkflowIds) }; const findWhere: FindConditions<ExecutionEntity> = { workflowId: In(sharedWorkflowIds) };
const rangeQuery: string[] = []; const rangeQuery: string[] = [];
const rangeQueryParams: { const rangeQueryParams: {
@ -452,66 +453,39 @@ export class ExecutionsService {
throw new Error('Either "deleteBefore" or "ids" must be present in the request body'); throw new Error('Either "deleteBefore" or "ids" must be present in the request body');
} }
const binaryDataManager = BinaryDataManager.getInstance(); const where: FindConditions<ExecutionEntity> = { workflowId: In(sharedWorkflowIds) };
// delete executions by date, if user may access the underlying workflows
if (deleteBefore) { if (deleteBefore) {
const filters: IDataObject = { // delete executions by date, if user may access the underlying workflows
startedAt: LessThanOrEqual(deleteBefore), where.startedAt = LessThanOrEqual(deleteBefore);
}; Object.assign(where, requestFilters);
} else if (ids) {
let query = Db.collections.Execution.createQueryBuilder()
.select('id')
.where({
...filters,
workflowId: In(sharedWorkflowIds),
});
if (requestFilters) {
query = query.andWhere(requestFilters);
}
const executions = await query.getMany();
if (!executions.length) return;
const idsToDelete = executions.map(({ id }) => id);
await Promise.all(
idsToDelete.map(async (id) => binaryDataManager.deleteBinaryDataByExecutionId(id)),
);
await Db.collections.Execution.delete({ id: In(idsToDelete) });
return;
}
// delete executions by IDs, if user may access the underlying workflows // delete executions by IDs, if user may access the underlying workflows
where.id = In(ids);
} else return;
if (ids) {
const executions = await Db.collections.Execution.find({ const executions = await Db.collections.Execution.find({
where: { select: ['id'],
id: In(ids), where,
workflowId: In(sharedWorkflowIds),
},
}); });
if (!executions.length) { if (!executions.length) {
if (ids) {
LoggerProxy.error('Failed to delete an execution due to insufficient permissions', { LoggerProxy.error('Failed to delete an execution due to insufficient permissions', {
userId: req.user.id, userId: req.user.id,
executionIds: ids, executionIds: ids,
}); });
}
return; return;
} }
const idsToDelete = executions.map(({ id }) => id); const idsToDelete = executions.map(({ id }) => id);
const binaryDataManager = BinaryDataManager.getInstance();
await Promise.all( await Promise.all(
idsToDelete.map(async (id) => binaryDataManager.deleteBinaryDataByExecutionId(id)), idsToDelete.map(async (id) => binaryDataManager.deleteBinaryDataByExecutionId(id)),
); );
await Db.collections.Execution.delete(idsToDelete); await Db.collections.Execution.delete(idsToDelete);
} }
}
} }