ProjectInviteTests.coffee 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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. CollaboratorsEmailHandler = require "../../../app/js/Features/Collaborators/CollaboratorsEmailHandler"
  7. createInvite = (sendingUser, projectId, email, callback=(err, invite)->) ->
  8. sendingUser.getCsrfToken (err) ->
  9. return callback(err) if err
  10. sendingUser.request.post {
  11. url: "/project/#{projectId}/invite",
  12. json:
  13. email: email
  14. privileges: 'readAndWrite'
  15. }, (err, response, body) ->
  16. return callback(err) if err
  17. callback(null, body.invite)
  18. createProject = (owner, projectName, callback=(err, projectId, project)->) ->
  19. owner.createProject projectName, (err, projectId) ->
  20. throw err if err
  21. fakeProject = {
  22. _id: projectId,
  23. name: projectName,
  24. owner_ref: owner
  25. }
  26. callback(err, projectId, fakeProject)
  27. createProjectAndInvite = (owner, projectName, email, callback=(err, project, invite)->) ->
  28. createProject owner, projectName, (err, projectId, project) ->
  29. return callback(err) if err
  30. createInvite owner, projectId, email, (err, invite) ->
  31. return callback(err) if err
  32. link = CollaboratorsEmailHandler._buildInviteUrl(project, invite)
  33. callback(null, project, invite, link)
  34. revokeInvite = (sendingUser, projectId, inviteId, callback=(err)->) ->
  35. sendingUser.getCsrfToken (err) ->
  36. return callback(err) if err
  37. sendingUser.request.delete {
  38. url: "/project/#{projectId}/invite/#{inviteId}",
  39. }, (err, response, body) ->
  40. return callback(err) if err
  41. callback(null)
  42. # Actions
  43. tryFollowInviteLink = (user, link, callback=(err, response, body)->) ->
  44. user.request.get {
  45. uri: link
  46. baseUrl: null
  47. }, callback
  48. tryAcceptInvite = (user, invite, callback=(err, response, body)->) ->
  49. user.request.post {
  50. uri: "/project/#{invite.projectId}/invite/#{invite._id}/accept"
  51. json:
  52. token: invite.token
  53. }, callback
  54. # Expectations
  55. expectProjectAccess = (user, projectId, callback=()->) ->
  56. # should have access to project
  57. user.openProject projectId, (err) =>
  58. expect(err).to.be.oneOf [null, undefined]
  59. callback()
  60. expectNoProjectAccess = (user, projectId, callback=()->) ->
  61. # should not have access to project page
  62. user.openProject projectId, (err) =>
  63. expect(err).to.be.instanceof Error
  64. callback()
  65. expectInvitePage = (user, link, callback=()->) ->
  66. # view invite
  67. tryFollowInviteLink user, link, (err, response, body) ->
  68. expect(err).to.be.oneOf [null, undefined]
  69. expect(response.statusCode).to.equal 200
  70. expect(body).to.match new RegExp("<title>Project Invite - .*</title>")
  71. callback()
  72. expectInvalidInvitePage = (user, link, callback=()->) ->
  73. # view invalid invite
  74. tryFollowInviteLink user, link, (err, response, body) ->
  75. expect(err).to.be.oneOf [null, undefined]
  76. expect(response.statusCode).to.equal 200
  77. expect(body).to.match new RegExp("<title>Invalid Invite - .*</title>")
  78. callback()
  79. expectInviteRedirectToRegister = (user, link, callback=()->) ->
  80. tryFollowInviteLink user, link, (err, response, body) ->
  81. expect(err).to.be.oneOf [null, undefined]
  82. expect(response.statusCode).to.equal 302
  83. expect(response.headers.location).to.match new RegExp("^/register\?.*redir=.*$")
  84. callback()
  85. expectAcceptInviteAndRedirect = (user, invite, callback=()->) ->
  86. # should accept the invite and redirect to project
  87. tryAcceptInvite user, invite, (err, response, body) =>
  88. expect(err).to.be.oneOf [null, undefined]
  89. expect(response.statusCode).to.equal 302
  90. expect(response.headers.location).to.equal "/project/#{invite.projectId}"
  91. callback()
  92. describe "ProjectInviteTests", ->
  93. before (done) ->
  94. @sendingUser = new User()
  95. @user = new User()
  96. @site_admin = new User({email: "admin@example.com"})
  97. @email = 'smoketestuser@example.com'
  98. @projectName = 'sharing test'
  99. Async.series [
  100. (cb) => @user.login cb
  101. (cb) => @user.logout cb
  102. (cb) => @sendingUser.login cb
  103. ], done
  104. describe 'clicking the invite link', ->
  105. beforeEach (done) ->
  106. @projectId = null
  107. @fakeProject = null
  108. done()
  109. describe "user is logged in already", ->
  110. beforeEach (done) ->
  111. Async.series [
  112. (cb) =>
  113. createProjectAndInvite @sendingUser, @projectName, @email, (err, project, invite, link) =>
  114. @projectId = project._id
  115. @fakeProject = project
  116. @invite = invite
  117. @link = link
  118. cb()
  119. (cb) =>
  120. @user.login (err) =>
  121. if err
  122. throw err
  123. cb()
  124. ], done
  125. afterEach (done) ->
  126. Async.series [
  127. (cb) => @sendingUser.deleteProject(@projectId, cb)
  128. (cb) => @sendingUser.deleteProject(@projectId, cb)
  129. (cb) => revokeInvite(@sendingUser, @projectId, @invite._id, cb)
  130. ], done
  131. # describe 'user is already a member of the project', ->
  132. describe 'user is not a member of the project', ->
  133. it 'should not grant access if the user does not accept the invite', (done) ->
  134. Async.series(
  135. [
  136. (cb) =>
  137. expectInvitePage @user, @link, cb
  138. (cb) =>
  139. expectNoProjectAccess @user, @invite.projectId, cb
  140. ], done
  141. )
  142. it 'should render the invalid-invite page if the token is invalid', (done) ->
  143. Async.series(
  144. [
  145. (cb) =>
  146. link = @link.replace(@invite.token, 'not_a_real_token')
  147. expectInvalidInvitePage @user, link, cb
  148. (cb) =>
  149. expectNoProjectAccess @user, @invite.projectId, cb
  150. ], done
  151. )
  152. it 'should allow the user to accept the invite and access the project', (done) ->
  153. Async.series(
  154. [
  155. (cb) =>
  156. expectInvitePage @user, @link, cb
  157. (cb) =>
  158. expectAcceptInviteAndRedirect @user, @invite, cb
  159. (cb) =>
  160. expectProjectAccess @user, @invite.projectId, cb
  161. ], done
  162. )
  163. describe 'user is not logged in initially', ->
  164. before (done) ->
  165. @user.logout done
  166. beforeEach (done) ->
  167. Async.series [
  168. (cb) =>
  169. createProjectAndInvite @sendingUser, @projectName, @email, (err, project, invite, link) =>
  170. @projectId = project._id
  171. @fakeProject = project
  172. @invite = invite
  173. @link = link
  174. cb()
  175. ], done
  176. afterEach (done) ->
  177. Async.series [
  178. (cb) => @sendingUser.deleteProject(@projectId, cb)
  179. (cb) => @sendingUser.deleteProject(@projectId, cb)
  180. (cb) => revokeInvite(@sendingUser, @projectId, @invite._id, cb)
  181. ], done
  182. describe 'user is not a member of the project', ->
  183. it 'should redirect to the register page', (done) ->
  184. Async.series [
  185. (cb) => expectInviteRedirectToRegister(@user, @link, cb)
  186. ], done