Make tests in RegistrationTests not depend on previous run state

GitOrigin-RevId: 68bcf9530ec6f5831c67449f35d0f010e5104f78
This commit is contained in:
Simon Detheridge 2019-08-08 16:46:30 +01:00 committed by sharelatex
parent 7d253651ca
commit 6defe1a693

View file

@ -76,93 +76,59 @@ const tryLoginThroughRegistrationForm = function(
})
}
describe('LoginRateLimit', function() {
before(function() {
this.user = new User()
this.badEmail = 'bademail@example.com'
return (this.badPassword = 'badpassword')
})
describe('Registration', function() {
describe('LoginRateLimit', function() {
beforeEach(function() {
this.user = new User()
this.badEmail = 'bademail@example.com'
return (this.badPassword = 'badpassword')
})
it('should rate limit login attempts after 10 within two minutes', function(done) {
return this.user.request.get('/login', (err, res, body) => {
return async.timesSeries(
15,
(n, cb) => {
return this.user.getCsrfToken(error => {
if (error != null) {
return cb(error)
}
return this.user.request.post(
{
url: '/login',
json: {
email: this.badEmail,
password: this.badPassword
}
},
(err, response, body) => {
return cb(
null,
__guard__(
body != null ? body.message : undefined,
x => x.text
)
)
it('should rate limit login attempts after 10 within two minutes', function(done) {
return this.user.request.get('/login', (err, res, body) => {
return async.timesSeries(
15,
(n, cb) => {
return this.user.getCsrfToken(error => {
if (error != null) {
return cb(error)
}
)
})
},
(err, results) => {
// ten incorrect-credentials messages, then five rate-limit messages
expect(results.length).to.equal(15)
assert.deepEqual(
results,
_.concat(
_.fill(
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'Your email or password is incorrect. Please try again'
),
_.fill(
[1, 2, 3, 4, 5],
'This account has had too many login requests. Please wait 2 minutes before trying to log in again'
return this.user.request.post(
{
url: '/login',
json: {
email: this.badEmail,
password: this.badPassword
}
},
(err, response, body) => {
return cb(
null,
__guard__(
body != null ? body.message : undefined,
x => x.text
)
)
}
)
})
},
(err, results) => {
// ten incorrect-credentials messages, then five rate-limit messages
expect(results.length).to.equal(15)
assert.deepEqual(
results,
_.concat(
_.fill(
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'Your email or password is incorrect. Please try again'
),
_.fill(
[1, 2, 3, 4, 5],
'This account has had too many login requests. Please wait 2 minutes before trying to log in again'
)
)
)
)
return done()
}
)
})
})
})
describe('CSRF protection', function() {
beforeEach(function() {
this.user = new User()
this.email = `test+${Math.random()}@example.com`
return (this.password = 'password11')
})
afterEach(function() {
return this.user.full_delete_user(this.email)
})
it('should register with the csrf token', function(done) {
return this.user.request.get('/login', (err, res, body) => {
return this.user.getCsrfToken(error => {
return this.user.request.post(
{
url: '/register',
json: {
email: this.email,
password: this.password
},
headers: {
'x-csrf-token': this.user.csrfToken
}
},
(error, response, body) => {
expect(err != null).to.equal(false)
expect(response.statusCode).to.equal(200)
return done()
}
)
@ -170,34 +136,20 @@ describe('CSRF protection', function() {
})
})
it('should fail with no csrf token', function(done) {
return this.user.request.get('/login', (err, res, body) => {
return this.user.getCsrfToken(error => {
return this.user.request.post(
{
url: '/register',
json: {
email: this.email,
password: this.password
},
headers: {
'x-csrf-token': ''
}
},
(error, response, body) => {
expect(response.statusCode).to.equal(403)
return done()
}
)
})
describe('CSRF protection', function() {
beforeEach(function() {
this.user = new User()
this.email = `test+${Math.random()}@example.com`
return (this.password = 'password11')
})
})
it('should fail with a stale csrf token', function(done) {
return this.user.request.get('/login', (err, res, body) => {
return this.user.getCsrfToken(error => {
const oldCsrfToken = this.user.csrfToken
return this.user.logout(err => {
afterEach(function() {
return this.user.full_delete_user(this.email)
})
it('should register with the csrf token', function(done) {
return this.user.request.get('/login', (err, res, body) => {
return this.user.getCsrfToken(error => {
return this.user.request.post(
{
url: '/register',
@ -206,7 +158,31 @@ describe('CSRF protection', function() {
password: this.password
},
headers: {
'x-csrf-token': oldCsrfToken
'x-csrf-token': this.user.csrfToken
}
},
(error, response, body) => {
expect(err != null).to.equal(false)
expect(response.statusCode).to.equal(200)
return done()
}
)
})
})
})
it('should fail with no csrf token', function(done) {
return this.user.request.get('/login', (err, res, body) => {
return this.user.getCsrfToken(error => {
return this.user.request.post(
{
url: '/register',
json: {
email: this.email,
password: this.password
},
headers: {
'x-csrf-token': ''
}
},
(error, response, body) => {
@ -217,127 +193,153 @@ describe('CSRF protection', function() {
})
})
})
})
})
describe('Register', function() {
before(function() {
return (this.user = new User())
})
it('Set emails attribute', function(done) {
return this.user.register((error, user) => {
expect(error).to.not.exist
user.email.should.equal(this.user.email)
user.emails.should.exist
user.emails.should.be.a('array')
user.emails.length.should.equal(1)
user.emails[0].email.should.equal(this.user.email)
return done()
})
})
})
describe('Register with bonus referal id', function() {
before(function(done) {
this.user1 = new User()
this.user2 = new User()
return async.series(
[
cb => this.user1.register(cb),
cb =>
this.user2.registerWithQuery(
`?r=${this.user1.referal_id}&rm=d&rs=b`,
cb
)
],
done
)
})
it('Adds a referal when an id is supplied and the referal source is "bonus"', function(done) {
return this.user1.get((error, user) => {
expect(error).to.not.exist
user.refered_user_count.should.eql(1)
return done()
})
})
})
describe('LoginViaRegistration', function() {
before(function(done) {
this.timeout(60000)
this.user1 = new User()
this.user2 = new User()
async.series(
[
cb => this.user1.login(cb),
cb => this.user1.logout(cb),
cb => redis.clearUserSessions(this.user1, cb),
cb => this.user2.login(cb),
cb => this.user2.logout(cb),
cb => redis.clearUserSessions(this.user2, cb)
],
done
)
return (this.project_id = null)
})
describe('[Security] Trying to register/login as another user', function() {
it('should not allow sign in with secondary email', function(done) {
const secondaryEmail = 'acceptance-test-secondary@example.com'
return this.user1.addEmail(secondaryEmail, err => {
return this.user1.loginWith(secondaryEmail, err => {
expect(err != null).to.equal(false)
return this.user1.isLoggedIn((err, isLoggedIn) => {
expect(isLoggedIn).to.equal(false)
return done()
it('should fail with a stale csrf token', function(done) {
return this.user.request.get('/login', (err, res, body) => {
return this.user.getCsrfToken(error => {
const oldCsrfToken = this.user.csrfToken
return this.user.logout(err => {
return this.user.request.post(
{
url: '/register',
json: {
email: this.email,
password: this.password
},
headers: {
'x-csrf-token': oldCsrfToken
}
},
(error, response, body) => {
expect(response.statusCode).to.equal(403)
return done()
}
)
})
})
})
})
})
it('should have user1 login', function(done) {
return this.user1.login(err => {
expect(err != null).to.equal(false)
describe('Register', function() {
beforeEach(function() {
return (this.user = new User())
})
it('Set emails attribute', function(done) {
return this.user.register((error, user) => {
expect(error).to.not.exist
user.email.should.equal(this.user.email)
user.emails.should.exist
user.emails.should.be.a('array')
user.emails.length.should.equal(1)
user.emails[0].email.should.equal(this.user.email)
return done()
})
})
})
it('should have user1 create a project', function(done) {
return this.user1.createProject('Private Project', (err, project_id) => {
expect(err != null).to.equal(false)
this.project_id = project_id
return done()
})
})
it('should ensure user1 can access their project', function(done) {
return expectProjectAccess(this.user1, this.project_id, done)
})
it('should ensure user2 cannot access the project', function(done) {
return expectNoProjectAccess(this.user2, this.project_id, done)
})
it('should prevent user2 from login/register with user1 email address', function(done) {
return tryLoginThroughRegistrationForm(
this.user2,
this.user1.email,
'totally_not_the_right_password',
(err, response, body) => {
expect(body.redir != null).to.equal(false)
expect(body.message != null).to.equal(true)
expect(body.message).to.have.all.keys('type', 'text')
expect(body.message.type).to.equal('error')
return done()
}
describe('Register with bonus referal id', function() {
beforeEach(function(done) {
this.user1 = new User()
this.user2 = new User()
return async.series(
[
cb => this.user1.register(cb),
cb =>
this.user2.registerWithQuery(
`?r=${this.user1.referal_id}&rm=d&rs=b`,
cb
)
],
done
)
})
it('should still ensure user2 cannot access the project', function(done) {
return expectNoProjectAccess(this.user2, this.project_id, done)
it('Adds a referal when an id is supplied and the referal source is "bonus"', function(done) {
return this.user1.get((error, user) => {
expect(error).to.not.exist
user.refered_user_count.should.eql(1)
return done()
})
})
})
describe('LoginViaRegistration', function() {
beforeEach(function(done) {
this.timeout(60000)
this.user1 = new User()
this.user2 = new User()
async.series(
[
cb => this.user1.login(cb),
cb => this.user1.logout(cb),
cb => redis.clearUserSessions(this.user1, cb),
cb => this.user2.login(cb),
cb => this.user2.logout(cb),
cb => redis.clearUserSessions(this.user2, cb)
],
done
)
return (this.project_id = null)
})
describe('[Security] Trying to register/login as another user', function() {
it('should not allow sign in with secondary email', function(done) {
const secondaryEmail = 'acceptance-test-secondary@example.com'
return this.user1.addEmail(secondaryEmail, err => {
return this.user1.loginWith(secondaryEmail, err => {
expect(err != null).to.equal(false)
return this.user1.isLoggedIn((err, isLoggedIn) => {
expect(isLoggedIn).to.equal(false)
return done()
})
})
})
})
it('should have user1 login and create a project, which user2 cannot access', function(done) {
let projectId
async.series(
[
// user1 logs in and creates a project which only they can access
cb => {
this.user1.login(err => {
expect(err).not.to.exist
cb()
})
},
cb => {
this.user1.createProject('Private Project', (err, id) => {
expect(err).not.to.exist
projectId = id
cb()
})
},
cb => expectProjectAccess(this.user1, projectId, cb),
cb => expectNoProjectAccess(this.user2, projectId, cb),
// should prevent user2 from login/register with user1 email address
cb => {
tryLoginThroughRegistrationForm(
this.user2,
this.user1.email,
'totally_not_the_right_password',
(err, response, body) => {
expect(body.redir != null).to.equal(false)
expect(body.message != null).to.equal(true)
expect(body.message).to.have.all.keys('type', 'text')
expect(body.message.type).to.equal('error')
cb()
}
)
},
// check user still can't access the project
cb => expectNoProjectAccess(this.user2, projectId, done)
],
done
)
})
})
})
})