mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
token based reset works
This commit is contained in:
parent
1ffd19099b
commit
96d98329f1
8 changed files with 50 additions and 24 deletions
|
@ -37,16 +37,30 @@ Henry <br>
|
|||
ShareLaTeX Co-founder
|
||||
'''
|
||||
|
||||
templates.passwordReset =
|
||||
templates.passwordResetRequested =
|
||||
subject: _.template "Password Reset - ShareLatex.com"
|
||||
layout: NotificationEmailLayout
|
||||
type:"notification"
|
||||
compiledTemplate: _.template '''
|
||||
<h1 class="h1">Password Reset</h1>
|
||||
<p>
|
||||
Your password has been reset, the new password is <p> <%= newPassword %>
|
||||
We got a request to reset your ShareLaTeX password.
|
||||
<p>
|
||||
please <a href="https://www.sharelatex.com/login">login here</a> and then change your password <a href=#{Settings.siteUrl}/user/settings> in your user settings</a>
|
||||
<center>
|
||||
<div style="width:200px;background-color:#0069CC;border:1px solid #02A9D6;border-radius:4px;padding:15px; margin:10px 5px">
|
||||
<div style="padding-right:10px;padding-left:10px">
|
||||
<a href="<%= setNewPasswordUrl %>" style="text-decoration:none" target="_blank">
|
||||
<span style= "font-size:16px;font-family:Arial;font-weight:bold;color:#fff;white-space:nowrap;display:block; text-align:center">
|
||||
Reset password
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</center>
|
||||
|
||||
If you ignore this message, your password won't be changed.
|
||||
<p>
|
||||
If you didn't request a password reset, let us know.
|
||||
|
||||
</p>
|
||||
<p>Thank you</p>
|
||||
|
@ -79,6 +93,7 @@ module.exports =
|
|||
|
||||
buildEmail: (templateName, opts)->
|
||||
template = templates[templateName]
|
||||
console.log opts
|
||||
opts.body = template.compiledTemplate(opts)
|
||||
return {
|
||||
subject : template.subject(opts)
|
||||
|
|
|
@ -16,7 +16,7 @@ module.exports =
|
|||
if err then return callback(err)
|
||||
emailOptions =
|
||||
to : email
|
||||
setNewPasswordUrl : "#{settings.siteUrl}/user/password/set?resetToken=#{token}"
|
||||
setNewPasswordUrl : "#{settings.siteUrl}/user/password/set?passwordResetToken=#{token}"
|
||||
EmailHandler.sendEmail "passwordResetRequested", emailOptions, callback
|
||||
|
||||
setNewUserPassword: (token, password, callback)->
|
||||
|
|
|
@ -4,23 +4,24 @@ rclient = redis.createClient(Settings.redis.web.port, Settings.redis.web.host)
|
|||
rclient.auth(Settings.redis.web.password)
|
||||
uuid = require("node-uuid")
|
||||
|
||||
ONE_MIN = 60 * 1000
|
||||
ONE_HOUR_IN_MS = ONE_MIN * 60
|
||||
ONE_HOUR_IN_S = 60 * 60
|
||||
|
||||
buildKey = (token)-> return "password_token:#{token}"
|
||||
|
||||
module.exports =
|
||||
|
||||
getNewToken: (user_id, callback)->
|
||||
token = uuid.v4()
|
||||
multi = rclient.multi()
|
||||
multi.set token, user_id
|
||||
multi.expire token, ONE_HOUR_IN_MS
|
||||
multi.set buildKey(token), user_id
|
||||
multi.expire buildKey(token), ONE_HOUR_IN_S
|
||||
multi.exec (err)->
|
||||
callback(err, token)
|
||||
|
||||
getUserIdFromToken: (token, callback)->
|
||||
multi = rclient.multi()
|
||||
multi.get token
|
||||
multi.del token
|
||||
multi.get buildKey(token)
|
||||
multi.del buildKey(token)
|
||||
multi.exec (err, results)->
|
||||
callback err, results[0]
|
||||
|
||||
|
|
|
@ -20,5 +20,5 @@ block content
|
|||
input.span4#password.required(type='password', name='password', placeholder='********')
|
||||
.actions
|
||||
button.btn-primary.btn.btn-large#login(type='submit') Login
|
||||
a#passwordReset(href='/user/passwordreset') forgot password?
|
||||
a#passwordReset(href='/user/password/reset') forgot password?
|
||||
include ../general/small-footer
|
||||
|
|
|
@ -7,7 +7,7 @@ block content
|
|||
.page-header
|
||||
h1 Set Password
|
||||
.messageArea
|
||||
form.validate#passwordReset(method='post')
|
||||
form.validate#setPasswordReset(method='post')
|
||||
input(type="hidden", name="_csrf", value=csrfToken)
|
||||
.clearfix
|
||||
label(for='xlInput') Password
|
||||
|
|
|
@ -93,16 +93,26 @@ require [
|
|||
event.preventDefault()
|
||||
formData = $(this).serialize()
|
||||
$.ajax
|
||||
url: "/user/passwordReset"
|
||||
url: "/user/password/reset"
|
||||
type:'POST'
|
||||
data: formData
|
||||
success: (data)->
|
||||
if data.message
|
||||
new Message data.message
|
||||
else if data.redir
|
||||
window.location.href = data.redir
|
||||
else
|
||||
window.location.href = '/'
|
||||
new Message text:"You have been sent an email to complete your password reset."
|
||||
error:(data)->
|
||||
new Message type:"error", text:"something went wrong processing your request."
|
||||
|
||||
$('form#setPasswordReset').submit (event)->
|
||||
event.preventDefault()
|
||||
formData = $(this).serialize()
|
||||
$.ajax
|
||||
url: "/user/password/set"
|
||||
type:'POST'
|
||||
data: formData
|
||||
success: (data)->
|
||||
new Message text:"Your password has been reset"
|
||||
error:(data)->
|
||||
new Message type:"error", text:"something went wrong processing your request."
|
||||
|
||||
|
||||
|
||||
$('a#deleteUserAccount').click (e)->
|
||||
|
|
|
@ -54,7 +54,7 @@ describe "PasswordResetHandler", ->
|
|||
@EmailHandler.sendEmail.called.should.equal true
|
||||
args = @EmailHandler.sendEmail.args[0]
|
||||
args[0].should.equal "passwordResetRequested"
|
||||
args[1].setNewPasswordUrl.should.equal "#{@settings.siteUrl}/user/password/set?resetToken=#{@token}"
|
||||
args[1].setNewPasswordUrl.should.equal "#{@settings.siteUrl}/user/password/set?passwordResetToken=#{@token}"
|
||||
done()
|
||||
|
||||
|
||||
|
|
|
@ -39,8 +39,8 @@ describe "TokenGenerator", ->
|
|||
it "should set a new token into redis with a ttl", (done)->
|
||||
@redisMulti.exec.callsArgWith(0)
|
||||
@TokenGenerator.getNewToken @user_id, (err, token)=>
|
||||
@redisMulti.set @stubbedToken, @user_id
|
||||
@redisMulti.expire @stubbedToken, (60*1000)*60
|
||||
@redisMulti.set "password_token:#{@stubbedToken}", @user_id
|
||||
@redisMulti.expire "password_token:#{@stubbedToken}", 60 * 60
|
||||
done()
|
||||
|
||||
it "should return if there was an error", (done)->
|
||||
|
@ -56,8 +56,8 @@ describe "TokenGenerator", ->
|
|||
@redisMulti.exec.callsArgWith(0, null, [@user_id])
|
||||
@TokenGenerator.getUserIdFromToken @stubbedToken, (err, user_id)=>
|
||||
user_id.should.equal @user_id
|
||||
@redisMulti.get.calledWith(@stubbedToken).should.equal true
|
||||
@redisMulti.del.calledWith(@stubbedToken).should.equal true
|
||||
@redisMulti.get.calledWith("password_token:#{@stubbedToken}").should.equal true
|
||||
@redisMulti.del.calledWith("password_token:#{@stubbedToken}").should.equal true
|
||||
done()
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue