nodebb-plugin-webhooks 1.1.5 → 2.0.0
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/index.js +27 -26
- package/package.json +6 -8
- package/public/admin.js +3 -3
- package/public/templates/admin/plugins/webhooks.tpl +63 -56
package/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
const
|
|
5
|
-
const
|
|
4
|
+
const https = require('https');
|
|
5
|
+
const axios = require('axios');
|
|
6
6
|
const crypto = require('crypto');
|
|
7
7
|
|
|
8
8
|
const winston = require.main.require('winston');
|
|
@@ -18,17 +18,16 @@ const plugin = module.exports;
|
|
|
18
18
|
let hooks = [];
|
|
19
19
|
|
|
20
20
|
plugin.init = async function (params) {
|
|
21
|
-
routeHelpers.setupAdminPageRoute(params.router, '/admin/plugins/webhooks',
|
|
21
|
+
routeHelpers.setupAdminPageRoute(params.router, '/admin/plugins/webhooks', renderAdmin);
|
|
22
22
|
hooks = await getHooks();
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
async function renderAdmin(req, res
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
25
|
+
async function renderAdmin(req, res) {
|
|
26
|
+
const hooks = await getHooks();
|
|
27
|
+
res.render('admin/plugins/webhooks', {
|
|
28
|
+
title: 'Webhooks',
|
|
29
|
+
hooks: hooks,
|
|
30
|
+
});
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
async function getHooks() {
|
|
@@ -40,8 +39,8 @@ plugin.onHookFired = async function (hookData) {
|
|
|
40
39
|
const { secret } = await meta.settings.get('webhooks');
|
|
41
40
|
hookData = cleanPayload(hookData);
|
|
42
41
|
|
|
43
|
-
|
|
44
|
-
if (hook.name === hookData.hook) {
|
|
42
|
+
for (const hook of hooks) {
|
|
43
|
+
if (hook && hook.name === hookData.hook) {
|
|
45
44
|
let signature;
|
|
46
45
|
if (secret) {
|
|
47
46
|
const hash = crypto.createHmac('sha1', secret);
|
|
@@ -50,7 +49,7 @@ plugin.onHookFired = async function (hookData) {
|
|
|
50
49
|
}
|
|
51
50
|
await makeRequest(hook.endpoint, hookData, signature);
|
|
52
51
|
}
|
|
53
|
-
}
|
|
52
|
+
}
|
|
54
53
|
};
|
|
55
54
|
|
|
56
55
|
function cleanPayload(data) {
|
|
@@ -73,20 +72,22 @@ async function makeRequest(endpoint, hookData, signature) {
|
|
|
73
72
|
const { noStrictSSL } = await meta.settings.get('webhooks');
|
|
74
73
|
const headers = signature && { 'x-webhook-signature': signature };
|
|
75
74
|
const strictSSL = noStrictSSL !== 'on';
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
75
|
+
const axiosOptions = {
|
|
76
|
+
timeout: 2500,
|
|
77
|
+
maxRedirects: 10,
|
|
78
|
+
headers,
|
|
79
|
+
responseType: 'json',
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
if (!strictSSL) {
|
|
83
|
+
axiosOptions.httpsAgent = new https.Agent({
|
|
84
|
+
rejectUnauthorized: false,
|
|
86
85
|
});
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
const { status, data } = await axios.post(endpoint, hookData, )
|
|
89
|
+
if (status !== 200) {
|
|
90
|
+
winston.error(`[nodebb-plugin-webhooks] ${status} ${data}`);
|
|
90
91
|
}
|
|
91
92
|
} catch (e) {
|
|
92
93
|
winston.error(`[nodebb-plugin-webhooks] ${e.message}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nodebb-plugin-webhooks",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "A Plugin that pings end points when a hook is triggered",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -18,16 +18,14 @@
|
|
|
18
18
|
"author": "Baris Usakli <baris@nodebb.org>",
|
|
19
19
|
"license": "MIT",
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"
|
|
22
|
-
"request": "2.88.0",
|
|
23
|
-
"request-promise-native": "^1.0.9"
|
|
21
|
+
"axios": "1.6.2"
|
|
24
22
|
},
|
|
25
23
|
"devDependencies": {
|
|
26
|
-
"eslint": "
|
|
27
|
-
"eslint-config-
|
|
28
|
-
"eslint-plugin-import": "2.
|
|
24
|
+
"eslint": "8.55.0",
|
|
25
|
+
"eslint-config-nodebb": "0.2.1",
|
|
26
|
+
"eslint-plugin-import": "2.29.0"
|
|
29
27
|
},
|
|
30
28
|
"nbbpm": {
|
|
31
|
-
"compatibility": "^
|
|
29
|
+
"compatibility": "^3.2.0"
|
|
32
30
|
}
|
|
33
31
|
}
|
package/public/admin.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
|
-
define('admin/plugins/webhooks', ['settings'], function (settings) {
|
|
5
|
+
define('admin/plugins/webhooks', ['settings', 'alerts'], function (settings, alerts) {
|
|
6
6
|
var WebHooks = {};
|
|
7
7
|
|
|
8
8
|
WebHooks.init = function () {
|
|
@@ -30,12 +30,12 @@ define('admin/plugins/webhooks', ['settings'], function (settings) {
|
|
|
30
30
|
settings.save('webhooks', $('.webhooks-settings'), err => (!err ? resolve() : reject(err)));
|
|
31
31
|
}),
|
|
32
32
|
]).then(() => {
|
|
33
|
-
|
|
33
|
+
alerts.alert({
|
|
34
34
|
type: 'success',
|
|
35
35
|
alert_id: 'webhooks-saved',
|
|
36
36
|
title: 'Settings Saved',
|
|
37
37
|
});
|
|
38
|
-
}).catch(
|
|
38
|
+
}).catch(alerts.error);
|
|
39
39
|
});
|
|
40
40
|
|
|
41
41
|
$('#hooks-parent').on('click', '.hook-remove', function () {
|
|
@@ -1,64 +1,71 @@
|
|
|
1
|
-
<
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
<label for="secret">Signature Verification Secret</label>
|
|
7
|
-
<input type="text" id="secret" name="secret" title="Signature Verification Secret" class="form-control" placeholder="mye3cr37p@55w0r[)">
|
|
8
|
-
<p class="help-block">
|
|
9
|
-
If set, then a header <code>x-webhook-signature</code> will be sent with the web hook. The value of this header is a `sha1` HMAC of the payload. To verify that the payload sender is authenticated, run the HMAC with this shared secret and ensure the hashes match.
|
|
10
|
-
</p>
|
|
11
|
-
</div>
|
|
1
|
+
<div class="acp-page-container">
|
|
2
|
+
<!-- IMPORT admin/partials/settings/header.tpl -->
|
|
3
|
+
|
|
4
|
+
<div class="row m-0">
|
|
5
|
+
<div id="spy-container" class="col-12 px-0 mb-4" tabindex="0">
|
|
12
6
|
|
|
13
|
-
<
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
<
|
|
7
|
+
<form role="form" class="webhooks-settings">
|
|
8
|
+
<h5 class="fw-bold tracking-tight settings-header">Security</h5>
|
|
9
|
+
|
|
10
|
+
<div class="mb-3">
|
|
11
|
+
<label class="form-label" for="secret">Signature Verification Secret</label>
|
|
12
|
+
<input type="text" id="secret" name="secret" title="Signature Verification Secret" class="form-control" placeholder="mye3cr37p@55w0r[)">
|
|
13
|
+
<p class="form-text">
|
|
14
|
+
If set, then a header <code>x-webhook-signature</code> will be sent with the web hook. The value of this header is a `sha1` HMAC of the payload. To verify that the payload sender is authenticated, run the HMAC with this shared secret and ensure the hashes match.
|
|
15
|
+
</p>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div class="mb-3">
|
|
19
|
+
<div class="form-check form-switch">
|
|
20
|
+
<input class="form-check-input" id="noStrictSSL" type="checkbox" name="noStrictSSL" />
|
|
21
|
+
<label class="form-check-label" for="noStrictSSL">Disable strict verification of SSL certificates</label>
|
|
22
|
+
</div>
|
|
23
|
+
<p class="form-text">
|
|
18
24
|
This is helpful if you are testing with a self-signed certificate. It is <strong>not recommended</strong> for you to leave this option checked in production.
|
|
19
25
|
</p>
|
|
20
|
-
</
|
|
21
|
-
</
|
|
22
|
-
</div>
|
|
23
|
-
</div>
|
|
24
|
-
</form>
|
|
26
|
+
</div>
|
|
27
|
+
</form>
|
|
25
28
|
|
|
26
|
-
<div class="row">
|
|
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
|
-
|
|
29
|
+
<div class="row">
|
|
30
|
+
<div class="col-12">
|
|
31
|
+
<h5 class="fw-bold tracking-tight settings-header">Webhooks</h5>
|
|
32
|
+
<p>Click <a target="_blank" href="https://github.com/NodeBB/NodeBB/wiki/Hooks">here</a> for available hooks.</p>
|
|
33
|
+
<div class="table-responsive">
|
|
34
|
+
<table class="table">
|
|
35
|
+
<thead>
|
|
36
|
+
<tr>
|
|
37
|
+
<th>Hook Name</th>
|
|
38
|
+
<th>End Point</th>
|
|
39
|
+
<th></th>
|
|
40
|
+
</tr>
|
|
41
|
+
</thead>
|
|
42
|
+
<tbody id="hooks-parent">
|
|
43
|
+
{{{ each hooks }}}
|
|
44
|
+
<tr>
|
|
45
|
+
<td class="col-md-3">
|
|
46
|
+
<input class="hook-name form-control" value="{hooks.name}" />
|
|
47
|
+
</td>
|
|
48
|
+
<td class="col-md-8">
|
|
49
|
+
<input class="hook-endpoint form-control" value="{hooks.endpoint}" />
|
|
50
|
+
</td>
|
|
51
|
+
<td class="col-md-1">
|
|
52
|
+
<button class="hook-remove btn btn-danger">Remove</button>
|
|
53
|
+
</td>
|
|
54
|
+
</tr>
|
|
55
|
+
{{{ end }}}
|
|
56
|
+
</tbody>
|
|
57
|
+
</table>
|
|
58
|
+
</div>
|
|
59
|
+
<div class="text-end">
|
|
60
|
+
<button id="add-hook" class="btn btn-success"><i class="fa fa-plus"></i> Add Hook</button>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
58
64
|
</div>
|
|
59
65
|
</div>
|
|
60
66
|
</div>
|
|
61
67
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|