Merge pull request #2753 from GSA/2721-create-enums-and-replace-hardcoded-status-strings-with-enums-3

Replace send_messages and manage_service strings with enum type PART 3
This commit is contained in:
ccostino
2025-07-17 17:48:28 -04:00
committed by GitHub
41 changed files with 249 additions and 192 deletions

View File

@@ -359,6 +359,11 @@ def init_app(application):
def _attach_current_user():
return {"current_user": current_user}
@application.context_processor
def _attach_enums():
from app.enums import ServicePermission
return {"ServicePermission": ServicePermission}
@application.context_processor
def _nav_selected():
return navigation

View File

@@ -69,6 +69,12 @@ class JobStatus(StrEnum):
SENT_TO_DVLA = "sent to dvla"
class ServicePermission(StrEnum):
SEND_MESSAGES = "send_messages"
MANAGE_SERVICE = "manage_service"
MANAGE_TEMPLATES = "manage_templates"
class InvitedUserStatus(StrEnum):
ACCEPTED = "accepted"
CANCELLED = "cancelled"

View File

@@ -2,6 +2,7 @@ from flask import jsonify, redirect, render_template, session, url_for
from flask_login import current_user
from app import current_service, notification_api_client, service_api_client
from app.enums import ServicePermission
from app.main import main
from app.main.forms import SearchByNameForm
from app.models.template_list import TemplateList
@@ -45,7 +46,7 @@ def conversation_updates(service_id, notification_id):
@main.route(
"/services/<uuid:service_id>/conversation/<uuid:notification_id>/reply-with/from-folder/<uuid:from_folder>"
)
@user_has_permissions("send_messages")
@user_has_permissions(ServicePermission.SEND_MESSAGES)
def conversation_reply(
service_id,
notification_id,
@@ -69,7 +70,7 @@ def conversation_reply(
@main.route(
"/services/<uuid:service_id>/conversation/<uuid:notification_id>/reply-with/<uuid:template_id>"
)
@user_has_permissions("send_messages")
@user_has_permissions(ServicePermission.SEND_MESSAGES)
def conversation_reply_with_template(
service_id,
notification_id,

View File

@@ -14,7 +14,7 @@ from app import (
service_api_client,
template_statistics_client,
)
from app.enums import JobStatus, NotificationStatus
from app.enums import JobStatus, NotificationStatus, ServicePermission
from app.main import main
from app.main.views.user_profile import set_timezone
from app.statistics_utils import get_formatted_percentage
@@ -24,7 +24,7 @@ from app.utils.user import user_has_permissions
@main.route("/services/<uuid:service_id>/dashboard")
@user_has_permissions("view_activity", "send_messages")
@user_has_permissions("view_activity", ServicePermission.SEND_MESSAGES)
def old_service_dashboard(service_id):
return redirect(url_for(".service_dashboard", service_id=service_id))
@@ -222,7 +222,7 @@ def template_usage(service_id):
@main.route("/services/<uuid:service_id>/usage")
@user_has_permissions("manage_service", allow_org_user=True)
@user_has_permissions(ServicePermission.MANAGE_SERVICE, allow_org_user=True)
def usage(service_id):
year, current_financial_year = requested_and_current_financial_year(request)

View File

@@ -4,13 +4,14 @@ from operator import attrgetter
from flask import render_template, request
from app import current_service, format_date_numeric
from app.enums import ServicePermission
from app.main import main
from app.models.event import APIKeyEvent, APIKeyEvents, ServiceEvents
from app.utils.user import user_has_permissions
@main.route("/services/<uuid:service_id>/history")
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
def history(service_id):
events = _get_events(current_service.id, request.args.get("selected"))

View File

@@ -23,7 +23,7 @@ from app import (
notification_api_client,
service_api_client,
)
from app.enums import JobStatus, NotificationStatus
from app.enums import JobStatus, NotificationStatus, ServicePermission
from app.formatters import get_time_left, message_count_noun
from app.main import main
from app.main.forms import SearchNotificationsForm
@@ -106,7 +106,7 @@ def view_job_csv(service_id, job_id):
@main.route("/services/<uuid:service_id>/jobs/<uuid:job_id>", methods=["POST"])
@user_has_permissions("send_messages")
@user_has_permissions(ServicePermission.SEND_MESSAGES)
def cancel_job(service_id, job_id):
Job.from_id(job_id, service_id=service_id).cancel()
return redirect(url_for("main.service_dashboard", service_id=service_id))

View File

@@ -2,6 +2,7 @@ from flask import abort, flash, redirect, render_template, request, session, url
from flask_login import current_user
from app import current_service, service_api_client
from app.enums import ServicePermission
from app.event_handlers import (
create_cancel_user_invite_to_service_event,
create_email_change_event,
@@ -43,7 +44,7 @@ def manage_users(service_id):
@main.route(
"/services/<uuid:service_id>/users/invite/<uuid:user_id>", methods=["GET", "POST"]
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
def invite_user(service_id, user_id=None):
form_class = InviteUserForm
form = form_class(
@@ -113,7 +114,7 @@ def invite_user(service_id, user_id=None):
@main.route("/services/<uuid:service_id>/users/<uuid:user_id>", methods=["GET", "POST"])
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
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)
@@ -164,7 +165,7 @@ def edit_user_permissions(service_id, user_id):
@main.route("/services/<uuid:service_id>/users/<uuid:user_id>/delete", methods=["POST"])
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
def remove_user_from_service(service_id, user_id):
try:
service_api_client.remove_user_from_service(service_id, user_id)
@@ -187,7 +188,7 @@ def remove_user_from_service(service_id, user_id):
"/services/<uuid:service_id>/users/<uuid:user_id>/edit-email",
methods=["GET", "POST"],
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
def edit_user_email(service_id, user_id):
user = current_service.get_team_member(user_id)
user_email = user.email_address
@@ -220,7 +221,7 @@ def edit_user_email(service_id, user_id):
"/services/<uuid:service_id>/users/<uuid:user_id>/edit-email/confirm",
methods=["GET", "POST"],
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
def confirm_edit_user_email(service_id, user_id):
user = current_service.get_team_member(user_id)
session_key = "team_member_email_change-{}".format(user_id)
@@ -258,7 +259,7 @@ def confirm_edit_user_email(service_id, user_id):
"/services/<uuid:service_id>/users/<uuid:user_id>/edit-mobile-number",
methods=["GET", "POST"],
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
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)
@@ -288,7 +289,7 @@ def edit_user_mobile_number(service_id, user_id):
"/services/<uuid:service_id>/users/<uuid:user_id>/edit-mobile-number/confirm",
methods=["GET", "POST"],
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
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:
@@ -326,7 +327,7 @@ def confirm_edit_user_mobile_number(service_id, user_id):
"/services/<uuid:service_id>/cancel-invited-user/<uuid:invited_user_id>",
methods=["GET"],
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
def cancel_invited_user(service_id, invited_user_id):
current_service.cancel_invite(invited_user_id)
@@ -345,7 +346,7 @@ def cancel_invited_user(service_id, invited_user_id):
"/services/<uuid:service_id>/resend-invite/<uuid:invited_user_id>",
methods=["GET"],
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
def resend_invite(service_id, invited_user_id):
current_service.resend_invite(invited_user_id)

View File

@@ -12,6 +12,7 @@ from flask import (
)
from app import current_service, job_api_client, notification_api_client
from app.enums import ServicePermission
from app.main import main
from app.notify_client.api_key_api_client import KEY_TYPE_TEST
from app.utils import (
@@ -27,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", "send_messages")
@user_has_permissions("view_activity", ServicePermission.SEND_MESSAGES)
def view_notification(service_id, notification_id, error_message=None):
if error_message:
flash(error_message)
@@ -100,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", "send_messages")
@user_has_permissions("view_activity", ServicePermission.SEND_MESSAGES)
def view_notification_updates(service_id, notification_id):
return jsonify(
**get_single_notification_partials(

View File

@@ -27,6 +27,7 @@ from app import (
notification_api_client,
service_api_client,
)
from app.enums import ServicePermission
from app.main import main
from app.main.forms import (
ChooseTimeForm,
@@ -94,7 +95,7 @@ def get_example_csv_rows(template, use_example_as_example=True, submitted_fields
@main.route(
"/services/<uuid:service_id>/send/<uuid:template_id>/csv", methods=["GET", "POST"]
)
@user_has_permissions("send_messages", restrict_admin_usage=True)
@user_has_permissions(ServicePermission.SEND_MESSAGES, restrict_admin_usage=True)
def send_messages(service_id, template_id):
notification_count = service_api_client.get_notification_count(service_id)
remaining_messages = current_service.message_limit - notification_count
@@ -189,7 +190,9 @@ def send_messages(service_id, template_id):
@main.route("/services/<uuid:service_id>/send/<uuid:template_id>.csv", methods=["GET"])
@user_has_permissions("send_messages", "manage_templates")
@user_has_permissions(
ServicePermission.SEND_MESSAGES, ServicePermission.MANAGE_TEMPLATES
)
def get_example_csv(service_id, template_id):
template = get_template(
service_api_client.get_service_template(service_id, template_id)["data"],
@@ -214,7 +217,7 @@ def get_example_csv(service_id, template_id):
"/services/<uuid:service_id>/send/<uuid:template_id>/set-sender",
methods=["GET", "POST"],
)
@user_has_permissions("send_messages", restrict_admin_usage=True)
@user_has_permissions(ServicePermission.SEND_MESSAGES, restrict_admin_usage=True)
def set_sender(service_id, template_id):
session["sender_id"] = None
redirect_to_one_off = redirect(
@@ -343,7 +346,7 @@ def get_sender_details(service_id, template_type):
@main.route("/services/<uuid:service_id>/send/<uuid:template_id>/one-off")
@user_has_permissions("send_messages", restrict_admin_usage=True)
@user_has_permissions(ServicePermission.SEND_MESSAGES, restrict_admin_usage=True)
def send_one_off(service_id, template_id):
session["recipient"] = None
session["placeholders"] = {}
@@ -387,7 +390,7 @@ def get_notification_check_endpoint(service_id, template):
"/services/<uuid:service_id>/send/<uuid:template_id>/one-off/step-<int:step_index>",
methods=["GET", "POST"],
)
@user_has_permissions("send_messages", restrict_admin_usage=True)
@user_has_permissions(ServicePermission.SEND_MESSAGES, restrict_admin_usage=True)
def send_one_off_step(service_id, template_id, step_index):
if {"recipient", "placeholders"} - set(session.keys()):
return redirect(
@@ -647,7 +650,7 @@ def _check_messages(service_id, template_id, upload_id, preview_row, **kwargs):
"/services/<uuid:service_id>/<uuid:template_id>/check/<uuid:upload_id>/row-<int:row_index>",
methods=["GET"],
)
@user_has_permissions("send_messages", restrict_admin_usage=True)
@user_has_permissions(ServicePermission.SEND_MESSAGES, restrict_admin_usage=True)
def check_messages(service_id, template_id, upload_id, row_index=2):
data = _check_messages(service_id, template_id, upload_id, row_index)
data["allowed_file_extensions"] = Spreadsheet.ALLOWED_FILE_EXTENSIONS
@@ -691,7 +694,7 @@ def check_messages(service_id, template_id, upload_id, row_index=2):
"/services/<uuid:service_id>/<uuid:template_id>/check/<uuid:upload_id>/preview/row-<int:row_index>",
methods=["POST"],
)
@user_has_permissions("send_messages", restrict_admin_usage=True)
@user_has_permissions(ServicePermission.SEND_MESSAGES, restrict_admin_usage=True)
def preview_job(service_id, template_id, upload_id, row_index=2):
session["scheduled_for"] = request.form.get("scheduled_for", "")
data = _check_messages(
@@ -706,7 +709,7 @@ def preview_job(service_id, template_id, upload_id, row_index=2):
@main.route("/services/<uuid:service_id>/start-job/<uuid:upload_id>", methods=["POST"])
@user_has_permissions("send_messages", restrict_admin_usage=True)
@user_has_permissions(ServicePermission.SEND_MESSAGES, restrict_admin_usage=True)
def start_job(service_id, upload_id):
scheduled_for = session.pop("scheduled_for", None)
job_api_client.create_job(
@@ -843,7 +846,9 @@ def get_skip_link(step_index, template):
and step_index == 0
and template.template_type in ("sms", "email")
and not (template.template_type == "sms" and current_user.mobile_number is None)
and current_user.has_permissions("manage_templates", "manage_service")
and current_user.has_permissions(
ServicePermission.MANAGE_TEMPLATES, ServicePermission.MANAGE_SERVICE
)
):
return (
"Use my {}".format(first_column_headings[template.template_type][0]),
@@ -859,7 +864,7 @@ def get_skip_link(step_index, template):
"/services/<uuid:service_id>/template/<uuid:template_id>/one-off/send-to-myself",
methods=["GET"],
)
@user_has_permissions("send_messages", restrict_admin_usage=True)
@user_has_permissions(ServicePermission.SEND_MESSAGES, restrict_admin_usage=True)
def send_one_off_to_myself(service_id, template_id):
current_app.logger.info("Send one off to myself")
try:
@@ -896,7 +901,7 @@ def send_one_off_to_myself(service_id, template_id):
"/services/<uuid:service_id>/template/<uuid:template_id>/notification/check",
methods=["GET"],
)
@user_has_permissions("send_messages", restrict_admin_usage=True)
@user_has_permissions(ServicePermission.SEND_MESSAGES, restrict_admin_usage=True)
def check_notification(service_id, template_id):
return render_template(
"views/notifications/check.html",
@@ -978,7 +983,7 @@ def get_template_error_dict(exception):
"/services/<uuid:service_id>/template/<uuid:template_id>/notification/check/preview",
methods=["POST"],
)
@user_has_permissions("send_messages", restrict_admin_usage=True)
@user_has_permissions(ServicePermission.SEND_MESSAGES, restrict_admin_usage=True)
def preview_notification(service_id, template_id):
recipient = get_recipient()
if not recipient:
@@ -1010,7 +1015,7 @@ def preview_notification(service_id, template_id):
"/services/<uuid:service_id>/template/<uuid:template_id>/notification/check",
methods=["POST"],
)
@user_has_permissions("send_messages", restrict_admin_usage=True)
@user_has_permissions(ServicePermission.SEND_MESSAGES, restrict_admin_usage=True)
def send_notification(service_id, template_id):
recipient = get_recipient()

View File

@@ -21,7 +21,7 @@ from app import (
organizations_client,
service_api_client,
)
from app.enums import VerificationStatus
from app.enums import ServicePermission, VerificationStatus
from app.event_handlers import (
create_archive_service_event,
create_resume_service_event,
@@ -70,7 +70,7 @@ PLATFORM_ADMIN_SERVICE_PERMISSIONS = OrderedDict(
@main.route("/services/<uuid:service_id>/service-settings")
@user_has_permissions("manage_service", "manage_api_keys")
@user_has_permissions(ServicePermission.MANAGE_SERVICE, "manage_api_keys")
def service_settings(service_id):
return render_template(
"views/service-settings.html",
@@ -81,7 +81,7 @@ def service_settings(service_id):
@main.route(
"/services/<uuid:service_id>/service-settings/name", methods=["GET", "POST"]
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
def service_name_change(service_id):
form = RenameServiceForm(name=current_service.name)
@@ -195,7 +195,7 @@ def service_set_permission(service_id, permission):
@main.route(
"/services/<uuid:service_id>/service-settings/archive", methods=["GET", "POST"]
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
def archive_service(service_id):
if not current_service.active or not (
current_service.trial_mode or current_user.platform_admin
@@ -268,7 +268,7 @@ def resume_service(service_id):
"/services/<uuid:service_id>/service-settings/send-files-by-email",
methods=["GET", "POST"],
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
def send_files_by_email_contact_details(service_id):
form = ServiceContactDetailsForm()
contact_details = None
@@ -298,7 +298,7 @@ def send_files_by_email_contact_details(service_id):
@main.route(
"/services/<uuid:service_id>/service-settings/set-reply-to-email", methods=["GET"]
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
def service_set_reply_to_email(service_id):
return redirect(url_for(".service_email_reply_to", service_id=service_id))
@@ -306,7 +306,7 @@ def service_set_reply_to_email(service_id):
@main.route(
"/services/<uuid:service_id>/service-settings/email-reply-to", methods=["GET"]
)
@user_has_permissions("manage_service", "manage_api_keys")
@user_has_permissions(ServicePermission.MANAGE_SERVICE, "manage_api_keys")
def service_email_reply_to(service_id):
return render_template("views/service-settings/email_reply_to.html")
@@ -315,7 +315,7 @@ def service_email_reply_to(service_id):
"/services/<uuid:service_id>/service-settings/email-reply-to/add",
methods=["GET", "POST"],
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
def service_add_email_reply_to(service_id):
form = ServiceReplyToEmailForm()
first_email_address = current_service.count_email_reply_to_addresses == 0
@@ -359,7 +359,7 @@ def service_add_email_reply_to(service_id):
"/services/<uuid:service_id>/service-settings/email-reply-to/<uuid:notification_id>/verify",
methods=["GET", "POST"],
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
def service_verify_reply_to_address(service_id, notification_id):
replace = request.args.get("replace", False)
is_default = request.args.get("is_default", False)
@@ -379,7 +379,7 @@ def service_verify_reply_to_address(service_id, notification_id):
@main.route(
"/services/<uuid:service_id>/service-settings/email-reply-to/<uuid:notification_id>/verify.json"
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
def service_verify_reply_to_address_updates(service_id, notification_id):
return jsonify(
**get_service_verify_reply_to_address_partials(service_id, notification_id)
@@ -456,7 +456,7 @@ def get_service_verify_reply_to_address_partials(service_id, notification_id):
methods=["GET"],
endpoint="service_confirm_delete_email_reply_to",
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
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(
@@ -525,7 +525,7 @@ def service_edit_email_reply_to(service_id, reply_to_email_id):
"/services/<uuid:service_id>/service-settings/email-reply-to/<uuid:reply_to_email_id>/delete",
methods=["POST"],
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
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,
@@ -538,7 +538,7 @@ def service_delete_email_reply_to(service_id, reply_to_email_id):
"/services/<uuid:service_id>/service-settings/set-inbound-number",
methods=["GET", "POST"],
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
def service_set_inbound_number(service_id):
available_inbound_numbers = (
inbound_number_client.get_available_inbound_sms_numbers()
@@ -571,7 +571,7 @@ def service_set_inbound_number(service_id):
@main.route(
"/services/<uuid:service_id>/service-settings/sms-prefix", methods=["GET", "POST"]
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
def service_set_sms_prefix(service_id):
form = SMSPrefixForm(enabled=current_service.prefix_sms)
@@ -590,7 +590,7 @@ def service_set_sms_prefix(service_id):
"/services/<uuid:service_id>/service-settings/set-international-sms",
methods=["GET", "POST"],
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
def service_set_international_sms(service_id):
form = ServiceOnOffSettingForm(
"Send text messages to international phone numbers",
@@ -611,7 +611,7 @@ def service_set_international_sms(service_id):
@main.route(
"/services/<uuid:service_id>/service-settings/set-inbound-sms", methods=["GET"]
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
def service_set_inbound_sms(service_id):
return render_template(
"views/service-settings/set-inbound-sms.html",
@@ -622,7 +622,7 @@ def service_set_inbound_sms(service_id):
"/services/<uuid:service_id>/service-settings/set-<channel>",
methods=["GET", "POST"],
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
def service_set_channel(service_id, channel):
if channel not in {"email", "sms"}:
abort(404)
@@ -647,7 +647,7 @@ def service_set_channel(service_id, channel):
@main.route(
"/services/<uuid:service_id>/service-settings/set-auth-type", methods=["GET"]
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
def service_set_auth_type(service_id):
return render_template(
"views/service-settings/set-auth-type.html",
@@ -655,7 +655,7 @@ def service_set_auth_type(service_id):
@main.route("/services/<uuid:service_id>/service-settings/sms-sender", methods=["GET"])
@user_has_permissions("manage_service", "manage_api_keys")
@user_has_permissions(ServicePermission.MANAGE_SERVICE, "manage_api_keys")
def service_sms_senders(service_id):
return render_template(
"views/service-settings/sms-senders.html",
@@ -666,7 +666,7 @@ def service_sms_senders(service_id):
"/services/<uuid:service_id>/service-settings/sms-sender/add",
methods=["GET", "POST"],
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
def service_add_sms_sender(service_id):
form = ServiceSmsSenderForm()
first_sms_sender = current_service.count_sms_senders == 0
@@ -694,7 +694,7 @@ def service_add_sms_sender(service_id):
methods=["GET"],
endpoint="service_confirm_delete_sms_sender",
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
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"]
@@ -732,7 +732,7 @@ def service_edit_sms_sender(service_id, sms_sender_id):
"/services/<uuid:service_id>/service-settings/sms-sender/<uuid:sms_sender_id>/delete",
methods=["POST"],
)
@user_has_permissions("manage_service")
@user_has_permissions(ServicePermission.MANAGE_SERVICE)
def service_delete_sms_sender(service_id, sms_sender_id):
service_api_client.delete_sms_sender(
service_id=current_service.id,

View File

@@ -12,6 +12,7 @@ from app import (
template_folder_api_client,
template_statistics_client,
)
from app.enums import ServicePermission
from app.formatters import character_count, message_count
from app.main import main
from app.main.forms import (
@@ -117,7 +118,7 @@ def choose_template(service_id, template_type="all", template_folder_id=None):
single_notification_channel = notification_channels[0]
if request.method == "POST" and templates_and_folders_form.validate_on_submit():
if not current_user.has_permissions("manage_templates"):
if not current_user.has_permissions(ServicePermission.MANAGE_TEMPLATES):
abort(403)
try:
return process_folder_management_form(
@@ -266,7 +267,7 @@ def _add_template_by_type(template_type, template_folder_id):
@main.route(
"/services/<uuid:service_id>/templates/copy/from-service/<uuid:from_service>/from-folder/<uuid:from_folder>"
)
@user_has_permissions("manage_templates")
@user_has_permissions(ServicePermission.MANAGE_TEMPLATES)
def choose_template_to_copy(
service_id,
from_service=None,
@@ -298,7 +299,7 @@ def choose_template_to_copy(
"/services/<uuid:service_id>/templates/copy/<uuid:template_id>",
methods=["GET", "POST"],
)
@user_has_permissions("manage_templates")
@user_has_permissions(ServicePermission.MANAGE_TEMPLATES)
def copy_template(service_id, template_id):
from_service = request.args.get("from_service")
@@ -355,7 +356,7 @@ def _get_template_copy_name(template, existing_templates):
"<template_type:notification_type>/<return_to>/<uuid:template_id>"
)
)
@user_has_permissions("manage_templates")
@user_has_permissions(ServicePermission.MANAGE_TEMPLATES)
def action_blocked(service_id, notification_type, return_to, template_id=None):
back_link = {
"add_new_template": partial(
@@ -387,7 +388,7 @@ def action_blocked(service_id, notification_type, return_to, template_id=None):
"/services/<uuid:service_id>/templates/folders/<uuid:template_folder_id>/manage",
methods=["GET", "POST"],
)
@user_has_permissions("manage_templates")
@user_has_permissions(ServicePermission.MANAGE_TEMPLATES)
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
@@ -401,7 +402,7 @@ def manage_template_folder(service_id, template_folder_id):
)
if form.validate_on_submit():
if (
current_user.has_permissions("manage_service")
current_user.has_permissions(ServicePermission.MANAGE_SERVICE)
and form.users_with_permission.all_service_users
):
users_with_permission = form.users_with_permission.data + [current_user.id]
@@ -437,7 +438,7 @@ def manage_template_folder(service_id, template_folder_id):
"/services/<uuid:service_id>/templates/folders/<uuid:template_folder_id>/delete",
methods=["GET", "POST"],
)
@user_has_permissions("manage_templates")
@user_has_permissions(ServicePermission.MANAGE_TEMPLATES)
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
@@ -502,7 +503,7 @@ def delete_template_folder(service_id, template_folder_id):
"/services/<uuid:service_id>/templates/folders/<uuid:template_folder_id>/add-<template_type:template_type>",
methods=["GET", "POST"],
)
@user_has_permissions("manage_templates")
@user_has_permissions(ServicePermission.MANAGE_TEMPLATES)
def add_service_template(service_id, template_type, template_folder_id=None):
if template_type not in current_service.available_template_types:
return redirect(
@@ -566,7 +567,7 @@ def abort_403_if_not_admin_user():
"/services/<uuid:service_id>/templates/<uuid:template_id>/edit",
methods=["GET", "POST"],
)
@user_has_permissions("manage_templates")
@user_has_permissions(ServicePermission.MANAGE_TEMPLATES)
def edit_service_template(service_id, template_id):
template = current_service.get_template_with_user_permission_or_403(
template_id, current_user
@@ -724,7 +725,7 @@ def _get_content_count_error_and_message_for_template(template):
"/services/<uuid:service_id>/templates/<uuid:template_id>/delete",
methods=["GET", "POST"],
)
@user_has_permissions("manage_templates")
@user_has_permissions(ServicePermission.MANAGE_TEMPLATES)
def delete_service_template(service_id, template_id):
template = current_service.get_template_with_user_permission_or_403(
template_id, current_user
@@ -782,7 +783,7 @@ def delete_service_template(service_id, template_id):
@main.route(
"/services/<uuid:service_id>/templates/<uuid:template_id>/redact", methods=["GET"]
)
@user_has_permissions("manage_templates")
@user_has_permissions(ServicePermission.MANAGE_TEMPLATES)
def confirm_redact_template(service_id, template_id):
template = current_service.get_template_with_user_permission_or_403(
template_id, current_user
@@ -803,7 +804,7 @@ def confirm_redact_template(service_id, template_id):
@main.route(
"/services/<uuid:service_id>/templates/<uuid:template_id>/redact", methods=["POST"]
)
@user_has_permissions("manage_templates")
@user_has_permissions(ServicePermission.MANAGE_TEMPLATES)
def redact_template(service_id, template_id):
service_api_client.redact_service_template(service_id, template_id)
@@ -842,7 +843,7 @@ def view_template_versions(service_id, template_id):
"/services/<uuid:service_id>/templates/<uuid:template_id>/set-template-sender",
methods=["GET", "POST"],
)
@user_has_permissions("manage_templates")
@user_has_permissions(ServicePermission.MANAGE_TEMPLATES)
def set_template_sender(service_id, template_id):
template = current_service.get_template_with_user_permission_or_403(
template_id, current_user

View File

@@ -1,6 +1,7 @@
from flask import abort, redirect, render_template, session
from app import current_service, current_user, service_api_client, url_for
from app.enums import ServicePermission
from app.main import main
from app.main.views.send import (
all_placeholders_in_session,
@@ -14,7 +15,7 @@ from app.utils.user import user_has_permissions
@main.route("/services/<uuid:service_id>/tour/<uuid:template_id>")
@user_has_permissions("send_messages")
@user_has_permissions(ServicePermission.SEND_MESSAGES)
def begin_tour(service_id, template_id):
db_template = current_service.get_template_with_user_permission_or_403(
template_id, current_user
@@ -47,7 +48,7 @@ def begin_tour(service_id, template_id):
"/services/<uuid:service_id>/tour/<uuid:template_id>/step-<int:step_index>",
methods=["GET", "POST"],
)
@user_has_permissions("send_messages", restrict_admin_usage=True)
@user_has_permissions(ServicePermission.SEND_MESSAGES, restrict_admin_usage=True)
def tour_step(service_id, template_id, step_index):
db_template = current_service.get_template_with_user_permission_or_403(
template_id, current_user
@@ -166,7 +167,7 @@ def _get_tour_step_back_link(service_id, template_id, step_index):
@main.route(
"/services/<uuid:service_id>/tour/<uuid:template_id>/check", methods=["GET"]
)
@user_has_permissions("send_messages", restrict_admin_usage=True)
@user_has_permissions(ServicePermission.SEND_MESSAGES, restrict_admin_usage=True)
def check_tour_notification(service_id, template_id):
db_template = current_service.get_template_with_user_permission_or_403(
template_id, current_user
@@ -223,7 +224,7 @@ def check_tour_notification(service_id, template_id):
@main.route("/services/<uuid:service_id>/end-tour/<uuid:example_template_id>")
@user_has_permissions("manage_templates")
@user_has_permissions(ServicePermission.MANAGE_TEMPLATES)
def go_to_dashboard_after_tour(service_id, example_template_id):
service_api_client.delete_service_template(service_id, example_template_id)

View File

@@ -1,6 +1,7 @@
from flask import abort, current_app
from werkzeug.utils import cached_property
from app.enums import ServicePermission
from app.models import JSONModel, SortByNameMixin
from app.models.job import ImmediateJobs, PaginatedJobs, PaginatedUploads, ScheduledJobs
from app.models.organization import Organization
@@ -175,7 +176,9 @@ class Service(JSONModel, SortByNameMixin):
[
user
for user in self.team_members
if user.has_permission_for_service(self.id, "manage_service")
if user.has_permission_for_service(
self.id, ServicePermission.MANAGE_SERVICE
)
]
)
> 1

View File

@@ -2,6 +2,8 @@ from itertools import chain
from flask import request
from app.enums import ServicePermission
class Navigation:
mapping = {}
@@ -74,7 +76,7 @@ class HeaderNavigation(Navigation):
"delete_service_template",
"edit_service_template",
"manage_template_folder",
"send_messages",
ServicePermission.SEND_MESSAGES,
"send_one_off",
"send_one_off_step",
"send_one_off_to_myself",
@@ -177,7 +179,7 @@ class MainNavigation(Navigation):
"delete_service_template",
"edit_service_template",
"manage_template_folder",
"send_messages",
ServicePermission.SEND_MESSAGES,
"send_one_off",
"send_one_off_step",
"send_one_off_to_myself",

View File

@@ -12,7 +12,7 @@
{% endif %}
{% if current_service %}
{% if current_user.has_permissions('manage_service') %}
{% if current_user.has_permissions(ServicePermission.MANAGE_SERVICE) %}
{% set secondaryNavigation = [
{"href": url_for('main.service_settings', service_id=current_service.id), "text": "Settings", "active": secondary_navigation.is_selected('settings')},
{"href": url_for('main.sign_out'), "text": "Sign out"}

View File

@@ -27,7 +27,7 @@
'messages',
) }}
{% if current_user.has_permissions('send_messages') %}
{% if current_user.has_permissions(ServicePermission.SEND_MESSAGES) %}
<p class="sms-message-reply-link">
<a class="usa-link" href="{{ url_for('.conversation_reply', service_id=current_service.id, notification_id=notification_id) }}">Send a text message to this phone number</a>
</p>

View File

@@ -16,7 +16,7 @@ Dashboard
<div class="dashboard margin-top-0 margin-bottom-2">
<h1 class="usa-sr-only">Dashboard</h1>
{% if current_user.has_permissions('manage_templates') and not current_service.all_templates %}
{% if current_user.has_permissions(ServicePermission.MANAGE_TEMPLATES) and not current_service.all_templates %}
{% include 'views/dashboard/write-first-messages.html' %}
{% endif %}
@@ -43,7 +43,7 @@ Dashboard
<div id="totalMessageTable" class="margin-0"></div>
{% include 'views/dashboard/activity-table.html' %}
{% if current_user.has_permissions('manage_service') %}{% endif %}
{% if current_user.has_permissions(ServicePermission.MANAGE_SERVICE) %}{% endif %}
{% include 'views/dashboard/most-used-templates.html' %}

View File

@@ -19,7 +19,7 @@
<h1 class="font-body-2xl margin-0">
Team members
</h1>
{% if current_user.has_permissions('manage_service') %}
{% if current_user.has_permissions(ServicePermission.MANAGE_SERVICE) %}
{{ usaButton({
"element": "a",
"text": "Invite a team member",
@@ -108,7 +108,7 @@
{% if current_user.has_permissions('manage_service') %}
{% if current_user.has_permissions(ServicePermission.MANAGE_SERVICE) %}
{% if user.status == 'pending' or user.status == 'expired' %}
<a class="user-list-edit-link usa-link padding-x-2" href="{{ url_for('.cancel_invited_user', service_id=current_service.id, invited_user_id=user.id) }}">
Cancel invitation<span class="usa-sr-only"> for {{ user.email_address }}</span>

View File

@@ -50,7 +50,7 @@
{{ ajax_block(partials, updates_url, 'status', finished=finished) }}
{% endif %}
{% if current_user.has_permissions('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('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

@@ -30,7 +30,7 @@
{{ edit_field(
'Change',
url_for('.service_name_change', service_id=current_service.id),
permissions=['manage_service'],
permissions=[ServicePermission.MANAGE_SERVICE],
suffix='service name',
)
}}
@@ -46,7 +46,7 @@
service_id=current_service.id,
channel='sms'
),
permissions=['manage_service'],
permissions=[ServicePermission.MANAGE_SERVICE],
suffix='your settings for sending text messages',
)}} #}
{% endcall %}
@@ -65,7 +65,7 @@
{{ edit_field(
'Manage',
url_for('.service_sms_senders', service_id=current_service.id),
permissions=['manage_service','manage_api_keys'],
permissions=[ServicePermission.MANAGE_SERVICE,'manage_api_keys'],
suffix='text message senders',
)
}}
@@ -78,7 +78,7 @@
{{ edit_field(
'Change',
url_for('.service_set_sms_prefix', service_id=current_service.id),
permissions=['manage_service'],
permissions=[ServicePermission.MANAGE_SERVICE],
suffix='your settings for starting text messages with service name',
)
}}
@@ -91,7 +91,7 @@
{{ edit_field(
'Change',
url_for('.service_set_international_sms', service_id=current_service.id),
permissions=['manage_service'],
permissions=[ServicePermission.MANAGE_SERVICE],
suffix='your settings for sending international text messages',
)
}}
@@ -104,7 +104,7 @@
{{ edit_field(
'Change',
url_for('.service_set_inbound_sms', service_id=current_service.id),
permissions=['manage_service'],
permissions=[ServicePermission.MANAGE_SERVICE],
suffix='your settings for receiving text messages',
)
}}
@@ -128,7 +128,7 @@
channel='email',
service_id=current_service.id
),
permissions=['manage_service'],
permissions=[ServicePermission.MANAGE_SERVICE],
suffix='your settings for sending emails',
)}}
{% endcall %}
@@ -146,7 +146,7 @@
{{ edit_field(
'Manage',
url_for('.service_email_reply_to', service_id=current_service.id),
permissions=['manage_service','manage_api_keys'],
permissions=[ServicePermission.MANAGE_SERVICE,'manage_api_keys'],
suffix='reply-to email addresses',
)
}}
@@ -158,7 +158,7 @@
{{ edit_field(
'Manage',
url_for('.send_files_by_email_contact_details', service_id=current_service.id),
permissions=['manage_service'],
permissions=[ServicePermission.MANAGE_SERVICE],
suffix='sending files by email',
)}}
{% endcall %}
@@ -178,7 +178,7 @@
</ul>
<p>
{% if current_user.has_permissions('manage_service') %}
{% if current_user.has_permissions(ServicePermission.MANAGE_SERVICE) %}
To remove these restrictions, you can send us a
<a class="usa-link" href="mailto:notify-support@gsa.gov">request to go live</a>.
{% else %}

View File

@@ -36,7 +36,7 @@
</h2>
</div>
<div class="grid-col-3">
{% if current_user.has_permissions('manage_service') %}
{% if current_user.has_permissions(ServicePermission.MANAGE_SERVICE) %}
<a class="usa-link user-list-edit-link" href="{{ url_for('.service_edit_email_reply_to', service_id =current_service.id, reply_to_email_id = item.id) }}">
Change<span class="usa-sr-only"> {{ item.email_address }}</span>
</a>
@@ -55,7 +55,7 @@
</div>
<div class="grid-row">
<div class="grid-col-12">
{% if current_user.has_permissions('manage_service') %}
{% if current_user.has_permissions(ServicePermission.MANAGE_SERVICE) %}
<div class="js-stick-at-bottom-when-scrolling">
{{ usaButton({
"element": "a",

View File

@@ -38,7 +38,7 @@
</h2>
</div>
<div class="grid-col">
{% if current_user.has_permissions('manage_service') %}
{% if current_user.has_permissions(ServicePermission.MANAGE_SERVICE) %}
<a class="usa-link user-list-edit-link" href="{{ url_for('.service_edit_sms_sender', service_id=current_service.id, sms_sender_id = item.id) }}">
Change<span class="usa-sr-only"> {{ item.sms_sender }}</span>
</a>
@@ -52,7 +52,7 @@
{% endfor %}
</div>
{% if current_user.has_permissions('manage_service') %}
{% if current_user.has_permissions(ServicePermission.MANAGE_SERVICE) %}
<div class="grid-row bottom-gutter">
<div class="grid-col-12">
{{ usaButton({

View File

@@ -8,7 +8,7 @@
<p class="hint">
This template was deleted {{ template._template.updated_at|format_datetime_relative }}.
</p>
{% elif not current_user.has_permissions('send_messages', 'manage_api_keys', 'manage_templates', 'manage_service') or not user_has_template_permission %}
{% elif not current_user.has_permissions(ServicePermission.SEND_MESSAGES, 'manage_api_keys', ServicePermission.MANAGE_TEMPLATES, ServicePermission.MANAGE_SERVICE) or not user_has_template_permission %}
<p class="top-gutter-1-3 {% if template.template_type != 'sms' %}bottom-gutter{% endif %}">
If you need to send this
{{ 1|message_count_label(template.template_type, suffix='') }}
@@ -17,12 +17,12 @@
{% else %}
<div class="grid-row margin-bottom-5">
<div class="usa-button-group">
{% if current_user.has_permissions('send_messages', restrict_admin_usage=True) %}
{% if current_user.has_permissions(ServicePermission.SEND_MESSAGES, restrict_admin_usage=True) %}
<a href="{{ url_for(".set_sender", service_id=current_service.id, template_id=template.id) }}" class="usa-button usa-pill-separate-item">
Use this template
</a>
{% endif %}
{% if current_user.has_permissions('manage_templates') %}
{% if current_user.has_permissions(ServicePermission.MANAGE_TEMPLATES) %}
<a href="{{ url_for(".edit_service_template", service_id=current_service.id, template_id=template.id) }}" class="usa-button usa-button--outline usa-pill-separate-item">
Edit this template
</a>

View File

@@ -24,7 +24,7 @@
<nav id="template-list" aria-label="Template list">
{% set checkboxes_data = [] %}
{% if not current_user.has_permissions('manage_templates') %}
{% if not current_user.has_permissions(ServicePermission.MANAGE_TEMPLATES) %}
<ul>
{% endif %}
@@ -94,7 +94,7 @@
} %}
{% set _ = checkboxes_data.append(checkbox_config) %}
{% if not current_user.has_permissions('manage_templates') %}
{% if not current_user.has_permissions(ServicePermission.MANAGE_TEMPLATES) %}
<li
class="template-list-item {%- if item.ancestors %} template-list-item-hidden-by-default {%- else %} template-list-item-without-ancestors{%- endif %}">
{{ item_link_content }}
@@ -105,11 +105,11 @@
{% endif %}
{% endfor %}
{% if not current_user.has_permissions('manage_templates') %}
{% if not current_user.has_permissions(ServicePermission.MANAGE_TEMPLATES) %}
</ul>
{% endif %}
{% if current_user.has_permissions('manage_templates') %}
{% if current_user.has_permissions(ServicePermission.MANAGE_TEMPLATES) %}
{{ templates_and_folders_form.templates_and_folders(param_extensions={
"items": checkboxes_data,
"formGroup": False

View File

@@ -17,7 +17,7 @@
{% if not templates_and_folders.templates_to_show %}
{% if current_user.has_permissions('manage_templates') %}
{% if current_user.has_permissions(ServicePermission.MANAGE_TEMPLATES) %}
<p class="bottom-gutter">
You need a template before you can send text messages.
</p>

View File

@@ -21,7 +21,7 @@
<p>
Every message starts with a template. You can change it later.
{% if current_user.has_permissions('manage_templates') %}
{% if current_user.has_permissions(ServicePermission.MANAGE_TEMPLATES) %}
You need a template before you can
{% else %}
You need to ask your service manager to add templates before you can
@@ -33,7 +33,7 @@
<div class="grid-row flex-column">
<h1 class="font-body-2xl line-height-sans-2 margin-bottom-1 margin-top-0" id="page-title">{{page_title}}</h1>
<div class="{% if current_user.has_permissions('manage_templates') %} grid-col-10 {% else %} grid-col-12 {% endif %}">
<div class="{% if current_user.has_permissions(ServicePermission.MANAGE_TEMPLATES) %} grid-col-10 {% else %} grid-col-12 {% endif %}">
<p class="margin-top-0 margin-bottom-4" id="page-description">
Every message starts with a template. To send, choose or create a template.
</p>
@@ -44,7 +44,7 @@
current_user=current_user
) }}
</div>
{% if current_user.has_permissions('manage_templates') and current_template_folder_id and user_has_template_folder_permission %}
{% if current_user.has_permissions(ServicePermission.MANAGE_TEMPLATES) and current_template_folder_id and user_has_template_folder_permission %}
<div class="grid-col-2">
<a href="{{ url_for('.manage_template_folder', service_id=current_service.id, template_folder_id=current_template_folder_id) }}" class="usa-link folder-heading-manage-link">Manage this folder<span class="usa-sr-only">Manage this folder</span></a>
</div>
@@ -63,7 +63,7 @@
<p class="usa-body margin-top-2">No templates found</p>
</div>
{% if current_user.has_permissions('manage_templates') and user_has_template_folder_permission %}
{% if current_user.has_permissions(ServicePermission.MANAGE_TEMPLATES) and user_has_template_folder_permission %}
{% call form_wrapper(
class='sticky-scroll-area',
module='template-folder-form',

View File

@@ -25,7 +25,7 @@
{{ form.name(param_extensions={
"classes": ""
}) }}
{% if current_user.has_permissions("manage_service") and form.users_with_permission.all_service_users %}
{% if current_user.has_permissions(ServicePermission.MANAGE_SERVICE) and form.users_with_permission.all_service_users %}
{{ form.users_with_permission }}
{% endif %}

View File

@@ -61,7 +61,7 @@
href="{{ url_for('.view_template_versions', service_id=current_service.id, template_id=template.id) }}">See previous versions</a>
</div>
{% endif %}
{% if current_user.has_permissions('manage_templates') and user_has_template_permission %}
{% if current_user.has_permissions(ServicePermission.MANAGE_TEMPLATES) and user_has_template_permission %}
<h2 class="margin-bottom-1 font-body-lg">More actions</h2>
<ul class="usa-list usa-list--unstyled">
{% if not template._template.archived %}

View File

@@ -7,7 +7,7 @@ from ordered_set import OrderedSet
from werkzeug.datastructures import MultiDict
from werkzeug.routing import RequestRedirect
from app.enums import NotificationStatus, NotificationType
from app.enums import NotificationStatus, NotificationType, ServicePermission
from notifications_utils.field import Field
SENDING_STATUSES = NotificationStatus.sending_statuses()
@@ -73,8 +73,10 @@ def unicode_truncate(s, length):
def should_skip_template_page(db_template):
return (
current_user.has_permissions("send_messages")
and not current_user.has_permissions("manage_templates", "manage_api_keys")
current_user.has_permissions(ServicePermission.SEND_MESSAGES)
and not current_user.has_permissions(
ServicePermission.MANAGE_TEMPLATES, "manage_api_keys"
)
and not db_template["archived"]
)

View File

@@ -1,10 +1,12 @@
from itertools import chain
from app.enums import ServicePermission
permission_mappings = {
# TODO: consider turning off email-sending permissions during SMS pilot
"send_messages": ["send_texts", "send_emails"],
"manage_templates": ["manage_templates"],
"manage_service": ["manage_users", "manage_settings"],
ServicePermission.SEND_MESSAGES: ["send_texts", "send_emails"],
ServicePermission.MANAGE_TEMPLATES: [ServicePermission.MANAGE_TEMPLATES],
ServicePermission.MANAGE_SERVICE: ["manage_users", "manage_settings"],
"manage_api_keys": ["manage_api_keys"],
"view_activity": ["view_activity"],
}
@@ -14,9 +16,9 @@ all_db_permissions = set(chain(*permission_mappings.values()))
permission_options = (
("view_activity", "See dashboard"),
("send_messages", "Send messages"),
("manage_templates", "Add and edit templates"),
("manage_service", "Manage settings, team and usage"),
(ServicePermission.SEND_MESSAGES, "Send messages"),
(ServicePermission.MANAGE_TEMPLATES, "Add and edit templates"),
(ServicePermission.MANAGE_SERVICE, "Manage settings, team and usage"),
)