TokenAccessHandlerTests.coffee 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. should = require('chai').should()
  2. SandboxedModule = require('sandboxed-module')
  3. assert = require('assert')
  4. path = require('path')
  5. sinon = require('sinon')
  6. modulePath = path.join __dirname, "../../../../app/js/Features/TokenAccess/TokenAccessHandler"
  7. expect = require("chai").expect
  8. ObjectId = require("mongojs").ObjectId
  9. describe "TokenAccessHandler", ->
  10. beforeEach ->
  11. @token = 'sometokenthing'
  12. @projectId = ObjectId()
  13. @project =
  14. _id: @projectId
  15. publicAccesLevel: 'tokenBased'
  16. @userId = ObjectId()
  17. @req = {}
  18. @TokenAccessHandler = SandboxedModule.require modulePath, requires:
  19. '../../models/Project': {Project: @Project = {}}
  20. describe 'findProjectWithReadOnlyToken', ->
  21. beforeEach ->
  22. @Project.findOne = sinon.stub().callsArgWith(2, null, @project)
  23. it 'should call Project.findOne', (done) ->
  24. @TokenAccessHandler.findProjectWithReadOnlyToken @token, (err, project) =>
  25. expect(@Project.findOne.callCount).to.equal 1
  26. expect(@Project.findOne.calledWith({
  27. 'tokens.readOnly': @token,
  28. 'publicAccesLevel': 'tokenBased'
  29. })).to.equal true
  30. done()
  31. it 'should produce a project object with no error', (done) ->
  32. @TokenAccessHandler.findProjectWithReadOnlyToken @token, (err, project) =>
  33. expect(err).to.not.exist
  34. expect(project).to.exist
  35. expect(project).to.deep.equal @project
  36. done()
  37. describe 'when Project.findOne produces an error', ->
  38. beforeEach ->
  39. @Project.findOne = sinon.stub().callsArgWith(2, new Error('woops'))
  40. it 'should produce an error', (done) ->
  41. @TokenAccessHandler.findProjectWithReadOnlyToken @token, (err, project) =>
  42. expect(err).to.exist
  43. expect(project).to.not.exist
  44. expect(err).to.be.instanceof Error
  45. done()
  46. describe 'findProjectWithReadAndWriteToken', ->
  47. beforeEach ->
  48. @Project.findOne = sinon.stub().callsArgWith(2, null, @project)
  49. it 'should call Project.findOne', (done) ->
  50. @TokenAccessHandler.findProjectWithReadAndWriteToken @token, (err, project) =>
  51. expect(@Project.findOne.callCount).to.equal 1
  52. expect(@Project.findOne.calledWith({
  53. 'tokens.readAndWrite': @token,
  54. 'publicAccesLevel': 'tokenBased'
  55. })).to.equal true
  56. done()
  57. it 'should produce a project object with no error', (done) ->
  58. @TokenAccessHandler.findProjectWithReadAndWriteToken @token, (err, project) =>
  59. expect(err).to.not.exist
  60. expect(project).to.exist
  61. expect(project).to.deep.equal @project
  62. done()
  63. describe 'when Project.findOne produces an error', ->
  64. beforeEach ->
  65. @Project.findOne = sinon.stub().callsArgWith(2, new Error('woops'))
  66. it 'should produce an error', (done) ->
  67. @TokenAccessHandler.findProjectWithReadAndWriteToken @token, (err, project) =>
  68. expect(err).to.exist
  69. expect(project).to.not.exist
  70. expect(err).to.be.instanceof Error
  71. done()
  72. describe 'addReadOnlyUserToProject', ->
  73. beforeEach ->
  74. @Project.update = sinon.stub().callsArgWith(2, null)
  75. it 'should call Project.update', (done) ->
  76. @TokenAccessHandler.addReadOnlyUserToProject @userId, @projectId, (err) =>
  77. expect(@Project.update.callCount).to.equal 1
  78. expect(@Project.update.calledWith({
  79. _id: @projectId
  80. })).to.equal true
  81. expect(@Project.update.lastCall.args[1]['$addToSet'])
  82. .to.have.keys 'tokenAccessReadOnly_refs'
  83. done()
  84. it 'should not produce an error', (done) ->
  85. @TokenAccessHandler.addReadOnlyUserToProject @userId, @projectId, (err) =>
  86. expect(err).to.not.exist
  87. done()
  88. describe 'when Project.update produces an error', ->
  89. beforeEach ->
  90. @Project.update = sinon.stub().callsArgWith(2, new Error('woops'))
  91. it 'should produce an error', (done) ->
  92. @TokenAccessHandler.addReadOnlyUserToProject @userId, @projectId, (err) =>
  93. expect(err).to.exist
  94. done()
  95. describe 'addReadAndWriteUserToProject', ->
  96. beforeEach ->
  97. @Project.update = sinon.stub().callsArgWith(2, null)
  98. it 'should call Project.update', (done) ->
  99. @TokenAccessHandler.addReadAndWriteUserToProject @userId, @projectId, (err) =>
  100. expect(@Project.update.callCount).to.equal 1
  101. expect(@Project.update.calledWith({
  102. _id: @projectId
  103. })).to.equal true
  104. expect(@Project.update.lastCall.args[1]['$addToSet'])
  105. .to.have.keys 'tokenAccessReadAndWrite_refs'
  106. done()
  107. it 'should not produce an error', (done) ->
  108. @TokenAccessHandler.addReadAndWriteUserToProject @userId, @projectId, (err) =>
  109. expect(err).to.not.exist
  110. done()
  111. describe 'when Project.update produces an error', ->
  112. beforeEach ->
  113. @Project.update = sinon.stub().callsArgWith(2, new Error('woops'))
  114. it 'should produce an error', (done) ->
  115. @TokenAccessHandler.addReadAndWriteUserToProject @userId, @projectId, (err) =>
  116. expect(err).to.exist
  117. done()
  118. describe 'grantSessionReadOnlyTokenAccess', ->
  119. beforeEach ->
  120. @req = {session: {}, headers: {}}
  121. it 'should add the token to the session', (done) ->
  122. @TokenAccessHandler.grantSessionReadOnlyTokenAccess(@req, @projectId, @token)
  123. expect(@req.session.anonReadOnlyTokenAccess[@projectId.toString()])
  124. .to.equal @token
  125. done()
  126. describe 'requestHasReadOnlyTokenAccess', ->
  127. beforeEach ->
  128. @req = {session: {}, headers: {}}
  129. @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub()
  130. .callsArgWith(1, null, @project)
  131. describe 'with header', ->
  132. beforeEach ->
  133. @req.headers['x-sl-anon-token'] = @token
  134. it 'should call findProjectWithReadOnlyToken', (done) ->
  135. @TokenAccessHandler.requestHasReadOnlyTokenAccess @req, @projectId, (err, allowed) =>
  136. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.callCount)
  137. .to.equal 1
  138. done()
  139. it 'should allow access', (done) ->
  140. @TokenAccessHandler.requestHasReadOnlyTokenAccess @req, @projectId, (err, allowed) =>
  141. expect(err).to.not.exist
  142. expect(allowed).to.equal true
  143. done()
  144. describe 'with session', ->
  145. beforeEach ->
  146. @req.session.anonReadOnlyTokenAccess = {}
  147. @req.session.anonReadOnlyTokenAccess[@projectId.toString()] = @token
  148. describe 'when no project is found', ->
  149. beforeEach ->
  150. @req.headers['x-sl-anon-token'] = @token
  151. @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub()
  152. .callsArgWith(1, null, null)
  153. it 'should call findProjectWithReadOnlyToken', (done) ->
  154. @TokenAccessHandler.requestHasReadOnlyTokenAccess @req, @projectId, (err, allowed) =>
  155. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.callCount)
  156. .to.equal 1
  157. done()
  158. it 'should not allow access', (done) ->
  159. @TokenAccessHandler.requestHasReadOnlyTokenAccess @req, @projectId, (err, allowed) =>
  160. expect(err).to.not.exist
  161. expect(allowed).to.equal false
  162. done()
  163. describe 'when no findProject produces an error', ->
  164. beforeEach ->
  165. @req.headers['x-sl-anon-token'] = @token
  166. @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub()
  167. .callsArgWith(1, new Error('woops'))
  168. it 'should call findProjectWithReadOnlyToken', (done) ->
  169. @TokenAccessHandler.requestHasReadOnlyTokenAccess @req, @projectId, (err, allowed) =>
  170. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.callCount)
  171. .to.equal 1
  172. done()
  173. it 'should produce an error and not allow access', (done) ->
  174. @TokenAccessHandler.requestHasReadOnlyTokenAccess @req, @projectId, (err, allowed) =>
  175. expect(err).to.exist
  176. expect(err).to.be.instanceof Error
  177. expect(allowed).to.equal undefined
  178. done()
  179. describe 'when project is not set to token-based access', ->
  180. beforeEach ->
  181. @req.headers['x-sl-anon-token'] = @token
  182. @project.publicAccesLevel = 'private'
  183. @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub()
  184. .callsArgWith(1, null, @project)
  185. it 'should call findProjectWithReadOnlyToken', (done) ->
  186. @TokenAccessHandler.requestHasReadOnlyTokenAccess @req, @projectId, (err, allowed) =>
  187. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.callCount)
  188. .to.equal 1
  189. done()
  190. it 'should not allow access', (done) ->
  191. @TokenAccessHandler.requestHasReadOnlyTokenAccess @req, @projectId, (err, allowed) =>
  192. expect(err).to.not.exist
  193. expect(allowed).to.equal false
  194. done()
  195. describe 'with nothing', ->
  196. beforeEach ->
  197. it 'should not call findProjectWithReadOnlyToken', (done) ->
  198. @TokenAccessHandler.requestHasReadOnlyTokenAccess @req, @projectId, (err, allowed) =>
  199. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.callCount)
  200. .to.equal 0
  201. done()
  202. it 'should not allow access', (done) ->
  203. @TokenAccessHandler.requestHasReadOnlyTokenAccess @req, @projectId, (err, allowed) =>
  204. expect(err).to.not.exist
  205. expect(allowed).to.equal false
  206. done()