openhim-core
Version:
The OpenHIM core application that provides logging and routing of http requests
503 lines (438 loc) • 17.1 kB
text/coffeescript
should = require 'should'
request = require 'supertest'
server = require '../../lib/server'
contact = require '../../lib/contact'
User = require('../../lib/model/users').User
testUtils = require "../testUtils"
auth = require("../testUtils").auth
sinon = require "sinon"
moment = require 'moment'
describe 'API Integration Tests', ->
describe 'Users REST Api testing', ->
user1 = new User
firstname: 'Ryan'
surname: 'Chrichton'
email: 'r..@jembi.org'
passwordAlgorithm: 'sha512'
passwordHash: '796a5a8e-4e44-4d9f-9e04-c27ec6374ffa'
passwordSalt: 'bf93caba-6eec-4c0c-a1a3-d968a7533fd7'
groups: [ 'admin', 'RHIE' ]
user2 = new User
firstname: 'Bill'
surname: 'Murray'
email: 'bfm@crazy.net'
passwordAlgorithm: 'sha512'
passwordHash: '3cc90918-7044-4e55-b61d-92ae73cb261e'
passwordSalt: '22a61686-66f6-483c-a524-185aac251fb0'
groups: [ 'HISP' ]
newUser = new User
firstname: 'Jane'
surname: 'Doe'
email: 'jane@doe.net'
token: 'l9Q87x4b0OXHM9eaUBHIv59co5NZG1bM'
tokenType: 'newUser'
locked: true
expiry: moment().add(2, 'days').utc().format()
groups: [ 'HISP' ]
newUserExpired = new User
firstname: 'John'
surname: 'Smith'
email: 'john@smith.net'
token: 'hS40KZItS7y9vqqEGhE6ARXtAA3wNhCg'
tokenType: 'newUser'
locked: true
expiry: moment().subtract(2, 'days').utc().format()
groups: [ 'HISP' ]
authDetails = {}
before (done) ->
user1.save ->
user2.save ->
newUser.save ->
newUserExpired.save ->
auth.setupTestUsers (err) ->
server.start apiPort: 8080, ->
done()
after (done) ->
User.remove {}, ->
auth.cleanupTestUsers (err) ->
server.stop ->
done()
beforeEach ->
authDetails = auth.getAuthDetails()
describe '*authenticate(email)', ->
it 'should return the requested users salt', (done) ->
request("https://localhost:8080")
.get("/authenticate/bfm@crazy.net")
.set("auth-username", testUtils.rootUser.email)
.set("auth-ts", authDetails.authTS)
.set("auth-salt", authDetails.authSalt)
.set("auth-token", authDetails.authToken)
.expect(200)
.end (err, res) ->
if err
done err
else
res.body.salt.should.eql '22a61686-66f6-483c-a524-185aac251fb0'
should.exist(res.body.ts)
done()
describe '*userPasswordResetRequest(email)', ->
it 'should return 403 when requesting root@openhim.org password reset', (done) ->
request("https://localhost:8080")
.get("/password-reset-request/root@openhim.org")
.expect(403)
.end (err, res) ->
if err
done err
else
done()
it 'should update the user with a token and send reset email', (done) ->
stubContact = sinon.stub(contact, 'sendEmail')
stubContact.yields(null)
request("https://localhost:8080")
.get("/password-reset-request/r..@jembi.org")
.expect(201)
.end (err, res) ->
if err
done err
else
User.findOne { email: "r..@jembi.org" }, (err, user) ->
user.should.have.property "firstname", "Ryan"
user.should.have.property "surname", "Chrichton"
user.should.have.property "token"
user.should.have.property "tokenType", 'existingUser'
user.should.have.property "expiry"
stubContact.restore()
done()
it 'should update the user with a token get a 500 error when nodemailer fails', (done) ->
stubContact = sinon.stub(contact, 'sendEmail')
stubContact.yields('An error occurred trying to send the email.')
request("https://localhost:8080")
.get("/password-reset-request/r..@jembi.org")
.expect(500)
.end (err, res) ->
stubContact.restore()
if err
done err
else
done()
it 'should return a not found error', (done) ->
request("https://localhost:8080")
.get("/password-reset-request/test@jembi.org")
.expect(404)
.end (err, res) ->
if err
done err
else
done()
describe '*getUserByToken(token)', ->
it 'should return a users details (basic details)', (done) ->
request("https://localhost:8080")
.get("/token/l9Q87x4b0OXHM9eaUBHIv59co5NZG1bM")
.expect(200)
.end (err, res) ->
if err
done err
else
res.body.email.should.eql 'jane@doe.net'
res.body.firstname.should.eql 'Jane'
res.body.surname.should.eql 'Doe'
res.body.token.should.eql 'l9Q87x4b0OXHM9eaUBHIv59co5NZG1bM'
res.body.tokenType.should.eql 'newUser'
res.body.locked.should.eql true
should.exist(res.body.expiry)
should.not.exist(res.body.passwordAlgorithm)
should.not.exist(res.body.passwordHash)
should.not.exist(res.body.passwordSalt)
should.not.exist(res.body.groups)
done()
it 'should return a not found error', (done) ->
request("https://localhost:8080")
.get("/token/hSas987asdS7y9vqqKJHDSoARXtA098g")
.expect(404)
.end (err, res) ->
if err
done err
else
done()
it 'should return a expired token error', (done) ->
request("https://localhost:8080")
.get("/token/hS40KZItS7y9vqqEGhE6ARXtAA3wNhCg")
.expect(410)
.end (err, res) ->
if err
done err
else
done()
describe '*updateUserByToken(token)', ->
it 'should update a user by the supplied token', (done) ->
updates =
firstname: 'Jane Sally'
surname: 'Doe'
msisdn: '27123456789'
passwordAlgorithm: 'sha256'
passwordHash: 'af200ab5-4227-4840-97d1-92ba91206499'
passwordSalt: 'eca7205c-2129-4558-85da-45845d17bd5f'
request("https://localhost:8080")
.put("/token/l9Q87x4b0OXHM9eaUBHIv59co5NZG1bM")
.send(updates)
.expect(200)
.end (err, res) ->
if err
done err
else
User.findOne { email: "jane@doe.net" }, (err, user) ->
user.should.have.property "firstname", "Jane Sally"
user.should.have.property "surname", "Doe"
user.should.have.property "passwordHash", "af200ab5-4227-4840-97d1-92ba91206499"
user.should.have.property "passwordSalt", "eca7205c-2129-4558-85da-45845d17bd5f"
user.should.have.property "token", null
user.should.have.property "tokenType", null
user.should.have.property "locked", false
user.should.have.property "expiry", null
done()
it 'should prevent an update with an expired token (expired token)', (done) ->
updates =
firstname: 'Peter'
surname: 'smith'
msisdn: '27123456789'
passwordAlgorithm: 'sha256'
passwordHash: 'af200ab5-4227-4840-97d1-92ba91206499'
passwordSalt: 'eca7205c-2129-4558-85da-45845d17bd5f'
request("https://localhost:8080")
.put("/token/hS40KZItS7y9vqqEGhE6ARXtAA3wNhCg")
.send(updates)
.expect(410)
.end (err, res) ->
if err
done err
else
done()
describe '*getUsers()', ->
it 'should fetch all users', (done) ->
request("https://localhost:8080")
.get("/users")
.set("auth-username", testUtils.rootUser.email)
.set("auth-ts", authDetails.authTS)
.set("auth-salt", authDetails.authSalt)
.set("auth-token", authDetails.authToken)
.expect(200)
.end (err, res) ->
if err
done err
else
# user1, user2, newUser, newUserExpired, + the 2 API test users and the root user
res.body.length.should.be.eql(7);
done()
it 'should not allow non admin user to fetch all users', (done) ->
request("https://localhost:8080")
.get("/users")
.set("auth-username", testUtils.nonRootUser.email)
.set("auth-ts", authDetails.authTS)
.set("auth-salt", authDetails.authSalt)
.set("auth-token", authDetails.authToken)
.expect(403)
.end (err, res) ->
if err
done err
else
done()
describe '*addUser()', ->
it 'should add a new user', (done) ->
newUser =
firstname: 'Bill'
surname: 'Newman'
email: 'bill@newman.com'
passwordAlgorithm: 'sha256'
passwordHash: 'af200ab5-4227-4840-97d1-92ba91206499'
passwordSalt: 'eca7205c-2129-4558-85da-45845d17bd5f'
groups: [ 'HISP' ]
request("https://localhost:8080")
.post("/users")
.set("auth-username", testUtils.rootUser.email)
.set("auth-ts", authDetails.authTS)
.set("auth-salt", authDetails.authSalt)
.set("auth-token", authDetails.authToken)
.send(newUser)
.expect(201)
.end (err, res) ->
if err
done err
else
User.findOne { email: 'bill@newman.com' }, (err, user) ->
user.should.have.property 'firstname', 'Bill'
user.should.have.property 'surname', 'Newman'
user.groups.should.have.length 1
user.should.have.property 'token'
user.should.have.property 'tokenType', 'newUser'
user.should.have.property 'locked', true
user.should.have.property 'expiry'
done()
it 'should not allow a non admin user to add a user', (done) ->
newUser = {}
request("https://localhost:8080")
.post("/users")
.set("auth-username", testUtils.nonRootUser.email)
.set("auth-ts", authDetails.authTS)
.set("auth-salt", authDetails.authSalt)
.set("auth-token", authDetails.authToken)
.send(newUser)
.expect(403)
.end (err, res) ->
if err
done err
else
done()
describe '*findUserByUsername(email)', ->
it 'should find a user by their email address', (done) ->
request("https://localhost:8080")
.get("/users/r..@jembi.org")
.set("auth-username", testUtils.rootUser.email)
.set("auth-ts", authDetails.authTS)
.set("auth-salt", authDetails.authSalt)
.set("auth-token", authDetails.authToken)
.expect(200)
.end (err, res) ->
if err
done err
else
res.body.should.have.property "surname", "Chrichton"
res.body.should.have.property "email", "r..@jembi.org"
res.body.groups.should.have.length 2
done()
it 'should not allow a non admin user to find a user to email', (done) ->
request("https://localhost:8080")
.get("/users/r..@jembi.org")
.set("auth-username", testUtils.nonRootUser.email)
.set("auth-ts", authDetails.authTS)
.set("auth-salt", authDetails.authSalt)
.set("auth-token", authDetails.authToken)
.expect(403)
.end (err, res) ->
if err
done err
else
done()
it 'should always allow a user to fetch their own details', (done) ->
request("https://localhost:8080")
.get("/users/" + testUtils.nonRootUser.email)
.set("auth-username", testUtils.nonRootUser.email)
.set("auth-ts", authDetails.authTS)
.set("auth-salt", authDetails.authSalt)
.set("auth-token", authDetails.authToken)
.expect(200)
.end (err, res) ->
if err
done err
else
res.body.should.have.property "firstname", "Non"
res.body.should.have.property "surname", "Root"
res.body.should.have.property "email", "nonroot@jembi.org"
res.body.groups.should.have.length 2
done()
describe '*updateUser(email)', ->
it 'should update a specific user by email', (done) ->
updates =
_id: "thisShouldBeIgnored"
surname: 'Crichton'
email: 'rg..@jembi.org'
groups: [ 'admin', 'RHIE', 'HISP' ]
request("https://localhost:8080")
.put("/users/r..@jembi.org")
.set("auth-username", testUtils.rootUser.email)
.set("auth-ts", authDetails.authTS)
.set("auth-salt", authDetails.authSalt)
.set("auth-token", authDetails.authToken)
.send(updates)
.expect(200)
.end (err, res) ->
if err
done err
else
User.findOne { email: "rg..@jembi.org" }, (err, user) ->
user.should.have.property "surname", "Crichton"
user.should.have.property "email", "rg..@jembi.org"
user.groups.should.have.length 3
done()
it 'should not allow non admin users to update a user', (done) ->
updates = {}
request("https://localhost:8080")
.put("/users/r..@jembi.org")
.set("auth-username", testUtils.nonRootUser.email)
.set("auth-ts", authDetails.authTS)
.set("auth-salt", authDetails.authSalt)
.set("auth-token", authDetails.authToken)
.send(updates)
.expect(403)
.end (err, res) ->
if err
done err
else
done()
it 'should always allow a user to update their own details', (done) ->
updates =
_id: "thisShouldBeIgnored"
surname: 'Root-updated'
request("https://localhost:8080")
.put("/users/" + testUtils.nonRootUser.email)
.set("auth-username", testUtils.nonRootUser.email)
.set("auth-ts", authDetails.authTS)
.set("auth-salt", authDetails.authSalt)
.set("auth-token", authDetails.authToken)
.send(updates)
.expect(200)
.end (err, res) ->
if err
done err
else
User.findOne { email: testUtils.nonRootUser.email }, (err, user) ->
user.should.have.property "surname", "Root-updated"
done()
it 'should NOT allow a non-admin user to update their groups', (done) ->
updates =
_id: "thisShouldBeIgnored"
groups: [ "admin" ]
request("https://localhost:8080")
.put("/users/" + testUtils.nonRootUser.email)
.set("auth-username", testUtils.nonRootUser.email)
.set("auth-ts", authDetails.authTS)
.set("auth-salt", authDetails.authSalt)
.set("auth-token", authDetails.authToken)
.send(updates)
.expect(200)
.end (err, res) ->
if err
done err
else
User.findOne { email: testUtils.nonRootUser.email }, (err, user) ->
user.groups.should.be.length 2
user.groups.should.not.containEql "admin"
done()
describe '*removeUser(email)', ->
it 'should remove a specific user by email', (done) ->
request("https://localhost:8080")
.del("/users/bfm@crazy.net")
.set("auth-username", testUtils.rootUser.email)
.set("auth-ts", authDetails.authTS)
.set("auth-salt", authDetails.authSalt)
.set("auth-token", authDetails.authToken)
.expect(200)
.end (err, res) ->
if err
done err
else
User.find { name: "bfm@crazy.net" }, (err, users) ->
users.should.have.length 0
done()
it 'should not allow a non admin user to remove a user', (done) ->
request("https://localhost:8080")
.del("/users/bfm@crazy.net")
.set("auth-username", testUtils.nonRootUser.email)
.set("auth-ts", authDetails.authTS)
.set("auth-salt", authDetails.authSalt)
.set("auth-token", authDetails.authToken)
.expect(403)
.end (err, res) ->
if err
done err
else
done()