From 69da9f8f327bbd0ffd2f4e703532b673b2a567b4 Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Fri, 4 Dec 2015 16:21:01 +0000 Subject: [PATCH 1/8] 109526520: render verify template with VerifyForm --- app/main/__init__.py | 2 +- app/main/forms.py | 7 ++++++- app/main/views/index.py | 5 ----- app/main/views/verify.py | 19 +++++++++++++++++++ tests/app/main/views/test_verify.py | 7 +++++++ 5 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 app/main/views/verify.py create mode 100644 tests/app/main/views/test_verify.py diff --git a/app/main/__init__.py b/app/main/__init__.py index 1305744ce..506599396 100644 --- a/app/main/__init__.py +++ b/app/main/__init__.py @@ -3,4 +3,4 @@ from flask import Blueprint main = Blueprint('main', __name__) -from app.main.views import index, sign_in, register +from app.main.views import index, sign_in, register, verify diff --git a/app/main/forms.py b/app/main/forms.py index ea5978fa3..874126341 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -1,5 +1,5 @@ from flask_wtf import Form -from wtforms import StringField, PasswordField +from wtforms import StringField, PasswordField, IntegerField from wtforms.validators import DataRequired, Email, Length, Regexp from app.main.validators import Blacklist @@ -36,3 +36,8 @@ class RegisterUserForm(Form): 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')]) + + +class VerifyForm(Form): + sms_code = IntegerField(DataRequired(message='SMS code can not be empty')) + email_code = IntegerField(DataRequired(message='Email code can not be empty')) diff --git a/app/main/views/index.py b/app/main/views/index.py index f664ee835..6f46ae671 100644 --- a/app/main/views/index.py +++ b/app/main/views/index.py @@ -19,11 +19,6 @@ def registerfrominvite(): return render_template('register-from-invite.html') -@main.route("/verify") -def verify(): - return render_template('verify.html') - - @main.route("/verify-mobile") def verifymobile(): return render_template('verify-mobile.html') diff --git a/app/main/views/verify.py b/app/main/views/verify.py new file mode 100644 index 000000000..ed4ef3bfb --- /dev/null +++ b/app/main/views/verify.py @@ -0,0 +1,19 @@ +from app.main import main +from flask import render_template, redirect, jsonify + +from app.main.forms import VerifyForm + + +@main.route('/verify', methods=['GET']) +def render_verify(): + return render_template('verify.html', form=VerifyForm()) + + +@main.route('/verify', methods=['POST']) +def process_verify(): + form = VerifyForm() + + if form.validate_on_submit(): + return redirect('/add-service') + else: + return jsonify(form.errors), 400 diff --git a/tests/app/main/views/test_verify.py b/tests/app/main/views/test_verify.py new file mode 100644 index 000000000..c3b994ad4 --- /dev/null +++ b/tests/app/main/views/test_verify.py @@ -0,0 +1,7 @@ + + +def test_should_return_verify_template(notifications_admin, notifications_admin_db): + response = notifications_admin.test_client().get('/verify') + + assert response.status_code == 200 + assert 'Activate your account' in response.get_data(as_text=True) From 6d47c011170db8092f7242dea8804404f823c02d Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Fri, 4 Dec 2015 17:10:06 +0000 Subject: [PATCH 2/8] 109526520: Implememt verify post method. --- app/main/views/verify.py | 14 ++++++++++++-- tests/app/main/views/test_verify.py | 25 +++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/app/main/views/verify.py b/app/main/views/verify.py index ed4ef3bfb..1abfda53e 100644 --- a/app/main/views/verify.py +++ b/app/main/views/verify.py @@ -1,6 +1,7 @@ from app.main import main -from flask import render_template, redirect, jsonify +from flask import render_template, redirect, jsonify, session +from app.main.encryption import checkpw from app.main.forms import VerifyForm @@ -14,6 +15,15 @@ def process_verify(): form = VerifyForm() if form.validate_on_submit(): - return redirect('/add-service') + valid_sms = checkpw(form.sms_code.data, session['sms_code']) + valid_email = checkpw(form.email_code.data, session['email_code']) + if valid_sms == False: + return jsonify(sms_code='invalid'), 400 + if valid_email == False: + return jsonify(email_code='invalid'), 400 else: return jsonify(form.errors), 400 + + return redirect('/add-service') + + diff --git a/tests/app/main/views/test_verify.py b/tests/app/main/views/test_verify.py index c3b994ad4..2e2119668 100644 --- a/tests/app/main/views/test_verify.py +++ b/tests/app/main/views/test_verify.py @@ -1,3 +1,4 @@ +from app.main.encryption import hashpw def test_should_return_verify_template(notifications_admin, notifications_admin_db): @@ -5,3 +6,27 @@ def test_should_return_verify_template(notifications_admin, notifications_admin_ assert response.status_code == 200 assert 'Activate your account' in response.get_data(as_text=True) + + +def test_should_redirect_to_add_service_when_code_are_correct(notifications_admin, notifications_admin_db): + with notifications_admin.test_client() as client: + with client.session_transaction() as session: + session['sms_code'] = hashpw('12345') + session['email_code'] = hashpw('23456') + response = client.post('/verify', + data={'sms_code': '12345', + 'email_code': '23456'}) + assert response.status_code == 302 + assert response.location == 'http://localhost/add-service' + + +def test_should_return_400_when_sms_code_is_wrong(notifications_admin, notifications_admin_db): + with notifications_admin.test_client() as client: + with client.session_transaction() as session: + session['sms_code'] = hashpw('12345') + session['email_code'] = hashpw('23456') + response = client.post('/verify', + data={'sms_code': '98765', + 'email_code': '23456'}) + assert response.status_code == 400 + assert 'sms_code' in response.get_data(as_text=True) From 56db1ad400cfd7ec551a72cc5c6546e48f548c9f Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Mon, 7 Dec 2015 09:08:49 +0000 Subject: [PATCH 3/8] 109526520: fix code style --- app/main/views/verify.py | 6 ++---- tests/app/main/views/test_verify.py | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/app/main/views/verify.py b/app/main/views/verify.py index 1abfda53e..8317fa55c 100644 --- a/app/main/views/verify.py +++ b/app/main/views/verify.py @@ -17,13 +17,11 @@ def process_verify(): if form.validate_on_submit(): valid_sms = checkpw(form.sms_code.data, session['sms_code']) valid_email = checkpw(form.email_code.data, session['email_code']) - if valid_sms == False: + if valid_sms is False: return jsonify(sms_code='invalid'), 400 - if valid_email == False: + if valid_email is False: return jsonify(email_code='invalid'), 400 else: return jsonify(form.errors), 400 return redirect('/add-service') - - diff --git a/tests/app/main/views/test_verify.py b/tests/app/main/views/test_verify.py index 2e2119668..cd943c6ea 100644 --- a/tests/app/main/views/test_verify.py +++ b/tests/app/main/views/test_verify.py @@ -21,7 +21,7 @@ def test_should_redirect_to_add_service_when_code_are_correct(notifications_admi def test_should_return_400_when_sms_code_is_wrong(notifications_admin, notifications_admin_db): - with notifications_admin.test_client() as client: + with notifications_admin.test_client() as client: with client.session_transaction() as session: session['sms_code'] = hashpw('12345') session['email_code'] = hashpw('23456') From 16618e80f965efb130538377b81e3c8cfe5c62cd Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Mon, 7 Dec 2015 16:08:30 +0000 Subject: [PATCH 4/8] 109526520: Implement verify flow When a person registers with a valid mobile number and email address, a code will be sent to each. That person can enter the verify codes and continue to the add-service page. --- app/__init__.py | 2 +- app/main/dao/users_dao.py | 7 +++ app/main/forms.py | 6 ++- app/main/views/register.py | 1 + app/main/views/verify.py | 13 ++++-- app/templates/verify.html | 29 ++++++------ tests/app/main/dao/test_users_dao.py | 20 +++++++++ tests/app/main/views/test_verify.py | 66 +++++++++++++++++++++++++++- 8 files changed, 122 insertions(+), 22 deletions(-) diff --git a/app/__init__.py b/app/__init__.py index 333a108b3..7a5730483 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -34,7 +34,7 @@ def create_app(config_name): init_csrf(application) login_manager.init_app(application) - login_manager.login_view = 'main.sign_in.render_sign_in' + # login_manager.login_view = 'main.sign_in.render_sign_in' from app.main import main as main_blueprint application.register_blueprint(main_blueprint) diff --git a/app/main/dao/users_dao.py b/app/main/dao/users_dao.py index d4d3a0b42..83521985e 100644 --- a/app/main/dao/users_dao.py +++ b/app/main/dao/users_dao.py @@ -30,3 +30,10 @@ def increment_failed_login_count(id): user = User.query.filter_by(id=id).first() user.failed_login_count += 1 db.session.commit() + + +def activate_user(id): + user = get_user_by_id(id) + user.state = 'active' + db.session.add(user) + db.session.commit() diff --git a/app/main/forms.py b/app/main/forms.py index 874126341..92ec1b8c5 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -39,5 +39,7 @@ class RegisterUserForm(Form): class VerifyForm(Form): - sms_code = IntegerField(DataRequired(message='SMS code can not be empty')) - email_code = IntegerField(DataRequired(message='Email code can not be empty')) + sms_code = IntegerField("Text message confirmation code", + validators=[DataRequired(message='SMS code can not be empty')]) + email_code = IntegerField("Email confirmation code", + validators=[DataRequired(message='Email code can not be empty')]) diff --git a/app/main/views/register.py b/app/main/views/register.py index 48c9d68fa..953d514b5 100644 --- a/app/main/views/register.py +++ b/app/main/views/register.py @@ -36,6 +36,7 @@ def process_register(): session['email_code'] = hashpw(email_code) session['expiry_date'] = str(datetime.now() + timedelta(hours=1)) users_dao.insert_user(user) + session['user_id'] = user.id except AdminApiClientException as e: return jsonify(admin_api_client_error=e.value) except SQLAlchemyError: diff --git a/app/main/views/verify.py b/app/main/views/verify.py index 8317fa55c..4e627d0a7 100644 --- a/app/main/views/verify.py +++ b/app/main/views/verify.py @@ -1,6 +1,8 @@ -from app.main import main from flask import render_template, redirect, jsonify, session +from flask_login import login_user +from app.main import main +from app.main.dao import users_dao from app.main.encryption import checkpw from app.main.forms import VerifyForm @@ -13,15 +15,18 @@ def render_verify(): @main.route('/verify', methods=['POST']) def process_verify(): form = VerifyForm() - if form.validate_on_submit(): valid_sms = checkpw(form.sms_code.data, session['sms_code']) valid_email = checkpw(form.email_code.data, session['email_code']) if valid_sms is False: - return jsonify(sms_code='invalid'), 400 + return jsonify(sms_code='does not match'), 400 if valid_email is False: - return jsonify(email_code='invalid'), 400 + return jsonify(email_code='does not match'), 400 else: return jsonify(form.errors), 400 + user = users_dao.get_user_by_id(session['user_id']) + users_dao.activate_user(user.id) + login_user(user) + return redirect('/add-service') diff --git a/app/templates/verify.html b/app/templates/verify.html index a6ab5b8f5..0248e2348 100644 --- a/app/templates/verify.html +++ b/app/templates/verify.html @@ -12,20 +12,23 @@ GOV.UK Notify | Confirm email address and mobile number

