diff --git a/public/src/client/login.js b/public/src/client/login.js index 0c59cdf2cc..204dd799e2 100644 --- a/public/src/client/login.js +++ b/public/src/client/login.js @@ -1,7 +1,7 @@ 'use strict'; -define('forum/login', ['hooks', 'jquery-form'], function (hooks) { +define('forum/login', ['hooks', 'translator', 'jquery-form'], function (hooks, translator) { var Login = { _capsState: false, }; @@ -44,17 +44,22 @@ define('forum/login', ['hooks', 'jquery-form'], function (hooks) { window.location.href = pathname + '?' + qs; }, error: function (data) { + var message = data.responseText; + var errInfo = data.responseJSON; if (data.status === 403 && data.responseText === 'Forbidden') { window.location.href = config.relative_path + '/login?error=csrf-invalid'; - } else { - errorEl.find('p').translateText(data.responseText); - errorEl.show(); - submitEl.removeClass('disabled'); - - // Select the entire password if that field has focus - if ($('#password:focus').length) { - $('#password').select(); - } + } else if (errInfo && errInfo.hasOwnProperty('banned_until')) { + message = errInfo.banned_until ? + translator.compile('error:user-banned-reason-until', (new Date(errInfo.banned_until).toLocaleString()), errInfo.reason) : + '[[error:user-banned-reason, ' + errInfo.reason + ']]'; + } + errorEl.find('p').translateText(message); + errorEl.show(); + submitEl.removeClass('disabled'); + + // Select the entire password if that field has focus + if ($('#password:focus').length) { + $('#password').select(); } }, }); diff --git a/src/controllers/authentication.js b/src/controllers/authentication.js index 4340b16508..5e8a2cd6b9 100644 --- a/src/controllers/authentication.js +++ b/src/controllers/authentication.js @@ -273,7 +273,7 @@ function continueLogin(strategy, req, res, next) { passport.authenticate(strategy, async (err, userData, info) => { if (err) { plugins.hooks.fire('action:login.continue', { req, strategy, userData, error: err }); - return helpers.noScriptErrors(req, res, err.message, 403); + return helpers.noScriptErrors(req, res, err.data || err.message, 403); } if (!userData) { @@ -433,8 +433,7 @@ authenticationController.localLogin = async function (req, username, password, n userData.isAdminOrGlobalMod = isAdminOrGlobalMod; if (!canLoginIfBanned) { - const banMesage = await getBanInfo(uid); - return next(new Error(banMesage)); + return next(await getBanError(uid)); } // Doing this after the ban check, because user's privileges might change after a ban expires @@ -493,19 +492,19 @@ authenticationController.logout = async function (req, res, next) { } }; -async function getBanInfo(uid) { +async function getBanError(uid) { try { const banInfo = await user.getLatestBanInfo(uid); if (!banInfo.reason) { - banInfo.reason = await translator.translate('[[user:info.banned-no-reason]]'); + banInfo.reason = '[[user:info.banned-no-reason]]'; } - return banInfo.banned_until ? - `[[error:user-banned-reason-until, ${banInfo.banned_until_readable}, ${banInfo.reason}]]` : - `[[error:user-banned-reason, ${banInfo.reason}]]`; + const err = new Error(banInfo.reason); + err.data = banInfo; + return err; } catch (err) { if (err.message === 'no-ban-info') { - return '[[error:user-banned]]'; + return new Error('[[error:user-banned]]'); } throw err; } diff --git a/src/controllers/helpers.js b/src/controllers/helpers.js index 6173402c47..6b91bba943 100644 --- a/src/controllers/helpers.js +++ b/src/controllers/helpers.js @@ -21,7 +21,10 @@ const url = nconf.get('url'); helpers.noScriptErrors = async function (req, res, error, httpStatus) { if (req.body.noscript !== 'true') { - return res.status(httpStatus).send(error); + if (typeof error === 'string') { + return res.status(httpStatus).send(error); + } + return res.status(httpStatus).json(error); } const middleware = require('../middleware'); const httpStatusString = httpStatus.toString();