Merge pull request #2794 from alphagov/edit_user_email

Allow users with "manage_service" permission to edit team members' email addresses
This commit is contained in:
Pea (Malgorzata Tyczynska)
2019-02-25 10:18:34 +00:00
committed by GitHub
7 changed files with 253 additions and 5 deletions

View File

@@ -1,4 +1,12 @@
from flask import abort, flash, redirect, render_template, request, url_for
from flask import (
abort,
flash,
redirect,
render_template,
request,
session,
url_for,
)
from flask_login import current_user, login_required
from notifications_python_client.errors import HTTPError
@@ -9,7 +17,12 @@ from app import (
user_api_client,
)
from app.main import main
from app.main.forms import InviteUserForm, PermissionsForm, SearchUsersForm
from app.main.forms import (
ChangeEmailForm,
InviteUserForm,
PermissionsForm,
SearchUsersForm,
)
from app.models.user import permissions
from app.utils import user_has_permissions
@@ -122,6 +135,69 @@ def remove_user_from_service(service_id, user_id):
)
@main.route("/services/<service_id>/users/<user_id>/edit-email", methods=['GET', 'POST'])
@login_required
@user_has_permissions('manage_service')
def edit_user_email(service_id, user_id):
user = user_api_client.get_user(user_id)
user_email = user.email_address
def _is_email_already_in_use(email):
return user_api_client.is_email_already_in_use(email)
form = ChangeEmailForm(_is_email_already_in_use, email_address=user_email)
if form.validate_on_submit():
session['team_member_email_change'] = form.email_address.data
return redirect(url_for('.confirm_edit_user_email', user_id=user.id, service_id=service_id))
return render_template(
'views/manage-users/edit-user-email.html',
user=user,
form=form,
service_id=service_id
)
@main.route("/services/<service_id>/users/<user_id>/edit-email/confirm", methods=['GET', 'POST'])
@login_required
@user_has_permissions('manage_service')
def confirm_edit_user_email(service_id, user_id):
user = user_api_client.get_user(user_id)
if 'team_member_email_change' in session:
new_email = session['team_member_email_change']
else:
return redirect(url_for(
'.edit_user_email',
service_id=service_id,
user_id=user_id
))
if request.method == 'POST':
try:
user_api_client.update_user_attribute(user_id, email_address=new_email)
except HTTPError as e:
if e.status_code == 403:
flash("You don't have permission to edit users emails for this service", 'info')
return redirect(url_for(
'.manage_users',
service_id=service_id))
else:
abort(500, e)
finally:
session.pop("team_member_email_change", None)
return redirect(url_for(
'.manage_users',
service_id=service_id
))
return render_template(
'views/manage-users/confirm-edit-user-email.html',
user=user,
service_id=service_id,
new_email=new_email
)
@main.route("/services/<service_id>/cancel-invited-user/<invited_user_id>", methods=['GET'])
@user_has_permissions('manage_service')
def cancel_invited_user(service_id, invited_user_id):

View File

