New-password endpoints are implemented.

There should be a better way to validate the token.
This commit is contained in:
Rebecca Law
2016-01-06 17:37:07 +00:00
parent f94966154d
commit b5901a1ac7
9 changed files with 104 additions and 36 deletions

View File

@@ -3,9 +3,15 @@ from app import db
from app.models import PasswordResetToken
def insert(token):
token.expiry_date = datetime.now() + timedelta(hours=1)
db.session.add(token)
def insert(token, user_id):
password_reset_token = PasswordResetToken(token=token,
user_id=user_id,
expiry_date=datetime.now() + timedelta(hours=1))
insert_token(password_reset_token)
def insert_token(password_reset_token):
db.session.add(password_reset_token)
db.session.commit()

View File

@@ -1,3 +1,5 @@
from datetime import datetime
from flask import session
from flask_wtf import Form
from wtforms import StringField, PasswordField, ValidationError
@@ -139,3 +141,8 @@ class ForgotPasswordForm(Form):
raise ValidationError('Please enter the email address that you registered with')
class NewPasswordForm(Form):
new_password = StringField('Create a password',
validators=[DataRequired(message='Please enter your password'),
Length(10, 255, message='Password must be at least 10 characters'),
Blacklist(message='That password is blacklisted, too common')])

View File

@@ -6,7 +6,7 @@ from flask import url_for
from app import admin_api_client
from app.main.exceptions import AdminApiClientException
from app.main.dao import verify_codes_dao
from app.main.dao import verify_codes_dao, password_reset_token_dao
def create_verify_code():
@@ -38,13 +38,15 @@ def send_email_code(user_id, email):
return email_code
def send_change_password_email(email):
def send_change_password_email(email, user_id):
try:
link_to_change_password = url_for('.new_password', token=str(uuid.uuid4()))
reset_password_token = str(uuid.uuid4()).replace('-', '')
link_to_change_password = url_for('.new_password', token=reset_password_token, _external=True)
password_reset_token_dao.insert(reset_password_token, user_id)
admin_api_client.send_email(email_address=email,
from_str='notify@digital.cabinet-office.gov.uk',
message=link_to_change_password,
subject='Verification code',
subject='Reset password for GOV.UK Notify',
token=admin_api_client.auth_token)
except:
traceback.print_exc()

View File

@@ -10,7 +10,8 @@ from app.main.views import send_change_password_email
def forgot_password():
form = ForgotPasswordForm(users_dao.find_all_email_address())
if form.validate_on_submit():
send_change_password_email(form.email_address.data)
user = users_dao.get_user_by_email(form.email_address.data)
send_change_password_email(form.email_address.data, user.id)
return render_template('views/password-reset-sent.html')
else:
return render_template('views/forgot-password.html', form=form)

View File

@@ -1,16 +1,29 @@
from flask import request
from datetime import datetime
from flask import (Markup, render_template, url_for, redirect)
from app.main import main
from app.main.dao import (password_reset_token_dao, users_dao)
from app.main.forms import NewPasswordForm
from app.main.views import send_sms_code
@main.route('/new-password/<token>', methods=['GET', 'POST'])
def new_password():
# Validate token
token = request.args.get('token')
# get password token (better name)
# is it expired
# add NewPasswordForm
# update password
# create password_token table (id, token, user_id, expiry_date
@main.route('/new-password/<path:token>', methods=['GET', 'POST'])
def new_password(token):
form = NewPasswordForm()
if form.validate_on_submit():
password_reset_token = password_reset_token_dao.get_token(str(Markup.escape(token)))
if not valid_token(password_reset_token):
form.new_password.errors.append('token is invalid') # Is there a better way
return render_template('views/new-password.html', form=form)
else:
users_dao.update_password(password_reset_token.user_id, form.new_password.data)
user = users_dao.get_user_by_id(password_reset_token.user_id)
send_sms_code(user.id, user.mobile_number)
return redirect(url_for('main.render_two_factor'))
else:
return render_template('views/new-password.html', toke=token, form=form)
return 'Got here'
def valid_token(token):
return token and datetime.now() <= token.expiry_date

View File

@@ -12,15 +12,18 @@ GOV.UK Notify
<p> You can now create a new password for your account.</p>
<p>
<label class="form-label" for="password">Create a password</label>
<input class="form-control-1-4" id="password" type="password"> <br>
<form action="" autocomplete="off" method="post">
{{ form.hidden_tag() }}
<p>
{{ render_field(form.new_password, class="form-control-1-4", type="password") }}
<span class="font-xsmall">Your password must have at least 10 characters</span>
</p>
<p>
<a class="button" href="two-factor" role="button">Continue</a>
<button class="button" role="button">Continue</button>
</p>
</form>
</div>
</div>