SudoModeControllerTests.coffee 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. SandboxedModule = require('sandboxed-module')
  2. sinon = require 'sinon'
  3. should = require("chai").should()
  4. expect = require('chai').expect
  5. MockRequest = require "../helpers/MockRequest"
  6. MockResponse = require "../helpers/MockResponse"
  7. modulePath = '../../../../app/js/Features/SudoMode/SudoModeController'
  8. describe 'SudoModeController', ->
  9. beforeEach ->
  10. @user =
  11. _id: 'abcd'
  12. email: 'user@example.com'
  13. @UserGetter =
  14. getUser: sinon.stub().callsArgWith(2, null, @user)
  15. @SudoModeHandler =
  16. isSudoModeActive: sinon.stub()
  17. activateSudoMode: sinon.stub()
  18. @AuthenticationController =
  19. getLoggedInUserId: sinon.stub().returns(@user._id)
  20. _getRediretFromSession: sinon.stub()
  21. @AuthenticationManager =
  22. authenticate: sinon.stub()
  23. @UserGetter =
  24. getUser: sinon.stub()
  25. @SudoModeController = SandboxedModule.require modulePath, requires:
  26. 'logger-sharelatex': {log: sinon.stub(), err: sinon.stub()}
  27. './SudoModeHandler': @SudoModeHandler
  28. '../Authentication/AuthenticationController': @AuthenticationController
  29. '../Authentication/AuthenticationManager': @AuthenticationManager
  30. '../../infrastructure/Mongoose': {mongo: {ObjectId: () -> 'some_object_id'}}
  31. '../User/UserGetter': @UserGetter
  32. describe 'sudoModePrompt', ->
  33. beforeEach ->
  34. @SudoModeHandler.isSudoModeActive = sinon.stub().callsArgWith(1, null, false)
  35. @req = {externalAuthenticationSystemUsed: sinon.stub().returns(false)}
  36. @res = {redirect: sinon.stub(), render: sinon.stub()}
  37. @next = sinon.stub()
  38. it 'should get the logged in user id', ->
  39. @SudoModeController.sudoModePrompt(@req, @res, @next)
  40. @AuthenticationController.getLoggedInUserId.callCount.should.equal 1
  41. @AuthenticationController.getLoggedInUserId.calledWith(@req).should.equal true
  42. it 'should check if sudo-mode is active', ->
  43. @SudoModeController.sudoModePrompt(@req, @res, @next)
  44. @SudoModeHandler.isSudoModeActive.callCount.should.equal 1
  45. @SudoModeHandler.isSudoModeActive.calledWith(@user._id).should.equal true
  46. it 'should redirect when sudo-mode is active', ->
  47. @SudoModeHandler.isSudoModeActive = sinon.stub().callsArgWith(1, null, true)
  48. @SudoModeController.sudoModePrompt(@req, @res, @next)
  49. @res.redirect.callCount.should.equal 1
  50. @res.redirect.calledWith('/project').should.equal true
  51. it 'should render the sudo_mode_prompt page when sudo mode is not active', ->
  52. @SudoModeHandler.isSudoModeActive = sinon.stub().callsArgWith(1, null, false)
  53. @SudoModeController.sudoModePrompt(@req, @res, @next)
  54. @res.render.callCount.should.equal 1
  55. @res.render.calledWith('sudo_mode/sudo_mode_prompt').should.equal true
  56. describe 'when isSudoModeActive produces an error', ->
  57. beforeEach ->
  58. @SudoModeHandler.isSudoModeActive = sinon.stub().callsArgWith(1, new Error('woops'))
  59. @next = sinon.stub()
  60. it 'should call next with an error', ->
  61. @SudoModeController.sudoModePrompt(@req, @res, @next)
  62. @next.callCount.should.equal 1
  63. expect(@next.lastCall.args[0]).to.be.instanceof Error
  64. it 'should not render page', ->
  65. @SudoModeController.sudoModePrompt(@req, @res, @next)
  66. @res.render.callCount.should.equal 0
  67. describe 'when external auth system is used', ->
  68. beforeEach ->
  69. @req.externalAuthenticationSystemUsed = sinon.stub().returns(true)
  70. it 'should redirect', ->
  71. @SudoModeController.sudoModePrompt(@req, @res, @next)
  72. @res.redirect.callCount.should.equal 1
  73. @res.redirect.calledWith('/project').should.equal true
  74. it 'should not check if sudo mode is active', ->
  75. @SudoModeController.sudoModePrompt(@req, @res, @next)
  76. @SudoModeHandler.isSudoModeActive.callCount.should.equal 0
  77. it 'should not render page', ->
  78. @SudoModeController.sudoModePrompt(@req, @res, @next)
  79. @res.render.callCount.should.equal 0
  80. describe 'submitPassword', ->
  81. beforeEach ->
  82. @AuthenticationController._getRedirectFromSession = sinon.stub().returns '/somewhere'
  83. @UserGetter.getUser = sinon.stub().callsArgWith(2, null, @user)
  84. @AuthenticationManager.authenticate = sinon.stub().callsArgWith(2, null, @user)
  85. @SudoModeHandler.activateSudoMode = sinon.stub().callsArgWith(1, null)
  86. @password = 'a_terrible_secret'
  87. @req = {body: {password: @password}}
  88. @res = {json: sinon.stub()}
  89. @next = sinon.stub()
  90. describe 'when all goes well', ->
  91. beforeEach ->
  92. it 'should get the logged in user id', ->
  93. @SudoModeController.submitPassword(@req, @res, @next)
  94. @AuthenticationController.getLoggedInUserId.callCount.should.equal 1
  95. @AuthenticationController.getLoggedInUserId.calledWith(@req).should.equal true
  96. it 'should get redirect from session', ->
  97. @SudoModeController.submitPassword(@req, @res, @next)
  98. @AuthenticationController._getRedirectFromSession.callCount.should.equal 1
  99. @AuthenticationController._getRedirectFromSession.calledWith(@req).should.equal true
  100. it 'should get the user from storage', ->
  101. @SudoModeController.submitPassword(@req, @res, @next)
  102. @UserGetter.getUser.callCount.should.equal 1
  103. @UserGetter.getUser.calledWith('some_object_id', {email: 1}).should.equal true
  104. it 'should try to authenticate the user with the password', ->
  105. @SudoModeController.submitPassword(@req, @res, @next)
  106. @AuthenticationManager.authenticate.callCount.should.equal 1
  107. @AuthenticationManager.authenticate.calledWith({email: @user.email}, @password).should.equal true
  108. it 'should activate sudo mode', ->
  109. @SudoModeController.submitPassword(@req, @res, @next)
  110. @SudoModeHandler.activateSudoMode.callCount.should.equal 1
  111. @SudoModeHandler.activateSudoMode.calledWith(@user._id).should.equal true
  112. it 'should send back a json response', ->
  113. @SudoModeController.submitPassword(@req, @res, @next)
  114. @res.json.callCount.should.equal 1
  115. @res.json.calledWith({redir: '/somewhere'}).should.equal true
  116. it 'should not call next', ->
  117. @SudoModeController.submitPassword(@req, @res, @next)
  118. @next.callCount.should.equal 0
  119. describe 'when no password is supplied', ->
  120. beforeEach ->
  121. @req.body.password = ''
  122. @next = sinon.stub()
  123. it 'should return next with an error', ->
  124. @SudoModeController.submitPassword(@req, @res, @next)
  125. @next.callCount.should.equal 1
  126. expect(@next.lastCall.args[0]).to.be.instanceof Error
  127. it 'should not get the user from storage', ->
  128. @SudoModeController.submitPassword(@req, @res, @next)
  129. @UserGetter.getUser.callCount.should.equal 0
  130. it 'should not try to authenticate the user with the password', ->
  131. @SudoModeController.submitPassword(@req, @res, @next)
  132. @AuthenticationManager.authenticate.callCount.should.equal 0
  133. it 'should not activate sudo mode', ->
  134. @SudoModeController.submitPassword(@req, @res, @next)
  135. @SudoModeHandler.activateSudoMode.callCount.should.equal 0
  136. it 'should not send back a json response', ->
  137. @SudoModeController.submitPassword(@req, @res, @next)
  138. @res.json.callCount.should.equal 0
  139. describe 'when getUser produces an error', ->
  140. beforeEach ->
  141. @UserGetter.getUser = sinon.stub().callsArgWith(2, new Error('woops'))
  142. @next = sinon.stub()
  143. it 'should return next with an error', ->
  144. @SudoModeController.submitPassword(@req, @res, @next)
  145. @next.callCount.should.equal 1
  146. expect(@next.lastCall.args[0]).to.be.instanceof Error
  147. it 'should get the user from storage', ->
  148. @SudoModeController.submitPassword(@req, @res, @next)
  149. @UserGetter.getUser.callCount.should.equal 1
  150. @UserGetter.getUser.calledWith('some_object_id', {email: 1}).should.equal true
  151. it 'should not try to authenticate the user with the password', ->
  152. @SudoModeController.submitPassword(@req, @res, @next)
  153. @AuthenticationManager.authenticate.callCount.should.equal 0
  154. it 'should not activate sudo mode', ->
  155. @SudoModeController.submitPassword(@req, @res, @next)
  156. @SudoModeHandler.activateSudoMode.callCount.should.equal 0
  157. it 'should not send back a json response', ->
  158. @SudoModeController.submitPassword(@req, @res, @next)
  159. @res.json.callCount.should.equal 0
  160. describe 'when getUser does not find a user', ->
  161. beforeEach ->
  162. @UserGetter.getUser = sinon.stub().callsArgWith(2, null, null)
  163. @next = sinon.stub()
  164. it 'should return next with an error', ->
  165. @SudoModeController.submitPassword(@req, @res, @next)
  166. @next.callCount.should.equal 1
  167. expect(@next.lastCall.args[0]).to.be.instanceof Error
  168. it 'should get the user from storage', ->
  169. @SudoModeController.submitPassword(@req, @res, @next)
  170. @UserGetter.getUser.callCount.should.equal 1
  171. @UserGetter.getUser.calledWith('some_object_id', {email: 1}).should.equal true
  172. it 'should not try to authenticate the user with the password', ->
  173. @SudoModeController.submitPassword(@req, @res, @next)
  174. @AuthenticationManager.authenticate.callCount.should.equal 0
  175. it 'should not activate sudo mode', ->
  176. @SudoModeController.submitPassword(@req, @res, @next)
  177. @SudoModeHandler.activateSudoMode.callCount.should.equal 0
  178. it 'should not send back a json response', ->
  179. @SudoModeController.submitPassword(@req, @res, @next)
  180. @res.json.callCount.should.equal 0
  181. describe 'when authentication fails', ->
  182. beforeEach ->
  183. @AuthenticationManager.authenticate = sinon.stub().callsArgWith(2, null, null)
  184. @res.json = sinon.stub()
  185. @req.i18n = {translate: sinon.stub()}
  186. it 'should send back a failure message', ->
  187. @SudoModeController.submitPassword(@req, @res, @next)
  188. @res.json.callCount.should.equal 1
  189. expect(@res.json.lastCall.args[0]).to.have.keys ['message']
  190. expect(@res.json.lastCall.args[0].message).to.have.keys ['text', 'type']
  191. @req.i18n.translate.callCount.should.equal 1
  192. @req.i18n.translate.calledWith('invalid_password')
  193. it 'should get the user from storage', ->
  194. @SudoModeController.submitPassword(@req, @res, @next)
  195. @UserGetter.getUser.callCount.should.equal 1
  196. @UserGetter.getUser.calledWith('some_object_id', {email: 1}).should.equal true
  197. it 'should try to authenticate the user with the password', ->
  198. @SudoModeController.submitPassword(@req, @res, @next)
  199. @AuthenticationManager.authenticate.callCount.should.equal 1
  200. @AuthenticationManager.authenticate.calledWith({email: @user.email}, @password).should.equal true
  201. it 'should not activate sudo mode', ->
  202. @SudoModeController.submitPassword(@req, @res, @next)
  203. @SudoModeHandler.activateSudoMode.callCount.should.equal 0
  204. describe 'when authentication produces an error', ->
  205. beforeEach ->
  206. @AuthenticationManager.authenticate = sinon.stub().callsArgWith(2, new Error('woops'))
  207. @next = sinon.stub()
  208. it 'should return next with an error', ->
  209. @SudoModeController.submitPassword(@req, @res, @next)
  210. @next.callCount.should.equal 1
  211. expect(@next.lastCall.args[0]).to.be.instanceof Error
  212. it 'should get the user from storage', ->
  213. @SudoModeController.submitPassword(@req, @res, @next)
  214. @UserGetter.getUser.callCount.should.equal 1
  215. @UserGetter.getUser.calledWith('some_object_id', {email: 1}).should.equal true
  216. it 'should try to authenticate the user with the password', ->
  217. @SudoModeController.submitPassword(@req, @res, @next)
  218. @AuthenticationManager.authenticate.callCount.should.equal 1
  219. @AuthenticationManager.authenticate.calledWith({email: @user.email}, @password).should.equal true
  220. it 'should not activate sudo mode', ->
  221. @SudoModeController.submitPassword(@req, @res, @next)
  222. @SudoModeHandler.activateSudoMode.callCount.should.equal 0
  223. describe 'when sudo mode activation produces an error', ->
  224. beforeEach ->
  225. @SudoModeHandler.activateSudoMode = sinon.stub().callsArgWith(1, new Error('woops'))
  226. @next = sinon.stub()
  227. it 'should return next with an error', ->
  228. @SudoModeController.submitPassword(@req, @res, @next)
  229. @next.callCount.should.equal 1
  230. expect(@next.lastCall.args[0]).to.be.instanceof Error
  231. it 'should get the user from storage', ->
  232. @SudoModeController.submitPassword(@req, @res, @next)
  233. @UserGetter.getUser.callCount.should.equal 1
  234. @UserGetter.getUser.calledWith('some_object_id', {email: 1}).should.equal true
  235. it 'should try to authenticate the user with the password', ->
  236. @SudoModeController.submitPassword(@req, @res, @next)
  237. @AuthenticationManager.authenticate.callCount.should.equal 1
  238. @AuthenticationManager.authenticate.calledWith({email: @user.email}, @password).should.equal true
  239. it 'should have tried to activate sudo mode', ->
  240. @SudoModeController.submitPassword(@req, @res, @next)
  241. @SudoModeHandler.activateSudoMode.callCount.should.equal 1
  242. @SudoModeHandler.activateSudoMode.calledWith(@user._id).should.equal true