This repository has been archived by the owner on Mar 5, 2021. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 17
/
index.js
122 lines (110 loc) · 5.21 KB
/
index.js
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
(function (Plugin) {
'use strict';
var ExpressBrute = require('express-brute'),
moment = require('moment'),
async = require('async'),
nodebb = require('./nodebb'),
utils = nodebb.utils,
user = nodebb.user,
db = nodebb.db,
passwordUtil = nodebb.password,
winston = nodebb.winston,
store = new ExpressBrute.MemoryStore(),
settings = {
freeRetries : 5,
proxyDepth : 1,
minWait : 5 * 60 * 1000, // 5 minutes
maxWait : 60 * 60 * 1000, // 1 hour,
failCallback: failCallback
},
userDefence = new ExpressBrute(store, settings);
function failCallback(req, res, next, nextValidRequestDate) {
res.status(403).json({
message: 'You have made too many failed attempts in a short period of time, please try again ' + moment(nextValidRequestDate).fromNow()
});
}
//NodeBB list of Hooks: https://github.com/NodeBB/NodeBB/wiki/Hooks
Plugin.hooks = {
statics: {
load: function (params, callback) {
var router = params.router,
middleware = params.middleware,
controllers = params.controllers,
apiUri = '/api/ns/login';
router.post(
apiUri,
userDefence.getMiddleware({
key: function (req, res, next) {
// prevent too many attempts for the same username
next(req.body.username);
}
}),
function (req, res, next) {
var username = req.body.username,
password = req.body.password,
uid = null,
userObject = null;
if (!username) {
return res.status(400).json({
message: 'Username is not provided, username and password are required fields'
});
}
if (!password) {
return res.status(400).json({
message: 'Password is empty'
});
}
async.waterfall([
function (next) {
if (utils.isEmailValid(username)) {
user.getUidByEmail(username, next);
} else {
user.getUidByUserslug(utils.slugify(username), next);
}
},
function (_uid, next) {
if (!_uid) {
return next(new Error('User ' + username + ' does not exist'));
}
uid = _uid;
next();
},
function (next) {
async.parallel({
user : async.apply(user.getUserData, uid),
secure : async.apply(db.getObjectFields, 'user:' + uid, ['password', 'banned', 'passwordExpiry', 'email:confirmed']),
isAdmin: async.apply(user.isAdministrator, uid)
}, next);
},
function (payload, next) {
if (parseInt(payload.secure.banned) === 1) {
return next(new Error('User ' + username + ' is banned.'));
}
userObject = payload.user;
userObject['email:confirmed'] = parseInt(payload.secure['email:confirmed']);
passwordUtil.compare(password, payload.secure.password, next);
},
function (passwordMatch, next) {
if (!passwordMatch) {
return next(new Error('Invalid Password'));
}
next(null, userObject);
}
], function (error, user) {
if (error) {
return res.status(403).json({
message: error.message
});
}
// Reset the failure counter
req.brute.reset(function () {
winston.log('verbose', '[plugins/ns-login] Successful external login, uid: %d', uid);
res.json(user);
});
});
});
callback();
}
}
};
})(module.exports);