TokenAccessTests.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005
  1. const { expect } = require('chai')
  2. const async = require('async')
  3. const MockV1Api = require('./helpers/MockV1Api')
  4. const User = require('./helpers/User')
  5. const request = require('./helpers/request')
  6. const settings = require('settings-sharelatex')
  7. const { db, ObjectId } = require('../../../app/src/infrastructure/mongojs')
  8. const tryReadAccess = (user, projectId, test, callback) =>
  9. async.series(
  10. [
  11. cb =>
  12. user.request.get(`/project/${projectId}`, (error, response, body) => {
  13. if (error != null) {
  14. return cb(error)
  15. }
  16. test(response, body)
  17. cb()
  18. }),
  19. cb =>
  20. user.request.get(
  21. `/project/${projectId}/download/zip`,
  22. (error, response, body) => {
  23. if (error != null) {
  24. return cb(error)
  25. }
  26. test(response, body)
  27. cb()
  28. }
  29. )
  30. ],
  31. callback
  32. )
  33. const tryReadOnlyTokenAccess = (user, token, test, callback) =>
  34. user.request.get(`/read/${token}`, (error, response, body) => {
  35. if (error != null) {
  36. return callback(error)
  37. }
  38. test(response, body)
  39. callback()
  40. })
  41. const tryReadAndWriteTokenAccess = (user, token, test, callback) =>
  42. user.request.get(`/${token}`, (error, response, body) => {
  43. if (error != null) {
  44. return callback(error)
  45. }
  46. test(response, body)
  47. callback()
  48. })
  49. const tryContentAccess = (user, projcetId, test, callback) => {
  50. // The real-time service calls this end point to determine the user's
  51. // permissions.
  52. let userId
  53. if (user.id != null) {
  54. userId = user.id
  55. } else {
  56. userId = 'anonymous-user'
  57. }
  58. request.post(
  59. {
  60. url: `/project/${projcetId}/join`,
  61. qs: { user_id: userId },
  62. auth: {
  63. user: settings.apis.web.user,
  64. pass: settings.apis.web.pass,
  65. sendImmediately: true
  66. },
  67. json: true,
  68. jar: false
  69. },
  70. (error, response, body) => {
  71. if (error != null) {
  72. return callback(error)
  73. }
  74. test(response, body)
  75. callback()
  76. }
  77. )
  78. }
  79. const tryAnonContentAccess = (user, projectId, token, test, callback) => {
  80. // The real-time service calls this end point to determine the user's
  81. // permissions.
  82. let userId
  83. if (user.id != null) {
  84. userId = user.id
  85. } else {
  86. userId = 'anonymous-user'
  87. }
  88. request.post(
  89. {
  90. url: `/project/${projectId}/join`,
  91. qs: { user_id: userId },
  92. auth: {
  93. user: settings.apis.web.user,
  94. pass: settings.apis.web.pass,
  95. sendImmediately: true
  96. },
  97. headers: {
  98. 'x-sl-anonymous-access-token': token
  99. },
  100. json: true,
  101. jar: false
  102. },
  103. (error, response, body) => {
  104. if (error != null) {
  105. return callback(error)
  106. }
  107. test(response, body)
  108. callback()
  109. }
  110. )
  111. }
  112. describe('TokenAccess', function() {
  113. beforeEach(function(done) {
  114. this.timeout(90000)
  115. this.owner = new User()
  116. this.other1 = new User()
  117. this.other2 = new User()
  118. this.anon = new User()
  119. async.parallel(
  120. [
  121. cb => this.owner.login(cb),
  122. cb => this.other1.login(cb),
  123. cb => this.other2.login(cb),
  124. cb => this.anon.getCsrfToken(cb)
  125. ],
  126. done
  127. )
  128. })
  129. describe('no token-access', function() {
  130. beforeEach(function(done) {
  131. this.owner.createProject(
  132. `token-ro-test${Math.random()}`,
  133. (err, projectId) => {
  134. if (err != null) {
  135. return done(err)
  136. }
  137. this.projectId = projectId
  138. // Note, never made token-based,
  139. // thus no tokens
  140. done()
  141. }
  142. )
  143. })
  144. it('should deny access ', function(done) {
  145. async.series(
  146. [
  147. cb => {
  148. tryReadAccess(
  149. this.other1,
  150. this.projectId,
  151. (response, body) => {
  152. expect(response.statusCode).to.equal(302)
  153. expect(body).to.match(/.*\/restricted.*/)
  154. },
  155. cb
  156. )
  157. },
  158. cb => {
  159. tryContentAccess(
  160. this.other1,
  161. this.projectId,
  162. (response, body) => {
  163. expect(body.privilegeLevel).to.equal(false)
  164. },
  165. cb
  166. )
  167. }
  168. ],
  169. done
  170. )
  171. })
  172. })
  173. describe('read-only token', function() {
  174. beforeEach(function(done) {
  175. this.owner.createProject(
  176. `token-ro-test${Math.random()}`,
  177. (err, projectId) => {
  178. if (err != null) {
  179. return done(err)
  180. }
  181. this.projectId = projectId
  182. this.owner.makeTokenBased(this.projectId, err => {
  183. if (err != null) {
  184. return done(err)
  185. }
  186. this.owner.getProject(this.projectId, (err, project) => {
  187. if (err != null) {
  188. return done(err)
  189. }
  190. this.tokens = project.tokens
  191. done()
  192. })
  193. })
  194. }
  195. )
  196. })
  197. it('allow the user read-only access to the project', function(done) {
  198. async.series(
  199. [
  200. cb => {
  201. // deny access before token is used
  202. tryReadAccess(
  203. this.other1,
  204. this.projectId,
  205. (response, body) => {
  206. expect(response.statusCode).to.equal(302)
  207. expect(body).to.match(/.*\/restricted.*/)
  208. },
  209. cb
  210. )
  211. },
  212. cb => {
  213. // use token
  214. tryReadOnlyTokenAccess(
  215. this.other1,
  216. this.tokens.readOnly,
  217. (response, body) => {
  218. expect(response.statusCode).to.equal(200)
  219. },
  220. cb
  221. )
  222. },
  223. cb => {
  224. // allow content access read-only
  225. tryContentAccess(
  226. this.other1,
  227. this.projectId,
  228. (response, body) => {
  229. expect(body.privilegeLevel).to.equal('readOnly')
  230. expect(body.isRestrictedUser).to.equal(true)
  231. expect(body.project.owner).to.have.keys('_id')
  232. expect(body.project.owner).to.not.have.any.keys(
  233. 'email',
  234. 'first_name',
  235. 'last_name'
  236. )
  237. },
  238. cb
  239. )
  240. }
  241. ],
  242. done
  243. )
  244. })
  245. describe('made private again', function() {
  246. beforeEach(function(done) {
  247. this.owner.makePrivate(this.projectId, () => setTimeout(done, 1000))
  248. })
  249. it('should not allow the user to access the project', function(done) {
  250. async.series(
  251. [
  252. // no access before token is used
  253. cb =>
  254. tryReadAccess(
  255. this.other1,
  256. this.projectId,
  257. (response, body) => {
  258. expect(response.statusCode).to.equal(302)
  259. expect(body).to.match(/.*\/restricted.*/)
  260. },
  261. cb
  262. ),
  263. cb =>
  264. tryReadOnlyTokenAccess(
  265. this.other1,
  266. this.tokens.readOnly,
  267. (response, body) => {
  268. expect(response.statusCode).to.equal(404)
  269. },
  270. cb
  271. ),
  272. cb =>
  273. tryContentAccess(
  274. this.other1,
  275. this.projectId,
  276. (response, body) => {
  277. expect(body.privilegeLevel).to.equal(false)
  278. },
  279. cb
  280. )
  281. ],
  282. done
  283. )
  284. })
  285. })
  286. })
  287. describe('anonymous read-only token', function() {
  288. beforeEach(function(done) {
  289. this.owner.createProject(
  290. `token-anon-ro-test${Math.random()}`,
  291. (err, projectId) => {
  292. if (err != null) {
  293. return done(err)
  294. }
  295. this.projectId = projectId
  296. this.owner.makeTokenBased(this.projectId, err => {
  297. if (err != null) {
  298. return done(err)
  299. }
  300. this.owner.getProject(this.projectId, (err, project) => {
  301. if (err != null) {
  302. return done(err)
  303. }
  304. this.tokens = project.tokens
  305. done()
  306. })
  307. })
  308. }
  309. )
  310. })
  311. it('should allow the user to access project via read-only token url', function(done) {
  312. async.series(
  313. [
  314. cb =>
  315. tryReadAccess(
  316. this.anon,
  317. this.projectId,
  318. (response, body) => {
  319. expect(response.statusCode).to.equal(302)
  320. expect(body).to.match(/.*\/restricted.*/)
  321. },
  322. cb
  323. ),
  324. cb =>
  325. tryReadOnlyTokenAccess(
  326. this.anon,
  327. this.tokens.readOnly,
  328. (response, body) => {
  329. expect(response.statusCode).to.equal(200)
  330. },
  331. cb
  332. ),
  333. cb =>
  334. tryAnonContentAccess(
  335. this.anon,
  336. this.projectId,
  337. this.tokens.readOnly,
  338. (response, body) => {
  339. expect(body.privilegeLevel).to.equal('readOnly')
  340. expect(body.isRestrictedUser).to.equal(true)
  341. expect(body.project.owner).to.have.keys('_id')
  342. expect(body.project.owner).to.not.have.any.keys(
  343. 'email',
  344. 'first_name',
  345. 'last_name'
  346. )
  347. },
  348. cb
  349. )
  350. ],
  351. done
  352. )
  353. })
  354. describe('made private again', function() {
  355. beforeEach(function(done) {
  356. this.owner.makePrivate(this.projectId, () => setTimeout(done, 1000))
  357. })
  358. it('should deny access to project', function(done) {
  359. async.series(
  360. [
  361. cb =>
  362. tryReadAccess(
  363. this.anon,
  364. this.projectId,
  365. (response, body) => {
  366. expect(response.statusCode).to.equal(302)
  367. expect(body).to.match(/.*\/restricted.*/)
  368. },
  369. cb
  370. ),
  371. // should not allow the user to access read-only token
  372. cb =>
  373. tryReadOnlyTokenAccess(
  374. this.anon,
  375. this.tokens.readOnly,
  376. (response, body) => {
  377. expect(response.statusCode).to.equal(404)
  378. },
  379. cb
  380. ),
  381. // should not allow the user to join the project
  382. cb =>
  383. tryAnonContentAccess(
  384. this.anon,
  385. this.projectId,
  386. this.tokens.readOnly,
  387. (response, body) => {
  388. expect(body.privilegeLevel).to.equal(false)
  389. },
  390. cb
  391. )
  392. ],
  393. done
  394. )
  395. })
  396. })
  397. })
  398. describe('read-and-write token', function() {
  399. beforeEach(function(done) {
  400. this.owner.createProject(
  401. `token-rw-test${Math.random()}`,
  402. (err, projectId) => {
  403. if (err != null) {
  404. return done(err)
  405. }
  406. this.projectId = projectId
  407. this.owner.makeTokenBased(this.projectId, err => {
  408. if (err != null) {
  409. return done(err)
  410. }
  411. this.owner.getProject(this.projectId, (err, project) => {
  412. if (err != null) {
  413. return done(err)
  414. }
  415. this.tokens = project.tokens
  416. done()
  417. })
  418. })
  419. }
  420. )
  421. })
  422. it('should allow the user to access project via read-and-write token url', function(done) {
  423. async.series(
  424. [
  425. // deny access before the token is used
  426. cb =>
  427. tryReadAccess(
  428. this.other1,
  429. this.projectId,
  430. (response, body) => {
  431. expect(response.statusCode).to.equal(302)
  432. expect(response.headers.location).to.match(/\/restricted.*/)
  433. expect(body).to.match(/.*\/restricted.*/)
  434. },
  435. cb
  436. ),
  437. cb =>
  438. tryReadAndWriteTokenAccess(
  439. this.other1,
  440. this.tokens.readAndWrite,
  441. (response, body) => {
  442. expect(response.statusCode).to.equal(200)
  443. },
  444. cb
  445. ),
  446. cb =>
  447. tryContentAccess(
  448. this.other1,
  449. this.projectId,
  450. (response, body) => {
  451. expect(body.privilegeLevel).to.equal('readAndWrite')
  452. expect(body.isRestrictedUser).to.equal(false)
  453. expect(body.project.owner).to.have.all.keys(
  454. '_id',
  455. 'email',
  456. 'first_name',
  457. 'last_name',
  458. 'privileges',
  459. 'signUpDate'
  460. )
  461. },
  462. cb
  463. )
  464. ],
  465. done
  466. )
  467. })
  468. describe('made private again', function() {
  469. beforeEach(function(done) {
  470. this.owner.makePrivate(this.projectId, () => setTimeout(done, 1000))
  471. })
  472. it('should deny access to project', function(done) {
  473. async.series(
  474. [
  475. cb => {
  476. tryReadAccess(
  477. this.other1,
  478. this.projectId,
  479. (response, body) => {
  480. expect(response.statusCode).to.equal(302)
  481. expect(body).to.match(/.*\/restricted.*/)
  482. },
  483. cb
  484. )
  485. },
  486. cb => {
  487. tryReadAndWriteTokenAccess(
  488. this.other1,
  489. this.tokens.readAndWrite,
  490. (response, body) => {
  491. expect(response.statusCode).to.equal(404)
  492. },
  493. cb
  494. )
  495. },
  496. cb => {
  497. tryContentAccess(
  498. this.other1,
  499. this.projectId,
  500. (response, body) => {
  501. expect(body.privilegeLevel).to.equal(false)
  502. },
  503. cb
  504. )
  505. }
  506. ],
  507. done
  508. )
  509. })
  510. })
  511. })
  512. if (!settings.allowAnonymousReadAndWriteSharing) {
  513. describe('anonymous read-and-write token, disabled', function() {
  514. beforeEach(function(done) {
  515. this.owner.createProject(
  516. `token-anon-rw-test${Math.random()}`,
  517. (err, projectId) => {
  518. if (err != null) {
  519. return done(err)
  520. }
  521. this.projectId = projectId
  522. this.owner.makeTokenBased(this.projectId, err => {
  523. if (err != null) {
  524. return done(err)
  525. }
  526. this.owner.getProject(this.projectId, (err, project) => {
  527. if (err != null) {
  528. return done(err)
  529. }
  530. this.tokens = project.tokens
  531. done()
  532. })
  533. })
  534. }
  535. )
  536. })
  537. it('should not allow the user to access read-and-write token', function(done) {
  538. async.series(
  539. [
  540. cb =>
  541. tryReadAccess(
  542. this.anon,
  543. this.projectId,
  544. (response, body) => {
  545. expect(response.statusCode).to.equal(302)
  546. expect(body).to.match(/.*\/restricted.*/)
  547. },
  548. cb
  549. ),
  550. cb =>
  551. tryReadAndWriteTokenAccess(
  552. this.anon,
  553. this.tokens.readAndWrite,
  554. (response, body) => {
  555. expect(response.statusCode).to.equal(302)
  556. expect(body).to.match(/.*\/restricted.*/)
  557. },
  558. cb
  559. ),
  560. cb =>
  561. tryAnonContentAccess(
  562. this.anon,
  563. this.projectId,
  564. this.tokens.readAndWrite,
  565. (response, body) => {
  566. expect(body.privilegeLevel).to.equal(false)
  567. },
  568. cb
  569. )
  570. ],
  571. done
  572. )
  573. })
  574. })
  575. } else {
  576. describe('anonymous read-and-write token, enabled', function() {
  577. beforeEach(function(done) {
  578. this.owner.createProject(
  579. `token-anon-rw-test${Math.random()}`,
  580. (err, projectId) => {
  581. if (err != null) {
  582. return done(err)
  583. }
  584. this.projectId = projectId
  585. this.owner.makeTokenBased(this.projectId, err => {
  586. if (err != null) {
  587. return done(err)
  588. }
  589. this.owner.getProject(this.projectId, (err, project) => {
  590. if (err != null) {
  591. return done(err)
  592. }
  593. this.tokens = project.tokens
  594. done()
  595. })
  596. })
  597. }
  598. )
  599. })
  600. it('should allow the user to access project via read-and-write token url', function(done) {
  601. async.series(
  602. [
  603. cb =>
  604. tryReadAccess(
  605. this.anon,
  606. this.projectId,
  607. (response, body) => {
  608. expect(response.statusCode).to.equal(302)
  609. expect(body).to.match(/.*\/restricted.*/)
  610. },
  611. cb
  612. ),
  613. cb =>
  614. tryReadAndWriteTokenAccess(
  615. this.anon,
  616. this.tokens.readAndWrite,
  617. (response, body) => {
  618. expect(response.statusCode).to.equal(200)
  619. },
  620. cb
  621. ),
  622. cb =>
  623. tryAnonContentAccess(
  624. this.anon,
  625. this.projectId,
  626. this.tokens.readAndWrite,
  627. (response, body) => {
  628. expect(body.privilegeLevel).to.equal('readAndWrite')
  629. },
  630. cb
  631. )
  632. ],
  633. done
  634. )
  635. })
  636. describe('made private again', function() {
  637. beforeEach(function(done) {
  638. this.owner.makePrivate(this.projectId, () => setTimeout(done, 1000))
  639. })
  640. it('should not allow the user to access read-and-write token', function(done) {
  641. async.series(
  642. [
  643. cb =>
  644. tryReadAccess(
  645. this.anon,
  646. this.projectId,
  647. (response, body) => {
  648. expect(response.statusCode).to.equal(302)
  649. expect(body).to.match(/.*\/restricted.*/)
  650. },
  651. cb
  652. ),
  653. cb =>
  654. tryReadAndWriteTokenAccess(
  655. this.anon,
  656. this.tokens.readAndWrite,
  657. (response, body) => {
  658. expect(response.statusCode).to.equal(404)
  659. },
  660. cb
  661. ),
  662. cb =>
  663. tryAnonContentAccess(
  664. this.anon,
  665. this.projectId,
  666. this.tokens.readAndWrite,
  667. (response, body) => {
  668. expect(body.privilegeLevel).to.equal(false)
  669. },
  670. cb
  671. )
  672. ],
  673. done
  674. )
  675. })
  676. })
  677. })
  678. }
  679. describe('private overleaf project', function() {
  680. beforeEach(function(done) {
  681. this.owner.createProject('overleaf-import', (err, projectId) => {
  682. expect(err).not.to.exist
  683. this.projectId = projectId
  684. this.owner.makeTokenBased(this.projectId, err => {
  685. expect(err).not.to.exist
  686. this.owner.getProject(this.projectId, (err, project) => {
  687. expect(err).not.to.exist
  688. this.tokens = project.tokens
  689. this.owner.makePrivate(this.projectId, () => {
  690. db.projects.update(
  691. { _id: project._id },
  692. {
  693. $set: {
  694. overleaf: { id: 1234 }
  695. }
  696. },
  697. err => {
  698. expect(err).not.to.exist
  699. done()
  700. }
  701. )
  702. })
  703. })
  704. })
  705. })
  706. })
  707. it('should only allow the owner access to the project', function(done) {
  708. async.series(
  709. [
  710. // should redirect to canonical path, when owner uses read-write token
  711. cb =>
  712. tryReadAndWriteTokenAccess(
  713. this.owner,
  714. this.tokens.readAndWrite,
  715. (response, body) => {
  716. expect(response.statusCode).to.equal(302)
  717. expect(response.headers.location).to.equal(
  718. `/project/${this.projectId}`
  719. )
  720. },
  721. cb
  722. ),
  723. cb =>
  724. tryReadAccess(
  725. this.owner,
  726. this.projectId,
  727. (response, body) => {
  728. expect(response.statusCode).to.equal(200)
  729. },
  730. cb
  731. ),
  732. cb =>
  733. tryContentAccess(
  734. this.owner,
  735. this.projectId,
  736. (response, body) => {
  737. expect(body.privilegeLevel).to.equal('owner')
  738. },
  739. cb
  740. ),
  741. // non-owner should be denied access
  742. cb =>
  743. tryContentAccess(
  744. this.other2,
  745. this.projectId,
  746. (response, body) => {
  747. expect(body.privilegeLevel).to.equal(false)
  748. },
  749. cb
  750. )
  751. ],
  752. done
  753. )
  754. })
  755. })
  756. describe('private project, with higher access', function() {
  757. beforeEach(function(done) {
  758. this.owner.createProject(
  759. `higher-access-test-${Math.random()}`,
  760. (err, projectId) => {
  761. expect(err).not.to.exist
  762. this.projectId = projectId
  763. this.owner.addUserToProject(
  764. this.projectId,
  765. this.other1,
  766. 'readAndWrite',
  767. err => {
  768. expect(err).not.to.exist
  769. this.owner.makeTokenBased(this.projectId, err => {
  770. expect(err).not.to.exist
  771. this.owner.getProject(this.projectId, (err, project) => {
  772. expect(err).not.to.exist
  773. this.tokens = project.tokens
  774. this.owner.makePrivate(this.projectId, () => {
  775. setTimeout(done, 1000)
  776. })
  777. })
  778. })
  779. }
  780. )
  781. }
  782. )
  783. })
  784. it('should allow the user access to the project', function(done) {
  785. async.series(
  786. [
  787. // should redirect to canonical path, when user uses read-write token
  788. cb =>
  789. tryReadAndWriteTokenAccess(
  790. this.other1,
  791. this.tokens.readAndWrite,
  792. (response, body) => {
  793. expect(response.statusCode).to.equal(302)
  794. expect(response.headers.location).to.equal(
  795. `/project/${this.projectId}`
  796. )
  797. },
  798. cb
  799. ),
  800. // should redirect to canonical path, when user uses read-only token
  801. cb =>
  802. tryReadOnlyTokenAccess(
  803. this.other1,
  804. this.tokens.readOnly,
  805. (response, body) => {
  806. expect(response.statusCode).to.equal(302)
  807. expect(response.headers.location).to.equal(
  808. `/project/${this.projectId}`
  809. )
  810. },
  811. cb
  812. ),
  813. // should allow the user access to the project
  814. cb =>
  815. tryReadAccess(
  816. this.other1,
  817. this.projectId,
  818. (response, body) => {
  819. expect(response.statusCode).to.equal(200)
  820. },
  821. cb
  822. ),
  823. // should allow user to join the project
  824. cb =>
  825. tryContentAccess(
  826. this.other1,
  827. this.projectId,
  828. (response, body) => {
  829. expect(body.privilegeLevel).to.equal('readAndWrite')
  830. },
  831. cb
  832. ),
  833. // should not allow a different user to join the project
  834. cb =>
  835. tryContentAccess(
  836. this.other2,
  837. this.projectId,
  838. (response, body) => {
  839. expect(body.privilegeLevel).to.equal(false)
  840. },
  841. cb
  842. )
  843. ],
  844. done
  845. )
  846. })
  847. })
  848. describe('unimported v1 project', function() {
  849. beforeEach(function() {
  850. settings.overleaf = { host: 'http://localhost:5000' }
  851. })
  852. afterEach(function() {
  853. delete settings.overleaf
  854. })
  855. it('should show error page for read and write token', function(done) {
  856. const unimportedV1Token = '123abc'
  857. tryReadAndWriteTokenAccess(
  858. this.owner,
  859. unimportedV1Token,
  860. (response, body) => {
  861. expect(response.statusCode).to.equal(400)
  862. },
  863. done
  864. )
  865. })
  866. it('should show error page for read only token to v1', function(done) {
  867. const unimportedV1Token = 'abcd'
  868. tryReadOnlyTokenAccess(
  869. this.owner,
  870. unimportedV1Token,
  871. (response, body) => {
  872. expect(response.statusCode).to.equal(400)
  873. },
  874. done
  875. )
  876. })
  877. })
  878. describe('importing v1 project', function() {
  879. beforeEach(function(done) {
  880. settings.projectImportingCheckMaxCreateDelta = 3600
  881. settings.overleaf = { host: 'http://localhost:5000' }
  882. this.owner.createProject(
  883. `token-rw-test${Math.random()}`,
  884. (err, projectId) => {
  885. if (err != null) {
  886. return done(err)
  887. }
  888. this.projectId = projectId
  889. this.owner.makeTokenBased(this.projectId, err => {
  890. if (err != null) {
  891. return done(err)
  892. }
  893. db.projects.update(
  894. { _id: ObjectId(projectId) },
  895. { $set: { overleaf: { id: 1234 } } },
  896. err => {
  897. if (err != null) {
  898. return done(err)
  899. }
  900. this.owner.getProject(this.projectId, (err, project) => {
  901. if (err != null) {
  902. return done(err)
  903. }
  904. this.tokens = project.tokens
  905. MockV1Api.setDocExported(this.tokens.readAndWrite, {
  906. exporting: true
  907. })
  908. MockV1Api.setDocExported(this.tokens.readOnly, {
  909. exporting: true
  910. })
  911. done()
  912. })
  913. }
  914. )
  915. })
  916. }
  917. )
  918. })
  919. afterEach(function() {
  920. delete settings.projectImportingCheckMaxCreateDelta
  921. delete settings.overleaf
  922. })
  923. it('should show importing page for read, and read-write tokens', function(done) {
  924. async.series(
  925. [
  926. cb =>
  927. tryReadAndWriteTokenAccess(
  928. this.owner,
  929. this.tokens.readAndWrite,
  930. (response, body) => {
  931. expect(response.statusCode).to.equal(200)
  932. expect(body).to.include('ImportingController')
  933. },
  934. cb
  935. ),
  936. cb =>
  937. tryReadOnlyTokenAccess(
  938. this.owner,
  939. this.tokens.readOnly,
  940. (response, body) => {
  941. expect(response.statusCode).to.equal(200)
  942. expect(body).to.include('ImportingController')
  943. },
  944. cb
  945. )
  946. ],
  947. done
  948. )
  949. })
  950. describe('when importing check not configured', function() {
  951. beforeEach(function() {
  952. delete settings.projectImportingCheckMaxCreateDelta
  953. })
  954. it('should load editor', function(done) {
  955. tryReadAndWriteTokenAccess(
  956. this.owner,
  957. this.tokens.readAndWrite,
  958. (response, body) => {
  959. expect(response.statusCode).to.equal(200)
  960. expect(body).to.include('IdeController')
  961. },
  962. done
  963. )
  964. })
  965. })
  966. })
  967. })