diff --git a/test/api/v3/integration/user/auth/POST-register_local.test.js b/test/api/v3/integration/user/auth/POST-register_local.test.js index a8fa55f095..4be22ed0ec 100644 --- a/test/api/v3/integration/user/auth/POST-register_local.test.js +++ b/test/api/v3/integration/user/auth/POST-register_local.test.js @@ -6,7 +6,7 @@ import { import { v4 as generateRandomUserName } from 'uuid'; import { each } from 'lodash'; -describe.skip('POST /user/register/local', () => { +describe('POST /user/register/local', () => { context('username and email are free', () => { it('registers a new user', () => { let api = requester(); diff --git a/website/src/controllers/api-v3/user.js b/website/src/controllers/api-v3/user.js index 0d347b17fb..8e7cbb4c62 100644 --- a/website/src/controllers/api-v3/user.js +++ b/website/src/controllers/api-v3/user.js @@ -28,11 +28,32 @@ api.registerLocal = { method: 'POST', url: '/user/auth/local/register', handler (req, res, next) { - let email = req.body.email.toLowerCase(); + let email = req.body.email && req.body.email.toLowerCase(); let username = req.body.username; // Get the lowercase version of username to check that we do not have duplicates // So we can search for it in the database and then reject the choosen username if 1 or more results are found - let lowerCaseUsername = username.toLowerCase(); + let lowerCaseUsername = username && username.toLowerCase(); + + let newUser = new User({ + auth: { + local: { + username, + lowerCaseUsername, // Store the lowercase version of the username + email, // Store email as lowercase + salt: passwordUtils.makeSalt(), + password: req.body.password, + passwordConfirmation: req.body.passwordConfirmation, + }, + }, + preferences: { + language: req.language, + }, + }); + + newUser.registeredThrough = req.headers['x-client']; // TODO is this saved somewhere? + let validationErrors = newUser.validateSync(); // Validate synchronously for speed, remove if we add any async validator + + if (validationErrors) return next(validationErrors); // Search for duplicates using lowercase version of username User.findOne({$or: [ @@ -47,24 +68,6 @@ api.registerLocal = { if (lowerCaseUsername === user.auth.local.lowerCaseUsername) return next(new NotAuthorized(res.t('usernameTaken'))); } - let newUser = new User({ - auth: { - local: { - username, - lowerCaseUsername, // Store the lowercase version of the username - email, // Store email as lowercase - salt: passwordUtils.makeSalt(), - password: req.body.password, - passwordConfirmation: req.body.passwordConfirmation, - }, - }, - preferences: { - language: req.language, - }, - }); - - newUser.registeredThrough = req.headers['x-client']; // TODO is this saved somewhere? - return newUser.save(); }) .then((savedUser) => { diff --git a/website/src/models/user.js b/website/src/models/user.js index aff9fb0483..f4810bae01 100644 --- a/website/src/models/user.js +++ b/website/src/models/user.js @@ -609,7 +609,7 @@ function _setProfileName (user) { return localUsername || facebookUsername || anonymous; } -schema.pre('save', function postSaveUser (next) { +schema.pre('validate', function beforeValidateUser (next) { // Validate the auth path (doesn't work with schema.path('auth').validate) if (!this.auth.facebook.id) { if (!this.auth.local.email) { @@ -617,7 +617,7 @@ schema.pre('save', function postSaveUser (next) { return next(); } - if (!this.auth.local.email) { + if (!this.auth.local.username) { this.invalidate('auth.local.username', shared.i18n.t('missingUsername')); return next(); } @@ -638,6 +638,10 @@ schema.pre('save', function postSaveUser (next) { this.hashed_password = passwordUtils.encrypt(this.auth.local.password, this.auth.local.salt); // eslint-disable-line camelcase } + next(); +}); + +schema.pre('save', function postSaveUser (next) { // Do not store password and passwordConfirmation this.auth.local.password = this.local.auth.passwordConfirmation = undefined;