diff --git a/src/routes/test/users-test.js b/src/routes/test/users-test.js index 20aa3ea50..ff0805d9e 100644 --- a/src/routes/test/users-test.js +++ b/src/routes/test/users-test.js @@ -8,7 +8,6 @@ var accesscontrol = require('../../accesscontrol.js'), async = require('async'), config = require('../../config.js'), - constants = require('../../constants.js'), database = require('../../database.js'), domains = require('../../domains.js'), tokendb = require('../../tokendb.js'), @@ -17,7 +16,8 @@ var accesscontrol = require('../../accesscontrol.js'), mail = require('../../mail.js'), mailer = require('../../mailer.js'), superagent = require('superagent'), - server = require('../../server.js'); + server = require('../../server.js'), + users = require('../../users.js'); const SERVER_URL = 'http://localhost:' + config.get('port'); @@ -83,7 +83,7 @@ describe('Users API', function () { this.timeout(5000); var user_0, user_1, user_2, user_4; - var token = null; + var token = null, userToken = null; var token_1 = tokendb.generateToken(); before(setup); @@ -680,7 +680,7 @@ describe('Users API', function () { superagent.post(SERVER_URL + '/api/v1/users') .query({ access_token: token }) - .send({ username: USERNAME_4, email: EMAIL_4, invite: false, password: 'tooweak' }) + .send({ username: USERNAME_4, email: EMAIL_4, password: 'tooweak' }) .end(function (error, result) { expect(error).to.be.ok(); expect(result.statusCode).to.equal(400); @@ -691,23 +691,23 @@ describe('Users API', function () { it('can create user with a password', function (done) { superagent.post(SERVER_URL + '/api/v1/users') .query({ access_token: token }) - .send({ username: USERNAME_4, email: EMAIL_4, invite: false, password: 'Secret1#' }) + .send({ username: USERNAME_4, email: EMAIL_4, password: 'Secret1#' }) .end(function (error, result) { expect(error).to.not.be.ok(); expect(result.statusCode).to.equal(201); user_4 = result.body; - token = tokendb.generateToken(); + userToken = tokendb.generateToken(); var expires = Date.now() + 2000; // 1 sec - tokendb.add(token, user_4.id, null, expires, accesscontrol.SCOPE_PROFILE, '', done); + tokendb.add(userToken, user_4.id, null, expires, accesscontrol.SCOPE_PROFILE, '', done); }); }); it('can get profile of user with pre-set password', function (done) { superagent.get(SERVER_URL + '/api/v1/profile') - .query({ access_token: token }) + .query({ access_token: userToken }) .end(function (err, res) { expect(res.statusCode).to.equal(200); @@ -716,5 +716,42 @@ describe('Users API', function () { done(); }); }); + + // Change password + it('change password fails due to missing token', function (done) { + superagent.post(SERVER_URL + '/api/v1/users/' + user_0.id + '/password') + .send({ password: 'youdontsay' }) + .end(function (error, result) { + expect(result.statusCode).to.equal(401); + done(); + }); + }); + + it('change password fails due to small password', function (done) { + superagent.post(SERVER_URL + '/api/v1/users/' + user_0.id + '/password') + .query({ access_token: token }) + .send({ password: 'small' }) + .end(function (error, result) { + expect(result.statusCode).to.equal(400); + done(); + }); + }); + + it('change password succeeds', function (done) { + superagent.post(SERVER_URL + '/api/v1/users/' + user_0.id + '/password') + .query({ access_token: token }) + .send({ password: 'bigenough' }) + .end(function (error, result) { + expect(result.statusCode).to.equal(204); + done(); + }); + }); + + it('did change the user password', function (done) { + users.verify(user_0.id, 'bigenough', function (error) { + expect(error).to.be(null); + done(); + }); + }); }); diff --git a/src/routes/users.js b/src/routes/users.js index bbf3ed3c8..1f375a3f9 100644 --- a/src/routes/users.js +++ b/src/routes/users.js @@ -6,6 +6,7 @@ exports = module.exports = { list: list, create: create, remove: remove, + changePassword: changePassword, verifyPassword: verifyPassword, createInvite: createInvite, sendInvite: sendInvite, @@ -186,4 +187,19 @@ function transferOwnership(req, res, next) { next(new HttpSuccess(200, {})); }); -} \ No newline at end of file +} + +function changePassword(req, res, next) { + assert.strictEqual(typeof req.body, 'object'); + assert.strictEqual(typeof req.params.userId, 'string'); + + if (typeof req.body.password !== 'string') return next(new HttpError(400, 'password must be a string')); + + users.setPassword(req.params.userId, req.body.password, function (error) { + if (error && error.reason === UsersError.BAD_FIELD) return next(new HttpError(400, error.message)); + if (error && error.reason === UsersError.NOT_FOUND) return next(new HttpError(404, 'User not found')); + if (error) return next(new HttpError(500, error)); + + next(new HttpSuccess(204)); + }); +} diff --git a/src/server.js b/src/server.js index f920f1183..d9f6a5a88 100644 --- a/src/server.js +++ b/src/server.js @@ -149,6 +149,7 @@ function initializeExpressSync() { router.get ('/api/v1/users/:userId', usersManageScope, routes.users.get); // this is manage scope because it returns non-restricted fields router.del ('/api/v1/users/:userId', usersManageScope, routes.users.verifyPassword, routes.users.remove); router.post('/api/v1/users/:userId', usersManageScope, routes.users.update); + router.post('/api/v1/users/:userId/password', usersManageScope, routes.users.changePassword); router.put ('/api/v1/users/:userId/groups', usersManageScope, routes.users.setGroups); router.post('/api/v1/users/:userId/send_invite', usersManageScope, routes.users.sendInvite); router.post('/api/v1/users/:userId/create_invite', usersManageScope, routes.users.createInvite);