n8n/packages/nodes-base/nodes/Dropbox/Dropbox.node.ts

624 lines
15 KiB
TypeScript
Raw Normal View History

2020-06-03 07:24:17 -07:00
import { BINARY_ENCODING, IExecuteFunctions } from 'n8n-core';
2019-06-23 03:35:23 -07:00
import {
IDataObject,
INodeExecutionData,
INodeType,
2020-06-03 07:24:17 -07:00
INodeTypeDescription
2019-06-23 03:35:23 -07:00
} from 'n8n-workflow';
2020-06-03 07:24:17 -07:00
import { dropboxApiRequest } from './GenericFunctions';
2019-06-23 03:35:23 -07:00
export class Dropbox implements INodeType {
description: INodeTypeDescription = {
displayName: 'Dropbox',
name: 'dropbox',
icon: 'file:dropbox.png',
group: ['input'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
2019-06-23 03:35:23 -07:00
description: 'Access data on Dropbox',
defaults: {
name: 'Dropbox',
2020-06-03 07:24:17 -07:00
color: '#22BB44'
2019-06-23 03:35:23 -07:00
},
inputs: ['main'],
outputs: ['main'],
credentials: [
{
name: 'dropboxApi',
required: true,
2020-06-03 07:24:17 -07:00
displayOptions: {
show: {
authentication: ['accessToken']
}
}
},
{
name: 'dropboxOAuth2Api',
required: true,
displayOptions: {
show: {
authentication: ['oAuth2']
}
}
2019-06-23 03:35:23 -07:00
}
],
properties: [
2020-06-03 07:24:17 -07:00
{
displayName: 'Authentication',
name: 'authentication',
type: 'options',
options: [
{
name: 'Access Token',
value: 'accessToken'
},
{
name: 'OAuth2',
value: 'oAuth2'
}
],
default: 'accessToken',
description: 'Means of authenticating with the serivce.'
},
{
displayName: 'Resource',
name: 'resource',
type: 'options',
options: [
{
name: 'File',
2020-06-03 07:24:17 -07:00
value: 'file'
},
{
name: 'Folder',
2020-06-03 07:24:17 -07:00
value: 'folder'
}
],
default: 'file',
2020-06-03 07:24:17 -07:00
description: 'The resource to operate on.'
},
// ----------------------------------
// operations
// ----------------------------------
2019-06-23 03:35:23 -07:00
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
2020-06-03 07:24:17 -07:00
resource: ['file']
}
},
2019-06-23 03:35:23 -07:00
options: [
{
name: 'Copy',
value: 'copy',
2020-06-03 07:24:17 -07:00
description: 'Copy a file'
2019-06-23 03:35:23 -07:00
},
{
name: 'Delete',
value: 'delete',
2020-06-03 07:24:17 -07:00
description: 'Delete a file'
2019-06-23 03:35:23 -07:00
},
{
name: 'Download',
value: 'download',
2020-06-03 07:24:17 -07:00
description: 'Download a file'
2019-06-23 03:35:23 -07:00
},
{
name: 'Move',
value: 'move',
2020-06-03 07:24:17 -07:00
description: 'Move a file'
2019-06-23 03:35:23 -07:00
},
{
name: 'Upload',
value: 'upload',
2020-06-03 07:24:17 -07:00
description: 'Upload a file'
}
2019-06-23 03:35:23 -07:00
],
default: 'upload',
2020-06-03 07:24:17 -07:00
description: 'The operation to perform.'
2019-06-23 03:35:23 -07:00
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
2020-06-03 07:24:17 -07:00
resource: ['folder']
}
},
options: [
{
name: 'Copy',
value: 'copy',
2020-06-03 07:24:17 -07:00
description: 'Copy a folder'
},
{
name: 'Create',
value: 'create',
2020-06-03 07:24:17 -07:00
description: 'Create a folder'
},
{
name: 'Delete',
value: 'delete',
2020-06-03 07:24:17 -07:00
description: 'Delete a folder'
},
{
name: 'List',
value: 'list',
2020-06-03 07:24:17 -07:00
description: 'Return the files and folders in a given folder'
},
{
name: 'Move',
value: 'move',
2020-06-03 07:24:17 -07:00
description: 'Move a folder'
}
],
default: 'create',
2020-06-03 07:24:17 -07:00
description: 'The operation to perform.'
},
2019-06-23 03:35:23 -07:00
// ----------------------------------
// file
// ----------------------------------
// ----------------------------------
// file/folder:copy
2019-06-23 03:35:23 -07:00
// ----------------------------------
{
displayName: 'From Path',
name: 'path',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
2020-06-03 07:24:17 -07:00
operation: ['copy'],
resource: ['file', 'folder']
}
2019-06-23 03:35:23 -07:00
},
placeholder: '/invoices/original.txt',
2020-06-03 07:24:17 -07:00
description: 'The path of file or folder to copy.'
2019-06-23 03:35:23 -07:00
},
{
displayName: 'To Path',
name: 'toPath',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
2020-06-03 07:24:17 -07:00
operation: ['copy'],
resource: ['file', 'folder']
}
2019-06-23 03:35:23 -07:00
},
placeholder: '/invoices/copy.txt',
2020-06-03 07:24:17 -07:00
description: 'The destination path of file or folder.'
2019-06-23 03:35:23 -07:00
},
// ----------------------------------
// file/folder:delete
2019-06-23 03:35:23 -07:00
// ----------------------------------
{
displayName: 'Delete Path',
name: 'path',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
2020-06-03 07:24:17 -07:00
operation: ['delete'],
resource: ['file', 'folder']
}
2019-06-23 03:35:23 -07:00
},
placeholder: '/invoices/2019/invoice_1.pdf',
2020-06-03 07:24:17 -07:00
description:
'The path to delete. Can be a single file or a whole folder.'
2019-06-23 03:35:23 -07:00
},
// ----------------------------------
// file/folder:move
2019-06-23 03:35:23 -07:00
// ----------------------------------
{
displayName: 'From Path',
2019-06-23 03:35:23 -07:00
name: 'path',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
2020-06-03 07:24:17 -07:00
operation: ['move'],
resource: ['file', 'folder']
}
2019-06-23 03:35:23 -07:00
},
placeholder: '/invoices/old_name.txt',
2020-06-03 07:24:17 -07:00
description: 'The path of file or folder to move.'
2019-06-23 03:35:23 -07:00
},
{
displayName: 'To Path',
name: 'toPath',
2019-06-23 03:35:23 -07:00
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
2020-06-03 07:24:17 -07:00
operation: ['move'],
resource: ['file', 'folder']
}
2019-06-23 03:35:23 -07:00
},
placeholder: '/invoices/new_name.txt',
2020-06-03 07:24:17 -07:00
description: 'The new path of file or folder.'
2019-06-23 03:35:23 -07:00
},
// ----------------------------------
// file:download
2019-06-23 03:35:23 -07:00
// ----------------------------------
{
displayName: 'File Path',
2019-06-23 03:35:23 -07:00
name: 'path',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
2020-06-03 07:24:17 -07:00
operation: ['download'],
resource: ['file']
}
2019-06-23 03:35:23 -07:00
},
placeholder: '/invoices/2019/invoice_1.pdf',
2020-06-03 07:24:17 -07:00
description:
'The file path of the file to download. Has to contain the full path.'
2019-06-23 03:35:23 -07:00
},
{
displayName: 'Binary Property',
name: 'binaryPropertyName',
2019-06-23 03:35:23 -07:00
type: 'string',
required: true,
default: 'data',
2019-06-23 03:35:23 -07:00
displayOptions: {
show: {
2020-06-03 07:24:17 -07:00
operation: ['download'],
resource: ['file']
}
2019-06-23 03:35:23 -07:00
},
2020-06-03 07:24:17 -07:00
description:
'Name of the binary property to which to<br />write the data of the read file.'
2019-06-23 03:35:23 -07:00
},
// ----------------------------------
// file:upload
2019-06-23 03:35:23 -07:00
// ----------------------------------
{
displayName: 'File Path',
name: 'path',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
2020-06-03 07:24:17 -07:00
operation: ['upload'],
resource: ['file']
}
2019-06-23 03:35:23 -07:00
},
placeholder: '/invoices/2019/invoice_1.pdf',
2020-06-03 07:24:17 -07:00
description:
'The file path of the file to upload. Has to contain the full path. The parent folder has to exist. Existing files get overwritten.'
2019-06-23 03:35:23 -07:00
},
{
displayName: 'Binary Data',
name: 'binaryData',
type: 'boolean',
default: false,
displayOptions: {
show: {
2020-06-03 07:24:17 -07:00
operation: ['upload'],
resource: ['file']
}
2019-06-23 03:35:23 -07:00
},
2020-06-03 07:24:17 -07:00
description: 'If the data to upload should be taken from binary field.'
2019-06-23 03:35:23 -07:00
},
{
displayName: 'File Content',
name: 'fileContent',
type: 'string',
default: '',
displayOptions: {
show: {
2020-06-03 07:24:17 -07:00
operation: ['upload'],
resource: ['file'],
binaryData: [false]
}
2019-06-23 03:35:23 -07:00
},
placeholder: '',
2020-06-03 07:24:17 -07:00
description: 'The text content of the file to upload.'
2019-06-23 03:35:23 -07:00
},
{
displayName: 'Binary Property',
name: 'binaryPropertyName',
type: 'string',
default: 'data',
required: true,
displayOptions: {
show: {
2020-06-03 07:24:17 -07:00
operation: ['upload'],
resource: ['file'],
binaryData: [true]
}
2019-06-23 03:35:23 -07:00
},
placeholder: '',
2020-06-03 07:24:17 -07:00
description:
'Name of the binary property which contains<br />the data for the file to be uploaded.'
2019-06-23 03:35:23 -07:00
},
// ----------------------------------
// folder
// ----------------------------------
// ----------------------------------
// folder:create
// ----------------------------------
{
displayName: 'Folder',
name: 'path',
type: 'string',
default: '',
required: true,
displayOptions: {
show: {
2020-06-03 07:24:17 -07:00
operation: ['create'],
resource: ['folder']
}
},
placeholder: '/invoices/2019',
2020-06-03 07:24:17 -07:00
description: 'The folder to create. The parent folder has to exist.'
},
// ----------------------------------
// folder:list
// ----------------------------------
{
displayName: 'Folder Path',
name: 'path',
type: 'string',
default: '',
displayOptions: {
show: {
2020-06-03 07:24:17 -07:00
operation: ['list'],
resource: ['folder']
}
},
placeholder: '/invoices/2019/',
2020-06-03 07:24:17 -07:00
description: 'The path of which to list the content.'
}
]
2019-06-23 03:35:23 -07:00
};
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const items = this.getInputData();
const returnData: IDataObject[] = [];
const resource = this.getNodeParameter('resource', 0) as string;
2019-06-23 03:35:23 -07:00
const operation = this.getNodeParameter('operation', 0) as string;
let endpoint = '';
let requestMethod = '';
let body: IDataObject | Buffer;
2020-06-03 07:24:17 -07:00
const headers: IDataObject = {};
2019-06-23 03:35:23 -07:00
for (let i = 0; i < items.length; i++) {
body = {};
if (resource === 'file') {
if (operation === 'download') {
// ----------------------------------
// download
// ----------------------------------
2019-06-23 03:35:23 -07:00
requestMethod = 'POST';
headers['Dropbox-API-Arg'] = JSON.stringify({
2020-06-03 07:24:17 -07:00
path: this.getNodeParameter('path', i) as string
});
2019-06-23 03:35:23 -07:00
endpoint = 'https://content.dropboxapi.com/2/files/download';
} else if (operation === 'upload') {
// ----------------------------------
// upload
// ----------------------------------
2019-06-23 03:35:23 -07:00
requestMethod = 'POST';
headers['Content-Type'] = 'application/octet-stream';
headers['Dropbox-API-Arg'] = JSON.stringify({
mode: 'overwrite',
2020-06-03 07:24:17 -07:00
path: this.getNodeParameter('path', i) as string
});
2019-06-23 03:35:23 -07:00
endpoint = 'https://content.dropboxapi.com/2/files/upload';
2019-06-23 03:35:23 -07:00
if (this.getNodeParameter('binaryData', i) === true) {
// Is binary file to upload
const item = items[i];
2019-06-23 03:35:23 -07:00
if (item.binary === undefined) {
throw new Error('No binary data exists on item!');
}
2019-06-23 03:35:23 -07:00
2020-06-03 07:24:17 -07:00
const propertyNameUpload = this.getNodeParameter(
'binaryPropertyName',
i
) as string;
2019-06-23 03:35:23 -07:00
if (item.binary[propertyNameUpload] === undefined) {
2020-06-03 07:24:17 -07:00
throw new Error(
`No binary data property "${propertyNameUpload}" does not exists on item!`
);
}
2019-06-23 03:35:23 -07:00
2020-06-03 07:24:17 -07:00
body = Buffer.from(
item.binary[propertyNameUpload].data,
BINARY_ENCODING
);
} else {
// Is text file
2020-06-03 07:24:17 -07:00
body = Buffer.from(
this.getNodeParameter('fileContent', i) as string,
'utf8'
);
}
}
} else if (resource === 'folder') {
if (operation === 'create') {
// ----------------------------------
// create
// ----------------------------------
2019-06-23 03:35:23 -07:00
requestMethod = 'POST';
body = {
2020-06-03 07:24:17 -07:00
path: this.getNodeParameter('path', i) as string
};
2019-06-23 03:35:23 -07:00
endpoint = 'https://api.dropboxapi.com/2/files/create_folder_v2';
} else if (operation === 'list') {
// ----------------------------------
// list
// ----------------------------------
2019-06-23 03:35:23 -07:00
requestMethod = 'POST';
body = {
path: this.getNodeParameter('path', i) as string,
2020-06-03 07:24:17 -07:00
limit: 2000
};
2019-06-23 03:35:23 -07:00
// TODO: If more files than the max-amount exist it has to be possible to
// also request them.
2019-06-23 03:35:23 -07:00
endpoint = 'https://api.dropboxapi.com/2/files/list_folder';
}
}
if (['file', 'folder'].includes(resource)) {
if (operation === 'copy') {
// ----------------------------------
// copy
// ----------------------------------
requestMethod = 'POST';
body = {
from_path: this.getNodeParameter('path', i) as string,
2020-06-03 07:24:17 -07:00
to_path: this.getNodeParameter('toPath', i) as string
};
endpoint = 'https://api.dropboxapi.com/2/files/copy_v2';
} else if (operation === 'delete') {
// ----------------------------------
// delete
// ----------------------------------
requestMethod = 'POST';
body = {
2020-06-03 07:24:17 -07:00
path: this.getNodeParameter('path', i) as string
};
endpoint = 'https://api.dropboxapi.com/2/files/delete_v2';
} else if (operation === 'move') {
// ----------------------------------
// move
// ----------------------------------
requestMethod = 'POST';
body = {
from_path: this.getNodeParameter('path', i) as string,
2020-06-03 07:24:17 -07:00
to_path: this.getNodeParameter('toPath', i) as string
};
endpoint = 'https://api.dropboxapi.com/2/files/move_v2';
2019-06-23 03:35:23 -07:00
}
} else {
throw new Error(`The resource "${resource}" is not known!`);
2019-06-23 03:35:23 -07:00
}
2020-06-03 07:24:17 -07:00
let encoding: string | null = '';
if (resource === 'file' && operation === 'download') {
2019-06-23 03:35:23 -07:00
// Return the data as a buffer
2020-06-03 07:24:17 -07:00
encoding = null;
2019-06-23 03:35:23 -07:00
}
2020-06-03 07:24:17 -07:00
const responseData = await dropboxApiRequest.call(
this,
requestMethod,
endpoint,
body,
headers,
encoding
);
2019-06-23 03:35:23 -07:00
if (resource === 'file' && operation === 'download') {
const newItem: INodeExecutionData = {
json: items[i].json,
2020-06-03 07:24:17 -07:00
binary: {}
};
if (items[i].binary !== undefined) {
// 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);
2019-06-23 03:35:23 -07:00
}
items[i] = newItem;
2020-06-03 07:24:17 -07:00
const dataPropertyNameDownload = this.getNodeParameter(
'binaryPropertyName',
i
) as string;
2019-06-23 03:35:23 -07:00
const filePathDownload = this.getNodeParameter('path', i) as string;
2020-06-03 07:24:17 -07:00
items[i].binary![
dataPropertyNameDownload
] = await this.helpers.prepareBinaryData(
Buffer.from(responseData.data),
filePathDownload
);
} else if (resource === 'folder' && operation === 'list') {
2019-06-23 03:35:23 -07:00
const propNames: { [key: string]: string } = {
2020-06-03 07:24:17 -07:00
id: 'id',
name: 'name',
client_modified: 'lastModifiedClient',
server_modified: 'lastModifiedServer',
rev: 'rev',
size: 'contentSize',
2019-06-23 03:35:23 -07:00
'.tag': 'type',
2020-06-03 07:24:17 -07:00
content_hash: 'contentHash'
2019-06-23 03:35:23 -07:00
};
for (const item of responseData.entries) {
const newItem: IDataObject = {};
// Get the props and save them under a proper name
for (const propName of Object.keys(propNames)) {
if (item[propName] !== undefined) {
newItem[propNames[propName]] = item[propName];
}
}
returnData.push(newItem as IDataObject);
}
} else if (resource === 'file' && operation === 'upload') {
2020-06-03 07:24:17 -07:00
returnData.push(responseData as IDataObject);
2019-06-23 03:35:23 -07:00
} else {
returnData.push(responseData as IDataObject);
}
}
if (resource === 'file' && operation === 'download') {
2019-06-23 03:35:23 -07:00
// For file downloads the files get attached to the existing items
return this.prepareOutputData(items);
} else {
// For all other ones does the output items get replaced
2019-06-23 03:35:23 -07:00
return [this.helpers.returnJsonArray(returnData)];
}
}
}