diff --git a/app/main/views/add_service.py b/app/main/views/add_service.py index 4fb52a377..86019caa1 100644 --- a/app/main/views/add_service.py +++ b/app/main/views/add_service.py @@ -1,11 +1,11 @@ from flask import current_app, redirect, render_template, session, url_for -from flask_login import current_user, login_required +from flask_login import current_user from notifications_python_client.errors import HTTPError from app import billing_api_client, service_api_client from app.main import main from app.main.forms import CreateServiceForm -from app.utils import email_safe, user_is_gov_user +from app.utils import email_safe, user_is_gov_user, user_is_logged_in def _create_service(service_name, organisation_type, email_from, form): @@ -44,7 +44,7 @@ def _create_example_template(service_id): @main.route("/add-service", methods=['GET', 'POST']) -@login_required +@user_is_logged_in @user_is_gov_user def add_service(): form = CreateServiceForm( diff --git a/app/main/views/agreement.py b/app/main/views/agreement.py index b934a34dc..c906f6339 100644 --- a/app/main/views/agreement.py +++ b/app/main/views/agreement.py @@ -1,18 +1,18 @@ from datetime import datetime from flask import abort, redirect, render_template, request, send_file, url_for -from flask_login import current_user, login_required +from flask_login import current_user from app import current_service from app.main import main from app.main.forms import AcceptAgreementForm from app.main.views.sub_navigation_dictionaries import features_nav from app.s3_client.s3_mou_client import get_mou -from app.utils import user_has_permissions +from app.utils import user_has_permissions, user_is_logged_in @main.route('/agreement') -@login_required +@user_is_logged_in def agreement(): return render_template( 'views/agreement/{}.html'.format(current_user.default_organisation.as_jinja_template), @@ -23,7 +23,6 @@ def agreement(): @main.route('/services//agreement') @user_has_permissions('manage_service') -@login_required def service_agreement(service_id): return render_template( 'views/agreement/service-{}.html'.format(current_service.organisation.as_jinja_template), @@ -33,7 +32,6 @@ def service_agreement(service_id): @main.route('/services//agreement.pdf') @user_has_permissions('manage_service') -@login_required def service_download_agreement(service_id): return send_file(**get_mou( current_service.organisation.crown_status_or_404 @@ -42,7 +40,6 @@ def service_download_agreement(service_id): @main.route('/services//agreement/accept', methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def service_accept_agreement(service_id): if not current_service.organisation: @@ -66,7 +63,6 @@ def service_accept_agreement(service_id): @main.route('/services//agreement/confirm', methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def service_confirm_agreement(service_id): if ( @@ -87,7 +83,7 @@ def service_confirm_agreement(service_id): @main.route('/agreement.pdf') -@login_required +@user_is_logged_in def download_agreement(): return send_file(**get_mou( current_user.default_organisation.crown_status_or_404 diff --git a/app/main/views/api_keys.py b/app/main/views/api_keys.py index c07202d61..10c07ef44 100644 --- a/app/main/views/api_keys.py +++ b/app/main/views/api_keys.py @@ -7,7 +7,7 @@ from flask import ( request, url_for, ) -from flask_login import current_user, login_required +from flask_login import current_user from app import ( api_key_api_client, @@ -34,7 +34,6 @@ dummy_bearer_token = 'bearer_token_set' @main.route("/services//api") @user_has_permissions('manage_api_keys') -@login_required def api_integration(service_id): callbacks_link = ( '.api_callbacks' if current_service.has_permission('inbound_sms') @@ -49,14 +48,12 @@ def api_integration(service_id): @main.route("/services//api/documentation") @user_has_permissions('manage_api_keys') -@login_required def api_documentation(service_id): return redirect(url_for('.documentation'), code=301) @main.route("/services//api/whitelist", methods=['GET', 'POST']) @user_has_permissions('manage_api_keys') -@login_required def whitelist(service_id): form = Whitelist() if form.validate_on_submit(): @@ -76,7 +73,6 @@ def whitelist(service_id): @main.route("/services//api/keys") @user_has_permissions('manage_api_keys') -@login_required def api_keys(service_id): return render_template( 'views/api/keys.html', @@ -85,7 +81,6 @@ def api_keys(service_id): @main.route("/services//api/keys/create", methods=['GET', 'POST']) @user_has_permissions('manage_api_keys', restrict_admin_usage=True) -@login_required def create_api_key(service_id): form = CreateKeyForm(current_service.api_keys) form.key_type.choices = [ @@ -126,7 +121,6 @@ def create_api_key(service_id): @main.route("/services//api/keys/revoke/", methods=['GET', 'POST']) @user_has_permissions('manage_api_keys') -@login_required def revoke_api_key(service_id, key_id): key_name = current_service.get_api_key(key_id)['name'] if request.method == 'GET': @@ -169,7 +163,6 @@ def check_token_against_dummy_bearer(token): @main.route("/services//api/callbacks", methods=['GET']) @user_has_permissions('manage_api_keys') -@login_required def api_callbacks(service_id): if not current_service.has_permission('inbound_sms'): return redirect(url_for('.delivery_status_callback', service_id=service_id)) @@ -194,7 +187,6 @@ def get_delivery_status_callback_details(): @main.route("/services//api/callbacks/delivery-status-callback", methods=['GET', 'POST']) @user_has_permissions('manage_api_keys') -@login_required def delivery_status_callback(service_id): delivery_status_callback = get_delivery_status_callback_details() back_link = ( @@ -257,7 +249,6 @@ def get_received_text_messages_callback(): @main.route("/services//api/callbacks/received-text-messages-callback", methods=['GET', 'POST']) @user_has_permissions('manage_api_keys') -@login_required def received_text_messages_callback(service_id): if not current_service.has_permission('inbound_sms'): return redirect(url_for('.api_integration', service_id=service_id)) diff --git a/app/main/views/choose_account.py b/app/main/views/choose_account.py index 69a713aba..febecaeea 100644 --- a/app/main/views/choose_account.py +++ b/app/main/views/choose_account.py @@ -1,8 +1,8 @@ from flask import redirect, render_template, session, url_for -from flask_login import current_user, login_required +from flask_login import current_user from app.main import main -from app.utils import PermanentRedirect +from app.utils import PermanentRedirect, user_is_logged_in @main.route("/services") @@ -16,7 +16,7 @@ def services_or_dashboard(): @main.route("/accounts") -@login_required +@user_is_logged_in def choose_account(): return render_template( 'views/choose-account.html', diff --git a/app/main/views/conversation.py b/app/main/views/conversation.py index e30f72396..e4558dac9 100644 --- a/app/main/views/conversation.py +++ b/app/main/views/conversation.py @@ -1,5 +1,5 @@ from flask import jsonify, redirect, render_template, session, url_for -from flask_login import current_user, login_required +from flask_login import current_user from notifications_python_client.errors import HTTPError from notifications_utils.recipients import format_phone_number_human_readable from notifications_utils.template import SMSPreviewTemplate @@ -13,7 +13,6 @@ from app.utils import user_has_permissions @main.route("/services//conversation/") @user_has_permissions('view_activity') -@login_required def conversation(service_id, notification_id): user_number = get_user_number(service_id, notification_id) @@ -29,7 +28,6 @@ def conversation(service_id, notification_id): @main.route("/services//conversation/.json") @user_has_permissions('view_activity') -@login_required def conversation_updates(service_id, notification_id): return jsonify(get_conversation_partials( @@ -41,7 +39,6 @@ def conversation_updates(service_id, notification_id): @main.route("/services//conversation//reply-with") @main.route("/services//conversation//reply-with/from-folder/") @user_has_permissions('send_messages') -@login_required def conversation_reply( service_id, notification_id, @@ -64,7 +61,6 @@ def conversation_reply( @main.route("/services//conversation//reply-with/") @user_has_permissions('send_messages') -@login_required def conversation_reply_with_template( service_id, notification_id, diff --git a/app/main/views/dashboard.py b/app/main/views/dashboard.py index 8b9abbaeb..13dba983f 100644 --- a/app/main/views/dashboard.py +++ b/app/main/views/dashboard.py @@ -12,7 +12,7 @@ from flask import ( session, url_for, ) -from flask_login import current_user, login_required +from flask_login import current_user from werkzeug.utils import redirect from app import ( @@ -43,7 +43,6 @@ from app.utils import ( # to view history @main.route("/services//history") @user_has_permissions() -@login_required def temp_service_history(service_id): data = service_api_client.get_service_history(service_id)['data'] return render_template('views/temp-history.html', @@ -54,14 +53,12 @@ def temp_service_history(service_id): @main.route("/services//dashboard") @user_has_permissions('view_activity', 'send_messages') -@login_required def old_service_dashboard(service_id): return redirect(url_for('.service_dashboard', service_id=service_id)) @main.route("/services/") @user_has_permissions() -@login_required def service_dashboard(service_id): if session.get('invited_user'): @@ -80,14 +77,12 @@ def service_dashboard(service_id): @main.route("/services//dashboard.json") @user_has_permissions('view_activity') -@login_required def service_dashboard_updates(service_id): return jsonify(**get_dashboard_partials(service_id)) @main.route("/services//template-activity") @user_has_permissions('view_activity') -@login_required def template_history(service_id): return redirect(url_for('main.template_usage', service_id=service_id), code=301) @@ -95,7 +90,6 @@ def template_history(service_id): @main.route("/services//template-usage") @user_has_permissions('view_activity') -@login_required def template_usage(service_id): year, current_financial_year = requested_and_current_financial_year(request) @@ -145,7 +139,6 @@ def template_usage(service_id): @main.route("/services//usage") @user_has_permissions('manage_service', allow_org_user=True) -@login_required def usage(service_id): year, current_financial_year = requested_and_current_financial_year(request) @@ -176,7 +169,6 @@ def usage(service_id): @main.route("/services//monthly") @user_has_permissions('view_activity') -@login_required def monthly(service_id): year, current_financial_year = requested_and_current_financial_year(request) return render_template( @@ -195,7 +187,6 @@ def monthly(service_id): @main.route("/services//inbox") @user_has_permissions('view_activity') -@login_required def inbox(service_id): return render_template( @@ -207,7 +198,6 @@ def inbox(service_id): @main.route("/services//inbox.json") @user_has_permissions('view_activity') -@login_required def inbox_updates(service_id): return jsonify(get_inbox_partials(service_id)) @@ -215,7 +205,6 @@ def inbox_updates(service_id): @main.route("/services//inbox.csv") @user_has_permissions('view_activity') -@login_required def inbox_download(service_id): return Response( Spreadsheet.from_rows( diff --git a/app/main/views/email_branding.py b/app/main/views/email_branding.py index 521b7b1e8..50d7aa70c 100644 --- a/app/main/views/email_branding.py +++ b/app/main/views/email_branding.py @@ -1,5 +1,4 @@ from flask import current_app, redirect, render_template, session, url_for -from flask_login import login_required from app import email_branding_client from app.main import main @@ -16,7 +15,6 @@ from app.utils import get_logo_cdn_domain, user_is_platform_admin @main.route("/email-branding", methods=['GET', 'POST']) -@login_required @user_is_platform_admin def email_branding(): brandings = email_branding_client.get_all_email_branding(sort_key='name') @@ -30,7 +28,6 @@ def email_branding(): @main.route("/email-branding//edit", methods=['GET', 'POST']) @main.route("/email-branding//edit/", methods=['GET', 'POST']) -@login_required @user_is_platform_admin def update_email_branding(branding_id, logo=None): email_branding = email_branding_client.get_email_branding(branding_id)['email_branding'] @@ -87,7 +84,6 @@ 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_is_platform_admin def create_email_branding(logo=None): form = ServiceUpdateEmailBranding(brand_type='org') diff --git a/app/main/views/find_users.py b/app/main/views/find_users.py index ed364b954..11c1242f6 100644 --- a/app/main/views/find_users.py +++ b/app/main/views/find_users.py @@ -1,5 +1,5 @@ from flask import flash, redirect, render_template, request, url_for -from flask_login import current_user, login_required +from flask_login import current_user from app import user_api_client from app.event_handlers import create_archive_user_event @@ -10,7 +10,6 @@ from app.utils import user_is_platform_admin @main.route("/find-users-by-email", methods=['GET', 'POST']) -@login_required @user_is_platform_admin def find_users_by_email(): form = SearchUsersByEmailForm() @@ -28,7 +27,6 @@ def find_users_by_email(): @main.route("/users/", methods=['GET']) -@login_required @user_is_platform_admin def user_information(user_id): return render_template( @@ -38,7 +36,6 @@ def user_information(user_id): @main.route("/users//archive", methods=['GET', 'POST']) -@login_required @user_is_platform_admin def archive_user(user_id): if request.method == 'POST': diff --git a/app/main/views/inbound_number.py b/app/main/views/inbound_number.py index 2bf316ec9..3007db9e5 100644 --- a/app/main/views/inbound_number.py +++ b/app/main/views/inbound_number.py @@ -1,5 +1,4 @@ from flask import render_template -from flask_login import login_required from app import inbound_number_client from app.main import main @@ -7,7 +6,6 @@ from app.utils import user_is_platform_admin @main.route('/inbound-sms-admin', methods=['GET', 'POST']) -@login_required @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 194b25615..20c445b8c 100644 --- a/app/main/views/index.py +++ b/app/main/views/index.py @@ -6,7 +6,7 @@ from flask import ( request, url_for, ) -from flask_login import current_user, login_required +from flask_login import current_user from notifications_utils.international_billing_rates import ( INTERNATIONAL_BILLING_RATES, ) @@ -17,7 +17,7 @@ from app.main import main from app.main.forms import FieldWithNoneOption, SearchByNameForm from app.main.views.feedback import QUESTION_TICKET_TYPE from app.main.views.sub_navigation_dictionaries import features_nav, pricing_nav -from app.utils import get_logo_cdn_domain +from app.utils import get_logo_cdn_domain, user_is_logged_in @main.route('/') @@ -51,7 +51,7 @@ def error(status_code): @main.route("/verify-mobile") -@login_required +@user_is_logged_in def verify_mobile(): return render_template('views/verify-mobile.html') diff --git a/app/main/views/jobs.py b/app/main/views/jobs.py index 8822acf3c..e19f72210 100644 --- a/app/main/views/jobs.py +++ b/app/main/views/jobs.py @@ -10,7 +10,7 @@ from flask import ( stream_with_context, url_for, ) -from flask_login import current_user, login_required +from flask_login import current_user from notifications_utils.letter_timings import get_letter_timings from notifications_utils.template import Template, WithSubjectTemplate @@ -39,7 +39,6 @@ from app.utils import ( @main.route("/services//jobs") @user_has_permissions() -@login_required def view_jobs(service_id): page = int(request.args.get('page', 1)) jobs_response = job_api_client.get_page_of_jobs(service_id, page=page) @@ -74,7 +73,6 @@ def view_jobs(service_id): @main.route("/services//jobs/") @user_has_permissions() -@login_required def view_job(service_id, job_id): job = job_api_client.get_job(service_id, job_id)['data'] if job['job_status'] == 'cancelled': @@ -120,7 +118,6 @@ def view_job(service_id, job_id): @main.route("/services//jobs/.csv") @user_has_permissions('view_activity') -@login_required def view_job_csv(service_id, job_id): job = job_api_client.get_job(service_id, job_id)['data'] template = service_api_client.get_service_template( @@ -155,7 +152,6 @@ def view_job_csv(service_id, job_id): @main.route("/services//jobs/", methods=['POST']) @user_has_permissions('send_messages') -@login_required def cancel_job(service_id, job_id): job_api_client.cancel_job(service_id, job_id) return redirect(url_for('main.service_dashboard', service_id=service_id)) @@ -163,7 +159,6 @@ def cancel_job(service_id, job_id): @main.route("/services//jobs/.json") @user_has_permissions() -@login_required def view_job_updates(service_id, job_id): job = job_api_client.get_job(service_id, job_id)['data'] @@ -181,7 +176,6 @@ def view_job_updates(service_id, job_id): @main.route('/services//notifications', methods=['GET', 'POST']) @main.route('/services//notifications/', methods=['GET', 'POST']) @user_has_permissions() -@login_required def view_notifications(service_id, message_type=None): return render_template( 'views/notifications.html', @@ -206,7 +200,6 @@ def view_notifications(service_id, message_type=None): @main.route('/services//notifications.json', methods=['GET', 'POST']) @main.route('/services//notifications/.json', methods=['GET', 'POST']) @user_has_permissions() -@login_required def get_notifications_as_json(service_id, message_type=None): return jsonify(get_notifications( service_id, message_type, status_override=request.args.get('status') @@ -215,7 +208,6 @@ def get_notifications_as_json(service_id, message_type=None): @main.route('/services//notifications/.csv', endpoint="view_notifications_csv") @user_has_permissions() -@login_required def get_notifications(service_id, message_type, status_override=None): # TODO get the api to return count of pages as well. page = get_page_from_request() diff --git a/app/main/views/letter_branding.py b/app/main/views/letter_branding.py index 634dfa777..97b01c9f4 100644 --- a/app/main/views/letter_branding.py +++ b/app/main/views/letter_branding.py @@ -7,7 +7,6 @@ from flask import ( session, url_for, ) -from flask_login import login_required from notifications_python_client.errors import HTTPError from requests import get as requests_get @@ -33,7 +32,6 @@ from app.utils import get_logo_cdn_domain, user_is_platform_admin @main.route("/letter-branding", methods=['GET']) -@login_required @user_is_platform_admin def letter_branding(): @@ -48,7 +46,6 @@ def letter_branding(): @main.route("/letter-branding//edit", methods=['GET', 'POST']) @main.route("/letter-branding//edit/", methods=['GET', 'POST']) -@login_required @user_is_platform_admin def update_letter_branding(branding_id, logo=None): letter_branding = letter_branding_client.get_letter_branding(branding_id) @@ -128,7 +125,6 @@ def update_letter_branding(branding_id, logo=None): @main.route("/letter-branding/create", methods=['GET', 'POST']) @main.route("/letter-branding/create/", methods=['GET', 'POST']) -@login_required @user_is_platform_admin def create_letter_branding(logo=None): file_upload_form = SVGFileUpload() diff --git a/app/main/views/manage_users.py b/app/main/views/manage_users.py index 3dfa8d7b8..d74ffd36e 100644 --- a/app/main/views/manage_users.py +++ b/app/main/views/manage_users.py @@ -7,7 +7,7 @@ from flask import ( session, url_for, ) -from flask_login import current_user, login_required +from flask_login import current_user from notifications_python_client.errors import HTTPError from app import current_service, service_api_client @@ -31,7 +31,6 @@ from app.utils import is_gov_user, redact_mobile_number, user_has_permissions @main.route("/services//users") @user_has_permissions(allow_org_user=True) -@login_required def manage_users(service_id): return render_template( 'views/manage-users.html', @@ -45,7 +44,6 @@ def manage_users(service_id): @main.route("/services//users/invite", methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def invite_user(service_id): form = InviteUserForm( @@ -82,7 +80,6 @@ def invite_user(service_id): @main.route("/services//users/", methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def edit_user_permissions(service_id, user_id): service_has_email_auth = current_service.has_permission('email_auth') user = current_service.get_team_member(user_id) @@ -123,7 +120,6 @@ def edit_user_permissions(service_id, user_id): @main.route("/services//users//delete", methods=['POST']) @user_has_permissions('manage_service') -@login_required def remove_user_from_service(service_id, user_id): try: service_api_client.remove_user_from_service(service_id, user_id) @@ -145,7 +141,6 @@ def remove_user_from_service(service_id, user_id): @main.route("/services//users//edit-email", methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def edit_user_email(service_id, user_id): user = current_service.get_team_member(user_id) user_email = user.email_address @@ -173,7 +168,6 @@ def edit_user_email(service_id, user_id): @main.route("/services//users//edit-email/confirm", methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def confirm_edit_user_email(service_id, user_id): user = current_service.get_team_member(user_id) if 'team_member_email_change' in session: @@ -208,7 +202,6 @@ def confirm_edit_user_email(service_id, user_id): @main.route("/services//users//edit-mobile-number", methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def edit_user_mobile_number(service_id, user_id): user = current_service.get_team_member(user_id) user_mobile_number = redact_mobile_number(user.mobile_number) @@ -233,7 +226,6 @@ def edit_user_mobile_number(service_id, user_id): @main.route("/services//users//edit-mobile-number/confirm", methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def confirm_edit_user_mobile_number(service_id, user_id): user = current_service.get_team_member(user_id) if 'team_member_mobile_change' in session: @@ -269,7 +261,6 @@ def confirm_edit_user_mobile_number(service_id, user_id): @main.route("/services//cancel-invited-user/", methods=['GET']) @user_has_permissions('manage_service') -@login_required def cancel_invited_user(service_id, invited_user_id): current_service.cancel_invite(invited_user_id) diff --git a/app/main/views/notifications.py b/app/main/views/notifications.py index 6a2c52dce..6c55c4b2a 100644 --- a/app/main/views/notifications.py +++ b/app/main/views/notifications.py @@ -16,7 +16,6 @@ from flask import ( stream_with_context, url_for, ) -from flask_login import login_required from notifications_python_client.errors import APIError from notifications_utils.letter_timings import ( get_letter_timings, @@ -51,7 +50,6 @@ from app.utils import ( @main.route("/services//notification/") @user_has_permissions('view_activity', 'send_messages') -@login_required def view_notification(service_id, notification_id): notification = notification_api_client.get_notification(service_id, str(notification_id)) notification['template'].update({'reply_to_text': notification['reply_to_text']}) @@ -158,7 +156,6 @@ def view_notification(service_id, notification_id): @main.route("/services//notification//cancel", methods=['GET', 'POST']) @user_has_permissions('view_activity', 'send_messages') -@login_required def cancel_letter(service_id, notification_id): if request.method == 'POST': @@ -189,7 +186,6 @@ def get_preview_error_image(): @main.route("/services//notification/.") @user_has_permissions('view_activity') -@login_required def view_letter_notification_as_preview(service_id, notification_id, filetype): if filetype not in ('pdf', 'png'): @@ -220,7 +216,6 @@ def view_letter_notification_as_preview(service_id, notification_id, filetype): @main.route("/services//notification/.json") @user_has_permissions('view_activity', 'send_messages') -@login_required def view_notification_updates(service_id, notification_id): return jsonify(**get_single_notification_partials( notification_api_client.get_notification(service_id, notification_id) @@ -255,7 +250,6 @@ def get_all_personalisation_from_notification(notification): @main.route("/services//download-notifications.csv") @user_has_permissions('view_activity') -@login_required def download_notifications_csv(service_id): filter_args = parse_filter_args(request.args) filter_args['status'] = set_status_filters(filter_args) diff --git a/app/main/views/organisations.py b/app/main/views/organisations.py index fc3db32b7..40016d43b 100644 --- a/app/main/views/organisations.py +++ b/app/main/views/organisations.py @@ -1,7 +1,7 @@ from collections import OrderedDict from flask import flash, redirect, render_template, request, session, url_for -from flask_login import current_user, login_required +from flask_login import current_user from notifications_python_client.errors import HTTPError from werkzeug.exceptions import abort @@ -38,7 +38,6 @@ from app.utils import user_has_permissions, user_is_platform_admin @main.route("/organisations", methods=['GET']) @user_is_platform_admin -@login_required def organisations(): return render_template( 'views/organisations/index.html', @@ -49,7 +48,6 @@ def organisations(): @main.route("/organisations/add", methods=['GET', 'POST']) @user_is_platform_admin -@login_required def add_organisation(): form = CreateOrUpdateOrganisation() @@ -68,7 +66,6 @@ def add_organisation(): @main.route("/organisations/", methods=['GET']) @user_has_permissions() -@login_required def organisation_dashboard(org_id): return render_template( 'views/organisations/organisation/index.html', @@ -77,7 +74,6 @@ def organisation_dashboard(org_id): @main.route("/organisations//trial-services", methods=['GET']) @user_is_platform_admin -@login_required def organisation_trial_mode_services(org_id): return render_template( 'views/organisations/organisation/trial-mode-services.html', @@ -87,7 +83,6 @@ def organisation_trial_mode_services(org_id): @main.route("/organisations//users", methods=['GET']) @user_has_permissions() -@login_required def manage_org_users(org_id): return render_template( 'views/organisations/organisation/users/index.html', @@ -99,7 +94,6 @@ def manage_org_users(org_id): @main.route("/organisations//users/invite", methods=['GET', 'POST']) @user_has_permissions() -@login_required def invite_org_user(org_id): form = InviteOrgUserForm( invalid_email_address=current_user.email_address @@ -123,7 +117,6 @@ def invite_org_user(org_id): @main.route("/organisations//users/", methods=['GET', 'POST']) @user_has_permissions() -@login_required def edit_user_org_permissions(org_id, user_id): return render_template( 'views/organisations/organisation/users/user/index.html', @@ -133,7 +126,6 @@ def edit_user_org_permissions(org_id, user_id): @main.route("/organisations//users//delete", methods=['GET', 'POST']) @user_has_permissions() -@login_required def remove_user_from_organisation(org_id, user_id): user = User.from_id(user_id) if request.method == 'POST': @@ -163,7 +155,6 @@ def remove_user_from_organisation(org_id, user_id): @main.route("/organisations//cancel-invited-user/", methods=['GET']) @user_has_permissions() -@login_required 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) @@ -172,7 +163,6 @@ def cancel_invited_org_user(org_id, invited_user_id): @main.route("/organisations//settings/", methods=['GET']) @user_is_platform_admin -@login_required def organisation_settings(org_id): email_branding = 'GOV.UK' @@ -198,7 +188,6 @@ def organisation_settings(org_id): @main.route("/organisations//settings/edit-name", methods=['GET', 'POST']) @user_is_platform_admin -@login_required def edit_organisation_name(org_id): form = RenameOrganisationForm() @@ -221,7 +210,6 @@ def edit_organisation_name(org_id): @main.route("/organisations//settings/edit-type", methods=['GET', 'POST']) @user_is_platform_admin -@login_required def edit_organisation_type(org_id): form = OrganisationOrganisationTypeForm( @@ -243,7 +231,6 @@ def edit_organisation_type(org_id): @main.route("/organisations//settings/edit-crown-status", methods=['GET', 'POST']) @user_is_platform_admin -@login_required def edit_organisation_crown_status(org_id): form = OrganisationCrownStatusForm( @@ -273,7 +260,6 @@ def edit_organisation_crown_status(org_id): @main.route("/organisations//settings/edit-agreement", methods=['GET', 'POST']) @user_is_platform_admin -@login_required def edit_organisation_agreement(org_id): form = OrganisationAgreementSignedForm( @@ -303,7 +289,6 @@ def edit_organisation_agreement(org_id): @main.route("/organisations//settings/set-email-branding", methods=['GET', 'POST']) @user_is_platform_admin -@login_required def edit_organisation_email_branding(org_id): email_branding = email_branding_client.get_all_email_branding() @@ -329,7 +314,6 @@ def edit_organisation_email_branding(org_id): @main.route("/organisations//settings/preview-email-branding", methods=['GET', 'POST']) @user_is_platform_admin -@login_required def organisation_preview_email_branding(org_id): branding_style = request.args.get('branding_style', None) @@ -352,7 +336,6 @@ def organisation_preview_email_branding(org_id): @main.route("/organisations//settings/set-letter-branding", methods=['GET', 'POST']) @user_is_platform_admin -@login_required def edit_organisation_letter_branding(org_id): letter_branding = letter_branding_client.get_all_letter_branding() @@ -377,7 +360,6 @@ def edit_organisation_letter_branding(org_id): @main.route("/organisations//settings/preview-letter-branding", methods=['GET', 'POST']) @user_is_platform_admin -@login_required def organisation_preview_letter_branding(org_id): branding_style = request.args.get('branding_style') @@ -399,7 +381,6 @@ def organisation_preview_letter_branding(org_id): @main.route("/organisations//settings/edit-organisation-domains", methods=['GET', 'POST']) @user_is_platform_admin -@login_required def edit_organisation_domains(org_id): form = OrganisationDomainsForm() @@ -424,7 +405,6 @@ def edit_organisation_domains(org_id): @main.route("/organisations//settings/edit-name/confirm", methods=['GET', 'POST']) @user_has_permissions() -@login_required def confirm_edit_organisation_name(org_id): # Validate password for form def _check_password(pwd): @@ -457,7 +437,6 @@ def confirm_edit_organisation_name(org_id): @main.route("/organisations//settings/edit-go-live-notes", methods=['GET', 'POST']) @user_is_platform_admin -@login_required def edit_organisation_go_live_notes(org_id): form = GoLiveNotesForm() diff --git a/app/main/views/platform_admin.py b/app/main/views/platform_admin.py index f0d12569d..743f08e70 100644 --- a/app/main/views/platform_admin.py +++ b/app/main/views/platform_admin.py @@ -4,7 +4,6 @@ from collections import OrderedDict from datetime import datetime from flask import abort, flash, redirect, render_template, request, url_for -from flask_login import login_required from notifications_python_client.errors import HTTPError from requests import RequestException @@ -43,7 +42,6 @@ ZERO_FAILURE_THRESHOLD = 0 @main.route("/platform-admin") -@login_required @user_is_platform_admin def platform_admin(): form = DateFilterForm(request.args, meta={'csrf': False}) @@ -152,7 +150,6 @@ def make_columns(global_stats, complaints_number): @main.route("/platform-admin/live-services", endpoint='live_services') @main.route("/platform-admin/trial-services", endpoint='trial_services') -@login_required @user_is_platform_admin def platform_admin_services(): form = DateFilterForm(request.args) @@ -191,7 +188,6 @@ def platform_admin_services(): @main.route("/platform-admin/reports") -@login_required @user_is_platform_admin def platform_admin_reports(): return render_template( @@ -200,7 +196,6 @@ def platform_admin_reports(): @main.route("/platform-admin/reports/live-services.csv") -@login_required @user_is_platform_admin def live_services_csv(): results = service_api_client.get_live_services_data()["data"] @@ -242,7 +237,6 @@ def live_services_csv(): @main.route("/platform-admin/reports/performance-platform.xlsx") -@login_required @user_is_platform_admin def performance_platform_xlsx(): results = service_api_client.get_live_services_data()["data"] @@ -270,7 +264,6 @@ def performance_platform_xlsx(): @main.route("/platform-admin/complaints") -@login_required @user_is_platform_admin def platform_admin_list_complaints(): page = get_page_from_request() @@ -297,7 +290,6 @@ def platform_admin_list_complaints(): @main.route("/platform-admin/returned-letters", methods=["GET", "POST"]) -@login_required @user_is_platform_admin def platform_admin_returned_letters(): form = ReturnedLettersForm() @@ -332,7 +324,6 @@ def platform_admin_returned_letters(): @main.route("/platform-admin/letter-validation-preview", methods=["GET", "POST"]) -@login_required @user_is_platform_admin def platform_admin_letter_validation_preview(): return letter_validation_preview(from_platform_admin=True) @@ -340,7 +331,6 @@ def platform_admin_letter_validation_preview(): @main.route("/services//letter-validation-preview", methods=["GET", "POST"]) @user_has_permissions() -@login_required def service_letter_validation_preview(service_id): return letter_validation_preview(from_platform_admin=False) @@ -392,7 +382,6 @@ def letter_validation_preview(from_platform_admin): @main.route("/platform-admin/clear-cache", methods=['GET', 'POST']) -@login_required @user_is_platform_admin def clear_cache(): # note: `service-{uuid}-templates` cache is cleared for both services and templates. diff --git a/app/main/views/providers.py b/app/main/views/providers.py index 3d3611d84..fd1ea684f 100644 --- a/app/main/views/providers.py +++ b/app/main/views/providers.py @@ -1,5 +1,4 @@ from flask import render_template, url_for -from flask_login import login_required from werkzeug.utils import redirect from app import provider_client @@ -9,7 +8,6 @@ from app.utils import user_is_platform_admin @main.route("/providers") -@login_required @user_is_platform_admin def view_providers(): providers = provider_client.get_all_providers()['provider_details'] @@ -41,7 +39,6 @@ def add_monthly_traffic(domestic_sms_providers): @main.route("/provider//edit", methods=['GET', 'POST']) -@login_required @user_is_platform_admin def edit_provider(provider_id): provider = provider_client.get_provider_by_id(provider_id)['provider_details'] @@ -55,7 +52,6 @@ def edit_provider(provider_id): @main.route("/provider/") -@login_required @user_is_platform_admin def view_provider(provider_id): versions = provider_client.get_provider_versions(provider_id) diff --git a/app/main/views/send.py b/app/main/views/send.py index d4c82c59f..c6206e494 100644 --- a/app/main/views/send.py +++ b/app/main/views/send.py @@ -13,7 +13,7 @@ from flask import ( session, url_for, ) -from flask_login import current_user, login_required +from flask_login import current_user from notifications_python_client.errors import HTTPError from notifications_utils import SMS_CHAR_COUNT_LIMIT from notifications_utils.columns import Columns @@ -101,7 +101,6 @@ def get_example_letter_address(key): @main.route("/services//send//csv", methods=['GET', 'POST']) @user_has_permissions('send_messages', restrict_admin_usage=True) -@login_required def send_messages(service_id, template_id): # if there's lots of data in the session, lets log it for debugging purposes # TODO: Remove this once we're confident we have session size under control @@ -186,7 +185,6 @@ def send_messages(service_id, template_id): @main.route("/services//send/.csv", methods=['GET']) @user_has_permissions('send_messages', 'manage_templates') -@login_required def get_example_csv(service_id, template_id): template = get_template( service_api_client.get_service_template(service_id, template_id)['data'], current_service @@ -202,7 +200,6 @@ def get_example_csv(service_id, template_id): @main.route("/services//send//set-sender", methods=['GET', 'POST']) @user_has_permissions('send_messages', restrict_admin_usage=True) -@login_required def set_sender(service_id, template_id): session['sender_id'] = None redirect_to_one_off = redirect( @@ -291,7 +288,6 @@ def get_sender_details(service_id, template_type): @main.route("/services//send//test", endpoint='send_test') @main.route("/services//send//one-off", endpoint='send_one_off') @user_has_permissions('send_messages', restrict_admin_usage=True) -@login_required def send_test(service_id, template_id): session['recipient'] = None session['placeholders'] = {} @@ -342,7 +338,6 @@ def get_notification_check_endpoint(service_id, template): endpoint='send_one_off_step', ) @user_has_permissions('send_messages', restrict_admin_usage=True) -@login_required def send_test_step(service_id, template_id, step_index): if {'recipient', 'placeholders'} - set(session.keys()): return redirect(url_for( @@ -473,7 +468,6 @@ def send_test_step(service_id, template_id, step_index): @main.route("/services//send//test.", methods=['GET']) @user_has_permissions('send_messages') -@login_required def send_test_preview(service_id, template_id, filetype): if filetype not in ('pdf', 'png'): @@ -605,7 +599,6 @@ def _check_messages(service_id, template_id, upload_id, preview_row, letters_as_ @main.route("/services///check/", methods=['GET']) @main.route("/services///check//row-", methods=['GET']) @user_has_permissions('send_messages', restrict_admin_usage=True) -@login_required def check_messages(service_id, template_id, upload_id, row_index=2): data = _check_messages(service_id, template_id, upload_id, row_index) @@ -658,7 +651,6 @@ def check_messages(service_id, template_id, upload_id, row_index=2): methods=['GET'], ) @user_has_permissions('send_messages') -@login_required def check_messages_preview(service_id, template_id, upload_id, filetype, row_index=2): if filetype == 'pdf': page = None @@ -678,7 +670,6 @@ def check_messages_preview(service_id, template_id, upload_id, filetype, row_ind methods=['GET'], ) @user_has_permissions('send_messages') -@login_required def check_notification_preview(service_id, template_id, filetype): if filetype == 'pdf': page = None @@ -695,7 +686,6 @@ def check_notification_preview(service_id, template_id, filetype): @main.route("/services//start-job/", methods=['POST']) @user_has_permissions('send_messages', restrict_admin_usage=True) -@login_required def start_job(service_id, upload_id): job_api_client.create_job( @@ -719,7 +709,6 @@ def start_job(service_id, upload_id): @main.route("/services//end-tour/") @user_has_permissions('manage_templates') -@login_required def go_to_dashboard_after_tour(service_id, example_template_id): service_api_client.delete_service_template(service_id, example_template_id) @@ -849,7 +838,6 @@ def get_back_link(service_id, template, step_index): @main.route("/services//template//notification/check", methods=['GET']) @user_has_permissions('send_messages', restrict_admin_usage=True) -@login_required def check_notification(service_id, template_id): return render_template( 'views/notifications/check.html', @@ -924,7 +912,6 @@ def get_template_error_dict(exception): @main.route("/services//template//notification/check", methods=['POST']) @user_has_permissions('send_messages', restrict_admin_usage=True) -@login_required def send_notification(service_id, template_id): if {'recipient', 'placeholders'} - set(session.keys()): return redirect(url_for( diff --git a/app/main/views/service_settings.py b/app/main/views/service_settings.py index f9e6f841a..9a50c48df 100644 --- a/app/main/views/service_settings.py +++ b/app/main/views/service_settings.py @@ -12,7 +12,7 @@ from flask import ( session, url_for, ) -from flask_login import current_user, login_required +from flask_login import current_user from notifications_python_client.errors import HTTPError from app import ( @@ -73,7 +73,6 @@ PLATFORM_ADMIN_SERVICE_PERMISSIONS = OrderedDict([ @main.route("/services//service-settings") @user_has_permissions('manage_service', 'manage_api_keys') -@login_required def service_settings(service_id): return render_template( 'views/service-settings.html', @@ -83,7 +82,6 @@ def service_settings(service_id): @main.route("/services//service-settings/name", methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def service_name_change(service_id): form = RenameServiceForm() @@ -112,7 +110,6 @@ def service_name_change(service_id): @main.route("/services//service-settings/name/confirm", methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def service_name_change_confirm(service_id): # Validate password for form def _check_password(pwd): @@ -145,7 +142,6 @@ def service_name_change_confirm(service_id): @main.route("/services//service-settings/request-to-go-live/estimate-usage", methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def estimate_usage(service_id): form = EstimateUsageForm( @@ -178,7 +174,6 @@ def estimate_usage(service_id): @main.route("/services//service-settings/request-to-go-live", methods=['GET']) @user_has_permissions('manage_service') -@login_required def request_to_go_live(service_id): agreement_signed = current_service.organisation.agreement_signed @@ -192,7 +187,6 @@ def request_to_go_live(service_id): @main.route("/services//service-settings/request-to-go-live", methods=['POST']) @user_has_permissions('manage_service') -@login_required @user_is_gov_user def submit_request_to_go_live(service_id): @@ -239,7 +233,6 @@ def submit_request_to_go_live(service_id): @main.route("/services//service-settings/switch-live", methods=["GET", "POST"]) @user_is_platform_admin -@login_required def service_switch_live(service_id): form = ServiceOnOffSettingForm( name="Make service live", @@ -259,7 +252,6 @@ def service_switch_live(service_id): @main.route("/services//service-settings/switch-count-as-live", methods=["GET", "POST"]) @user_is_platform_admin -@login_required def service_switch_count_as_live(service_id): form = ServiceOnOffSettingForm( @@ -282,7 +274,6 @@ def service_switch_count_as_live(service_id): @main.route("/services//service-settings/permissions/", methods=["GET", "POST"]) @user_is_platform_admin -@login_required def service_set_permission(service_id, permission): if permission not in PLATFORM_ADMIN_SERVICE_PERMISSIONS: abort(404) @@ -307,7 +298,6 @@ def service_set_permission(service_id, permission): @main.route("/services//service-settings/can-upload-document", methods=['GET', 'POST']) @user_is_platform_admin -@login_required def service_switch_can_upload_document(service_id): if current_service.contact_link: return redirect(url_for('.service_set_permission', service_id=service_id, permission='upload_document')) @@ -328,7 +318,6 @@ def service_switch_can_upload_document(service_id): @main.route("/services//service-settings/archive", methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def archive_service(service_id): if not current_service.active and ( current_service.trial_mode or current_user.platform_admin @@ -351,7 +340,6 @@ def archive_service(service_id): @main.route("/services//service-settings/suspend", methods=["GET", "POST"]) @user_has_permissions('manage_service') -@login_required def suspend_service(service_id): if request.method == 'POST': service_api_client.suspend_service(service_id) @@ -364,7 +352,6 @@ def suspend_service(service_id): @main.route("/services//service-settings/resume", methods=["GET", "POST"]) @user_has_permissions('manage_service') -@login_required def resume_service(service_id): if request.method == 'POST': service_api_client.resume_service(service_id) @@ -376,7 +363,6 @@ def resume_service(service_id): @main.route("/services//service-settings/contact-link", methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def service_set_contact_link(service_id): form = ServiceContactDetailsForm() @@ -401,21 +387,18 @@ def service_set_contact_link(service_id): @main.route("/services//service-settings/set-reply-to-email", methods=['GET']) @user_has_permissions('manage_service') -@login_required def service_set_reply_to_email(service_id): return redirect(url_for('.service_email_reply_to', service_id=service_id)) @main.route("/services//service-settings/email-reply-to", methods=['GET']) @user_has_permissions('manage_service', 'manage_api_keys') -@login_required def service_email_reply_to(service_id): return render_template('views/service-settings/email_reply_to.html') @main.route("/services//service-settings/email-reply-to/add", methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def service_add_email_reply_to(service_id): form = ServiceReplyToEmailForm() first_email_address = current_service.count_email_reply_to_addresses == 0 @@ -447,7 +430,6 @@ def service_add_email_reply_to(service_id): @main.route("/services//service-settings/email-reply-to//verify", methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def service_verify_reply_to_address(service_id, notification_id): replace = request.args.get('replace', False) is_default = request.args.get('is_default', False) @@ -464,7 +446,6 @@ def service_verify_reply_to_address(service_id, notification_id): @main.route("/services//service-settings/email-reply-to//verify.json") @user_has_permissions('manage_service') -@login_required def service_verify_reply_to_address_updates(service_id, notification_id): return jsonify(**get_service_verify_reply_to_address_partials(service_id, notification_id)) @@ -530,7 +511,6 @@ def get_service_verify_reply_to_address_partials(service_id, notification_id): endpoint="service_confirm_delete_email_reply_to" ) @user_has_permissions('manage_service') -@login_required def service_edit_email_reply_to(service_id, reply_to_email_id): form = ServiceReplyToEmailForm() reply_to_email_address = current_service.get_email_reply_to_address(reply_to_email_id) @@ -576,7 +556,6 @@ def service_edit_email_reply_to(service_id, reply_to_email_id): @main.route("/services//service-settings/email-reply-to//delete", methods=['POST']) @user_has_permissions('manage_service') -@login_required def service_delete_email_reply_to(service_id, reply_to_email_id): service_api_client.delete_reply_to_email_address( service_id=current_service.id, @@ -587,7 +566,6 @@ def service_delete_email_reply_to(service_id, reply_to_email_id): @main.route("/services//service-settings/set-inbound-number", methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def service_set_inbound_number(service_id): available_inbound_numbers = inbound_number_client.get_available_inbound_sms_numbers() inbound_numbers_value_and_label = [ @@ -617,7 +595,6 @@ def service_set_inbound_number(service_id): @main.route("/services//service-settings/sms-prefix", methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def service_set_sms_prefix(service_id): form = SMSPrefixForm(enabled=( @@ -640,7 +617,6 @@ def service_set_sms_prefix(service_id): @main.route("/services//service-settings/set-international-sms", methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def service_set_international_sms(service_id): form = InternationalSMSForm( enabled='on' if current_service.has_permission('international_sms') else 'off' @@ -661,7 +637,6 @@ def service_set_international_sms(service_id): @main.route("/services//service-settings/set-inbound-sms", methods=['GET']) @user_has_permissions('manage_service') -@login_required def service_set_inbound_sms(service_id): return render_template( 'views/service-settings/set-inbound-sms.html', @@ -670,7 +645,6 @@ def service_set_inbound_sms(service_id): @main.route("/services//service-settings/set-letters", methods=['GET']) @user_has_permissions('manage_service') -@login_required def service_set_letters(service_id): return redirect( url_for( @@ -684,7 +658,6 @@ def service_set_letters(service_id): @main.route("/services//service-settings/set-", methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def service_set_channel(service_id, channel): if channel not in {'email', 'sms', 'letter'}: @@ -712,7 +685,6 @@ def service_set_channel(service_id, channel): @main.route("/services//service-settings/set-auth-type", methods=['GET']) @user_has_permissions('manage_service') -@login_required def service_set_auth_type(service_id): return render_template( 'views/service-settings/set-auth-type.html', @@ -721,7 +693,6 @@ def service_set_auth_type(service_id): @main.route("/services//service-settings/letter-contacts", methods=['GET']) @user_has_permissions('manage_service', 'manage_api_keys') -@login_required def service_letter_contact_details(service_id): letter_contact_details = service_api_client.get_letter_contacts(service_id) return render_template( @@ -731,7 +702,6 @@ def service_letter_contact_details(service_id): @main.route("/services//service-settings/letter-contact/add", methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def service_add_letter_contact(service_id): form = ServiceLetterContactBlockForm() first_contact_block = current_service.count_letter_contact_details == 0 @@ -755,7 +725,6 @@ def service_add_letter_contact(service_id): @main.route("/services//service-settings/letter-contact//edit", methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def service_edit_letter_contact(service_id, letter_contact_id): letter_contact_block = current_service.get_letter_contact_block(letter_contact_id) form = ServiceLetterContactBlockForm( @@ -779,7 +748,6 @@ def service_edit_letter_contact(service_id, letter_contact_id): @main.route("/services//service-settings/sms-sender", methods=['GET']) @user_has_permissions('manage_service', 'manage_api_keys') -@login_required def service_sms_senders(service_id): return render_template( 'views/service-settings/sms-senders.html', @@ -788,7 +756,6 @@ def service_sms_senders(service_id): @main.route("/services//service-settings/sms-sender/add", methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def service_add_sms_sender(service_id): form = ServiceSmsSenderForm() first_sms_sender = current_service.count_sms_senders == 0 @@ -816,7 +783,6 @@ def service_add_sms_sender(service_id): endpoint="service_confirm_delete_sms_sender" ) @user_has_permissions('manage_service') -@login_required def service_edit_sms_sender(service_id, sms_sender_id): sms_sender = current_service.get_sms_sender(sms_sender_id) is_inbound_number = sms_sender['inbound_number_id'] @@ -851,7 +817,6 @@ def service_edit_sms_sender(service_id, sms_sender_id): methods=['POST'], ) @user_has_permissions('manage_service') -@login_required def service_delete_sms_sender(service_id, sms_sender_id): service_api_client.delete_sms_sender( service_id=current_service.id, @@ -862,7 +827,6 @@ def service_delete_sms_sender(service_id, sms_sender_id): @main.route("/services//service-settings/set-letter-contact-block", methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def service_set_letter_contact_block(service_id): if not current_service.has_permission('letter'): @@ -886,7 +850,6 @@ def service_set_letter_contact_block(service_id): @main.route("/services//service-settings/set-organisation-type", methods=['GET', 'POST']) @user_is_platform_admin -@login_required def set_organisation_type(service_id): form = OrganisationTypeForm(organisation_type=current_service.organisation_type) @@ -910,7 +873,6 @@ def set_organisation_type(service_id): @main.route("/services//service-settings/set-free-sms-allowance", methods=['GET', 'POST']) @user_is_platform_admin -@login_required def set_free_sms_allowance(service_id): form = FreeSMSAllowance(free_sms_allowance=current_service.free_sms_fragment_limit) @@ -928,7 +890,6 @@ def set_free_sms_allowance(service_id): @main.route("/services//service-settings/set-email-branding", methods=['GET', 'POST']) @user_is_platform_admin -@login_required def service_set_email_branding(service_id): email_branding = email_branding_client.get_all_email_branding() @@ -953,7 +914,6 @@ def service_set_email_branding(service_id): @main.route("/services//service-settings/preview-email-branding", methods=['GET', 'POST']) @user_is_platform_admin -@login_required def service_preview_email_branding(service_id): branding_style = request.args.get('branding_style', None) @@ -975,7 +935,6 @@ def service_preview_email_branding(service_id): @main.route("/services//service-settings/set-letter-branding", methods=['GET', 'POST']) @user_is_platform_admin -@login_required def service_set_letter_branding(service_id): letter_branding = letter_branding_client.get_all_letter_branding() @@ -1000,7 +959,6 @@ def service_set_letter_branding(service_id): @main.route("/services//service-settings/preview-letter-branding", methods=['GET', 'POST']) @user_is_platform_admin -@login_required def service_preview_letter_branding(service_id): branding_style = request.args.get('branding_style') @@ -1022,7 +980,6 @@ def service_preview_letter_branding(service_id): @main.route("/services//service-settings/request-letter-branding", methods=['GET', 'POST']) @user_has_permissions('manage_service', 'manage_templates') -@login_required def request_letter_branding(service_id): return render_template( 'views/service-settings/request-letter-branding.html', @@ -1032,7 +989,6 @@ def request_letter_branding(service_id): @main.route("/services//service-settings/link-service-to-organisation", methods=['GET', 'POST']) @user_is_platform_admin -@login_required def link_service_to_organisation(service_id): all_organisations = organisations_client.get_organisations() @@ -1060,7 +1016,6 @@ def link_service_to_organisation(service_id): @main.route("/services//branding-request/email", methods=['GET', 'POST']) @user_has_permissions('manage_service') -@login_required def branding_request(service_id): branding_type = 'govuk' @@ -1109,7 +1064,6 @@ def branding_request(service_id): @main.route("/services//data-retention", methods=['GET']) @user_is_platform_admin -@login_required def data_retention(service_id): return render_template( 'views/service-settings/data-retention.html', @@ -1118,7 +1072,6 @@ def data_retention(service_id): @main.route("/services//data-retention/add", methods=['GET', 'POST']) @user_is_platform_admin -@login_required def add_data_retention(service_id): form = ServiceDataRetentionForm() if form.validate_on_submit(): @@ -1134,7 +1087,6 @@ def add_data_retention(service_id): @main.route("/services//data-retention//edit", methods=['GET', 'POST']) @user_is_platform_admin -@login_required def edit_data_retention(service_id, data_retention_id): data_retention_item = current_service.get_data_retention_item(data_retention_id) form = ServiceDataRetentionEditForm(days_of_retention=data_retention_item['days_of_retention']) diff --git a/app/main/views/templates.py b/app/main/views/templates.py index 755096cd5..4f7c3de48 100644 --- a/app/main/views/templates.py +++ b/app/main/views/templates.py @@ -3,7 +3,7 @@ from string import ascii_uppercase from dateutil.parser import parse from flask import abort, flash, redirect, render_template, request, url_for -from flask_login import current_user, login_required +from flask_login import current_user from markupsafe import Markup from notifications_python_client.errors import HTTPError from notifications_utils.formatters import nl2br @@ -47,7 +47,6 @@ form_objects = { @main.route("/services//templates/") @user_has_permissions() -@login_required def view_template(service_id, template_id): template = current_service.get_template(template_id) template_folder = current_service.get_template_folder(template['folder']) @@ -88,7 +87,6 @@ def view_template(service_id, template_id): @main.route("/services//start-tour/") @user_has_permissions('view_activity') -@login_required def start_tour(service_id, template_id): template = current_service.get_template(template_id) @@ -112,7 +110,6 @@ def start_tour(service_id, template_id): @main.route("/services//templates/", methods=['GET', 'POST']) @main.route("/services//templates//folders/", methods=['GET', 'POST']) @user_has_permissions() -@login_required def choose_template(service_id, template_type='all', template_folder_id=None): template_folder = current_service.get_template_folder(template_folder_id) @@ -221,7 +218,6 @@ def get_template_nav_items(template_folder_id): @main.route("/services//templates/.") @user_has_permissions() -@login_required def view_letter_template_preview(service_id, template_id, filetype): if filetype not in ('pdf', 'png'): abort(404) @@ -232,7 +228,6 @@ def view_letter_template_preview(service_id, template_id, filetype): @main.route("/templates/letter-preview-image/") -@login_required @user_is_platform_admin def letter_branding_preview_image(filename): template = { @@ -276,7 +271,6 @@ def _view_template_version(service_id, template_id, version, letters_as_pdf=Fals @main.route("/services//templates//version/") @user_has_permissions() -@login_required def view_template_version(service_id, template_id, version): return render_template( 'views/templates/template_history.html', @@ -286,7 +280,6 @@ def view_template_version(service_id, template_id, version): @main.route("/services//templates//version/.") @user_has_permissions() -@login_required def view_template_version_preview(service_id, template_id, version, filetype): db_template = current_service.get_template(template_id, version=version) return TemplatePreview.from_database_object(db_template, filetype) @@ -338,7 +331,6 @@ def _add_template_by_type(template_type, template_folder_id): @main.route("/services//templates/copy/from-service/") @main.route("/services//templates/copy/from-service//from-folder/") @user_has_permissions('manage_templates') -@login_required def choose_template_to_copy( service_id, from_service=None, @@ -374,7 +366,6 @@ def choose_template_to_copy( @main.route("/services//templates/copy/", methods=['GET', 'POST']) @user_has_permissions('manage_templates') -@login_required def copy_template(service_id, template_id): from_service = request.args.get('from_service') @@ -418,7 +409,6 @@ def _get_template_copy_name(template, existing_templates): @main.route("/services//templates/action-blocked///") @user_has_permissions('manage_templates') -@login_required def action_blocked(service_id, notification_type, return_to, template_id): if notification_type == 'sms': notification_type = 'text messages' @@ -436,7 +426,6 @@ def action_blocked(service_id, notification_type, return_to, template_id): @main.route("/services//templates/folders//manage", methods=['GET', 'POST']) @user_has_permissions('manage_templates') -@login_required def manage_template_folder(service_id, template_folder_id): template_folder = current_service.get_template_folder_with_user_permission_or_403(template_folder_id, current_user) form = TemplateFolderForm( @@ -471,7 +460,6 @@ def manage_template_folder(service_id, template_folder_id): @main.route("/services//templates/folders//delete", methods=['GET', 'POST']) @user_has_permissions('manage_templates') -@login_required def delete_template_folder(service_id, template_folder_id): template_folder = current_service.get_template_folder_with_user_permission_or_403(template_folder_id, current_user) @@ -516,7 +504,6 @@ def delete_template_folder(service_id, template_folder_id): @main.route("/services//templates/folders//add-", methods=['GET', 'POST']) @user_has_permissions('manage_templates') -@login_required def add_service_template(service_id, template_type, template_folder_id=None): if template_type not in ['sms', 'email', 'letter']: @@ -578,7 +565,6 @@ def abort_403_if_not_admin_user(): @main.route("/services//templates//edit", methods=['GET', 'POST']) @user_has_permissions('manage_templates') -@login_required def edit_service_template(service_id, template_id): template = current_service.get_template_with_user_permission_or_403(template_id, current_user) template['template_content'] = template['content'] @@ -661,7 +647,6 @@ def edit_service_template(service_id, template_id): @main.route("/services//templates//delete", methods=['GET', 'POST']) @user_has_permissions('manage_templates') -@login_required def delete_service_template(service_id, template_id): template = current_service.get_template_with_user_permission_or_403(template_id, current_user) @@ -711,7 +696,6 @@ def delete_service_template(service_id, template_id): @main.route("/services//templates//redact", methods=['GET']) @user_has_permissions('manage_templates') -@login_required def confirm_redact_template(service_id, template_id): template = current_service.get_template_with_user_permission_or_403(template_id, current_user) @@ -736,7 +720,6 @@ def confirm_redact_template(service_id, template_id): @main.route("/services//templates//redact", methods=['POST']) @user_has_permissions('manage_templates') -@login_required def redact_template(service_id, template_id): service_api_client.redact_service_template(service_id, template_id) @@ -755,7 +738,6 @@ def redact_template(service_id, template_id): @main.route('/services//templates//versions') @user_has_permissions('view_activity') -@login_required def view_template_versions(service_id, template_id): return render_template( 'views/templates/choose_history.html', @@ -779,7 +761,6 @@ def view_template_versions(service_id, template_id): @main.route('/services//templates//set-template-sender', methods=['GET', 'POST']) @user_has_permissions('manage_templates') -@login_required def set_template_sender(service_id, template_id): template = current_service.get_template_with_user_permission_or_403(template_id, current_user) sender_details = get_template_sender_form_dict(service_id, template) @@ -810,7 +791,6 @@ def set_template_sender(service_id, template_id): @main.route('/services//templates//edit-postage', methods=['GET', 'POST']) @user_has_permissions('manage_templates') -@login_required def edit_template_postage(service_id, template_id): template = current_service.get_template_with_user_permission_or_403(template_id, current_user) if template["template_type"] != "letter": diff --git a/app/main/views/user_profile.py b/app/main/views/user_profile.py index f136c61b7..a3be79178 100644 --- a/app/main/views/user_profile.py +++ b/app/main/views/user_profile.py @@ -8,7 +8,7 @@ from flask import ( session, url_for, ) -from flask_login import current_user, login_required +from flask_login import current_user from notifications_utils.url_safe_token import check_token from app import user_api_client @@ -23,7 +23,7 @@ from app.main.forms import ( TwoFactorForm, ) from app.models.user import User -from app.utils import user_is_gov_user +from app.utils import user_is_gov_user, user_is_logged_in NEW_EMAIL = 'new-email' NEW_MOBILE = 'new-mob' @@ -31,7 +31,7 @@ NEW_MOBILE_PASSWORD_CONFIRMED = 'new-mob-password-confirmed' @main.route("/user-profile") -@login_required +@user_is_logged_in def user_profile(): return render_template( 'views/user-profile.html', @@ -40,7 +40,7 @@ def user_profile(): @main.route("/user-profile/name", methods=['GET', 'POST']) -@login_required +@user_is_logged_in def user_profile_name(): form = ChangeNameForm(new_name=current_user.name) @@ -57,7 +57,7 @@ def user_profile_name(): @main.route("/user-profile/email", methods=['GET', 'POST']) -@login_required +@user_is_logged_in @user_is_gov_user def user_profile_email(): @@ -75,7 +75,7 @@ def user_profile_email(): @main.route("/user-profile/email/authenticate", methods=['GET', 'POST']) -@login_required +@user_is_logged_in def user_profile_email_authenticate(): # Validate password for form def _check_password(pwd): @@ -99,7 +99,7 @@ def user_profile_email_authenticate(): @main.route("/user-profile/email/confirm/", methods=['GET']) -@login_required +@user_is_logged_in def user_profile_email_confirm(token): token_data = check_token(token, current_app.config['SECRET_KEY'], @@ -114,7 +114,7 @@ def user_profile_email_confirm(token): @main.route("/user-profile/mobile-number", methods=['GET', 'POST']) -@login_required +@user_is_logged_in def user_profile_mobile_number(): form = ChangeMobileNumberForm(mobile_number=current_user.mobile_number) @@ -131,7 +131,7 @@ def user_profile_mobile_number(): @main.route("/user-profile/mobile-number/authenticate", methods=['GET', 'POST']) -@login_required +@user_is_logged_in def user_profile_mobile_number_authenticate(): # Validate password for form @@ -156,7 +156,7 @@ def user_profile_mobile_number_authenticate(): @main.route("/user-profile/mobile-number/confirm", methods=['GET', 'POST']) -@login_required +@user_is_logged_in def user_profile_mobile_number_confirm(): # Validate verify code for form @@ -184,7 +184,7 @@ def user_profile_mobile_number_confirm(): @main.route("/user-profile/password", methods=['GET', 'POST']) -@login_required +@user_is_logged_in def user_profile_password(): # Validate password for form @@ -203,7 +203,7 @@ def user_profile_password(): @main.route("/user-profile/disable-platform-admin-view", methods=['GET', 'POST']) -@login_required +@user_is_logged_in def user_profile_disable_platform_admin_view(): if not current_user.platform_admin and not session.get('disable_platform_admin_view'): abort(403) diff --git a/app/utils.py b/app/utils.py index cf4c93ee1..56fece882 100644 --- a/app/utils.py +++ b/app/utils.py @@ -14,7 +14,7 @@ import dateutil import pyexcel import pyexcel_xlsx from flask import abort, current_app, redirect, request, session, url_for -from flask_login import current_user +from flask_login import current_user, login_required from notifications_utils.field import Field from notifications_utils.formatters import make_quotes_smart from notifications_utils.recipients import RecipientCSV @@ -44,20 +44,18 @@ with open('{}/email_domains.txt'.format( GOVERNMENT_EMAIL_DOMAIN_NAMES = [line.strip() for line in email_domains] +user_is_logged_in = login_required + + def user_has_permissions(*permissions, **permission_kwargs): def wrap(func): @wraps(func) def wrap_func(*args, **kwargs): - if current_user and current_user.is_authenticated: - if current_user.has_permissions( - *permissions, - **permission_kwargs - ): - return func(*args, **kwargs) - else: - abort(403) - else: - abort(401) + if not current_user.is_authenticated: + return current_app.login_manager.unauthorized() + if not current_user.has_permissions(*permissions, **permission_kwargs): + abort(403) + return func(*args, **kwargs) return wrap_func return wrap @@ -65,6 +63,8 @@ def user_has_permissions(*permissions, **permission_kwargs): def user_is_gov_user(f): @wraps(f) def wrapped(*args, **kwargs): + if not current_user.is_authenticated: + return current_app.login_manager.unauthorized() if not current_user.is_gov_user: abort(403) return f(*args, **kwargs) @@ -75,7 +75,7 @@ def user_is_platform_admin(f): @wraps(f) def wrapped(*args, **kwargs): if not current_user.is_authenticated: - abort(401) + return current_app.login_manager.unauthorized() if not current_user.platform_admin: abort(403) return f(*args, **kwargs) diff --git a/tests/app/main/test_permissions.py b/tests/app/main/test_permissions.py index bf6847940..72b79d457 100644 --- a/tests/app/main/test_permissions.py +++ b/tests/app/main/test_permissions.py @@ -3,7 +3,6 @@ import inspect import pytest from flask import request -from orderedset import OrderedSet from werkzeug.exceptions import Forbidden, Unauthorized from app.main.views.index import index @@ -39,8 +38,11 @@ def _test_permissions( decorated_index() else: try: - decorated_index() - pytest.fail("Failed to throw a forbidden or unauthorised exception") + if ( + decorated_index().location != '/sign-in?next=%2F' or + decorated_index().status_code != 302 + ): + pytest.fail("Failed to throw a forbidden or unauthorised exception") except (Forbidden, Unauthorized): pass @@ -380,6 +382,8 @@ def get_name_of_decorator_from_ast_node(node): return str(node.id) if isinstance(node, ast.Call) and isinstance(node.func, ast.Name): return get_name_of_decorator_from_ast_node(node.func) + if isinstance(node, ast.Attribute): + return node.value.id return '{}.{}'.format(node.func.value.id, node.func.attr) @@ -394,16 +398,16 @@ SERVICE_ID_ARGUMENT = 'service_id' ORGANISATION_ID_ARGUMENT = 'org_id' -def get_routes_and_decorators_with_argument(argument_name): +def get_routes_and_decorators(argument_name=None): import app.main.views as views for module_name, module in inspect.getmembers(views): for function_name, function in inspect.getmembers(module): - if ( - inspect.isfunction(function) and - argument_name in inspect.signature(function).parameters.keys() - ): + if inspect.isfunction(function): decorators = list(get_decorators_for_function(function)) - if 'main.route' in decorators: + if 'main.route' in decorators and ( + not argument_name or + argument_name in inspect.signature(function).parameters.keys() + ): yield '{}.{}'.format(module_name, function_name), decorators @@ -417,47 +421,63 @@ def format_decorators(decorators, indent=8): def test_code_to_extract_decorators_works_with_known_examples(): assert ( 'templates.choose_template', - ['main.route', 'main.route', 'main.route', 'main.route', 'user_has_permissions', 'login_required'], + ['main.route', 'main.route', 'main.route', 'main.route', 'user_has_permissions'], ) in list( - get_routes_and_decorators_with_argument(SERVICE_ID_ARGUMENT) + get_routes_and_decorators(SERVICE_ID_ARGUMENT) ) assert ( 'organisations.organisation_dashboard', - ['main.route', 'user_has_permissions', 'login_required'], + ['main.route', 'user_has_permissions'], ) in list( - get_routes_and_decorators_with_argument(ORGANISATION_ID_ARGUMENT) + get_routes_and_decorators(ORGANISATION_ID_ARGUMENT) + ) + assert ( + 'platform_admin.platform_admin', + ['main.route', 'user_is_platform_admin'], + ) in list( + get_routes_and_decorators() ) -def test_service_routes_have_decorator(): +def test_routes_have_permissions_decorators(): for endpoint, decorators in ( - list(get_routes_and_decorators_with_argument(SERVICE_ID_ARGUMENT)) + - list(get_routes_and_decorators_with_argument(ORGANISATION_ID_ARGUMENT)) + list(get_routes_and_decorators(SERVICE_ID_ARGUMENT)) + + list(get_routes_and_decorators(ORGANISATION_ID_ARGUMENT)) ): file, function = endpoint.split('.') + + assert 'user_is_logged_in' not in decorators, ( + '@user_is_logged_in used on service or organisation specific endpoint\n' + 'Use @user_has_permissions() or @user_is_platform_admin only\n' + 'app/main/views/{}.py::{}\n' + ).format(file, function) + if 'user_is_platform_admin' in decorators: - required_decorators = ('main.route', 'user_is_platform_admin', 'login_required') - else: - required_decorators = ('main.route', 'user_has_permissions', 'login_required') + continue - for required_decorator in required_decorators: - assert required_decorator in decorators, ( - 'Missing {} decorator on app/main/views/{}.py::{}' - ).format(required_decorator, file, function) + assert 'user_has_permissions' in decorators, ( + 'Missing @user_has_permissions decorator\n' + 'Use @user_has_permissions() or @user_is_platform_admin instead\n' + 'app/main/views/{}.py::{}\n' + ).format(file, function) - present_required_decorators = tuple(OrderedSet( - decorator for decorator in decorators - if decorator in required_decorators - )) - assert present_required_decorators == required_decorators, ( - 'Wrong order of permissions decorators on app/main/views/{}.py::{}\n' - ' Expected:\n' - '{}\n' - ' Actual:\n' - '{}\n' - ).format( - file, function, - format_decorators(required_decorators), - format_decorators(present_required_decorators), - ) + for endpoint, decorators in get_routes_and_decorators(): + + assert 'login_required' not in decorators, ( + '@login_required found\n' + 'For consistency, use @user_is_logged_in() instead (from app.utils)\n' + 'app/main/views/{}.py::{}\n' + ).format(file, function) + + if 'user_is_platform_admin' in decorators: + assert 'user_has_permissions' not in decorators, ( + '@user_has_permissions and @user_is_platform_admin decorating same function\n' + 'You can only use one of these at a time\n' + 'app/main/views/{}.py::{}\n' + ).format(file, function) + assert 'user_is_logged_in' not in decorators, ( + '@user_is_logged_in used with @user_is_platform_admin\n' + 'Use @user_is_platform_admin only\n' + 'app/main/views/{}.py::{}\n' + ).format(file, function) diff --git a/tests/app/models/test_user.py b/tests/app/models/test_user.py index edc69b51e..9a4258933 100644 --- a/tests/app/models/test_user.py +++ b/tests/app/models/test_user.py @@ -1,6 +1,17 @@ import pytest -from app.models.user import User +from app.models.user import AnonymousUser, User + + +def test_anonymous_user(app_): + assert AnonymousUser().is_authenticated is False + assert AnonymousUser().logged_in_elsewhere() is False + assert AnonymousUser().default_organisation.name is None + assert AnonymousUser().default_organisation.crown is None + assert AnonymousUser().default_organisation.agreement_signed is None + assert AnonymousUser().default_organisation.domains == [] + assert AnonymousUser().default_organisation.organisation_type is None + assert AnonymousUser().default_organisation.request_to_go_live_notes is None def test_user(app_):