diff --git a/app/main/views/email_branding.py b/app/main/views/email_branding.py index a8cf56f62..f9b72c493 100644 --- a/app/main/views/email_branding.py +++ b/app/main/views/email_branding.py @@ -19,12 +19,12 @@ from app.main.views.service_settings import ( get_branding_as_dict, get_branding_as_value_and_label, ) -from app.utils import get_cdn_domain, user_has_permissions +from app.utils import get_cdn_domain, user_is_platform_admin @main.route("/email-branding", methods=['GET', 'POST']) @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def email_branding(): brandings = email_branding_client.get_all_email_branding() @@ -47,7 +47,7 @@ def email_branding(): @main.route("/email-branding//edit", methods=['GET', 'POST']) @main.route("/email-branding//edit/", methods=['GET', 'POST']) @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def update_email_branding(branding_id, logo=None): email_branding = email_branding_client.get_email_branding(branding_id)['email_branding'] @@ -98,7 +98,7 @@ def update_email_branding(branding_id, logo=None): @main.route("/email-branding/create", methods=['GET', 'POST']) @main.route("/email-branding/create/", methods=['GET', 'POST']) @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def create_email_branding(logo=None): form = ServiceCreateEmailBranding() diff --git a/app/main/views/inbound_number.py b/app/main/views/inbound_number.py index 0f58d8cf4..2bf316ec9 100644 --- a/app/main/views/inbound_number.py +++ b/app/main/views/inbound_number.py @@ -3,12 +3,12 @@ from flask_login import login_required from app import inbound_number_client from app.main import main -from app.utils import user_has_permissions +from app.utils import user_is_platform_admin @main.route('/inbound-sms-admin', methods=['GET', 'POST']) @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def inbound_sms_admin(): data = inbound_number_client.get_all_inbound_sms_number_service() diff --git a/app/main/views/index.py b/app/main/views/index.py index a00ab5523..e16361fad 100644 --- a/app/main/views/index.py +++ b/app/main/views/index.py @@ -1,8 +1,7 @@ from flask import redirect, render_template, request, url_for from flask_login import current_user, login_required -from notifications_utils.international_billing_rates import ( - INTERNATIONAL_BILLING_RATES, -) +from notifications_utils.international_billing_rates import \ + INTERNATIONAL_BILLING_RATES from notifications_utils.template import HTMLEmailTemplate from app import convert_to_boolean diff --git a/app/main/views/letter_jobs.py b/app/main/views/letter_jobs.py index a63e1f99d..ae3e733e9 100644 --- a/app/main/views/letter_jobs.py +++ b/app/main/views/letter_jobs.py @@ -3,12 +3,12 @@ from flask_login import login_required from app import letter_jobs_client from app.main import main -from app.utils import user_has_permissions +from app.utils import user_is_platform_admin @main.route("/letter-jobs", methods=['GET', 'POST']) @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def letter_jobs(): letter_jobs_list = letter_jobs_client.get_letter_jobs() diff --git a/app/main/views/organisations.py b/app/main/views/organisations.py index e1e3639bc..f8b193689 100644 --- a/app/main/views/organisations.py +++ b/app/main/views/organisations.py @@ -10,12 +10,12 @@ from app.main.forms import ( InviteOrgUserForm, SearchUsersForm, ) -from app.utils import user_has_permissions +from app.utils import user_is_platform_admin @main.route("/organisations", methods=['GET']) @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def organisations(): orgs = organisations_client.get_organisations() @@ -27,7 +27,7 @@ def organisations(): @main.route("/organisations/add", methods=['GET', 'POST']) @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def add_organisation(): form = CreateOrUpdateOrganisation() @@ -46,7 +46,7 @@ def add_organisation(): @main.route("/organisations/", methods=['GET']) @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def organisation_dashboard(org_id): organisation_services = organisations_client.get_organisation_services(org_id) @@ -58,7 +58,7 @@ def organisation_dashboard(org_id): @main.route("/organisations//edit", methods=['GET', 'POST']) @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def update_organisation(org_id): org = organisations_client.get_organisation(org_id) @@ -83,7 +83,7 @@ def update_organisation(org_id): @main.route("/organisations//users", methods=['GET']) @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def manage_org_users(org_id): users = sorted( user_api_client.get_users_for_organisation(org_id=org_id) + [ @@ -103,7 +103,7 @@ def manage_org_users(org_id): @main.route("/organisations//users/invite", methods=['GET', 'POST']) @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def invite_org_user(org_id): form = InviteOrgUserForm( invalid_email_address=current_user.email_address @@ -127,7 +127,7 @@ def invite_org_user(org_id): @main.route("/organisations//users/", methods=['GET', 'POST']) @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def edit_user_org_permissions(org_id, user_id): user = user_api_client.get_user(user_id) @@ -139,7 +139,7 @@ def edit_user_org_permissions(org_id, user_id): @main.route("/organisations//users//delete", methods=['GET', 'POST']) @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def remove_user_from_organisation(org_id, user_id): user = user_api_client.get_user(user_id) if request.method == 'POST': @@ -169,7 +169,7 @@ def remove_user_from_organisation(org_id, user_id): @main.route("/organisations//cancel-invited-user/", methods=['GET']) @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def cancel_invited_org_user(org_id, invited_user_id): org_invite_api_client.cancel_invited_user(org_id=org_id, invited_user_id=invited_user_id) diff --git a/app/main/views/platform_admin.py b/app/main/views/platform_admin.py index bc4712538..872a85095 100644 --- a/app/main/views/platform_admin.py +++ b/app/main/views/platform_admin.py @@ -8,12 +8,12 @@ from app import service_api_client from app.main import main from app.main.forms import DateFilterForm from app.statistics_utils import get_formatted_percentage -from app.utils import user_has_permissions +from app.utils import user_is_platform_admin @main.route("/platform-admin") @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def platform_admin(): form = DateFilterForm(request.args) api_args = {'detailed': True, @@ -41,7 +41,7 @@ def platform_admin(): @main.route("/platform-admin/live-services", endpoint='live_services') @main.route("/platform-admin/trial-services", endpoint='trial_services') @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def platform_admin_services(): form = DateFilterForm(request.args) api_args = {'detailed': True, diff --git a/app/main/views/providers.py b/app/main/views/providers.py index 5fffedf10..c1edda49a 100644 --- a/app/main/views/providers.py +++ b/app/main/views/providers.py @@ -5,12 +5,12 @@ from werkzeug.utils import redirect from app import provider_client from app.main import main from app.main.forms import ProviderForm -from app.utils import user_has_permissions +from app.utils import user_is_platform_admin @main.route("/providers") @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def view_providers(): providers = provider_client.get_all_providers()['provider_details'] domestic_email_providers, domestic_sms_providers, intl_sms_providers = [], [], [] @@ -32,7 +32,7 @@ def view_providers(): @main.route("/provider//edit", methods=['GET', 'POST']) @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def edit_provider(provider_id): provider = provider_client.get_provider_by_id(provider_id)['provider_details'] form = ProviderForm(active=provider['active'], priority=provider['priority']) @@ -46,7 +46,7 @@ def edit_provider(provider_id): @main.route("/provider/") @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def view_provider(provider_id): versions = provider_client.get_provider_versions(provider_id) return render_template('views/providers/provider.html', provider_versions=versions['data']) diff --git a/app/main/views/service_settings.py b/app/main/views/service_settings.py index 7b42732c3..8392d0064 100644 --- a/app/main/views/service_settings.py +++ b/app/main/views/service_settings.py @@ -43,7 +43,12 @@ from app.main.forms import ( ServiceSwitchLettersForm, SMSPrefixForm, ) -from app.utils import email_safe, get_cdn_domain, user_has_permissions +from app.utils import ( + email_safe, + get_cdn_domain, + user_has_permissions, + user_is_platform_admin, +) @main.route("/services//service-settings") @@ -212,7 +217,7 @@ def submit_request_to_go_live(service_id): @main.route("/services//service-settings/switch-live") @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def service_switch_live(service_id): service_api_client.update_service( current_service['id'], @@ -226,7 +231,7 @@ def service_switch_live(service_id): @main.route("/services//service-settings/research-mode") @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def service_switch_research_mode(service_id): service_api_client.update_service_with_properties( service_id, @@ -270,7 +275,7 @@ def update_service_permissions(service_id, permissions, sms_sender=None): @main.route("/services//service-settings/can-send-email") @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def service_switch_can_send_email(service_id): switch_service_permissions(service_id, 'email') return redirect(url_for('.service_settings', service_id=service_id)) @@ -278,7 +283,7 @@ def service_switch_can_send_email(service_id): @main.route("/services//service-settings/can-send-sms") @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def service_switch_can_send_sms(service_id): switch_service_permissions(service_id, 'sms') return redirect(url_for('.service_settings', service_id=service_id)) @@ -286,7 +291,7 @@ def service_switch_can_send_sms(service_id): @main.route("/services//service-settings/email-auth") @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def service_switch_email_auth(service_id): switch_service_permissions(service_id, 'email_auth') return redirect(url_for('.service_settings', service_id=service_id)) @@ -294,7 +299,7 @@ def service_switch_email_auth(service_id): @main.route("/services//service-settings/can-send-precompiled-letter") @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def service_switch_can_send_precompiled_letter(service_id): switch_service_permissions(service_id, 'precompiled_letter') return redirect(url_for('.service_settings', service_id=service_id)) @@ -690,7 +695,7 @@ def service_set_letter_contact_block(service_id): @main.route("/services//service-settings/set-organisation-type", methods=['GET', 'POST']) @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def set_organisation_type(service_id): form = OrganisationTypeForm(organisation_type=current_service.get('organisation_type')) @@ -715,7 +720,7 @@ def set_organisation_type(service_id): @main.route("/services//service-settings/set-free-sms-allowance", methods=['GET', 'POST']) @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def set_free_sms_allowance(service_id): form = FreeSMSAllowance(free_sms_allowance=billing_api_client.get_free_sms_fragment_limit_for_year(service_id)) @@ -733,7 +738,7 @@ def set_free_sms_allowance(service_id): @main.route("/services//service-settings/set-email-branding", methods=['GET', 'POST']) @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def service_set_email_branding(service_id): email_branding = email_branding_client.get_all_email_branding() @@ -762,7 +767,7 @@ def service_set_email_branding(service_id): @main.route("/services//service-settings/set-letter-branding", methods=['GET', 'POST']) @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def set_letter_branding(service_id): form = LetterBranding(choices=email_branding_client.get_letter_email_branding().items()) @@ -784,7 +789,7 @@ def set_letter_branding(service_id): @main.route("/services//service-settings/link-service-to-organisation", methods=['GET', 'POST']) @login_required -@user_has_permissions(admin_override=True) +@user_is_platform_admin def link_service_to_organisation(service_id): organisations = organisations_client.get_organisations() diff --git a/app/main/views/templates.py b/app/main/views/templates.py index 0fc06cd3b..0888b7098 100644 --- a/app/main/views/templates.py +++ b/app/main/views/templates.py @@ -328,7 +328,7 @@ def add_service_template(service_id, template_type): def abort_403_if_not_admin_user(): - if not current_user.has_permissions(admin_override=True): + if not current_user.platform_admin: abort(403) diff --git a/app/templates/admin_template.html b/app/templates/admin_template.html index 35319907d..29323efe6 100644 --- a/app/templates/admin_template.html +++ b/app/templates/admin_template.html @@ -44,7 +44,7 @@ {% if current_user.is_authenticated %}
  • Documentation
  • {{ current_user.name }}
  • - {% if current_user.has_permissions(admin_override=True) %} + {% if current_user.platform_admin %}
  • Platform admin
  • {% endif %}
  • Sign out
  • diff --git a/app/templates/org_nav.html b/app/templates/org_nav.html index a8df3392c..78805cb65 100644 --- a/app/templates/org_nav.html +++ b/app/templates/org_nav.html @@ -1,8 +1,6 @@ diff --git a/app/templates/views/edit-email-template.html b/app/templates/views/edit-email-template.html index 81534fa8c..bc6010a29 100644 --- a/app/templates/views/edit-email-template.html +++ b/app/templates/views/edit-email-template.html @@ -19,7 +19,7 @@ {{ textbox(form.name, width='1-1', hint='Your recipients won’t see this', rows=10) }} {{ textbox(form.subject, width='1-1', highlight_tags=True, rows=2) }} {{ textbox(form.template_content, highlight_tags=True, width='1-1', rows=8) }} - {% if current_user.has_permissions(admin_override=True) %} + {% if current_user.platform_admin %} {{ radios(form.process_type) }} {% endif %} {{ page_footer( diff --git a/app/templates/views/edit-sms-template.html b/app/templates/views/edit-sms-template.html index 16d2b8ee4..e7578aee0 100644 --- a/app/templates/views/edit-sms-template.html +++ b/app/templates/views/edit-sms-template.html @@ -20,7 +20,7 @@
    {{ textbox(form.template_content, highlight_tags=True, width='1-1', rows=5) }} - {% if current_user.has_permissions(admin_override=True) %} + {% if current_user.platform_admin %} {{ radios(form.process_type) }} {% endif %} {{ page_footer( diff --git a/app/templates/views/service-settings.html b/app/templates/views/service-settings.html index 7c4adc14b..a2ab35512 100644 --- a/app/templates/views/service-settings.html +++ b/app/templates/views/service-settings.html @@ -250,7 +250,7 @@ {% endif %} - {% if current_user.has_permissions(admin_override=True) %} + {% if current_user.platform_admin %}

    Platform admin settings

    {% call mapping_table( diff --git a/app/utils.py b/app/utils.py index 9568aea23..8470f884d 100644 --- a/app/utils.py +++ b/app/utils.py @@ -78,6 +78,17 @@ def user_has_permissions(*permissions, admin_override=False, any_=False): return wrap +def user_is_platform_admin(f): + @wraps(f) + def wrapped(*args, **kwargs): + if not current_user.is_authenticated: + abort(401) + if not current_user.platform_admin: + abort(403) + return f(*args, **kwargs) + return wrapped + + def redirect_to_sign_in(f): @wraps(f) def wrapped(*args, **kwargs): diff --git a/tests/app/main/views/test_manage_users.py b/tests/app/main/views/test_manage_users.py index d2439dbe1..9dbe11d78 100644 --- a/tests/app/main/views/test_manage_users.py +++ b/tests/app/main/views/test_manage_users.py @@ -3,6 +3,7 @@ import copy import pytest from bs4 import BeautifulSoup from flask import url_for +from tests.conftest import service_one as create_sample_service from tests.conftest import ( SERVICE_ONE_ID, active_user_manage_template_permission, @@ -11,7 +12,6 @@ from tests.conftest import ( active_user_with_permissions, normalize_spaces, ) -from tests.conftest import service_one as create_sample_service import app from app.notify_client.models import InvitedUser diff --git a/tests/app/main/views/test_templates.py b/tests/app/main/views/test_templates.py index 803703564..3c7adafbb 100644 --- a/tests/app/main/views/test_templates.py +++ b/tests/app/main/views/test_templates.py @@ -11,6 +11,7 @@ from tests import ( template_json, validate_route_permission, ) +from tests.conftest import service_one as create_sample_service from tests.conftest import ( SERVICE_ONE_ID, mock_get_service_email_template, @@ -18,9 +19,8 @@ from tests.conftest import ( mock_get_service_template, no_letter_contact_blocks, normalize_spaces, + single_letter_contact_block, ) -from tests.conftest import service_one as create_sample_service -from tests.conftest import single_letter_contact_block from app.main.views.templates import ( get_human_readable_delta, diff --git a/tests/app/notify_client/test_template_statistics_client.py b/tests/app/notify_client/test_template_statistics_client.py index a6f30de6b..cbb01ac74 100644 --- a/tests/app/notify_client/test_template_statistics_client.py +++ b/tests/app/notify_client/test_template_statistics_client.py @@ -1,8 +1,7 @@ import uuid -from app.notify_client.template_statistics_api_client import ( - TemplateStatisticsApiClient, -) +from app.notify_client.template_statistics_api_client import \ + TemplateStatisticsApiClient def test_template_statistics_client_calls_correct_api_endpoint_for_service(mocker, api_user_active):