diff --git a/config.js b/config.js index a99e08923..6a1f999a7 100644 --- a/config.js +++ b/config.js @@ -212,6 +212,13 @@ const CONFIG = { RECAPTCHA_PUBLIC: process.env.TALK_RECAPTCHA_PUBLIC, RECAPTCHA_SECRET: process.env.TALK_RECAPTCHA_SECRET, + // RECAPTCHA_WINDOW is the rate limit's time interval + RECAPTCHA_WINDOW: process.env.TALK_RECAPTCHA_WINDOW || '10m', + + // After RECAPTCHA_INCORRECT_TRIGGER incorrect attempts, recaptcha will be required. + RECAPTCHA_INCORRECT_TRIGGER: + process.env.TALK_RECAPTCHA_INCORRECT_TRIGGER || 5, + // WEBSOCKET_LIVE_URI is the absolute url to the live endpoint. WEBSOCKET_LIVE_URI: process.env.TALK_WEBSOCKET_LIVE_URI || null, diff --git a/docs/source/02-02-advanced-configuration.md b/docs/source/02-02-advanced-configuration.md index b2ad29ad0..5b638401d 100644 --- a/docs/source/02-02-advanced-configuration.md +++ b/docs/source/02-02-advanced-configuration.md @@ -316,6 +316,18 @@ default to providing only a time based lockout. Refer to [reCAPTCHA](https://www.google.com/recaptcha/intro/index.html) for information on getting an account setup. +## TALK_RECAPTCHA_WINDOW + +The rate limit time interval that there can be [TALK_RECAPTCHA_INCORRECT_TRIGGER](#talk_recaptcha_incorrect_trigger) incorrect attempts until the reCAPTCHA is +marked as required, parsed by +[ms](https://www.npmjs.com/package/ms). (Default `10m`) + +## TALK_RECAPTCHA_INCORRECT_TRIGGER + +The number of times that an incorrect login can be entered before within a time +perioud indicated by [TALK_RECAPTCHA_WINDOW](#talk_recaptcha_window) until the +reCAPTCHA is marked as required. (Default `5`) + ## TALK_REDIS_CLIENT_CONFIGURATION Configuration overrides for the redis client configuration in a JSON encoded @@ -531,4 +543,4 @@ Sets the logging level for the context logger (from [Bunyan](https://github.com/ A JSON string representing the configuration passed to the [fetch](https://www.npmjs.com/package/node-fetch) call for the scraper. It can be used to set an authorization header, or change the user agent. (Default -`{}`) \ No newline at end of file +`{}`) diff --git a/plugins/talk-plugin-local-auth/server/mutators.js b/plugins/talk-plugin-local-auth/server/mutators.js index cb34bed7a..95ab7cefc 100644 --- a/plugins/talk-plugin-local-auth/server/mutators.js +++ b/plugins/talk-plugin-local-auth/server/mutators.js @@ -5,7 +5,6 @@ const { ErrIncorrectPassword, } = require('./errors'); const { get } = require('lodash'); -const bcrypt = require('bcryptjs'); // hasLocalProfile checks a user's profiles to see if they already have a local // profile associated with their account. @@ -88,7 +87,7 @@ async function attachUserLocalAuth(ctx, email, password) { await Users.isValidPassword(password); // Hash the new password. - const hashedPassword = await bcrypt.hash(password, 10); + const hashedPassword = await Users.hashPassword(password); try { // Associate the account with the user. diff --git a/services/users.js b/services/users.js index e53df4119..651d24165 100644 --- a/services/users.js +++ b/services/users.js @@ -18,12 +18,14 @@ const { ErrCannotIgnoreStaff, } = require('../errors'); const { difference, sample, some, merge, random } = require('lodash'); -const { ROOT_URL } = require('../config'); +const { + ROOT_URL, + RECAPTCHA_WINDOW, + RECAPTCHA_INCORRECT_TRIGGER, +} = require('../config'); const { jwt: JWT_SECRET } = require('../secrets'); const debug = require('debug')('talk:services:users'); const User = require('../models/user'); -const RECAPTCHA_WINDOW = '10m'; // 10 minutes. -const RECAPTCHA_INCORRECT_TRIGGER = 5; // after 5 incorrect attempts, recaptcha will be required. const Actions = require('./actions'); const mailer = require('./mailer'); const i18n = require('./i18n'); @@ -557,7 +559,7 @@ class Users { throw new ErrPasswordTooShort(); } - const hashedPassword = await bcrypt.hash(password, SALT_ROUNDS); + const hashedPassword = await Users.hashPassword(password); return User.update( { id }, @@ -634,7 +636,7 @@ class Users { Users.isValidPassword(password), ]); - const hashedPassword = await bcrypt.hash(password, SALT_ROUNDS); + const hashedPassword = await Users.hashPassword(password); let user = new User({ username, @@ -811,6 +813,10 @@ class Users { return { user, redirect, version }; } + static async hashPassword(password) { + return bcrypt.hash(password, SALT_ROUNDS); + } + // TODO: update doc static async resetPassword(token, password) { const { user, redirect, version } = await this.verifyPasswordResetToken( @@ -821,7 +827,7 @@ class Users { throw new ErrPasswordTooShort(); } - const hashedPassword = await bcrypt.hash(password, SALT_ROUNDS); + const hashedPassword = await Users.hashPassword(password); // Update the user's password. await User.update(