merge from main

This commit is contained in:
Kenneth Kehl
2024-03-01 13:50:09 -08:00
140 changed files with 8031 additions and 5017 deletions

View File

@@ -13,12 +13,9 @@ from app.dao.service_inbound_api_dao import (
reset_service_inbound_api,
save_service_inbound_api,
)
from app.enums import CallbackType
from app.errors import InvalidRequest, register_errors
from app.models import (
DELIVERY_STATUS_CALLBACK_TYPE,
ServiceCallbackApi,
ServiceInboundApi,
)
from app.models import ServiceCallbackApi, ServiceInboundApi
from app.schema_validation import validate
from app.service.service_callback_api_schema import (
create_service_callback_api_schema,
@@ -90,7 +87,7 @@ def create_service_callback_api(service_id):
data = request.get_json()
validate(data, create_service_callback_api_schema)
data["service_id"] = service_id
data["callback_type"] = DELIVERY_STATUS_CALLBACK_TYPE
data["callback_type"] = CallbackType.DELIVERY_STATUS
callback_api = ServiceCallbackApi(**data)
try:
save_service_callback_api(callback_api)

View File

@@ -73,8 +73,9 @@ from app.dao.services_dao import (
)
from app.dao.templates_dao import dao_get_template_by_id
from app.dao.users_dao import get_user_by_id
from app.enums import KeyType
from app.errors import InvalidRequest, register_errors
from app.models import KEY_TYPE_NORMAL, EmailBranding, Permission, Service
from app.models import EmailBranding, Permission, Service
from app.notifications.process_notifications import (
persist_notification,
send_notification_to_queue,
@@ -638,7 +639,7 @@ def get_detailed_services(
@service_blueprint.route("/<uuid:service_id>/guest-list", methods=["GET"])
def get_guest_list(service_id):
from app.models import EMAIL_TYPE, MOBILE_TYPE
from app.enums import RecipientType
service = dao_fetch_service_by_id(service_id)
@@ -648,10 +649,14 @@ def get_guest_list(service_id):
guest_list = dao_fetch_service_guest_list(service.id)
return jsonify(
email_addresses=[
item.recipient for item in guest_list if item.recipient_type == EMAIL_TYPE
item.recipient
for item in guest_list
if item.recipient_type == RecipientType.EMAIL
],
phone_numbers=[
item.recipient for item in guest_list if item.recipient_type == MOBILE_TYPE
item.recipient
for item in guest_list
if item.recipient_type == RecipientType.MOBILE
],
)
@@ -783,7 +788,7 @@ def verify_reply_to_email_address(service_id):
personalisation="",
notification_type=template.template_type,
api_key_id=None,
key_type=KEY_TYPE_NORMAL,
key_type=KeyType.NORMAL,
reply_to_text=notify_service.get_default_reply_to_email_address(),
)

View File

@@ -6,7 +6,7 @@ from app.dao.service_sms_sender_dao import dao_get_service_sms_senders_by_id
from app.dao.services_dao import dao_fetch_service_by_id
from app.dao.templates_dao import dao_get_template_by_id_and_service_id
from app.dao.users_dao import get_user_by_id
from app.models import EMAIL_TYPE, KEY_TYPE_NORMAL, PRIORITY, SMS_TYPE
from app.enums import KeyType, NotificationType, TemplateProcessType
from app.notifications.process_notifications import (
persist_notification,
send_notification_to_queue,
@@ -45,11 +45,11 @@ def send_one_off_notification(service_id, post_data):
validate_template(template.id, personalisation, service, template.template_type)
check_service_over_total_message_limit(KEY_TYPE_NORMAL, service)
check_service_over_total_message_limit(KeyType.NORMAL, service)
validate_and_format_recipient(
send_to=post_data["to"],
key_type=KEY_TYPE_NORMAL,
key_type=KeyType.NORMAL,
service=service,
notification_type=template.template_type,
allow_guest_list_recipients=False,
@@ -73,14 +73,18 @@ def send_one_off_notification(service_id, post_data):
personalisation=personalisation,
notification_type=template.template_type,
api_key_id=None,
key_type=KEY_TYPE_NORMAL,
key_type=KeyType.NORMAL,
created_by_id=post_data["created_by"],
reply_to_text=reply_to,
reference=create_one_off_reference(template.template_type),
client_reference=client_reference,
)
queue_name = QueueNames.PRIORITY if template.process_type == PRIORITY else None
queue_name = (
QueueNames.PRIORITY
if template.process_type == TemplateProcessType.PRIORITY
else None
)
send_notification_to_queue(
notification=notification,
@@ -94,10 +98,10 @@ def get_reply_to_text(notification_type, sender_id, service, template):
reply_to = None
if sender_id:
try:
if notification_type == EMAIL_TYPE:
if notification_type == NotificationType.EMAIL:
message = "Reply to email address not found"
reply_to = dao_get_reply_to_by_id(service.id, sender_id).email_address
elif notification_type == SMS_TYPE:
elif notification_type == NotificationType.SMS:
message = "SMS sender not found"
reply_to = dao_get_service_sms_senders_by_id(
service.id, sender_id

View File

@@ -6,7 +6,7 @@ from app.dao.services_dao import (
dao_fetch_service_by_id,
)
from app.dao.templates_dao import dao_get_template_by_id
from app.models import EMAIL_TYPE, KEY_TYPE_NORMAL
from app.enums import KeyType, TemplateType
from app.notifications.process_notifications import (
persist_notification,
send_notification_to_queue,
@@ -29,13 +29,13 @@ def send_notification_to_service_users(
template_id=template.id,
template_version=template.version,
recipient=user.email_address
if template.template_type == EMAIL_TYPE
if template.template_type == TemplateType.EMAIL
else user.mobile_number,
service=notify_service,
personalisation=personalisation,
notification_type=template.template_type,
api_key_id=None,
key_type=KEY_TYPE_NORMAL,
key_type=KeyType.NORMAL,
reply_to_text=notify_service.get_default_reply_to_email_address(),
)
send_notification_to_queue(notification, queue=QueueNames.NOTIFY)

View File

@@ -1,3 +1,5 @@
from app.enums import NotificationType
add_service_data_retention_request = {
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "POST service data retention schema",
@@ -5,7 +7,7 @@ add_service_data_retention_request = {
"type": "object",
"properties": {
"days_of_retention": {"type": "integer"},
"notification_type": {"enum": ["sms", "email"]},
"notification_type": {"enum": [NotificationType.SMS, NotificationType.EMAIL]},
},
"required": ["days_of_retention", "notification_type"],
}

View File

@@ -2,7 +2,7 @@ from collections import defaultdict
from datetime import datetime
from app.dao.date_util import get_months_for_financial_year
from app.models import NOTIFICATION_STATUS_TYPES, NOTIFICATION_TYPES
from app.enums import KeyType, NotificationStatus, StatisticsType, TemplateType
def format_statistics(statistics):
@@ -23,15 +23,15 @@ def format_admin_stats(statistics):
counts = create_stats_dict()
for row in statistics:
if row.key_type == "test":
if row.key_type == KeyType.TEST:
counts[row.notification_type]["test-key"] += row.count
else:
counts[row.notification_type]["total"] += row.count
if row.status in (
"technical-failure",
"permanent-failure",
"temporary-failure",
"virus-scan-failed",
NotificationStatus.TECHNICAL_FAILURE,
NotificationStatus.PERMANENT_FAILURE,
NotificationStatus.TEMPORARY_FAILURE,
NotificationStatus.VIRUS_SCAN_FAILED,
):
counts[row.notification_type]["failures"][row.status] += row.count
@@ -40,17 +40,17 @@ def format_admin_stats(statistics):
def create_stats_dict():
stats_dict = {}
for template in NOTIFICATION_TYPES:
for template in (TemplateType.SMS, TemplateType.EMAIL):
stats_dict[template] = {}
for status in ("total", "test-key"):
stats_dict[template][status] = 0
stats_dict[template]["failures"] = {
"technical-failure": 0,
"permanent-failure": 0,
"temporary-failure": 0,
"virus-scan-failed": 0,
NotificationStatus.TECHNICAL_FAILURE: 0,
NotificationStatus.PERMANENT_FAILURE: 0,
NotificationStatus.TEMPORARY_FAILURE: 0,
NotificationStatus.VIRUS_SCAN_FAILED: 0,
}
return stats_dict
@@ -68,7 +68,7 @@ def format_monthly_template_notification_stats(year, rows):
stats[formatted_month][str(row.template_id)] = {
"name": row.name,
"type": row.template_type,
"counts": dict.fromkeys(NOTIFICATION_STATUS_TYPES, 0),
"counts": dict.fromkeys(list(NotificationStatus), 0),
}
stats[formatted_month][str(row.template_id)]["counts"][row.status] += row.count
@@ -77,25 +77,25 @@ def format_monthly_template_notification_stats(year, rows):
def create_zeroed_stats_dicts():
return {
template_type: {status: 0 for status in ("requested", "delivered", "failed")}
for template_type in NOTIFICATION_TYPES
template_type: {status: 0 for status in StatisticsType}
for template_type in (TemplateType.SMS, TemplateType.EMAIL)
}
def _update_statuses_from_row(update_dict, row):
if row.status != "cancelled":
update_dict["requested"] += row.count
if row.status in ("delivered", "sent"):
update_dict["delivered"] += row.count
if row.status != NotificationStatus.CANCELLED:
update_dict[StatisticsType.REQUESTED] += row.count
if row.status in (NotificationStatus.DELIVERED, NotificationStatus.SENT):
update_dict[StatisticsType.DELIVERED] += row.count
elif row.status in (
"failed",
"technical-failure",
"temporary-failure",
"permanent-failure",
"validation-failed",
"virus-scan-failed",
NotificationStatus.FAILED,
NotificationStatus.TECHNICAL_FAILURE,
NotificationStatus.TEMPORARY_FAILURE,
NotificationStatus.PERMANENT_FAILURE,
NotificationStatus.VALIDATION_FAILED,
NotificationStatus.VIRUS_SCAN_FAILED,
):
update_dict["failed"] += row.count
update_dict[StatisticsType.FAILURE] += row.count
def create_empty_monthly_notification_status_stats_dict(year):
@@ -103,7 +103,8 @@ def create_empty_monthly_notification_status_stats_dict(year):
# nested dicts - data[month][template type][status] = count
return {
start.strftime("%Y-%m"): {
template_type: defaultdict(int) for template_type in NOTIFICATION_TYPES
template_type: defaultdict(int)
for template_type in (TemplateType.SMS, TemplateType.EMAIL)
}
for start in utc_month_starts
}

View File

@@ -3,14 +3,8 @@ import itertools
from notifications_utils.recipients import allowed_to_send_to
from app.dao.services_dao import dao_fetch_service_by_id
from app.models import (
EMAIL_TYPE,
KEY_TYPE_NORMAL,
KEY_TYPE_TEAM,
KEY_TYPE_TEST,
MOBILE_TYPE,
ServiceGuestList,
)
from app.enums import KeyType, RecipientType
from app.models import ServiceGuestList
def get_recipients_from_request(request_json, key, type):
@@ -21,8 +15,12 @@ def get_guest_list_objects(service_id, request_json):
return [
ServiceGuestList.from_string(service_id, type, recipient)
for type, recipient in (
get_recipients_from_request(request_json, "phone_numbers", MOBILE_TYPE)
+ get_recipients_from_request(request_json, "email_addresses", EMAIL_TYPE)
get_recipients_from_request(
request_json, "phone_numbers", RecipientType.MOBILE
)
+ get_recipients_from_request(
request_json, "email_addresses", RecipientType.EMAIL
)
)
]
@@ -30,10 +28,10 @@ def get_guest_list_objects(service_id, request_json):
def service_allowed_to_send_to(
recipient, service, key_type, allow_guest_list_recipients=True
):
if key_type == KEY_TYPE_TEST:
if key_type == KeyType.TEST:
return True
if key_type == KEY_TYPE_NORMAL and not service.restricted:
if key_type == KeyType.NORMAL and not service.restricted:
return True
# Revert back to the ORM model here so we can get some things which
@@ -47,8 +45,8 @@ def service_allowed_to_send_to(
member.recipient for member in service.guest_list if allow_guest_list_recipients
]
if (key_type == KEY_TYPE_NORMAL and service.restricted) or (
key_type == KEY_TYPE_TEAM
if (key_type == KeyType.NORMAL and service.restricted) or (
key_type == KeyType.TEAM
):
return allowed_to_send_to(
recipient, itertools.chain(team_members, guest_list_members)