Updated generate_token to use encrypt the entire url.

Created notify_client.sender to hold the methods to send notifications.
This commit is contained in:
Rebecca Law
2016-01-11 15:17:00 +00:00
parent dd242752c7
commit 05695a1c03
13 changed files with 113 additions and 93 deletions

View File

View File

@@ -1,54 +0,0 @@
from random import randint
from flask import url_for, current_app
from app import admin_api_client
from app.main.dao import verify_codes_dao
def create_verify_code():
return ''.join(["%s" % randint(0, 9) for _ in range(0, 5)])
def send_sms_code(user_id, mobile_number):
sms_code = create_verify_code()
verify_codes_dao.add_code(user_id=user_id, code=sms_code, code_type='sms')
admin_api_client.send_sms(mobile_number=mobile_number, message=sms_code, token=admin_api_client.auth_token)
return sms_code
def send_email_code(user_id, email):
email_code = create_verify_code()
verify_codes_dao.add_code(user_id=user_id, code=email_code, code_type='email')
admin_api_client.send_email(email_address=email,
from_str='notify@digital.cabinet-office.gov.uk',
message=email_code,
subject='Verification code',
token=admin_api_client.auth_token)
return email_code
def send_change_password_email(email):
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,
subject='Reset password for GOV.UK Notify',
token=admin_api_client.auth_token)
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)

View File

@@ -1,10 +1,10 @@
from flask import (
render_template, redirect, jsonify, session, url_for)
render_template, redirect, session, url_for)
from app.main import main
from app.main.dao import users_dao
from app.main.forms import EmailNotReceivedForm, TextNotReceivedForm
from app.main.views import send_sms_code, send_email_code
from app.notify_client.sender import send_sms_code, send_email_code
@main.route('/email-not-received', methods=['GET', 'POST'])

View File

@@ -1,8 +1,8 @@
from flask import render_template, flash, current_app
from flask import render_template, current_app
from app.main import main
from app.main.dao import users_dao
from app.main.forms import ForgotPasswordForm
from app.main.views import send_change_password_email
from app.notify_client.sender import send_change_password_email
@main.route('/forgot-password', methods=['GET', 'POST'])

View File

@@ -3,7 +3,7 @@ from flask import (render_template, url_for, redirect, flash)
from app.main import main
from app.main.dao import users_dao
from app.main.forms import NewPasswordForm
from app.main.views import send_sms_code, check_token
from app.notify_client.sender import check_token, send_sms_code
@main.route('/new-password/<path:token>', methods=['GET', 'POST'])
@@ -13,7 +13,7 @@ def new_password(token):
flash('The link in the email we sent you has expired. Enter your email address to resend.')
return redirect(url_for('.forgot_password'))
user = users_dao.get_user_by_email(email_address=email_address.decode('utf-8'))
user = users_dao.get_user_by_email(email_address=email_address)
if user and user.state != 'request_password_reset':
flash('The link in the email we sent you has already been used.')
return redirect(url_for('.index'))

View File

@@ -5,12 +5,14 @@ from flask import render_template, redirect, session
from app.main import main
from app.main.dao import users_dao
from app.main.forms import RegisterUserForm
from app.main.views import send_sms_code, send_email_code
from app.models import User
# TODO how do we handle duplicate unverifed email addresses?
# malicious or otherwise.
from app.notify_client.sender import send_sms_code, send_email_code
@main.route('/register', methods=['GET', 'POST'])
def register():
form = RegisterUserForm(users_dao.get_user_by_email)

View File

@@ -1,12 +1,12 @@
from flask import (
render_template, redirect, jsonify, url_for)
render_template, redirect, url_for)
from flask import session
from app.main import main
from app.main.dao import users_dao
from app.main.encryption import check_hash
from app.main.forms import LoginForm
from app.main.views import send_sms_code
from app.notify_client.sender import send_sms_code
@main.route('/sign-in', methods=(['GET', 'POST']))

View File

@@ -0,0 +1,52 @@
from random import randint
from flask import url_for, current_app
from itsdangerous import URLSafeTimedSerializer, SignatureExpired
from app import admin_api_client
from app.main.dao import verify_codes_dao
def create_verify_code():
return ''.join(["%s" % randint(0, 9) for _ in range(0, 5)])
def send_sms_code(user_id, mobile_number):
sms_code = create_verify_code()
verify_codes_dao.add_code(user_id=user_id, code=sms_code, code_type='sms')
admin_api_client.send_sms(mobile_number=mobile_number, message=sms_code, token=admin_api_client.auth_token)
return sms_code
def send_email_code(user_id, email):
email_code = create_verify_code()
verify_codes_dao.add_code(user_id=user_id, code=email_code, code_type='email')
admin_api_client.send_email(email_address=email,
from_str='notify@digital.cabinet-office.gov.uk',
message=email_code,
subject='Verification code',
token=admin_api_client.auth_token)
return email_code
def send_change_password_email(email):
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,
subject='Reset password for GOV.UK Notify',
token=admin_api_client.auth_token)
def generate_token(email):
ser = URLSafeTimedSerializer(current_app.config['SECRET_KEY'])
return ser.dumps(email, current_app.config.get('DANGEROUS_SALT'))
def check_token(token):
ser = URLSafeTimedSerializer(current_app.config['SECRET_KEY'])
try:
email = ser.loads(token, max_age=current_app.config['TOKEN_MAX_AGE_SECONDS'],
salt=current_app.config.get('DANGEROUS_SALT'))
return email
except SignatureExpired as e:
current_app.logger.info('token expired %s' % e)