diff --git a/src/cloudron.js b/src/cloudron.js index 27b8dea9d..e8ce785b2 100644 --- a/src/cloudron.js +++ b/src/cloudron.js @@ -196,10 +196,11 @@ function setTimeZone(ip, callback) { }); } -function activate(username, password, email, ip, callback) { +function activate(username, password, email, displayName, ip, callback) { assert.strictEqual(typeof username, 'string'); assert.strictEqual(typeof password, 'string'); assert.strictEqual(typeof email, 'string'); + assert.strictEqual(typeof displayName, 'string'); assert.strictEqual(typeof ip, 'string'); assert.strictEqual(typeof callback, 'function'); @@ -207,7 +208,7 @@ function activate(username, password, email, ip, callback) { setTimeZone(ip, function () { }); // TODO: get this from user. note that timezone is detected based on the browser location and not the cloudron region - user.createOwner(username, password, email, function (error, userObject) { + user.createOwner(username, password, email, displayName, function (error, userObject) { if (error && error.reason === UserError.ALREADY_EXISTS) return callback(new CloudronError(CloudronError.ALREADY_PROVISIONED)); if (error && error.reason === UserError.BAD_USERNAME) return callback(new CloudronError(CloudronError.BAD_USERNAME)); if (error && error.reason === UserError.BAD_PASSWORD) return callback(new CloudronError(CloudronError.BAD_PASSWORD)); diff --git a/src/routes/cloudron.js b/src/routes/cloudron.js index 9658c0eb7..fd2e48c24 100644 --- a/src/routes/cloudron.js +++ b/src/routes/cloudron.js @@ -41,15 +41,17 @@ function activate(req, res, next) { if (typeof req.body.username !== 'string') return next(new HttpError(400, 'username must be string')); if (typeof req.body.password !== 'string') return next(new HttpError(400, 'password must be string')); if (typeof req.body.email !== 'string') return next(new HttpError(400, 'email must be string')); + if ('displayName' in req.body && typeof req.body.displayName !== 'string') return next(new HttpError(400, 'email must be string')); var username = req.body.username; var password = req.body.password; var email = req.body.email; + var displayName = req.body.displayName || ''; var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; debug('activate: username:%s ip:%s', username, ip); - cloudron.activate(username, password, email, ip, function (error, info) { + cloudron.activate(username, password, email, displayName, ip, function (error, info) { if (error && error.reason === CloudronError.ALREADY_PROVISIONED) return next(new HttpError(409, 'Already setup')); if (error && error.reason === CloudronError.BAD_USERNAME) return next(new HttpError(400, 'Bad username')); if (error && error.reason === CloudronError.BAD_PASSWORD) return next(new HttpError(400, 'Bad password')); diff --git a/src/routes/test/oauth2-test.js b/src/routes/test/oauth2-test.js index 4b8be3ee8..aefaa9864 100644 --- a/src/routes/test/oauth2-test.js +++ b/src/routes/test/oauth2-test.js @@ -145,7 +145,8 @@ describe('OAuth2', function () { salt: 'somesalt', createdAt: (new Date()).toUTCString(), modifiedAt: (new Date()).toUTCString(), - resetToken: hat(256) + resetToken: hat(256), + displayName: '' }; var APP_0 = { @@ -291,7 +292,7 @@ describe('OAuth2', function () { appdb.add.bind(null, APP_1.id, APP_1.appStoreId, APP_1.manifest, APP_1.location, APP_1.portBindings, APP_1.accessRestriction, APP_1.oauthProxy), appdb.add.bind(null, APP_2.id, APP_2.appStoreId, APP_2.manifest, APP_2.location, APP_2.portBindings, APP_2.accessRestriction, APP_2.oauthProxy), function (callback) { - user.create(USER_0.username, USER_0.password, USER_0.email, true, '', false, function (error, userObject) { + user.create(USER_0.username, USER_0.password, USER_0.email, USER_0.displayName, true, '', false, function (error, userObject) { expect(error).to.not.be.ok(); // update the global objects to reflect the new user id diff --git a/src/routes/user.js b/src/routes/user.js index 315f09006..c4bf8f754 100644 --- a/src/routes/user.js +++ b/src/routes/user.js @@ -46,13 +46,15 @@ function createUser(req, res, next) { if (typeof req.body.username !== 'string') return next(new HttpError(400, 'username must be string')); if (typeof req.body.email !== 'string') return next(new HttpError(400, 'email must be string')); if (typeof req.body.invite !== 'boolean') return next(new HttpError(400, 'invite must be boolean')); + if ('displayName' in req.body && req.body.displayName !== 'string') return next(new HttpError(400, 'displayName must be string')); var username = req.body.username; var password = generatePassword(8, true /* memorable */); var email = req.body.email; var sendInvite = req.body.invite; + var displayName = req.body.displayName || ''; - user.create(username, password, email, false /* admin */, req.user /* creator */, sendInvite, function (error, user) { + user.create(username, password, email, displayName, false /* admin */, req.user /* creator */, sendInvite, function (error, user) { if (error && error.reason === UserError.BAD_USERNAME) return next(new HttpError(400, 'Invalid username')); if (error && error.reason === UserError.BAD_EMAIL) return next(new HttpError(400, 'Invalid email')); if (error && error.reason === UserError.BAD_PASSWORD) return next(new HttpError(400, 'Invalid password')); diff --git a/src/test/ldap-test.js b/src/test/ldap-test.js index e228a1f86..722a6a947 100644 --- a/src/test/ldap-test.js +++ b/src/test/ldap-test.js @@ -18,13 +18,15 @@ var database = require('../database.js'), var USER_0 = { username: 'foobar0', password: 'password0', - email: 'foo0@bar.com' + email: 'foo0@bar.com', + displayName: 'Bob bobson' }; var USER_1 = { username: 'foobar1', password: 'password1', - email: 'foo1@bar.com' + email: 'foo1@bar.com', + displayName: 'Jesus' }; function setup(done) { @@ -32,8 +34,8 @@ function setup(done) { database.initialize.bind(null), database._clear.bind(null), ldapServer.start.bind(null), - user.create.bind(null, USER_0.username, USER_0.password, USER_0.email, true, null, false), - user.create.bind(null, USER_1.username, USER_1.password, USER_1.email, false, USER_0, false) + user.create.bind(null, USER_0.username, USER_0.password, USER_0.email, USER_0.displayName, true, null, false), + user.create.bind(null, USER_1.username, USER_1.password, USER_1.email, USER_0.displayName, false, USER_0, false) ], done); } diff --git a/src/test/user-test.js b/src/test/user-test.js index 194c203f0..19fcd6a78 100644 --- a/src/test/user-test.js +++ b/src/test/user-test.js @@ -20,6 +20,7 @@ var EMAIL_NEW = 'nobodynew@no.body'; var PASSWORD = 'foobar'; var NEW_PASSWORD = 'somenewpassword'; var IS_ADMIN = true; +var DISPLAY_NAME = 'Nobody cares'; var userObject = null; function cleanupUsers(done) { @@ -30,7 +31,7 @@ function cleanupUsers(done) { } function createUser(done) { - user.create(USERNAME, PASSWORD, EMAIL, IS_ADMIN, null /* invitor */, false, function (error, result) { + user.create(USERNAME, PASSWORD, EMAIL, DISPLAY_NAME, IS_ADMIN, null /* invitor */, false, function (error, result) { expect(error).to.not.be.ok(); expect(result).to.be.ok(); @@ -75,7 +76,7 @@ describe('User', function () { after(cleanupUsers); it('succeeds and attempts to send invite', function (done) { - user.create(USERNAME, PASSWORD, EMAIL, IS_ADMIN, null /* invitor */, true, function (error, result) { + user.create(USERNAME, PASSWORD, EMAIL, DISPLAY_NAME, IS_ADMIN, null /* invitor */, true, function (error, result) { expect(error).not.to.be.ok(); expect(result).to.be.ok(); expect(result.username).to.equal(USERNAME); @@ -110,7 +111,7 @@ describe('User', function () { }); it('fails because user exists', function (done) { - user.create(USERNAME, PASSWORD, EMAIL, IS_ADMIN, null /* invitor */, false, function (error, result) { + user.create(USERNAME, PASSWORD, EMAIL, DISPLAY_NAME, IS_ADMIN, null /* invitor */, false, function (error, result) { expect(error).to.be.ok(); expect(result).not.to.be.ok(); expect(error.reason).to.equal(UserError.ALREADY_EXISTS); @@ -120,7 +121,7 @@ describe('User', function () { }); it('fails because password is empty', function (done) { - user.create(USERNAME, '', EMAIL, IS_ADMIN, null /* invitor */, false, function (error, result) { + user.create(USERNAME, '', EMAIL, DISPLAY_NAME, IS_ADMIN, null /* invitor */, false, function (error, result) { expect(error).to.be.ok(); expect(result).not.to.be.ok(); expect(error.reason).to.equal(UserError.BAD_PASSWORD); @@ -330,7 +331,7 @@ describe('User', function () { email: 'some@thi.ng' }; - user.create(user1.username, user1.password, user1.email, false, { username: USERNAME, email: EMAIL } /* invitor */, false, function (error, result) { + user.create(user1.username, user1.password, user1.email, DISPLAY_NAME, false, { username: USERNAME, email: EMAIL } /* invitor */, false, function (error, result) { expect(error).to.not.be.ok(); expect(result).to.be.ok(); @@ -372,7 +373,7 @@ describe('User', function () { email: 'some@thi.ng' }; - user.create(user1.username, user1.password, user1.email, false, { username: USERNAME, email: EMAIL } /* invitor */, false, function (error, result) { + user.create(user1.username, user1.password, user1.email, DISPLAY_NAME, false, { username: USERNAME, email: EMAIL } /* invitor */, false, function (error, result) { expect(error).to.eql(null); expect(result).to.be.ok(); diff --git a/src/user.js b/src/user.js index 3b1207250..47d185c0f 100644 --- a/src/user.js +++ b/src/user.js @@ -114,10 +114,17 @@ function validateToken(token) { return null; } -function createUser(username, password, email, admin, invitor, sendInvite, callback) { +function validateDisplayName(name) { + assert.strictEqual(typeof name, 'string'); + + return null; +} + +function createUser(username, password, email, displayName, admin, invitor, sendInvite, callback) { assert.strictEqual(typeof username, 'string'); assert.strictEqual(typeof password, 'string'); assert.strictEqual(typeof email, 'string'); + assert.strictEqual(typeof displayName, 'string'); assert.strictEqual(typeof admin, 'boolean'); assert(invitor || admin); assert.strictEqual(typeof sendInvite, 'boolean'); @@ -132,6 +139,9 @@ function createUser(username, password, email, admin, invitor, sendInvite, callb error = validateEmail(email); if (error) return callback(error); + error = validateDisplayName(displayName); + if (error) return callback(error); + crypto.randomBytes(CRYPTO_SALT_SIZE, function (error, salt) { if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error)); @@ -149,7 +159,7 @@ function createUser(username, password, email, admin, invitor, sendInvite, callb createdAt: now, modifiedAt: now, resetToken: hat(256), - displayName: '' + displayName: displayName }; userdb.add(user.id, user, function (error) { @@ -387,12 +397,12 @@ function changePassword(username, oldPassword, newPassword, callback) { }); } -function createOwner(username, password, email, callback) { +function createOwner(username, password, email, displayName, callback) { userdb.count(function (error, count) { if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error)); if (count !== 0) return callback(new UserError(UserError.ALREADY_EXISTS)); - createUser(username, password, email, true /* admin */, null /* invitor */, false /* sendInvite */, callback); + createUser(username, password, email, displayName, true /* admin */, null /* invitor */, false /* sendInvite */, callback); }); }