remove letters from app/template

This commit is contained in:
stvnrlly
2022-12-07 22:17:01 -05:00
parent 42447fcb8c
commit 14a1d499fa
6 changed files with 41 additions and 892 deletions

View File

@@ -132,28 +132,3 @@ def dao_get_template_versions(service_id, template_id):
).order_by(
desc(TemplateHistory.version)
).all()
def get_precompiled_letter_template(service_id):
template = Template.query.filter_by(
service_id=service_id,
template_type=LETTER_TYPE,
hidden=True
).first()
if template is not None:
return template
template = Template(
name='Pre-compiled PDF',
created_by=get_user_by_id(current_app.config['NOTIFY_USER_ID']),
service_id=service_id,
template_type=LETTER_TYPE,
hidden=True,
subject='Pre-compiled PDF',
content='',
postage=SECOND_CLASS
)
dao_create_template(template)
return template

View File

@@ -1,30 +1,13 @@
import urllib
from flask import current_app
from notifications_utils.s3 import S3ObjectNotFound
from notifications_utils.s3 import s3download as utils_s3download
from sqlalchemy.orm.exc import NoResultFound
from app import create_random_identifier
from app.config import QueueNames
from app.dao.notifications_dao import (
_update_notification_status,
get_notification_by_id,
)
from app.dao.notifications_dao import _update_notification_status
from app.dao.service_email_reply_to_dao import dao_get_reply_to_by_id
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,
get_precompiled_letter_template,
)
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.letters.utils import (
generate_letter_pdf_filename,
get_billable_units_for_letter_page_count,
get_page_count,
move_uploaded_pdf_to_letters_bucket,
)
from app.models import (
EMAIL_TYPE,
KEY_TYPE_NORMAL,
@@ -38,7 +21,6 @@ from app.notifications.process_notifications import (
send_notification_to_queue,
)
from app.notifications.validators import (
check_service_has_permission,
check_service_over_daily_message_limit,
validate_address,
validate_and_format_recipient,
@@ -151,72 +133,3 @@ def get_reply_to_text(notification_type, sender_id, service, template):
else:
reply_to = template.get_reply_to_text()
return reply_to
def send_pdf_letter_notification(service_id, post_data):
service = dao_fetch_service_by_id(service_id)
check_service_has_permission(LETTER_TYPE, [
p.permission for p in service.permissions
])
check_service_over_daily_message_limit(KEY_TYPE_NORMAL, service)
validate_created_by(service, post_data['created_by'])
validate_and_format_recipient(
send_to=post_data['recipient_address'],
key_type=KEY_TYPE_NORMAL,
service=service,
notification_type=LETTER_TYPE,
allow_guest_list_recipients=False,
)
# notification already exists e.g. if the user clicked send in different tabs
if get_notification_by_id(post_data['file_id']):
return {'id': str(post_data['file_id'])}
template = get_precompiled_letter_template(service.id)
file_location = 'service-{}/{}.pdf'.format(service.id, post_data['file_id'])
try:
letter = utils_s3download(current_app.config['TRANSIENT_UPLOADED_LETTERS'], file_location)
except S3ObjectNotFound as e:
current_app.logger.warning('Letter {}.pdf not in transient {} bucket'.format(
post_data['file_id'], current_app.config['TRANSIENT_UPLOADED_LETTERS'])
)
raise e
# Getting the page count won't raise an error since admin has already checked the PDF is valid
page_count = get_page_count(letter.read())
billable_units = get_billable_units_for_letter_page_count(page_count)
personalisation = {
'address_line_1': post_data['filename']
}
notification = persist_notification(
notification_id=post_data['file_id'],
template_id=template.id,
template_version=template.version,
recipient=urllib.parse.unquote(post_data['recipient_address']),
service=service,
personalisation=personalisation,
notification_type=LETTER_TYPE,
api_key_id=None,
key_type=KEY_TYPE_NORMAL,
reference=create_one_off_reference(LETTER_TYPE),
client_reference=post_data['filename'],
created_by_id=post_data['created_by'],
billable_units=billable_units,
postage=post_data['postage'] or template.postage,
)
upload_filename = generate_letter_pdf_filename(
reference=notification.reference,
created_at=notification.created_at,
ignore_folder=False,
postage=notification.postage
)
move_uploaded_pdf_to_letters_bucket(file_location, upload_filename)
return {'id': str(notification.id)}

View File

@@ -1,16 +1,8 @@
import base64
from io import BytesIO
import botocore
from flask import Blueprint, current_app, jsonify, request
from flask import Blueprint, jsonify, request
from notifications_utils import SMS_CHAR_COUNT_LIMIT
from notifications_utils.pdf import extract_page_from_pdf
from notifications_utils.template import SMSMessageTemplate
from PyPDF2.errors import PdfReadError
from requests import post as requests_post
from sqlalchemy.orm.exc import NoResultFound
from app.dao.notifications_dao import get_notification_by_id
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,
@@ -18,17 +10,14 @@ from app.dao.template_folder_dao import (
from app.dao.templates_dao import (
dao_create_template,
dao_get_all_templates_for_service,
dao_get_template_by_id,
dao_get_template_by_id_and_service_id,
dao_get_template_versions,
dao_redact_template,
dao_update_template,
dao_update_template_reply_to,
get_precompiled_letter_template,
)
from app.errors import InvalidRequest, register_errors
from app.letters.utils import get_letter_pdf_and_metadata
from app.models import LETTER_TYPE, SECOND_CLASS, SMS_TYPE, Template
from app.models import SMS_TYPE, Template
from app.notifications.validators import check_reply_to, service_has_permission
from app.schema_validation import validate
from app.schemas import (
@@ -84,9 +73,6 @@ def create_template(service_id):
errors = {'template_type': [message]}
raise InvalidRequest(errors, 403)
if not new_template.postage and new_template.template_type == LETTER_TYPE:
new_template.postage = SECOND_CLASS
new_template.service = fetched_service
over_limit = _content_count_greater_than_limit(new_template.content, new_template.template_type)
@@ -151,14 +137,6 @@ def update_template(service_id, template_id):
return jsonify(data=template_schema.dump(update_dict)), 200
@template_blueprint.route('/precompiled', methods=['GET'])
def get_precompiled_template_for_service(service_id):
template = get_precompiled_letter_template(service_id)
template_dict = template_schema.dump(template)
return jsonify(template_dict), 200
@template_blueprint.route('', methods=['GET'])
def get_all_templates_for_service(service_id):
templates = dao_get_all_templates_for_service(service_id=service_id)
@@ -236,116 +214,3 @@ def redact_template(template, data):
if not template.redact_personalisation:
dao_redact_template(template, data['created_by'])
return 'null', 200
@template_blueprint.route('/preview/<uuid:notification_id>/<file_type>', methods=['GET'])
def preview_letter_template_by_notification_id(service_id, notification_id, file_type):
if file_type not in ('pdf', 'png'):
raise InvalidRequest({'content': ["file_type must be pdf or png"]}, status_code=400)
page = request.args.get('page')
notification = get_notification_by_id(notification_id)
template = dao_get_template_by_id(notification.template_id, notification.template_version)
metadata = {}
if template.is_precompiled_letter:
try:
pdf_file, metadata = get_letter_pdf_and_metadata(notification)
except botocore.exceptions.ClientError as e:
raise InvalidRequest(
'Error extracting requested page from PDF file for notification_id {} type {} {}'.format(
notification_id, type(e), e),
status_code=500
)
page_number = page if page else "1"
content = base64.b64encode(pdf_file).decode('utf-8')
content_outside_printable_area = metadata.get("message") == "content-outside-printable-area"
page_is_in_invalid_pages = page_number in metadata.get('invalid_pages', '[]')
if content_outside_printable_area and (file_type == "pdf" or page_is_in_invalid_pages):
path = '/precompiled/overlay.{}'.format(file_type)
query_string = '?page_number={}'.format(page_number) if file_type == 'png' else ''
content = pdf_file
elif file_type == 'png':
query_string = '?hide_notify=true' if page_number == '1' else ''
path = '/precompiled-preview.png'
else:
path = None
if file_type == 'png':
try:
pdf_page = extract_page_from_pdf(BytesIO(pdf_file), int(page_number) - 1)
if content_outside_printable_area and page_is_in_invalid_pages:
content = pdf_page
else:
content = base64.b64encode(pdf_page).decode('utf-8')
except PdfReadError as e:
raise InvalidRequest(
'Error extracting requested page from PDF file for notification_id {} type {} {}'.format(
notification_id, type(e), e),
status_code=500
)
if path:
url = current_app.config['TEMPLATE_PREVIEW_API_HOST'] + path + query_string
response_content = _get_png_preview_or_overlaid_pdf(url, content, notification.id, json=False)
else:
response_content = content
else:
template_for_letter_print = {
"id": str(notification.template_id),
"subject": template.subject,
"content": template.content,
"version": str(template.version),
"template_type": template.template_type
}
service = dao_fetch_service_by_id(service_id)
letter_logo_filename = service.letter_branding and service.letter_branding.filename
data = {
'letter_contact_block': notification.reply_to_text,
'template': template_for_letter_print,
'values': notification.personalisation,
'date': notification.created_at.isoformat(),
'filename': letter_logo_filename,
}
url = '{}/preview.{}{}'.format(
current_app.config['TEMPLATE_PREVIEW_API_HOST'],
file_type,
'?page={}'.format(page) if page else ''
)
response_content = _get_png_preview_or_overlaid_pdf(url, data, notification.id, json=True)
return jsonify({"content": response_content, "metadata": metadata})
def _get_png_preview_or_overlaid_pdf(url, data, notification_id, json=True):
if json:
resp = requests_post(
url,
json=data,
headers={'Authorization': 'Token {}'.format(current_app.config['TEMPLATE_PREVIEW_API_KEY'])}
)
else:
resp = requests_post(
url,
data=data,
headers={'Authorization': 'Token {}'.format(current_app.config['TEMPLATE_PREVIEW_API_KEY'])}
)
if resp.status_code != 200:
raise InvalidRequest(
'Error generating preview letter for {} Status code: {} {}'.format(
notification_id,
resp.status_code,
resp.content
), status_code=500
)
return base64.b64encode(resp.content).decode('utf-8')

View File

@@ -19,7 +19,7 @@ post_create_template_schema = {
},
"if": {
"properties": {
"template_type": {"enum": ["email", "letter"]}
"template_type": {"enum": ["email"]}
}
},
"then": {"required": ["subject"]},

View File

@@ -19,7 +19,6 @@ from app.celery.tasks import save_api_email, save_api_sms
from app.clients.document_download import DocumentDownloadError
from app.config import QueueNames, TaskNames
from app.dao.dao_utils import transaction
from app.dao.templates_dao import get_precompiled_letter_template
from app.letters.utils import upload_letter_pdf
from app.models import (
EMAIL_TYPE,
@@ -66,7 +65,6 @@ from app.v2.notifications.create_response import (
from app.v2.notifications.notification_schemas import (
post_email_request,
post_letter_request,
post_precompiled_letter_request,
post_sms_request,
)
from app.v2.utils import get_valid_json
@@ -77,38 +75,39 @@ POST_NOTIFICATION_JSON_PARSE_DURATION_SECONDS = Histogram(
)
@v2_notification_blueprint.route('/{}'.format(LETTER_TYPE), methods=['POST'])
def post_precompiled_letter_notification():
request_json = get_valid_json()
if 'content' not in (request_json or {}):
return post_notification(LETTER_TYPE)
# TODO: return deprecation message
# @v2_notification_blueprint.route('/{}'.format(LETTER_TYPE), methods=['POST'])
# def post_precompiled_letter_notification():
# request_json = get_valid_json()
# if 'content' not in (request_json or {}):
# return post_notification(LETTER_TYPE)
form = validate(request_json, post_precompiled_letter_request)
# form = validate(request_json, post_precompiled_letter_request)
# Check permission to send letters
check_service_has_permission(LETTER_TYPE, authenticated_service.permissions)
# # Check permission to send letters
# check_service_has_permission(LETTER_TYPE, authenticated_service.permissions)
check_rate_limiting(authenticated_service, api_user)
# check_rate_limiting(authenticated_service, api_user)
template = get_precompiled_letter_template(authenticated_service.id)
# template = get_precompiled_letter_template(authenticated_service.id)
# For precompiled letters the to field will be set to Provided as PDF until the validation passes,
# then the address of the letter will be set as the to field
form['personalisation'] = {
'address_line_1': 'Provided as PDF'
}
# # For precompiled letters the to field will be set to Provided as PDF until the validation passes,
# # then the address of the letter will be set as the to field
# form['personalisation'] = {
# 'address_line_1': 'Provided as PDF'
# }
notification = process_letter_notification(
letter_data=form,
api_key=api_user,
service=authenticated_service,
template=template,
template_with_content=None, # not required for precompiled
reply_to_text='', # not required for precompiled
precompiled=True
)
# notification = process_letter_notification(
# letter_data=form,
# api_key=api_user,
# service=authenticated_service,
# template=template,
# template_with_content=None, # not required for precompiled
# reply_to_text='', # not required for precompiled
# precompiled=True
# )
return jsonify(notification), 201
# return jsonify(notification), 201
@v2_notification_blueprint.route('/<notification_type>', methods=['POST'])
@@ -120,8 +119,6 @@ def post_notification(notification_type):
form = validate(request_json, post_email_request)
elif notification_type == SMS_TYPE:
form = validate(request_json, post_sms_request)
elif notification_type == LETTER_TYPE:
form = validate(request_json, post_letter_request)
else:
abort(404)
@@ -139,25 +136,16 @@ def post_notification(notification_type):
reply_to = get_reply_to_text(notification_type, form, template)
if notification_type == LETTER_TYPE:
notification = process_letter_notification(
letter_data=form,
api_key=api_user,
service=authenticated_service,
template=template,
template_with_content=template_with_content,
reply_to_text=reply_to
)
else:
notification = process_sms_or_email_notification(
form=form,
notification_type=notification_type,
template=template,
template_with_content=template_with_content,
template_process_type=template.process_type,
service=authenticated_service,
reply_to_text=reply_to
)
notification = process_sms_or_email_notification(
form=form,
notification_type=notification_type,
template=template,
template_with_content=template_with_content,
template_process_type=template.process_type,
service=authenticated_service,
reply_to_text=reply_to
)
return jsonify(notification), 201
@@ -443,9 +431,6 @@ def get_reply_to_text(notification_type, form, template):
else:
reply_to = template.reply_to_text
elif notification_type == LETTER_TYPE:
reply_to = template.reply_to_text
return reply_to
@@ -470,11 +455,6 @@ def create_response_for_post_notification(
subject=template_with_content.subject,
email_from='{}@{}'.format(authenticated_service.email_from, current_app.config['NOTIFY_EMAIL_DOMAIN']),
)
elif notification_type == LETTER_TYPE:
create_resp_partial = functools.partial(
create_post_letter_response_from_notification,
subject=template_with_content.subject,
)
resp = create_resp_partial(
notification_id, client_reference, template_id, template_version, service_id,
url_root=request.url_root,

View File

@@ -1131,587 +1131,3 @@ def test_update_redact_template_400s_if_no_created_by(admin_request, sample_temp
assert sample_template.redact_personalisation is False
assert sample_template.template_redacted.updated_at == original_updated_time
def test_preview_letter_template_by_id_invalid_file_type(
sample_letter_notification,
admin_request):
resp = admin_request.get(
'template.preview_letter_template_by_notification_id',
service_id=sample_letter_notification.service_id,
template_id=sample_letter_notification.template_id,
notification_id=sample_letter_notification.id,
file_type='doc',
_expected_status=400
)
assert ['file_type must be pdf or png'] == resp['message']['content']
@freeze_time('2012-12-12')
@pytest.mark.parametrize('file_type', ('png', 'pdf'))
def test_preview_letter_template_by_id_valid_file_type(
notify_api,
sample_letter_notification,
admin_request,
file_type,
):
sample_letter_notification.created_at = datetime.utcnow()
with set_config_values(notify_api, {
'TEMPLATE_PREVIEW_API_HOST': 'http://localhost/notifications-template-preview',
'TEMPLATE_PREVIEW_API_KEY': 'test-key'
}):
with requests_mock.Mocker() as request_mock:
content = b'\x00\x01'
mock_post = request_mock.post(
'http://localhost/notifications-template-preview/preview.{}'.format(file_type),
content=content,
headers={'X-pdf-page-count': '1'},
status_code=200
)
resp = admin_request.get(
'template.preview_letter_template_by_notification_id',
service_id=sample_letter_notification.service_id,
notification_id=sample_letter_notification.id,
file_type=file_type,
)
post_json = mock_post.last_request.json()
assert post_json['template']['id'] == str(sample_letter_notification.template_id)
assert post_json['values'] == {
'address_line_1': 'A1',
'address_line_2': 'A2',
'address_line_3': 'A3',
'address_line_4': 'A4',
'address_line_5': 'A5',
'address_line_6': 'A6',
'postcode': 'A_POST',
}
assert post_json['date'] == '2012-12-12T00:00:00'
assert post_json['filename'] is None
assert base64.b64decode(resp['content']) == content
@freeze_time('2012-12-12')
def test_preview_letter_template_by_id_shows_template_version_used_by_notification(
notify_api,
sample_letter_notification,
sample_letter_template,
admin_request
):
sample_letter_notification.created_at = datetime.utcnow()
assert sample_letter_notification.template_version == 1
# Create a new template history to check that our preview doesn't use the newest version
# but instead the one linked with the notification
sample_letter_template.content = 'new content'
dao_update_template(sample_letter_template)
versions = dao_get_template_versions(sample_letter_notification.service.id, sample_letter_template.id)
assert len(versions) == 2
with set_config_values(notify_api, {
'TEMPLATE_PREVIEW_API_HOST': 'http://localhost/notifications-template-preview',
'TEMPLATE_PREVIEW_API_KEY': 'test-key'
}):
with requests_mock.Mocker() as request_mock:
content = b'\x00\x01'
mock_post = request_mock.post(
'http://localhost/notifications-template-preview/preview.png',
content=content,
headers={'X-pdf-page-count': '1'},
status_code=200
)
admin_request.get(
'template.preview_letter_template_by_notification_id',
service_id=sample_letter_notification.service_id,
notification_id=sample_letter_notification.id,
file_type='png',
)
post_json = mock_post.last_request.json()
assert post_json['template']['id'] == str(sample_letter_notification.template_id)
assert post_json['template']['version'] == '1'
def test_preview_letter_template_by_id_template_preview_500(
notify_api,
client,
admin_request,
sample_letter_notification):
with set_config_values(notify_api, {
'TEMPLATE_PREVIEW_API_HOST': 'http://localhost/notifications-template-preview',
'TEMPLATE_PREVIEW_API_KEY': 'test-key'
}):
import requests_mock
with requests_mock.Mocker() as request_mock:
content = b'\x00\x01'
mock_post = request_mock.post(
'http://localhost/notifications-template-preview/preview.pdf',
content=content,
headers={'X-pdf-page-count': '1'},
status_code=404
)
resp = admin_request.get(
'template.preview_letter_template_by_notification_id',
service_id=sample_letter_notification.service_id,
notification_id=sample_letter_notification.id,
file_type='pdf',
_expected_status=500
)
assert mock_post.last_request.json()
assert 'Status code: 404' in resp['message']
assert 'Error generating preview letter for {}'.format(sample_letter_notification.id) in resp['message']
def test_preview_letter_template_precompiled_pdf_file_type(
notify_api,
client,
admin_request,
sample_service,
mocker
):
template = create_template(sample_service,
template_type='letter',
template_name='Pre-compiled PDF',
subject='Pre-compiled PDF',
hidden=True)
notification = create_notification(template)
with set_config_values(notify_api, {
'TEMPLATE_PREVIEW_API_HOST': 'http://localhost/notifications-template-preview',
'TEMPLATE_PREVIEW_API_KEY': 'test-key'
}):
with requests_mock.Mocker():
content = b'\x00\x01'
mock_get_letter_pdf = mocker.patch(
'app.template.rest.get_letter_pdf_and_metadata',
return_value=(content, {
"message": "",
"invalid_pages": "",
"page_count": "1"
})
)
resp = admin_request.get(
'template.preview_letter_template_by_notification_id',
service_id=notification.service_id,
notification_id=notification.id,
file_type='pdf'
)
assert mock_get_letter_pdf.called_once_with(notification)
assert base64.b64decode(resp['content']) == content
def test_preview_letter_template_precompiled_s3_error(
notify_api,
client,
admin_request,
sample_service,
mocker
):
template = create_template(sample_service,
template_type='letter',
template_name='Pre-compiled PDF',
subject='Pre-compiled PDF',
hidden=True)
notification = create_notification(template)
with set_config_values(notify_api, {
'TEMPLATE_PREVIEW_API_HOST': 'http://localhost/notifications-template-preview',
'TEMPLATE_PREVIEW_API_KEY': 'test-key'
}):
with requests_mock.Mocker():
mocker.patch('app.template.rest.get_letter_pdf_and_metadata',
side_effect=botocore.exceptions.ClientError(
{'Error': {'Code': '403', 'Message': 'Unauthorized'}},
'GetObject'
))
request = admin_request.get(
'template.preview_letter_template_by_notification_id',
service_id=notification.service_id,
notification_id=notification.id,
file_type='pdf',
_expected_status=500
)
assert request['message'] == "Error extracting requested page from PDF file for notification_id {} type " \
"<class 'botocore.exceptions.ClientError'> An error occurred (403) " \
"when calling the GetObject operation: Unauthorized".format(notification.id)
@pytest.mark.parametrize(
"requested_page, message, expected_post_url",
[
# page defaults to 1, page is valid, no overlay shown
("", "", 'precompiled-preview.png'),
# page is valid, no overlay shown
("1", "", 'precompiled-preview.png'),
# page is invalid but not because content is outside printable area so no overlay
("1", "letter-not-a4-portrait-oriented", 'precompiled-preview.png'),
# page is invalid, overlay shown
("1", "content-outside-printable-area", 'precompiled/overlay.png?page_number=1'),
# page is valid, no overlay shown
("2", "content-outside-printable-area", 'precompiled-preview.png'),
# page is invalid, overlay shown
("3", "content-outside-printable-area", 'precompiled/overlay.png?page_number=3'),
]
)
def test_preview_letter_template_precompiled_for_png_shows_overlay_on_pages_with_content_outside_printable_area(
notify_api,
client,
admin_request,
sample_service,
mocker,
requested_page,
message,
expected_post_url,
):
template = create_template(sample_service,
template_type='letter',
template_name='Pre-compiled PDF',
subject='Pre-compiled PDF',
hidden=True)
notification = create_notification(template)
with set_config_values(notify_api, {
'TEMPLATE_PREVIEW_API_HOST': 'http://localhost/notifications-template-preview',
'TEMPLATE_PREVIEW_API_KEY': 'test-key'
}):
with requests_mock.Mocker() as request_mock:
pdf_content = b'\x00\x01'
expected_returned_content = b'\x00\x02'
metadata = {
"message": message,
"invalid_pages": "[1,3]",
"page_count": "4"
}
mock_get_letter_pdf = mocker.patch(
'app.template.rest.get_letter_pdf_and_metadata',
return_value=(pdf_content, metadata)
)
mocker.patch('app.template.rest.extract_page_from_pdf', return_value=pdf_content)
mock_post = request_mock.post(
'http://localhost/notifications-template-preview/{}'.format(expected_post_url),
content=expected_returned_content,
headers={'X-pdf-page-count': '4'},
status_code=200
)
response = admin_request.get(
'template.preview_letter_template_by_notification_id',
page=requested_page,
service_id=notification.service_id,
notification_id=notification.id,
file_type="png",
)
with pytest.raises(ValueError):
mock_post.last_request.json()
assert mock_get_letter_pdf.called_once_with(notification)
assert base64.b64decode(response['content']) == expected_returned_content
assert response["metadata"] == metadata
@pytest.mark.parametrize(
"invalid_pages",
[
"[1,3]",
"[2,4]", # it shouldn't make a difference if the error was on the first page or not
]
)
def test_preview_letter_template_precompiled_for_pdf_shows_overlay_on_all_pages_if_content_outside_printable_area(
notify_api,
client,
admin_request,
sample_service,
mocker,
invalid_pages,
):
template = create_template(sample_service,
template_type='letter',
template_name='Pre-compiled PDF',
subject='Pre-compiled PDF',
hidden=True)
notification = create_notification(template)
with set_config_values(notify_api, {
'TEMPLATE_PREVIEW_API_HOST': 'http://localhost/notifications-template-preview',
'TEMPLATE_PREVIEW_API_KEY': 'test-key'
}):
with requests_mock.Mocker() as request_mock:
pdf_content = b'\x00\x01'
expected_returned_content = b'\x00\x02'
metadata = {
"message": "content-outside-printable-area",
"invalid_pages": invalid_pages,
"page_count": "4"
}
mock_get_letter_pdf = mocker.patch(
'app.template.rest.get_letter_pdf_and_metadata',
return_value=(pdf_content, metadata)
)
mocker.patch('app.template.rest.extract_page_from_pdf', return_value=pdf_content)
mock_post = request_mock.post(
'http://localhost/notifications-template-preview/precompiled/overlay.pdf',
content=expected_returned_content,
headers={'X-pdf-page-count': '4'},
status_code=200
)
response = admin_request.get(
'template.preview_letter_template_by_notification_id',
service_id=notification.service_id,
notification_id=notification.id,
file_type="pdf",
)
with pytest.raises(ValueError):
mock_post.last_request.json()
assert mock_get_letter_pdf.called_once_with(notification)
assert base64.b64decode(response['content']) == expected_returned_content
assert response["metadata"] == metadata
@pytest.mark.parametrize('page_number,expect_preview_url', [
('', 'http://localhost/notifications-template-preview/precompiled-preview.png?hide_notify=true'),
('1', 'http://localhost/notifications-template-preview/precompiled-preview.png?hide_notify=true'),
('2', 'http://localhost/notifications-template-preview/precompiled-preview.png')
])
def test_preview_letter_template_precompiled_png_file_type_hide_notify_tag_only_on_first_page(
notify_api,
client,
admin_request,
sample_service,
mocker,
page_number,
expect_preview_url
):
template = create_template(sample_service,
template_type='letter',
template_name='Pre-compiled PDF',
subject='Pre-compiled PDF',
hidden=True)
notification = create_notification(template)
with set_config_values(notify_api, {
'TEMPLATE_PREVIEW_API_HOST': 'http://localhost/notifications-template-preview',
'TEMPLATE_PREVIEW_API_KEY': 'test-key'
}):
pdf_content = b'\x00\x01'
png_content = b'\x00\x02'
encoded = base64.b64encode(png_content).decode('utf-8')
mocker.patch(
'app.template.rest.get_letter_pdf_and_metadata',
return_value=(pdf_content, {
"message": "",
"invalid_pages": "",
"page_count": "2"
})
)
mocker.patch('app.template.rest.extract_page_from_pdf', return_value=png_content)
mock_get_png_preview = mocker.patch('app.template.rest._get_png_preview_or_overlaid_pdf', return_value=encoded)
admin_request.get(
'template.preview_letter_template_by_notification_id',
service_id=notification.service_id,
notification_id=notification.id,
file_type='png',
page=page_number
)
mock_get_png_preview.assert_called_once_with(
expect_preview_url, encoded, notification.id, json=False
)
def test_preview_letter_template_precompiled_png_template_preview_500_error(
notify_api,
client,
admin_request,
sample_service,
mocker
):
template = create_template(sample_service,
template_type='letter',
template_name='Pre-compiled PDF',
subject='Pre-compiled PDF',
hidden=True)
notification = create_notification(template)
with set_config_values(notify_api, {
'TEMPLATE_PREVIEW_API_HOST': 'http://localhost/notifications-template-preview',
'TEMPLATE_PREVIEW_API_KEY': 'test-key'
}):
with requests_mock.Mocker() as request_mock:
pdf_content = b'\x00\x01'
png_content = b'\x00\x02'
mocker.patch('app.template.rest.get_letter_pdf_and_metadata', return_value=(pdf_content, {
"message": "",
"invalid_pages": "",
"page_count": "1"
}))
mocker.patch('app.template.rest.extract_page_from_pdf', return_value=pdf_content)
mock_post = request_mock.post(
'http://localhost/notifications-template-preview/precompiled-preview.png',
content=png_content,
headers={'X-pdf-page-count': '1'},
status_code=500
)
admin_request.get(
'template.preview_letter_template_by_notification_id',
service_id=notification.service_id,
notification_id=notification.id,
file_type='png',
_expected_status=500
)
with pytest.raises(ValueError):
mock_post.last_request.json()
def test_preview_letter_template_precompiled_png_template_preview_400_error(
notify_api,
client,
admin_request,
sample_service,
mocker
):
template = create_template(sample_service,
template_type='letter',
template_name='Pre-compiled PDF',
subject='Pre-compiled PDF',
hidden=True)
notification = create_notification(template)
with set_config_values(notify_api, {
'TEMPLATE_PREVIEW_API_HOST': 'http://localhost/notifications-template-preview',
'TEMPLATE_PREVIEW_API_KEY': 'test-key'
}):
with requests_mock.Mocker() as request_mock:
pdf_content = b'\x00\x01'
png_content = b'\x00\x02'
mocker.patch('app.template.rest.get_letter_pdf_and_metadata', return_value=(pdf_content, {
"message": "",
"invalid_pages": "",
"page_count": "1"
}))
mocker.patch('app.template.rest.extract_page_from_pdf', return_value=pdf_content)
mock_post = request_mock.post(
'http://localhost/notifications-template-preview/precompiled-preview.png',
content=png_content,
headers={'X-pdf-page-count': '1'},
status_code=404
)
admin_request.get(
'template.preview_letter_template_by_notification_id',
service_id=notification.service_id,
notification_id=notification.id,
file_type='png',
_expected_status=500
)
with pytest.raises(ValueError):
mock_post.last_request.json()
def test_preview_letter_template_precompiled_png_template_preview_pdf_error(
notify_api,
client,
admin_request,
sample_service,
mocker
):
template = create_template(sample_service,
template_type='letter',
template_name='Pre-compiled PDF',
subject='Pre-compiled PDF',
hidden=True)
notification = create_notification(template)
with set_config_values(notify_api, {
'TEMPLATE_PREVIEW_API_HOST': 'http://localhost/notifications-template-preview',
'TEMPLATE_PREVIEW_API_KEY': 'test-key'
}):
with requests_mock.Mocker() as request_mock:
pdf_content = b'\x00\x01'
png_content = b'\x00\x02'
mocker.patch('app.template.rest.get_letter_pdf_and_metadata', return_value=(pdf_content, {
"message": "",
"invalid_pages": "",
"page_count": "1"
}))
error_message = "PDF Error message"
mocker.patch('app.template.rest.extract_page_from_pdf', side_effect=PdfReadError(error_message))
request_mock.post(
'http://localhost/notifications-template-preview/precompiled-preview.png',
content=png_content,
headers={'X-pdf-page-count': '1'},
status_code=404
)
request = admin_request.get(
'template.preview_letter_template_by_notification_id',
service_id=notification.service_id,
notification_id=notification.id,
file_type='png',
_expected_status=500
)
assert request['message'] == "Error extracting requested page from PDF file for notification_id {} type " \
"{} {}".format(notification.id, type(PdfReadError()), error_message)