mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-09-02 17:48:50 -04:00
Implementation of the new_password endpoint.
Found a way to create the token that does not need to persist it to the database. This requires proper error messages, written by people who speak menglis good.
This commit is contained in:
@@ -1,12 +1,11 @@
|
||||
import traceback
|
||||
import uuid
|
||||
from random import randint
|
||||
|
||||
from flask import url_for
|
||||
from flask import url_for, current_app
|
||||
|
||||
from app import admin_api_client
|
||||
from app.main.dao import verify_codes_dao
|
||||
from app.main.exceptions import AdminApiClientException
|
||||
from app.main.dao import verify_codes_dao, password_reset_token_dao
|
||||
|
||||
|
||||
def create_verify_code():
|
||||
@@ -38,11 +37,9 @@ def send_email_code(user_id, email):
|
||||
return email_code
|
||||
|
||||
|
||||
def send_change_password_email(email, user_id):
|
||||
def send_change_password_email(email):
|
||||
try:
|
||||
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)
|
||||
link_to_change_password = url_for('.new_password', token=generate_token(email), _external=True)
|
||||
admin_api_client.send_email(email_address=email,
|
||||
from_str='notify@digital.cabinet-office.gov.uk',
|
||||
message=link_to_change_password,
|
||||
@@ -51,3 +48,20 @@ def send_change_password_email(email, user_id):
|
||||
except:
|
||||
traceback.print_exc()
|
||||
raise AdminApiClientException('Exception when sending email.')
|
||||
|
||||
|
||||
def generate_token(email):
|
||||
from itsdangerous import TimestampSigner
|
||||
signer = TimestampSigner(current_app.config['SECRET_KEY'])
|
||||
return signer.sign(email).decode('utf8')
|
||||
|
||||
|
||||
def check_token(token):
|
||||
from itsdangerous import TimestampSigner, SignatureExpired
|
||||
signer = TimestampSigner(current_app.config['SECRET_KEY'])
|
||||
try:
|
||||
email = signer.unsign(token, max_age=current_app.config['TOKEN_MAX_AGE_SECONDS'])
|
||||
return email
|
||||
except SignatureExpired as e:
|
||||
current_app.logger.info('token expired %s' % e)
|
||||
return None
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from flask import render_template
|
||||
|
||||
from flask import render_template, flash
|
||||
from app.main import main
|
||||
from app.main.dao import users_dao
|
||||
from app.main.forms import ForgotPasswordForm
|
||||
@@ -8,10 +7,13 @@ from app.main.views import send_change_password_email
|
||||
|
||||
@main.route('/forgot-password', methods=['GET', 'POST'])
|
||||
def forgot_password():
|
||||
form = ForgotPasswordForm(users_dao.find_all_email_address())
|
||||
form = ForgotPasswordForm()
|
||||
if form.validate_on_submit():
|
||||
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')
|
||||
if users_dao.get_user_by_email(form.email_address.data):
|
||||
send_change_password_email(form.email_address.data)
|
||||
return render_template('views/password-reset-sent.html')
|
||||
else:
|
||||
flash('The email address is not recognized. Try again.')
|
||||
return render_template('views/forgot-password.html', form=form)
|
||||
else:
|
||||
return render_template('views/forgot-password.html', form=form)
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
from datetime import datetime
|
||||
|
||||
from flask import (Markup, render_template, url_for, redirect)
|
||||
from flask import (render_template, url_for, redirect, flash, current_app)
|
||||
|
||||
from app.main import main
|
||||
from app.main.dao import (password_reset_token_dao, users_dao)
|
||||
from app.main.dao import users_dao
|
||||
from app.main.forms import NewPasswordForm
|
||||
from app.main.views import send_sms_code
|
||||
from app.main.views import send_sms_code, check_token
|
||||
|
||||
|
||||
@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)
|
||||
email_address = check_token(token)
|
||||
if email_address:
|
||||
user = users_dao.update_password(email_address.decode('utf-8'), form.new_password.data)
|
||||
send_sms_code(user.id, user.mobile_number)
|
||||
return redirect(url_for('main.two_factor'))
|
||||
else:
|
||||
flash('expired token request again')
|
||||
current_app.logger.info('we got here')
|
||||
return redirect(url_for('.forgot_password'))
|
||||
else:
|
||||
return render_template('views/new-password.html', toke=token, form=form)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user