n8n/packages/nodes-base/nodes/Wise/WiseTrigger.node.ts
Omar Ajoue 7ce7285f7a
Load credentials from the database (#1741)
* Changes to types so that credentials can be always loaded from DB

This first commit changes all return types from the execute functions
and calls to get credentials to be async so we can use await.

This is a first step as previously credentials were loaded in memory and
always available. We will now be loading them from the DB which requires
turning the whole call chain async.

* Fix updated files

* Removed unnecessary credential loading to improve performance

* Fix typo

*  Fix issue

* Updated new nodes to load credentials async

*  Remove not needed comment

Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
2021-08-20 18:57:30 +02:00

189 lines
4.7 KiB
TypeScript

import {
IHookFunctions,
IWebhookFunctions,
} from 'n8n-core';
import {
IDataObject,
ILoadOptionsFunctions,
INodeType,
INodeTypeDescription,
IWebhookResponseData,
} from 'n8n-workflow';
import {
getTriggerName,
livePublicKey,
Profile,
testPublicKey,
wiseApiRequest,
} from './GenericFunctions';
import {
createVerify,
} from 'crypto';
export class WiseTrigger implements INodeType {
description: INodeTypeDescription = {
displayName: 'Wise Trigger',
name: 'wiseTrigger',
icon: 'file:wise.svg',
group: ['trigger'],
version: 1,
subtitle: '={{$parameter["event"]}}',
description: 'Handle Wise events via webhooks',
defaults: {
name: 'Wise Trigger',
color: '#37517e',
},
inputs: [],
outputs: ['main'],
credentials: [
{
name: 'wiseApi',
required: true,
},
],
webhooks: [
{
name: 'default',
httpMethod: 'POST',
responseMode: 'onReceived',
path: 'webhook',
},
],
properties: [
{
displayName: 'Profile',
name: 'profileId',
type: 'options',
required: true,
typeOptions: {
loadOptionsMethod: 'getProfiles',
},
default: '',
},
{
displayName: 'Event',
name: 'event',
type: 'options',
required: true,
default: '',
options: [
{
name: 'Balance Credit',
value: 'balanceCredit',
description: 'Triggered every time a balance account is credited.',
},
{
name: 'Transfer Active Case',
value: 'transferActiveCases',
description: `Triggered every time a transfer's list of active cases is updated.`,
},
{
name: 'Transfer State Changed',
value: 'tranferStateChange',
description: `Triggered every time a transfer's status is updated.`,
},
],
},
],
};
methods = {
loadOptions: {
async getProfiles(this: ILoadOptionsFunctions) {
const profiles = await wiseApiRequest.call(this, 'GET', 'v1/profiles');
return profiles.map(({ id, type }: Profile) => ({
name: type.charAt(0).toUpperCase() + type.slice(1),
value: id,
}));
},
},
};
// @ts-ignore
webhookMethods = {
default: {
async checkExists(this: IHookFunctions): Promise<boolean> {
const webhookData = this.getWorkflowStaticData('node');
const webhookUrl = this.getNodeWebhookUrl('default');
const profileId = this.getNodeParameter('profileId') as string;
const event = this.getNodeParameter('event') as string;
const webhooks = await wiseApiRequest.call(this, 'GET', `v3/profiles/${profileId}/subscriptions`);
const trigger = getTriggerName(event);
for (const webhook of webhooks) {
if (webhook.delivery.url === webhookUrl && webhook.scope.id === profileId && webhook.trigger_on === trigger) {
webhookData.webhookId = webhook.id;
return true;
}
}
return false;
},
async create(this: IHookFunctions): Promise<boolean> {
const webhookUrl = this.getNodeWebhookUrl('default');
const webhookData = this.getWorkflowStaticData('node');
const profileId = this.getNodeParameter('profileId') as string;
const event = this.getNodeParameter('event') as string;
const trigger = getTriggerName(event);
const body: IDataObject = {
name: `n8n Webhook`,
trigger_on: trigger,
delivery: {
version: '2.0.0',
url: webhookUrl,
},
};
const webhook = await wiseApiRequest.call(this, 'POST', `v3/profiles/${profileId}/subscriptions`, body);
webhookData.webhookId = webhook.id;
return true;
},
async delete(this: IHookFunctions): Promise<boolean> {
const webhookData = this.getWorkflowStaticData('node');
const profileId = this.getNodeParameter('profileId') as string;
try {
await wiseApiRequest.call(this, 'DELETE', `v3/profiles/${profileId}/subscriptions/${webhookData.webhookId}`);
} catch (error) {
return false;
}
delete webhookData.webhookId;
return true;
},
},
};
async webhook(this: IWebhookFunctions): Promise<IWebhookResponseData> {
const req = this.getRequestObject();
const headers = this.getHeaderData() as IDataObject;
const credentials = await this.getCredentials('wiseApi') as IDataObject;
if (headers['x-test-notification'] === 'true') {
const res = this.getResponseObject();
res.status(200).end();
return {
noWebhookResponse: true,
};
}
const signature = headers['x-signature'] as string;
const publicKey = (credentials.environment === 'test') ? testPublicKey : livePublicKey as string;
//@ts-ignore
const sig = createVerify('RSA-SHA1').update(req.rawBody);
const verified = sig.verify(
publicKey,
signature,
'base64',
);
if (verified === false) {
return {};
}
return {
workflowData: [
this.helpers.returnJsonArray(req.body),
],
};
}
}