TokenAccessHandlerTests.coffee 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  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. 'settings-sharelatex': @settings = {}
  21. '../Collaborators/CollaboratorsHandler': @CollaboratorsHandler = {}
  22. '../User/UserGetter': @UserGetter = {}
  23. '../V1/V1Api': @V1Api = {
  24. request: sinon.stub()
  25. }
  26. describe 'findProjectWithReadOnlyToken', ->
  27. beforeEach ->
  28. @Project.findOne = sinon.stub().callsArgWith(2, null, @project)
  29. it 'should call Project.findOne', (done) ->
  30. @TokenAccessHandler.findProjectWithReadOnlyToken @token, (err, project) =>
  31. expect(@Project.findOne.callCount).to.equal 1
  32. expect(@Project.findOne.calledWith({
  33. 'tokens.readOnly': @token
  34. })).to.equal true
  35. done()
  36. it 'should produce a project object with no error', (done) ->
  37. @TokenAccessHandler.findProjectWithReadOnlyToken @token, (err, project) =>
  38. expect(err).to.not.exist
  39. expect(project).to.exist
  40. expect(project).to.deep.equal @project
  41. done()
  42. it 'should return projectExists flag as true', (done) ->
  43. @TokenAccessHandler.findProjectWithReadOnlyToken @token, (err, project, projectExists) ->
  44. expect(projectExists).to.equal true
  45. done()
  46. describe 'when Project.findOne produces an error', ->
  47. beforeEach ->
  48. @Project.findOne = sinon.stub().callsArgWith(2, new Error('woops'))
  49. it 'should produce an error', (done) ->
  50. @TokenAccessHandler.findProjectWithReadOnlyToken @token, (err, project) =>
  51. expect(err).to.exist
  52. expect(project).to.not.exist
  53. expect(err).to.be.instanceof Error
  54. done()
  55. describe 'when project does not have tokenBased access level', ->
  56. beforeEach ->
  57. @project.publicAccesLevel = 'private'
  58. @Project.findOne = sinon.stub().callsArgWith(2, null, @project, true)
  59. it 'should not return a project', (done) ->
  60. @TokenAccessHandler.findProjectWithReadOnlyToken @token, (err, project) ->
  61. expect(err).to.not.exist
  62. expect(project).to.not.exist
  63. done()
  64. it 'should return projectExists flag as true', (done) ->
  65. @TokenAccessHandler.findProjectWithReadOnlyToken @token, (err, project, projectExists) ->
  66. expect(projectExists).to.equal true
  67. done()
  68. describe 'when project does not exist', ->
  69. beforeEach ->
  70. @Project.findOne = sinon.stub().callsArgWith(2, null, null)
  71. it 'should not return a project', (done) ->
  72. @TokenAccessHandler.findProjectWithReadOnlyToken @token, (err, project) ->
  73. expect(err).to.not.exist
  74. expect(project).to.not.exist
  75. done()
  76. it 'should return projectExists flag as false', (done) ->
  77. @TokenAccessHandler.findProjectWithReadOnlyToken @token, (err, project, projectExists) ->
  78. expect(projectExists).to.equal false
  79. done()
  80. describe 'findProjectWithReadAndWriteToken', ->
  81. beforeEach ->
  82. @Project.findOne = sinon.stub().callsArgWith(2, null, @project)
  83. it 'should call Project.findOne', (done) ->
  84. @TokenAccessHandler.findProjectWithReadAndWriteToken @token, (err, project) =>
  85. expect(@Project.findOne.callCount).to.equal 1
  86. expect(@Project.findOne.calledWith({
  87. 'tokens.readAndWrite': @token
  88. })).to.equal true
  89. done()
  90. it 'should produce a project object with no error', (done) ->
  91. @TokenAccessHandler.findProjectWithReadAndWriteToken @token, (err, project) =>
  92. expect(err).to.not.exist
  93. expect(project).to.exist
  94. expect(project).to.deep.equal @project
  95. done()
  96. it 'should return projectExists flag as true', (done) ->
  97. @TokenAccessHandler.findProjectWithReadAndWriteToken @token, (err, project, projectExists) ->
  98. expect(projectExists).to.equal true
  99. done()
  100. describe 'when Project.findOne produces an error', ->
  101. beforeEach ->
  102. @Project.findOne = sinon.stub().callsArgWith(2, new Error('woops'))
  103. it 'should produce an error', (done) ->
  104. @TokenAccessHandler.findProjectWithReadAndWriteToken @token, (err, project) =>
  105. expect(err).to.exist
  106. expect(project).to.not.exist
  107. expect(err).to.be.instanceof Error
  108. done()
  109. describe 'when project does not have tokenBased access level', ->
  110. beforeEach ->
  111. @project.publicAccesLevel = 'private'
  112. @Project.findOne = sinon.stub().callsArgWith(2, null, @project, true)
  113. it 'should not return a project', (done) ->
  114. @TokenAccessHandler.findProjectWithReadAndWriteToken @token, (err, project) ->
  115. expect(err).to.not.exist
  116. expect(project).to.not.exist
  117. done()
  118. it 'should return projectExists flag as true', (done) ->
  119. @TokenAccessHandler.findProjectWithReadAndWriteToken @token, (err, project, projectExists) ->
  120. expect(projectExists).to.equal true
  121. done()
  122. describe 'findProjectWithHigherAccess', ->
  123. describe 'when user does have higher access', ->
  124. beforeEach ->
  125. @Project.findOne = sinon.stub().callsArgWith(2, null, @project)
  126. @CollaboratorsHandler.isUserInvitedMemberOfProject = sinon.stub()
  127. .callsArgWith(2, null, true)
  128. it 'should call Project.findOne', (done) ->
  129. @TokenAccessHandler.findProjectWithHigherAccess @token, @userId, (err, project) =>
  130. expect(@Project.findOne.callCount).to.equal 1
  131. expect(@Project.findOne.calledWith($or: [
  132. {'tokens.readAndWrite': @token},
  133. {'tokens.readOnly': @token}
  134. ])).to.equal true
  135. done()
  136. it 'should call isUserInvitedMemberOfProject', (done) ->
  137. @TokenAccessHandler.findProjectWithHigherAccess @token, @userId, (err, project) =>
  138. expect(@CollaboratorsHandler.isUserInvitedMemberOfProject.callCount)
  139. .to.equal 1
  140. expect(@CollaboratorsHandler.isUserInvitedMemberOfProject.calledWith(
  141. @userId, @project._id
  142. )).to.equal true
  143. done()
  144. it 'should produce a project object', (done) ->
  145. @TokenAccessHandler.findProjectWithHigherAccess @token, @userId, (err, project) =>
  146. expect(err).to.not.exist
  147. expect(project).to.exist
  148. expect(project).to.deep.equal @project
  149. done()
  150. describe 'when user does not have higher access', ->
  151. beforeEach ->
  152. @Project.findOne = sinon.stub().callsArgWith(2, null, @project)
  153. @CollaboratorsHandler.isUserInvitedMemberOfProject = sinon.stub()
  154. .callsArgWith(2, null, false)
  155. it 'should call Project.findOne', (done) ->
  156. @TokenAccessHandler.findProjectWithHigherAccess @token, @userId, (err, project) =>
  157. expect(@Project.findOne.callCount).to.equal 1
  158. expect(@Project.findOne.calledWith($or: [
  159. {'tokens.readAndWrite': @token},
  160. {'tokens.readOnly': @token}
  161. ])).to.equal true
  162. done()
  163. it 'should call isUserInvitedMemberOfProject', (done) ->
  164. @TokenAccessHandler.findProjectWithHigherAccess @token, @userId, (err, project) =>
  165. expect(@CollaboratorsHandler.isUserInvitedMemberOfProject.callCount)
  166. .to.equal 1
  167. expect(@CollaboratorsHandler.isUserInvitedMemberOfProject.calledWith(
  168. @userId, @project._id
  169. )).to.equal true
  170. done()
  171. it 'should not produce a project', (done) ->
  172. @TokenAccessHandler.findProjectWithHigherAccess @token, @userId, (err, project) =>
  173. expect(err).to.not.exist
  174. expect(project).to.not.exist
  175. done()
  176. describe 'when Project.findOne produces an error', ->
  177. beforeEach ->
  178. @Project.findOne = sinon.stub().callsArgWith(2, new Error('woops'))
  179. it 'should produce an error', (done) ->
  180. @TokenAccessHandler.findProjectWithHigherAccess @token, @userId, (err, project) =>
  181. expect(err).to.exist
  182. expect(project).to.not.exist
  183. expect(err).to.be.instanceof Error
  184. done()
  185. describe 'when isUserInvitedMemberOfProject produces an error', ->
  186. beforeEach ->
  187. @Project.findOne = sinon.stub().callsArgWith(2, null, @project)
  188. @CollaboratorsHandler.isUserInvitedMemberOfProject = sinon.stub()
  189. .callsArgWith(2, new Error('woops'))
  190. it 'should produce an error', (done) ->
  191. @TokenAccessHandler.findProjectWithHigherAccess @token, @userId, (err, project) =>
  192. expect(err).to.exist
  193. expect(project).to.not.exist
  194. expect(err).to.be.instanceof Error
  195. done()
  196. describe 'addReadOnlyUserToProject', ->
  197. beforeEach ->
  198. @Project.update = sinon.stub().callsArgWith(2, null)
  199. it 'should call Project.update', (done) ->
  200. @TokenAccessHandler.addReadOnlyUserToProject @userId, @projectId, (err) =>
  201. expect(@Project.update.callCount).to.equal 1
  202. expect(@Project.update.calledWith({
  203. _id: @projectId
  204. })).to.equal true
  205. expect(@Project.update.lastCall.args[1]['$addToSet'])
  206. .to.have.keys 'tokenAccessReadOnly_refs'
  207. done()
  208. it 'should not produce an error', (done) ->
  209. @TokenAccessHandler.addReadOnlyUserToProject @userId, @projectId, (err) =>
  210. expect(err).to.not.exist
  211. done()
  212. describe 'when Project.update produces an error', ->
  213. beforeEach ->
  214. @Project.update = sinon.stub().callsArgWith(2, new Error('woops'))
  215. it 'should produce an error', (done) ->
  216. @TokenAccessHandler.addReadOnlyUserToProject @userId, @projectId, (err) =>
  217. expect(err).to.exist
  218. done()
  219. describe 'addReadAndWriteUserToProject', ->
  220. beforeEach ->
  221. @Project.update = sinon.stub().callsArgWith(2, null)
  222. it 'should call Project.update', (done) ->
  223. @TokenAccessHandler.addReadAndWriteUserToProject @userId, @projectId, (err) =>
  224. expect(@Project.update.callCount).to.equal 1
  225. expect(@Project.update.calledWith({
  226. _id: @projectId
  227. })).to.equal true
  228. expect(@Project.update.lastCall.args[1]['$addToSet'])
  229. .to.have.keys 'tokenAccessReadAndWrite_refs'
  230. done()
  231. it 'should not produce an error', (done) ->
  232. @TokenAccessHandler.addReadAndWriteUserToProject @userId, @projectId, (err) =>
  233. expect(err).to.not.exist
  234. done()
  235. describe 'when Project.update produces an error', ->
  236. beforeEach ->
  237. @Project.update = sinon.stub().callsArgWith(2, new Error('woops'))
  238. it 'should produce an error', (done) ->
  239. @TokenAccessHandler.addReadAndWriteUserToProject @userId, @projectId, (err) =>
  240. expect(err).to.exist
  241. done()
  242. describe 'grantSessionTokenAccess', ->
  243. beforeEach ->
  244. @req = {session: {}, headers: {}}
  245. it 'should add the token to the session', (done) ->
  246. @TokenAccessHandler.grantSessionTokenAccess(@req, @projectId, @token)
  247. expect(@req.session.anonTokenAccess[@projectId.toString()])
  248. .to.equal @token
  249. done()
  250. describe 'isValidToken', ->
  251. describe 'when a read-only project is found', ->
  252. beforeEach ->
  253. @TokenAccessHandler.findProjectWithReadAndWriteToken = sinon.stub()
  254. .callsArgWith(1, null, null)
  255. @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub()
  256. .callsArgWith(1, null, @project)
  257. it 'should try to find projects with both kinds of token', (done) ->
  258. @TokenAccessHandler.isValidToken @projectId, @token, (err, allowed) =>
  259. expect(@TokenAccessHandler.findProjectWithReadAndWriteToken.callCount)
  260. .to.equal 1
  261. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.callCount)
  262. .to.equal 1
  263. done()
  264. it 'should allow read-only access', (done) ->
  265. @TokenAccessHandler.isValidToken @projectId, @token, (err, rw, ro) =>
  266. expect(err).to.not.exist
  267. expect(rw).to.equal false
  268. expect(ro).to.equal true
  269. done()
  270. describe 'when a read-and-write project is found', ->
  271. beforeEach ->
  272. @TokenAccessHandler.findProjectWithReadAndWriteToken = sinon.stub()
  273. .callsArgWith(1, null, @project)
  274. @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub()
  275. .callsArgWith(1, null, null)
  276. it 'should try to find projects with both kinds of token', (done) ->
  277. @TokenAccessHandler.isValidToken @projectId, @token, (err, allowed) =>
  278. expect(@TokenAccessHandler.findProjectWithReadAndWriteToken.callCount)
  279. .to.equal 1
  280. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.callCount)
  281. .to.equal 1
  282. done()
  283. it 'should allow read-and-write access', (done) ->
  284. @TokenAccessHandler.isValidToken @projectId, @token, (err, rw, ro) =>
  285. expect(err).to.not.exist
  286. expect(rw).to.equal true
  287. expect(ro).to.equal false
  288. done()
  289. describe 'when no project is found', ->
  290. beforeEach ->
  291. @TokenAccessHandler.findProjectWithReadAndWriteToken = sinon.stub()
  292. .callsArgWith(1, null, null)
  293. @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub()
  294. .callsArgWith(1, null, null)
  295. it 'should try to find projects with both kinds of token', (done) ->
  296. @TokenAccessHandler.isValidToken @projectId, @token, (err, allowed) =>
  297. expect(@TokenAccessHandler.findProjectWithReadAndWriteToken.callCount)
  298. .to.equal 1
  299. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.callCount)
  300. .to.equal 1
  301. done()
  302. it 'should not allow any access', (done) ->
  303. @TokenAccessHandler.isValidToken @projectId, @token, (err, rw, ro) =>
  304. expect(err).to.not.exist
  305. expect(rw).to.equal false
  306. expect(ro).to.equal false
  307. done()
  308. describe 'when findProject produces an error', ->
  309. beforeEach ->
  310. @TokenAccessHandler.findProjectWithReadAndWriteToken = sinon.stub()
  311. .callsArgWith(1, null, null)
  312. @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub()
  313. .callsArgWith(1, new Error('woops'))
  314. it 'should try to find projects with both kinds of token', (done) ->
  315. @TokenAccessHandler.isValidToken @projectId, @token, (err, allowed) =>
  316. expect(@TokenAccessHandler.findProjectWithReadAndWriteToken.callCount)
  317. .to.equal 1
  318. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.callCount)
  319. .to.equal 1
  320. done()
  321. it 'should produce an error and not allow access', (done) ->
  322. @TokenAccessHandler.isValidToken @projectId, @token, (err, rw, ro) =>
  323. expect(err).to.exist
  324. expect(err).to.be.instanceof Error
  325. expect(rw).to.equal undefined
  326. expect(ro).to.equal undefined
  327. done()
  328. describe 'when project is not set to token-based access', ->
  329. beforeEach ->
  330. @project.publicAccesLevel = 'private'
  331. describe 'for read-and-write project', ->
  332. beforeEach ->
  333. @TokenAccessHandler.findProjectWithReadAndWriteToken = sinon.stub()
  334. .callsArgWith(1, null, @project)
  335. @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub()
  336. .callsArgWith(1, null, null)
  337. it 'should try to find projects with both kinds of token', (done) ->
  338. @TokenAccessHandler.isValidToken @projectId, @token, (err, allowed) =>
  339. expect(@TokenAccessHandler.findProjectWithReadAndWriteToken.callCount)
  340. .to.equal 1
  341. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.callCount)
  342. .to.equal 1
  343. done()
  344. it 'should not allow any access', (done) ->
  345. @TokenAccessHandler.isValidToken @projectId, @token, (err, rw, ro) =>
  346. expect(err).to.not.exist
  347. expect(rw).to.equal false
  348. expect(ro).to.equal false
  349. done()
  350. describe 'for read-only project', ->
  351. beforeEach ->
  352. @TokenAccessHandler.findProjectWithReadAndWriteToken = sinon.stub()
  353. .callsArgWith(1, null, null)
  354. @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub()
  355. .callsArgWith(1, null, @project)
  356. it 'should try to find projects with both kinds of token', (done) ->
  357. @TokenAccessHandler.isValidToken @projectId, @token, (err, allowed) =>
  358. expect(@TokenAccessHandler.findProjectWithReadAndWriteToken.callCount)
  359. .to.equal 1
  360. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.callCount)
  361. .to.equal 1
  362. done()
  363. it 'should not allow any access', (done) ->
  364. @TokenAccessHandler.isValidToken @projectId, @token, (err, rw, ro) =>
  365. expect(err).to.not.exist
  366. expect(rw).to.equal false
  367. expect(ro).to.equal false
  368. done()
  369. describe 'with nothing', ->
  370. beforeEach ->
  371. @TokenAccessHandler.findProjectWithReadAndWriteToken = sinon.stub()
  372. .callsArgWith(1, null, @project)
  373. @TokenAccessHandler.findProjectWithReadOnlyToken = sinon.stub()
  374. .callsArgWith(1, null, null)
  375. it 'should not call findProjectWithReadOnlyToken', (done) ->
  376. @TokenAccessHandler.isValidToken @projectId, null, (err, allowed) =>
  377. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.callCount)
  378. .to.equal 0
  379. done()
  380. it 'should try to find projects with both kinds of token', (done) ->
  381. @TokenAccessHandler.isValidToken @projectId, null, (err, allowed) =>
  382. expect(@TokenAccessHandler.findProjectWithReadAndWriteToken.callCount)
  383. .to.equal 0
  384. expect(@TokenAccessHandler.findProjectWithReadOnlyToken.callCount)
  385. .to.equal 0
  386. done()
  387. it 'should not allow any access', (done) ->
  388. @TokenAccessHandler.isValidToken @projectId, null, (err, rw, ro) =>
  389. expect(err).to.not.exist
  390. expect(rw).to.equal false
  391. expect(ro).to.equal false
  392. done()
  393. describe 'protectTokens', ->
  394. beforeEach ->
  395. @project = {tokens: {readAndWrite: 'rw', readOnly: 'ro'}}
  396. it 'should hide write token from read-only user', ->
  397. @TokenAccessHandler.protectTokens(@project, 'readOnly')
  398. expect(@project.tokens.readAndWrite).to.equal ''
  399. expect(@project.tokens.readOnly).to.equal 'ro'
  400. it 'should hide read token from read-write user', ->
  401. @TokenAccessHandler.protectTokens(@project, 'readAndWrite')
  402. expect(@project.tokens.readAndWrite).to.equal 'rw'
  403. expect(@project.tokens.readOnly).to.equal ''
  404. it 'should leave tokens in place for owner', ->
  405. @TokenAccessHandler.protectTokens(@project, 'owner')
  406. expect(@project.tokens.readAndWrite).to.equal 'rw'
  407. expect(@project.tokens.readOnly).to.equal 'ro'
  408. describe 'getDocPublishedInfo', ->
  409. beforeEach ->
  410. @callback = sinon.stub()
  411. describe 'when v1 api not set', ->
  412. beforeEach ->
  413. @TokenAccessHandler.getV1DocPublishedInfo @token, @callback
  414. it 'should not check access and return default info', ->
  415. expect(@V1Api.request.called).to.equal false
  416. expect(@callback.calledWith null, {
  417. allow: true
  418. }).to.equal true
  419. describe 'when v1 api is set', ->
  420. beforeEach ->
  421. @settings.apis = { v1: 'v1' }
  422. describe 'on V1Api.request success', ->
  423. beforeEach ->
  424. @V1Api.request = sinon.stub().callsArgWith(1, null, null, 'mock-data')
  425. @TokenAccessHandler.getV1DocPublishedInfo @token, @callback
  426. it 'should return response body', ->
  427. expect(@V1Api.request.calledWith { url: "/api/v1/sharelatex/docs/#{@token}/is_published" }).to.equal true
  428. expect(@callback.calledWith null, 'mock-data').to.equal true
  429. describe 'on V1Api.request error', ->
  430. beforeEach ->
  431. @V1Api.request = sinon.stub().callsArgWith(1, 'error')
  432. @TokenAccessHandler.getV1DocPublishedInfo @token, @callback
  433. it 'should callback with error', ->
  434. expect(@callback.calledWith 'error').to.equal true
  435. describe 'getV1DocInfo', ->
  436. beforeEach ->
  437. @v2UserId = 123
  438. @callback = sinon.stub()
  439. describe 'when v1 api not set', ->
  440. beforeEach ->
  441. @TokenAccessHandler.getV1DocInfo @token, @v2UserId, @callback
  442. it 'should not check access and return default info', ->
  443. expect(@V1Api.request.called).to.equal false
  444. expect(@callback.calledWith null, {
  445. exists: true
  446. exported: false
  447. }).to.equal true
  448. describe 'when v1 api is set', ->
  449. beforeEach ->
  450. @settings.apis = { v1: 'v1' }
  451. describe 'on UserGetter.getUser success', ->
  452. beforeEach ->
  453. @UserGetter.getUser = sinon.stub().yields(null, {
  454. overleaf: { id: 1 }
  455. })
  456. @TokenAccessHandler.getV1DocInfo @token, @v2UserId, @callback
  457. it 'should get user', ->
  458. expect(@UserGetter.getUser.calledWith(@v2UserId)).to.equal true
  459. describe 'on UserGetter.getUser error', ->
  460. beforeEach ->
  461. @error = new Error('failed to get user')
  462. @UserGetter.getUser = sinon.stub().yields(@error)
  463. @TokenAccessHandler.getV1DocInfo @token, @v2UserId, @callback
  464. it 'should callback with error', ->
  465. expect(@callback.calledWith @error).to.equal true
  466. describe 'on V1Api.request success', ->
  467. beforeEach ->
  468. @v1UserId = 1
  469. @UserGetter.getUser = sinon.stub().yields(null, {
  470. overleaf: { id: @v1UserId }
  471. })
  472. @V1Api.request = sinon.stub().callsArgWith(1, null, null, 'mock-data')
  473. @TokenAccessHandler.getV1DocInfo @token, @v2UserId, @callback
  474. it 'should return response body', ->
  475. expect(@V1Api.request.calledWith { url: "/api/v1/sharelatex/users/#{@v1UserId}/docs/#{@token}/info" }).to.equal true
  476. expect(@callback.calledWith null, 'mock-data').to.equal true
  477. describe 'on V1Api.request error', ->
  478. beforeEach ->
  479. @UserGetter.getUser = sinon.stub().yields(null, {
  480. overleaf: { id: 1 }
  481. })
  482. @V1Api.request = sinon.stub().callsArgWith(1, 'error')
  483. @TokenAccessHandler.getV1DocInfo @token, @v2UserId, @callback
  484. it 'should callback with error', ->
  485. expect(@callback.calledWith 'error').to.equal true