SudoModeControllerTests.coffee 12 KB

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