diff --git a/config/env/test.js b/config/env/test.js index 2efb791e64..c6d24db171 100644 --- a/config/env/test.js +++ b/config/env/test.js @@ -50,10 +50,11 @@ module.exports = { mailer: { from: process.env.MAILER_FROM || 'MAILER_FROM', options: { - service: process.env.MAILER_SERVICE_PROVIDER || 'MAILER_SERVICE_PROVIDER', - auth: { - user: process.env.MAILER_EMAIL_ID || 'MAILER_EMAIL_ID', - pass: process.env.MAILER_PASSWORD || 'MAILER_PASSWORD' + // The TLS configuration option is required for the test environment due + // to testing the e-mail functionality which requires that on an + // uncongifured email setup it is ok to work with unauthorized servers + tls: { + rejectUnauthorized: false } } }, diff --git a/modules/users/tests/server/user.server.routes.tests.js b/modules/users/tests/server/user.server.routes.tests.js index e104ba7152..6a30bb93f8 100644 --- a/modules/users/tests/server/user.server.routes.tests.js +++ b/modules/users/tests/server/user.server.routes.tests.js @@ -272,6 +272,582 @@ describe('User CRUD tests', function () { }); }); + it('forgot password should return 400 for non-existent username', function (done) { + user.roles = ['user']; + + user.save(function (err) { + should.not.exist(err); + agent.post('/api/auth/forgot') + .send({ + username: 'some_username_that_doesnt_exist' + }) + .expect(400) + .end(function (err, res) { + // Handle error + if (err) { + return done(err); + } + + res.body.message.should.equal('No account with that username has been found'); + return done(); + }); + }); + }); + + it('forgot password should return 400 for no username provided', function (done) { + var provider = 'facebook'; + user.provider = provider; + user.roles = ['user']; + + user.save(function (err) { + should.not.exist(err); + agent.post('/api/auth/forgot') + .send({ + username: '' + }) + .expect(400) + .end(function (err, res) { + // Handle error + if (err) { + return done(err); + } + + res.body.message.should.equal('Username field must not be blank'); + return done(); + }); + }); + }); + + it('forgot password should return 400 for non-local provider set for the user object', function (done) { + var provider = 'facebook'; + user.provider = provider; + user.roles = ['user']; + + user.save(function (err) { + should.not.exist(err); + agent.post('/api/auth/forgot') + .send({ + username: user.username + }) + .expect(400) + .end(function (err, res) { + // Handle error + if (err) { + return done(err); + } + + res.body.message.should.equal('It seems like you signed up using your ' + user.provider + ' account'); + return done(); + }); + }); + }); + + it('forgot password should be able to reset password for user password reset request', function (done) { + user.roles = ['user']; + + user.save(function (err) { + should.not.exist(err); + agent.post('/api/auth/forgot') + .send({ + username: user.username + }) + .expect(200) + .end(function (err, res) { + // Handle error + if (err) { + return done(err); + } + + User.findOne({username: user.username.toLowerCase()}, function(err, userRes) { + userRes.resetPasswordToken.should.not.be.empty(); + should.exist(userRes.resetPasswordExpires); + res.body.message.should.be.equal('An email has been sent to the provided email with further instructions.'); + return done(); + }); + }); + }); + }); + + it('forgot password should be able to reset the password using reset token', function (done) { + user.roles = ['user']; + + user.save(function (err) { + should.not.exist(err); + agent.post('/api/auth/forgot') + .send({ + username: user.username + }) + .expect(200) + .end(function (err, res) { + // Handle error + if (err) { + return done(err); + } + + User.findOne({username: user.username.toLowerCase()}, function(err, userRes) { + userRes.resetPasswordToken.should.not.be.empty(); + should.exist(userRes.resetPasswordExpires); + + agent.get('/api/auth/reset/' + userRes.resetPasswordToken) + .expect(302) + .end(function (err, res) { + // Handle error + if (err) { + return done(err); + } + + res.headers.location.should.be.equal('/password/reset/' + userRes.resetPasswordToken); + + return done(); + }); + }); + }); + }); + }); + + it('forgot password should return error when using invalid reset token', function (done) { + user.roles = ['user']; + + user.save(function (err) { + should.not.exist(err); + agent.post('/api/auth/forgot') + .send({ + username: user.username + }) + .expect(200) + .end(function (err, res) { + // Handle error + if (err) { + return done(err); + } + + var invalidToken = 'someTOKEN1234567890'; + agent.get('/api/auth/reset/' + invalidToken) + .expect(302) + .end(function (err, res) { + // Handle error + if (err) { + return done(err); + } + + res.headers.location.should.be.equal('/password/reset/invalid'); + + return done(); + }); + }); + }); + }); + + it('should be able to change user own password successfully', function (done) { + agent.post('/api/auth/signin') + .send(credentials) + .expect(200) + .end(function (signinErr, signinRes) { + // Handle signin error + if (signinErr) { + return done(signinErr); + } + + // Change password + agent.post('/api/users/password') + .send({ + newPassword: '1234567890Aa$', + verifyPassword: '1234567890Aa$', + currentPassword: credentials.password + }) + .expect(200) + .end(function (err, res) { + if (err) { + return done(err); + } + + res.body.message.should.equal('Password changed successfully'); + return done(); + }); + }); + }); + + it('should not be able to change user own password if wrong verifyPassword is given', function (done) { + agent.post('/api/auth/signin') + .send(credentials) + .expect(200) + .end(function (signinErr, signinRes) { + // Handle signin error + if (signinErr) { + return done(signinErr); + } + + // Change password + agent.post('/api/users/password') + .send({ + newPassword: '1234567890Aa$', + verifyPassword: '1234567890-ABC-123-Aa$', + currentPassword: credentials.password + }) + .expect(400) + .end(function (err, res) { + if (err) { + return done(err); + } + + res.body.message.should.equal('Passwords do not match'); + return done(); + }); + }); + }); + + it('should not be able to change user own password if wrong currentPassword is given', function (done) { + agent.post('/api/auth/signin') + .send(credentials) + .expect(200) + .end(function (signinErr, signinRes) { + // Handle signin error + if (signinErr) { + return done(signinErr); + } + + // Change password + agent.post('/api/users/password') + .send({ + newPassword: '1234567890Aa$', + verifyPassword: '1234567890Aa$', + currentPassword: 'some_wrong_passwordAa$' + }) + .expect(400) + .end(function (err, res) { + if (err) { + return done(err); + } + + res.body.message.should.equal('Current password is incorrect'); + return done(); + }); + }); + }); + + it('should not be able to change user own password if no new password is at all given', function (done) { + agent.post('/api/auth/signin') + .send(credentials) + .expect(200) + .end(function (signinErr, signinRes) { + // Handle signin error + if (signinErr) { + return done(signinErr); + } + + // Change password + agent.post('/api/users/password') + .send({ + newPassword: '', + verifyPassword: '', + currentPassword: credentials.password + }) + .expect(400) + .end(function (err, res) { + if (err) { + return done(err); + } + + res.body.message.should.equal('Please provide a new password'); + return done(); + }); + }); + }); + + it('should not be able to change user own password if no new password is at all given', function (done) { + + // Change password + agent.post('/api/users/password') + .send({ + newPassword: '1234567890Aa$', + verifyPassword: '1234567890Aa$', + currentPassword: credentials.password + }) + .expect(400) + .end(function (err, res) { + if (err) { + return done(err); + } + + res.body.message.should.equal('User is not signed in'); + return done(); + }); + }); + + it('should be able to get own user details successfully', function (done) { + agent.post('/api/auth/signin') + .send(credentials) + .expect(200) + .end(function (signinErr, signinRes) { + // Handle signin error + if (signinErr) { + return done(signinErr); + } + + // Get own user details + agent.get('/api/users/me') + .expect(200) + .end(function (err, res) { + if (err) { + return done(err); + } + + res.body.should.be.instanceof(Object); + res.body.username.should.equal(user.username); + res.body.email.should.equal(user.email); + should.not.exist(res.body.salt); + should.not.exist(res.body.password); + return done(); + }); + }); + }); + + it('should not be able to get any user details if not logged in', function (done) { + // Get own user details + agent.get('/api/users/me') + .expect(200) + .end(function (err, res) { + if (err) { + return done(err); + } + + should.not.exist(res.body); + return done(); + }); + }); + + it('should be able to update own user details', function (done) { + user.roles = ['user']; + + user.save(function (err) { + should.not.exist(err); + agent.post('/api/auth/signin') + .send(credentials) + .expect(200) + .end(function (signinErr, signinRes) { + // Handle signin error + if (signinErr) { + return done(signinErr); + } + + var userUpdate = { + firstName: 'user_update_first', + lastName: 'user_update_last', + }; + + agent.put('/api/users') + .send(userUpdate) + .expect(200) + .end(function (userInfoErr, userInfoRes) { + if (userInfoErr) { + return done(userInfoErr); + } + + userInfoRes.body.should.be.instanceof(Object); + userInfoRes.body.firstName.should.be.equal('user_update_first'); + userInfoRes.body.lastName.should.be.equal('user_update_last'); + userInfoRes.body.roles.should.be.instanceof(Array).and.have.lengthOf(1); + userInfoRes.body.roles.indexOf('user').should.equal(0); + userInfoRes.body._id.should.be.equal(String(user._id)); + + // Call the assertion callback + return done(); + }); + }); + }); + }); + + it('should not be able to update own user details and add roles if not admin', function (done) { + user.roles = ['user']; + + user.save(function (err) { + should.not.exist(err); + agent.post('/api/auth/signin') + .send(credentials) + .expect(200) + .end(function (signinErr, signinRes) { + // Handle signin error + if (signinErr) { + return done(signinErr); + } + + var userUpdate = { + firstName: 'user_update_first', + lastName: 'user_update_last', + roles: ['user', 'admin'] + }; + + agent.put('/api/users') + .send(userUpdate) + .expect(200) + .end(function (userInfoErr, userInfoRes) { + if (userInfoErr) { + return done(userInfoErr); + } + + userInfoRes.body.should.be.instanceof(Object); + userInfoRes.body.firstName.should.be.equal('user_update_first'); + userInfoRes.body.lastName.should.be.equal('user_update_last'); + userInfoRes.body.roles.should.be.instanceof(Array).and.have.lengthOf(1); + userInfoRes.body.roles.indexOf('user').should.equal(0); + userInfoRes.body._id.should.be.equal(String(user._id)); + + // Call the assertion callback + return done(); + }); + }); + }); + }); + + it('should not be able to update own user details with existing username', function (done) { + + var _user2 = _user; + + _user2.username = 'user2_username'; + _user2.email = 'user2_email@test.com'; + + var credentials2 = { + username: 'username2', + password: 'M3@n.jsI$Aw3$0m3' + }; + + _user2.username = credentials2.username; + _user2.password = credentials2.password; + + var user2 = new User(_user2); + + user2.save(function (err) { + should.not.exist(err); + + agent.post('/api/auth/signin') + .send(credentials2) + .expect(200) + .end(function (signinErr, signinRes) { + // Handle signin error + if (signinErr) { + return done(signinErr); + } + + var userUpdate = { + firstName: 'user_update_first', + lastName: 'user_update_last', + username: user.username + }; + + agent.put('/api/users') + .send(userUpdate) + .expect(400) + .end(function (userInfoErr, userInfoRes) { + if (userInfoErr) { + return done(userInfoErr); + } + + // Call the assertion callback + userInfoRes.body.message.should.equal('Username already exists'); + + return done(); + }); + }); + }); + }); + + it('should not be able to update own user details with existing email', function (done) { + + var _user2 = _user; + + _user2.username = 'user2_username'; + _user2.email = 'user2_email@test.com'; + + var credentials2 = { + username: 'username2', + password: 'M3@n.jsI$Aw3$0m3' + }; + + _user2.username = credentials2.username; + _user2.password = credentials2.password; + + var user2 = new User(_user2); + + user2.save(function (err) { + should.not.exist(err); + + agent.post('/api/auth/signin') + .send(credentials2) + .expect(200) + .end(function (signinErr, signinRes) { + // Handle signin error + if (signinErr) { + return done(signinErr); + } + + var userUpdate = { + firstName: 'user_update_first', + lastName: 'user_update_last', + email: user.email + }; + + agent.put('/api/users') + .send(userUpdate) + .expect(400) + .end(function (userInfoErr, userInfoRes) { + if (userInfoErr) { + return done(userInfoErr); + } + + // Call the assertion callback + userInfoRes.body.message.should.equal('Email already exists'); + + return done(); + }); + }); + }); + }); + + it('should not be able to update own user details if not logged-in', function (done) { + user.roles = ['user']; + + user.save(function (err) { + + should.not.exist(err); + + var userUpdate = { + firstName: 'user_update_first', + lastName: 'user_update_last', + }; + + agent.put('/api/users') + .send(userUpdate) + .expect(400) + .end(function (userInfoErr, userInfoRes) { + if (userInfoErr) { + return done(userInfoErr); + } + + userInfoRes.body.message.should.equal('User is not signed in'); + + // Call the assertion callback + return done(); + }); + }); + }); + + it('should not be able to update own user profile picture without being logged-in', function (done) { + + agent.post('/api/users/picture') + .send({}) + .expect(400) + .end(function (userInfoErr, userInfoRes) { + if (userInfoErr) { + return done(userInfoErr); + } + + userInfoRes.body.message.should.equal('User is not signed in'); + + // Call the assertion callback + return done(); + }); + }); + afterEach(function (done) { User.remove().exec(done); });