From 89ed3c4a6d2e06caa3fe255d0a7bd1a8cfbf8610 Mon Sep 17 00:00:00 2001 From: Rupenieks <32895755+Rupenieks@users.noreply.github.com> Date: Wed, 2 Sep 2020 10:50:14 +0200 Subject: [PATCH] :sparkles: Recursive listing for FTP/SFTP (#903) * :zap: Add allowUnauthorizedCerts to Postgres-Node * :zap: Added recursive directory listing for SFTP * :zap: Added recursive listing for FTP * Removed unused imports * :zap: Fixed creating an instance of both ftp/sftp both regardless of which is used Co-authored-by: Jan Oberhauser --- packages/nodes-base/nodes/Ftp.node.ts | 79 ++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 8 deletions(-) diff --git a/packages/nodes-base/nodes/Ftp.node.ts b/packages/nodes-base/nodes/Ftp.node.ts index 49f828f2ed..84106640ac 100644 --- a/packages/nodes-base/nodes/Ftp.node.ts +++ b/packages/nodes-base/nodes/Ftp.node.ts @@ -220,6 +220,21 @@ export class Ftp implements INodeType { description: 'Path of directory to list contents of.', required: true, }, + { + displayName: 'Recursive', + displayOptions: { + show: { + operation: [ + 'list', + ], + }, + }, + name: 'recursive', + type: 'boolean', + default: false, + description: 'Return object representing all directories / objects recursively found within SFTP server', + required: true, + }, ], }; @@ -234,6 +249,7 @@ export class Ftp implements INodeType { let credentials: ICredentialDataDecryptedObject | undefined = undefined; const protocol = this.getNodeParameter('protocol', 0) as string; + if (protocol === 'sftp') { credentials = this.getCredentials('sftp'); } else { @@ -244,11 +260,11 @@ export class Ftp implements INodeType { throw new Error('Failed to get credentials!'); } - let ftp: ftpClient; - let sftp: sftpClient; + let ftp : ftpClient; + let sftp : sftpClient; + if (protocol === 'sftp') { sftp = new sftpClient(); - await sftp.connect({ host: credentials.host as string, port: credentials.port as number, @@ -258,7 +274,6 @@ export class Ftp implements INodeType { } else { ftp = new ftpClient(); - await ftp.connect({ host: credentials.host as string, port: credentials.port as number, @@ -286,8 +301,15 @@ export class Ftp implements INodeType { const path = this.getNodeParameter('path', i) as string; if (operation === 'list') { - responseData = await sftp!.list(path); - returnItems.push.apply(returnItems, this.helpers.returnJsonArray(responseData as unknown as IDataObject[])); + const recursive = this.getNodeParameter('recursive', i) as boolean; + + if (recursive) { + responseData = await callRecursiveList(path, sftp); + returnItems.push.apply(returnItems, this.helpers.returnJsonArray(responseData as unknown as IDataObject[])); + } else { + responseData = await sftp!.list(path); + returnItems.push.apply(returnItems, this.helpers.returnJsonArray(responseData as unknown as IDataObject[])); + } } if (operation === 'download') { @@ -347,8 +369,15 @@ export class Ftp implements INodeType { const path = this.getNodeParameter('path', i) as string; if (operation === 'list') { - responseData = await ftp!.list(path); - returnItems.push.apply(returnItems, this.helpers.returnJsonArray(responseData as unknown as IDataObject[])); + const recursive = this.getNodeParameter('recursive', i) as boolean; + + if (recursive) { + responseData = await callRecursiveList(path, ftp); + returnItems.push.apply(returnItems, this.helpers.returnJsonArray(responseData as unknown as IDataObject[])); + } else { + responseData = await ftp!.list(path); + returnItems.push.apply(returnItems, this.helpers.returnJsonArray(responseData as unknown as IDataObject[])); + } } if (operation === 'download') { @@ -432,3 +461,37 @@ export class Ftp implements INodeType { return [returnItems]; } } +async function callRecursiveList(path: string, client : sftpClient | ftpClient) { + const pathArray : string[] = [path]; + let currentPath = path; + const directoryItems : sftpClient.FileInfo[] = []; + let index = 0; + + do { + // tslint:disable-next-line: array-type + const returnData : sftpClient.FileInfo[] | (string | ftpClient.ListingElement)[] = await client.list(pathArray[index]); + + // @ts-ignore + returnData.map((item : sftpClient.FileInfo) => { + if ((pathArray[index] as string).endsWith('/')) { + currentPath = `${pathArray[index]}${item.name}`; + } else { + currentPath = `${pathArray[index]}/${item.name}`; + } + + // Is directory + if (item.type === 'd') { + pathArray.push(currentPath); + } + + //@ts-ignore + item.path = currentPath; + directoryItems.push(item); + }); + index++; + + } while (index <= pathArray.length - 1); + + + return directoryItems; +}