mirror of
https://github.com/overleaf/overleaf.git
synced 2025-03-15 08:23:08 +00:00
Update email in v1 when setting default in v2
This commit is contained in:
parent
f08b64eeac
commit
d0f77abc70
6 changed files with 194 additions and 5 deletions
|
@ -68,6 +68,13 @@ V1ConnectionError = (message) ->
|
||||||
return error
|
return error
|
||||||
V1ConnectionError.prototype.__proto___ = Error.prototype
|
V1ConnectionError.prototype.__proto___ = Error.prototype
|
||||||
|
|
||||||
|
UnconfirmedEmailError = (message) ->
|
||||||
|
error = new Error(message)
|
||||||
|
error.name = "UnconfirmedEmailError"
|
||||||
|
error.__proto__ = UnconfirmedEmailError.prototype
|
||||||
|
return error
|
||||||
|
UnconfirmedEmailError.prototype.__proto___ = Error.prototype
|
||||||
|
|
||||||
module.exports = Errors =
|
module.exports = Errors =
|
||||||
NotFoundError: NotFoundError
|
NotFoundError: NotFoundError
|
||||||
ServiceNotConfiguredError: ServiceNotConfiguredError
|
ServiceNotConfiguredError: ServiceNotConfiguredError
|
||||||
|
@ -79,3 +86,4 @@ module.exports = Errors =
|
||||||
V1HistoryNotSyncedError: V1HistoryNotSyncedError
|
V1HistoryNotSyncedError: V1HistoryNotSyncedError
|
||||||
ProjectHistoryDisabledError: ProjectHistoryDisabledError
|
ProjectHistoryDisabledError: ProjectHistoryDisabledError
|
||||||
V1ConnectionError: V1ConnectionError
|
V1ConnectionError: V1ConnectionError
|
||||||
|
UnconfirmedEmailError: UnconfirmedEmailError
|
||||||
|
|
|
@ -47,9 +47,14 @@ module.exports = UserEmailsController =
|
||||||
email = EmailHelper.parseEmail(req.body.email)
|
email = EmailHelper.parseEmail(req.body.email)
|
||||||
return res.sendStatus 422 unless email?
|
return res.sendStatus 422 unless email?
|
||||||
|
|
||||||
UserUpdater.setDefaultEmailAddress userId, email, (error)->
|
UserUpdater.updateV1AndSetDefaultEmailAddress userId, email, (error)->
|
||||||
return next(error) if error?
|
if error?
|
||||||
res.sendStatus 200
|
if error instanceof Errors.UnconfirmedEmailError
|
||||||
|
return res.sendStatus 409
|
||||||
|
else
|
||||||
|
return next(error)
|
||||||
|
else
|
||||||
|
return res.sendStatus 200
|
||||||
|
|
||||||
|
|
||||||
endorse: (req, res, next) ->
|
endorse: (req, res, next) ->
|
||||||
|
|
|
@ -8,6 +8,8 @@ UserGetter = require("./UserGetter")
|
||||||
{ addAffiliation, removeAffiliation } = require("./UserAffiliationsManager")
|
{ addAffiliation, removeAffiliation } = require("./UserAffiliationsManager")
|
||||||
EmailHelper = require "../Helpers/EmailHelper"
|
EmailHelper = require "../Helpers/EmailHelper"
|
||||||
Errors = require "../Errors/Errors"
|
Errors = require "../Errors/Errors"
|
||||||
|
Settings = require "settings-sharelatex"
|
||||||
|
request = require 'request'
|
||||||
|
|
||||||
module.exports = UserUpdater =
|
module.exports = UserUpdater =
|
||||||
updateUser: (query, update, callback = (error) ->) ->
|
updateUser: (query, update, callback = (error) ->) ->
|
||||||
|
@ -106,6 +108,45 @@ module.exports = UserUpdater =
|
||||||
return callback(new Error('Default email does not belong to user'))
|
return callback(new Error('Default email does not belong to user'))
|
||||||
callback()
|
callback()
|
||||||
|
|
||||||
|
updateV1AndSetDefaultEmailAddress: (userId, email, callback) ->
|
||||||
|
@updateEmailAddressInV1 userId, email, (error) =>
|
||||||
|
return callback(error) if error?
|
||||||
|
@setDefaultEmailAddress userId, email, callback
|
||||||
|
|
||||||
|
updateEmailAddressInV1: (userId, newEmail, callback) ->
|
||||||
|
if !Settings.apis?.v1?.url?
|
||||||
|
return callback()
|
||||||
|
UserGetter.getUser userId, { 'overleaf.id': 1, emails: 1 }, (error, user) ->
|
||||||
|
return callback(error) if error?
|
||||||
|
return callback(new Errors.NotFoundError('no user found')) if !user?
|
||||||
|
if !user.overleaf?.id?
|
||||||
|
return callback()
|
||||||
|
newEmailIsConfirmed = false
|
||||||
|
for email in user.emails
|
||||||
|
if email.email == newEmail and email.confirmedAt?
|
||||||
|
newEmailIsConfirmed = true
|
||||||
|
break
|
||||||
|
if !newEmailIsConfirmed
|
||||||
|
return callback(new Errors.UnconfirmedEmailError("can't update v1 with unconfirmed email"))
|
||||||
|
request {
|
||||||
|
baseUrl: Settings.apis.v1.url
|
||||||
|
url: "/api/v1/sharelatex/users/#{user.overleaf.id}/email"
|
||||||
|
method: 'PUT'
|
||||||
|
auth:
|
||||||
|
user: Settings.apis.v1.user
|
||||||
|
pass: Settings.apis.v1.pass
|
||||||
|
sendImmediately: true
|
||||||
|
json: { email: newEmail },
|
||||||
|
timeout: 5 * 1000
|
||||||
|
}, (error, response, body) ->
|
||||||
|
if error?
|
||||||
|
error = new Errors.V1ConnectionError('No V1 connection') if error.code == 'ECONNREFUSED'
|
||||||
|
return callback(error)
|
||||||
|
if 200 <= response.statusCode < 300
|
||||||
|
return callback()
|
||||||
|
else
|
||||||
|
return callback new Error("non-success code from v1: #{response.statusCode}")
|
||||||
|
|
||||||
confirmEmail: (userId, email, callback) ->
|
confirmEmail: (userId, email, callback) ->
|
||||||
email = EmailHelper.parseEmail(email)
|
email = EmailHelper.parseEmail(email)
|
||||||
return callback(new Error('invalid email')) if !email?
|
return callback(new Error('invalid email')) if !email?
|
||||||
|
|
|
@ -302,3 +302,131 @@ describe "UserEmails", ->
|
||||||
expect(tokens.length).to.equal 0
|
expect(tokens.length).to.equal 0
|
||||||
cb()
|
cb()
|
||||||
], done
|
], done
|
||||||
|
|
||||||
|
describe 'setting a default email', ->
|
||||||
|
it 'should update confirmed emails', (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 v2', (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()
|
||||||
|
|
|
@ -28,6 +28,8 @@ module.exports = MockV1Api =
|
||||||
|
|
||||||
affiliations: []
|
affiliations: []
|
||||||
|
|
||||||
|
updateEmail: sinon.stub()
|
||||||
|
|
||||||
setAffiliations: (affiliations) -> @affiliations = affiliations
|
setAffiliations: (affiliations) -> @affiliations = affiliations
|
||||||
|
|
||||||
run: () ->
|
run: () ->
|
||||||
|
@ -64,6 +66,10 @@ module.exports = MockV1Api =
|
||||||
app.get '/university/domains', (req, res, next) ->
|
app.get '/university/domains', (req, res, next) ->
|
||||||
res.json []
|
res.json []
|
||||||
|
|
||||||
|
app.put '/api/v1/sharelatex/users/:id/email', (req, res, next) =>
|
||||||
|
@updateEmail parseInt(req.params.id), req.body.email
|
||||||
|
res.sendStatus 200
|
||||||
|
|
||||||
app.listen 5000, (error) ->
|
app.listen 5000, (error) ->
|
||||||
throw error if error?
|
throw error if error?
|
||||||
.on "error", (error) ->
|
.on "error", (error) ->
|
||||||
|
|
|
@ -24,6 +24,7 @@ describe "UserEmailsController", ->
|
||||||
addEmailAddress: sinon.stub()
|
addEmailAddress: sinon.stub()
|
||||||
removeEmailAddress: sinon.stub()
|
removeEmailAddress: sinon.stub()
|
||||||
setDefaultEmailAddress: sinon.stub()
|
setDefaultEmailAddress: sinon.stub()
|
||||||
|
updateV1AndSetDefaultEmailAddress: sinon.stub()
|
||||||
@EmailHelper =
|
@EmailHelper =
|
||||||
parseEmail: sinon.stub()
|
parseEmail: sinon.stub()
|
||||||
@endorseAffiliation = sinon.stub().yields()
|
@endorseAffiliation = sinon.stub().yields()
|
||||||
|
@ -126,13 +127,13 @@ describe "UserEmailsController", ->
|
||||||
@EmailHelper.parseEmail.returns @email
|
@EmailHelper.parseEmail.returns @email
|
||||||
|
|
||||||
it 'sets default email', (done) ->
|
it 'sets default email', (done) ->
|
||||||
@UserUpdater.setDefaultEmailAddress.callsArgWith 2, null
|
@UserUpdater.updateV1AndSetDefaultEmailAddress.callsArgWith 2, null
|
||||||
|
|
||||||
@UserEmailsController.setDefault @req,
|
@UserEmailsController.setDefault @req,
|
||||||
sendStatus: (code) =>
|
sendStatus: (code) =>
|
||||||
code.should.equal 200
|
code.should.equal 200
|
||||||
assertCalledWith @EmailHelper.parseEmail, @email
|
assertCalledWith @EmailHelper.parseEmail, @email
|
||||||
assertCalledWith @UserUpdater.setDefaultEmailAddress, @user._id, @email
|
assertCalledWith @UserUpdater.updateV1AndSetDefaultEmailAddress, @user._id, @email
|
||||||
done()
|
done()
|
||||||
|
|
||||||
it 'handles email parse error', (done) ->
|
it 'handles email parse error', (done) ->
|
||||||
|
|
Loading…
Reference in a new issue