Merge branch 'main' into 2721-create-enums-and-replace-hardcoded-status-strings-with-enums-PART5

This commit is contained in:
Beverly Nguyen
2025-07-22 12:55:45 -07:00
43 changed files with 127 additions and 116 deletions

View File

@@ -362,6 +362,7 @@ def init_app(application):
@application.context_processor
def _attach_enums():
from app.enums import ServicePermission
return {"ServicePermission": ServicePermission}
@application.context_processor

View File

@@ -17,7 +17,7 @@ class Config(object):
ADMIN_BASE_URL = getenv("ADMIN_BASE_URL", "http://localhost:6012")
HEADER_COLOUR = (
"#81878b" # mix(govuk-colour("dark-grey"), govuk-colour("mid-grey"))
"#81878b" # mix of dark-grey and mid-grey
)
LOGO_CDN_DOMAIN = (
"static-logos.notifications.service.gov.uk" # TODO use our own CDN
@@ -141,7 +141,7 @@ class Test(Development):
class Production(Config):
HEADER_COLOUR = "#005EA5" # $govuk-blue
HEADER_COLOUR = "#005EA5" # primary blue
HTTP_PROTOCOL = "https"
ASSET_DOMAIN = "" # TODO use a CDN
ASSET_PATH = "/static/" # TODO use a CDN

View File

@@ -81,6 +81,9 @@ class ServicePermission(StrEnum):
EDIT_FOLDER_PERMISSIONS = "edit_folder_permissions"
RESEARCH_MODE = "research_mode"
UPLOAD_DOCUMENT = "upload_document"
VIEW_ACTIVITY = "view_activity"
MANAGE_USERS = "manage_users"
SEND_EMAILS = "send_emails"
class InvitedUserStatus(StrEnum):

View File

@@ -1,7 +1,7 @@
from flask import abort, render_template, request, url_for
from app import current_service, job_api_client
from app.enums import NotificationStatus
from app.enums import NotificationStatus, ServicePermission
from app.formatters import get_time_left
from app.main import main
from app.utils.pagination import (
@@ -14,7 +14,7 @@ from app.utils.user import user_has_permissions
@main.route("/activity/services/<uuid:service_id>")
@user_has_permissions("view_activity")
@user_has_permissions(ServicePermission.VIEW_ACTIVITY)
def all_jobs_activity(service_id):
service_data_retention_days = 7
page = get_page_from_request()

View File

@@ -13,7 +13,7 @@ from notifications_utils.template import SMSPreviewTemplate
@main.route("/services/<uuid:service_id>/conversation/<uuid:notification_id>")
@user_has_permissions("view_activity")
@user_has_permissions(ServicePermission.VIEW_ACTIVITY)
def conversation(service_id, notification_id):
user_number = get_user_number(service_id, notification_id)
@@ -31,7 +31,7 @@ def conversation(service_id, notification_id):
@main.route("/services/<uuid:service_id>/conversation/<uuid:notification_id>.json")
@user_has_permissions("view_activity")
@user_has_permissions(ServicePermission.VIEW_ACTIVITY)
def conversation_updates(service_id, notification_id):
return jsonify(
get_conversation_partials(

View File

@@ -24,7 +24,7 @@ from app.utils.user import user_has_permissions
@main.route("/services/<uuid:service_id>/dashboard")
@user_has_permissions("view_activity", ServicePermission.SEND_MESSAGES)
@user_has_permissions(ServicePermission.VIEW_ACTIVITY, ServicePermission.SEND_MESSAGES)
def old_service_dashboard(service_id):
return redirect(url_for(".service_dashboard", service_id=service_id))
@@ -37,7 +37,7 @@ def service_dashboard(service_id):
session.pop("invited_user_id", None)
session["service_id"] = service_id
if not current_user.has_permissions("view_activity"):
if not current_user.has_permissions(ServicePermission.VIEW_ACTIVITY):
return redirect(url_for("main.choose_template", service_id=service_id))
job_response = job_api_client.get_jobs(service_id)["data"]
@@ -166,7 +166,7 @@ def get_daily_stats_by_user(service_id):
@main.route("/services/<uuid:service_id>/template-usage")
@user_has_permissions("view_activity")
@user_has_permissions(ServicePermission.VIEW_ACTIVITY)
def template_usage(service_id):
year, current_financial_year = requested_and_current_financial_year(request)
stats = template_statistics_client.get_monthly_template_usage_for_service(

View File

@@ -78,7 +78,7 @@ def view_job(service_id, job_id):
@main.route("/services/<uuid:service_id>/jobs/<uuid:job_id>.csv")
@user_has_permissions("view_activity")
@user_has_permissions(ServicePermission.VIEW_ACTIVITY)
def view_job_csv(service_id, job_id):
job = Job.from_id(job_id, service_id=service_id)
filter_args = parse_filter_args(request.args)
@@ -222,7 +222,9 @@ def get_notifications(service_id, message_type, status_override=None): # noqa
message_type, number_of_days="seven_day"
)
if request.path.endswith("csv") and current_user.has_permissions("view_activity"):
if request.path.endswith("csv") and current_user.has_permissions(
ServicePermission.VIEW_ACTIVITY
):
return Response(
generate_notifications_csv(
service_id=service_id,

View File

@@ -28,7 +28,7 @@ from app.utils.user import user_has_permissions
@main.route("/services/<uuid:service_id>/notification/<uuid:notification_id>")
@user_has_permissions("view_activity", ServicePermission.SEND_MESSAGES)
@user_has_permissions(ServicePermission.VIEW_ACTIVITY, ServicePermission.SEND_MESSAGES)
def view_notification(service_id, notification_id, error_message=None):
if error_message:
flash(error_message)
@@ -101,7 +101,7 @@ def view_notification(service_id, notification_id, error_message=None):
@main.route("/services/<uuid:service_id>/notification/<uuid:notification_id>.json")
@user_has_permissions("view_activity", ServicePermission.SEND_MESSAGES)
@user_has_permissions(ServicePermission.VIEW_ACTIVITY, ServicePermission.SEND_MESSAGES)
def view_notification_updates(service_id, notification_id):
return jsonify(
**get_single_notification_partials(
@@ -134,7 +134,7 @@ def get_all_personalisation_from_notification(notification):
@main.route("/services/<uuid:service_id>/download-notifications.csv")
@user_has_permissions("view_activity")
@user_has_permissions(ServicePermission.VIEW_ACTIVITY)
def download_notifications_csv(service_id):
filter_args = parse_filter_args(request.args)
filter_args["status"] = set_status_filters(filter_args)

View File

@@ -823,7 +823,7 @@ def redact_template(service_id, template_id):
@main.route("/services/<uuid:service_id>/templates/<uuid:template_id>/versions")
@user_has_permissions("view_activity")
@user_has_permissions(ServicePermission.VIEW_ACTIVITY)
def view_template_versions(service_id, template_id):
return render_template(
"views/templates/choose_history.html",

View File

@@ -6,11 +6,11 @@
href="{{ url_for('.choose_template', service_id=current_service.id) }}">Send messages</a>
<ul class="usa-sidenav">
{% if current_user.has_permissions() %}
{% if current_user.has_permissions('view_activity') %}
{% if current_user.has_permissions(ServicePermission.VIEW_ACTIVITY) %}
<li class="usa-sidenav__item"><a class="{{ main_navigation.is_selected('dashboard') }}" href="{{ url_for('.service_dashboard', service_id=current_service.id) }}">Dashboard</a></li>
<li class="usa-sidenav__item"><a class="{{ main_navigation.is_selected('activity') }}" href="{{ url_for('.all_jobs_activity', service_id=current_service.id) }}">Activity</a></li>
{% endif %}
{% if not current_user.has_permissions('view_activity') %}
{% if not current_user.has_permissions(ServicePermission.VIEW_ACTIVITY) %}
<li class="usa-sidenav__item"><a class="{{ casework_navigation.is_selected('sent-messages') }}" href="{{ url_for('.view_notifications', service_id=current_service.id, status='sending,delivered,failed') }}">Sent messages</a></li>
{% endif %}
{% elif current_user.has_permissions(allow_org_user=True) %}

View File

@@ -125,7 +125,7 @@
<p><b>Note: </b>Report data is only available for 7 days after your message has been sent</p>
</div>
{{show_pagination}}
{% if current_user.has_permissions('view_activity') %}
{% if current_user.has_permissions(ServicePermission.VIEW_ACTIVITY) %}
<h2 class="line-height-sans-2 margin-bottom-0 margin-top-4">Download recent reports</h2>
<p class="font-body-sm">
<a href="{{ download_link_one_day }}" download="download" class="usa-link">Download all data last 24 hours (<abbr title="Comma separated values">CSV</abbr>)</a>

View File

@@ -47,7 +47,7 @@
{% endif %}
{% for notification in api_notifications.notifications %}
<details class="api-notifications-item govuk-details" data-module="govuk-details">
<summary class="govuk-details__summary govuk-clearfix api-notifications-item__heading">
<summary class="govuk-details__summary api-notifications-item__heading">
<h3>
<span class="govuk-details__summary-text">
{{ notification.to }}

View File

@@ -7,7 +7,7 @@
{% set page_title = (
(99|message_count_label(message_type, suffix='')) | capitalize
if current_user.has_permissions('view_activity')
if current_user.has_permissions(ServicePermission.VIEW_ACTIVITY)
else 'Sent messages'
) %}
@@ -62,7 +62,7 @@
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
{% endcall %}
{% if current_user.has_permissions('view_activity') %}
{% if current_user.has_permissions(ServicePermission.VIEW_ACTIVITY) %}
<p class="font-body-sm">
<a href="{{ download_link_seven_day }}" download="download" class="usa-link">Download all data last 7 days (<abbr title="Comma separated values">CSV</abbr>)</a>
&emsp;

View File

@@ -50,7 +50,7 @@
{{ ajax_block(partials, updates_url, 'status', finished=finished) }}
{% endif %}
{% if current_user.has_permissions(ServicePermission.SEND_MESSAGES) and current_user.has_permissions('view_activity') and template.template_type == 'sms' and can_receive_inbound %}
{% if current_user.has_permissions(ServicePermission.SEND_MESSAGES) and current_user.has_permissions(ServicePermission.VIEW_ACTIVITY) and template.template_type == 'sms' and can_receive_inbound %}
<p>
<a class="usa-link" href="{{ url_for('.conversation', service_id=current_service.id, notification_id=notification_id, _anchor='n{}'.format(notification_id)) }}">See all text messages sent to this phone number</a>
</p>

View File

@@ -1,4 +1,4 @@
{% extends "base.html" %}
{% extends "views/platform-admin/_base_template.html" %}
{% from "components/page-header.html" import page_header %}
{% from "components/page-footer.html" import page_footer %}
{% from "components/form.html" import form_wrapper %}
@@ -7,31 +7,11 @@
New organization
{% endblock %}
{% block main %}
<div class="govuk-width-container">
<div class="navigation-service usa-breadcrumb">
<a href="{{ url_for('.organizations') }}" class="usa-link navigation-service usa-breadcrumb__link usa-breadcrumb-back-to">All organizations</a>
<a href="{{ url_for('main.choose_account') }}" class="usa-link navigation-service usa-breadcrumb-switch">Switch service</a>
</div>
<div class="grid-row">
<div class="grid-col-3">
&nbsp;
</div>
<div class="grid-col-9">
<main class="govuk-main-wrapper column-main" id="main-content" role="main" >
{% block beforeContent %}{% endblock %}
{% block content %}
{{ page_header('New organization') }}
{% call form_wrapper() %}
{{ form.name }}
{{ form.organization_type }}
{{ page_footer('Save') }}
{% endcall %}
{% endblock %}
</main>
</div>
</div>
</div>
{% block platform_admin_content %}
{{ page_header('New organization') }}
{% call form_wrapper() %}
{{ form.name }}
{{ form.organization_type }}
{{ page_footer('Save') }}
{% endcall %}
{% endblock %}

View File

@@ -78,7 +78,7 @@
{% endset %}
{# create the item config now to include the label content -#}
{# TODO: "attributes": { "aria-describedby": item.id ~ "-hint" } needs to be added but govuk-frontend-jinja doesn't
{# TODO: "attributes": { "aria-describedby": item.id ~ "-hint" } needs to be added but USWDS framework doesn't
currently support this -#}
{% set checkbox_config = {
"html": label_content,

View File

@@ -4,18 +4,21 @@ from app.enums import ServicePermission
permission_mappings = {
# TODO: consider turning off email-sending permissions during SMS pilot
ServicePermission.SEND_MESSAGES: [ServicePermission.SEND_TEXTS, "send_emails"],
ServicePermission.SEND_MESSAGES: [ServicePermission.SEND_TEXTS, ServicePermission.SEND_EMAILS],
ServicePermission.MANAGE_TEMPLATES: [ServicePermission.MANAGE_TEMPLATES],
ServicePermission.MANAGE_SERVICE: ["manage_users", "manage_settings"],
ServicePermission.MANAGE_SERVICE: [
ServicePermission.MANAGE_USERS,
"manage_settings",
],
"manage_api_keys": ["manage_api_keys"],
"view_activity": ["view_activity"],
ServicePermission.VIEW_ACTIVITY: [ServicePermission.VIEW_ACTIVITY],
}
all_ui_permissions = set(permission_mappings.keys())
all_db_permissions = set(chain(*permission_mappings.values()))
permission_options = (
("view_activity", "See dashboard"),
(ServicePermission.VIEW_ACTIVITY, "See dashboard"),
(ServicePermission.SEND_MESSAGES, "Send messages"),
(ServicePermission.MANAGE_TEMPLATES, "Add and edit templates"),
(ServicePermission.MANAGE_SERVICE, "Manage settings, team and usage"),