-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathindex.js
More file actions
114 lines (95 loc) · 2.99 KB
/
Copy pathindex.js
File metadata and controls
114 lines (95 loc) · 2.99 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
'use strict';
const crypto = require('crypto');
const winston = nodebb.require('winston');
const db = nodebb.require('./src/database');
const meta = nodebb.require('./src/meta');
const request = nodebb.require('./src/request');
const routeHelpers = nodebb.require('./src/routes/helpers');
const apiHelpers = nodebb.require('./src/api/helpers');
const socketAdmin = nodebb.require('./src/socket.io/admin');
const pubsub = nodebb.require('./src/pubsub');
const plugin = module.exports;
let hooks = [];
plugin.init = async function (params) {
routeHelpers.setupAdminPageRoute(params.router, '/admin/plugins/webhooks', renderAdmin);
hooks = await getHooks();
};
async function renderAdmin(req, res) {
const hooks = await getHooks();
res.render('admin/plugins/webhooks', {
title: 'Webhooks',
hooks: hooks,
});
}
async function getHooks() {
const data = await db.get('nodebb-plugin-webhooks');
return JSON.parse(data || '[]');
}
plugin.onHookFired = async function (hookData) {
const { secret } = await meta.settings.get('webhooks');
hookData = cleanPayload(hookData);
for (const hook of hooks) {
if (hook && hook.name === hookData.hook) {
let signature;
if (secret) {
const hash = crypto.createHmac('sha1', secret);
hash.update(JSON.stringify(hookData));
signature = `sha1=${hash.digest('hex')}`;
}
// eslint-disable-next-line no-await-in-loop
await makeRequest(hook.endpoint, hookData, signature);
}
}
};
function cleanPayload(data) {
if (data.params) {
['req', 'socket'].forEach((prop) => {
if (data.params.hasOwnProperty(prop)) {
data.params[prop] = apiHelpers.buildReqObject(data.params[prop]);
if (data.params[prop] && data.params[prop].headers && data.params[prop].headers.hasOwnProperty('cookie')) {
delete data.params[prop].headers.cookie;
}
}
});
if (data.params.hasOwnProperty('res')) {
delete data.params.res;
}
}
return data;
}
async function makeRequest(endpoint, hookData, signature) {
const { noStrictSSL } = await meta.settings.get('webhooks');
const headers = signature ? { 'x-webhook-signature': signature } : undefined;
const strictSSL = noStrictSSL !== 'on';
try {
const { body, response } = await request.post(endpoint, {
body: hookData,
headers,
timeout: 2500,
rejectUnauthorized: strictSSL,
});
if (response.status !== 200) {
winston.error(`[nodebb-plugin-webhooks] ${response.status} ${JSON.stringify(body)}`);
}
} catch (e) {
winston.error(`[nodebb-plugin-webhooks] ${e.message}`);
}
}
plugin.admin = {};
plugin.admin.menu = function (menu, callback) {
menu.plugins.push({
route: '/plugins/webhooks',
icon: 'fa-chart-bar',
name: 'Web Hooks',
});
setImmediate(callback, null, menu);
};
socketAdmin.plugins.webhooks = {};
socketAdmin.plugins.webhooks.save = async function (socket, data) {
await db.set('nodebb-plugin-webhooks', JSON.stringify(data));
hooks = data;
pubsub.publish('nodebb-plugin-webhooks:save', data);
};
pubsub.on('nodebb-plugin-webhooks:save', function (data) {
hooks = data;
});