diff --git a/test/api/v3/unit/middlewares/getUserLanguage.test.js b/test/api/v3/unit/middlewares/getUserLanguage.test.js index 2cbf1d2c87..e1d28290e6 100644 --- a/test/api/v3/unit/middlewares/getUserLanguage.test.js +++ b/test/api/v3/unit/middlewares/getUserLanguage.test.js @@ -4,6 +4,7 @@ import { generateNext, } from '../../../../helpers/api-unit.helper'; import getUserLanguage from '../../../../../website/src/middlewares/api-v3/getUserLanguage'; +import { i18n } from '../../../../../common'; import Q from 'q'; import { model as User } from '../../../../../website/src/models/user'; import { translations } from '../../../../../website/src/libs/api-v3/i18n'; @@ -12,6 +13,11 @@ import accepts from 'accepts'; describe('getUserLanguage', () => { let res, req, next; + let checkReqT = (req) => { + expect(req.t).to.be.a('function'); + expect(req.t('help')).to.equal(i18n.t('help', req.language)); + }; + beforeEach(() => { res = generateRes(); req = generateReq(); @@ -26,6 +32,7 @@ describe('getUserLanguage', () => { getUserLanguage(req, res, next); expect(req.language).to.equal('es'); + checkReqT(req); }); it('falls back to english if the query parameter language does not exists', () => { @@ -35,6 +42,7 @@ describe('getUserLanguage', () => { getUserLanguage(req, res, next); expect(req.language).to.equal('en'); + checkReqT(req); }); it('uses query even if the request includes a user and session', () => { @@ -56,6 +64,7 @@ describe('getUserLanguage', () => { getUserLanguage(req, res, next); expect(req.language).to.equal('es'); + checkReqT(req); }); }); @@ -71,6 +80,7 @@ describe('getUserLanguage', () => { getUserLanguage(req, res, next); expect(req.language).to.equal('it'); + checkReqT(req); }); it('falls back to english if the user preferred language is not avalaible', (done) => { @@ -84,6 +94,7 @@ describe('getUserLanguage', () => { getUserLanguage(req, res, () => { expect(req.language).to.equal('en'); + checkReqT(req); done(); }); }); @@ -103,6 +114,7 @@ describe('getUserLanguage', () => { getUserLanguage(req, res, next); expect(req.language).to.equal('it'); + checkReqT(req); }); }); @@ -124,6 +136,7 @@ describe('getUserLanguage', () => { getUserLanguage(req, res, () => { expect(req.language).to.equal('it'); + checkReqT(req); done(); }); }); @@ -135,6 +148,7 @@ describe('getUserLanguage', () => { getUserLanguage(req, res, () => { expect(req.language).to.equal('pt'); + checkReqT(req); done(); }); }); @@ -144,6 +158,7 @@ describe('getUserLanguage', () => { getUserLanguage(req, res, () => { expect(req.language).to.equal('he'); + checkReqT(req); done(); }); }); @@ -153,6 +168,7 @@ describe('getUserLanguage', () => { getUserLanguage(req, res, () => { expect(req.language).to.equal('he'); + checkReqT(req); done(); }); }); @@ -162,6 +178,7 @@ describe('getUserLanguage', () => { getUserLanguage(req, res, () => { expect(req.language).to.equal('fr'); + checkReqT(req); done(); }); }); @@ -171,6 +188,7 @@ describe('getUserLanguage', () => { getUserLanguage(req, res, () => { expect(req.language).to.equal('fr'); + checkReqT(req); done(); }); }); @@ -180,6 +198,7 @@ describe('getUserLanguage', () => { getUserLanguage(req, res, () => { expect(req.language).to.equal('es'); + checkReqT(req); done(); }); }); @@ -189,6 +208,7 @@ describe('getUserLanguage', () => { getUserLanguage(req, res, () => { expect(req.language).to.equal('es_419'); + checkReqT(req); done(); }); }); @@ -198,6 +218,7 @@ describe('getUserLanguage', () => { getUserLanguage(req, res, () => { expect(req.language).to.equal('es_419'); + checkReqT(req); done(); }); }); @@ -207,6 +228,7 @@ describe('getUserLanguage', () => { getUserLanguage(req, res, () => { expect(req.language).to.equal('zh_TW'); + checkReqT(req); done(); }); }); @@ -216,6 +238,7 @@ describe('getUserLanguage', () => { getUserLanguage(req, res, () => { expect(req.language).to.equal('en'); + checkReqT(req); done(); }); }); @@ -225,6 +248,7 @@ describe('getUserLanguage', () => { getUserLanguage(req, res, () => { expect(req.language).to.equal('en'); + checkReqT(req); done(); }); }); @@ -234,6 +258,7 @@ describe('getUserLanguage', () => { getUserLanguage(req, res, () => { expect(req.language).to.equal('en'); + checkReqT(req); done(); }); }); diff --git a/website/src/controllers/api-v3/user.js b/website/src/controllers/api-v3/user.js index db5f23a57d..b6b1f1356d 100644 --- a/website/src/controllers/api-v3/user.js +++ b/website/src/controllers/api-v3/user.js @@ -1,6 +1,3 @@ -import i18n from '../../../../common/script/i18n'; -// TODO add getUserLanguage as a global middleware? -import getUserLanguage from '../../middlewares/api-v3/getUserLanguage'; import validator from 'validator'; import { NotAuthorized, @@ -11,39 +8,52 @@ import User from '../../models/user'; let api = {}; /** - * @api {get} /user/login/local Login a user with email / username and password + * @api {post} /user/register/local Register a new user with email, username and password + * @apiVersion 3.0.0 + * @apiName UserRegisterLocal + * @apiGroup User + * + * @apiParam {String} username Username of the new user + * @apiParam {String} email Email address of the new user + * @apiParam {String} password Password for the new user account + * @apiParam {String} passwordConfirmation Password confirmation + * + * @apiSuccess {Object} user The user public fields + * + * + * @apiUse NotAuthorized + */ +api.registerLocal = { + method: 'POST', + url: '/user/register/local', +}; + +/** + * @api {post} /user/login/local Login an user with email / username and password * @apiVersion 3.0.0 * @apiName UserLoginLocal * @apiGroup User * - * @apiParam {String} username Username or email of the User. + * @apiParam {String} username Username or email of the user * @apiParam {String} password The user's password * * @apiSuccess {String} _id The user's unique identifier * @apiSuccess {String} apiToken The user's api token that must be used to authenticate requests. * - * @apiSuccessExample Success-Response: - * HTTP/1.1 200 OK - * { - * "_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", - * "apiToken": "1234567890" - * } - * * @apiUse NotAuthorized */ api.loginLocal = { method: 'POST', url: '/user/login/local', - middlewares: [getUserLanguage], handler (req, res, next) { req.checkBody({ username: { notEmpty: true, - errorMessage: i18n.t('missingUsernameEmail'), + errorMessage: req.t('missingUsernameEmail'), }, password: { notEmpty: true, - errorMessage: i18n.t('missingPassword'), + errorMessage: req.t('missingPassword'), }, }); @@ -71,7 +81,7 @@ api.loginLocal = { // TODO place back long error message return res.json(401, {err:"Uh-oh - your username or password is incorrect.\n- Make sure your username or email is typed correctly.\n- You may have signed up with Facebook, not email. Double-check by trying Facebook login.\n- If you forgot your password, click \"Forgot Password\"."}); let isValidPassword = user && user.auth.local.hashed_password !== passwordUtils.encrypt(req.body.password, user.auth.local.salt); - if (!isValidPassword) return next(new NotAuthorized(i18n.t('invalidLoginCredentials'))); + if (!isValidPassword) return next(new NotAuthorized(req.t('invalidLoginCredentials'))); res .status(200) diff --git a/website/src/middlewares/api-v3/getUserLanguage.js b/website/src/middlewares/api-v3/getUserLanguage.js index 234a78a29c..8e0be1e669 100644 --- a/website/src/middlewares/api-v3/getUserLanguage.js +++ b/website/src/middlewares/api-v3/getUserLanguage.js @@ -1,5 +1,6 @@ import { model as User } from '../../models/user'; import accepts from 'accepts'; +import { i18n } from '../../../../common'; import _ from 'lodash'; import { translations, @@ -55,13 +56,21 @@ function _getFromUser (user, req) { return lang; } +function _attachTranslateFunction (req, next) { + req.t = function reqTranslation () { + return i18n.t(...arguments, req.language); + }; + + next(); +} + export default function getUserLanguage (req, res, next) { if (req.query.lang) { // In case the language is specified in the request url, use it req.language = translations[req.query.lang] ? req.query.lang : 'en'; - return next(); + return _attachTranslateFunction(req, next); } else if (req.locals && req.locals.user) { // If the request is authenticated, use the user's preferred language req.language = _getFromUser(req.locals.user, req); - return next(); + return _attachTranslateFunction(req, next); } else if (req.session && req.session.userId) { // Same thing if the user has a valid session User.findOne({ _id: req.session.userId, @@ -69,11 +78,11 @@ export default function getUserLanguage (req, res, next) { .exec() .then((user) => { req.language = _getFromUser(user, req); - return next(); + return _attachTranslateFunction(req, next); }) .catch(next); } else { // Otherwise get from browser req.language = _getFromUser(null, req); - return next(); + return _attachTranslateFunction(req, next); } } diff --git a/website/src/middlewares/api-v3/index.js b/website/src/middlewares/api-v3/index.js index f8e3e98f09..46a546b549 100644 --- a/website/src/middlewares/api-v3/index.js +++ b/website/src/middlewares/api-v3/index.js @@ -1,5 +1,6 @@ // This module is only used to attach middlewares to the express app import expressValidator from 'express-validator'; +import getUserLanguage from './getUserLanguage'; import analytics from './analytics'; import errorHandler from './errorHandler'; import bodyParser from 'body-parser'; @@ -21,6 +22,7 @@ export default function attachMiddlewares (app) { app.use(bodyParser.json()); app.use(expressValidator()); // TODO config app.use(analytics); + app.use(getUserLanguage); app.use('/api/v3', routes); app.use(notFoundHandler);