RegistrationTests.coffee 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. expect = require("chai").expect
  2. assert = require("chai").assert
  3. async = require("async")
  4. User = require "./helpers/User"
  5. request = require "./helpers/request"
  6. settings = require "settings-sharelatex"
  7. redis = require "./helpers/redis"
  8. _ = require 'lodash'
  9. # Currently this is testing registration via the 'public-registration' module,
  10. # whereas in production we're using the 'overleaf-integration' module.
  11. # Expectations
  12. expectProjectAccess = (user, projectId, callback=(err,result)->) ->
  13. # should have access to project
  14. user.openProject projectId, (err) =>
  15. expect(err).to.be.oneOf [null, undefined]
  16. callback()
  17. expectNoProjectAccess = (user, projectId, callback=(err,result)->) ->
  18. # should not have access to project page
  19. user.openProject projectId, (err) =>
  20. expect(err).to.be.instanceof Error
  21. callback()
  22. # Actions
  23. tryLoginThroughRegistrationForm = (user, email, password, callback=(err, response, body)->) ->
  24. user.getCsrfToken (err) ->
  25. return callback(err) if err?
  26. user.request.post {
  27. url: "/register"
  28. json:
  29. email: email
  30. password: password
  31. }, callback
  32. describe "LoginRateLimit", ->
  33. before ->
  34. @user = new User()
  35. @badEmail = 'bademail@example.com'
  36. @badPassword = 'badpassword'
  37. it 'should rate limit login attempts after 10 within two minutes', (done) ->
  38. @user.request.get '/login', (err, res, body) =>
  39. async.timesSeries(
  40. 15
  41. , (n, cb) =>
  42. @user.getCsrfToken (error) =>
  43. return cb(error) if error?
  44. @user.request.post {
  45. url: "/login"
  46. json:
  47. email: @badEmail
  48. password: @badPassword
  49. }, (err, response, body) =>
  50. cb(null, body?.message?.text)
  51. , (err, results) =>
  52. # ten incorrect-credentials messages, then five rate-limit messages
  53. expect(results.length).to.equal 15
  54. assert.deepEqual(
  55. results,
  56. _.concat(
  57. _.fill([1..10], 'Your email or password is incorrect. Please try again'),
  58. _.fill([1..5], 'This account has had too many login requests. Please wait 2 minutes before trying to log in again')
  59. )
  60. )
  61. done()
  62. )
  63. describe "CSRF protection", ->
  64. beforeEach ->
  65. @user = new User()
  66. @email = "test+#{Math.random()}@example.com"
  67. @password = "password11"
  68. afterEach ->
  69. @user.full_delete_user(@email)
  70. it 'should register with the csrf token', (done) ->
  71. @user.request.get '/login', (err, res, body) =>
  72. @user.getCsrfToken (error) =>
  73. @user.request.post {
  74. url: "/register"
  75. json:
  76. email: @email
  77. password: @password
  78. headers:{
  79. "x-csrf-token": @user.csrfToken
  80. }
  81. }, (error, response, body) =>
  82. expect(err?).to.equal false
  83. expect(response.statusCode).to.equal 200
  84. done()
  85. it 'should fail with no csrf token', (done) ->
  86. @user.request.get '/login', (err, res, body) =>
  87. @user.getCsrfToken (error) =>
  88. @user.request.post {
  89. url: "/register"
  90. json:
  91. email: @email
  92. password: @password
  93. headers:{
  94. "x-csrf-token": ""
  95. }
  96. }, (error, response, body) =>
  97. expect(response.statusCode).to.equal 403
  98. done()
  99. it 'should fail with a stale csrf token', (done) ->
  100. @user.request.get '/login', (err, res, body) =>
  101. @user.getCsrfToken (error) =>
  102. oldCsrfToken = @user.csrfToken
  103. @user.request.get '/logout', (err, res, body) =>
  104. @user.request.post {
  105. url: "/register"
  106. json:
  107. email: @email
  108. password: @password
  109. headers:{
  110. "x-csrf-token": oldCsrfToken
  111. }
  112. }, (error, response, body) =>
  113. expect(response.statusCode).to.equal 403
  114. done()
  115. describe "Register", ->
  116. before ->
  117. @user = new User()
  118. it 'Set emails attribute', (done) ->
  119. @user.register (error, user) =>
  120. expect(error).to.not.exist
  121. user.email.should.equal @user.email
  122. user.emails.should.exist
  123. user.emails.should.be.a 'array'
  124. user.emails.length.should.equal 1
  125. user.emails[0].email.should.equal @user.email
  126. done()
  127. describe "Register with bonus referal id", ->
  128. before (done) ->
  129. @user1 = new User()
  130. @user2 = new User()
  131. async.series [
  132. (cb) => @user1.register cb
  133. (cb) => @user2.registerWithQuery '?r=' + @user1.referal_id + '&rm=d&rs=b', cb
  134. ], done
  135. it 'Adds a referal when an id is supplied and the referal source is "bonus"', (done) ->
  136. @user1.get (error, user) =>
  137. expect(error).to.not.exist
  138. user.refered_user_count.should.eql 1
  139. done()
  140. describe "LoginViaRegistration", ->
  141. before (done) ->
  142. @timeout(60000)
  143. @user1 = new User()
  144. @user2 = new User()
  145. async.series [
  146. (cb) => @user1.login cb
  147. (cb) => @user1.logout cb
  148. (cb) => redis.clearUserSessions @user1, cb
  149. (cb) => @user2.login cb
  150. (cb) => @user2.logout cb
  151. (cb) => redis.clearUserSessions @user2, cb
  152. ], done
  153. @project_id = null
  154. describe "[Security] Trying to register/login as another user", ->
  155. it 'should not allow sign in with secondary email', (done) ->
  156. secondaryEmail = "acceptance-test-secondary@example.com"
  157. @user1.addEmail secondaryEmail, (err) =>
  158. @user1.loginWith secondaryEmail, (err) =>
  159. expect(err?).to.equal false
  160. @user1.isLoggedIn (err, isLoggedIn) ->
  161. expect(isLoggedIn).to.equal false
  162. done()
  163. it 'should have user1 login', (done) ->
  164. @user1.login (err) ->
  165. expect(err?).to.equal false
  166. done()
  167. it 'should have user1 create a project', (done) ->
  168. @user1.createProject 'Private Project', (err, project_id) =>
  169. expect(err?).to.equal false
  170. @project_id = project_id
  171. done()
  172. it 'should ensure user1 can access their project', (done) ->
  173. expectProjectAccess @user1, @project_id, done
  174. it 'should ensure user2 cannot access the project', (done) ->
  175. expectNoProjectAccess @user2, @project_id, done
  176. it 'should prevent user2 from login/register with user1 email address', (done) ->
  177. tryLoginThroughRegistrationForm @user2, @user1.email, 'totally_not_the_right_password', (err, response, body) =>
  178. expect(body.redir?).to.equal false
  179. expect(body.message?).to.equal true
  180. expect(body.message).to.have.all.keys('type', 'text')
  181. expect(body.message.type).to.equal 'error'
  182. done()
  183. it 'should still ensure user2 cannot access the project', (done) ->
  184. expectNoProjectAccess @user2, @project_id, done