TokenAccessControllerTests.coffee 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  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/TokenAccessController"
  7. expect = require("chai").expect
  8. ObjectId = require("mongojs").ObjectId
  9. MockRequest = require('../helpers/MockRequest')
  10. MockResponse = require('../helpers/MockResponse')
  11. Errors = require "../../../../app/js/Features/Errors/Errors.js"
  12. describe "TokenAccessController", ->
  13. beforeEach ->
  14. @readOnlyToken = 'somereadonlytoken'
  15. @readAndWriteToken = '42somereadandwritetoken'
  16. @projectId = ObjectId()
  17. @ownerId = 'owner'
  18. @project =
  19. _id: @projectId
  20. publicAccesLevel: 'tokenBased'
  21. tokens:
  22. readOnly: @readOnlyToken
  23. readAndWrite: @readAndWriteToken
  24. owner_ref: @ownerId
  25. @userId = ObjectId()
  26. @TokenAccessController = SandboxedModule.require modulePath, requires:
  27. '../Project/ProjectController': @ProjectController = {}
  28. '../Authentication/AuthenticationController': @AuthenticationController = {}
  29. './TokenAccessHandler': @TokenAccessHandler = {}
  30. 'logger-sharelatex': {log: sinon.stub(), err: sinon.stub()}
  31. @AuthenticationController.getLoggedInUserId = sinon.stub().returns(@userId.toString())
  32. describe 'readAndWriteToken', ->
  33. beforeEach ->
  34. describe 'when all goes well', ->
  35. beforeEach ->
  36. @req = new MockRequest()
  37. @res = new MockResponse()
  38. @next = sinon.stub()
  39. @req.params['read_and_write_token'] = @readAndWriteToken
  40. @TokenAccessHandler.findProjectWithReadAndWriteToken = sinon.stub()
  41. .callsArgWith(1, null, @project)
  42. @TokenAccessHandler.addReadAndWriteUserToProject = sinon.stub()
  43. .callsArgWith(2, null)
  44. @ProjectController.loadEditor = sinon.stub()
  45. @TokenAccessController.readAndWriteToken @req, @res, @next
  46. it 'should try to find a project with this token', (done) ->
  47. expect(@TokenAccessHandler.findProjectWithReadAndWriteToken.callCount)
  48. .to.equal 1
  49. expect(@TokenAccessHandler.findProjectWithReadAndWriteToken.calledWith(@readAndWriteToken))
  50. .to.equal true
  51. done()
  52. it 'should add the user to the project with read-write access', (done) ->
  53. expect(@TokenAccessHandler.addReadAndWriteUserToProject.callCount)
  54. .to.equal 1
  55. expect(@TokenAccessHandler.addReadAndWriteUserToProject.calledWith(
  56. @userId.toString(), @projectId
  57. ))
  58. .to.equal true
  59. done()
  60. it 'should pass control to loadEditor', (done) ->
  61. expect(@req.params.Project_id).to.equal @projectId.toString()
  62. expect(@ProjectController.loadEditor.callCount).to.equal 1
  63. expect(@ProjectController.loadEditor.calledWith(@req, @res, @next)).to.equal true
  64. done()
  65. describe 'when the user is already the owner', ->
  66. beforeEach ->
  67. @req = new MockRequest()
  68. @res = new MockResponse()
  69. @next = sinon.stub()
  70. @req.params['read_and_write_token'] = @readAndWriteToken
  71. @project.owner_ref = @userId
  72. @TokenAccessHandler.findProjectWithReadAndWriteToken = sinon.stub()
  73. .callsArgWith(1, null, @project)
  74. @TokenAccessHandler.addReadAndWriteUserToProject = sinon.stub()
  75. .callsArgWith(2, null)
  76. @ProjectController.loadEditor = sinon.stub()
  77. @TokenAccessController.readAndWriteToken @req, @res, @next
  78. it 'should try to find a project with this token', (done) ->
  79. expect(@TokenAccessHandler.findProjectWithReadAndWriteToken.callCount)
  80. .to.equal 1
  81. expect(@TokenAccessHandler.findProjectWithReadAndWriteToken.calledWith(@readAndWriteToken))
  82. .to.equal true
  83. done()
  84. it 'should not add the user to the project with read-write access', (done) ->
  85. expect(@TokenAccessHandler.addReadAndWriteUserToProject.callCount)
  86. .to.equal 0
  87. done()
  88. it 'should pass control to loadEditor', (done) ->
  89. expect(@req.params.Project_id).to.equal @projectId.toString()
  90. expect(@ProjectController.loadEditor.callCount).to.equal 1
  91. expect(@ProjectController.loadEditor.calledWith(@req, @res, @next)).to.equal true
  92. done()
  93. describe 'when findProject produces an error', ->
  94. beforeEach ->
  95. @req = new MockRequest()
  96. @res = new MockResponse()
  97. @next = sinon.stub()
  98. @req.params['read_and_write_token'] = @readAndWriteToken
  99. @TokenAccessHandler.findProjectWithReadAndWriteToken = sinon.stub()
  100. .callsArgWith(1, new Error('woops'))
  101. @TokenAccessHandler.addReadAndWriteUserToProject = sinon.stub()
  102. .callsArgWith(2, null)
  103. @ProjectController.loadEditor = sinon.stub()
  104. @TokenAccessController.readAndWriteToken @req, @res, @next
  105. it 'should try to find a project with this token', (done) ->
  106. expect(@TokenAccessHandler.findProjectWithReadAndWriteToken.callCount)
  107. .to.equal 1
  108. expect(@TokenAccessHandler.findProjectWithReadAndWriteToken.calledWith(@readAndWriteToken))
  109. .to.equal true
  110. done()
  111. it 'should not add the user to the project with read-write access', (done) ->
  112. expect(@TokenAccessHandler.addReadAndWriteUserToProject.callCount)
  113. .to.equal 0
  114. done()
  115. it 'should not pass control to loadEditor', (done) ->
  116. expect(@ProjectController.loadEditor.callCount).to.equal 0
  117. expect(@ProjectController.loadEditor.calledWith(@req, @res, @next)).to.equal false
  118. done()
  119. it 'should call next with an error', (done) ->
  120. expect(@next.callCount).to.equal 1
  121. expect(@next.lastCall.args[0]).to.be.instanceof Error
  122. done()
  123. describe 'when findProject does not find a project', ->
  124. beforeEach ->
  125. describe 'when it is a private overleaf project', ->
  126. beforeEach ->
  127. @req = new MockRequest()
  128. @res = new MockResponse()
  129. @res.redirect = sinon.stub()
  130. @next = sinon.stub()
  131. @req.params['read_and_write_token'] = @readAndWriteToken
  132. @TokenAccessHandler.findProjectWithReadAndWriteToken = sinon.stub()
  133. .callsArgWith(1, null, null)
  134. @TokenAccessHandler.findPrivateOverleafProjectWithReadAndWriteToken =
  135. sinon.stub()
  136. .callsArgWith(1, null, @project)
  137. @TokenAccessHandler.addReadAndWriteUserToProject = sinon.stub()
  138. .callsArgWith(2, null)
  139. @ProjectController.loadEditor = sinon.stub()
  140. @TokenAccessController.readAndWriteToken @req, @res, @next
  141. it 'should try to find a project with this token', (done) ->
  142. expect(@TokenAccessHandler.findProjectWithReadAndWriteToken.callCount)
  143. .to.equal 1
  144. expect(@TokenAccessHandler.findProjectWithReadAndWriteToken.calledWith(@readAndWriteToken))
  145. .to.equal true
  146. done()
  147. it 'should try to find a private overleaf project', (done) ->
  148. expect(
  149. @TokenAccessHandler.findPrivateOverleafProjectWithReadAndWriteToken
  150. .callCount
  151. ).to.equal 1
  152. expect(
  153. @TokenAccessHandler.findPrivateOverleafProjectWithReadAndWriteToken
  154. .calledWith(@readAndWriteToken)
  155. ).to.equal true
  156. done()
  157. it 'should not add the user to the project with read-write access', (done) ->
  158. expect(@TokenAccessHandler.addReadAndWriteUserToProject.callCount)
  159. .to.equal 0
  160. done()
  161. it 'should not pass control to loadEditor', (done) ->
  162. expect(@ProjectController.loadEditor.callCount).to.equal 0
  163. expect(@ProjectController.loadEditor.calledWith(@req, @res, @next)).to.equal false
  164. done()
  165. it 'should not call next with a not-found error', (done) ->
  166. expect(@next.callCount).to.equal 0
  167. done()
  168. it 'should redirect to the canonical project url', (done) ->
  169. expect(@res.redirect.callCount).to.equal 1
  170. expect(@res.redirect.calledWith(302, "/project/#{@project._id}")).to.equal true
  171. done()
  172. describe 'when it is not a private overleaf project', ->
  173. beforeEach ->
  174. @req = new MockRequest()
  175. @res = new MockResponse()
  176. @next = sinon.stub()
  177. @req.params['read_and_write_token'] = @readAndWriteToken
  178. @TokenAccessHandler.findProjectWithReadAndWriteToken = sinon.stub()
  179. .callsArgWith(1, null, null)
  180. @TokenAccessHandler.findPrivateOverleafProjectWithReadAndWriteToken =
  181. sinon.stub()
  182. .callsArgWith(1, null, null)
  183. @TokenAccessHandler.addReadAndWriteUserToProject = sinon.stub()
  184. .callsArgWith(2, null)
  185. @ProjectController.loadEditor = sinon.stub()
  186. @TokenAccessController.readAndWriteToken @req, @res, @next
  187. it 'should try to find a project with this token', (done) ->
  188. expect(@TokenAccessHandler.findProjectWithReadAndWriteToken.callCount)
  189. .to.equal 1
  190. expect(@TokenAccessHandler.findProjectWithReadAndWriteToken.calledWith(
  191. @readAndWriteToken
  192. )).to.equal true
  193. done()
  194. it 'should not add the user to the project with read-write access', (done) ->
  195. expect(@TokenAccessHandler.addReadAndWriteUserToProject.callCount)
  196. .to.equal 0
  197. done()
  198. it 'should not pass control to loadEditor', (done) ->
  199. expect(@ProjectController.loadEditor.callCount).to.equal 0
  200. expect(@ProjectController.loadEditor.calledWith(@req, @res, @next)).to.equal false
  201. done()
  202. it 'should call next with a not-found error', (done) ->
  203. expect(@next.callCount).to.equal 1
  204. expect(@next.lastCall.args[0]).to.be.instanceof Error
  205. done()
  206. describe 'when adding user to project produces an error', ->
  207. beforeEach ->
  208. @req = new MockRequest()
  209. @res = new MockResponse()
  210. @next = sinon.stub()
  211. @req.params['read_and_write_token'] = @readAndWriteToken
  212. @TokenAccessHandler.findProjectWithReadAndWriteToken = sinon.stub()
  213. .callsArgWith(1, null, @project)
  214. @TokenAccessHandler.addReadAndWriteUserToProject = sinon.stub()
  215. .callsArgWith(2, new Error('woops'))
  216. @ProjectController.loadEditor = sinon.stub()
  217. @TokenAccessController.readAndWriteToken @req, @res, @next
  218. it 'should try to find a project with this token', (done) ->
  219. expect(@TokenAccessHandler.findProjectWithReadAndWriteToken.callCount)
  220. .to.equal 1
  221. expect(@TokenAccessHandler.findProjectWithReadAndWriteToken.calledWith(@readAndWriteToken))
  222. .to.equal true
  223. done()
  224. it 'should add the user to the project with read-write access', (done) ->
  225. expect(@TokenAccessHandler.addReadAndWriteUserToProject.callCount)
  226. .to.equal 1
  227. expect(@TokenAccessHandler.addReadAndWriteUserToProject.calledWith(
  228. @userId.toString(), @projectId
  229. ))
  230. .to.equal true
  231. done()
  232. it 'should not pass control to loadEditor', (done) ->
  233. expect(@ProjectController.loadEditor.callCount).to.equal 0
  234. expect(@ProjectController.loadEditor.calledWith(@req, @res, @next)).to.equal false
  235. done()
  236. it 'should call next with an error', (done) ->
  237. expect(@next.callCount).to.equal 1
  238. expect(@next.lastCall.args[0]).to.be.instanceof Error
  239. done()
  240. describe 'readOnlyToken', ->
  241. beforeEach ->
  242. describe 'with a user', ->
  243. beforeEach ->
  244. @AuthenticationController.getLoggedInUserId = sinon.stub().returns(@userId.toString())
  245. describe 'when all goes well', ->
  246. beforeEach ->
  247. @req = new MockRequest()
  248. @res = new MockResponse()
  249. @next = sinon.stub()
  250. @req.params['read_only_token'] = @readOnlyToken
  251. @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub()
  252. .callsArgWith(1, null, @project)
  253. @TokenAccessHandler.addReadOnlyUserToProject = sinon.stub()
  254. .callsArgWith(2, null)
  255. @ProjectController.loadEditor = sinon.stub()
  256. @TokenAccessController.readOnlyToken @req, @res, @next
  257. it 'should try to find a project with this token', (done) ->
  258. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.callCount)
  259. .to.equal 1
  260. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.calledWith(@readOnlyToken))
  261. .to.equal true
  262. done()
  263. it 'should add the user to the project with read-only access', (done) ->
  264. expect(@TokenAccessHandler.addReadOnlyUserToProject.callCount)
  265. .to.equal 1
  266. expect(@TokenAccessHandler.addReadOnlyUserToProject.calledWith(
  267. @userId.toString(), @projectId
  268. ))
  269. .to.equal true
  270. done()
  271. it 'should pass control to loadEditor', (done) ->
  272. expect(@req.params.Project_id).to.equal @projectId.toString()
  273. expect(@ProjectController.loadEditor.callCount).to.equal 1
  274. expect(@ProjectController.loadEditor.calledWith(@req, @res, @next)).to.equal true
  275. done()
  276. describe 'when the user is already the owner', ->
  277. beforeEach ->
  278. @req = new MockRequest()
  279. @res = new MockResponse()
  280. @next = sinon.stub()
  281. @req.params['read_only_token'] = @readOnlyToken
  282. @project.owner_ref = @userId
  283. @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub()
  284. .callsArgWith(1, null, @project)
  285. @TokenAccessHandler.addReadOnlyUserToProject = sinon.stub()
  286. .callsArgWith(2, null)
  287. @ProjectController.loadEditor = sinon.stub()
  288. @TokenAccessController.readOnlyToken @req, @res, @next
  289. it 'should try to find a project with this token', (done) ->
  290. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.callCount)
  291. .to.equal 1
  292. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.calledWith(@readOnlyToken))
  293. .to.equal true
  294. done()
  295. it 'should not add the user to the project with read-only access', (done) ->
  296. expect(@TokenAccessHandler.addReadOnlyUserToProject.callCount)
  297. .to.equal 0
  298. done()
  299. it 'should pass control to loadEditor', (done) ->
  300. expect(@req.params.Project_id).to.equal @projectId.toString()
  301. expect(@ProjectController.loadEditor.callCount).to.equal 1
  302. expect(@ProjectController.loadEditor.calledWith(@req, @res, @next)).to.equal true
  303. done()
  304. describe 'when findProject produces an error', ->
  305. beforeEach ->
  306. @req = new MockRequest()
  307. @res = new MockResponse()
  308. @next = sinon.stub()
  309. @req.params['read_only_token'] = @readOnlyToken
  310. @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub()
  311. .callsArgWith(1, new Error('woops'))
  312. @TokenAccessHandler.addReadOnlyUserToProject = sinon.stub()
  313. .callsArgWith(2, null)
  314. @ProjectController.loadEditor = sinon.stub()
  315. @TokenAccessController.readOnlyToken @req, @res, @next
  316. it 'should try to find a project with this token', (done) ->
  317. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.callCount)
  318. .to.equal 1
  319. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.calledWith(@readOnlyToken))
  320. .to.equal true
  321. done()
  322. it 'should not add the user to the project with read-only access', (done) ->
  323. expect(@TokenAccessHandler.addReadOnlyUserToProject.callCount)
  324. .to.equal 0
  325. done()
  326. it 'should not pass control to loadEditor', (done) ->
  327. expect(@ProjectController.loadEditor.callCount).to.equal 0
  328. expect(@ProjectController.loadEditor.calledWith(@req, @res, @next)).to.equal false
  329. done()
  330. it 'should call next with an error', (done) ->
  331. expect(@next.callCount).to.equal 1
  332. expect(@next.lastCall.args[0]).to.be.instanceof Error
  333. done()
  334. describe 'when findProject does not find a project', ->
  335. beforeEach ->
  336. @req = new MockRequest()
  337. @res = new MockResponse()
  338. @next = sinon.stub()
  339. @req.params['read_only_token'] = @readOnlyToken
  340. @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub()
  341. .callsArgWith(1, null, null)
  342. @TokenAccessHandler.addReadOnlyUserToProject = sinon.stub()
  343. .callsArgWith(2, null)
  344. @ProjectController.loadEditor = sinon.stub()
  345. @TokenAccessController.readOnlyToken @req, @res, @next
  346. it 'should try to find a project with this token', (done) ->
  347. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.callCount)
  348. .to.equal 1
  349. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.calledWith(@readOnlyToken))
  350. .to.equal true
  351. done()
  352. it 'should not add the user to the project with read-only access', (done) ->
  353. expect(@TokenAccessHandler.addReadOnlyUserToProject.callCount)
  354. .to.equal 0
  355. done()
  356. it 'should not pass control to loadEditor', (done) ->
  357. expect(@ProjectController.loadEditor.callCount).to.equal 0
  358. expect(@ProjectController.loadEditor.calledWith(@req, @res, @next)).to.equal false
  359. done()
  360. it 'should call next with a not-found error', (done) ->
  361. expect(@next.callCount).to.equal 1
  362. expect(@next.lastCall.args[0]).to.be.instanceof Error
  363. done()
  364. describe 'when adding user to project produces an error', ->
  365. beforeEach ->
  366. @req = new MockRequest()
  367. @res = new MockResponse()
  368. @next = sinon.stub()
  369. @req.params['read_only_token'] = @readOnlyToken
  370. @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub()
  371. .callsArgWith(1, null, @project)
  372. @TokenAccessHandler.addReadOnlyUserToProject = sinon.stub()
  373. .callsArgWith(2, new Error('woops'))
  374. @ProjectController.loadEditor = sinon.stub()
  375. @TokenAccessController.readOnlyToken @req, @res, @next
  376. it 'should try to find a project with this token', (done) ->
  377. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.callCount)
  378. .to.equal 1
  379. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.calledWith(@readOnlyToken))
  380. .to.equal true
  381. done()
  382. it 'should add the user to the project with read-only access', (done) ->
  383. expect(@TokenAccessHandler.addReadOnlyUserToProject.callCount)
  384. .to.equal 1
  385. expect(@TokenAccessHandler.addReadOnlyUserToProject.calledWith(
  386. @userId.toString(), @projectId
  387. ))
  388. .to.equal true
  389. done()
  390. it 'should not pass control to loadEditor', (done) ->
  391. expect(@ProjectController.loadEditor.callCount).to.equal 0
  392. expect(@ProjectController.loadEditor.calledWith(@req, @res, @next)).to.equal false
  393. done()
  394. it 'should call next with an error', (done) ->
  395. expect(@next.callCount).to.equal 1
  396. expect(@next.lastCall.args[0]).to.be.instanceof Error
  397. done()
  398. describe 'anonymous', ->
  399. beforeEach ->
  400. @AuthenticationController.getLoggedInUserId = sinon.stub().returns(null)
  401. @TokenAccessHandler.grantSessionTokenAccess = sinon.stub()
  402. describe 'when all goes well', ->
  403. beforeEach ->
  404. @req = new MockRequest()
  405. @res = new MockResponse()
  406. @next = sinon.stub()
  407. @req.params['read_only_token'] = @readOnlyToken
  408. @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub()
  409. .callsArgWith(1, null, @project)
  410. @TokenAccessHandler.addReadOnlyUserToProject = sinon.stub()
  411. .callsArgWith(2, null)
  412. @ProjectController.loadEditor = sinon.stub()
  413. @TokenAccessController.readOnlyToken @req, @res, @next
  414. it 'should try to find a project with this token', (done) ->
  415. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.callCount)
  416. .to.equal 1
  417. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.calledWith(@readOnlyToken))
  418. .to.equal true
  419. done()
  420. it 'should give the user session read-only access', (done) ->
  421. expect(@TokenAccessHandler.grantSessionTokenAccess.callCount)
  422. .to.equal 1
  423. expect(@TokenAccessHandler.grantSessionTokenAccess.calledWith(
  424. @req, @projectId, @readOnlyToken
  425. ))
  426. .to.equal true
  427. done()
  428. it 'should not add the user to the project with read-only access', (done) ->
  429. expect(@TokenAccessHandler.addReadOnlyUserToProject.callCount)
  430. .to.equal 0
  431. done()
  432. it 'should pass control to loadEditor', (done) ->
  433. expect(@req.params.Project_id).to.equal @projectId.toString()
  434. expect(@req._anonToken).to.equal @readOnlyToken
  435. expect(@ProjectController.loadEditor.callCount).to.equal 1
  436. expect(@ProjectController.loadEditor.calledWith(@req, @res, @next)).to.equal true
  437. done()
  438. describe 'when findProject produces an error', ->
  439. beforeEach ->
  440. @req = new MockRequest()
  441. @res = new MockResponse()
  442. @next = sinon.stub()
  443. @req.params['read_only_token'] = @readOnlyToken
  444. @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub()
  445. .callsArgWith(1, new Error('woops'))
  446. @TokenAccessHandler.addReadOnlyUserToProject = sinon.stub()
  447. .callsArgWith(2, null)
  448. @ProjectController.loadEditor = sinon.stub()
  449. @TokenAccessController.readOnlyToken @req, @res, @next
  450. it 'should try to find a project with this token', (done) ->
  451. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.callCount)
  452. .to.equal 1
  453. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.calledWith(@readOnlyToken))
  454. .to.equal true
  455. done()
  456. it 'should not give the user session read-only access', (done) ->
  457. expect(@TokenAccessHandler.grantSessionTokenAccess.callCount)
  458. .to.equal 0
  459. done()
  460. it 'should not add the user to the project with read-only access', (done) ->
  461. expect(@TokenAccessHandler.addReadOnlyUserToProject.callCount)
  462. .to.equal 0
  463. done()
  464. it 'should not pass control to loadEditor', (done) ->
  465. expect(@ProjectController.loadEditor.callCount).to.equal 0
  466. expect(@ProjectController.loadEditor.calledWith(@req, @res, @next)).to.equal false
  467. done()
  468. it 'should call next with an error', (done) ->
  469. expect(@next.callCount).to.equal 1
  470. expect(@next.lastCall.args[0]).to.be.instanceof Error
  471. done()
  472. describe 'when findProject does not find a project', ->
  473. beforeEach ->
  474. @req = new MockRequest()
  475. @res = new MockResponse()
  476. @next = sinon.stub()
  477. @req.params['read_only_token'] = @readOnlyToken
  478. @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub()
  479. .callsArgWith(1, null, null)
  480. @TokenAccessHandler.addReadOnlyUserToProject = sinon.stub()
  481. .callsArgWith(2, null)
  482. @ProjectController.loadEditor = sinon.stub()
  483. @TokenAccessController.readOnlyToken @req, @res, @next
  484. it 'should try to find a project with this token', (done) ->
  485. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.callCount)
  486. .to.equal 1
  487. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.calledWith(@readOnlyToken))
  488. .to.equal true
  489. done()
  490. it 'should not give the user session read-only access', (done) ->
  491. expect(@TokenAccessHandler.grantSessionTokenAccess.callCount)
  492. .to.equal 0
  493. done()
  494. it 'should not pass control to loadEditor', (done) ->
  495. expect(@ProjectController.loadEditor.callCount).to.equal 0
  496. expect(@ProjectController.loadEditor.calledWith(@req, @res, @next)).to.equal false
  497. done()
  498. it 'should not add the user to the project with read-only access', (done) ->
  499. expect(@TokenAccessHandler.addReadOnlyUserToProject.callCount)
  500. .to.equal 0
  501. done()
  502. it 'should call next with a not-found error', (done) ->
  503. expect(@next.callCount).to.equal 1
  504. expect(@next.lastCall.args[0]).to.be.instanceof Error
  505. done()