TokenAccessTests.coffee 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. expect = require("chai").expect
  2. async = require("async")
  3. User = require "./helpers/User"
  4. request = require "./helpers/request"
  5. settings = require "settings-sharelatex"
  6. {db, ObjectId} = require("../../../app/js/infrastructure/mongojs")
  7. try_read_access = (user, project_id, test, callback) ->
  8. async.series [
  9. (cb) ->
  10. user.request.get "/project/#{project_id}", (error, response, body) ->
  11. return cb(error) if error?
  12. test(response, body)
  13. cb()
  14. (cb) ->
  15. user.request.get "/project/#{project_id}/download/zip", (error, response, body) ->
  16. return cb(error) if error?
  17. test(response, body)
  18. cb()
  19. ], callback
  20. try_read_only_token_access = (user, token, test, callback) ->
  21. async.series [
  22. (cb) ->
  23. user.request.get "/read/#{token}", (error, response, body) ->
  24. return cb(error) if error?
  25. test(response, body)
  26. cb()
  27. ], callback
  28. try_read_and_write_token_access = (user, token, test, callback) ->
  29. async.series [
  30. (cb) ->
  31. user.request.get "/#{token}", (error, response, body) ->
  32. return cb(error) if error?
  33. test(response, body)
  34. cb()
  35. ], callback
  36. try_content_access = (user, project_id, test, callback) ->
  37. # The real-time service calls this end point to determine the user's
  38. # permissions.
  39. if user.id?
  40. user_id = user.id
  41. else
  42. user_id = "anonymous-user"
  43. request.post {
  44. url: "/project/#{project_id}/join"
  45. qs: {user_id}
  46. auth:
  47. user: settings.apis.web.user
  48. pass: settings.apis.web.pass
  49. sendImmediately: true
  50. json: true
  51. jar: false
  52. }, (error, response, body) ->
  53. return callback(error) if error?
  54. test(response, body)
  55. callback()
  56. try_anon_content_access = (user, project_id, token, test, callback) ->
  57. # The real-time service calls this end point to determine the user's
  58. # permissions.
  59. if user.id?
  60. user_id = user.id
  61. else
  62. user_id = "anonymous-user"
  63. request.post {
  64. url: "/project/#{project_id}/join"
  65. qs: {user_id}
  66. auth:
  67. user: settings.apis.web.user
  68. pass: settings.apis.web.pass
  69. sendImmediately: true
  70. headers:
  71. 'x-sl-anonymous-access-token': token
  72. json: true
  73. jar: false
  74. }, (error, response, body) ->
  75. return callback(error) if error?
  76. test(response, body)
  77. callback()
  78. describe 'TokenAccess', ->
  79. before (done) ->
  80. @timeout(90000)
  81. @owner = new User()
  82. @other1 = new User()
  83. @other2 = new User()
  84. @anon = new User()
  85. async.parallel [
  86. (cb) => @owner.login cb
  87. (cb) => @other1.login cb
  88. (cb) => @other2.login cb
  89. (cb) => @anon.getCsrfToken cb
  90. ], done
  91. describe 'no token-access', ->
  92. before (done) ->
  93. @owner.createProject "token-ro-test#{Math.random()}", (err, project_id) =>
  94. return done(err) if err?
  95. @project_id = project_id
  96. # Note, never made token-based,
  97. # thus no tokens
  98. done()
  99. it 'should deny access ', (done) ->
  100. try_read_access(@other1, @project_id, (response, body) =>
  101. expect(response.statusCode).to.equal 302
  102. expect(body).to.match /.*\/restricted.*/
  103. , done)
  104. it 'should not allow the user to join the project', (done) ->
  105. try_content_access(@other1, @project_id, (response, body) =>
  106. expect(body.privilegeLevel).to.equal false
  107. , done)
  108. describe 'read-only token', ->
  109. before (done) ->
  110. @owner.createProject "token-ro-test#{Math.random()}", (err, project_id) =>
  111. return done(err) if err?
  112. @project_id = project_id
  113. @owner.makeTokenBased @project_id, (err) =>
  114. return done(err) if err?
  115. @owner.getProject @project_id, (err, project) =>
  116. return done(err) if err?
  117. @tokens = project.tokens
  118. done()
  119. it 'should deny access before the token is used', (done) ->
  120. try_read_access(@other1, @project_id, (response, body) =>
  121. expect(response.statusCode).to.equal 302
  122. expect(body).to.match /.*\/restricted.*/
  123. , done)
  124. it 'should allow the user to access project via read-only token url', (done) ->
  125. try_read_only_token_access(@other1, @tokens.readOnly, (response, body) =>
  126. expect(response.statusCode).to.equal 200
  127. , done)
  128. it 'should allow the user to join the project with read-only access', (done) ->
  129. try_content_access(@other1, @project_id, (response, body) =>
  130. expect(body.privilegeLevel).to.equal 'readOnly'
  131. , done)
  132. describe 'made private again', ->
  133. before (done) ->
  134. @owner.makePrivate @project_id, () -> setTimeout(done, 1000)
  135. it 'should deny access to project', (done) ->
  136. try_read_access(@other1, @project_id, (response, body) =>
  137. expect(response.statusCode).to.equal 302
  138. expect(body).to.match /.*\/restricted.*/
  139. , done)
  140. it 'should not allow the user to access read-only token', (done) ->
  141. try_read_only_token_access(@other1, @tokens.readOnly, (response, body) =>
  142. expect(response.statusCode).to.equal 404
  143. , done)
  144. it 'should not allow the user to join the project', (done) ->
  145. try_content_access(@other1, @project_id, (response, body) =>
  146. expect(body.privilegeLevel).to.equal false
  147. , done)
  148. describe 'anonymous read-only token', ->
  149. before (done) ->
  150. @owner.createProject "token-anon-ro-test#{Math.random()}", (err, project_id) =>
  151. return done(err) if err?
  152. @project_id = project_id
  153. @owner.makeTokenBased @project_id, (err) =>
  154. return done(err) if err?
  155. @owner.getProject @project_id, (err, project) =>
  156. return done(err) if err?
  157. @tokens = project.tokens
  158. done()
  159. it 'should deny access before the token is used', (done) ->
  160. try_read_access(@anon, @project_id, (response, body) =>
  161. expect(response.statusCode).to.equal 302
  162. expect(body).to.match /.*\/restricted.*/
  163. , done)
  164. it 'should allow the user to access project via read-only token url', (done) ->
  165. try_read_only_token_access(@anon, @tokens.readOnly, (response, body) =>
  166. expect(response.statusCode).to.equal 200
  167. , done)
  168. it 'should allow the user to anonymously join the project with read-only access', (done) ->
  169. try_anon_content_access(@anon, @project_id, @tokens.readOnly, (response, body) =>
  170. expect(body.privilegeLevel).to.equal 'readOnly'
  171. , done)
  172. describe 'made private again', ->
  173. before (done) ->
  174. @owner.makePrivate @project_id, () -> setTimeout(done, 1000)
  175. it 'should deny access to project', (done) ->
  176. try_read_access(@anon, @project_id, (response, body) =>
  177. expect(response.statusCode).to.equal 302
  178. expect(body).to.match /.*\/restricted.*/
  179. , done)
  180. it 'should not allow the user to access read-only token', (done) ->
  181. try_read_only_token_access(@anon, @tokens.readOnly, (response, body) =>
  182. expect(response.statusCode).to.equal 404
  183. , done)
  184. it 'should not allow the user to join the project', (done) ->
  185. try_anon_content_access(@anon, @project_id, @tokens.readOnly, (response, body) =>
  186. expect(body.privilegeLevel).to.equal false
  187. , done)
  188. describe 'read-and-write token', ->
  189. before (done) ->
  190. @owner.createProject "token-rw-test#{Math.random()}", (err, project_id) =>
  191. return done(err) if err?
  192. @project_id = project_id
  193. @owner.makeTokenBased @project_id, (err) =>
  194. return done(err) if err?
  195. @owner.getProject @project_id, (err, project) =>
  196. return done(err) if err?
  197. @tokens = project.tokens
  198. done()
  199. it 'should deny access before the token is used', (done) ->
  200. try_read_access(@other1, @project_id, (response, body) =>
  201. expect(response.statusCode).to.equal 302
  202. expect(response.headers.location).to.match /\/restricted.*/
  203. expect(body).to.match /.*\/restricted.*/
  204. , done)
  205. it 'should allow the user to access project via read-and-write token url', (done) ->
  206. try_read_and_write_token_access(@other1, @tokens.readAndWrite, (response, body) =>
  207. expect(response.statusCode).to.equal 200
  208. , done)
  209. it 'should allow the user to join the project with read-and-write access', (done) ->
  210. try_content_access(@other1, @project_id, (response, body) =>
  211. expect(body.privilegeLevel).to.equal 'readAndWrite'
  212. , done)
  213. describe 'made private again', ->
  214. before (done) ->
  215. @owner.makePrivate @project_id, () -> setTimeout(done, 1000)
  216. it 'should deny access to project', (done) ->
  217. try_read_access(@other1, @project_id, (response, body) =>
  218. expect(response.statusCode).to.equal 302
  219. expect(body).to.match /.*\/restricted.*/
  220. , done)
  221. it 'should not allow the user to access read-and-write token', (done) ->
  222. try_read_and_write_token_access(@other1, @tokens.readAndWrite, (response, body) =>
  223. expect(response.statusCode).to.equal 404
  224. , done)
  225. it 'should not allow the user to join the project', (done) ->
  226. try_content_access(@other1, @project_id, (response, body) =>
  227. expect(body.privilegeLevel).to.equal false
  228. , done)
  229. if !settings.allowAnonymousReadAndWriteSharing
  230. describe 'anonymous read-and-write token, disabled', ->
  231. before (done) ->
  232. @owner.createProject "token-anon-rw-test#{Math.random()}", (err, project_id) =>
  233. return done(err) if err?
  234. @project_id = project_id
  235. @owner.makeTokenBased @project_id, (err) =>
  236. return done(err) if err?
  237. @owner.getProject @project_id, (err, project) =>
  238. return done(err) if err?
  239. @tokens = project.tokens
  240. done()
  241. it 'should deny access before the token is used', (done) ->
  242. try_read_access(@anon, @project_id, (response, body) =>
  243. expect(response.statusCode).to.equal 302
  244. expect(body).to.match /.*\/restricted.*/
  245. , done)
  246. it 'should not allow the user to access read-and-write token', (done) ->
  247. try_read_and_write_token_access(@anon, @tokens.readAndWrite, (response, body) =>
  248. expect(response.statusCode).to.equal 302
  249. expect(body).to.match /.*\/restricted.*/
  250. , done)
  251. it 'should not allow the user to join the project', (done) ->
  252. try_anon_content_access(@anon, @project_id, @tokens.readAndWrite, (response, body) =>
  253. expect(body.privilegeLevel).to.equal false
  254. , done)
  255. else
  256. describe 'anonymous read-and-write token, enabled', ->
  257. before (done) ->
  258. @owner.createProject "token-anon-rw-test#{Math.random()}", (err, project_id) =>
  259. return done(err) if err?
  260. @project_id = project_id
  261. @owner.makeTokenBased @project_id, (err) =>
  262. return done(err) if err?
  263. @owner.getProject @project_id, (err, project) =>
  264. return done(err) if err?
  265. @tokens = project.tokens
  266. done()
  267. it 'should deny access before the token is used', (done) ->
  268. try_read_access(@anon, @project_id, (response, body) =>
  269. expect(response.statusCode).to.equal 302
  270. expect(body).to.match /.*\/restricted.*/
  271. , done)
  272. it 'should allow the user to access project via read-and-write token url', (done) ->
  273. try_read_and_write_token_access(@anon, @tokens.readAndWrite, (response, body) =>
  274. expect(response.statusCode).to.equal 200
  275. , done)
  276. it 'should allow the user to anonymously join the project with read-and-write access', (done) ->
  277. try_anon_content_access(@anon, @project_id, @tokens.readAndWrite, (response, body) =>
  278. expect(body.privilegeLevel).to.equal 'readAndWrite'
  279. , done)
  280. describe 'made private again', ->
  281. before (done) ->
  282. @owner.makePrivate @project_id, () -> setTimeout(done, 1000)
  283. it 'should deny access to project', (done) ->
  284. try_read_access(@anon, @project_id, (response, body) =>
  285. expect(response.statusCode).to.equal 302
  286. expect(body).to.match /.*\/restricted.*/
  287. , done)
  288. it 'should not allow the user to access read-and-write token', (done) ->
  289. try_read_and_write_token_access(@anon, @tokens.readAndWrite, (response, body) =>
  290. expect(response.statusCode).to.equal 404
  291. , done)
  292. it 'should not allow the user to join the project', (done) ->
  293. try_anon_content_access(@anon, @project_id, @tokens.readAndWrite, (response, body) =>
  294. expect(body.privilegeLevel).to.equal false
  295. , done)
  296. describe 'private overleaf project', ->
  297. before (done) ->
  298. @owner.createProject 'overleaf-import', (err, project_id) =>
  299. @project_id = project_id
  300. @owner.makeTokenBased @project_id, (err) =>
  301. @owner.getProject @project_id, (err, project) =>
  302. @tokens = project.tokens
  303. @owner.makePrivate @project_id, () =>
  304. db.projects.update {_id: project._id}, {
  305. $set: {
  306. overleaf: {id: 1234}
  307. }
  308. }, (err) =>
  309. done()
  310. it 'should redirect to canonical path, when owner uses read-write token', (done) ->
  311. try_read_and_write_token_access(@owner, @tokens.readAndWrite, (response, body) =>
  312. expect(response.statusCode).to.equal 302
  313. expect(response.headers.location).to.equal "/project/#{@project_id}"
  314. , done)
  315. it 'should allow the owner access to the project', (done) ->
  316. try_read_access(@owner, @project_id, (response, body) =>
  317. expect(response.statusCode).to.equal 200
  318. , done)
  319. it 'should allow owner to join the project', (done) ->
  320. try_content_access(@owner, @project_id, (response, body) =>
  321. expect(body.privilegeLevel).to.equal 'owner'
  322. , done)
  323. it 'should not allow other user to join the project', (done) ->
  324. try_content_access(@other2, @project_id, (response, body) =>
  325. expect(body.privilegeLevel).to.equal false
  326. , done)
  327. describe 'private project, with higher access', ->
  328. before (done) ->
  329. @owner.createProject "higher-access-test-#{Math.random()}", (err, project_id) =>
  330. @project_id = project_id
  331. @owner.addUserToProject @project_id, @other1, 'readAndWrite', (err) =>
  332. @owner.makeTokenBased @project_id, (err) =>
  333. @owner.getProject @project_id, (err, project) =>
  334. @tokens = project.tokens
  335. @owner.makePrivate @project_id, () =>
  336. setTimeout done, 1000
  337. it 'should redirect to canonical path, when user uses read-write token', (done) ->
  338. try_read_and_write_token_access(@other1, @tokens.readAndWrite, (response, body) =>
  339. expect(response.statusCode).to.equal 302
  340. expect(response.headers.location).to.equal "/project/#{@project_id}"
  341. , done)
  342. it 'should redirect to canonical path, when user uses read-only token', (done) ->
  343. try_read_only_token_access(@other1, @tokens.readOnly, (response, body) =>
  344. expect(response.statusCode).to.equal 302
  345. expect(response.headers.location).to.equal "/project/#{@project_id}"
  346. , done)
  347. it 'should allow the user access to the project', (done) ->
  348. try_read_access(@other1, @project_id, (response, body) =>
  349. expect(response.statusCode).to.equal 200
  350. , done)
  351. it 'should allow user to join the project', (done) ->
  352. try_content_access(@other1, @project_id, (response, body) =>
  353. expect(body.privilegeLevel).to.equal 'readAndWrite'
  354. , done)
  355. it 'should not allow a different user to join the project', (done) ->
  356. try_content_access(@other2, @project_id, (response, body) =>
  357. expect(body.privilegeLevel).to.equal false
  358. , done)