mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #801 from sharelatex/ho-mailchimp
Add non checked checkbox for newsletter subscription on signup and use mailchimp as newsletter provider.
This commit is contained in:
commit
5ed95694da
7 changed files with 104 additions and 39 deletions
|
@ -1,37 +1,68 @@
|
||||||
async = require('async')
|
async = require('async')
|
||||||
Request = require('request')
|
|
||||||
logger = require 'logger-sharelatex'
|
logger = require 'logger-sharelatex'
|
||||||
Settings = require 'settings-sharelatex'
|
Settings = require 'settings-sharelatex'
|
||||||
|
crypto = require('crypto')
|
||||||
|
Mailchimp = require('mailchimp-api-v3')
|
||||||
|
|
||||||
|
if !Settings.mailchimp?.api_key?
|
||||||
|
logger.info "Using newsletter provider: none"
|
||||||
|
mailchimp =
|
||||||
|
request: (opts, cb)-> cb()
|
||||||
|
else
|
||||||
|
logger.info "Using newsletter provider: mailchimp"
|
||||||
|
mailchimp = new Mailchimp(Settings.mailchimp?.api_key)
|
||||||
|
|
||||||
module.exports =
|
module.exports =
|
||||||
|
|
||||||
subscribe: (user, callback = () ->)->
|
subscribe: (user, callback = () ->)->
|
||||||
if !Settings.markdownmail?
|
|
||||||
logger.warn "No newsletter provider configured so not subscribing user"
|
|
||||||
return callback()
|
|
||||||
logger.log user:user, email:user.email, "trying to subscribe user to the mailing list"
|
|
||||||
options = buildOptions(user, true)
|
options = buildOptions(user, true)
|
||||||
Request.post options, (err, response, body)->
|
logger.log options:options, user:user, email:user.email, "trying to subscribe user to the mailing list"
|
||||||
logger.log body:body, user:user, "finished attempting to subscribe the user to the news letter"
|
mailchimp.request options, (err)->
|
||||||
|
if err?
|
||||||
|
logger.err err:err, "error subscribing person to newsletter"
|
||||||
|
else
|
||||||
|
logger.log user:user, "finished subscribing user to the newsletter"
|
||||||
callback(err)
|
callback(err)
|
||||||
|
|
||||||
unsubscribe: (user, callback = () ->)->
|
unsubscribe: (user, callback = () ->)->
|
||||||
if !Settings.markdownmail?
|
|
||||||
logger.warn "No newsletter provider configured so not unsubscribing user"
|
|
||||||
return callback()
|
|
||||||
logger.log user:user, email:user.email, "trying to unsubscribe user to the mailing list"
|
logger.log user:user, email:user.email, "trying to unsubscribe user to the mailing list"
|
||||||
options = buildOptions(user, false)
|
options = buildOptions(user, false)
|
||||||
Request.post options, (err, response, body)->
|
mailchimp.request options, (err)->
|
||||||
logger.log err:err, body:body, email:user.email, "compled newsletter unsubscribe attempt"
|
if err?
|
||||||
|
logger.err err:err, "error unsubscribing person to newsletter"
|
||||||
|
else
|
||||||
|
logger.log user:user, "finished unsubscribing user to the newsletter"
|
||||||
callback(err)
|
callback(err)
|
||||||
|
|
||||||
|
changeEmail: (oldEmail, newEmail, callback = ()->)->
|
||||||
|
options = buildOptions({email:oldEmail})
|
||||||
|
delete options.body.status
|
||||||
|
options.body.email_address = newEmail
|
||||||
|
mailchimp.request options, (err)->
|
||||||
|
# if the user has unsubscribed mailchimp will error on email address change
|
||||||
|
if err? and err?.message.indexOf("could not be validated") == -1
|
||||||
|
logger.err err:err, "error changing email in newsletter"
|
||||||
|
return callback(err)
|
||||||
|
else
|
||||||
|
logger.log "finished changing email in the newsletter"
|
||||||
|
return callback()
|
||||||
|
|
||||||
|
hashEmail = (email)->
|
||||||
|
crypto.createHash('md5').update(email.toLowerCase()).digest("hex")
|
||||||
|
|
||||||
buildOptions = (user, is_subscribed)->
|
buildOptions = (user, is_subscribed)->
|
||||||
options =
|
status = if is_subscribed then "subscribed" else "unsubscribed"
|
||||||
json:
|
subscriber_hash = hashEmail(user.email)
|
||||||
secret_token: Settings.markdownmail.secret
|
opts =
|
||||||
name: "#{user.first_name} #{user.last_name}"
|
method: "PUT"
|
||||||
email: user.email
|
path: "/lists/#{Settings.mailchimp?.list_id}/members/#{subscriber_hash}"
|
||||||
subscriber_list_id: Settings.markdownmail.list_id
|
body:
|
||||||
is_subscribed: is_subscribed
|
status_if_new: status
|
||||||
url: "https://www.markdownmail.io/lists/subscribe"
|
status: status
|
||||||
timeout: 30 * 1000
|
email_address:user.email
|
||||||
return options
|
merge_fields:
|
||||||
|
FNAME: user.first_name
|
||||||
|
LNAME: user.last_name
|
||||||
|
MONGO_ID:user._id
|
||||||
|
return opts
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
sanitize = require('sanitizer')
|
|
||||||
User = require("../../models/User").User
|
User = require("../../models/User").User
|
||||||
UserCreator = require("./UserCreator")
|
UserCreator = require("./UserCreator")
|
||||||
UserGetter = require("./UserGetter")
|
UserGetter = require("./UserGetter")
|
||||||
|
@ -54,7 +53,8 @@ module.exports = UserRegistrationHandler =
|
||||||
(cb)-> User.update {_id: user._id}, {"$set":{holdingAccount:false}}, cb
|
(cb)-> User.update {_id: user._id}, {"$set":{holdingAccount:false}}, cb
|
||||||
(cb)-> AuthenticationManager.setUserPassword user._id, userDetails.password, cb
|
(cb)-> AuthenticationManager.setUserPassword user._id, userDetails.password, cb
|
||||||
(cb)->
|
(cb)->
|
||||||
NewsLetterManager.subscribe user, ->
|
if userDetails.subscribeToNewsletter == "true"
|
||||||
|
NewsLetterManager.subscribe user, ->
|
||||||
cb() #this can be slow, just fire it off
|
cb() #this can be slow, just fire it off
|
||||||
], (err)->
|
], (err)->
|
||||||
logger.log user: user, "registered"
|
logger.log user: user, "registered"
|
||||||
|
|
|
@ -11,6 +11,7 @@ EmailHelper = require "../Helpers/EmailHelper"
|
||||||
Errors = require "../Errors/Errors"
|
Errors = require "../Errors/Errors"
|
||||||
Settings = require "settings-sharelatex"
|
Settings = require "settings-sharelatex"
|
||||||
request = require 'request'
|
request = require 'request'
|
||||||
|
NewsletterManager = require "../Newsletter/NewsletterManager"
|
||||||
|
|
||||||
module.exports = UserUpdater =
|
module.exports = UserUpdater =
|
||||||
updateUser: (query, update, callback = (error) ->) ->
|
updateUser: (query, update, callback = (error) ->) ->
|
||||||
|
@ -99,15 +100,21 @@ module.exports = UserUpdater =
|
||||||
setDefaultEmailAddress: (userId, email, callback) ->
|
setDefaultEmailAddress: (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?
|
||||||
query = _id: userId, 'emails.email': email
|
UserGetter.getUserEmail userId, (error, oldEmail) =>
|
||||||
update = $set: email: email
|
if err?
|
||||||
@updateUser query, update, (error, res) ->
|
|
||||||
if error?
|
|
||||||
logger.err error:error, 'problem setting default emails'
|
|
||||||
return callback(error)
|
return callback(error)
|
||||||
if res.n == 0 # TODO: Check n or nMatched?
|
query = _id: userId, 'emails.email': email
|
||||||
return callback(new Error('Default email does not belong to user'))
|
update = $set: email: email
|
||||||
callback()
|
@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) ->
|
updateV1AndSetDefaultEmailAddress: (userId, email, callback) ->
|
||||||
@updateEmailAddressInV1 userId, email, (error) =>
|
@updateEmailAddressInV1 userId, email, (error) =>
|
||||||
|
|
|
@ -278,10 +278,10 @@ module.exports = settings =
|
||||||
# Third party services
|
# Third party services
|
||||||
# --------------------
|
# --------------------
|
||||||
#
|
#
|
||||||
# ShareLaTeX's regular newsletter is managed by Markdown mail. Add your
|
# ShareLaTeX's regular newsletter is managed by mailchimp. Add your
|
||||||
# credentials here to integrate with this.
|
# credentials here to integrate with this.
|
||||||
# markdownmail:
|
# mailchimp:
|
||||||
# secret: ""
|
# api_key: ""
|
||||||
# list_id: ""
|
# list_id: ""
|
||||||
#
|
#
|
||||||
# Fill in your unique token from various analytics services to enable
|
# Fill in your unique token from various analytics services to enable
|
||||||
|
|
|
@ -59,6 +59,7 @@
|
||||||
"lodash": "^4.13.1",
|
"lodash": "^4.13.1",
|
||||||
"logger-sharelatex": "git+https://github.com/sharelatex/logger-sharelatex.git#master",
|
"logger-sharelatex": "git+https://github.com/sharelatex/logger-sharelatex.git#master",
|
||||||
"lynx": "0.1.1",
|
"lynx": "0.1.1",
|
||||||
|
"mailchimp-api-v3": "^1.12.0",
|
||||||
"marked": "^0.3.5",
|
"marked": "^0.3.5",
|
||||||
"method-override": "^2.3.3",
|
"method-override": "^2.3.3",
|
||||||
"metrics-sharelatex": "git+https://github.com/sharelatex/metrics-sharelatex.git#v1.7.1",
|
"metrics-sharelatex": "git+https://github.com/sharelatex/metrics-sharelatex.git#v1.7.1",
|
||||||
|
|
|
@ -132,11 +132,17 @@ describe "UserRegistrationHandler", ->
|
||||||
@AuthenticationManager.setUserPassword.calledWith(@user._id, @passingRequest.password).should.equal true
|
@AuthenticationManager.setUserPassword.calledWith(@user._id, @passingRequest.password).should.equal true
|
||||||
done()
|
done()
|
||||||
|
|
||||||
it "should add the user to the news letter manager", (done)->
|
it "should add the user to the newsletter if accepted terms", (done)->
|
||||||
|
@passingRequest.subscribeToNewsletter = "true"
|
||||||
@handler.registerNewUser @passingRequest, (err)=>
|
@handler.registerNewUser @passingRequest, (err)=>
|
||||||
@NewsLetterManager.subscribe.calledWith(@user).should.equal true
|
@NewsLetterManager.subscribe.calledWith(@user).should.equal true
|
||||||
done()
|
done()
|
||||||
|
|
||||||
|
it "should not add the user to the newsletter if not accepted terms", (done)->
|
||||||
|
@handler.registerNewUser @passingRequest, (err)=>
|
||||||
|
@NewsLetterManager.subscribe.calledWith(@user).should.equal false
|
||||||
|
done()
|
||||||
|
|
||||||
it "should track the registration event", (done)->
|
it "should track the registration event", (done)->
|
||||||
@handler.registerNewUser @passingRequest, (err)=>
|
@handler.registerNewUser @passingRequest, (err)=>
|
||||||
@AnalyticsManager.recordEvent
|
@AnalyticsManager.recordEvent
|
||||||
|
|
|
@ -18,21 +18,27 @@ describe "UserUpdater", ->
|
||||||
getUserEmail: sinon.stub()
|
getUserEmail: sinon.stub()
|
||||||
getUserByAnyEmail: sinon.stub()
|
getUserByAnyEmail: sinon.stub()
|
||||||
ensureUniqueEmailAddress: sinon.stub()
|
ensureUniqueEmailAddress: sinon.stub()
|
||||||
@logger = err: sinon.stub(), log: ->
|
@logger =
|
||||||
|
err: sinon.stub()
|
||||||
|
log: ->
|
||||||
|
warn: ->
|
||||||
@addAffiliation = sinon.stub().yields()
|
@addAffiliation = sinon.stub().yields()
|
||||||
@removeAffiliation = sinon.stub().callsArgWith(2, null)
|
@removeAffiliation = sinon.stub().callsArgWith(2, null)
|
||||||
@refreshFeatures = sinon.stub().yields()
|
@refreshFeatures = sinon.stub().yields()
|
||||||
|
@NewsletterManager =
|
||||||
|
changeEmail:sinon.stub()
|
||||||
@UserUpdater = SandboxedModule.require modulePath, requires:
|
@UserUpdater = SandboxedModule.require modulePath, requires:
|
||||||
"logger-sharelatex": @logger
|
"logger-sharelatex": @logger
|
||||||
|
"../../infrastructure/mongojs":@mongojs
|
||||||
|
"metrics-sharelatex": timeAsyncMethod: sinon.stub()
|
||||||
"./UserGetter": @UserGetter
|
"./UserGetter": @UserGetter
|
||||||
'../Institutions/InstitutionsAPI':
|
'../Institutions/InstitutionsAPI':
|
||||||
addAffiliation: @addAffiliation
|
addAffiliation: @addAffiliation
|
||||||
removeAffiliation: @removeAffiliation
|
removeAffiliation: @removeAffiliation
|
||||||
'../Subscription/FeaturesUpdater': refreshFeatures: @refreshFeatures
|
'../Subscription/FeaturesUpdater': refreshFeatures: @refreshFeatures
|
||||||
"../../infrastructure/mongojs":@mongojs
|
|
||||||
"metrics-sharelatex": timeAsyncMethod: sinon.stub()
|
|
||||||
"settings-sharelatex": @settings = {}
|
"settings-sharelatex": @settings = {}
|
||||||
"request": @request = {}
|
"request": @request = {}
|
||||||
|
"../Newsletter/NewsletterManager": @NewsletterManager
|
||||||
|
|
||||||
@stubbedUser =
|
@stubbedUser =
|
||||||
_id: "3131231"
|
_id: "3131231"
|
||||||
|
@ -174,6 +180,10 @@ describe "UserUpdater", ->
|
||||||
done()
|
done()
|
||||||
|
|
||||||
describe 'setDefaultEmailAddress', ->
|
describe 'setDefaultEmailAddress', ->
|
||||||
|
beforeEach ->
|
||||||
|
@UserGetter.getUserEmail.callsArgWith(1, null, @stubbedUser.email)
|
||||||
|
@NewsletterManager.changeEmail.callsArgWith(2, null)
|
||||||
|
|
||||||
it 'set default', (done)->
|
it 'set default', (done)->
|
||||||
@UserUpdater.updateUser = sinon.stub().callsArgWith(2, null, n: 1)
|
@UserUpdater.updateUser = sinon.stub().callsArgWith(2, null, n: 1)
|
||||||
|
|
||||||
|
@ -185,6 +195,16 @@ describe "UserUpdater", ->
|
||||||
).should.equal true
|
).should.equal true
|
||||||
done()
|
done()
|
||||||
|
|
||||||
|
it 'set changed the email in newsletter', (done)->
|
||||||
|
@UserUpdater.updateUser = sinon.stub().callsArgWith(2, null, n: 1)
|
||||||
|
|
||||||
|
@UserUpdater.setDefaultEmailAddress @stubbedUser._id, @newEmail, (err)=>
|
||||||
|
should.not.exist(err)
|
||||||
|
@NewsletterManager.changeEmail.calledWith(
|
||||||
|
@stubbedUser.email, @newEmail
|
||||||
|
).should.equal true
|
||||||
|
done()
|
||||||
|
|
||||||
it 'handle error', (done)->
|
it 'handle error', (done)->
|
||||||
@UserUpdater.updateUser = sinon.stub().callsArgWith(2, new Error('nope'))
|
@UserUpdater.updateUser = sinon.stub().callsArgWith(2, new Error('nope'))
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue