nodebb-plugin-session-sharing 7.1.7 → 7.2.1
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/eslint.config.mjs +10 -0
- package/lib/controllers.js +7 -4
- package/library.js +47 -32
- package/package.json +7 -7
- package/static/lib/admin.js +0 -2
- package/static/lib/main.js +0 -2
- package/static/templates/admin/plugins/session-sharing.tpl +76 -58
- package/test/index.js +0 -1
- package/.eslintrc +0 -137
package/lib/controllers.js
CHANGED
|
@@ -6,19 +6,22 @@ const Controllers = {};
|
|
|
6
6
|
|
|
7
7
|
Controllers.renderAdminPage = async (req, res) => {
|
|
8
8
|
const groupData = await groups.getGroupsFromSet('groups:visible:createtime', 0, -1);
|
|
9
|
-
res.render('admin/plugins/session-sharing', {
|
|
9
|
+
res.render('admin/plugins/session-sharing', {
|
|
10
|
+
title: 'Session Sharing',
|
|
11
|
+
groups: groupData,
|
|
12
|
+
});
|
|
10
13
|
};
|
|
11
14
|
|
|
12
15
|
Controllers.retrieveUser = async (req, res) => {
|
|
13
16
|
const main = module.parent.exports;
|
|
14
17
|
const remoteId = req.query.id;
|
|
15
|
-
|
|
18
|
+
|
|
16
19
|
if (!remoteId) {
|
|
17
20
|
return res.status(400).json({
|
|
18
21
|
error: 'no-id-supplied',
|
|
19
22
|
});
|
|
20
23
|
}
|
|
21
|
-
|
|
24
|
+
|
|
22
25
|
try {
|
|
23
26
|
const userObj = await main.getUser(remoteId);
|
|
24
27
|
|
|
@@ -42,7 +45,7 @@ Controllers.process = async (req, res) => {
|
|
|
42
45
|
error: 'no-token-provided',
|
|
43
46
|
});
|
|
44
47
|
}
|
|
45
|
-
|
|
48
|
+
|
|
46
49
|
try {
|
|
47
50
|
const uid = await main.process(req.body.token);
|
|
48
51
|
|
package/library.js
CHANGED
|
@@ -14,6 +14,7 @@ const groups = require.main.require('./src/groups');
|
|
|
14
14
|
const SocketPlugins = require.main.require('./src/socket.io/plugins');
|
|
15
15
|
const db = require.main.require('./src/database');
|
|
16
16
|
const plugins = require.main.require('./src/plugins');
|
|
17
|
+
const routeHelpers = require.main.require('./src/routes/helpers');
|
|
17
18
|
|
|
18
19
|
const controllers = require('./lib/controllers');
|
|
19
20
|
const nbbAuthController = require.main.require('./src/controllers/authentication');
|
|
@@ -61,11 +62,9 @@ payloadKeys.forEach(function (key) {
|
|
|
61
62
|
plugin.defaults = Object.freeze({ ...plugin.settings });
|
|
62
63
|
|
|
63
64
|
plugin.init = async (params) => {
|
|
64
|
-
|
|
65
|
-
var hostMiddleware = params.middleware;
|
|
65
|
+
const { router } = params;
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
router.get('/api/admin/plugins/session-sharing', controllers.renderAdminPage);
|
|
67
|
+
routeHelpers.setupAdminPageRoute(router, '/plugins/session-sharing', controllers.renderAdminPage);
|
|
69
68
|
|
|
70
69
|
router.get('/api/session-sharing/lookup', controllers.retrieveUser);
|
|
71
70
|
router.post('/api/session-sharing/user', controllers.process);
|
|
@@ -101,7 +100,9 @@ SocketPlugins.sessionSharing.showUserIds = async (socket, data) => {
|
|
|
101
100
|
throw new Error('no-uids-supplied');
|
|
102
101
|
}
|
|
103
102
|
|
|
104
|
-
return Promise.all(
|
|
103
|
+
return Promise.all(
|
|
104
|
+
uids.map(async uid => db.getSortedSetRangeByScore(plugin.settings.name + ':uid', 0, -1, uid, uid))
|
|
105
|
+
);
|
|
105
106
|
};
|
|
106
107
|
|
|
107
108
|
SocketPlugins.sessionSharing.findUserByRemoteId = async (socket, data) => {
|
|
@@ -115,7 +116,7 @@ SocketPlugins.sessionSharing.findUserByRemoteId = async (socket, data) => {
|
|
|
115
116
|
/* End Websocket Listeners */
|
|
116
117
|
|
|
117
118
|
/*
|
|
118
|
-
*
|
|
119
|
+
* Given a remoteId, show user data
|
|
119
120
|
*/
|
|
120
121
|
plugin.getUser = async (remoteId) => {
|
|
121
122
|
const uid = await db.sortedSetScore(plugin.settings.name + ':uid', remoteId);
|
|
@@ -151,7 +152,7 @@ plugin.normalizePayload = async (payload) => {
|
|
|
151
152
|
|
|
152
153
|
payloadKeys.forEach(function (key) {
|
|
153
154
|
const propName = plugin.settings['payload:' + key];
|
|
154
|
-
if (payload
|
|
155
|
+
if (payload.hasOwnProperty(propName)) {
|
|
155
156
|
userData[key] = payload[propName];
|
|
156
157
|
}
|
|
157
158
|
});
|
|
@@ -160,8 +161,10 @@ plugin.normalizePayload = async (payload) => {
|
|
|
160
161
|
winston.warn('[session-sharing] No user id was given in payload');
|
|
161
162
|
throw new Error('payload-invalid');
|
|
162
163
|
}
|
|
163
|
-
|
|
164
|
-
|
|
164
|
+
const setFullname = userData.hasOwnProperty('fullname') || userData.hasOwnProperty('firstName') || userData.hasOwnProperty('lastName');
|
|
165
|
+
if (setFullname) {
|
|
166
|
+
userData.fullname = (userData.fullname || [userData.firstName, userData.lastName].join(' ')).trim();
|
|
167
|
+
}
|
|
165
168
|
|
|
166
169
|
if (!userData.username) {
|
|
167
170
|
userData.username = userData.fullname;
|
|
@@ -279,7 +282,17 @@ plugin.updateUserProfile = async (uid, userData, isNewUser) => {
|
|
|
279
282
|
winston.debug('[session-sharing] Updating profile fields:', obj);
|
|
280
283
|
obj.uid = uid;
|
|
281
284
|
try {
|
|
285
|
+
const { trustPayloadEmail } = await meta.settings.get('session-sharing');
|
|
286
|
+
let email = '';
|
|
287
|
+
if (trustPayloadEmail === 'on') {
|
|
288
|
+
email = obj.email;
|
|
289
|
+
delete obj.email;
|
|
290
|
+
}
|
|
282
291
|
userObj = await user.updateProfile(uid, obj);
|
|
292
|
+
if (trustPayloadEmail && email) {
|
|
293
|
+
await user.setUserField(uid, 'email', email);
|
|
294
|
+
await user.email.confirmByUid(uid, 0);
|
|
295
|
+
}
|
|
283
296
|
|
|
284
297
|
// If it errors out, not that big of a deal, continue anyway.
|
|
285
298
|
if (!userObj) {
|
|
@@ -303,12 +316,12 @@ plugin.updateUserGroups = async (uid, userData) => {
|
|
|
303
316
|
// Retrieve user groups
|
|
304
317
|
let [userGroups] = await groups.getUserGroupsFromSet('groups:createtime', [uid]);
|
|
305
318
|
// Normalize user group data to just group names
|
|
306
|
-
userGroups = userGroups.map(
|
|
319
|
+
userGroups = userGroups.map(groupObj => groupObj.name);
|
|
307
320
|
|
|
308
321
|
// Build join and leave arrays
|
|
309
|
-
let join = userData.groups.filter(
|
|
322
|
+
let join = userData.groups.filter(name => !userGroups.includes(name));
|
|
310
323
|
if (plugin.settings.syncGroupList === 'on') {
|
|
311
|
-
join = join.filter(
|
|
324
|
+
join = join.filter(group => plugin.settings.syncGroups.includes(group));
|
|
312
325
|
}
|
|
313
326
|
|
|
314
327
|
let leave = userGroups.filter((name) => {
|
|
@@ -320,7 +333,7 @@ plugin.updateUserGroups = async (uid, userData) => {
|
|
|
320
333
|
return !userData.groups.includes(name);
|
|
321
334
|
});
|
|
322
335
|
if (plugin.settings.syncGroupList === 'on') {
|
|
323
|
-
leave = leave.filter(
|
|
336
|
+
leave = leave.filter(group => plugin.settings.syncGroups.includes(group));
|
|
324
337
|
}
|
|
325
338
|
|
|
326
339
|
await executeJoinLeave(uid, join, leave);
|
|
@@ -333,14 +346,14 @@ async function executeJoinLeave(uid, join, leave) {
|
|
|
333
346
|
return;
|
|
334
347
|
}
|
|
335
348
|
|
|
336
|
-
await Promise.all(join.map(
|
|
349
|
+
await Promise.all(join.map(name => groups.join(name, uid)));
|
|
337
350
|
})(),
|
|
338
351
|
(async () => {
|
|
339
352
|
if (plugin.settings.syncGroupLeave !== 'on') {
|
|
340
353
|
return;
|
|
341
354
|
}
|
|
342
355
|
|
|
343
|
-
await Promise.all(leave.map(
|
|
356
|
+
await Promise.all(leave.map(name => groups.leave(name, uid)));
|
|
344
357
|
})(),
|
|
345
358
|
]);
|
|
346
359
|
}
|
|
@@ -385,13 +398,13 @@ plugin.addMiddleware = async function ({ req, res }) {
|
|
|
385
398
|
const hasLoginLock = req.session.hasOwnProperty('loginLock');
|
|
386
399
|
|
|
387
400
|
if (
|
|
388
|
-
!plugin.ready ||
|
|
389
|
-
(plugin.settings.behaviour === 'trust' && hasSession) ||
|
|
401
|
+
!plugin.ready || // plugin not ready
|
|
402
|
+
(plugin.settings.behaviour === 'trust' && hasSession) || // user logged in + "trust" behaviour
|
|
390
403
|
((plugin.settings.behaviour === 'revalidate' || plugin.settings.behaviour === 'update') && hasLoginLock) ||
|
|
391
|
-
req.originalUrl.startsWith(nconf.get('relative_path') + '/api')
|
|
404
|
+
req.originalUrl.startsWith(nconf.get('relative_path') + '/api') // api routes
|
|
392
405
|
) {
|
|
393
406
|
// Let requests through under "update" or "revalidate" behaviour only if they're logging in for the first time
|
|
394
|
-
delete req.session.loginLock;
|
|
407
|
+
delete req.session.loginLock; // remove login lock for "update" or "revalidate" logins
|
|
395
408
|
|
|
396
409
|
return;
|
|
397
410
|
}
|
|
@@ -419,7 +432,9 @@ plugin.addMiddleware = async function ({ req, res }) {
|
|
|
419
432
|
return handleGuest.call(null, req, res);
|
|
420
433
|
}
|
|
421
434
|
|
|
422
|
-
if (Object.keys(req.cookies).length &&
|
|
435
|
+
if (Object.keys(req.cookies).length &&
|
|
436
|
+
req.cookies.hasOwnProperty(plugin.settings.cookieName) &&
|
|
437
|
+
req.cookies[plugin.settings.cookieName].length) {
|
|
423
438
|
try {
|
|
424
439
|
const uid = await plugin.process(req.cookies[plugin.settings.cookieName]);
|
|
425
440
|
if (uid === req.uid) {
|
|
@@ -438,16 +453,16 @@ plugin.addMiddleware = async function ({ req, res }) {
|
|
|
438
453
|
let handleAsGuest = false;
|
|
439
454
|
|
|
440
455
|
switch (error.message) {
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
456
|
+
case 'payload-invalid':
|
|
457
|
+
winston.warn('[session-sharing] The passed-in payload was invalid and could not be processed');
|
|
458
|
+
break;
|
|
459
|
+
case 'no-match':
|
|
460
|
+
winston.info('[session-sharing] Payload valid, but local account not found. Assuming guest.');
|
|
461
|
+
handleAsGuest = true;
|
|
462
|
+
break;
|
|
463
|
+
default:
|
|
464
|
+
winston.warn('[session-sharing] Error encountered while parsing token: ' + error.message);
|
|
465
|
+
break;
|
|
451
466
|
}
|
|
452
467
|
|
|
453
468
|
const data = await plugins.hooks.fire('filter:sessionSharing.error', {
|
|
@@ -590,10 +605,10 @@ plugin.appendTemplate = async (data) => {
|
|
|
590
605
|
|
|
591
606
|
plugin.saveReverseToken = async ({ req, userData: data }) => {
|
|
592
607
|
if (!plugin.ready || !data || plugin.settings.reverseToken !== 'on') {
|
|
593
|
-
return;
|
|
608
|
+
return; // no reverse token if secret not set
|
|
594
609
|
}
|
|
595
610
|
|
|
596
|
-
const res = req
|
|
611
|
+
const { res } = req;
|
|
597
612
|
const userData = await user.getUserFields(data.uid, ['uid', 'username', 'picture', 'reputation', 'postcount', 'banned']);
|
|
598
613
|
userData.groups = (await groups.getUserGroups([data.uid])).pop();
|
|
599
614
|
const token = jwt.sign(userData, plugin.settings.secret);
|
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nodebb-plugin-session-sharing",
|
|
3
|
-
"version": "7.1
|
|
3
|
+
"version": "7.2.1",
|
|
4
4
|
"description": "Allows login sessions from your app to persist in NodeBB",
|
|
5
5
|
"main": "library.js",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/julianlam/nodebb-plugin-session-sharing"
|
|
9
9
|
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"lint": "eslint ."
|
|
12
|
+
},
|
|
10
13
|
"keywords": [
|
|
11
14
|
"nodebb",
|
|
12
15
|
"plugin"
|
|
@@ -21,7 +24,7 @@
|
|
|
21
24
|
},
|
|
22
25
|
"readmeFilename": "README.md",
|
|
23
26
|
"nbbpm": {
|
|
24
|
-
"compatibility": "^3.0.
|
|
27
|
+
"compatibility": "^3.2.0 || ^4.x"
|
|
25
28
|
},
|
|
26
29
|
"husky": {
|
|
27
30
|
"hooks": {
|
|
@@ -38,7 +41,6 @@
|
|
|
38
41
|
"dependencies": {
|
|
39
42
|
"@commitlint/cli": "^9.1.2",
|
|
40
43
|
"async": "^3",
|
|
41
|
-
"eslint": "^7.7.0",
|
|
42
44
|
"jsonwebtoken": "^8.5.1",
|
|
43
45
|
"lint-staged": "^10.0.9",
|
|
44
46
|
"lodash": "^4.17.14"
|
|
@@ -46,10 +48,8 @@
|
|
|
46
48
|
"devDependencies": {
|
|
47
49
|
"@commitlint/cli": "^9.1.2",
|
|
48
50
|
"@commitlint/config-angular": "^7.1.2",
|
|
49
|
-
"eslint": "
|
|
50
|
-
"eslint-config-
|
|
51
|
-
"eslint-config-nodebb": "0.1.1",
|
|
52
|
-
"eslint-plugin-import": "2.x",
|
|
51
|
+
"eslint": "9.26.0",
|
|
52
|
+
"eslint-config-nodebb": "^1.1.4",
|
|
53
53
|
"husky": "^2.4.0",
|
|
54
54
|
"lint-staged": "^10.0.9",
|
|
55
55
|
"request": "^2.88.2",
|
package/static/lib/admin.js
CHANGED
package/static/lib/main.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
/* globals document, $, window, config, ajaxify, bootbox */
|
|
4
|
-
|
|
5
3
|
$(document).ready(function () {
|
|
6
4
|
if (config.sessionSharing && config.sessionSharing.hostWhitelist) {
|
|
7
5
|
var hosts = config.sessionSharing.hostWhitelist.split(',') || [config.sessionSharing.hostWhitelist];
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
<
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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 col-md-8 px-0 mb-4" tabindex="0">
|
|
6
|
+
<form role="form" class="session-sharing-settings">
|
|
7
|
+
<div class="mb-4">
|
|
8
|
+
<h5 class="fw-bold tracking-tight settings-header">General</h5>
|
|
9
|
+
|
|
7
10
|
<div class="mb-3">
|
|
8
11
|
<label class="form-label" for="name">Base Name</label>
|
|
9
12
|
<input type="text" id="name" name="name" title="Base Name" class="form-control" placeholder="appId" />
|
|
@@ -37,10 +40,10 @@
|
|
|
37
40
|
</p>
|
|
38
41
|
</div>
|
|
39
42
|
</div>
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
|
|
44
|
+
<div class="mb-4">
|
|
45
|
+
<h5 class="fw-bold tracking-tight settings-header">Session Handling</h5>
|
|
46
|
+
|
|
44
47
|
<div class="mb-3">
|
|
45
48
|
<label class="form-label" for="behaviour">Cookie changes</label>
|
|
46
49
|
<select class="form-control" name="behaviour" id="behaviour">
|
|
@@ -53,7 +56,7 @@
|
|
|
53
56
|
<div class="form-check">
|
|
54
57
|
<input class="form-check-input" type="checkbox" id="adminRevalidate" name="adminRevalidate" />
|
|
55
58
|
<label class="form-check-label">
|
|
56
|
-
<span
|
|
59
|
+
<span>Apply revalidation rules to administrators as well</span>
|
|
57
60
|
</label>
|
|
58
61
|
<p class="form-text">
|
|
59
62
|
Administrators are exempt from the <code>revalidate</code> behaviour because a
|
|
@@ -67,7 +70,7 @@
|
|
|
67
70
|
<div class="form-check">
|
|
68
71
|
<input class="form-check-input" type="checkbox" id="noRegistration" name="noRegistration" />
|
|
69
72
|
<label class="form-check-label">
|
|
70
|
-
<span
|
|
73
|
+
<span>Do not automatically create NodeBB accounts for unrecognized users</span>
|
|
71
74
|
</label>
|
|
72
75
|
<p class="form-text">
|
|
73
76
|
By default, an unrecognized user id found in a payload cookie will have a local NodeBB account automatically created for it. If enabled,
|
|
@@ -77,7 +80,7 @@
|
|
|
77
80
|
<div class="form-check">
|
|
78
81
|
<input class="form-check-input" type="checkbox" id="updateProfile" name="updateProfile" />
|
|
79
82
|
<label class="form-check-label">
|
|
80
|
-
<span
|
|
83
|
+
<span>Automatically update local profile information with information found in shared cookie</span>
|
|
81
84
|
</label>
|
|
82
85
|
<div class="form-text">
|
|
83
86
|
Basic information such as username and id are required, while others are optional (first name, last name, etc.). Enable this setting to allow
|
|
@@ -87,28 +90,28 @@
|
|
|
87
90
|
<div class="form-check">
|
|
88
91
|
<input class="form-check-input" type="checkbox" id="allowBannedUsers" name="allowBannedUsers" />
|
|
89
92
|
<label class="form-check-label">
|
|
90
|
-
<span
|
|
93
|
+
<span>Allow banned users to be logged in and placed into banned user group</span>
|
|
91
94
|
</label>
|
|
92
95
|
<p class="form-text">
|
|
93
96
|
By default banned users arent logged in and an error is thrown. If enabled, banned users are logged in and placed in the banned group.
|
|
94
97
|
</p>
|
|
95
98
|
</div>
|
|
96
|
-
<div class="form-check">
|
|
99
|
+
<div class="form-check mb-3">
|
|
97
100
|
<input class="form-check-input" type="checkbox" id="syncGroupJoin" name="syncGroupJoin" />
|
|
98
101
|
<label class="form-check-label">
|
|
99
|
-
<span
|
|
102
|
+
<span>Automatically join groups if present in payload</span>
|
|
100
103
|
</label>
|
|
101
104
|
</div>
|
|
102
|
-
<div class="form-check">
|
|
105
|
+
<div class="form-check mb-3">
|
|
103
106
|
<input class="form-check-input" type="checkbox" id="syncGroupLeave" name="syncGroupLeave" />
|
|
104
107
|
<label class="form-check-label">
|
|
105
|
-
<span
|
|
108
|
+
<span>Automatically leave groups if not present in payload</span>
|
|
106
109
|
</label>
|
|
107
110
|
</div>
|
|
108
|
-
<div class="form-check">
|
|
111
|
+
<div class="form-check mb-3">
|
|
109
112
|
<input class="form-check-input" type="checkbox" id="syncGroupList" name="syncGroupList" />
|
|
110
113
|
<label class="form-check-label">
|
|
111
|
-
<span
|
|
114
|
+
<span>Select groups to join/leave</span>
|
|
112
115
|
</label>
|
|
113
116
|
</div>
|
|
114
117
|
<select class="form-select mb-3" id="syncGroups" name="syncGroups" multiple size="10">
|
|
@@ -146,10 +149,9 @@
|
|
|
146
149
|
</p>
|
|
147
150
|
</div>
|
|
148
151
|
</div>
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
<div class="col-sm-10 col-12">
|
|
152
|
+
|
|
153
|
+
<div class="mb-4">
|
|
154
|
+
<h5 class="fw-bold tracking-tight settings-header">Payload Keys</h5>
|
|
153
155
|
<p>
|
|
154
156
|
In general, you should not need to change these values, as you should be adjusting your app's cookie's
|
|
155
157
|
JWT payload keys to match the defaults. However if circumstances require you to have different values,
|
|
@@ -158,6 +160,7 @@
|
|
|
158
160
|
<p class="form-text">
|
|
159
161
|
Default values are shown as placeholders in the corresponding input fields.
|
|
160
162
|
</p>
|
|
163
|
+
|
|
161
164
|
<div class="mb-3">
|
|
162
165
|
<label class="form-label" for="name">Unique ID</label>
|
|
163
166
|
<input type="text" id="payload:id" name="payload:id" title="Unique ID" class="form-control" placeholder="id">
|
|
@@ -166,6 +169,16 @@
|
|
|
166
169
|
<label class="form-label" for="payload:email">Email</label>
|
|
167
170
|
<input type="text" id="payload:email" name="payload:email" title="Email" class="form-control" placeholder="email">
|
|
168
171
|
</div>
|
|
172
|
+
<div class="form-check mb-3">
|
|
173
|
+
<input class="form-check-input" type="checkbox" id="trustPayloadEmail" name="trustPayloadEmail" />
|
|
174
|
+
<label class="form-check-label">
|
|
175
|
+
<span>Trust the email provided</span>
|
|
176
|
+
</label>
|
|
177
|
+
<p class="form-text">
|
|
178
|
+
If enabled, the email provided will be automatically verified.
|
|
179
|
+
Otherwise, the user will be emailed a confirmation link.
|
|
180
|
+
</p>
|
|
181
|
+
</div>
|
|
169
182
|
<div class="mb-3">
|
|
170
183
|
<label class="form-label" for="payload:username">Username</label>
|
|
171
184
|
<input type="text" id="payload:username" name="payload:username" title="Username" class="form-control" placeholder="username">
|
|
@@ -225,10 +238,10 @@
|
|
|
225
238
|
</p>
|
|
226
239
|
</div>
|
|
227
240
|
</div>
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
241
|
+
|
|
242
|
+
<div class="mb-4">
|
|
243
|
+
<h5 class="fw-bold tracking-tight settings-header">Guest Handling</h5>
|
|
244
|
+
|
|
232
245
|
<div class="mb-3">
|
|
233
246
|
<label class="form-label" for="guestRedirect">Re-direct unauthenticated sessions (guests) to this address</label>
|
|
234
247
|
<input type="text" id="guestRedirect" name="guestRedirect" class="form-control" placeholder="https://...">
|
|
@@ -240,10 +253,10 @@
|
|
|
240
253
|
</p>
|
|
241
254
|
</div>
|
|
242
255
|
</div>
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
256
|
+
|
|
257
|
+
<div class="mb-4">
|
|
258
|
+
<h5 class="fw-bold tracking-tight settings-header">Reverse Token</h5>
|
|
259
|
+
|
|
247
260
|
<div class="mb-3">
|
|
248
261
|
<div class="form-check">
|
|
249
262
|
<input type="checkbox" class="form-check-input" id="reverseToken" name="reverseToken">
|
|
@@ -259,32 +272,37 @@
|
|
|
259
272
|
</p>
|
|
260
273
|
</div>
|
|
261
274
|
</div>
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
<
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
275
|
+
|
|
276
|
+
<div class="mb-4">
|
|
277
|
+
<h5 class="fw-bold tracking-tight settings-header">Account Search</h5>
|
|
278
|
+
<div class="col">
|
|
279
|
+
<div class="card">
|
|
280
|
+
<div class="card-body">
|
|
281
|
+
<h5 class="card-title">User Search</h5>
|
|
282
|
+
<input type="text" class="form-control" id="search" />
|
|
283
|
+
<p class="form-text">
|
|
284
|
+
Search for a username here to find their associated unique ID.
|
|
285
|
+
</p>
|
|
286
|
+
<p id="result"></p>
|
|
287
|
+
</div>
|
|
288
|
+
</div>
|
|
289
|
+
</div>
|
|
290
|
+
<div class="col">
|
|
291
|
+
<div class="card">
|
|
292
|
+
<div class="card-body">
|
|
293
|
+
<h5 class="card-title">Remote ID Search</h5>
|
|
294
|
+
<input type="text" class="form-control" id="remote_search" />
|
|
295
|
+
<p class="form-text">
|
|
296
|
+
Enter a remote ID here to find their NodeBB user profile.
|
|
297
|
+
</p>
|
|
298
|
+
<p id="local_result"></p>
|
|
299
|
+
</div>
|
|
300
|
+
</div>
|
|
301
|
+
</div>
|
|
283
302
|
</div>
|
|
284
|
-
</
|
|
303
|
+
</form>
|
|
285
304
|
</div>
|
|
286
|
-
</div>
|
|
287
|
-
</form>
|
|
288
|
-
|
|
289
|
-
<!-- IMPORT admin/partials/save_button.tpl -->
|
|
290
305
|
|
|
306
|
+
<!-- IMPORT admin/partials/settings/toc.tpl -->
|
|
307
|
+
</div>
|
|
308
|
+
</div>
|
package/test/index.js
CHANGED
|
@@ -10,7 +10,6 @@ const url = require('url');
|
|
|
10
10
|
const util = require('util');
|
|
11
11
|
const request = require('request-promise-native');
|
|
12
12
|
|
|
13
|
-
// eslint-disable-next-line no-unused-vars
|
|
14
13
|
const db = require.main.require('./test/mocks/databasemock');
|
|
15
14
|
|
|
16
15
|
const nconf = require.main.require('nconf');
|
package/.eslintrc
DELETED
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "airbnb-base",
|
|
3
|
-
"parserOptions": {
|
|
4
|
-
"sourceType": "script"
|
|
5
|
-
},
|
|
6
|
-
|
|
7
|
-
"rules": {
|
|
8
|
-
// Customized
|
|
9
|
-
"handle-callback-err": [ "error","^(e$|(e|(.*(_e|E)))rr)" ],
|
|
10
|
-
"comma-dangle": ["error", {
|
|
11
|
-
"arrays": "always-multiline",
|
|
12
|
-
"objects": "always-multiline",
|
|
13
|
-
"imports": "always-multiline",
|
|
14
|
-
"exports": "always-multiline",
|
|
15
|
-
"functions": "never"
|
|
16
|
-
}],
|
|
17
|
-
"no-empty": ["error", { "allowEmptyCatch": true }],
|
|
18
|
-
"no-underscore-dangle": "off",
|
|
19
|
-
"no-console": "off",
|
|
20
|
-
"no-mixed-operators": ["error", { "allowSamePrecedence": true }],
|
|
21
|
-
"strict": ["error", "global"],
|
|
22
|
-
"consistent-return": "off",
|
|
23
|
-
"func-names": "off",
|
|
24
|
-
"no-tabs": "off",
|
|
25
|
-
"indent": ["error", "tab"],
|
|
26
|
-
"no-eq-null": "off",
|
|
27
|
-
"camelcase": "off",
|
|
28
|
-
"no-new": "off",
|
|
29
|
-
"no-shadow": "off",
|
|
30
|
-
"no-use-before-define": ["error", "nofunc"],
|
|
31
|
-
"no-prototype-builtins": "off",
|
|
32
|
-
"new-cap": "off",
|
|
33
|
-
"no-plusplus": ["error", { "allowForLoopAfterthoughts": true }],
|
|
34
|
-
"object-curly-newline": "off",
|
|
35
|
-
"no-restricted-globals": "off",
|
|
36
|
-
"function-paren-newline": "off",
|
|
37
|
-
"import/no-unresolved": "error",
|
|
38
|
-
"quotes": ["error", "single", {
|
|
39
|
-
"avoidEscape": true,
|
|
40
|
-
"allowTemplateLiterals": true
|
|
41
|
-
}],
|
|
42
|
-
"no-else-return": [ "error", { "allowElseIf": true } ],
|
|
43
|
-
"operator-linebreak": [ "error", "after" ],
|
|
44
|
-
|
|
45
|
-
// ES6
|
|
46
|
-
"prefer-rest-params": "off",
|
|
47
|
-
"prefer-spread": "off",
|
|
48
|
-
"prefer-arrow-callback": "off",
|
|
49
|
-
"prefer-template": "off",
|
|
50
|
-
"no-var": "off",
|
|
51
|
-
"object-shorthand": "off",
|
|
52
|
-
"vars-on-top": "off",
|
|
53
|
-
"prefer-destructuring": "off",
|
|
54
|
-
|
|
55
|
-
// TODO
|
|
56
|
-
"import/no-extraneous-dependencies": "off",
|
|
57
|
-
"import/no-dynamic-require": "off",
|
|
58
|
-
"import/newline-after-import": "off",
|
|
59
|
-
"no-bitwise": "off",
|
|
60
|
-
"global-require": "off",
|
|
61
|
-
"max-len": "off",
|
|
62
|
-
"no-param-reassign": "off",
|
|
63
|
-
"no-restricted-syntax": "off",
|
|
64
|
-
"no-script-url": "off",
|
|
65
|
-
"default-case": "off",
|
|
66
|
-
"linebreak-style": "off",
|
|
67
|
-
|
|
68
|
-
// "no-multi-assign": "off",
|
|
69
|
-
// "one-var": "off",
|
|
70
|
-
// "no-undef": "off",
|
|
71
|
-
// "max-nested-callbacks": "off",
|
|
72
|
-
// "no-mixed-requires": "off",
|
|
73
|
-
// "brace-style": "off",
|
|
74
|
-
// "max-statements-per-line": "off",
|
|
75
|
-
// "no-unused-vars": "off",
|
|
76
|
-
// "no-mixed-spaces-and-tabs": "off",
|
|
77
|
-
// "no-useless-concat": "off",
|
|
78
|
-
// "require-jsdoc": "off",
|
|
79
|
-
// "eqeqeq": "off",
|
|
80
|
-
// "no-negated-condition": "off",
|
|
81
|
-
// "one-var-declaration-per-line": "off",
|
|
82
|
-
// "no-lonely-if": "off",
|
|
83
|
-
// "radix": "off",
|
|
84
|
-
// "no-else-return": "off",
|
|
85
|
-
// "no-useless-escape": "off",
|
|
86
|
-
// "block-scoped-var": "off",
|
|
87
|
-
// "operator-assignment": "off",
|
|
88
|
-
// "yoda": "off",
|
|
89
|
-
// "no-loop-func": "off",
|
|
90
|
-
// "no-void": "off",
|
|
91
|
-
// "valid-jsdoc": "off",
|
|
92
|
-
// "no-cond-assign": "off",
|
|
93
|
-
// "no-redeclare": "off",
|
|
94
|
-
// "no-unreachable": "off",
|
|
95
|
-
// "no-nested-ternary": "off",
|
|
96
|
-
// "operator-linebreak": "off",
|
|
97
|
-
// "guard-for-in": "off",
|
|
98
|
-
// "no-unneeded-ternary": "off",
|
|
99
|
-
// "no-sequences": "off",
|
|
100
|
-
// "no-extend-native": "off",
|
|
101
|
-
// "no-shadow-restricted-names": "off",
|
|
102
|
-
// "no-extra-boolean-cast": "off",
|
|
103
|
-
// "no-path-concat": "off",
|
|
104
|
-
// "no-unused-expressions": "off",
|
|
105
|
-
// "no-return-assign": "off",
|
|
106
|
-
// "no-restricted-modules": "off",
|
|
107
|
-
// "object-curly-spacing": "off",
|
|
108
|
-
// "indent": "off",
|
|
109
|
-
// "padded-blocks": "off",
|
|
110
|
-
// "eol-last": "off",
|
|
111
|
-
// "lines-around-directive": "off",
|
|
112
|
-
// "strict": "off",
|
|
113
|
-
// "comma-dangle": "off",
|
|
114
|
-
// "no-multi-spaces": "off",
|
|
115
|
-
// "quotes": "off",
|
|
116
|
-
// "keyword-spacing": "off",
|
|
117
|
-
// "no-mixed-operators": "off",
|
|
118
|
-
// "comma-spacing": "off",
|
|
119
|
-
// "no-trailing-spaces": "off",
|
|
120
|
-
// "key-spacing": "off",
|
|
121
|
-
// "no-multiple-empty-lines": "off",
|
|
122
|
-
// "spaced-comment": "off",
|
|
123
|
-
// "space-in-parens": "off",
|
|
124
|
-
// "block-spacing": "off",
|
|
125
|
-
// "quote-props": "off",
|
|
126
|
-
// "space-unary-ops": "off",
|
|
127
|
-
// "no-empty": "off",
|
|
128
|
-
// "dot-notation": "off",
|
|
129
|
-
// "func-call-spacing": "off",
|
|
130
|
-
// "array-bracket-spacing": "off",
|
|
131
|
-
// "object-property-newline": "off",
|
|
132
|
-
// "no-continue": "off",
|
|
133
|
-
// "no-extra-semi": "off",
|
|
134
|
-
// "no-spaced-func": "off",
|
|
135
|
-
// "no-useless-return": "off"
|
|
136
|
-
}
|
|
137
|
-
}
|