All tests passing and merged with master.

This commit is contained in:
Nicholas Staples
2016-01-27 16:30:33 +00:00
51 changed files with 763 additions and 892 deletions

View File

@@ -26,8 +26,11 @@ def get_service_by_id(id_):
return notifications_api_client.get_service(id_)
def get_services():
return notifications_api_client.get_services()
def get_services(user_id=None):
if user_id:
return notifications_api_client.get_services({'user_id': str(user_id)})
else:
return notifications_api_client.get_services()
def unrestrict_service(service_id):
@@ -55,8 +58,8 @@ def activate_service(service_id):
# TODO Fix when functionality is added to the api.
def find_service_by_service_name(service_name):
resp = notifications_api_client.get_services()
def find_service_by_service_name(service_name, user_id=None):
resp = notifications_api_client.get_services(user_id)
retval = None
for srv_json in resp['data']:
if srv_json['name'] == service_name:
@@ -69,8 +72,8 @@ def delete_service(id_):
return notifications_api_client.delete_service(id_)
def find_all_service_names():
resp = notifications_api_client.get_services()
def find_all_service_names(user_id=None):
resp = notifications_api_client.get_services(user_id)
return [x['name'] for x in resp['data']]
@@ -90,4 +93,4 @@ class ServicesBrowsableItem(BrowsableItem):
@property
def hint(self):
return "Some service hint here"
return None

View File

@@ -38,6 +38,7 @@ def update_user(user):
def increment_failed_login_count(id):
user = get_user_by_id(id)
user.failed_login_count += 1
return user_api_client.update_user(user)
def activate_user(user):
@@ -45,38 +46,19 @@ def activate_user(user):
return user_api_client.update_user(user)
def update_email_address(id, email_address):
user = get_user_by_id(id)
user.email_address = email_address
# TODO update user
def is_email_unique(email_address):
if user_api_client.get_user_by_email(email_address):
return False
return True
def update_mobile_number(id, mobile_number):
user = get_user_by_id(id)
user.mobile_number = mobile_number
# TODO update user
def update_password(user, password):
user.password = hashpw(password)
user.password_changed_at = datetime.now()
user.state = 'active'
# TODO update user
def request_password_reset(email):
user = get_user_by_email(email)
user.state = 'request_password_reset'
# TODO update user
def send_verify_code(user_id, code_type):
def send_verify_code(user_id, code_type, to=None):
return user_api_client.send_verify_code(user_id, code_type)

View File

@@ -105,8 +105,8 @@ class LoginForm(Form):
class RegisterUserForm(Form):
def __init__(self, existing_email_addresses, *args, **kwargs):
self.existing_emails = existing_email_addresses
def __init__(self, unique_email_func, *args, **kwargs):
self.unique_email_func = unique_email_func
super(RegisterUserForm, self).__init__(*args, **kwargs)
name = StringField('Full name',
@@ -117,7 +117,7 @@ class RegisterUserForm(Form):
def validate_email_address(self, field):
# Validate email address is unique.
if self.existing_emails(field.data):
if not self.unique_email_func(field.data):
raise ValidationError('Email address already exists')

View File

@@ -1,12 +0,0 @@
templates = [
{
'type': 'sms',
'name': 'Confirmation with details Jan 2016',
'body': '((name)), weve received your ((thing)). Well contact you again within 1 week.'
},
{
'type': 'sms',
'name': 'Confirmation Jan 2016',
'body': 'Weve received your payment. Well contact you again within 1 week.'
}
]

View File

@@ -1,5 +1,5 @@
from flask import request, render_template, jsonify, redirect, session, url_for, abort
from flask_login import login_required
from flask import render_template, redirect, session, url_for
from flask_login import login_required, current_user
from app.main import main
from app.main.dao import services_dao, users_dao
from app.main.forms import AddServiceForm
@@ -9,7 +9,7 @@ from app.main.forms import AddServiceForm
@login_required
def add_service():
form = AddServiceForm(services_dao.find_all_service_names)
services = services_dao.get_services()
services = services_dao.get_services(current_user.id)
if len(services) > 0:
heading = 'Set up notifications for your service'
else:

View File

@@ -51,5 +51,5 @@ def revoke_api_key(service_id, key_id):
)
elif request.method == 'POST':
api_key_api_client.revoke_api_key(service_id=service_id, key_id=key_id)
flash('{} was revoked'.format(key_name))
flash('{} was revoked'.format(key_name), 'default')
return redirect(url_for('.api_keys', service_id=service_id))

View File

@@ -1,5 +1,5 @@
from flask import (render_template, redirect, url_for)
from flask_login import login_required
from flask_login import login_required, current_user
from app.main.dao import services_dao
from app.main import main
@@ -7,7 +7,7 @@ from app.main import main
@main.route("/services")
@login_required
def choose_service():
services = services_dao.get_services()
services = services_dao.get_services(current_user.id)
# If there is only one service redirect
# to the service dashboard.
if len(services['data']) == 1:

View File

