Skip to content

Commit

Permalink
fix(SSH Node): Cleanup temporary binary files as soon as possible
Browse files Browse the repository at this point in the history
  • Loading branch information
netroy committed Oct 18, 2024
1 parent 0aae47c commit 01d5c31
Showing 1 changed file with 52 additions and 58 deletions.
110 changes: 52 additions & 58 deletions packages/nodes-base/nodes/Ssh/Ssh.node.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { rm, writeFile } from 'fs/promises';
import { writeFile } from 'fs/promises';
import type { Readable } from 'stream';
import type {
ICredentialTestFunctions,
Expand Down Expand Up @@ -285,8 +285,6 @@ export class Ssh implements INodeType {
): Promise<INodeCredentialTestResult> {
const credentials = credential.data as IDataObject;
const ssh = new NodeSSH();
const temporaryFiles: string[] = [];

try {
if (!credentials.privateKey) {
await ssh.connect({
Expand Down Expand Up @@ -317,7 +315,6 @@ export class Ssh implements INodeType {
};
} finally {
ssh.dispose();
for (const tempFile of temporaryFiles) await rm(tempFile);
}
return {
status: 'OK',
Expand All @@ -336,8 +333,6 @@ export class Ssh implements INodeType {
const operation = this.getNodeParameter('operation', 0);
const authentication = this.getNodeParameter('authentication', 0) as string;

const temporaryFiles: string[] = [];

const ssh = new NodeSSH();

try {
Expand Down Expand Up @@ -396,33 +391,35 @@ export class Ssh implements INodeType {
i,
);

const { path } = await tmpFile({ prefix: 'n8n-ssh-' });
temporaryFiles.push(path);

await ssh.getFile(path, parameterPath);

const newItem: INodeExecutionData = {
json: items[i].json,
binary: {},
pairedItem: {
item: i,
},
};

if (items[i].binary !== undefined && newItem.binary) {
// Create a shallow copy of the binary data so that the old
// data references which do not get changed still stay behind
// but the incoming data does not get changed.
Object.assign(newItem.binary, items[i].binary);
const binaryFile = await tmpFile({ prefix: 'n8n-ssh-' });
try {
await ssh.getFile(binaryFile.path, parameterPath);

const newItem: INodeExecutionData = {
json: items[i].json,
binary: {},
pairedItem: {
item: i,
},
};

if (items[i].binary !== undefined && newItem.binary) {
// Create a shallow copy of the binary data so that the old
// data references which do not get changed still stay behind
// but the incoming data does not get changed.
Object.assign(newItem.binary, items[i].binary);
}

items[i] = newItem;

const fileName = this.getNodeParameter('options.fileName', i, '') as string;
items[i].binary![dataPropertyNameDownload] = await this.nodeHelpers.copyBinaryFile(
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') {
Expand All @@ -444,25 +441,28 @@ export class Ssh implements INodeType {
uploadData = Buffer.from(binaryData.data, BINARY_ENCODING);
}

const { path } = await tmpFile({ prefix: 'n8n-ssh-' });
temporaryFiles.push(path);
await writeFile(path, uploadData);

await ssh.putFile(
path,
`${parameterPath}${
parameterPath.charAt(parameterPath.length - 1) === '/' ? '' : '/'
}${fileName || binaryData.fileName}`,
);

returnItems.push({
json: {
success: true,
},
pairedItem: {
item: i,
},
});
const binaryFile = await tmpFile({ prefix: 'n8n-ssh-' });
try {
await writeFile(binaryFile.path, uploadData);

await ssh.putFile(
binaryFile.path,
`${parameterPath}${
parameterPath.charAt(parameterPath.length - 1) === '/' ? '' : '/'
}${fileName || binaryData.fileName}`,
);

returnItems.push({
json: {
success: true,
},
pairedItem: {
item: i,
},
});
} finally {
await binaryFile.cleanup();
}
}
}
} catch (error) {
Expand All @@ -488,16 +488,10 @@ export class Ssh implements INodeType {
throw error;
}
}
} catch (error) {
} finally {
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') {
// For file downloads the files get attached to the existing items
return [items];
Expand Down

0 comments on commit 01d5c31

Please sign in to comment.