fix(SSH Node): Cleanup temporary binary files as soon as possible (#11305)

This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™ 2024-10-22 15:41:41 +02:00 committed by GitHub
parent 8404282046
commit 08a7b5b742
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,4 +1,4 @@
import { rm, writeFile } from 'fs/promises'; import { writeFile } from 'fs/promises';
import type { Readable } from 'stream'; import type { Readable } from 'stream';
import type { import type {
ICredentialTestFunctions, ICredentialTestFunctions,
@ -285,8 +285,6 @@ export class Ssh implements INodeType {
): Promise<INodeCredentialTestResult> { ): Promise<INodeCredentialTestResult> {
const credentials = credential.data as IDataObject; const credentials = credential.data as IDataObject;
const ssh = new NodeSSH(); const ssh = new NodeSSH();
const temporaryFiles: string[] = [];
try { try {
if (!credentials.privateKey) { if (!credentials.privateKey) {
await ssh.connect({ await ssh.connect({
@ -317,7 +315,6 @@ export class Ssh implements INodeType {
}; };
} finally { } finally {
ssh.dispose(); ssh.dispose();
for (const tempFile of temporaryFiles) await rm(tempFile);
} }
return { return {
status: 'OK', status: 'OK',
@ -336,8 +333,6 @@ export class Ssh implements INodeType {
const operation = this.getNodeParameter('operation', 0); const operation = this.getNodeParameter('operation', 0);
const authentication = this.getNodeParameter('authentication', 0) as string; const authentication = this.getNodeParameter('authentication', 0) as string;
const temporaryFiles: string[] = [];
const ssh = new NodeSSH(); const ssh = new NodeSSH();
try { try {
@ -396,33 +391,35 @@ export class Ssh implements INodeType {
i, i,
); );
const { path } = await tmpFile({ prefix: 'n8n-ssh-' }); const binaryFile = await tmpFile({ prefix: 'n8n-ssh-' });
temporaryFiles.push(path); try {
await ssh.getFile(binaryFile.path, parameterPath);
await ssh.getFile(path, parameterPath); const newItem: INodeExecutionData = {
json: items[i].json,
binary: {},
pairedItem: {
item: i,
},
};
const newItem: INodeExecutionData = { if (items[i].binary !== undefined && newItem.binary) {
json: items[i].json, // Create a shallow copy of the binary data so that the old
binary: {}, // data references which do not get changed still stay behind
pairedItem: { // but the incoming data does not get changed.
item: i, Object.assign(newItem.binary, items[i].binary);
}, }
};
if (items[i].binary !== undefined && newItem.binary) { items[i] = newItem;
// Create a shallow copy of the binary data so that the old
// data references which do not get changed still stay behind const fileName = this.getNodeParameter('options.fileName', i, '') as string;
// but the incoming data does not get changed. items[i].binary![dataPropertyNameDownload] = await this.nodeHelpers.copyBinaryFile(
Object.assign(newItem.binary, items[i].binary); binaryFile.path,
fileName || parameterPath,
);
} finally {
await binaryFile.cleanup();
} }
items[i] = newItem;
const fileName = this.getNodeParameter('options.fileName', i, '') as string;
items[i].binary![dataPropertyNameDownload] = await this.nodeHelpers.copyBinaryFile(
path,
fileName || parameterPath,
);
} }
if (operation === 'upload') { if (operation === 'upload') {
@ -444,25 +441,28 @@ export class Ssh implements INodeType {
uploadData = Buffer.from(binaryData.data, BINARY_ENCODING); uploadData = Buffer.from(binaryData.data, BINARY_ENCODING);
} }
const { path } = await tmpFile({ prefix: 'n8n-ssh-' }); const binaryFile = await tmpFile({ prefix: 'n8n-ssh-' });
temporaryFiles.push(path); try {
await writeFile(path, uploadData); await writeFile(binaryFile.path, uploadData);
await ssh.putFile( await ssh.putFile(
path, binaryFile.path,
`${parameterPath}${ `${parameterPath}${
parameterPath.charAt(parameterPath.length - 1) === '/' ? '' : '/' parameterPath.charAt(parameterPath.length - 1) === '/' ? '' : '/'
}${fileName || binaryData.fileName}`, }${fileName || binaryData.fileName}`,
); );
returnItems.push({ returnItems.push({
json: { json: {
success: true, success: true,
}, },
pairedItem: { pairedItem: {
item: i, item: i,
}, },
}); });
} finally {
await binaryFile.cleanup();
}
} }
} }
} catch (error) { } catch (error) {
@ -488,16 +488,10 @@ export class Ssh implements INodeType {
throw error; throw error;
} }
} }
} catch (error) { } finally {
ssh.dispose(); ssh.dispose();
for (const tempFile of temporaryFiles) await rm(tempFile);
throw error;
} }
for (const tempFile of temporaryFiles) await rm(tempFile);
ssh.dispose();
if (resource === 'file' && operation === 'download') { if (resource === 'file' && operation === 'download') {
// For file downloads the files get attached to the existing items // For file downloads the files get attached to the existing items
return [items]; return [items];