mirror of
https://github.com/overleaf/overleaf.git
synced 2024-12-28 16:23:18 +00:00
482 lines
No EOL
14 KiB
CoffeeScript
482 lines
No EOL
14 KiB
CoffeeScript
expect = require("chai").expect
|
|
async = require("async")
|
|
User = require "./helpers/User"
|
|
request = require "./helpers/request"
|
|
settings = require "settings-sharelatex"
|
|
{db, ObjectId} = require("../../../app/js/infrastructure/mongojs")
|
|
MockV1Api = require "./helpers/MockV1Api"
|
|
|
|
describe "UserEmails", ->
|
|
beforeEach (done) ->
|
|
@timeout(20000)
|
|
@user = new User()
|
|
@user.login done
|
|
|
|
describe 'confirming an email', ->
|
|
it 'should confirm the email', (done) ->
|
|
token = null
|
|
async.series [
|
|
(cb) =>
|
|
@user.request {
|
|
method: 'POST',
|
|
url: '/user/emails',
|
|
json:
|
|
email: 'newly-added-email@example.com'
|
|
}, (error, response, body) =>
|
|
return done(error) if error?
|
|
expect(response.statusCode).to.equal 204
|
|
cb()
|
|
(cb) =>
|
|
@user.request { url: '/user/emails', json: true }, (error, response, body) ->
|
|
expect(response.statusCode).to.equal 200
|
|
expect(body[0].confirmedAt).to.not.exist
|
|
expect(body[1].confirmedAt).to.not.exist
|
|
cb()
|
|
(cb) =>
|
|
db.tokens.find {
|
|
use: 'email_confirmation',
|
|
'data.user_id': @user._id,
|
|
usedAt: { $exists: false }
|
|
}, (error, tokens) =>
|
|
# There should only be one confirmation token at the moment
|
|
expect(tokens.length).to.equal 1
|
|
expect(tokens[0].data.email).to.equal 'newly-added-email@example.com'
|
|
expect(tokens[0].data.user_id).to.equal @user._id
|
|
token = tokens[0].token
|
|
cb()
|
|
(cb) =>
|
|
@user.request {
|
|
method: 'POST',
|
|
url: '/user/emails/confirm',
|
|
json:
|
|
token: token
|
|
}, (error, response, body) =>
|
|
return done(error) if error?
|
|
expect(response.statusCode).to.equal 200
|
|
cb()
|
|
(cb) =>
|
|
@user.request { url: '/user/emails', json: true }, (error, response, body) ->
|
|
expect(response.statusCode).to.equal 200
|
|
expect(body[0].confirmedAt).to.not.exist
|
|
expect(body[1].confirmedAt).to.exist
|
|
cb()
|
|
(cb) =>
|
|
db.tokens.find {
|
|
use: 'email_confirmation',
|
|
'data.user_id': @user._id,
|
|
usedAt: { $exists: false }
|
|
}, (error, tokens) =>
|
|
# Token should be deleted after use
|
|
expect(tokens.length).to.equal 0
|
|
cb()
|
|
], done
|
|
|
|
it 'should not allow confirmation of the email if the user has changed', (done) ->
|
|
token1 = null
|
|
token2 = null
|
|
@user2 = new User()
|
|
@email = 'duplicate-email@example.com'
|
|
async.series [
|
|
(cb) => @user2.login cb
|
|
(cb) =>
|
|
# Create email for first user
|
|
@user.request {
|
|
method: 'POST',
|
|
url: '/user/emails',
|
|
json: {@email}
|
|
}, cb
|
|
(cb) =>
|
|
db.tokens.find {
|
|
use: 'email_confirmation',
|
|
'data.user_id': @user._id,
|
|
usedAt: { $exists: false }
|
|
}, (error, tokens) =>
|
|
# There should only be one confirmation token at the moment
|
|
expect(tokens.length).to.equal 1
|
|
expect(tokens[0].data.email).to.equal @email
|
|
expect(tokens[0].data.user_id).to.equal @user._id
|
|
token1 = tokens[0].token
|
|
cb()
|
|
(cb) =>
|
|
# Delete the email from the first user
|
|
@user.request {
|
|
method: 'POST',
|
|
url: '/user/emails/delete',
|
|
json: {@email}
|
|
}, cb
|
|
(cb) =>
|
|
# Create email for second user
|
|
@user2.request {
|
|
method: 'POST',
|
|
url: '/user/emails',
|
|
json: {@email}
|
|
}, cb
|
|
(cb) =>
|
|
# Original confirmation token should no longer work
|
|
@user.request {
|
|
method: 'POST',
|
|
url: '/user/emails/confirm',
|
|
json:
|
|
token: token1
|
|
}, (error, response, body) =>
|
|
return done(error) if error?
|
|
expect(response.statusCode).to.equal 404
|
|
cb()
|
|
(cb) =>
|
|
db.tokens.find {
|
|
use: 'email_confirmation',
|
|
'data.user_id': @user2._id,
|
|
usedAt: { $exists: false }
|
|
}, (error, tokens) =>
|
|
# The first token has been used, so this should be token2 now
|
|
expect(tokens.length).to.equal 1
|
|
expect(tokens[0].data.email).to.equal @email
|
|
expect(tokens[0].data.user_id).to.equal @user2._id
|
|
token2 = tokens[0].token
|
|
cb()
|
|
(cb) =>
|
|
# Second user should be able to confirm the email
|
|
@user2.request {
|
|
method: 'POST',
|
|
url: '/user/emails/confirm',
|
|
json:
|
|
token: token2
|
|
}, (error, response, body) =>
|
|
return done(error) if error?
|
|
expect(response.statusCode).to.equal 200
|
|
cb()
|
|
(cb) =>
|
|
@user2.request { url: '/user/emails', json: true }, (error, response, body) ->
|
|
expect(response.statusCode).to.equal 200
|
|
expect(body[0].confirmedAt).to.not.exist
|
|
expect(body[1].confirmedAt).to.exist
|
|
cb()
|
|
], done
|
|
|
|
describe "with an expired token", ->
|
|
it 'should not confirm the email', (done) ->
|
|
token = null
|
|
async.series [
|
|
(cb) =>
|
|
@user.request {
|
|
method: 'POST',
|
|
url: '/user/emails',
|
|
json:
|
|
email: @email = 'expired-token-email@example.com'
|
|
}, (error, response, body) =>
|
|
return done(error) if error?
|
|
expect(response.statusCode).to.equal 204
|
|
cb()
|
|
(cb) =>
|
|
db.tokens.find {
|
|
use: 'email_confirmation',
|
|
'data.user_id': @user._id,
|
|
usedAt: { $exists: false }
|
|
}, (error, tokens) =>
|
|
# There should only be one confirmation token at the moment
|
|
expect(tokens.length).to.equal 1
|
|
expect(tokens[0].data.email).to.equal @email
|
|
expect(tokens[0].data.user_id).to.equal @user._id
|
|
token = tokens[0].token
|
|
cb()
|
|
(cb) =>
|
|
db.tokens.update {
|
|
token: token
|
|
}, {
|
|
$set: {
|
|
expiresAt: new Date(Date.now() - 1000000)
|
|
}
|
|
}, cb
|
|
(cb) =>
|
|
@user.request {
|
|
method: 'POST',
|
|
url: '/user/emails/confirm',
|
|
json:
|
|
token: token
|
|
}, (error, response, body) =>
|
|
return done(error) if error?
|
|
expect(response.statusCode).to.equal 404
|
|
cb()
|
|
], done
|
|
|
|
describe 'resending the confirmation', ->
|
|
it 'should generate a new token', (done) ->
|
|
async.series [
|
|
(cb) =>
|
|
@user.request {
|
|
method: 'POST',
|
|
url: '/user/emails',
|
|
json:
|
|
email: 'reconfirmation-email@example.com'
|
|
}, (error, response, body) =>
|
|
return done(error) if error?
|
|
expect(response.statusCode).to.equal 204
|
|
cb()
|
|
(cb) =>
|
|
db.tokens.find {
|
|
use: 'email_confirmation',
|
|
'data.user_id': @user._id,
|
|
usedAt: { $exists: false }
|
|
}, (error, tokens) =>
|
|
# There should only be one confirmation token at the moment
|
|
expect(tokens.length).to.equal 1
|
|
expect(tokens[0].data.email).to.equal 'reconfirmation-email@example.com'
|
|
expect(tokens[0].data.user_id).to.equal @user._id
|
|
cb()
|
|
(cb) =>
|
|
@user.request {
|
|
method: 'POST',
|
|
url: '/user/emails/resend_confirmation',
|
|
json:
|
|
email: 'reconfirmation-email@example.com'
|
|
}, (error, response, body) =>
|
|
return done(error) if error?
|
|
expect(response.statusCode).to.equal 200
|
|
cb()
|
|
(cb) =>
|
|
db.tokens.find {
|
|
use: 'email_confirmation',
|
|
'data.user_id': @user._id,
|
|
usedAt: { $exists: false }
|
|
}, (error, tokens) =>
|
|
# There should be two tokens now
|
|
expect(tokens.length).to.equal 2
|
|
expect(tokens[0].data.email).to.equal 'reconfirmation-email@example.com'
|
|
expect(tokens[0].data.user_id).to.equal @user._id
|
|
expect(tokens[1].data.email).to.equal 'reconfirmation-email@example.com'
|
|
expect(tokens[1].data.user_id).to.equal @user._id
|
|
cb()
|
|
], done
|
|
|
|
it 'should create a new token if none exists', (done) ->
|
|
# This should only be for users that have sign up with their main
|
|
# emails before the confirmation system existed
|
|
async.series [
|
|
(cb) =>
|
|
db.tokens.remove {
|
|
use: 'email_confirmation',
|
|
'data.user_id': @user._id,
|
|
usedAt: { $exists: false }
|
|
}, cb
|
|
(cb) =>
|
|
@user.request {
|
|
method: 'POST',
|
|
url: '/user/emails/resend_confirmation',
|
|
json:
|
|
email: @user.email
|
|
}, (error, response, body) =>
|
|
return done(error) if error?
|
|
expect(response.statusCode).to.equal 200
|
|
cb()
|
|
(cb) =>
|
|
db.tokens.find {
|
|
use: 'email_confirmation',
|
|
'data.user_id': @user._id,
|
|
usedAt: { $exists: false }
|
|
}, (error, tokens) =>
|
|
# There should still only be one confirmation token
|
|
expect(tokens.length).to.equal 1
|
|
expect(tokens[0].data.email).to.equal @user.email
|
|
expect(tokens[0].data.user_id).to.equal @user._id
|
|
cb()
|
|
], done
|
|
|
|
it "should not allow reconfirmation if the email doesn't match the user", (done) ->
|
|
async.series [
|
|
(cb) =>
|
|
@user.request {
|
|
method: 'POST',
|
|
url: '/user/emails/resend_confirmation',
|
|
json:
|
|
email: 'non-matching-email@example.com'
|
|
}, (error, response, body) =>
|
|
return done(error) if error?
|
|
expect(response.statusCode).to.equal 422
|
|
cb()
|
|
(cb) =>
|
|
db.tokens.find {
|
|
use: 'email_confirmation',
|
|
'data.user_id': @user._id,
|
|
usedAt: { $exists: false }
|
|
}, (error, tokens) =>
|
|
expect(tokens.length).to.equal 0
|
|
cb()
|
|
], done
|
|
|
|
describe 'setting a default email', ->
|
|
it 'should update confirmed emails for users not in v1', (done) ->
|
|
token = null
|
|
async.series [
|
|
(cb) =>
|
|
@user.request {
|
|
method: 'POST',
|
|
url: '/user/emails',
|
|
json:
|
|
email: 'new-confirmed-default@example.com'
|
|
}, (error, response, body) =>
|
|
return done(error) if error?
|
|
expect(response.statusCode).to.equal 204
|
|
cb()
|
|
(cb) =>
|
|
# Mark the email as confirmed
|
|
db.users.update {
|
|
'emails.email': 'new-confirmed-default@example.com'
|
|
}, {
|
|
$set: {
|
|
'emails.$.confirmedAt': new Date()
|
|
}
|
|
}, cb
|
|
(cb) =>
|
|
@user.request {
|
|
method: 'POST',
|
|
url: '/user/emails/default',
|
|
json:
|
|
email: 'new-confirmed-default@example.com'
|
|
}, (error, response, body) =>
|
|
return done(error) if error?
|
|
expect(response.statusCode).to.equal 200
|
|
cb()
|
|
(cb) =>
|
|
@user.request { url: '/user/emails', json: true }, (error, response, body) ->
|
|
expect(response.statusCode).to.equal 200
|
|
expect(body[0].confirmedAt).to.not.exist
|
|
expect(body[0].default).to.equal false
|
|
expect(body[1].confirmedAt).to.exist
|
|
expect(body[1].default).to.equal true
|
|
cb()
|
|
], done
|
|
|
|
it 'should not allow changing unconfirmed emails in v1', (done) ->
|
|
token = null
|
|
async.series [
|
|
(cb) =>
|
|
db.users.update {
|
|
_id: ObjectId(@user._id)
|
|
}, {
|
|
$set: {
|
|
'overleaf.id': 42
|
|
}
|
|
}, cb
|
|
(cb) =>
|
|
@user.request {
|
|
method: 'POST',
|
|
url: '/user/emails',
|
|
json:
|
|
email: 'new-unconfirmed-default@example.com'
|
|
}, (error, response, body) =>
|
|
return done(error) if error?
|
|
expect(response.statusCode).to.equal 204
|
|
cb()
|
|
(cb) =>
|
|
@user.request {
|
|
method: 'POST',
|
|
url: '/user/emails/default',
|
|
json:
|
|
email: 'new-unconfirmed-default@example.com'
|
|
}, (error, response, body) =>
|
|
return done(error) if error?
|
|
expect(response.statusCode).to.equal 409
|
|
cb()
|
|
(cb) =>
|
|
@user.request { url: '/user/emails', json: true }, (error, response, body) ->
|
|
expect(body[0].default).to.equal true
|
|
expect(body[1].default).to.equal false
|
|
cb()
|
|
], done
|
|
|
|
it 'should update the email in v1 if confirmed', (done) ->
|
|
token = null
|
|
async.series [
|
|
(cb) =>
|
|
db.users.update {
|
|
_id: ObjectId(@user._id)
|
|
}, {
|
|
$set: {
|
|
'overleaf.id': 42
|
|
}
|
|
}, cb
|
|
(cb) =>
|
|
@user.request {
|
|
method: 'POST',
|
|
url: '/user/emails',
|
|
json:
|
|
email: 'new-confirmed-default-in-v1@example.com'
|
|
}, (error, response, body) =>
|
|
return done(error) if error?
|
|
expect(response.statusCode).to.equal 204
|
|
cb()
|
|
(cb) =>
|
|
# Mark the email as confirmed
|
|
db.users.update {
|
|
'emails.email': 'new-confirmed-default-in-v1@example.com'
|
|
}, {
|
|
$set: {
|
|
'emails.$.confirmedAt': new Date()
|
|
}
|
|
}, cb
|
|
(cb) =>
|
|
@user.request {
|
|
method: 'POST',
|
|
url: '/user/emails/default',
|
|
json:
|
|
email: 'new-confirmed-default-in-v1@example.com'
|
|
}, (error, response, body) =>
|
|
return done(error) if error?
|
|
expect(response.statusCode).to.equal 200
|
|
cb()
|
|
], (error) =>
|
|
return done(error) if error?
|
|
expect(
|
|
MockV1Api.updateEmail.calledWith(42, 'new-confirmed-default-in-v1@example.com')
|
|
).to.equal true
|
|
done()
|
|
|
|
it 'should return an error if the email exists in v1', (done) ->
|
|
MockV1Api.existingEmails.push 'exists-in-v1@example.com'
|
|
async.series [
|
|
(cb) =>
|
|
db.users.update {
|
|
_id: ObjectId(@user._id)
|
|
}, {
|
|
$set: {
|
|
'overleaf.id': 42
|
|
}
|
|
}, cb
|
|
(cb) =>
|
|
@user.request {
|
|
method: 'POST',
|
|
url: '/user/emails',
|
|
json:
|
|
email: 'exists-in-v1@example.com'
|
|
}, (error, response, body) =>
|
|
return done(error) if error?
|
|
expect(response.statusCode).to.equal 204
|
|
cb()
|
|
(cb) =>
|
|
# Mark the email as confirmed
|
|
db.users.update {
|
|
'emails.email': 'exists-in-v1@example.com'
|
|
}, {
|
|
$set: {
|
|
'emails.$.confirmedAt': new Date()
|
|
}
|
|
}, cb
|
|
(cb) =>
|
|
@user.request {
|
|
method: 'POST',
|
|
url: '/user/emails/default',
|
|
json:
|
|
email: 'exists-in-v1@example.com'
|
|
}, (error, response, body) =>
|
|
return done(error) if error?
|
|
expect(response.statusCode).to.equal 409
|
|
expect(body).to.deep.equal {
|
|
message: "This email is already registered"
|
|
}
|
|
cb()
|
|
(cb) =>
|
|
@user.request { url: '/user/emails', json: true }, (error, response, body) ->
|
|
expect(body[0].default).to.equal true
|
|
expect(body[1].default).to.equal false
|
|
cb()
|
|
], done |