TokenAccessTests.coffee 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  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-anon-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 'read-only token', ->
  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. @owner.makeTokenBased @project_id, (err) =>
  97. return done(err) if err?
  98. @owner.getProject @project_id, (err, project) =>
  99. return done(err) if err?
  100. @tokens = project.tokens
  101. done()
  102. it 'should deny access before the token is used', (done) ->
  103. try_read_access(@other1, @project_id, (response, body) =>
  104. expect(response.statusCode).to.equal 302
  105. expect(body).to.match /.*\/restricted.*/
  106. , done)
  107. it 'should allow the user to access project via read-only token url', (done) ->
  108. try_read_only_token_access(@other1, @tokens.readOnly, (response, body) =>
  109. expect(response.statusCode).to.equal 200
  110. , done)
  111. it 'should allow the user to join the project with read-only access', (done) ->
  112. try_content_access(@other1, @project_id, (response, body) =>
  113. expect(body.privilegeLevel).to.equal 'readOnly'
  114. , done)
  115. describe 'made private again', ->
  116. before (done) ->
  117. @owner.makePrivate @project_id, () -> setTimeout(done, 1000)
  118. it 'should deny access to project', (done) ->
  119. try_read_access(@other1, @project_id, (response, body) =>
  120. expect(response.statusCode).to.equal 302
  121. expect(body).to.match /.*\/restricted.*/
  122. , done)
  123. it 'should not allow the user to access read-only token', (done) ->
  124. try_read_only_token_access(@other1, @tokens.readOnly, (response, body) =>
  125. expect(response.statusCode).to.equal 404
  126. , done)
  127. it 'should not allow the user to join the project', (done) ->
  128. try_content_access(@other1, @project_id, (response, body) =>
  129. expect(body.privilegeLevel).to.equal false
  130. , done)
  131. describe 'anonymous read-only token', ->
  132. before (done) ->
  133. @owner.createProject 'token-anon-ro-test#{Math.random()}', (err, project_id) =>
  134. return done(err) if err?
  135. @project_id = project_id
  136. @owner.makeTokenBased @project_id, (err) =>
  137. return done(err) if err?
  138. @owner.getProject @project_id, (err, project) =>
  139. return done(err) if err?
  140. @tokens = project.tokens
  141. done()
  142. it 'should deny access before the token is used', (done) ->
  143. try_read_access(@anon, @project_id, (response, body) =>
  144. expect(response.statusCode).to.equal 302
  145. expect(body).to.match /.*\/restricted.*/
  146. , done)
  147. it 'should allow the user to access project via read-only token url', (done) ->
  148. try_read_only_token_access(@anon, @tokens.readOnly, (response, body) =>
  149. expect(response.statusCode).to.equal 200
  150. , done)
  151. it 'should allow the user to anonymously join the project with read-only access', (done) ->
  152. try_anon_content_access(@anon, @project_id, @tokens.readOnly, (response, body) =>
  153. expect(body.privilegeLevel).to.equal 'readOnly'
  154. , done)
  155. describe 'made private again', ->
  156. before (done) ->
  157. @owner.makePrivate @project_id, () -> setTimeout(done, 1000)
  158. it 'should deny access to project', (done) ->
  159. try_read_access(@anon, @project_id, (response, body) =>
  160. expect(response.statusCode).to.equal 302
  161. expect(body).to.match /.*\/restricted.*/
  162. , done)
  163. it 'should not allow the user to access read-only token', (done) ->
  164. try_read_only_token_access(@anon, @tokens.readOnly, (response, body) =>
  165. expect(response.statusCode).to.equal 404
  166. , done)
  167. it 'should not allow the user to join the project', (done) ->
  168. try_anon_content_access(@anon, @project_id, @tokens.readOnly, (response, body) =>
  169. expect(body.privilegeLevel).to.equal false
  170. , done)
  171. describe 'read-and-write token', ->
  172. before (done) ->
  173. @owner.createProject 'token-rw-test#{Math.random()}', (err, project_id) =>
  174. return done(err) if err?
  175. @project_id = project_id
  176. @owner.makeTokenBased @project_id, (err) =>
  177. return done(err) if err?
  178. @owner.getProject @project_id, (err, project) =>
  179. return done(err) if err?
  180. @tokens = project.tokens
  181. done()
  182. it 'should deny access before the token is used', (done) ->
  183. try_read_access(@other1, @project_id, (response, body) =>
  184. expect(response.statusCode).to.equal 302
  185. expect(response.headers.location).to.match /\/restricted.*/
  186. expect(body).to.match /.*\/restricted.*/
  187. , done)
  188. it 'should allow the user to access project via read-and-write token url', (done) ->
  189. try_read_and_write_token_access(@other1, @tokens.readAndWrite, (response, body) =>
  190. expect(response.statusCode).to.equal 200
  191. , done)
  192. it 'should allow the user to join the project with read-and-write access', (done) ->
  193. try_content_access(@other1, @project_id, (response, body) =>
  194. expect(body.privilegeLevel).to.equal 'readAndWrite'
  195. , done)
  196. describe 'made private again', ->
  197. before (done) ->
  198. @owner.makePrivate @project_id, () -> setTimeout(done, 1000)
  199. it 'should deny access to project', (done) ->
  200. try_read_access(@other1, @project_id, (response, body) =>
  201. expect(response.statusCode).to.equal 302
  202. expect(body).to.match /.*\/restricted.*/
  203. , done)
  204. it 'should not allow the user to access read-and-write token', (done) ->
  205. try_read_and_write_token_access(@other1, @tokens.readAndWrite, (response, body) =>
  206. expect(response.statusCode).to.equal 404
  207. , done)
  208. it 'should not allow the user to join the project', (done) ->
  209. try_content_access(@other1, @project_id, (response, body) =>
  210. expect(body.privilegeLevel).to.equal false
  211. , done)
  212. if !settings.allowAnonymousReadAndWriteSharing
  213. console.log ">> Skipping anonymous read-write token tests"
  214. else
  215. describe 'anonymous read-and-write token', ->
  216. before (done) ->
  217. @owner.createProject 'token-anon-rw-test#{Math.random()}', (err, project_id) =>
  218. return done(err) if err?
  219. @project_id = project_id
  220. @owner.makeTokenBased @project_id, (err) =>
  221. return done(err) if err?
  222. @owner.getProject @project_id, (err, project) =>
  223. return done(err) if err?
  224. @tokens = project.tokens
  225. done()
  226. it 'should deny access before the token is used', (done) ->
  227. try_read_access(@anon, @project_id, (response, body) =>
  228. expect(response.statusCode).to.equal 302
  229. expect(body).to.match /.*\/restricted.*/
  230. , done)
  231. it 'should allow the user to access project via read-and-write token url', (done) ->
  232. try_read_and_write_token_access(@anon, @tokens.readAndWrite, (response, body) =>
  233. expect(response.statusCode).to.equal 200
  234. , done)
  235. it 'should allow the user to anonymously join the project with read-and-write access', (done) ->
  236. try_anon_content_access(@anon, @project_id, @tokens.readAndWrite, (response, body) =>
  237. expect(body.privilegeLevel).to.equal 'readAndWrite'
  238. , done)
  239. describe 'made private again', ->
  240. before (done) ->
  241. @owner.makePrivate @project_id, () -> setTimeout(done, 1000)
  242. it 'should deny access to project', (done) ->
  243. try_read_access(@anon, @project_id, (response, body) =>
  244. expect(response.statusCode).to.equal 302
  245. expect(body).to.match /.*\/restricted.*/
  246. , done)
  247. it 'should not allow the user to access read-and-write token', (done) ->
  248. try_read_and_write_token_access(@anon, @tokens.readAndWrite, (response, body) =>
  249. expect(response.statusCode).to.equal 404
  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. describe 'private overleaf project', ->
  256. before (done) ->
  257. @owner.createProject 'overleaf-import', (err, project_id) =>
  258. @project_id = project_id
  259. @owner.makeTokenBased @project_id, (err) =>
  260. @owner.getProject @project_id, (err, project) =>
  261. @tokens = project.tokens
  262. @owner.makePrivate @project_id, () =>
  263. db.projects.update {_id: project._id}, {
  264. $set: {
  265. overleaf: {id: 1234}
  266. }
  267. }, (err) =>
  268. done()
  269. it 'should redirect to canonical path, when owner uses read-write token', (done) ->
  270. try_read_and_write_token_access(@owner, @tokens.readAndWrite, (response, body) =>
  271. expect(response.statusCode).to.equal 302
  272. expect(response.headers.location).to.equal "/project/#{@project_id}"
  273. , done)
  274. it 'should allow the owner access to the project', (done) ->
  275. try_read_access(@owner, @project_id, (response, body) =>
  276. expect(response.statusCode).to.equal 200
  277. , done)
  278. it 'should allow owner to join the project', (done) ->
  279. try_content_access(@owner, @project_id, (response, body) =>
  280. expect(body.privilegeLevel).to.equal 'owner'
  281. , done)
  282. it 'should not allow other user to join the project', (done) ->
  283. try_content_access(@other2, @project_id, (response, body) =>
  284. expect(body.privilegeLevel).to.equal false
  285. , done)