| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- logger = require("logger-sharelatex")
- mongojs = require("../../infrastructure/mongojs")
- metrics = require("metrics-sharelatex")
- db = mongojs.db
- async = require("async")
- ObjectId = mongojs.ObjectId
- UserGetter = require("./UserGetter")
- { addAffiliation, removeAffiliation } = require("../Institutions/InstitutionsAPI")
- FeaturesUpdater = require("../Subscription/FeaturesUpdater")
- EmailHelper = require "../Helpers/EmailHelper"
- Errors = require "../Errors/Errors"
- Settings = require "settings-sharelatex"
- request = require 'request'
- NewsletterManager = require "../Newsletter/NewsletterManager"
- module.exports = UserUpdater =
- updateUser: (query, update, callback = (error) ->) ->
- if typeof query == "string"
- query = _id: ObjectId(query)
- else if query instanceof ObjectId
- query = _id: query
- else if typeof query._id == "string"
- query._id = ObjectId(query._id)
- db.users.update query, update, callback
- #
- # DEPRECATED
- #
- # Change the user's main email address by adding a new email, switching the
- # default email and removing the old email. Prefer manipulating multiple
- # emails and the default rather than calling this method directly
- #
- changeEmailAddress: (userId, newEmail, callback)->
- newEmail = EmailHelper.parseEmail(newEmail)
- return callback(new Error('invalid email')) if !newEmail?
- logger.log userId: userId, newEmail: newEmail, "updaing email address of user"
- oldEmail = null
- async.series [
- (cb) ->
- UserGetter.getUserEmail userId, (error, email) ->
- oldEmail = email
- cb(error)
- (cb) -> UserUpdater.addEmailAddress userId, newEmail, cb
- (cb) -> UserUpdater.setDefaultEmailAddress userId, newEmail, cb
- (cb) -> UserUpdater.removeEmailAddress userId, oldEmail, cb
- ], callback
- # Add a new email address for the user. Email cannot be already used by this
- # or any other user
- addEmailAddress: (userId, newEmail, affiliationOptions, callback) ->
- unless callback? # affiliationOptions is optional
- callback = affiliationOptions
- affiliationOptions = {}
- newEmail = EmailHelper.parseEmail(newEmail)
- return callback(new Error('invalid email')) if !newEmail?
- UserGetter.ensureUniqueEmailAddress newEmail, (error) =>
- return callback(error) if error?
- addAffiliation userId, newEmail, affiliationOptions, (error) =>
- if error?
- logger.err error: error, 'problem adding affiliation while adding email'
- return callback(error)
- update = $push: emails: email: newEmail, createdAt: new Date()
- @updateUser userId, update, (error) ->
- if error?
- logger.err error: error, 'problem updating users emails'
- return callback(error)
- callback()
- # remove one of the user's email addresses. The email cannot be the user's
- # default email address
- removeEmailAddress: (userId, email, callback) ->
- email = EmailHelper.parseEmail(email)
- return callback(new Error('invalid email')) if !email?
- removeAffiliation userId, email, (error) =>
- if error?
- logger.err error: error, 'problem removing affiliation'
- return callback(error)
- query = _id: userId, email: $ne: email
- update = $pull: emails: email: email
- @updateUser query, update, (error, res) ->
- if error?
- logger.err error:error, 'problem removing users email'
- return callback(error)
- if res.n == 0
- return callback(new Error('Cannot remove email'))
- callback()
- # set the default email address by setting the `email` attribute. The email
- # must be one of the user's multiple emails (`emails` attribute)
- setDefaultEmailAddress: (userId, email, callback) ->
- email = EmailHelper.parseEmail(email)
- return callback(new Error('invalid email')) if !email?
- UserGetter.getUserEmail userId, (error, oldEmail) =>
- if err?
- return callback(error)
- query = _id: userId, 'emails.email': email
- update = $set: email: email
- @updateUser query, update, (error, res) ->
- if error?
- logger.err error:error, 'problem setting default emails'
- return callback(error)
- else if res.n == 0 # TODO: Check n or nMatched?
- return callback(new Error('Default email does not belong to user'))
- else
- NewsletterManager.changeEmail oldEmail, email, ->
- 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:
- user:
- 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 response.statusCode == 409 # Conflict
- return callback(new Errors.EmailExistsError('email exists in v1'))
- else if 200 <= response.statusCode < 300
- return callback()
- else
- return callback new Error("non-success code from v1: #{response.statusCode}")
- confirmEmail: (userId, email, confirmedAt, callback) ->
- if arguments.length == 3
- callback = confirmedAt
- confirmedAt = new Date()
- email = EmailHelper.parseEmail(email)
- return callback(new Error('invalid email')) if !email?
- logger.log {userId, email}, 'confirming user email'
- addAffiliation userId, email, {confirmedAt: confirmedAt}, (error) =>
- if error?
- logger.err error: error, 'problem adding affiliation while confirming email'
- return callback(error)
- query =
- _id: userId
- 'emails.email': email
- update =
- $set:
- 'emails.$.confirmedAt': confirmedAt
- @updateUser query, update, (error, res) ->
- return callback(error) if error?
- logger.log {res, userId, email}, "tried to confirm email"
- if res.n == 0
- return callback(new Errors.NotFoundError('user id and email do no match'))
- FeaturesUpdater.refreshFeatures userId, true, callback
- [
- 'updateUser'
- 'changeEmailAddress'
- 'setDefaultEmailAddress'
- 'addEmailAddress'
- 'removeEmailAddress'
- ].map (method) ->
- metrics.timeAsyncMethod(UserUpdater, method, 'mongo.UserUpdater', logger)
|