@limetech/n8n-nodes-lime 0.3.6 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/credentials/LimeCrmApi.credentials.ts +13 -0
- package/dist/credentials/LimeCrmApi.credentials.js +12 -0
- package/dist/credentials/LimeCrmApi.credentials.js.map +1 -1
- package/dist/nodes/lime-crm/LimeCrmTrigger.node.js +17 -2
- package/dist/nodes/lime-crm/LimeCrmTrigger.node.js.map +1 -1
- package/dist/nodes/lime-crm/commons/hmac.d.ts +1 -0
- package/dist/nodes/lime-crm/commons/hmac.js +11 -0
- package/dist/nodes/lime-crm/commons/hmac.js.map +1 -0
- package/dist/nodes/lime-crm/commons/webhook.d.ts +3 -0
- package/dist/nodes/lime-crm/commons/webhook.js.map +1 -1
- package/dist/nodes/lime-crm/resources/erpConnector/index.d.ts +2 -2
- package/dist/nodes/lime-crm/resources/limeObject/index.js +6 -6
- package/dist/nodes/lime-crm/resources/limeObject/index.js.map +1 -1
- package/dist/nodes/lime-crm/resources/limeObject/operations/fetchMany.operation.d.ts +9 -0
- package/dist/nodes/lime-crm/resources/limeObject/operations/fetchMany.operation.js +103 -0
- package/dist/nodes/lime-crm/resources/limeObject/operations/fetchMany.operation.js.map +1 -0
- package/dist/nodes/lime-crm/resources/limeType/index.d.ts +3 -3
- package/dist/nodes/lime-crm/transport/index.d.ts +1 -1
- package/dist/nodes/lime-crm/transport/index.js +2 -2
- package/dist/nodes/lime-crm/transport/index.js.map +1 -1
- package/dist/nodes/lime-crm/transport/limeobjects.d.ts +1 -1
- package/dist/nodes/lime-crm/transport/limeobjects.js +5 -3
- package/dist/nodes/lime-crm/transport/limeobjects.js.map +1 -1
- package/dist/nodes/lime-crm/transport/webhooks.d.ts +2 -1
- package/dist/nodes/lime-crm/transport/webhooks.js +1 -0
- package/dist/nodes/lime-crm/transport/webhooks.js.map +1 -1
- package/dist/package.json +2 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/nodes/lime-crm/LimeCrmTrigger.node.ts +29 -3
- package/nodes/lime-crm/commons/hmac.ts +13 -0
- package/nodes/lime-crm/commons/webhook.ts +4 -0
- package/nodes/lime-crm/resources/limeObject/index.ts +6 -6
- package/nodes/lime-crm/resources/limeObject/operations/{search.operation.ts → fetchMany.operation.ts} +11 -11
- package/nodes/lime-crm/transport/index.ts +1 -1
- package/nodes/lime-crm/transport/limeobjects.ts +8 -6
- package/nodes/lime-crm/transport/webhooks.ts +3 -1
- package/package.json +2 -1
|
@@ -19,6 +19,8 @@ import {
|
|
|
19
19
|
listSubscriptionsWithExistingData,
|
|
20
20
|
} from './transport';
|
|
21
21
|
|
|
22
|
+
import { verifyHmac } from './commons/hmac';
|
|
23
|
+
|
|
22
24
|
export class LimeCrmTrigger implements INodeType {
|
|
23
25
|
description: INodeTypeDescription = {
|
|
24
26
|
displayName: 'Lime CRM Trigger',
|
|
@@ -174,9 +176,17 @@ export class LimeCrmTrigger implements INodeType {
|
|
|
174
176
|
}
|
|
175
177
|
|
|
176
178
|
if (existingSubscriptionResponse.data.length === 0) {
|
|
179
|
+
const credentials = await this.getCredentials(
|
|
180
|
+
LIME_CRM_API_CREDENTIAL_KEY
|
|
181
|
+
);
|
|
182
|
+
const webhookCreateData = {
|
|
183
|
+
...webhook,
|
|
184
|
+
secret: credentials.webhookSecret as string,
|
|
185
|
+
};
|
|
186
|
+
|
|
177
187
|
const createSubscriptionResponse = await createSubscription(
|
|
178
188
|
this,
|
|
179
|
-
|
|
189
|
+
webhookCreateData
|
|
180
190
|
);
|
|
181
191
|
|
|
182
192
|
if (!createSubscriptionResponse.success) {
|
|
@@ -238,7 +248,24 @@ export class LimeCrmTrigger implements INodeType {
|
|
|
238
248
|
Logger.info('Webhook received. Starting webhook processing...', {
|
|
239
249
|
...webhook.context,
|
|
240
250
|
});
|
|
251
|
+
const credentials = await this.getCredentials(
|
|
252
|
+
LIME_CRM_API_CREDENTIAL_KEY
|
|
253
|
+
);
|
|
254
|
+
const webhookSecret = credentials.webhookSecret as string;
|
|
255
|
+
const requestObject = this.getRequestObject();
|
|
256
|
+
const headerData = this.getHeaderData();
|
|
241
257
|
const bodyData = this.getBodyData();
|
|
258
|
+
const limeSignature = headerData['x-lime-signature'] as string;
|
|
259
|
+
|
|
260
|
+
if (
|
|
261
|
+
(webhookSecret || limeSignature) &&
|
|
262
|
+
!verifyHmac(webhookSecret, requestObject.rawBody, limeSignature)
|
|
263
|
+
) {
|
|
264
|
+
throw new NodeOperationError(
|
|
265
|
+
this.getNode(),
|
|
266
|
+
'Webhook authentication failed, secret keys do not match!'
|
|
267
|
+
);
|
|
268
|
+
}
|
|
242
269
|
|
|
243
270
|
if (!bodyData || !bodyData.event || !bodyData.body) {
|
|
244
271
|
Logger.warn('Webhook data is invalid. Missing event or body', {
|
|
@@ -251,10 +278,9 @@ export class LimeCrmTrigger implements INodeType {
|
|
|
251
278
|
}
|
|
252
279
|
|
|
253
280
|
const returnData: IDataObject[] = [];
|
|
254
|
-
|
|
255
281
|
returnData.push({
|
|
256
282
|
body: bodyData,
|
|
257
|
-
headers:
|
|
283
|
+
headers: headerData,
|
|
258
284
|
query: this.getQueryData(),
|
|
259
285
|
});
|
|
260
286
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createHmac } from 'node:crypto';
|
|
2
|
+
|
|
3
|
+
function _generateHmac(key: string, data: Buffer): string {
|
|
4
|
+
return 'sha256=' + createHmac('sha256', key).update(data).digest('hex');
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function verifyHmac(
|
|
8
|
+
key: string,
|
|
9
|
+
data: Buffer,
|
|
10
|
+
comparedHmac: string
|
|
11
|
+
): boolean {
|
|
12
|
+
return _generateHmac(key, data) === comparedHmac;
|
|
13
|
+
}
|
|
@@ -17,6 +17,10 @@ export interface Webhook {
|
|
|
17
17
|
name: string;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
export interface CreateWebhook extends Webhook {
|
|
21
|
+
secret?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
20
24
|
function _getEvents(hookData: WebhookFunctions): string[] {
|
|
21
25
|
const eventData = hookData.getNodeParameter('events', []) as {
|
|
22
26
|
event: Array<{
|
|
@@ -8,7 +8,7 @@ import * as create from './operations/create.operation';
|
|
|
8
8
|
import * as get from './operations/get.operation';
|
|
9
9
|
import * as update from './operations/update.operation';
|
|
10
10
|
import * as delete_ from './operations/delete.operation';
|
|
11
|
-
import * as
|
|
11
|
+
import * as fetchMany from './operations/fetchMany.operation';
|
|
12
12
|
|
|
13
13
|
import { LIMEOBJECT_RESOURCE } from '../../commons';
|
|
14
14
|
|
|
@@ -28,16 +28,16 @@ export const limeObjectFields: INodeProperties[] = [
|
|
|
28
28
|
get.description,
|
|
29
29
|
update.description,
|
|
30
30
|
delete_.description,
|
|
31
|
-
|
|
31
|
+
fetchMany.description,
|
|
32
32
|
],
|
|
33
|
-
default: '
|
|
33
|
+
default: 'fetchMany',
|
|
34
34
|
},
|
|
35
35
|
|
|
36
36
|
...create.properties,
|
|
37
37
|
...get.properties,
|
|
38
38
|
...update.properties,
|
|
39
39
|
...delete_.properties,
|
|
40
|
-
...
|
|
40
|
+
...fetchMany.properties,
|
|
41
41
|
];
|
|
42
42
|
|
|
43
43
|
export async function limeObjectOperations(
|
|
@@ -56,8 +56,8 @@ export async function limeObjectOperations(
|
|
|
56
56
|
if (operation === 'delete') {
|
|
57
57
|
return await delete_.execute.call(this, i);
|
|
58
58
|
}
|
|
59
|
-
if (operation === '
|
|
60
|
-
return await
|
|
59
|
+
if (operation === 'fetchMany') {
|
|
60
|
+
return await fetchMany.execute.call(this, i);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
return null;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { IExecuteFunctions, INodeProperties } from 'n8n-workflow';
|
|
2
|
-
import {
|
|
2
|
+
import { fetchManyLimeObjects } from '../../../transport';
|
|
3
3
|
import { LIMEOBJECT_RESOURCE } from '../../../commons';
|
|
4
4
|
|
|
5
5
|
export const description = {
|
|
6
|
-
name: '
|
|
7
|
-
value: '
|
|
8
|
-
description: '
|
|
9
|
-
action: '
|
|
6
|
+
name: 'Fetch many',
|
|
7
|
+
value: 'fetchMany',
|
|
8
|
+
description: 'Fetch many Lime objects',
|
|
9
|
+
action: 'Fetch many objects',
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
export const properties: INodeProperties[] = [
|
|
@@ -23,7 +23,7 @@ export const properties: INodeProperties[] = [
|
|
|
23
23
|
displayOptions: {
|
|
24
24
|
show: {
|
|
25
25
|
resource: [LIMEOBJECT_RESOURCE],
|
|
26
|
-
operation: ['
|
|
26
|
+
operation: ['fetchMany'],
|
|
27
27
|
},
|
|
28
28
|
},
|
|
29
29
|
},
|
|
@@ -36,7 +36,7 @@ export const properties: INodeProperties[] = [
|
|
|
36
36
|
displayOptions: {
|
|
37
37
|
show: {
|
|
38
38
|
resource: [LIMEOBJECT_RESOURCE],
|
|
39
|
-
operation: ['
|
|
39
|
+
operation: ['fetchMany'],
|
|
40
40
|
},
|
|
41
41
|
},
|
|
42
42
|
},
|
|
@@ -54,7 +54,7 @@ export const properties: INodeProperties[] = [
|
|
|
54
54
|
displayOptions: {
|
|
55
55
|
show: {
|
|
56
56
|
resource: [LIMEOBJECT_RESOURCE],
|
|
57
|
-
operation: ['
|
|
57
|
+
operation: ['fetchMany'],
|
|
58
58
|
},
|
|
59
59
|
},
|
|
60
60
|
},
|
|
@@ -70,7 +70,7 @@ export const properties: INodeProperties[] = [
|
|
|
70
70
|
displayOptions: {
|
|
71
71
|
show: {
|
|
72
72
|
resource: [LIMEOBJECT_RESOURCE],
|
|
73
|
-
operation: ['
|
|
73
|
+
operation: ['fetchMany'],
|
|
74
74
|
},
|
|
75
75
|
},
|
|
76
76
|
},
|
|
@@ -86,7 +86,7 @@ export const properties: INodeProperties[] = [
|
|
|
86
86
|
displayOptions: {
|
|
87
87
|
show: {
|
|
88
88
|
resource: [LIMEOBJECT_RESOURCE],
|
|
89
|
-
operation: ['
|
|
89
|
+
operation: ['fetchMany'],
|
|
90
90
|
},
|
|
91
91
|
},
|
|
92
92
|
},
|
|
@@ -100,7 +100,7 @@ export async function execute(this: IExecuteFunctions, i: number) {
|
|
|
100
100
|
const offset = this.getNodeParameter('offset', i, 0) as number;
|
|
101
101
|
const options = this.getNodeParameter('options', i, {});
|
|
102
102
|
|
|
103
|
-
return await
|
|
103
|
+
return await fetchManyLimeObjects(
|
|
104
104
|
this,
|
|
105
105
|
limeType,
|
|
106
106
|
searchField,
|
|
@@ -4,7 +4,7 @@ import { NodeResponse } from '../../nodeResponse';
|
|
|
4
4
|
|
|
5
5
|
const LIMEOBJECT_URL = '/api/v1/limeobject/';
|
|
6
6
|
|
|
7
|
-
interface
|
|
7
|
+
interface FetchManyLimeObjectsApiResponse {
|
|
8
8
|
_embedded: {
|
|
9
9
|
limeobjects: Array<object>;
|
|
10
10
|
};
|
|
@@ -103,7 +103,7 @@ async function _searchLimeObjectWithLimit(
|
|
|
103
103
|
limit: number,
|
|
104
104
|
offset: number,
|
|
105
105
|
qs: IDataObject
|
|
106
|
-
): Promise<NodeResponse<
|
|
106
|
+
): Promise<NodeResponse<FetchManyLimeObjectsApiResponse>> {
|
|
107
107
|
const returnData = [];
|
|
108
108
|
let hasMoreData = true;
|
|
109
109
|
let currentOffset = Math.max(0, offset);
|
|
@@ -113,7 +113,7 @@ async function _searchLimeObjectWithLimit(
|
|
|
113
113
|
qs._limit = Math.min(limit, pageLimit);
|
|
114
114
|
qs._offset = currentOffset;
|
|
115
115
|
|
|
116
|
-
const response = await callLimeApi<
|
|
116
|
+
const response = await callLimeApi<FetchManyLimeObjectsApiResponse>(
|
|
117
117
|
nodeContext,
|
|
118
118
|
'GET',
|
|
119
119
|
url,
|
|
@@ -143,7 +143,7 @@ async function _searchLimeObjectWithLimit(
|
|
|
143
143
|
};
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
export async function
|
|
146
|
+
export async function fetchManyLimeObjects(
|
|
147
147
|
nodeContext: IAllExecuteFunctions,
|
|
148
148
|
limeType: string,
|
|
149
149
|
searchField: string,
|
|
@@ -169,7 +169,7 @@ export async function searchLimeObject(
|
|
|
169
169
|
qs
|
|
170
170
|
);
|
|
171
171
|
} else {
|
|
172
|
-
response = await callLimeApi<
|
|
172
|
+
response = await callLimeApi<FetchManyLimeObjectsApiResponse>(
|
|
173
173
|
nodeContext,
|
|
174
174
|
'GET',
|
|
175
175
|
url,
|
|
@@ -186,7 +186,9 @@ export async function searchLimeObject(
|
|
|
186
186
|
};
|
|
187
187
|
}
|
|
188
188
|
return {
|
|
189
|
-
|
|
189
|
+
success: response.success,
|
|
190
|
+
error: response.error,
|
|
191
|
+
status: response.status,
|
|
190
192
|
metadata: {
|
|
191
193
|
...response.metadata,
|
|
192
194
|
limeType: limeType,
|
|
@@ -2,6 +2,7 @@ import { Webhook } from '../commons';
|
|
|
2
2
|
import { callLimeApi } from '.';
|
|
3
3
|
import { IAllExecuteFunctions } from 'n8n-workflow';
|
|
4
4
|
import { NodeResponse } from '../../nodeResponse';
|
|
5
|
+
import { CreateWebhook } from '../commons/webhook';
|
|
5
6
|
|
|
6
7
|
const SUBSCRIPTION_URL = 'api/v1/subscription/';
|
|
7
8
|
|
|
@@ -39,13 +40,14 @@ export async function listSubscriptionsWithExistingData(
|
|
|
39
40
|
|
|
40
41
|
export async function createSubscription(
|
|
41
42
|
nodeContext: IAllExecuteFunctions,
|
|
42
|
-
webhook:
|
|
43
|
+
webhook: CreateWebhook
|
|
43
44
|
): Promise<NodeResponse<ApiResponseWebhook>> {
|
|
44
45
|
return await callLimeApi(nodeContext, 'POST', SUBSCRIPTION_URL, {
|
|
45
46
|
body: {
|
|
46
47
|
events: webhook.events,
|
|
47
48
|
target_url: webhook.url,
|
|
48
49
|
name: webhook.name,
|
|
50
|
+
secret: webhook.secret,
|
|
49
51
|
},
|
|
50
52
|
});
|
|
51
53
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@limetech/n8n-nodes-lime",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.8",
|
|
4
4
|
"description": "n8n node to connect to Lime CRM",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "index.js",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
],
|
|
31
31
|
"nodes": [
|
|
32
32
|
"dist/nodes/lime-crm/LimeCrmNode.node.js",
|
|
33
|
+
"dist/nodes/lime-crm/LimeCrmTrigger.node.js",
|
|
33
34
|
"dist/nodes/fortnox/Fortnox.node.js",
|
|
34
35
|
"dist/nodes/fortnox/FortnoxTrigger.node.js"
|
|
35
36
|
]
|