-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwebhooks.js
More file actions
131 lines (112 loc) · 4.54 KB
/
webhooks.js
File metadata and controls
131 lines (112 loc) · 4.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
'use strict';
(() => {
var util = require('util');
var lib = require('./lib');
var enumObjectType = require('integration-common/api-wrappers').OBJECT_TYPE;
var headerPatterns = {
'x-rpm-instanceid': /^\d+$/,
'x-rpm-subscriber': /^\d+$/,
'user-agent': /^RPM-Webhook$/,
'content-type': /^application\/json/
};
function validateHeaders(headers) {
console.log('validateHeaders()');
for (var key in headerPatterns) {
var value = headers[key];
if (!headerPatterns[key].test(value)) {
throw util.format('Invalid header %s=%s', key, value);
}
}
}
function createRpmWebHookCallback(secret, callback) {
return function (req, res) {
var body;
try {
validateHeaders(req.headers);
validateSignature(req.headers['x-rpm-signature'], req.body, secret);
body = JSON.parse(req.body);
validateWebHooksRequest(body);
body.time = new Date();
} catch (err) {
console.error('Validation error:', err);
res.status(400).send(err);
return;
}
res.send();
body.InstanceID = req.headers['x-rpm-instanceid'];
body.Instance = req.headers['x-rpm-instance'];
body.Subscriber = req.headers['x-rpm-subscriber'];
if (typeof callback === 'function') {
callback(body, req);
}
};
}
exports.createRpmWebHookCallback = createRpmWebHookCallback;
exports.start = function (config, callback) {
return lib.startPostServer(config, createRpmWebHookCallback(config.signSecret, callback));
};
function WebHooksRequestData(processId, formId, eventName, statusId) {
this.ObjectID = formId;
this.ParentID = processId;
this.EventName = eventName;
this.RequestID = ++WebHooksRequestData.prototype.RequestId;
this.ObjectType = enumObjectType.Form;
this.ParentType = enumObjectType.PMTemplate;
if (statusId) {
this.StatusID = statusId;
}
validateWebHooksRequest(this);
}
WebHooksRequestData.prototype.RequestId = 0;
exports.WebHooksRequestData = WebHooksRequestData;
exports.EVENT_FORM_START = 'form.start';
exports.EVENT_FORM_EDIT = 'form.edit';
exports.EVENT_FORM_TRASH = 'form.trash';
exports.EVENT_FORM_RESTORE = 'form.restore';
var EVENT_NAMES = [
exports.EVENT_FORM_START,
exports.EVENT_FORM_EDIT,
exports.EVENT_FORM_TRASH,
exports.EVENT_FORM_RESTORE
];
function isWebHooksRequest(obj) {
return typeof obj === 'object' &&
typeof obj.ObjectID === 'number' &&
typeof obj.ParentID === 'number' &&
(!obj.StatusID || typeof obj.StatusID === 'number') &&
EVENT_NAMES.indexOf(obj.EventName) >= 0 &&
obj.ObjectType === enumObjectType.Form &&
obj.ParentType === enumObjectType.PMTemplate;
}
exports.isWebHooksRequest = isWebHooksRequest;
function validateWebHooksRequest(obj) {
if (!isWebHooksRequest(obj)) {
throw 'Not a WebHooksRequest';
}
}
exports.WebHooksRequestHeader = function WebHooksRequestHeader(rpmInstanceID, rpmSubscriber, request, secret) {
this['x-rpm-instanceid'] = rpmInstanceID;
this['x-rpm-subscriber'] = rpmSubscriber;
this['user-agent'] = 'RPM-Webhook';
this['content-type'] = 'application/json';
validateHeaders(this);
validateWebHooksRequest(request);
this['x-rpm-signature'] = getSignature(request, secret);
};
var crypto = require('crypto');
function getSignature(data, secret) {
if (secret === undefined) {
throw new Error(util.format('Signature secret is missing'));
}
var hmac = crypto.createHmac('sha256', secret);
hmac.update(typeof data === 'object' ? JSON.stringify(data) : '' + data);
return hmac.digest('hex');
}
function validateSignature(signRecieved, data, secret) {
console.log('validateSignature()');
var signCalculated = getSignature(data, secret);
if (signCalculated !== signRecieved) {
throw new Error(util.format('Wrong signature. Calculated: %s, recieved: %s', signCalculated, signRecieved));
}
}
})();