From 208c3cbcf37e1227d2a406568ba442a3668bf7d9 Mon Sep 17 00:00:00 2001 From: Adam Shimali Date: Wed, 9 Mar 2016 13:00:52 +0000 Subject: [PATCH] Added validation to ensure user can't invite themselves. Refactored Invited user form into permissions and invite forms for use in invite and edit permissions. Added template for edit permissions. --- app/main/forms.py | 16 ++++++- app/main/views/manage_users.py | 12 +++--- .../views/edit-user-permissions.html | 43 +++++++++++++++++++ tests/app/main/views/test_manage_users.py | 36 ++++++++++++++++ 4 files changed, 100 insertions(+), 7 deletions(-) create mode 100644 app/templates/views/edit-user-permissions.html diff --git a/app/main/forms.py b/app/main/forms.py index dc2b18e33..7548c680c 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -98,9 +98,8 @@ class RegisterUserFromInviteForm(Form): email_address = HiddenField('email_address') -class InviteUserForm(Form): +class PermisisonsForm(Form): - email_address = email_address('Their email address') # TODO fix this Radio field so we are not having to test for yes or no rather # use operator equality. send_messages = RadioField("Send messages", choices=[('yes', 'yes'), ('no', 'no')]) @@ -108,6 +107,19 @@ class InviteUserForm(Form): manage_api_keys = RadioField("Manage API keys", choices=[('yes', 'yes'), ('no', 'no')]) +class InviteUserForm(PermisisonsForm): + + email_address = email_address('Their email address') + + def __init__(self, invalid_email_address, *args, **kwargs): + super(InviteUserForm, self).__init__(*args, **kwargs) + self.invalid_email_address = invalid_email_address.lower() + + def validate_email_address(self, field): + if field.data.lower() == self.invalid_email_address: + raise ValidationError("You can't send an invitation to yourself") + + class TwoFactorForm(Form): def __init__(self, validate_code_func, *args, **kwargs): ''' diff --git a/app/main/views/manage_users.py b/app/main/views/manage_users.py index a1f44ad71..5a0a7f5c9 100644 --- a/app/main/views/manage_users.py +++ b/app/main/views/manage_users.py @@ -15,7 +15,10 @@ from notifications_python_client.errors import HTTPError from app import user_api_client from app.main import main -from app.main.forms import InviteUserForm +from app.main.forms import ( + InviteUserForm, + PermisisonsForm +) from app.main.dao.services_dao import get_service_by_id from app import user_api_client from app import invite_api_client @@ -46,7 +49,7 @@ def invite_user(service_id): service = get_service_by_id(service_id) - form = InviteUserForm() + form = InviteUserForm(current_user.email_address) if form.validate_on_submit(): email_address = form.email_address.data permissions = _get_permissions(request.form) @@ -72,8 +75,7 @@ def edit_user_permissions(service_id, user_id): service = get_service_by_id(service_id) # Need to make the email address read only, or a disabled field? # Do it through the template or the form class? - form = InviteUserForm(**{ - 'email_address': user.email_address, + form = PermisisonsForm(**{ 'send_messages': 'yes' if user.has_permissions( ['send_texts', 'send_emails', 'send_letters']) else 'no', 'manage_service': 'yes' if user.has_permissions( @@ -94,7 +96,7 @@ def edit_user_permissions(service_id, user_id): return redirect(url_for('.manage_users', service_id=service_id)) return render_template( - 'views/invite-user.html', + 'views/edit-user-permissions.html', user=user, form=form, service_id=service_id diff --git a/app/templates/views/edit-user-permissions.html b/app/templates/views/edit-user-permissions.html new file mode 100644 index 000000000..291d7fa62 --- /dev/null +++ b/app/templates/views/edit-user-permissions.html @@ -0,0 +1,43 @@ +{% extends "withnav_template.html" %} +{% from "components/yes-no.html" import yes_no %} +{% from "components/textbox.html" import textbox %} +{% from "components/page-footer.html" import page_footer %} + +{% block page_title %} +Manage users – GOV.UK Notify +{% endblock %} + +{% block maincolumn_content %} + +

+ {{ user.name or user.email_localpart or "Add a new team member" }} +

+ +
+
+ +
+ + Permissions + + All team members can see message history + {{ yes_no(form.send_messages.name, form.send_messages.label, form.send_messages.data) }} + {{ yes_no(form.manage_service.name, form.manage_service.label, form.manage_service.data) }} + {{ yes_no(form.manage_api_keys.name, form.manage_api_keys.label, form.manage_api_keys.data) }} +
+ + {% if user %} + {{ page_footer( + 'Save', + delete_link=url_for('.delete_user', service_id=service_id, user_id=user_id), + delete_link_text='Delete this account', + back_link=url_for('.manage_users', service_id=service_id), + back_link_text='Cancel' + ) }} + {% else %} + {{ page_footer('Send invitation email') }} + {% endif %} + +
+
+{% endblock %} diff --git a/tests/app/main/views/test_manage_users.py b/tests/app/main/views/test_manage_users.py index e45392a06..a335ea8be 100644 --- a/tests/app/main/views/test_manage_users.py +++ b/tests/app/main/views/test_manage_users.py @@ -244,3 +244,39 @@ def test_manage_users_does_not_show_accepted_invite(app_, tables = page.find_all('table') assert len(tables) == 1 assert not page.find(text='invited_user@test.gov.uk') + + +def test_user_cant_invite_themselves( + app_, + service_one, + api_user_active, + mock_login, + mock_get_user, + mock_get_service, + mock_get_users_by_service, + mock_create_invite, + mock_get_invites_for_service, + mock_has_permissions +): + from_user = api_user_active.id + service_id = service_one['id'] + email_address = api_user_active.email_address + permissions = 'send_messages,manage_service,manage_api_keys' + + with app_.test_request_context(): + with app_.test_client() as client: + client.login(api_user_active) + response = client.post( + url_for('main.invite_user', service_id=service_id), + data={'email_address': email_address, + 'send_messages': 'yes', + 'manage_service': 'yes', + 'manage_api_keys': 'yes'}, + follow_redirects=True + ) + + assert response.status_code == 200 + page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') + assert page.h1.string.strip() == 'Add a new team member' + form_error = page.find('span', class_='error-message').string.strip() + assert form_error == "You can't send an invitation to yourself"