mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-08-24 08:16:51 -04:00
Add page to archive user
Users can only be archived by Platform Admin from the user page (/users/<user_id>). This removes them from all services and orgs and updates their details.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
from flask import render_template, request
|
from flask import flash, redirect, render_template, request, url_for
|
||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
|
|
||||||
from app import user_api_client
|
from app import user_api_client
|
||||||
@@ -37,3 +37,15 @@ def user_information(user_id):
|
|||||||
user=user,
|
user=user,
|
||||||
services=services,
|
services=services,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@main.route("/users/<uuid:user_id>/archive", methods=['GET', 'POST'])
|
||||||
|
@login_required
|
||||||
|
@user_is_platform_admin
|
||||||
|
def archive_user(user_id):
|
||||||
|
if request.method == 'POST':
|
||||||
|
user_api_client.archive_user(user_id)
|
||||||
|
return redirect(url_for('.user_information', user_id=user_id))
|
||||||
|
else:
|
||||||
|
flash('There\'s no way to reverse this! Are you sure you want to archive this user?', 'delete')
|
||||||
|
return user_information(user_id)
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ class HeaderNavigation(Navigation):
|
|||||||
},
|
},
|
||||||
'platform-admin': {
|
'platform-admin': {
|
||||||
'add_organisation',
|
'add_organisation',
|
||||||
|
'archive_user',
|
||||||
'clear_cache',
|
'clear_cache',
|
||||||
'create_email_branding',
|
'create_email_branding',
|
||||||
'create_letter_branding',
|
'create_letter_branding',
|
||||||
@@ -427,6 +428,7 @@ class MainNavigation(Navigation):
|
|||||||
'add_service',
|
'add_service',
|
||||||
'agreement',
|
'agreement',
|
||||||
'archive_service',
|
'archive_service',
|
||||||
|
'archive_user',
|
||||||
'bat_phone',
|
'bat_phone',
|
||||||
'callbacks',
|
'callbacks',
|
||||||
'cancel_invited_org_user',
|
'cancel_invited_org_user',
|
||||||
@@ -619,6 +621,7 @@ class CaseworkNavigation(Navigation):
|
|||||||
'api_integration',
|
'api_integration',
|
||||||
'api_keys',
|
'api_keys',
|
||||||
'archive_service',
|
'archive_service',
|
||||||
|
'archive_user',
|
||||||
'bat_phone',
|
'bat_phone',
|
||||||
'branding_request',
|
'branding_request',
|
||||||
'callbacks',
|
'callbacks',
|
||||||
@@ -902,6 +905,7 @@ class OrgNavigation(Navigation):
|
|||||||
'api_integration',
|
'api_integration',
|
||||||
'api_keys',
|
'api_keys',
|
||||||
'archive_service',
|
'archive_service',
|
||||||
|
'archive_user',
|
||||||
'bat_phone',
|
'bat_phone',
|
||||||
'branding_request',
|
'branding_request',
|
||||||
'callbacks',
|
'callbacks',
|
||||||
|
|||||||
@@ -65,6 +65,10 @@ class UserApiClient(NotifyAdminAPIClient):
|
|||||||
user_data = self.post(url, data=data)
|
user_data = self.post(url, data=data)
|
||||||
return user_data['data']
|
return user_data['data']
|
||||||
|
|
||||||
|
@cache.delete('user-{user_id}')
|
||||||
|
def archive_user(self, user_id):
|
||||||
|
return self.post('/user/{}/archive'.format(user_id), data=None)
|
||||||
|
|
||||||
@cache.delete('user-{user_id}')
|
@cache.delete('user-{user_id}')
|
||||||
def reset_failed_login_count(self, user_id):
|
def reset_failed_login_count(self, user_id):
|
||||||
url = "/user/{}/reset-failed-login-count".format(user_id)
|
url = "/user/{}/reset-failed-login-count".format(user_id)
|
||||||
|
|||||||
@@ -38,6 +38,11 @@
|
|||||||
{{ user.failed_login_count }} failed login attempts
|
{{ user.failed_login_count }} failed login attempts
|
||||||
</p>
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<span class="page-footer-delete-link page-footer-delete-link-without-button">
|
||||||
|
<a href="{{ url_for('main.archive_user', user_id=user.id) }}">
|
||||||
|
Archive user
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from bs4 import BeautifulSoup
|
||||||
from flask import url_for
|
from flask import url_for
|
||||||
from lxml import html
|
from lxml import html
|
||||||
|
|
||||||
@@ -145,3 +146,33 @@ def test_user_information_page_displays_if_there_are_failed_login_attempts(
|
|||||||
|
|
||||||
document = html.fromstring(response.get_data(as_text=True))
|
document = html.fromstring(response.get_data(as_text=True))
|
||||||
assert document.xpath("//p/text()[normalize-space()='2 failed login attempts']")
|
assert document.xpath("//p/text()[normalize-space()='2 failed login attempts']")
|
||||||
|
|
||||||
|
|
||||||
|
def test_archive_user_prompts_for_confirmation(
|
||||||
|
logged_in_platform_admin_client,
|
||||||
|
api_user_active,
|
||||||
|
mock_get_organisations_and_services_for_user,
|
||||||
|
):
|
||||||
|
response = logged_in_platform_admin_client.get(
|
||||||
|
url_for('main.archive_user', user_id=api_user_active.id)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||||||
|
assert 'Are you sure you want to archive this user?' in page.find('div', class_='banner-dangerous').text
|
||||||
|
|
||||||
|
|
||||||
|
def test_archive_user_posts_to_user_client(
|
||||||
|
logged_in_platform_admin_client,
|
||||||
|
api_user_active,
|
||||||
|
mocker,
|
||||||
|
):
|
||||||
|
mock_user_client = mocker.patch('app.user_api_client.post')
|
||||||
|
|
||||||
|
response = logged_in_platform_admin_client.post(
|
||||||
|
url_for('main.archive_user', user_id=api_user_active.id)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 302
|
||||||
|
assert response.location == url_for('main.user_information', user_id=api_user_active.id, _external=True)
|
||||||
|
mock_user_client.assert_called_once_with('/user/{}/archive'.format(api_user_active.id), data=None)
|
||||||
|
|||||||
@@ -194,6 +194,7 @@ def test_returns_value_from_cache(
|
|||||||
(user_api_client, 'add_user_to_organisation', [sample_uuid(), user_id], {}),
|
(user_api_client, 'add_user_to_organisation', [sample_uuid(), user_id], {}),
|
||||||
(user_api_client, 'set_user_permissions', [user_id, SERVICE_ONE_ID, []], {}),
|
(user_api_client, 'set_user_permissions', [user_id, SERVICE_ONE_ID, []], {}),
|
||||||
(user_api_client, 'activate_user', [api_user_pending(sample_uuid())['id']], {}),
|
(user_api_client, 'activate_user', [api_user_pending(sample_uuid())['id']], {}),
|
||||||
|
(user_api_client, 'archive_user', [user_id], {}),
|
||||||
(service_api_client, 'remove_user_from_service', [SERVICE_ONE_ID, user_id], {}),
|
(service_api_client, 'remove_user_from_service', [SERVICE_ONE_ID, user_id], {}),
|
||||||
(service_api_client, 'create_service', ['', '', 0, False, user_id, sample_uuid()], {}),
|
(service_api_client, 'create_service', ['', '', 0, False, user_id, sample_uuid()], {}),
|
||||||
(invite_api_client, 'accept_invite', [SERVICE_ONE_ID, user_id], {}),
|
(invite_api_client, 'accept_invite', [SERVICE_ONE_ID, user_id], {}),
|
||||||
|
|||||||
Reference in New Issue
Block a user