From 9fd6319583d0446e41de4fb80d4bc5a6c5e1ca07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Thu, 9 Nov 2023 14:39:16 +0100 Subject: [PATCH] fix(core): Reduce memory usage in credentials risk auditing (#7663) --- .../cli/src/audit/risks/credentials.risk.ts | 44 ++++++++++++------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/packages/cli/src/audit/risks/credentials.risk.ts b/packages/cli/src/audit/risks/credentials.risk.ts index 80d145e7505a0..57cfb4049f240 100644 --- a/packages/cli/src/audit/risks/credentials.risk.ts +++ b/packages/cli/src/audit/risks/credentials.risk.ts @@ -1,13 +1,16 @@ -import type { FindOperator } from 'typeorm'; -import { MoreThanOrEqual } from 'typeorm'; +import { In, MoreThanOrEqual } from 'typeorm'; import { DateUtils } from 'typeorm/util/DateUtils'; import { Container } from 'typedi'; -import * as Db from '@/Db'; +import type { IWorkflowBase } from 'n8n-workflow'; import config from '@/config'; import { CREDENTIALS_REPORT } from '@/audit/constants'; -import type { WorkflowEntity } from '@db/entities/WorkflowEntity'; import type { Risk } from '@/audit/types'; -import { ExecutionRepository } from '@db/repositories'; +import type { WorkflowEntity } from '@db/entities/WorkflowEntity'; +import { + CredentialsRepository, + ExecutionDataRepository, + ExecutionRepository, +} from '@db/repositories'; async function getAllCredsInUse(workflows: WorkflowEntity[]) { const credsInAnyUse = new Set(); @@ -34,36 +37,43 @@ async function getAllCredsInUse(workflows: WorkflowEntity[]) { } async function getAllExistingCreds() { - const credentials = await Db.collections.Credentials.find({ select: ['id', 'name'] }); + const credentials = await Container.get(CredentialsRepository).find({ select: ['id', 'name'] }); return credentials.map(({ id, name }) => ({ kind: 'credential' as const, id, name })); } -async function getExecutionsInPastDays(days: number) { +async function getExecutedWorkflowsInPastDays(days: number): Promise { const date = new Date(); date.setDate(date.getDate() - days); - const utcDate = DateUtils.mixedDateToUtcDatetimeString(date) as string; + const executionIds = await Container.get(ExecutionRepository) + .find({ + select: ['id'], + where: { + startedAt: MoreThanOrEqual(DateUtils.mixedDateToUtcDatetimeString(date) as Date), + }, + }) + .then((executions) => executions.map(({ id }) => id)); - return Container.get(ExecutionRepository).findMultipleExecutions( - { + return Container.get(ExecutionDataRepository) + .find({ + select: ['workflowData'], where: { - startedAt: MoreThanOrEqual(utcDate) as unknown as FindOperator, + executionId: In(executionIds), }, - }, - { includeData: true }, - ); + }) + .then((executionData) => executionData.map(({ workflowData }) => workflowData)); } /** * Return IDs of credentials in workflows executed in the past n days. */ async function getCredsInRecentlyExecutedWorkflows(days: number) { - const recentExecutions = await getExecutionsInPastDays(days); + const executedWorkflows = await getExecutedWorkflowsInPastDays(days); - return recentExecutions.reduce>((acc, execution) => { - execution.workflowData?.nodes.forEach((node) => { + return executedWorkflows.reduce>((acc, { nodes }) => { + nodes.forEach((node) => { if (node.credentials) { Object.values(node.credentials).forEach((c) => { if (c.id) acc.add(c.id);