mirror of
https://github.com/wassname/talk.git
synced 2026-09-12 13:01:11 +08:00
Merge branch 'master' into community-pagination-
This commit is contained in:
+12
-38
@@ -18,7 +18,7 @@ const UserModel = require('../models/user');
|
||||
const USER_STATUS = require('../models/enum/user_status');
|
||||
const USER_ROLES = require('../models/enum/user_roles');
|
||||
|
||||
const RECAPTCHA_WINDOW_SECONDS = 60 * 10; // 10 minutes.
|
||||
const RECAPTCHA_WINDOW = '10m'; // 10 minutes.
|
||||
const RECAPTCHA_INCORRECT_TRIGGER = 5; // after 3 incorrect attempts, recaptcha will be required.
|
||||
|
||||
const ActionsService = require('./actions');
|
||||
@@ -35,9 +35,8 @@ const PASSWORD_RESET_JWT_SUBJECT = 'password_reset';
|
||||
const SALT_ROUNDS = 10;
|
||||
|
||||
// Create a redis client to use for authentication.
|
||||
const {createClientFactory} = require('./redis');
|
||||
|
||||
const client = createClientFactory();
|
||||
const Limit = require('./limit');
|
||||
const loginRateLimiter = new Limit('loginAttempts', RECAPTCHA_INCORRECT_TRIGGER, RECAPTCHA_WINDOW);
|
||||
|
||||
// UsersService is the interface for the application to interact with the
|
||||
// UserModel through.
|
||||
@@ -71,23 +70,14 @@ module.exports = class UsersService {
|
||||
* where future login attempts must be made with the recaptcha flag.
|
||||
*/
|
||||
static async recordLoginAttempt(email) {
|
||||
const rdskey = `la[${email.toLowerCase().trim()}]`;
|
||||
try {
|
||||
await loginRateLimiter.test(email.toLowerCase().trim());
|
||||
} catch (err) {
|
||||
if (err === errors.ErrMaxRateLimit) {
|
||||
throw errors.ErrLoginAttemptMaximumExceeded;
|
||||
}
|
||||
|
||||
const replies = await client()
|
||||
.multi()
|
||||
.incr(rdskey)
|
||||
.expire(rdskey, RECAPTCHA_WINDOW_SECONDS)
|
||||
.exec();
|
||||
|
||||
// if this is new or has no expiry
|
||||
if (replies[0] === 1 || replies[1] === -1) {
|
||||
|
||||
// then expire it after the timeout
|
||||
client().expire(rdskey, RECAPTCHA_WINDOW_SECONDS);
|
||||
}
|
||||
|
||||
if (replies[0] >= RECAPTCHA_INCORRECT_TRIGGER) {
|
||||
throw errors.ErrLoginAttemptMaximumExceeded;
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,9 +88,7 @@ module.exports = class UsersService {
|
||||
* errors.ErrLoginAttemptMaximumExceeded
|
||||
*/
|
||||
static async checkLoginAttempts(email) {
|
||||
const rdskey = `la[${email.toLowerCase().trim()}]`;
|
||||
|
||||
const attempts = await client().get(rdskey);
|
||||
const attempts = await loginRateLimiter.get(email.toLowerCase().trim());
|
||||
if (!attempts) {
|
||||
return;
|
||||
}
|
||||
@@ -718,7 +706,7 @@ module.exports = class UsersService {
|
||||
* @param {String} email The email that we are needing to get confirmed.
|
||||
* @return {Promise}
|
||||
*/
|
||||
static async createEmailConfirmToken(userID = null, email, referer = ROOT_URL) {
|
||||
static async createEmailConfirmToken(user, email, referer = ROOT_URL) {
|
||||
if (!email || typeof email !== 'string') {
|
||||
throw new Error('email is required when creating a JWT for resetting passord');
|
||||
}
|
||||
@@ -732,20 +720,6 @@ module.exports = class UsersService {
|
||||
subject: EMAIL_CONFIRM_JWT_SUBJECT
|
||||
};
|
||||
|
||||
let user;
|
||||
if (!userID) {
|
||||
|
||||
// If there is no userID, we're coming from the endpoint where a new user
|
||||
// is re-requesting a confirmation email and we don't know the userID.
|
||||
user = await UserModel.findOne({profiles: {$elemMatch: {id: email, provider: 'local'}}});
|
||||
} else {
|
||||
user = await UsersService.findById(userID);
|
||||
}
|
||||
|
||||
if (!user) {
|
||||
throw errors.ErrNotFound;
|
||||
}
|
||||
|
||||
// Get the profile representing the local account.
|
||||
let profile = user.profiles.find((profile) => profile.id === email && profile.provider === 'local');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user