mirror of
https://github.com/GSA/notifications-api.git
synced 2026-09-11 18:38:14 -04:00
merge from main and reformat
This commit is contained in:
@@ -73,6 +73,7 @@ generate-version-file: ## Generates the app version file
|
||||
.PHONY: test
|
||||
test: export NEW_RELIC_ENVIRONMENT=test
|
||||
test: ## Run tests and create coverage report
|
||||
pipenv run black .
|
||||
pipenv run flake8 .
|
||||
pipenv run isort --check-only ./app ./tests
|
||||
pipenv run coverage run -m pytest -vv --maxfail=10
|
||||
|
||||
@@ -11,10 +11,10 @@ asn1crypto = "==1.5.1"
|
||||
async-timeout = "==4.0.2"
|
||||
attrs = "==23.1.0"
|
||||
awscli = "==1.29.15"
|
||||
black = "==23.7.0"
|
||||
bcrypt = "==3.2.2"
|
||||
beautifulsoup4 = "==4.12.2"
|
||||
billiard = "==3.6.4.0"
|
||||
black = "==23.7.0"
|
||||
bleach = "==4.1.0"
|
||||
blinker = "~=1.4"
|
||||
boto3 = "==1.28.15"
|
||||
|
||||
+5
-20
@@ -6,14 +6,7 @@ import uuid
|
||||
from time import monotonic
|
||||
|
||||
from celery import current_task
|
||||
from flask import (
|
||||
current_app,
|
||||
g,
|
||||
has_request_context,
|
||||
jsonify,
|
||||
make_response,
|
||||
request,
|
||||
)
|
||||
from flask import current_app, g, has_request_context, jsonify, make_response, request
|
||||
from flask_marshmallow import Marshmallow
|
||||
from flask_migrate import Migrate
|
||||
from flask_sqlalchemy import SQLAlchemy as _SQLAlchemy
|
||||
@@ -131,25 +124,17 @@ def register_blueprint(application):
|
||||
from app.inbound_number.rest import inbound_number_blueprint
|
||||
from app.inbound_sms.rest import inbound_sms as inbound_sms_blueprint
|
||||
from app.job.rest import job_blueprint
|
||||
from app.notifications.notifications_ses_callback import (
|
||||
ses_callback_blueprint,
|
||||
)
|
||||
from app.notifications.receive_notifications import (
|
||||
receive_notifications_blueprint,
|
||||
)
|
||||
from app.notifications.notifications_ses_callback import ses_callback_blueprint
|
||||
from app.notifications.receive_notifications import receive_notifications_blueprint
|
||||
from app.notifications.rest import notifications as notifications_blueprint
|
||||
from app.organization.invite_rest import organization_invite_blueprint
|
||||
from app.organization.rest import organization_blueprint
|
||||
from app.performance_dashboard.rest import performance_dashboard_blueprint
|
||||
from app.platform_stats.rest import platform_stats_blueprint
|
||||
from app.provider_details.rest import (
|
||||
provider_details as provider_details_blueprint,
|
||||
)
|
||||
from app.provider_details.rest import provider_details as provider_details_blueprint
|
||||
from app.service.callback_rest import service_callback_blueprint
|
||||
from app.service.rest import service_blueprint
|
||||
from app.service_invite.rest import (
|
||||
service_invite as service_invite_blueprint,
|
||||
)
|
||||
from app.service_invite.rest import service_invite as service_invite_blueprint
|
||||
from app.status.healthcheck import status as status_blueprint
|
||||
from app.template.rest import template_blueprint
|
||||
from app.template_folder.rest import template_folder_blueprint
|
||||
|
||||
@@ -5,10 +5,7 @@ from flask import current_app
|
||||
from app import notify_celery
|
||||
from app.config import QueueNames
|
||||
from app.cronitor import cronitor
|
||||
from app.dao.fact_billing_dao import (
|
||||
fetch_billing_data_for_day,
|
||||
update_fact_billing,
|
||||
)
|
||||
from app.dao.fact_billing_dao import fetch_billing_data_for_day, update_fact_billing
|
||||
from app.dao.fact_notification_status_dao import update_fact_notification_status
|
||||
from app.dao.notifications_dao import get_service_ids_with_notifications_on_date
|
||||
from app.models import EMAIL_TYPE, SMS_TYPE
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
import json
|
||||
|
||||
from flask import current_app
|
||||
from requests import HTTPError, request
|
||||
|
||||
from app.celery.process_ses_receipts_tasks import process_ses_results
|
||||
from app.config import QueueNames
|
||||
from app.dao.notifications_dao import get_notification_by_id
|
||||
from app.models import SMS_TYPE
|
||||
|
||||
temp_fail = "2028675303"
|
||||
perm_fail = "2028675302"
|
||||
delivered = "2028675309"
|
||||
|
||||
delivered_email = "delivered@simulator.notify"
|
||||
perm_fail_email = "perm-fail@simulator.notify"
|
||||
temp_fail_email = "temp-fail@simulator.notify"
|
||||
|
||||
|
||||
def send_sms_response(provider, reference):
|
||||
body = sns_callback(reference)
|
||||
headers = {"Content-type": "application/json"}
|
||||
|
||||
make_request(SMS_TYPE, provider, body, headers)
|
||||
|
||||
|
||||
def send_email_response(reference, to):
|
||||
if to == perm_fail_email:
|
||||
body = ses_hard_bounce_callback(reference)
|
||||
elif to == temp_fail_email:
|
||||
body = ses_soft_bounce_callback(reference)
|
||||
else:
|
||||
body = ses_notification_callback(reference)
|
||||
|
||||
process_ses_results.apply_async([body], queue=QueueNames.RESEARCH_MODE)
|
||||
|
||||
|
||||
def make_request(notification_type, provider, data, headers):
|
||||
api_call = "{}/notifications/{}/{}".format(
|
||||
current_app.config["API_HOST_NAME"], notification_type, provider
|
||||
)
|
||||
|
||||
try:
|
||||
response = request("POST", api_call, headers=headers, data=data, timeout=60)
|
||||
response.raise_for_status()
|
||||
except HTTPError as e:
|
||||
current_app.logger.error(
|
||||
"API POST request on {} failed with status {}".format(
|
||||
api_call, e.response.status_code
|
||||
)
|
||||
)
|
||||
raise e
|
||||
finally:
|
||||
current_app.logger.info("Mocked provider callback request finished")
|
||||
return response.json()
|
||||
|
||||
|
||||
def sns_callback(notification_id):
|
||||
notification = get_notification_by_id(notification_id)
|
||||
|
||||
# This will only work if all notifications, including successful ones, are in the notifications table
|
||||
# If we decide to delete successful notifications, we will have to get this from notifications history
|
||||
return json.dumps(
|
||||
{
|
||||
"CID": str(notification_id),
|
||||
"status": notification.status,
|
||||
# "deliverytime": notification.completed_at
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def ses_notification_callback(reference):
|
||||
ses_message_body = {
|
||||
"delivery": {
|
||||
"processingTimeMillis": 2003,
|
||||
"recipients": ["success@simulator.amazonses.com"],
|
||||
"remoteMtaIp": "123.123.123.123",
|
||||
"reportingMTA": "a7-32.smtp-out.us-west-2.amazonses.com",
|
||||
"smtpResponse": "250 2.6.0 Message received",
|
||||
"timestamp": "2017-11-17T12:14:03.646Z",
|
||||
},
|
||||
"mail": {
|
||||
"commonHeaders": {
|
||||
"from": ["TEST <TEST@notify.works>"],
|
||||
"subject": "lambda test",
|
||||
"to": ["success@simulator.amazonses.com"],
|
||||
},
|
||||
"destination": ["success@simulator.amazonses.com"],
|
||||
"headers": [
|
||||
{"name": "From", "value": "TEST <TEST@notify.works>"},
|
||||
{"name": "To", "value": "success@simulator.amazonses.com"},
|
||||
{"name": "Subject", "value": "lambda test"},
|
||||
{"name": "MIME-Version", "value": "1.0"},
|
||||
{
|
||||
"name": "Content-Type",
|
||||
"value": 'multipart/alternative; boundary="----=_Part_617203_1627511946.1510920841645"',
|
||||
},
|
||||
],
|
||||
"headersTruncated": False,
|
||||
"messageId": reference,
|
||||
"sendingAccountId": "12341234",
|
||||
"source": '"TEST" <TEST@notify.works>',
|
||||
"sourceArn": "arn:aws:ses:us-west-2:12341234:identity/notify.works",
|
||||
"sourceIp": "0.0.0.1",
|
||||
"timestamp": "2017-11-17T12:14:01.643Z",
|
||||
},
|
||||
"notificationType": "Delivery",
|
||||
}
|
||||
|
||||
return {
|
||||
"Type": "Notification",
|
||||
"MessageId": "8e83c020-1234-1234-1234-92a8ee9baa0a",
|
||||
"TopicArn": "arn:aws:sns:us-west-2:12341234:ses_notifications",
|
||||
"Subject": None,
|
||||
"Message": json.dumps(ses_message_body),
|
||||
"Timestamp": "2017-11-17T12:14:03.710Z",
|
||||
"SignatureVersion": "1",
|
||||
"Signature": "[REDACTED]",
|
||||
"SigningCertUrl": "https://sns.us-west-2.amazonaws.com/SimpleNotificationService-[REDACTED].pem",
|
||||
"UnsubscribeUrl": "https://sns.us-west-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=[REACTED]",
|
||||
"MessageAttributes": {},
|
||||
}
|
||||
|
||||
|
||||
def ses_hard_bounce_callback(reference):
|
||||
return _ses_bounce_callback(reference, "Permanent")
|
||||
|
||||
|
||||
def ses_soft_bounce_callback(reference):
|
||||
return _ses_bounce_callback(reference, "Temporary")
|
||||
|
||||
|
||||
def _ses_bounce_callback(reference, bounce_type):
|
||||
ses_message_body = {
|
||||
"bounce": {
|
||||
"bounceSubType": "General",
|
||||
"bounceType": bounce_type,
|
||||
"bouncedRecipients": [
|
||||
{
|
||||
"action": "failed",
|
||||
"diagnosticCode": "smtp; 550 5.1.1 user unknown",
|
||||
"emailAddress": "bounce@simulator.amazonses.com",
|
||||
"status": "5.1.1",
|
||||
}
|
||||
],
|
||||
"feedbackId": "0102015fc9e676fb-12341234-1234-1234-1234-9301e86a4fa8-000000",
|
||||
"remoteMtaIp": "123.123.123.123",
|
||||
"reportingMTA": "dsn; a7-31.smtp-out.us-west-2.amazonses.com",
|
||||
"timestamp": "2017-11-17T12:14:05.131Z",
|
||||
},
|
||||
"mail": {
|
||||
"commonHeaders": {
|
||||
"from": ["TEST <TEST@notify.works>"],
|
||||
"subject": "ses callback test",
|
||||
"to": ["bounce@simulator.amazonses.com"],
|
||||
},
|
||||
"destination": ["bounce@simulator.amazonses.com"],
|
||||
"headers": [
|
||||
{"name": "From", "value": "TEST <TEST@notify.works>"},
|
||||
{"name": "To", "value": "bounce@simulator.amazonses.com"},
|
||||
{"name": "Subject", "value": "lambda test"},
|
||||
{"name": "MIME-Version", "value": "1.0"},
|
||||
{
|
||||
"name": "Content-Type",
|
||||
"value": 'multipart/alternative; boundary="----=_Part_596529_2039165601.1510920843367"',
|
||||
},
|
||||
],
|
||||
"headersTruncated": False,
|
||||
"messageId": reference,
|
||||
"sendingAccountId": "12341234",
|
||||
"source": '"TEST" <TEST@notify.works>',
|
||||
"sourceArn": "arn:aws:ses:us-west-2:12341234:identity/notify.works",
|
||||
"sourceIp": "0.0.0.1",
|
||||
"timestamp": "2017-11-17T12:14:03.000Z",
|
||||
},
|
||||
"notificationType": "Bounce",
|
||||
}
|
||||
return {
|
||||
"Type": "Notification",
|
||||
"MessageId": "36e67c28-1234-1234-1234-2ea0172aa4a7",
|
||||
"TopicArn": "arn:aws:sns:us-west-2:12341234:ses_notifications",
|
||||
"Subject": None,
|
||||
"Message": json.dumps(ses_message_body),
|
||||
"Timestamp": "2017-11-17T12:14:05.149Z",
|
||||
"SignatureVersion": "1",
|
||||
"Signature": "[REDACTED]", # noqa
|
||||
"SigningCertUrl": "https://sns.us-west-2.amazonaws.com/SimpleNotificationService-[REDACTED]].pem",
|
||||
"UnsubscribeUrl": "https://sns.us-west-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=[REDACTED]]",
|
||||
"MessageAttributes": {},
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from flask import current_app
|
||||
from notifications_utils.clients.zendesk.zendesk_client import (
|
||||
NotifySupportTicket,
|
||||
)
|
||||
from notifications_utils.clients.zendesk.zendesk_client import NotifySupportTicket
|
||||
from sqlalchemy import between
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
|
||||
@@ -18,9 +16,7 @@ from app.config import QueueNames
|
||||
from app.dao.invited_org_user_dao import (
|
||||
delete_org_invitations_created_more_than_two_days_ago,
|
||||
)
|
||||
from app.dao.invited_user_dao import (
|
||||
delete_invitations_created_more_than_two_days_ago,
|
||||
)
|
||||
from app.dao.invited_user_dao import delete_invitations_created_more_than_two_days_ago
|
||||
from app.dao.jobs_dao import (
|
||||
dao_set_scheduled_jobs_to_pending,
|
||||
dao_update_job,
|
||||
@@ -222,8 +218,8 @@ def check_for_services_with_high_failure_rates_or_sending_to_tv_numbers():
|
||||
if current_app.config["NOTIFY_ENVIRONMENT"] in ["live", "production", "test"]:
|
||||
message += (
|
||||
"\nYou can find instructions for this ticket in our manual:\n"
|
||||
"https://github.com/alphagov/notifications-manuals/wiki/Support-Runbook#Deal-with-services-with-high-failure-rates-or-sending-sms-to-tv-numbers"
|
||||
) # noqa
|
||||
"https://github.com/alphagov/notifications-manuals/wiki/Support-Runbook#Deal-with-services-with-high-failure-rates-or-sending-sms-to-tv-numbers" # noqa
|
||||
)
|
||||
ticket = NotifySupportTicket(
|
||||
subject=f"[{current_app.config['NOTIFY_ENVIRONMENT']}] High failure rates for sms spotted for services",
|
||||
message=message,
|
||||
|
||||
@@ -4,11 +4,7 @@ import botocore
|
||||
from boto3 import client
|
||||
from flask import current_app
|
||||
|
||||
from app.clients import (
|
||||
AWS_CLIENT_CONFIG,
|
||||
STATISTICS_DELIVERED,
|
||||
STATISTICS_FAILURE,
|
||||
)
|
||||
from app.clients import AWS_CLIENT_CONFIG, STATISTICS_DELIVERED, STATISTICS_FAILURE
|
||||
from app.clients.email import (
|
||||
EmailClient,
|
||||
EmailClientException,
|
||||
|
||||
@@ -3,10 +3,7 @@ from datetime import datetime
|
||||
from flask import Blueprint, jsonify, request
|
||||
|
||||
from app.complaint.complaint_schema import complaint_count_request
|
||||
from app.dao.complaint_dao import (
|
||||
fetch_count_of_complaints,
|
||||
fetch_paginated_complaints,
|
||||
)
|
||||
from app.dao.complaint_dao import fetch_count_of_complaints, fetch_paginated_complaints
|
||||
from app.errors import register_errors
|
||||
from app.schema_validation import validate
|
||||
from app.utils import pagination_links
|
||||
|
||||
@@ -35,8 +35,9 @@ def get_model_api_keys(service_id, id=None):
|
||||
seven_days_ago = datetime.utcnow() - timedelta(days=7)
|
||||
return ApiKey.query.filter(
|
||||
or_(
|
||||
ApiKey.expiry_date == None, func.date(ApiKey.expiry_date) > seven_days_ago
|
||||
), # noqa
|
||||
ApiKey.expiry_date == None, # noqa
|
||||
func.date(ApiKey.expiry_date) > seven_days_ago, # noqa
|
||||
),
|
||||
ApiKey.service_id == service_id,
|
||||
).all()
|
||||
|
||||
|
||||
@@ -6,10 +6,7 @@ from sqlalchemy.dialects.postgresql import insert
|
||||
from sqlalchemy.sql.expression import case, literal
|
||||
|
||||
from app import db
|
||||
from app.dao.date_util import (
|
||||
get_calendar_year_dates,
|
||||
get_calendar_year_for_datetime,
|
||||
)
|
||||
from app.dao.date_util import get_calendar_year_dates, get_calendar_year_for_datetime
|
||||
from app.dao.organization_dao import dao_get_organization_live_services
|
||||
from app.models import (
|
||||
EMAIL_TYPE,
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from flask import current_app
|
||||
from notifications_utils.international_billing_rates import (
|
||||
INTERNATIONAL_BILLING_RATES,
|
||||
)
|
||||
from notifications_utils.international_billing_rates import INTERNATIONAL_BILLING_RATES
|
||||
from notifications_utils.recipients import (
|
||||
InvalidEmailError,
|
||||
try_validate_and_format_phone_number,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import random
|
||||
from datetime import datetime
|
||||
from urllib import parse
|
||||
|
||||
@@ -14,9 +13,7 @@ from app import create_uuid, db, notification_provider_clients
|
||||
from app.celery.test_key_tasks import send_email_response, send_sms_response
|
||||
from app.dao.email_branding_dao import dao_get_email_branding_by_id
|
||||
from app.dao.notifications_dao import dao_update_notification
|
||||
from app.dao.provider_details_dao import (
|
||||
get_provider_details_by_notification_type,
|
||||
)
|
||||
from app.dao.provider_details_dao import get_provider_details_by_notification_type
|
||||
from app.exceptions import NotificationTechnicalFailureException
|
||||
from app.models import (
|
||||
BRANDING_BOTH,
|
||||
@@ -161,13 +158,8 @@ def provider_to_use(notification_type, international=True):
|
||||
)
|
||||
raise Exception("No active {} providers".format(notification_type))
|
||||
|
||||
if len(active_providers) == 1:
|
||||
chosen_provider = active_providers[0]
|
||||
else:
|
||||
weights = [p.priority for p in active_providers]
|
||||
chosen_provider = random.choices(active_providers, weights=weights)[
|
||||
0
|
||||
] # nosec B311 - not sec/crypto related
|
||||
# we only have sns
|
||||
chosen_provider = active_providers[0]
|
||||
|
||||
return notification_provider_clients.get_client_by_name_and_type(
|
||||
chosen_provider.identifier, notification_type
|
||||
|
||||
@@ -10,9 +10,7 @@ from app.dao.service_data_retention_dao import (
|
||||
fetch_service_data_retention_by_notification_type,
|
||||
)
|
||||
from app.errors import register_errors
|
||||
from app.inbound_sms.inbound_sms_schemas import (
|
||||
get_inbound_sms_for_service_schema,
|
||||
)
|
||||
from app.inbound_sms.inbound_sms_schemas import get_inbound_sms_for_service_schema
|
||||
from app.schema_validation import validate
|
||||
|
||||
inbound_sms = Blueprint(
|
||||
|
||||
+2
-8
@@ -5,9 +5,7 @@ from flask import Blueprint, current_app, jsonify, request
|
||||
from app.aws.s3 import get_job_metadata_from_s3
|
||||
from app.celery.tasks import process_job
|
||||
from app.config import QueueNames
|
||||
from app.dao.fact_notification_status_dao import (
|
||||
fetch_notification_statuses_for_job,
|
||||
)
|
||||
from app.dao.fact_notification_status_dao import fetch_notification_statuses_for_job
|
||||
from app.dao.jobs_dao import (
|
||||
dao_create_job,
|
||||
dao_get_future_scheduled_job_by_id_and_service_id,
|
||||
@@ -24,11 +22,7 @@ from app.dao.notifications_dao import (
|
||||
from app.dao.services_dao import dao_fetch_service_by_id
|
||||
from app.dao.templates_dao import dao_get_template_by_id
|
||||
from app.errors import InvalidRequest, register_errors
|
||||
from app.models import (
|
||||
JOB_STATUS_CANCELLED,
|
||||
JOB_STATUS_PENDING,
|
||||
JOB_STATUS_SCHEDULED,
|
||||
)
|
||||
from app.models import JOB_STATUS_CANCELLED, JOB_STATUS_PENDING, JOB_STATUS_SCHEDULED
|
||||
from app.schemas import (
|
||||
job_schema,
|
||||
notification_with_template_schema,
|
||||
|
||||
+2
-7
@@ -3,9 +3,7 @@ import itertools
|
||||
import uuid
|
||||
|
||||
from flask import current_app, url_for
|
||||
from notifications_utils.clients.encryption.encryption_client import (
|
||||
EncryptionError,
|
||||
)
|
||||
from notifications_utils.clients.encryption.encryption_client import EncryptionError
|
||||
from notifications_utils.recipients import (
|
||||
InvalidEmailError,
|
||||
InvalidPhoneError,
|
||||
@@ -13,10 +11,7 @@ from notifications_utils.recipients import (
|
||||
validate_email_address,
|
||||
validate_phone_number,
|
||||
)
|
||||
from notifications_utils.template import (
|
||||
PlainTextEmailTemplate,
|
||||
SMSMessageTemplate,
|
||||
)
|
||||
from notifications_utils.template import PlainTextEmailTemplate, SMSMessageTemplate
|
||||
from sqlalchemy import CheckConstraint, Index, UniqueConstraint
|
||||
from sqlalchemy.dialects.postgresql import JSON, JSONB, UUID
|
||||
from sqlalchemy.ext.associationproxy import association_proxy
|
||||
|
||||
@@ -8,10 +8,7 @@ from notifications_utils.recipients import (
|
||||
get_international_phone_info,
|
||||
validate_and_format_phone_number,
|
||||
)
|
||||
from notifications_utils.template import (
|
||||
PlainTextEmailTemplate,
|
||||
SMSMessageTemplate,
|
||||
)
|
||||
from notifications_utils.template import PlainTextEmailTemplate, SMSMessageTemplate
|
||||
|
||||
from app import redis_store
|
||||
from app.celery import provider_tasks
|
||||
|
||||
@@ -138,6 +138,7 @@ def send_notification(notification_type):
|
||||
if not simulated:
|
||||
queue_name = QueueNames.PRIORITY if template.process_type == PRIORITY else None
|
||||
send_notification_to_queue(notification=notification_model, queue=queue_name)
|
||||
|
||||
else:
|
||||
current_app.logger.debug(
|
||||
"POST simulated notification for id: {}".format(notification_model.id)
|
||||
|
||||
@@ -22,9 +22,7 @@ from app.models import (
|
||||
SMS_TYPE,
|
||||
ServicePermission,
|
||||
)
|
||||
from app.notifications.process_notifications import (
|
||||
create_content_for_notification,
|
||||
)
|
||||
from app.notifications.process_notifications import create_content_for_notification
|
||||
from app.serialised_models import SerialisedTemplate
|
||||
from app.service.utils import service_allowed_to_send_to
|
||||
from app.utils import get_public_notify_type_text
|
||||
|
||||
@@ -2,9 +2,7 @@ from datetime import datetime
|
||||
|
||||
from flask import Blueprint, jsonify, request
|
||||
|
||||
from app.dao.fact_notification_status_dao import (
|
||||
get_total_notifications_for_date_range,
|
||||
)
|
||||
from app.dao.fact_notification_status_dao import get_total_notifications_for_date_range
|
||||
from app.dao.fact_processing_time_dao import (
|
||||
get_processing_time_percentage_for_date_range,
|
||||
)
|
||||
|
||||
@@ -4,9 +4,7 @@ from notifications_utils.template import SMSMessageTemplate
|
||||
from sqlalchemy.orm.exc import NoResultFound
|
||||
|
||||
from app.dao.services_dao import dao_fetch_service_by_id
|
||||
from app.dao.template_folder_dao import (
|
||||
dao_get_template_folder_by_id_and_service_id,
|
||||
)
|
||||
from app.dao.template_folder_dao import dao_get_template_folder_by_id_and_service_id
|
||||
from app.dao.templates_dao import (
|
||||
dao_create_template,
|
||||
dao_get_all_templates_for_service,
|
||||
|
||||
@@ -3,10 +3,7 @@ from sqlalchemy.exc import IntegrityError
|
||||
from sqlalchemy.orm.exc import NoResultFound
|
||||
|
||||
from app.dao.dao_utils import autocommit
|
||||
from app.dao.service_user_dao import (
|
||||
dao_get_active_service_users,
|
||||
dao_get_service_user,
|
||||
)
|
||||
from app.dao.service_user_dao import dao_get_active_service_users, dao_get_service_user
|
||||
from app.dao.services_dao import dao_fetch_service_by_id
|
||||
from app.dao.template_folder_dao import (
|
||||
dao_create_template_folder,
|
||||
|
||||
+1
-3
@@ -1,8 +1,6 @@
|
||||
from flask import Blueprint, current_app, jsonify, request
|
||||
|
||||
from app.dao.fact_notification_status_dao import (
|
||||
fetch_notification_statuses_for_job,
|
||||
)
|
||||
from app.dao.fact_notification_status_dao import fetch_notification_statuses_for_job
|
||||
from app.dao.jobs_dao import dao_get_notification_outcomes_for_job
|
||||
from app.dao.uploads_dao import dao_get_uploads_by_service_id
|
||||
from app.errors import register_errors
|
||||
|
||||
+4
-18
@@ -4,22 +4,14 @@ from datetime import datetime
|
||||
from urllib.parse import urlencode
|
||||
|
||||
from flask import Blueprint, abort, current_app, jsonify, request
|
||||
from notifications_utils.recipients import (
|
||||
is_us_phone_number,
|
||||
use_numeric_sender,
|
||||
)
|
||||
from notifications_utils.recipients import is_us_phone_number, use_numeric_sender
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
|
||||
from app.config import QueueNames
|
||||
from app.dao.permissions_dao import permission_dao
|
||||
from app.dao.service_user_dao import (
|
||||
dao_get_service_user,
|
||||
dao_update_service_user,
|
||||
)
|
||||
from app.dao.service_user_dao import dao_get_service_user, dao_update_service_user
|
||||
from app.dao.services_dao import dao_fetch_service_by_id
|
||||
from app.dao.template_folder_dao import (
|
||||
dao_get_template_folder_by_id_and_service_id,
|
||||
)
|
||||
from app.dao.template_folder_dao import dao_get_template_folder_by_id_and_service_id
|
||||
from app.dao.templates_dao import dao_get_template_by_id
|
||||
from app.dao.users_dao import (
|
||||
count_user_verify_codes,
|
||||
@@ -40,13 +32,7 @@ from app.dao.users_dao import (
|
||||
use_user_code,
|
||||
)
|
||||
from app.errors import InvalidRequest, register_errors
|
||||
from app.models import (
|
||||
EMAIL_TYPE,
|
||||
KEY_TYPE_NORMAL,
|
||||
SMS_TYPE,
|
||||
Permission,
|
||||
Service,
|
||||
)
|
||||
from app.models import EMAIL_TYPE, KEY_TYPE_NORMAL, SMS_TYPE, Permission, Service
|
||||
from app.notifications.process_notifications import (
|
||||
persist_notification,
|
||||
send_notification_to_queue,
|
||||
|
||||
@@ -6,12 +6,7 @@ import botocore
|
||||
from flask import abort, current_app, jsonify, request
|
||||
from notifications_utils.recipients import try_validate_and_format_phone_number
|
||||
|
||||
from app import (
|
||||
api_user,
|
||||
authenticated_service,
|
||||
document_download_client,
|
||||
encryption,
|
||||
)
|
||||
from app import api_user, authenticated_service, document_download_client, encryption
|
||||
from app.celery.tasks import save_api_email, save_api_sms
|
||||
from app.clients.document_download import DocumentDownloadError
|
||||
from app.config import QueueNames
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
from app.models import TEMPLATE_TYPES
|
||||
from app.v2.template.template_schemas import (
|
||||
get_template_by_id_response as template,
|
||||
)
|
||||
from app.v2.template.template_schemas import get_template_by_id_response as template
|
||||
|
||||
get_all_template_request = {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
|
||||
@@ -6,14 +6,12 @@ xfail_strict=true
|
||||
exclude = venv*,__pycache__,node_modules,cache,migrations,build,sample_cap_xml_documents.py
|
||||
max-line-length = 120
|
||||
# W504 line break after binary operator
|
||||
extend_ignore=B306, W504, E204
|
||||
|
||||
extend_ignore=B306, W504, E203
|
||||
|
||||
[isort]
|
||||
profile = black
|
||||
multi_line_output = 3
|
||||
|
||||
|
||||
[coverage:run]
|
||||
omit =
|
||||
# omit anything in a .local directory anywhere
|
||||
|
||||
@@ -16,16 +16,9 @@ from app.authentication.auth import (
|
||||
requires_auth,
|
||||
requires_internal_auth,
|
||||
)
|
||||
from app.dao.api_key_dao import (
|
||||
expire_api_key,
|
||||
get_model_api_keys,
|
||||
get_unsigned_secrets,
|
||||
)
|
||||
from app.dao.api_key_dao import expire_api_key, get_model_api_keys, get_unsigned_secrets
|
||||
from app.dao.services_dao import dao_fetch_service_by_id
|
||||
from tests import (
|
||||
create_admin_authorization_header,
|
||||
create_service_authorization_header,
|
||||
)
|
||||
from tests import create_admin_authorization_header, create_service_authorization_header
|
||||
from tests.conftest import set_config_values
|
||||
|
||||
|
||||
|
||||
@@ -4,9 +4,7 @@ from unittest import mock
|
||||
from unittest.mock import ANY, call
|
||||
|
||||
import pytest
|
||||
from notifications_utils.clients.zendesk.zendesk_client import (
|
||||
NotifySupportTicket,
|
||||
)
|
||||
from notifications_utils.clients.zendesk.zendesk_client import NotifySupportTicket
|
||||
|
||||
from app.celery import scheduled_tasks
|
||||
from app.celery.scheduled_tasks import (
|
||||
|
||||
@@ -8,10 +8,7 @@ import requests_mock
|
||||
from celery.exceptions import Retry
|
||||
from freezegun import freeze_time
|
||||
from notifications_utils.recipients import Row
|
||||
from notifications_utils.template import (
|
||||
PlainTextEmailTemplate,
|
||||
SMSMessageTemplate,
|
||||
)
|
||||
from notifications_utils.template import PlainTextEmailTemplate, SMSMessageTemplate
|
||||
from requests import RequestException
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
|
||||
@@ -663,14 +660,12 @@ def test_save_email_should_use_template_version_from_job_not_latest(
|
||||
notification = _notification_json(sample_email_template, "my_email@my_email.com")
|
||||
version_on_notification = sample_email_template.version
|
||||
# Change the template
|
||||
from app.dao.templates_dao import (
|
||||
dao_get_template_by_id,
|
||||
dao_update_template,
|
||||
)
|
||||
from app.dao.templates_dao import dao_get_template_by_id, dao_update_template
|
||||
|
||||
sample_email_template.content = (
|
||||
sample_email_template.content + " another version of the template"
|
||||
)
|
||||
|
||||
mocker.patch("app.celery.provider_tasks.deliver_email.apply_async")
|
||||
dao_update_template(sample_email_template)
|
||||
t = dao_get_template_by_id(sample_email_template.id)
|
||||
|
||||
@@ -2,10 +2,7 @@ import pytest
|
||||
import requests
|
||||
import requests_mock
|
||||
|
||||
from app.clients.document_download import (
|
||||
DocumentDownloadClient,
|
||||
DocumentDownloadError,
|
||||
)
|
||||
from app.clients.document_download import DocumentDownloadClient, DocumentDownloadError
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
|
||||
@@ -4,12 +4,7 @@ from app.dao.service_permissions_dao import (
|
||||
dao_fetch_service_permissions,
|
||||
dao_remove_service_permission,
|
||||
)
|
||||
from app.models import (
|
||||
EMAIL_TYPE,
|
||||
INBOUND_SMS_TYPE,
|
||||
INTERNATIONAL_SMS_TYPE,
|
||||
SMS_TYPE,
|
||||
)
|
||||
from app.models import EMAIL_TYPE, INBOUND_SMS_TYPE, INTERNATIONAL_SMS_TYPE, SMS_TYPE
|
||||
from tests.app.db import create_service, create_service_permission
|
||||
|
||||
|
||||
|
||||
@@ -16,10 +16,7 @@ from app.dao.inbound_numbers_dao import (
|
||||
)
|
||||
from app.dao.organization_dao import dao_add_service_to_organization
|
||||
from app.dao.service_permissions_dao import dao_remove_service_permission
|
||||
from app.dao.service_user_dao import (
|
||||
dao_get_service_user,
|
||||
dao_update_service_user,
|
||||
)
|
||||
from app.dao.service_user_dao import dao_get_service_user, dao_update_service_user
|
||||
from app.dao.services_dao import (
|
||||
dao_add_user_to_service,
|
||||
dao_create_service,
|
||||
|
||||
@@ -7,10 +7,7 @@ from sqlalchemy.exc import DataError
|
||||
from sqlalchemy.orm.exc import NoResultFound
|
||||
|
||||
from app import db
|
||||
from app.dao.service_user_dao import (
|
||||
dao_get_service_user,
|
||||
dao_update_service_user,
|
||||
)
|
||||
from app.dao.service_user_dao import dao_get_service_user, dao_update_service_user
|
||||
from app.dao.users_dao import (
|
||||
_remove_values_for_keys_if_present,
|
||||
count_user_verify_codes,
|
||||
|
||||
@@ -192,10 +192,7 @@ def test_send_sms_should_use_template_version_from_notification_not_latest(
|
||||
expected_template_id = sample_template.id
|
||||
|
||||
# Change the template
|
||||
from app.dao.templates_dao import (
|
||||
dao_get_template_by_id,
|
||||
dao_update_template,
|
||||
)
|
||||
from app.dao.templates_dao import dao_get_template_by_id, dao_update_template
|
||||
|
||||
sample_template.content = (
|
||||
sample_template.content + " another version of the template"
|
||||
|
||||
@@ -6,9 +6,7 @@ from notifications_utils import SMS_CHAR_COUNT_LIMIT
|
||||
import app
|
||||
from app.dao import templates_dao
|
||||
from app.models import EMAIL_TYPE, SMS_TYPE
|
||||
from app.notifications.process_notifications import (
|
||||
create_content_for_notification,
|
||||
)
|
||||
from app.notifications.process_notifications import create_content_for_notification
|
||||
from app.notifications.sns_cert_validator import (
|
||||
VALID_SNS_TOPICS,
|
||||
get_string_to_sign,
|
||||
@@ -238,7 +236,7 @@ def test_service_can_send_to_recipient_fails_when_ignoring_guest_list(
|
||||
("team", "Can’t send to this recipient using a team-only API key"),
|
||||
(
|
||||
"normal",
|
||||
"Can’t send to this recipient when service is in trial mode – see https://www.notifications.service.gov.uk/trial-mode",
|
||||
"Can’t send to this recipient when service is in trial mode – see https://www.notifications.service.gov.uk/trial-mode", # noqa
|
||||
),
|
||||
],
|
||||
) # noqa
|
||||
@@ -723,8 +721,8 @@ def test_get_string_to_sign():
|
||||
str = get_string_to_sign(sns_payload)
|
||||
assert (
|
||||
str
|
||||
== b'Message\n{"AbsoluteTime":"2021-09-08T13:28:24.656Z","Content":"help","ContentType":"text/plain","Id":"333333333-be0d-4a44-889d-d2a86fc06f0c","Type":"MESSAGE","ParticipantId":"bbbbbbbb-c562-4d95-b76c-dcbca8b4b5f7","DisplayName":"Jane","ParticipantRole":"CUSTOMER","InitialContactId":"33333333-abc5-46db-9ad5-d772559ab556","ContactId":"33333333-abc5-46db-9ad5-d772559ab556"}\nMessageId\nccccccccc-cccc-cccc-cccc-ccccccccccccc\nTimestamp\n2021-09-08T13:28:24.860Z\nTopicArn\narn:aws:sns:us-west-2:009969138378:connector-svc-test\nType\nNotification\n'
|
||||
) # noqa
|
||||
== b'Message\n{"AbsoluteTime":"2021-09-08T13:28:24.656Z","Content":"help","ContentType":"text/plain","Id":"333333333-be0d-4a44-889d-d2a86fc06f0c","Type":"MESSAGE","ParticipantId":"bbbbbbbb-c562-4d95-b76c-dcbca8b4b5f7","DisplayName":"Jane","ParticipantRole":"CUSTOMER","InitialContactId":"33333333-abc5-46db-9ad5-d772559ab556","ContactId":"33333333-abc5-46db-9ad5-d772559ab556"}\nMessageId\nccccccccc-cccc-cccc-cccc-ccccccccccccc\nTimestamp\n2021-09-08T13:28:24.860Z\nTopicArn\narn:aws:sns:us-west-2:009969138378:connector-svc-test\nType\nNotification\n' # noqa
|
||||
)
|
||||
|
||||
# This is a test payload with no valid cert, so it should raise a ValueError
|
||||
with pytest.raises(ValueError):
|
||||
|
||||
@@ -5,9 +5,7 @@ from freezegun import freeze_time
|
||||
|
||||
from app.errors import InvalidRequest
|
||||
from app.models import EMAIL_TYPE, SMS_TYPE
|
||||
from app.platform_stats.rest import (
|
||||
validate_date_range_is_within_a_financial_year,
|
||||
)
|
||||
from app.platform_stats.rest import validate_date_range_is_within_a_financial_year
|
||||
from tests.app.db import (
|
||||
create_ft_billing,
|
||||
create_ft_notification_status,
|
||||
|
||||
@@ -11,10 +11,7 @@ import app
|
||||
from app.dao import notifications_dao
|
||||
from app.dao.api_key_dao import save_model_api_key
|
||||
from app.dao.services_dao import dao_update_service
|
||||
from app.dao.templates_dao import (
|
||||
dao_get_all_templates_for_service,
|
||||
dao_update_template,
|
||||
)
|
||||
from app.dao.templates_dao import dao_get_all_templates_for_service, dao_update_template
|
||||
from app.errors import InvalidRequest
|
||||
from app.models import (
|
||||
EMAIL_TYPE,
|
||||
|
||||
@@ -6,9 +6,7 @@ from notifications_utils import SMS_CHAR_COUNT_LIMIT
|
||||
from notifications_utils.recipients import InvalidPhoneError
|
||||
|
||||
from app.config import QueueNames
|
||||
from app.dao.service_guest_list_dao import (
|
||||
dao_add_and_commit_guest_list_contacts,
|
||||
)
|
||||
from app.dao.service_guest_list_dao import dao_add_and_commit_guest_list_contacts
|
||||
from app.models import (
|
||||
EMAIL_TYPE,
|
||||
KEY_TYPE_NORMAL,
|
||||
|
||||
@@ -11,10 +11,7 @@ from sqlalchemy.exc import SQLAlchemyError
|
||||
from app.dao.organization_dao import dao_add_service_to_organization
|
||||
from app.dao.service_sms_sender_dao import dao_get_sms_senders_by_service_id
|
||||
from app.dao.service_user_dao import dao_get_service_user
|
||||
from app.dao.services_dao import (
|
||||
dao_add_user_to_service,
|
||||
dao_remove_user_from_service,
|
||||
)
|
||||
from app.dao.services_dao import dao_add_user_to_service, dao_remove_user_from_service
|
||||
from app.dao.templates_dao import dao_redact_template
|
||||
from app.dao.users_dao import save_model_user
|
||||
from app.models import (
|
||||
@@ -761,7 +758,6 @@ def test_update_service_flags(client, sample_service):
|
||||
json_resp = resp.json
|
||||
assert resp.status_code == 200
|
||||
assert json_resp["data"]["name"] == sample_service.name
|
||||
|
||||
data = {"permissions": [INTERNATIONAL_SMS_TYPE]}
|
||||
|
||||
auth_header = create_admin_authorization_header()
|
||||
|
||||
@@ -5,9 +5,7 @@ import pytest
|
||||
from jsonschema import ValidationError
|
||||
|
||||
from app.schema_validation import validate
|
||||
from app.service.service_callback_api_schema import (
|
||||
update_service_callback_api_schema,
|
||||
)
|
||||
from app.service.service_callback_api_schema import update_service_callback_api_schema
|
||||
|
||||
|
||||
def test_service_callback_api_schema_validates():
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import json
|
||||
import uuid
|
||||
|
||||
from app.dao.service_guest_list_dao import (
|
||||
dao_add_and_commit_guest_list_contacts,
|
||||
)
|
||||
from app.dao.service_guest_list_dao import dao_add_and_commit_guest_list_contacts
|
||||
from app.models import EMAIL_TYPE, MOBILE_TYPE, ServiceGuestList
|
||||
from tests import create_admin_authorization_header
|
||||
|
||||
|
||||
@@ -275,9 +275,7 @@ def test_delete_template_folder_fails_if_folder_has_subfolders(
|
||||
admin_request, sample_service
|
||||
):
|
||||
existing_folder = create_template_folder(sample_service)
|
||||
existing_subfolder = create_template_folder(
|
||||
sample_service, parent=existing_folder
|
||||
) # noqa
|
||||
create_template_folder(sample_service, parent=existing_folder) # noqa
|
||||
|
||||
resp = admin_request.delete(
|
||||
"template_folder.delete_template_folder",
|
||||
|
||||
@@ -8,10 +8,7 @@ from flask import current_app
|
||||
from freezegun import freeze_time
|
||||
|
||||
from app.dao.permissions_dao import default_service_permissions
|
||||
from app.dao.service_user_dao import (
|
||||
dao_get_service_user,
|
||||
dao_update_service_user,
|
||||
)
|
||||
from app.dao.service_user_dao import dao_get_service_user, dao_update_service_user
|
||||
from app.models import (
|
||||
EMAIL_AUTH_TYPE,
|
||||
MANAGE_SETTINGS,
|
||||
|
||||
Reference in New Issue
Block a user