mirror of
https://github.com/overleaf/overleaf.git
synced 2025-02-24 17:44:14 +00:00
Refactor registration so it can be called from modules
This commit is contained in:
parent
58604d3c91
commit
e8f21986dd
5 changed files with 108 additions and 83 deletions
|
@ -8,10 +8,7 @@ metrics = require("../../infrastructure/Metrics")
|
|||
Url = require("url")
|
||||
AuthenticationManager = require("../Authentication/AuthenticationManager")
|
||||
UserUpdater = require("./UserUpdater")
|
||||
EmailHandler = require("../Email/EmailHandler")
|
||||
OneTimeTokenHandler = require "../Security/OneTimeTokenHandler"
|
||||
settings = require "settings-sharelatex"
|
||||
crypto = require "crypto"
|
||||
|
||||
module.exports =
|
||||
|
||||
|
@ -85,32 +82,12 @@ module.exports =
|
|||
if !email? or email == ""
|
||||
res.sendStatus 422 # Unprocessable Entity
|
||||
return
|
||||
logger.log {email}, "registering new user"
|
||||
UserRegistrationHandler.registerNewUser {
|
||||
email: email
|
||||
password: crypto.randomBytes(32).toString("hex")
|
||||
}, (err, user)->
|
||||
if err? and err?.message != "EmailAlreadyRegistered"
|
||||
return next(err)
|
||||
|
||||
if err?.message == "EmailAlreadyRegistered"
|
||||
logger.log {email}, "user already exists, resending welcome email"
|
||||
|
||||
ONE_WEEK = 7 * 24 * 60 * 60 # seconds
|
||||
OneTimeTokenHandler.getNewToken user._id, { expiresIn: ONE_WEEK }, (err, token)->
|
||||
return next(err) if err?
|
||||
|
||||
setNewPasswordUrl = "#{settings.siteUrl}/user/activate?token=#{token}&user_id=#{user._id}"
|
||||
|
||||
EmailHandler.sendEmail "registered", {
|
||||
to: user.email
|
||||
setNewPasswordUrl: setNewPasswordUrl
|
||||
}, () ->
|
||||
|
||||
res.json {
|
||||
email: user.email
|
||||
setNewPasswordUrl: setNewPasswordUrl
|
||||
}
|
||||
UserRegistrationHandler.registerNewUserAndSendActivationEmail email, (error, user, setNewPasswordUrl) ->
|
||||
return next(error) if error?
|
||||
res.json {
|
||||
email: user.email
|
||||
setNewPasswordUrl: setNewPasswordUrl
|
||||
}
|
||||
|
||||
changePassword : (req, res, next = (error) ->)->
|
||||
metrics.inc "user.password-change"
|
||||
|
|
|
@ -5,8 +5,12 @@ AuthenticationManager = require("../Authentication/AuthenticationManager")
|
|||
NewsLetterManager = require("../Newsletter/NewsletterManager")
|
||||
async = require("async")
|
||||
logger = require("logger-sharelatex")
|
||||
crypto = require("crypto")
|
||||
EmailHandler = require("../Email/EmailHandler")
|
||||
OneTimeTokenHandler = require "../Security/OneTimeTokenHandler"
|
||||
settings = require "settings-sharelatex"
|
||||
|
||||
module.exports =
|
||||
module.exports = UserRegistrationHandler =
|
||||
validateEmail : (email) ->
|
||||
re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\ ".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA -Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
||||
return re.test(email)
|
||||
|
@ -58,6 +62,31 @@ module.exports =
|
|||
], (err)->
|
||||
logger.log user: user, "registered"
|
||||
callback(err, user)
|
||||
|
||||
registerNewUserAndSendActivationEmail: (email, callback = (error, user, setNewPasswordUrl) ->) ->
|
||||
logger.log {email}, "registering new user"
|
||||
UserRegistrationHandler.registerNewUser {
|
||||
email: email
|
||||
password: crypto.randomBytes(32).toString("hex")
|
||||
}, (err, user)->
|
||||
if err? and err?.message != "EmailAlreadyRegistered"
|
||||
return next(err)
|
||||
|
||||
if err?.message == "EmailAlreadyRegistered"
|
||||
logger.log {email}, "user already exists, resending welcome email"
|
||||
|
||||
ONE_WEEK = 7 * 24 * 60 * 60 # seconds
|
||||
OneTimeTokenHandler.getNewToken user._id, { expiresIn: ONE_WEEK }, (err, token)->
|
||||
return next(err) if err?
|
||||
|
||||
setNewPasswordUrl = "#{settings.siteUrl}/user/activate?token=#{token}&user_id=#{user._id}"
|
||||
|
||||
EmailHandler.sendEmail "registered", {
|
||||
to: user.email
|
||||
setNewPasswordUrl: setNewPasswordUrl
|
||||
}, () ->
|
||||
|
||||
callback null, user, setNewPasswordUrl
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ describe "AuthenticationManager", ->
|
|||
@bcrypt.genSalt = sinon.stub().callsArgWith(1, null, @salt)
|
||||
@bcrypt.hash = sinon.stub().callsArgWith(2, null, @hashedPassword)
|
||||
@db.users.update = sinon.stub().callsArg(2)
|
||||
@AuthenticationManager.setUserPassword(@user_id, @unencryptedPassword, @callback)
|
||||
@AuthenticationManager.setUserPassword(@user_id, @password, @callback)
|
||||
|
||||
it "should update the user's password in the database", ->
|
||||
@db.users.update
|
||||
|
|
|
@ -40,10 +40,6 @@ describe "UserController", ->
|
|||
autoAllocate:sinon.stub()
|
||||
@UserUpdater =
|
||||
changeEmailAddress:sinon.stub()
|
||||
@EmailHandler =
|
||||
sendEmail:sinon.stub().callsArgWith(2)
|
||||
@OneTimeTokenHandler =
|
||||
getNewToken: sinon.stub()
|
||||
@settings =
|
||||
siteUrl: "sharelatex.example.com"
|
||||
@UserController = SandboxedModule.require modulePath, requires:
|
||||
|
@ -57,9 +53,6 @@ describe "UserController", ->
|
|||
"../Authentication/AuthenticationManager": @AuthenticationManager
|
||||
"../Referal/ReferalAllocator":@ReferalAllocator
|
||||
"../Subscription/SubscriptionDomainHandler":@SubscriptionDomainHandler
|
||||
"../Email/EmailHandler": @EmailHandler
|
||||
"../Security/OneTimeTokenHandler": @OneTimeTokenHandler
|
||||
"crypto": @crypto = {}
|
||||
"settings-sharelatex": @settings
|
||||
"logger-sharelatex": {log:->}
|
||||
|
||||
|
@ -175,51 +168,23 @@ describe "UserController", ->
|
|||
|
||||
describe "register", ->
|
||||
beforeEach ->
|
||||
@req.body.email = @user.email = "email@example.com"
|
||||
@crypto.randomBytes = sinon.stub().returns({toString: () => @password = "mock-password"})
|
||||
@OneTimeTokenHandler.getNewToken.callsArgWith(2, null, @token = "mock-token")
|
||||
@UserRegistrationHandler.registerNewUserAndSendActivationEmail = sinon.stub().callsArgWith(1, null, @user, @url = "mock/url")
|
||||
@req.body.email = @user.email = @email = "email@example.com"
|
||||
@UserController.register @req, @res
|
||||
|
||||
describe "with a new user", ->
|
||||
beforeEach ->
|
||||
@UserRegistrationHandler.registerNewUser.callsArgWith(1, null, @user)
|
||||
@UserController.register @req, @res
|
||||
|
||||
it "should ask the UserRegistrationHandler to register user", ->
|
||||
@UserRegistrationHandler.registerNewUser
|
||||
.calledWith({
|
||||
email: @req.body.email
|
||||
password: @password
|
||||
}).should.equal true
|
||||
|
||||
it "should generate a new password reset token", ->
|
||||
@OneTimeTokenHandler.getNewToken
|
||||
.calledWith(@user_id, expiresIn: 7 * 24 * 60 * 60)
|
||||
.should.equal true
|
||||
|
||||
it "should send a registered email", ->
|
||||
@EmailHandler.sendEmail
|
||||
.calledWith("registered", {
|
||||
to: @user.email
|
||||
setNewPasswordUrl: "#{@settings.siteUrl}/user/activate?token=#{@token}&user_id=#{@user_id}"
|
||||
})
|
||||
.should.equal true
|
||||
|
||||
it "should return the user", ->
|
||||
@res.json
|
||||
.calledWith({
|
||||
email: @user.email
|
||||
setNewPasswordUrl: "#{@settings.siteUrl}/user/activate?token=#{@token}&user_id=#{@user_id}"
|
||||
})
|
||||
.should.equal true
|
||||
|
||||
describe "with a user that already exists", ->
|
||||
beforeEach ->
|
||||
@UserRegistrationHandler.registerNewUser.callsArgWith(1, new Error("EmailAlreadyRegistered"), @user)
|
||||
@UserController.register @req, @res
|
||||
|
||||
it "should still generate a new password token and email", ->
|
||||
@OneTimeTokenHandler.getNewToken.called.should.equal true
|
||||
@EmailHandler.sendEmail.called.should.equal true
|
||||
it "should register the user and send them an email", ->
|
||||
@UserRegistrationHandler.registerNewUserAndSendActivationEmail
|
||||
.calledWith(@email)
|
||||
.should.equal true
|
||||
|
||||
it "should return the user and activation url", ->
|
||||
console.log @res.json.args
|
||||
@res.json
|
||||
.calledWith({
|
||||
email: @email,
|
||||
setNewPasswordUrl: @url
|
||||
})
|
||||
.should.equal true
|
||||
|
||||
describe "changePassword", ->
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ describe "UserRegistrationHandler", ->
|
|||
|
||||
beforeEach ->
|
||||
@user =
|
||||
_id: "31j2lk21kjl"
|
||||
_id: @user_id = "31j2lk21kjl"
|
||||
@User =
|
||||
findOne:sinon.stub()
|
||||
update: sinon.stub().callsArgWith(2)
|
||||
|
@ -20,12 +20,20 @@ describe "UserRegistrationHandler", ->
|
|||
setUserPassword: sinon.stub().callsArgWith(2)
|
||||
@NewsLetterManager =
|
||||
subscribe: sinon.stub().callsArgWith(1)
|
||||
@EmailHandler =
|
||||
sendEmail:sinon.stub().callsArgWith(2)
|
||||
@OneTimeTokenHandler =
|
||||
getNewToken: sinon.stub()
|
||||
@handler = SandboxedModule.require modulePath, requires:
|
||||
"../../models/User": {User:@User}
|
||||
"./UserCreator": @UserCreator
|
||||
"../Authentication/AuthenticationManager":@AuthenticationManager
|
||||
"../Newsletter/NewsletterManager":@NewsLetterManager
|
||||
"logger-sharelatex": @logger = { log: sinon.stub() }
|
||||
"crypto": @crypto = {}
|
||||
"../Email/EmailHandler": @EmailHandler
|
||||
"../Security/OneTimeTokenHandler": @OneTimeTokenHandler
|
||||
"settings-sharelatex": @settings = {siteUrl: "http://sl.example.com"}
|
||||
|
||||
@passingRequest = {email:"something@email.com", password:"123"}
|
||||
|
||||
|
@ -128,4 +136,50 @@ describe "UserRegistrationHandler", ->
|
|||
it "should call the ReferalAllocator", (done)->
|
||||
done()
|
||||
|
||||
describe "registerNewUserAndSendActivationEmail", ->
|
||||
beforeEach ->
|
||||
@email = "email@example.com"
|
||||
@crypto.randomBytes = sinon.stub().returns({toString: () => @password = "mock-password"})
|
||||
@OneTimeTokenHandler.getNewToken.callsArgWith(2, null, @token = "mock-token")
|
||||
@handler.registerNewUser = sinon.stub()
|
||||
@callback = sinon.stub()
|
||||
|
||||
describe "with a new user", ->
|
||||
beforeEach ->
|
||||
@handler.registerNewUser.callsArgWith(1, null, @user)
|
||||
@handler.registerNewUserAndSendActivationEmail @email, @callback
|
||||
|
||||
it "should ask the UserRegistrationHandler to register user", ->
|
||||
@handler.registerNewUser
|
||||
.calledWith({
|
||||
email: @email
|
||||
password: @password
|
||||
}).should.equal true
|
||||
|
||||
it "should generate a new password reset token", ->
|
||||
|
||||
@OneTimeTokenHandler.getNewToken
|
||||
.calledWith(@user_id, expiresIn: 7 * 24 * 60 * 60)
|
||||
.should.equal true
|
||||
|
||||
it "should send a registered email", ->
|
||||
@EmailHandler.sendEmail
|
||||
.calledWith("registered", {
|
||||
to: @user.email
|
||||
setNewPasswordUrl: "#{@settings.siteUrl}/user/activate?token=#{@token}&user_id=#{@user_id}"
|
||||
})
|
||||
.should.equal true
|
||||
|
||||
it "should return the user", ->
|
||||
@callback
|
||||
.calledWith(null, @user, "#{@settings.siteUrl}/user/activate?token=#{@token}&user_id=#{@user_id}")
|
||||
.should.equal true
|
||||
|
||||
describe "with a user that already exists", ->
|
||||
beforeEach ->
|
||||
@handler.registerNewUser.callsArgWith(1, new Error("EmailAlreadyRegistered"), @user)
|
||||
@handler.registerNewUserAndSendActivationEmail @email, @callback
|
||||
|
||||
it "should still generate a new password token and email", ->
|
||||
@OneTimeTokenHandler.getNewToken.called.should.equal true
|
||||
@EmailHandler.sendEmail.called.should.equal true
|
Loading…
Reference in a new issue