@@ -1,6 +1,8 @@
from flask import (
render_template, redirect, session, url_for)
from flask_login import current_user
from app.main import main
from app.main.dao import users_dao
from app.main.forms import EmailNotReceivedForm, TextNotReceivedForm
@@ -12,8 +14,9 @@ def check_and_resend_email_code():
user = users_dao.get_user_by_email(session['user_details']['email'])
form = EmailNotReceivedForm(email_address=user.email_address)
if form.validate_on_submit():
users_dao.update_email_address(id=user.id, email_address=form.email_address.data)
users_dao.send_verify_code(user.id, 'email')
users_dao.send_verify_code(user.id, 'email', to=form.email_address.data)
user.email_address = form.email_address.data
users_dao.update_user(user)
return redirect(url_for('.verify'))
return render_template('views/email-not-received.html', form=form)
@@ -24,8 +27,9 @@ def check_and_resend_text_code():
user = users_dao.get_user_by_email(session['user_details']['email'])
form = TextNotReceivedForm(mobile_number=user.mobile_number)
if form.validate_on_submit():
users_dao.update_mobile_number(id=user.id, mobile_number=form.mobile_number.data)
users_dao.send_verify_code(user.id, 'sms')
users_dao.send_verify_code(user.id, 'sms', to=form.mobile_number.data)
user.mobile_number = form.mobile_number.data
users_dao.update_user(user)
return redirect(url_for('.verify'))
return render_template('views/text-not-received.html', form=form)

View File

@@ -1,10 +1,14 @@
from flask import render_template
from flask import render_template, url_for, redirect
from app.main import main
from flask_login import login_required
from flask.ext.login import current_user
@main.route('/')
def index():
if current_user and current_user.is_authenticated():
return redirect(url_for('main.choose_service'))
return render_template('views/signedout.html')

View File

@@ -21,8 +21,11 @@ def new_password(token):
form = NewPasswordForm()
if form.validate_on_submit():
users_dao.update_password(user, form.new_password.data)
users_dao.send_verify_code(user.id, 'sms')
session['user_details'] = {
'id': user.id,
'email': user.email_address,
'password': form.new_password.data}
return redirect(url_for('main.two_factor'))
else:
return render_template('views/new-password.html', token=token, form=form, user=user)

View File

@@ -8,6 +8,8 @@ from flask import (
url_for
)
from flask.ext.login import current_user
from client.errors import HTTPError
from app.main import main
@@ -19,7 +21,10 @@ from app import user_api_client
@main.route('/register', methods=['GET', 'POST'])
def register():
form = RegisterUserForm(users_dao.get_user_by_email)
if current_user and current_user.is_authenticated():
return redirect(url_for('main.choose_service'))
form = RegisterUserForm(users_dao.is_email_unique)
if form.validate_on_submit():
try:

View File

@@ -6,6 +6,8 @@ from flask import (
abort
)
from flask.ext.login import current_user
from app.main import main
from app.main.dao import users_dao
from app.main.forms import LoginForm
@@ -13,18 +15,31 @@ from app.main.forms import LoginForm
@main.route('/sign-in', methods=(['GET', 'POST']))
def sign_in():
if current_user and current_user.is_authenticated():
return redirect(url_for('main.choose_service'))
form = LoginForm()
if form.validate_on_submit():
user = users_dao.get_user_by_email(form.email_address.data)
user = _get_and_verify_user(form.email_address.data, form.password.data)
if user:
if not user.is_locked() and user.is_active() and users_dao.verify_password(user, form.password.data):
users_dao.send_verify_code(user.id, 'sms')
session['user_details'] = {"email": user.email_address, "id": user.id}
return redirect(url_for('.two_factor'))
else:
# TODO re wire this increment to api
users_dao.increment_failed_login_count(user.id)
# Vague error message for login
form.password.errors.append('Username or password is incorrect')
users_dao.send_verify_code(user.id, 'sms')
session['user_details'] = {"email": user.email_address, "id": user.id}
return redirect(url_for('.two_factor'))
else:
# Vague error message for login in case of user not known, locked, inactive or password not verified
form.password.errors.append('Username or password is incorrect')
return render_template('views/signin.html', form=form)
def _get_and_verify_user(email_address, password):
user = users_dao.get_user_by_email(email_address)
if not user:
return None
elif user.is_locked():
return None
elif not user.is_active():
return None
elif not users_dao.verify_password(user, password):
return None
else:
return user

View File

@@ -24,12 +24,7 @@ from app.main.uploader import (
s3upload,
s3download
)
from ._templates import templates
sms_templates = [
template for template in templates if template['type'] == 'sms'
]
from app.main.dao import templates_dao
@main.route("/services/<int:service_id>/sms/send", methods=['GET', 'POST'])
@@ -51,8 +46,16 @@ def send_sms(service_id):
flash(str(e))
return redirect(url_for('.send_sms', service_id=service_id))
try:
templates = templates_dao.get_service_templates(service_id)['data']
except HTTPError as e:
if e.status_code == 404:
abort(404)
else:
raise e
return render_template('views/send-sms.html',
message_templates=sms_templates,
templates=templates,
form=form,
service_id=service_id)
@@ -69,7 +72,9 @@ def check_sms(service_id, upload_id):
'views/check-sms.html',
upload_result=upload_result,
filename='someupload_file_name.csv',
message_template=sms_templates[0]['body'],
message_template='''
((name)), weve received your ((thing)). Well contact you again within 1 week.
''',
service_id=service_id
)
elif request.method == 'POST':

View File

@@ -20,8 +20,12 @@ def two_factor():
form = TwoFactorForm(_check_code)
if form.validate_on_submit():
del session['user_details']
user = users_dao.get_user_by_id(user_id)
# Check if coming from new password page
if 'password' in session['user_details']:
user.set_password(session['user_details']['password'])
users_dao.update_user(user)
del session['user_details']
login_user(user)
return redirect(url_for('.choose_service'))