We've sent you confirmation codes by email and text message. You need to enter both codes here.

-

-

-

-

+
+ {{ form.hidden_tag() }} +

+ + {{ form.email_code(class="form-control-1-4", autocomplete="off") }}
+ I haven't received an email +

+

+ + {{ form.sms_code(class="form-control-1-4", autocomplete="off") }}
+ I haven't received a text +

-

- Continue -

+

+ +

+
diff --git a/tests/app/main/dao/test_users_dao.py b/tests/app/main/dao/test_users_dao.py index 9fde6bd9b..f6d8d5f87 100644 --- a/tests/app/main/dao/test_users_dao.py +++ b/tests/app/main/dao/test_users_dao.py @@ -119,3 +119,23 @@ def test_user_is_active_is_false_if_state_is_inactive(notifications_admin, notif saved_user = users_dao.get_user_by_id(user.id) assert saved_user.is_active() is False + + +def test_should_update_user_to_active(notifications_admin, notifications_admin_db): + user = User(name='Make user active', + password='somepassword', + email_address='activate@user.gov.uk', + mobile_number='+441234123412', + created_at=datetime.now(), + role_id=1, + state='pending') + users_dao.insert_user(user) + users_dao.activate_user(user.id) + updated_user = users_dao.get_user_by_id(user.id) + assert updated_user.state == 'active' + + +def test_should_throws_error_when_id_does_not_exist(notifications_admin, notifications_admin_db): + with pytest.raises(AttributeError) as error: + users_dao.activate_user(123) + assert '''object has no attribute 'state''''' in str(error.value) diff --git a/tests/app/main/views/test_verify.py b/tests/app/main/views/test_verify.py index cd943c6ea..a595cbd5d 100644 --- a/tests/app/main/views/test_verify.py +++ b/tests/app/main/views/test_verify.py @@ -1,9 +1,12 @@ +from datetime import datetime + +from app.main.dao import users_dao from app.main.encryption import hashpw +from app.models import User def test_should_return_verify_template(notifications_admin, notifications_admin_db): response = notifications_admin.test_client().get('/verify') - assert response.status_code == 200 assert 'Activate your account' in response.get_data(as_text=True) @@ -11,6 +14,8 @@ def test_should_return_verify_template(notifications_admin, notifications_admin_ def test_should_redirect_to_add_service_when_code_are_correct(notifications_admin, notifications_admin_db): with notifications_admin.test_client() as client: with client.session_transaction() as session: + user = _create_test_user() + session['user_id'] = user.id session['sms_code'] = hashpw('12345') session['email_code'] = hashpw('23456') response = client.post('/verify', @@ -20,13 +25,70 @@ def test_should_redirect_to_add_service_when_code_are_correct(notifications_admi assert response.location == 'http://localhost/add-service' +def test_should_activate_user_after_verify(notifications_admin, notifications_admin_db): + with notifications_admin.test_client() as client: + with client.session_transaction() as session: + user = _create_test_user() + session['user_id'] = user.id + session['sms_code'] = hashpw('12345') + session['email_code'] = hashpw('23456') + client.post('/verify', + data={'sms_code': '12345', + 'email_code': '23456'}) + + after_verify = users_dao.get_user_by_id(user.id) + assert after_verify.state == 'active' + + def test_should_return_400_when_sms_code_is_wrong(notifications_admin, notifications_admin_db): with notifications_admin.test_client() as client: with client.session_transaction() as session: + user = _create_test_user() + session['user_id'] = user.id session['sms_code'] = hashpw('12345') session['email_code'] = hashpw('23456') response = client.post('/verify', data={'sms_code': '98765', 'email_code': '23456'}) assert response.status_code == 400 - assert 'sms_code' in response.get_data(as_text=True) + assert '"sms_code": "does not match"' in response.get_data(as_text=True) + + +def test_should_return_400_when_email_code_is_wrong(notifications_admin, notifications_admin_db): + with notifications_admin.test_client() as client: + with client.session_transaction() as session: + user = _create_test_user() + session['user_id'] = user.id + session['sms_code'] = hashpw('12345') + session['email_code'] = hashpw('98456') + response = client.post('/verify', + data={'sms_code': '12345', + 'email_code': '23456'}) + assert response.status_code == 400 + assert '"email_code": "does not match"' in response.get_data(as_text=True) + + +def test_should_return_400_when_sms_code_is_missing(notifications_admin, notifications_admin_db): + response = notifications_admin.test_client().post('/verify', + data={'email_code': '23456'}) + assert response.status_code == 400 + assert 'SMS code can not be empty' in response.get_data(as_text=True) + + +def test_should_return_400_when_email_code_is_missing(notifications_admin, notifications_admin_db): + response = notifications_admin.test_client().post('/verify', + data={'sms_code': '23456'}) + assert response.status_code == 400 + assert 'Email code can not be empty' in response.get_data(as_text=True) + + +def _create_test_user(): + user = User(name='Test User', + password='somepassword', + email_address='test@user.gov.uk', + mobile_number='+441234123412', + created_at=datetime.now(), + role_id=1, + state='pending') + users_dao.insert_user(user) + return user From 4486a859f8394d97ce7b3cfe16650c7460f2e254 Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Mon, 7 Dec 2015 16:28:27 +0000 Subject: [PATCH 5/8] 109638656: fix the login_manager.login_view --- app/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/__init__.py b/app/__init__.py index 7a5730483..30795420a 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -34,7 +34,7 @@ def create_app(config_name): init_csrf(application) login_manager.init_app(application) - # login_manager.login_view = 'main.sign_in.render_sign_in' + login_manager.login_view = 'main.render_sign_in' from app.main import main as main_blueprint application.register_blueprint(main_blueprint) From bef2258803383cf42ea70bd3d8d8bcbbcfd53df4 Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Tue, 8 Dec 2015 11:56:49 +0000 Subject: [PATCH 6/8] 109526520: Add custom validators for the VerifyForm If the email_code or sms_code entered does not pass check password, then add errors to the form. --- app/main/forms.py | 18 +++++++++++++++ app/main/views/verify.py | 18 +++++---------- tests/app/main/views/test_verify.py | 35 ++++++++++++++++++++--------- 3 files changed, 48 insertions(+), 23 deletions(-) diff --git a/app/main/forms.py b/app/main/forms.py index 92ec1b8c5..75118e611 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -1,7 +1,9 @@ +from flask import session from flask_wtf import Form from wtforms import StringField, PasswordField, IntegerField from wtforms.validators import DataRequired, Email, Length, Regexp +from app.main.encryption import checkpw from app.main.validators import Blacklist @@ -43,3 +45,19 @@ class VerifyForm(Form): validators=[DataRequired(message='SMS code can not be empty')]) email_code = IntegerField("Email confirmation code", validators=[DataRequired(message='Email code can not be empty')]) + + def validate_email_code(self, a): + if self.email_code.data is not None: + if checkpw(str(self.email_code.data), session['email_code']) is False: + self.email_code.errors.append('Code does not match') + return False + else: + return True + + def validate_sms_code(self, a): + if self.sms_code.data is not None: + if checkpw(str(self.sms_code.data), session['sms_code']) is False: + self.sms_code.errors.append('Code does not match') + return False + else: + return True diff --git a/app/main/views/verify.py b/app/main/views/verify.py index 4e627d0a7..3e3c139af 100644 --- a/app/main/views/verify.py +++ b/app/main/views/verify.py @@ -3,7 +3,6 @@ from flask_login import login_user from app.main import main from app.main.dao import users_dao -from app.main.encryption import checkpw from app.main.forms import VerifyForm @@ -16,17 +15,10 @@ def render_verify(): def process_verify(): form = VerifyForm() if form.validate_on_submit(): - valid_sms = checkpw(form.sms_code.data, session['sms_code']) - valid_email = checkpw(form.email_code.data, session['email_code']) - if valid_sms is False: - return jsonify(sms_code='does not match'), 400 - if valid_email is False: - return jsonify(email_code='does not match'), 400 + user = users_dao.get_user_by_id(session['user_id']) + users_dao.activate_user(user.id) + login_user(user) + return redirect('/add-service') else: + print(form.errors) return jsonify(form.errors), 400 - - user = users_dao.get_user_by_id(session['user_id']) - users_dao.activate_user(user.id) - login_user(user) - - return redirect('/add-service') diff --git a/tests/app/main/views/test_verify.py b/tests/app/main/views/test_verify.py index a595cbd5d..bc1106a0d 100644 --- a/tests/app/main/views/test_verify.py +++ b/tests/app/main/views/test_verify.py @@ -51,7 +51,8 @@ def test_should_return_400_when_sms_code_is_wrong(notifications_admin, notificat data={'sms_code': '98765', 'email_code': '23456'}) assert response.status_code == 400 - assert '"sms_code": "does not match"' in response.get_data(as_text=True) + assert 'sms_code' in response.get_data(as_text=True) + assert 'Code does not match' in response.get_data(as_text=True) def test_should_return_400_when_email_code_is_wrong(notifications_admin, notifications_admin_db): @@ -65,21 +66,35 @@ def test_should_return_400_when_email_code_is_wrong(notifications_admin, notific data={'sms_code': '12345', 'email_code': '23456'}) assert response.status_code == 400 - assert '"email_code": "does not match"' in response.get_data(as_text=True) + print(response.get_data(as_text=True)) + assert 'email_code' in response.get_data(as_text=True) + assert 'Code does not match' in response.get_data(as_text=True) def test_should_return_400_when_sms_code_is_missing(notifications_admin, notifications_admin_db): - response = notifications_admin.test_client().post('/verify', - data={'email_code': '23456'}) - assert response.status_code == 400 - assert 'SMS code can not be empty' in response.get_data(as_text=True) + with notifications_admin.test_client() as client: + with client.session_transaction() as session: + user = _create_test_user() + session['user_id'] = user.id + session['sms_code'] = hashpw('12345') + session['email_code'] = hashpw('98456') + response = client.post('/verify', + data={'email_code': '23456'}) + assert response.status_code == 400 + assert 'SMS code can not be empty' in response.get_data(as_text=True) def test_should_return_400_when_email_code_is_missing(notifications_admin, notifications_admin_db): - response = notifications_admin.test_client().post('/verify', - data={'sms_code': '23456'}) - assert response.status_code == 400 - assert 'Email code can not be empty' in response.get_data(as_text=True) + with notifications_admin.test_client() as client: + with client.session_transaction() as session: + user = _create_test_user() + session['user_id'] = user.id + session['sms_code'] = hashpw('23456') + session['email_code'] = hashpw('23456') + response = client.post('/verify', + data={'sms_code': '23456'}) + assert response.status_code == 400 + assert 'Email code can not be empty' in response.get_data(as_text=True) def _create_test_user(): From 9923c14e73c6eb7dc52735649a5819bb9122678c Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Tue, 8 Dec 2015 15:30:55 +0000 Subject: [PATCH 7/8] 109526520: Changed the code form fields to StringField When the codes were IntegerFields and the code started with zero, the zero was trimmed, resulting in a failed match. --- app/main/forms.py | 10 ++++++---- app/main/views/sign_in.py | 5 +---- tests/app/main/views/test_verify.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/app/main/forms.py b/app/main/forms.py index 75118e611..a228a8f61 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -41,10 +41,12 @@ class RegisterUserForm(Form): class VerifyForm(Form): - sms_code = IntegerField("Text message confirmation code", - validators=[DataRequired(message='SMS code can not be empty')]) - email_code = IntegerField("Email confirmation code", - validators=[DataRequired(message='Email code can not be empty')]) + sms_code = StringField("Text message confirmation code", + validators=[DataRequired(message='SMS code can not be empty'), + Length(min=5, max=5, message='Code must be 5 digits')]) + email_code = StringField("Email confirmation code", + validators=[DataRequired(message='Email code can not be empty'), + Length(min=5, max=5, message='Code must be 5 digits')]) def validate_email_code(self, a): if self.email_code.data is not None: diff --git a/app/main/views/sign_in.py b/app/main/views/sign_in.py index 5fb1abc5b..aaa6d827b 100644 --- a/app/main/views/sign_in.py +++ b/app/main/views/sign_in.py @@ -1,13 +1,10 @@ -from datetime import datetime - from flask import render_template, redirect, jsonify from flask_login import login_user from app.main import main -from app.main.forms import LoginForm from app.main.dao import users_dao -from app.models import User from app.main.encryption import checkpw +from app.main.forms import LoginForm @main.route("/sign-in", methods=(['GET'])) diff --git a/tests/app/main/views/test_verify.py b/tests/app/main/views/test_verify.py index bc1106a0d..7d9ea4f0e 100644 --- a/tests/app/main/views/test_verify.py +++ b/tests/app/main/views/test_verify.py @@ -97,6 +97,34 @@ def test_should_return_400_when_email_code_is_missing(notifications_admin, notif assert 'Email code can not be empty' in response.get_data(as_text=True) +def test_should_return_400_when_email_code_has_letter(notifications_admin, notifications_admin_db): + with notifications_admin.test_client() as client: + with client.session_transaction() as session: + user = _create_test_user() + session['user_id'] = user.id + session['sms_code'] = hashpw('23456') + session['email_code'] = hashpw('23456') + response = client.post('/verify', + data={'sms_code': '23456', + 'email_code': 'abcde'}) + assert response.status_code == 400 + assert 'Code does not match' in response.get_data(as_text=True) + + +def test_should_return_302_when_email_code_starts_with_zero(notifications_admin, notifications_admin_db): + with notifications_admin.test_client() as client: + with client.session_transaction() as session: + user = _create_test_user() + session['user_id'] = user.id + session['sms_code'] = hashpw('23456') + session['email_code'] = hashpw('09765') + response = client.post('/verify', + data={'sms_code': '23456', + 'email_code': '09765'}) + assert response.status_code == 302 + assert response.location == 'http://localhost/add-service' + + def _create_test_user(): user = User(name='Test User', password='somepassword', From ae19161b32ec95172e7940a63c9d010738772746 Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Tue, 8 Dec 2015 15:40:45 +0000 Subject: [PATCH 8/8] 109526520: Use Regex validator to test the code is 5 digits. --- app/main/forms.py | 5 +++-- tests/app/main/views/test_verify.py | 22 +++++++++++++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/app/main/forms.py b/app/main/forms.py index a228a8f61..4b8e400ba 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -20,6 +20,7 @@ class LoginForm(Form): gov_uk_email = "(^[^@^\\s]+@[^@^\\.^\\s]+(\\.[^@^\\.^\\s]*)*.gov.uk)" mobile_number = "^\\+44[\\d]{10}$" +verify_code = "[\\d]{5}$" class RegisterUserForm(Form): @@ -43,10 +44,10 @@ class RegisterUserForm(Form): class VerifyForm(Form): sms_code = StringField("Text message confirmation code", validators=[DataRequired(message='SMS code can not be empty'), - Length(min=5, max=5, message='Code must be 5 digits')]) + Regexp(regex=verify_code, message='Code must be 5 digits')]) email_code = StringField("Email confirmation code", validators=[DataRequired(message='Email code can not be empty'), - Length(min=5, max=5, message='Code must be 5 digits')]) + Regexp(regex=verify_code, message='Code must be 5 digits')]) def validate_email_code(self, a): if self.email_code.data is not None: diff --git a/tests/app/main/views/test_verify.py b/tests/app/main/views/test_verify.py index 7d9ea4f0e..17ebf35bf 100644 --- a/tests/app/main/views/test_verify.py +++ b/tests/app/main/views/test_verify.py @@ -107,8 +107,28 @@ def test_should_return_400_when_email_code_has_letter(notifications_admin, notif response = client.post('/verify', data={'sms_code': '23456', 'email_code': 'abcde'}) + data = response.get_data(as_text=True) assert response.status_code == 400 - assert 'Code does not match' in response.get_data(as_text=True) + assert 'email_code' in data + assert 'Code does not match' in data + assert 'Code must be 5 digits' in data + + +def test_should_return_400_when_sms_code_is_too_short(notifications_admin, notifications_admin_db): + with notifications_admin.test_client() as client: + with client.session_transaction() as session: + user = _create_test_user() + session['user_id'] = user.id + session['sms_code'] = hashpw('23456') + session['email_code'] = hashpw('23456') + response = client.post('/verify', + data={'sms_code': '2345', + 'email_code': '23456'}) + assert response.status_code == 400 + data = response.get_data(as_text=True) + assert 'sms_code' in data + assert 'Code must be 5 digits' in data + assert 'Code does not match' in data def test_should_return_302_when_email_code_starts_with_zero(notifications_admin, notifications_admin_db):