mirror of
https://github.com/GSA/notifications-api.git
synced 2026-08-15 07:18:09 -04:00
Remove letters-related code (#175)
This deletes a big ol' chunk of code related to letters. It's not everything—there are still a few things that might be tied to sms/email—but it's the the heart of letters function. SMS and email function should be untouched by this. Areas affected: - Things obviously about letters - PDF tasks, used for precompiling letters - Virus scanning, used for those PDFs - FTP, used to send letters to the printer - Postage stuff
This commit is contained in:
@@ -1,61 +0,0 @@
|
||||
import json
|
||||
from functools import wraps
|
||||
|
||||
from flask import Blueprint, current_app, jsonify, request
|
||||
|
||||
from app.celery.tasks import (
|
||||
record_daily_sorted_counts,
|
||||
update_letter_notifications_statuses,
|
||||
)
|
||||
from app.config import QueueNames
|
||||
from app.notifications.utils import autoconfirm_subscription
|
||||
from app.schema_validation import validate
|
||||
from app.v2.errors import register_errors
|
||||
|
||||
letter_callback_blueprint = Blueprint('notifications_letter_callback', __name__)
|
||||
register_errors(letter_callback_blueprint)
|
||||
|
||||
|
||||
dvla_sns_callback_schema = {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"description": "sns callback received on s3 update",
|
||||
"type": "object",
|
||||
"title": "dvla internal sns callback",
|
||||
"properties": {
|
||||
"Type": {"enum": ["Notification", "SubscriptionConfirmation"]},
|
||||
"MessageId": {"type": "string"},
|
||||
"Message": {"type": ["string", "object"]}
|
||||
},
|
||||
"required": ["Type", "MessageId", "Message"]
|
||||
}
|
||||
|
||||
|
||||
def validate_schema(schema):
|
||||
def decorator(f):
|
||||
@wraps(f)
|
||||
def wrapper(*args, **kw):
|
||||
validate(request.get_json(force=True), schema)
|
||||
return f(*args, **kw)
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
|
||||
@letter_callback_blueprint.route('/notifications/letter/dvla', methods=['POST'])
|
||||
@validate_schema(dvla_sns_callback_schema)
|
||||
def process_letter_response():
|
||||
req_json = request.get_json(force=True)
|
||||
current_app.logger.debug('Received SNS callback: {}'.format(req_json))
|
||||
if not autoconfirm_subscription(req_json):
|
||||
# The callback should have one record for an S3 Put Event.
|
||||
message = json.loads(req_json['Message'])
|
||||
filename = message['Records'][0]['s3']['object']['key']
|
||||
current_app.logger.info('Received file from DVLA: {}'.format(filename))
|
||||
|
||||
if filename.lower().endswith('rs.txt') or filename.lower().endswith('rsp.txt'):
|
||||
current_app.logger.info('DVLA callback: Calling task to update letter notifications')
|
||||
update_letter_notifications_statuses.apply_async([filename], queue=QueueNames.NOTIFY)
|
||||
record_daily_sorted_counts.apply_async([filename], queue=QueueNames.NOTIFY)
|
||||
|
||||
return jsonify(
|
||||
result="success", message="DVLA callback succeeded"
|
||||
), 200
|
||||
@@ -1,41 +0,0 @@
|
||||
from notifications_utils.postal_address import PostalAddress
|
||||
|
||||
from app import create_random_identifier
|
||||
from app.models import LETTER_TYPE
|
||||
from app.notifications.process_notifications import persist_notification
|
||||
|
||||
|
||||
def create_letter_notification(
|
||||
letter_data,
|
||||
template,
|
||||
service,
|
||||
api_key,
|
||||
status,
|
||||
reply_to_text=None,
|
||||
billable_units=None,
|
||||
updated_at=None,
|
||||
postage=None
|
||||
):
|
||||
notification = persist_notification(
|
||||
template_id=template.id,
|
||||
template_version=template.version,
|
||||
# we only accept addresses_with_underscores from the API (from CSV we also accept dashes, spaces etc)
|
||||
recipient=PostalAddress.from_personalisation(letter_data['personalisation']).normalised,
|
||||
service=service,
|
||||
personalisation=letter_data['personalisation'],
|
||||
notification_type=LETTER_TYPE,
|
||||
api_key_id=api_key.id,
|
||||
key_type=api_key.key_type,
|
||||
job_id=None,
|
||||
job_row_number=None,
|
||||
reference=create_random_identifier(),
|
||||
client_reference=letter_data.get('reference'),
|
||||
status=status,
|
||||
reply_to_text=reply_to_text,
|
||||
billable_units=billable_units,
|
||||
# letter_data.get('postage') is only set for precompiled letters (if international it is set after sanitise)
|
||||
# letters from a template will pass in 'europe' or 'rest-of-world' if None then use postage from template
|
||||
postage=postage or letter_data.get('postage') or template.postage,
|
||||
updated_at=updated_at
|
||||
)
|
||||
return notification
|
||||
@@ -10,14 +10,12 @@ from notifications_utils.recipients import (
|
||||
validate_and_format_phone_number,
|
||||
)
|
||||
from notifications_utils.template import (
|
||||
LetterPrintTemplate,
|
||||
PlainTextEmailTemplate,
|
||||
SMSMessageTemplate,
|
||||
)
|
||||
|
||||
from app import redis_store
|
||||
from app.celery import provider_tasks
|
||||
from app.celery.letters_pdf_tasks import get_pdf_for_templated_letter
|
||||
from app.config import QueueNames
|
||||
from app.dao.notifications_dao import (
|
||||
dao_create_notification,
|
||||
@@ -25,9 +23,7 @@ from app.dao.notifications_dao import (
|
||||
)
|
||||
from app.models import (
|
||||
EMAIL_TYPE,
|
||||
INTERNATIONAL_POSTAGE_TYPES,
|
||||
KEY_TYPE_TEST,
|
||||
LETTER_TYPE,
|
||||
NOTIFICATION_CREATED,
|
||||
SMS_TYPE,
|
||||
Notification,
|
||||
@@ -58,16 +54,6 @@ def create_content_for_notification(template, personalisation):
|
||||
},
|
||||
personalisation,
|
||||
)
|
||||
if template.template_type == LETTER_TYPE:
|
||||
template_object = LetterPrintTemplate(
|
||||
{
|
||||
'content': template.content,
|
||||
'subject': template.subject,
|
||||
'template_type': template.template_type,
|
||||
},
|
||||
personalisation,
|
||||
contact_block=template.reply_to_text,
|
||||
)
|
||||
|
||||
check_placeholders(template_object)
|
||||
|
||||
@@ -101,7 +87,6 @@ def persist_notification(
|
||||
status=NOTIFICATION_CREATED,
|
||||
reply_to_text=None,
|
||||
billable_units=None,
|
||||
postage=None,
|
||||
document_download_count=None,
|
||||
updated_at=None
|
||||
):
|
||||
@@ -149,10 +134,6 @@ def persist_notification(
|
||||
current_app.logger.info('Persisting notification with type: {}'.format(EMAIL_TYPE))
|
||||
notification.normalised_to = format_email_address(notification.to)
|
||||
current_app.logger.info('Persisting notification to formatted email: {}'.format(notification.normalised_to))
|
||||
elif notification_type == LETTER_TYPE:
|
||||
notification.postage = postage
|
||||
notification.international = postage in INTERNATIONAL_POSTAGE_TYPES
|
||||
notification.normalised_to = ''.join(notification.to.split()).lower()
|
||||
|
||||
# if simulated create a Notification model to return but do not persist the Notification to the dB
|
||||
if not simulated:
|
||||
@@ -194,10 +175,6 @@ def send_notification_to_queue_detached(
|
||||
if not queue:
|
||||
queue = QueueNames.SEND_EMAIL
|
||||
deliver_task = provider_tasks.deliver_email
|
||||
if notification_type == LETTER_TYPE:
|
||||
if not queue:
|
||||
queue = QueueNames.CREATE_LETTERS_PDF
|
||||
deliver_task = get_pdf_for_templated_letter
|
||||
|
||||
try:
|
||||
deliver_task.apply_async([str(notification_id)], queue=queue)
|
||||
|
||||
@@ -5,13 +5,7 @@ from app import api_user, authenticated_service
|
||||
from app.config import QueueNames
|
||||
from app.dao import notifications_dao
|
||||
from app.errors import InvalidRequest, register_errors
|
||||
from app.models import (
|
||||
EMAIL_TYPE,
|
||||
KEY_TYPE_TEAM,
|
||||
LETTER_TYPE,
|
||||
PRIORITY,
|
||||
SMS_TYPE,
|
||||
)
|
||||
from app.models import EMAIL_TYPE, KEY_TYPE_TEAM, PRIORITY, SMS_TYPE
|
||||
from app.notifications.process_notifications import (
|
||||
persist_notification,
|
||||
send_notification_to_queue,
|
||||
@@ -81,7 +75,6 @@ def send_notification(notification_type):
|
||||
|
||||
if notification_type not in [SMS_TYPE, EMAIL_TYPE]:
|
||||
msg = "{} notification type is not supported".format(notification_type)
|
||||
msg = msg + ", please use the latest version of the client" if notification_type == LETTER_TYPE else msg
|
||||
raise InvalidRequest(msg, 400)
|
||||
|
||||
notification_form = (
|
||||
@@ -111,7 +104,6 @@ def send_notification(notification_type):
|
||||
simulated = simulated_recipient(notification_form['to'], notification_type)
|
||||
notification_model = persist_notification(template_id=template.id,
|
||||
template_version=template.version,
|
||||
postage=template.postage,
|
||||
recipient=request.get_json()['to'],
|
||||
service=authenticated_service,
|
||||
personalisation=notification_form.get('personalisation', None),
|
||||
|
||||
@@ -5,7 +5,6 @@ from notifications_utils.clients.redis import (
|
||||
daily_limit_cache_key,
|
||||
rate_limit_cache_key,
|
||||
)
|
||||
from notifications_utils.postal_address import PostalAddress
|
||||
from notifications_utils.recipients import (
|
||||
get_international_phone_info,
|
||||
validate_and_format_email_address,
|
||||
@@ -15,15 +14,12 @@ from sqlalchemy.orm.exc import NoResultFound
|
||||
|
||||
from app import redis_store
|
||||
from app.dao.service_email_reply_to_dao import dao_get_reply_to_by_id
|
||||
from app.dao.service_letter_contact_dao import dao_get_letter_contact_by_id
|
||||
from app.dao.service_sms_sender_dao import dao_get_service_sms_senders_by_id
|
||||
from app.models import (
|
||||
EMAIL_TYPE,
|
||||
INTERNATIONAL_LETTERS,
|
||||
INTERNATIONAL_SMS_TYPE,
|
||||
KEY_TYPE_TEAM,
|
||||
KEY_TYPE_TEST,
|
||||
LETTER_TYPE,
|
||||
SMS_TYPE,
|
||||
ServicePermission,
|
||||
)
|
||||
@@ -33,12 +29,7 @@ from app.notifications.process_notifications import (
|
||||
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
|
||||
from app.v2.errors import (
|
||||
BadRequestError,
|
||||
RateLimitError,
|
||||
TooManyRequestsError,
|
||||
ValidationError,
|
||||
)
|
||||
from app.v2.errors import BadRequestError, RateLimitError, TooManyRequestsError
|
||||
|
||||
REDIS_EXCEEDED_RATE_LIMIT_DURATION_SECONDS = Histogram(
|
||||
'redis_exceeded_rate_limit_duration_seconds',
|
||||
@@ -208,8 +199,6 @@ def check_reply_to(service_id, reply_to_id, type_):
|
||||
return check_service_email_reply_to_id(service_id, reply_to_id, type_)
|
||||
elif type_ == SMS_TYPE:
|
||||
return check_service_sms_sender_id(service_id, reply_to_id, type_)
|
||||
elif type_ == LETTER_TYPE:
|
||||
return check_service_letter_contact_id(service_id, reply_to_id, type_)
|
||||
|
||||
|
||||
def check_service_email_reply_to_id(service_id, reply_to_id, notification_type):
|
||||
@@ -230,44 +219,3 @@ def check_service_sms_sender_id(service_id, sms_sender_id, notification_type):
|
||||
message = 'sms_sender_id {} does not exist in database for service id {}' \
|
||||
.format(sms_sender_id, service_id)
|
||||
raise BadRequestError(message=message)
|
||||
|
||||
|
||||
def check_service_letter_contact_id(service_id, letter_contact_id, notification_type):
|
||||
if letter_contact_id:
|
||||
try:
|
||||
return dao_get_letter_contact_by_id(service_id, letter_contact_id).contact_block
|
||||
except NoResultFound:
|
||||
message = 'letter_contact_id {} does not exist in database for service id {}' \
|
||||
.format(letter_contact_id, service_id)
|
||||
raise BadRequestError(message=message)
|
||||
|
||||
|
||||
def validate_address(service, letter_data):
|
||||
address = PostalAddress.from_personalisation(
|
||||
letter_data,
|
||||
allow_international_letters=(INTERNATIONAL_LETTERS in str(service.permissions)),
|
||||
)
|
||||
if not address.has_enough_lines:
|
||||
raise ValidationError(
|
||||
message=f'Address must be at least {PostalAddress.MIN_LINES} lines'
|
||||
)
|
||||
if address.has_too_many_lines:
|
||||
raise ValidationError(
|
||||
message=f'Address must be no more than {PostalAddress.MAX_LINES} lines'
|
||||
)
|
||||
if not address.has_valid_last_line:
|
||||
if address.allow_international_letters:
|
||||
raise ValidationError(
|
||||
message='Last line of address must be a real UK postcode or another country'
|
||||
)
|
||||
raise ValidationError(
|
||||
message='Must be a real UK postcode'
|
||||
)
|
||||
if address.has_invalid_characters:
|
||||
raise ValidationError(
|
||||
message='Address lines must not start with any of the following characters: @ ( ) = [ ] ” \\ / , < >'
|
||||
)
|
||||
if address.international:
|
||||
return address.postage
|
||||
else:
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user