AuthorizationMiddlewareTests.coffee 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. sinon = require('sinon')
  2. chai = require('chai')
  3. should = chai.should()
  4. expect = chai.expect
  5. modulePath = "../../../../app/js/Features/Authorization/AuthorizationMiddleware.js"
  6. SandboxedModule = require('sandboxed-module')
  7. Errors = require "../../../../app/js/Features/Errors/Errors.js"
  8. describe "AuthorizationMiddleware", ->
  9. beforeEach ->
  10. @user_id = "user-id-123"
  11. @project_id = "project-id-123"
  12. @token = 'some-token'
  13. @AuthenticationController =
  14. getLoggedInUserId: sinon.stub().returns(@user_id)
  15. isUserLoggedIn: sinon.stub().returns(true)
  16. @AuthorizationMiddleware = SandboxedModule.require modulePath, requires:
  17. "./AuthorizationManager": @AuthorizationManager = {}
  18. "logger-sharelatex": {log: () ->}
  19. "mongojs": ObjectId: @ObjectId = {}
  20. "../Errors/Errors": Errors
  21. '../Authentication/AuthenticationController': @AuthenticationController
  22. "../TokenAccess/TokenAccessHandler": @TokenAccessHandler =
  23. getRequestToken: sinon.stub().returns(@token)
  24. @req = {}
  25. @res = {}
  26. @ObjectId.isValid = sinon.stub()
  27. @ObjectId.isValid.withArgs(@project_id).returns true
  28. @next = sinon.stub()
  29. describe "_getUserId", ->
  30. beforeEach ->
  31. @req = {}
  32. it "should get the user from session", (done) ->
  33. @AuthenticationController.getLoggedInUserId = sinon.stub().returns("1234")
  34. @AuthorizationMiddleware._getUserId @req, (err, user_id) =>
  35. expect(err).to.not.exist
  36. expect(user_id).to.equal "1234"
  37. done()
  38. it "should get oauth_user from request", (done) ->
  39. @AuthenticationController.getLoggedInUserId = sinon.stub().returns(null)
  40. @req.oauth_user = {_id: "5678"}
  41. @AuthorizationMiddleware._getUserId @req, (err, user_id) =>
  42. expect(err).to.not.exist
  43. expect(user_id).to.equal "5678"
  44. done()
  45. it "should fall back to null", (done) ->
  46. @AuthenticationController.getLoggedInUserId = sinon.stub().returns(null)
  47. @req.oauth_user = undefined
  48. @AuthorizationMiddleware._getUserId @req, (err, user_id) =>
  49. expect(err).to.not.exist
  50. expect(user_id).to.equal null
  51. done()
  52. METHODS_TO_TEST = {
  53. "ensureUserCanReadProject": "canUserReadProject"
  54. "ensureUserCanWriteProjectSettings": "canUserWriteProjectSettings"
  55. "ensureUserCanWriteProjectContent": "canUserWriteProjectContent"
  56. "ensureUserCanAdminProject": "canUserAdminProject"
  57. }
  58. for middlewareMethod, managerMethod of METHODS_TO_TEST
  59. do (middlewareMethod, managerMethod) ->
  60. describe middlewareMethod, ->
  61. beforeEach ->
  62. @req.params =
  63. project_id: @project_id
  64. @AuthorizationManager[managerMethod] = sinon.stub()
  65. @AuthorizationMiddleware.redirectToRestricted = sinon.stub()
  66. describe "with missing project_id", ->
  67. beforeEach ->
  68. @req.params = {}
  69. it "should return an error to next", ->
  70. @AuthorizationMiddleware[middlewareMethod] @req, @res, @next
  71. @next.calledWith(new Error()).should.equal true
  72. describe "with logged in user", ->
  73. beforeEach ->
  74. @AuthenticationController.getLoggedInUserId.returns(@user_id)
  75. describe "when user has permission", ->
  76. beforeEach ->
  77. @AuthorizationManager[managerMethod]
  78. .withArgs(@user_id, @project_id, @token)
  79. .yields(null, true)
  80. it "should return next", ->
  81. @AuthorizationMiddleware[middlewareMethod] @req, @res, @next
  82. @next.called.should.equal true
  83. describe "when user doesn't have permission", ->
  84. beforeEach ->
  85. @AuthorizationManager[managerMethod]
  86. .withArgs(@user_id, @project_id, @token)
  87. .yields(null, false)
  88. it "should redirect to redirectToRestricted", ->
  89. @AuthorizationMiddleware[middlewareMethod] @req, @res, @next
  90. @next.called.should.equal false
  91. @AuthorizationMiddleware.redirectToRestricted
  92. .calledWith(@req, @res, @next)
  93. .should.equal true
  94. describe "with anonymous user", ->
  95. describe "when user has permission", ->
  96. beforeEach ->
  97. @AuthenticationController.getLoggedInUserId.returns(null)
  98. @AuthorizationManager[managerMethod]
  99. .withArgs(null, @project_id, @token)
  100. .yields(null, true)
  101. it "should return next", ->
  102. @AuthorizationMiddleware[middlewareMethod] @req, @res, @next
  103. @next.called.should.equal true
  104. describe "when user doesn't have permission", ->
  105. beforeEach ->
  106. @AuthenticationController.getLoggedInUserId.returns(null)
  107. @AuthorizationManager[managerMethod]
  108. .withArgs(null, @project_id, @token)
  109. .yields(null, false)
  110. it "should redirect to redirectToRestricted", ->
  111. @AuthorizationMiddleware[middlewareMethod] @req, @res, @next
  112. @next.called.should.equal false
  113. @AuthorizationMiddleware.redirectToRestricted
  114. .calledWith(@req, @res, @next)
  115. .should.equal true
  116. describe "with malformed project id", ->
  117. beforeEach ->
  118. @req.params =
  119. project_id: "blah"
  120. @ObjectId.isValid = sinon.stub().returns false
  121. it "should return a not found error", (done) ->
  122. @AuthorizationMiddleware[middlewareMethod] @req, @res, (error) ->
  123. error.should.be.instanceof Errors.NotFoundError
  124. done()
  125. describe "ensureUserIsSiteAdmin", ->
  126. beforeEach ->
  127. @AuthorizationManager.isUserSiteAdmin = sinon.stub()
  128. @AuthorizationMiddleware.redirectToRestricted = sinon.stub()
  129. describe "with logged in user", ->
  130. beforeEach ->
  131. @AuthenticationController.getLoggedInUserId.returns(@user_id)
  132. describe "when user has permission", ->
  133. beforeEach ->
  134. @AuthorizationManager.isUserSiteAdmin
  135. .withArgs(@user_id)
  136. .yields(null, true)
  137. it "should return next", ->
  138. @AuthorizationMiddleware.ensureUserIsSiteAdmin @req, @res, @next
  139. @next.called.should.equal true
  140. describe "when user doesn't have permission", ->
  141. beforeEach ->
  142. @AuthorizationManager.isUserSiteAdmin
  143. .withArgs(@user_id)
  144. .yields(null, false)
  145. it "should redirect to redirectToRestricted", ->
  146. @AuthorizationMiddleware.ensureUserIsSiteAdmin @req, @res, @next
  147. @next.called.should.equal false
  148. @AuthorizationMiddleware.redirectToRestricted
  149. .calledWith(@req, @res, @next)
  150. .should.equal true
  151. describe "with anonymous user", ->
  152. describe "when user has permission", ->
  153. beforeEach ->
  154. @AuthenticationController.getLoggedInUserId.returns(null)
  155. @AuthorizationManager.isUserSiteAdmin
  156. .withArgs(null)
  157. .yields(null, true)
  158. it "should return next", ->
  159. @AuthorizationMiddleware.ensureUserIsSiteAdmin @req, @res, @next
  160. @next.called.should.equal true
  161. describe "when user doesn't have permission", ->
  162. beforeEach ->
  163. @AuthenticationController.getLoggedInUserId.returns(null)
  164. @AuthorizationManager.isUserSiteAdmin
  165. .withArgs(null)
  166. .yields(null, false)
  167. it "should redirect to redirectToRestricted", ->
  168. @AuthorizationMiddleware.ensureUserIsSiteAdmin @req, @res, @next
  169. @next.called.should.equal false
  170. @AuthorizationMiddleware.redirectToRestricted
  171. .calledWith(@req, @res, @next)
  172. .should.equal true
  173. describe "ensureUserCanReadMultipleProjects", ->
  174. beforeEach ->
  175. @AuthorizationManager.canUserReadProject = sinon.stub()
  176. @AuthorizationMiddleware.redirectToRestricted = sinon.stub()
  177. @req.query =
  178. project_ids: "project1,project2"
  179. describe "with logged in user", ->
  180. beforeEach ->
  181. @AuthenticationController.getLoggedInUserId.returns(@user_id)
  182. describe "when user has permission to access all projects", ->
  183. beforeEach ->
  184. @AuthorizationManager.canUserReadProject
  185. .withArgs(@user_id, "project1", @token)
  186. .yields(null, true)
  187. @AuthorizationManager.canUserReadProject
  188. .withArgs(@user_id, "project2", @token)
  189. .yields(null, true)
  190. it "should return next", ->
  191. @AuthorizationMiddleware.ensureUserCanReadMultipleProjects @req, @res, @next
  192. @next.called.should.equal true
  193. describe "when user doesn't have permission to access one of the projects", ->
  194. beforeEach ->
  195. @AuthorizationManager.canUserReadProject
  196. .withArgs(@user_id, "project1", @token)
  197. .yields(null, true)
  198. @AuthorizationManager.canUserReadProject
  199. .withArgs(@user_id, "project2", @token)
  200. .yields(null, false)
  201. it "should redirect to redirectToRestricted", ->
  202. @AuthorizationMiddleware.ensureUserCanReadMultipleProjects @req, @res, @next
  203. @next.called.should.equal false
  204. @AuthorizationMiddleware.redirectToRestricted
  205. .calledWith(@req, @res, @next)
  206. .should.equal true
  207. describe "with anonymous user", ->
  208. describe "when user has permission", ->
  209. describe "when user has permission to access all projects", ->
  210. beforeEach ->
  211. @AuthenticationController.getLoggedInUserId.returns(null)
  212. @AuthorizationManager.canUserReadProject
  213. .withArgs(null, "project1", @token)
  214. .yields(null, true)
  215. @AuthorizationManager.canUserReadProject
  216. .withArgs(null, "project2", @token)
  217. .yields(null, true)
  218. it "should return next", ->
  219. @AuthorizationMiddleware.ensureUserCanReadMultipleProjects @req, @res, @next
  220. @next.called.should.equal true
  221. describe "when user doesn't have permission to access one of the projects", ->
  222. beforeEach ->
  223. @AuthenticationController.getLoggedInUserId.returns(null)
  224. @AuthorizationManager.canUserReadProject
  225. .withArgs(null, "project1", @token)
  226. .yields(null, true)
  227. @AuthorizationManager.canUserReadProject
  228. .withArgs(null, "project2", @token)
  229. .yields(null, false)
  230. it "should redirect to redirectToRestricted", ->
  231. @AuthorizationMiddleware.ensureUserCanReadMultipleProjects @req, @res, @next
  232. @next.called.should.equal false
  233. @AuthorizationMiddleware.redirectToRestricted
  234. .calledWith(@req, @res, @next)
  235. .should.equal true