AuthenticationManagerTests.coffee 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. sinon = require('sinon')
  2. chai = require('chai')
  3. should = chai.should()
  4. expect = chai.expect
  5. modulePath = "../../../../app/js/Features/Authentication/AuthenticationManager.js"
  6. SandboxedModule = require('sandboxed-module')
  7. events = require "events"
  8. ObjectId = require("mongojs").ObjectId
  9. describe "AuthenticationManager", ->
  10. beforeEach ->
  11. @AuthenticationManager = SandboxedModule.require modulePath, requires:
  12. "../../models/User": User: @User = {}
  13. "../../infrastructure/mongojs":
  14. db: @db =
  15. users: {}
  16. ObjectId: ObjectId
  17. "bcrypt": @bcrypt = {}
  18. "settings-sharelatex": { security: { bcryptRounds: 12 } }
  19. @callback = sinon.stub()
  20. describe "authenticate", ->
  21. describe "when the user exists in the database", ->
  22. beforeEach ->
  23. @user =
  24. _id: "user-id"
  25. email: @email = "USER@sharelatex.com"
  26. @unencryptedPassword = "banana"
  27. @User.findOne = sinon.stub().callsArgWith(1, null, @user)
  28. describe "when the hashed password matches", ->
  29. beforeEach (done) ->
  30. @user.hashedPassword = @hashedPassword = "asdfjadflasdf"
  31. @bcrypt.compare = sinon.stub().callsArgWith(2, null, true)
  32. @bcrypt.getRounds = sinon.stub().returns 12
  33. @AuthenticationManager.authenticate email: @email, @unencryptedPassword, (error, user) =>
  34. @callback(error, user)
  35. done()
  36. it "should look up the correct user in the database", ->
  37. @User.findOne.calledWith(email: @email).should.equal true
  38. it "should check that the passwords match", ->
  39. @bcrypt.compare
  40. .calledWith(@unencryptedPassword, @hashedPassword)
  41. .should.equal true
  42. it "should return the user", ->
  43. @callback.calledWith(null, @user).should.equal true
  44. describe "when the encrypted passwords do not match", ->
  45. beforeEach ->
  46. @AuthenticationManager._encryptPassword = sinon.stub().returns("Not the encrypted password")
  47. @AuthenticationManager.authenticate(email: @email, @unencryptedPassword, @callback)
  48. it "should not return the user", ->
  49. @callback.calledWith(null, null).should.equal true
  50. describe "when the hashed password matches but the number of rounds is too low", ->
  51. beforeEach (done) ->
  52. @user.hashedPassword = @hashedPassword = "asdfjadflasdf"
  53. @bcrypt.compare = sinon.stub().callsArgWith(2, null, true)
  54. @bcrypt.getRounds = sinon.stub().returns 7
  55. @AuthenticationManager.setUserPassword = sinon.stub().callsArgWith(2, null)
  56. @AuthenticationManager.authenticate email: @email, @unencryptedPassword, (error, user) =>
  57. @callback(error, user)
  58. done()
  59. it "should look up the correct user in the database", ->
  60. @User.findOne.calledWith(email: @email).should.equal true
  61. it "should check that the passwords match", ->
  62. @bcrypt.compare
  63. .calledWith(@unencryptedPassword, @hashedPassword)
  64. .should.equal true
  65. it "should check the number of rounds", ->
  66. @bcrypt.getRounds.called.should.equal true
  67. it "should set the users password (with a higher number of rounds)", ->
  68. @AuthenticationManager.setUserPassword
  69. .calledWith("user-id", @unencryptedPassword)
  70. .should.equal true
  71. it "should return the user", ->
  72. @callback.calledWith(null, @user).should.equal true
  73. describe "when the user does not exist in the database", ->
  74. beforeEach ->
  75. @User.findOne = sinon.stub().callsArgWith(1, null, null)
  76. @AuthenticationManager.authenticate(email: @email, @unencrpytedPassword, @callback)
  77. it "should not return a user", ->
  78. @callback.calledWith(null, null).should.equal true
  79. describe "setUserPassword", ->
  80. beforeEach ->
  81. @user_id = ObjectId()
  82. @password = "banana"
  83. @hashedPassword = "asdkjfa;osiuvandf"
  84. @salt = "saltaasdfasdfasdf"
  85. @bcrypt.genSalt = sinon.stub().callsArgWith(1, null, @salt)
  86. @bcrypt.hash = sinon.stub().callsArgWith(2, null, @hashedPassword)
  87. @db.users.update = sinon.stub().callsArg(2)
  88. @AuthenticationManager.setUserPassword(@user_id, @password, @callback)
  89. it "should update the user's password in the database", ->
  90. @db.users.update
  91. .calledWith({
  92. _id: ObjectId(@user_id.toString())
  93. }, {
  94. $set: {
  95. "hashedPassword": @hashedPassword
  96. }
  97. $unset: password: true
  98. })
  99. .should.equal true
  100. it "should hash the password", ->
  101. @bcrypt.genSalt
  102. .calledWith(12)
  103. .should.equal true
  104. @bcrypt.hash
  105. .calledWith(@password, @salt)
  106. .should.equal true
  107. it "should call the callback", ->
  108. @callback.called.should.equal true