@@ -135,6 +135,7 @@ class HeaderNavigation(Navigation):
'choose_template',
'choose_template_to_copy',
'confirm_edit_organisation_name',
'confirm_edit_user_email',
'confirm_redact_template',
'conversation',
'conversation_reply',
@@ -157,6 +158,7 @@ class HeaderNavigation(Navigation):
'edit_service_template',
'edit_template_postage',
'edit_user_org_permissions',
'edit_user_email',
'edit_user_permissions',
'email_not_received',
'email_template',
@@ -324,6 +326,8 @@ class MainNavigation(Navigation):
'view_template_versions',
},
'team-members': {
'confirm_edit_user_email',
'edit_user_email',
'edit_user_permissions',
'invite_user',
'manage_users',
@@ -579,6 +583,7 @@ class CaseworkNavigation(Navigation):
'choose_template_to_copy',
'clear_cache',
'confirm_edit_organisation_name',
'confirm_edit_user_email',
'confirm_redact_template',
'conversation',
'conversation_reply',
@@ -603,6 +608,7 @@ class CaseworkNavigation(Navigation):
'edit_provider',
'edit_service_template',
'edit_template_postage',
'edit_user_email',
'edit_user_org_permissions',
'edit_user_permissions',
'email_branding',
@@ -816,6 +822,7 @@ class OrgNavigation(Navigation):
'choose_template',
'choose_template_to_copy',
'clear_cache',
'confirm_edit_user_email',
'confirm_redact_template',
'conversation',
'conversation_reply',
@@ -839,6 +846,7 @@ class OrgNavigation(Navigation):
'edit_provider',
'edit_service_template',
'edit_template_postage',
'edit_user_email',
'edit_user_permissions',
'email_branding',
'email_not_received',

View File

@@ -14,7 +14,7 @@
</h1>
<p>
{{ user.email_address }}
{{ user.email_address }}&emsp;<a href="{{ url_for('.edit_user_email', service_id=current_service.id, user_id=user.id)}}">Change</a>
</p>
<div class="grid-row">

View File

@@ -63,7 +63,7 @@
{% if user.status == 'pending' %}
<a href="{{ url_for('.cancel_invited_user', service_id=current_service.id, invited_user_id=user.id)}}">Cancel invitation</a>
{% elif user.state == 'active' and current_user.id != user.id %}
<a href="{{ url_for('.edit_user_permissions', service_id=current_service.id, user_id=user.id)}}">Edit permissions</a>
<a href="{{ url_for('.edit_user_permissions', service_id=current_service.id, user_id=user.id)}}">Edit team member</a>
{% endif %}
</li>
{% endif %}

View File

@@ -0,0 +1,30 @@
{% extends "withnav_template.html" %}
{% from "components/page-footer.html" import page_footer %}
{% from "components/form.html" import form_wrapper %}
{% block per_page_title %}
Confirm change of email address
{% endblock %}
{% block maincolumn_content %}
<h1 class="heading-large">Confirm change of email address</h1>
<div class="grid-row">
<div class="column-whole">
{% call form_wrapper() %}
<p>New email address:</p>
<div class="panel panel-border-wide bottom-gutter">
<p>{{ new_email }}</p>
</div>
<p>We will send {{ user.name }} an email to tell them about the change.</p>
{{ page_footer(
'Confirm',
destructive=destructive,
back_link=url_for('.edit_user_email', service_id=service_id, user_id=user.id)
) }}
{% endcall %}
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,27 @@
{% extends "withnav_template.html" %}
{% from "components/textbox.html" import textbox %}
{% from "components/page-footer.html" import page_footer %}
{% from "components/form.html" import form_wrapper %}
{% block per_page_title %}
Change team members email address
{% endblock %}
{% block maincolumn_content %}
<h1 class="heading-large">Change team members email address</h1>
<p id="user_name">This will change the email address for {{ user.name }}.</p>
<div class="grid-row">
<div class="column-three-quarters">
{% call form_wrapper() %}
{{ textbox(form.email_address) }}
{{ page_footer(
'Save',
back_link=url_for('.edit_user_permissions', service_id=service_id, user_id=user.id),
back_link_text="Back"
) }}
{% endcall %}
</div>
</div>
{% endblock %}

View File

@@ -39,7 +39,7 @@ from tests.conftest import service_one as create_sample_service
'Cant Add and edit templates '
'Cant Manage settings, team and usage '
'Cant Manage API integration '
'Edit permissions'
'Edit team member'
)
),
(
@@ -769,3 +769,110 @@ def test_can_invite_user_as_platform_admin(
response = logged_in_client.get(url_for('main.manage_users', service_id=service_one['id']))
resp_text = response.get_data(as_text=True)
assert url_for('.invite_user', service_id=service_one['id']) in resp_text
def test_edit_user_email_page(
client_request,
active_user_with_permissions,
service_one,
mocker
):
user = active_user_with_permissions
test_user = mocker.patch('app.user_api_client.get_user', return_value=user)
page = client_request.get(
'main.edit_user_email',
service_id=service_one['id'],
user_id=test_user.id
)
assert page.find('h1').text == "Change team members email address"
assert page.select('p[id=user_name]')[0].text == "This will change the email address for {}.".format(user.name)
assert page.select('input[type=email]')[0].attrs["value"] == user.email_address
assert page.select('button[type=submit]')[0].text == "Save"
def test_edit_user_email_redirects_to_confirmation(
logged_in_client,
active_user_with_permissions,
service_one,
mocker,
mock_get_user,
):
response = logged_in_client.post(
url_for(
'main.edit_user_email',
service_id=service_one['id'],
user_id=active_user_with_permissions.id))
assert response.status_code == 302
assert response.location == url_for(
'main.confirm_edit_user_email',
service_id=service_one['id'],
user_id=active_user_with_permissions.id,
_external=True
)
def test_confirm_edit_user_email_page(
logged_in_client,
active_user_with_permissions,
service_one,
mocker,
mock_get_user,
):
new_email = 'new_email@gov.uk'
with logged_in_client.session_transaction() as session:
session['team_member_email_change'] = new_email
response = logged_in_client.get(url_for(
'main.confirm_edit_user_email',
service_id=service_one['id'],
user_id=active_user_with_permissions.id
))
assert 'Confirm change of email address' in response.get_data(as_text=True)
for text in [
'New email address:',
new_email,
'We will send {} an email to tell them about the change.'.format(active_user_with_permissions.name)
]:
assert text in response.get_data(as_text=True)
assert 'Confirm' in response.get_data(as_text=True)
assert response.status_code == 200
def test_confirm_edit_user_email_page_redirects_if_session_empty(
logged_in_client,
active_user_with_permissions,
service_one,
mocker,
mock_get_user,
):
response = logged_in_client.get(url_for(
'main.confirm_edit_user_email',
service_id=service_one['id'],
user_id=active_user_with_permissions.id
))
assert response.status_code == 302
assert 'Confirm change of email address' not in response.get_data(as_text=True)
def test_confirm_edit_user_email_changes_user_email(
logged_in_client,
active_user_with_permissions,
service_one,
mocker,
mock_get_user,
mock_update_user_attribute
):
new_email = 'new_email@gov.uk'
with logged_in_client.session_transaction() as session:
session['team_member_email_change'] = new_email
response = logged_in_client.post(
url_for(
'main.confirm_edit_user_email',
service_id=service_one['id'],
user_id=active_user_with_permissions.id))
assert response.status_code == 302
assert response.location == url_for(
'main.manage_users', service_id=service_one['id'], _external=True)
mock_update_user_attribute.assert_called_once_with(active_user_with_permissions.id, email_address=new_email)