mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-09-08 06:38:26 -04:00
Merge pull request #3201 from alphagov/remove-letter-validation-preview
Remove the letter validation preview endpoints
This commit is contained in:
@@ -386,77 +386,6 @@ def platform_admin_returned_letters():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@main.route("/platform-admin/letter-validation-preview", methods=["GET", "POST"])
|
|
||||||
@user_is_platform_admin
|
|
||||||
def platform_admin_letter_validation_preview():
|
|
||||||
return letter_validation_preview(from_platform_admin=True)
|
|
||||||
|
|
||||||
|
|
||||||
@main.route("/services/<uuid:service_id>/letter-validation-preview", methods=["GET", "POST"])
|
|
||||||
@user_has_permissions()
|
|
||||||
def service_letter_validation_preview(service_id):
|
|
||||||
return letter_validation_preview(from_platform_admin=False)
|
|
||||||
|
|
||||||
|
|
||||||
def letter_validation_preview(from_platform_admin):
|
|
||||||
message, pages, passed_validation, error_code = None, [], None, None
|
|
||||||
form = PDFUploadForm()
|
|
||||||
|
|
||||||
view_location = 'views/platform-admin/letter-validation-preview.html' \
|
|
||||||
if from_platform_admin else'views/letter-validation-preview.html'
|
|
||||||
|
|
||||||
if form.validate_on_submit():
|
|
||||||
pdf_file = form.file.data
|
|
||||||
virus_free = antivirus_client.scan(pdf_file)
|
|
||||||
|
|
||||||
if not virus_free:
|
|
||||||
return render_template(
|
|
||||||
view_location,
|
|
||||||
form=form, message="Document did not pass the virus scan",
|
|
||||||
pages=pages, passed_validation=passed_validation
|
|
||||||
), 400
|
|
||||||
|
|
||||||
try:
|
|
||||||
if len(pdf_file.read()) > (2 * 1024 * 1024):
|
|
||||||
return render_template(
|
|
||||||
view_location,
|
|
||||||
form=form,
|
|
||||||
message="File must be less than 2MB",
|
|
||||||
pages=pages, passed_validation=passed_validation
|
|
||||||
), 400
|
|
||||||
pdf_file.seek(0)
|
|
||||||
response = validate_letter(pdf_file)
|
|
||||||
response.raise_for_status()
|
|
||||||
if response.status_code == 200:
|
|
||||||
pages, message = response.json()["pages"], response.json()["message"],
|
|
||||||
passed_validation = response.json()["result"]
|
|
||||||
invalid_pages = response.json().get('invalid_pages')
|
|
||||||
page_count = len(pages)
|
|
||||||
if page_count > LETTER_MAX_PAGE_COUNT:
|
|
||||||
message = "letter-too-long"
|
|
||||||
passed_validation = False
|
|
||||||
|
|
||||||
if not passed_validation:
|
|
||||||
error_code = message
|
|
||||||
message = get_letter_validation_error(
|
|
||||||
message, invalid_pages=invalid_pages, page_count=page_count
|
|
||||||
)
|
|
||||||
except RequestException as error:
|
|
||||||
if error.response and error.response.status_code == 400:
|
|
||||||
message = "Something was wrong with the file you tried to upload. Please upload a valid PDF file."
|
|
||||||
return render_template(
|
|
||||||
view_location,
|
|
||||||
form=form, message=message, pages=pages, passed_validation=passed_validation
|
|
||||||
), 400
|
|
||||||
else:
|
|
||||||
raise error
|
|
||||||
|
|
||||||
return render_template(
|
|
||||||
view_location,
|
|
||||||
form=form, message=message, pages=pages, passed_validation=passed_validation, error_code=error_code
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@main.route("/platform-admin/clear-cache", methods=['GET', 'POST'])
|
@main.route("/platform-admin/clear-cache", methods=['GET', 'POST'])
|
||||||
@user_is_platform_admin
|
@user_is_platform_admin
|
||||||
def clear_cache():
|
def clear_cache():
|
||||||
|
|||||||
@@ -94,7 +94,6 @@ class HeaderNavigation(Navigation):
|
|||||||
'performance_platform_xlsx',
|
'performance_platform_xlsx',
|
||||||
'usage_for_all_services',
|
'usage_for_all_services',
|
||||||
'platform_admin',
|
'platform_admin',
|
||||||
'platform_admin_letter_validation_preview',
|
|
||||||
'platform_admin_list_complaints',
|
'platform_admin_list_complaints',
|
||||||
'platform_admin_reports',
|
'platform_admin_reports',
|
||||||
'platform_admin_returned_letters',
|
'platform_admin_returned_letters',
|
||||||
@@ -267,7 +266,6 @@ class HeaderNavigation(Navigation):
|
|||||||
'service_edit_sms_sender',
|
'service_edit_sms_sender',
|
||||||
'service_email_reply_to',
|
'service_email_reply_to',
|
||||||
'service_letter_contact_details',
|
'service_letter_contact_details',
|
||||||
'service_letter_validation_preview',
|
|
||||||
'service_make_blank_default_letter_contact',
|
'service_make_blank_default_letter_contact',
|
||||||
'service_name_change',
|
'service_name_change',
|
||||||
'service_name_change_confirm',
|
'service_name_change_confirm',
|
||||||
@@ -543,7 +541,6 @@ class MainNavigation(Navigation):
|
|||||||
'organisations',
|
'organisations',
|
||||||
'performance_platform_xlsx',
|
'performance_platform_xlsx',
|
||||||
'platform_admin',
|
'platform_admin',
|
||||||
'platform_admin_letter_validation_preview',
|
|
||||||
'platform_admin_list_complaints',
|
'platform_admin_list_complaints',
|
||||||
'platform_admin_reports',
|
'platform_admin_reports',
|
||||||
'platform_admin_returned_letters',
|
'platform_admin_returned_letters',
|
||||||
@@ -570,7 +567,6 @@ class MainNavigation(Navigation):
|
|||||||
'service_delete_letter_contact',
|
'service_delete_letter_contact',
|
||||||
'service_delete_sms_sender',
|
'service_delete_sms_sender',
|
||||||
'service_download_agreement',
|
'service_download_agreement',
|
||||||
'service_letter_validation_preview',
|
|
||||||
'service_switch_can_upload_document',
|
'service_switch_can_upload_document',
|
||||||
'service_switch_count_as_live',
|
'service_switch_count_as_live',
|
||||||
'service_switch_live',
|
'service_switch_live',
|
||||||
@@ -776,7 +772,6 @@ class CaseworkNavigation(Navigation):
|
|||||||
'organisation_settings',
|
'organisation_settings',
|
||||||
'organisations',
|
'organisations',
|
||||||
'performance_platform_xlsx',
|
'performance_platform_xlsx',
|
||||||
'platform_admin_letter_validation_preview',
|
|
||||||
'platform_admin_list_complaints',
|
'platform_admin_list_complaints',
|
||||||
'platform_admin_reports',
|
'platform_admin_reports',
|
||||||
'platform_admin_returned_letters',
|
'platform_admin_returned_letters',
|
||||||
@@ -826,7 +821,6 @@ class CaseworkNavigation(Navigation):
|
|||||||
'service_edit_sms_sender',
|
'service_edit_sms_sender',
|
||||||
'service_email_reply_to',
|
'service_email_reply_to',
|
||||||
'service_letter_contact_details',
|
'service_letter_contact_details',
|
||||||
'service_letter_validation_preview',
|
|
||||||
'service_make_blank_default_letter_contact',
|
'service_make_blank_default_letter_contact',
|
||||||
'service_name_change',
|
'service_name_change',
|
||||||
'service_name_change_confirm',
|
'service_name_change_confirm',
|
||||||
@@ -1055,7 +1049,6 @@ class OrgNavigation(Navigation):
|
|||||||
'organisations',
|
'organisations',
|
||||||
'performance_platform_xlsx',
|
'performance_platform_xlsx',
|
||||||
'platform_admin',
|
'platform_admin',
|
||||||
'platform_admin_letter_validation_preview',
|
|
||||||
'platform_admin_list_complaints',
|
'platform_admin_list_complaints',
|
||||||
'platform_admin_reports',
|
'platform_admin_reports',
|
||||||
'platform_admin_returned_letters',
|
'platform_admin_returned_letters',
|
||||||
@@ -1107,7 +1100,6 @@ class OrgNavigation(Navigation):
|
|||||||
'service_edit_sms_sender',
|
'service_edit_sms_sender',
|
||||||
'service_email_reply_to',
|
'service_email_reply_to',
|
||||||
'service_letter_contact_details',
|
'service_letter_contact_details',
|
||||||
'service_letter_validation_preview',
|
|
||||||
'service_make_blank_default_letter_contact',
|
'service_make_blank_default_letter_contact',
|
||||||
'service_name_change',
|
'service_name_change',
|
||||||
'service_name_change_confirm',
|
'service_name_change_confirm',
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
{% extends "withnav_template.html" %}
|
|
||||||
{% from "components/banner.html" import banner %}
|
|
||||||
{% from "components/textbox.html" import textbox %}
|
|
||||||
{% from "components/file-upload.html" import file_upload %}
|
|
||||||
{% from "components/page-footer.html" import page_footer %}
|
|
||||||
|
|
||||||
{% from "components/form.html" import form_wrapper %}
|
|
||||||
|
|
||||||
{% block service_page_title %}
|
|
||||||
Letter validation preview
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block maincolumn_content %}
|
|
||||||
|
|
||||||
<div class="grid-row">
|
|
||||||
<div class="column-whole">
|
|
||||||
{% if passed_validation %}
|
|
||||||
{{ banner(message, with_tick=True) }}
|
|
||||||
{% elif message %}
|
|
||||||
{% include "partials/check/letter-validation-failed-banner.html" %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<h1 class="heading-large">Letter validation preview</h1>
|
|
||||||
<div class="bottom-gutter">
|
|
||||||
{{ file_upload(
|
|
||||||
form.file,
|
|
||||||
action = url_for('main.service_letter_validation_preview', service_id=current_service.id),
|
|
||||||
button_text='Choose a file',
|
|
||||||
)}}
|
|
||||||
</div>
|
|
||||||
{%if not pages %}
|
|
||||||
<div>
|
|
||||||
<p>Your file must be:
|
|
||||||
<li>a PDF</li>
|
|
||||||
<li>no more than 10 pages long</li>
|
|
||||||
<li>less than 2 MB</li>
|
|
||||||
</p>
|
|
||||||
<p>The content of your letter must appear inside the printable area.</p>
|
|
||||||
<p>
|
|
||||||
<a href="https://docs.notifications.service.gov.uk/documentation/images/notify-pdf-letter-spec-v2.4.pdf">
|
|
||||||
Download the letter specification</a> for more information.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
{% endif%}
|
|
||||||
</div>
|
|
||||||
<div class="column-whole template-container" >
|
|
||||||
|
|
||||||
{% for page in pages %}
|
|
||||||
<div class="letter">
|
|
||||||
<img src="data:image/png;base64,{{ page }}">
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
@@ -24,7 +24,6 @@
|
|||||||
('Find users by email', url_for('main.find_users_by_email')),
|
('Find users by email', url_for('main.find_users_by_email')),
|
||||||
('Email Complaints', url_for('main.platform_admin_list_complaints')),
|
('Email Complaints', url_for('main.platform_admin_list_complaints')),
|
||||||
('Returned letters', url_for('main.platform_admin_returned_letters')),
|
('Returned letters', url_for('main.platform_admin_returned_letters')),
|
||||||
('Letter validation preview', url_for('main.platform_admin_letter_validation_preview')),
|
|
||||||
('Clear cache', url_for('main.clear_cache')),
|
('Clear cache', url_for('main.clear_cache')),
|
||||||
] %}
|
] %}
|
||||||
<li>
|
<li>
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
{% extends "views/platform-admin/_base_template.html" %}
|
|
||||||
{% from "components/banner.html" import banner %}
|
|
||||||
{% from "components/textbox.html" import textbox %}
|
|
||||||
{% from "components/file-upload.html" import file_upload %}
|
|
||||||
{% from "components/page-footer.html" import page_footer %}
|
|
||||||
|
|
||||||
{% block per_page_title %}
|
|
||||||
{{ page_title|capitalize }}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block platform_admin_content %}
|
|
||||||
|
|
||||||
<div class="grid-row">
|
|
||||||
<div class="column-whole">
|
|
||||||
<h1 class="heading-large">Letter Validation Preview</h1>
|
|
||||||
|
|
||||||
{{ file_upload(
|
|
||||||
form.file,
|
|
||||||
action = url_for('main.platform_admin_letter_validation_preview'),
|
|
||||||
button_text='Upload a PDF document',
|
|
||||||
)}}
|
|
||||||
</div>
|
|
||||||
<div class="column-whole template-container">
|
|
||||||
{% if passed_validation %}
|
|
||||||
{{ banner(message, with_tick=True) }}
|
|
||||||
{% elif message %}
|
|
||||||
{% include "partials/check/letter-validation-failed-banner.html" %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% for page in pages %}
|
|
||||||
<div class="letter">
|
|
||||||
<img src="data:image/png;base64,{{ page }}">
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
@@ -709,132 +709,6 @@ def test_platform_admin_submit_empty_returned_letters(mocker, platform_admin_cli
|
|||||||
assert "Cannot be empty" in response.get_data(as_text=True)
|
assert "Cannot be empty" in response.get_data(as_text=True)
|
||||||
|
|
||||||
|
|
||||||
def test_service_letter_validation_preview_renders_correctly(
|
|
||||||
client_request,
|
|
||||||
mock_has_no_jobs
|
|
||||||
|
|
||||||
):
|
|
||||||
page = client_request.get('main.service_letter_validation_preview', service_id=SERVICE_ONE_ID)
|
|
||||||
|
|
||||||
assert page.find('h1').text.strip() == "Letter validation preview"
|
|
||||||
assert page.find_all('input', class_='file-upload-field')
|
|
||||||
|
|
||||||
|
|
||||||
def test_service_letter_validation_preview_returns_400_if_file_is_too_big(
|
|
||||||
client_request,
|
|
||||||
mock_has_no_jobs,
|
|
||||||
mocker
|
|
||||||
|
|
||||||
):
|
|
||||||
with open('tests/test_pdf_files/big.pdf', 'rb') as file:
|
|
||||||
page = client_request.post('main.service_letter_validation_preview', service_id=SERVICE_ONE_ID,
|
|
||||||
_data=dict(
|
|
||||||
pdf_file=file,
|
|
||||||
),
|
|
||||||
content_type='multipart/form-data',
|
|
||||||
_follow_redirects=True)
|
|
||||||
|
|
||||||
assert page.find('h1').text.strip() == "Letter validation preview"
|
|
||||||
assert page.find_all('input', class_='file-upload-field')
|
|
||||||
page.find('span', class_='error-message').text.strip() == "File must be less than 2MB"
|
|
||||||
|
|
||||||
|
|
||||||
def test_letter_validation_preview_renders_correctly(mocker, platform_admin_client):
|
|
||||||
response = platform_admin_client.get(url_for('main.platform_admin_letter_validation_preview'))
|
|
||||||
assert response.status_code == 200
|
|
||||||
|
|
||||||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
|
||||||
assert page.find('h1').text.strip() == "Letter Validation Preview"
|
|
||||||
assert page.find_all('input', class_='file-upload-field')
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("passed_validation,message,expected_class", [
|
|
||||||
(True, 'Your PDF passed the layout check', 'banner-with-tick'),
|
|
||||||
(False, 'content-outside-printable-area', "banner-dangerous")
|
|
||||||
])
|
|
||||||
def test_letter_validation_preview_calls_template_preview_when_data_correct_and_displays_correct_message(
|
|
||||||
mocker, platform_admin_client, passed_validation, message, expected_class
|
|
||||||
):
|
|
||||||
endpoint = '{}/precompiled/validate?include_preview=true'.format(current_app.config['TEMPLATE_PREVIEW_API_HOST'])
|
|
||||||
mocker.patch('app.main.views.platform_admin.antivirus_client.scan', return_value=True)
|
|
||||||
|
|
||||||
with requests_mock.mock() as rmock:
|
|
||||||
rmock.request(
|
|
||||||
"POST",
|
|
||||||
endpoint,
|
|
||||||
json={"pages": [], "message": message, "result": passed_validation},
|
|
||||||
status_code=200
|
|
||||||
)
|
|
||||||
with open('tests/test_pdf_files/multi_page_pdf.pdf', 'rb') as file:
|
|
||||||
response = platform_admin_client.post(
|
|
||||||
url_for('main.platform_admin_letter_validation_preview'),
|
|
||||||
data={"file": file},
|
|
||||||
content_type='multipart/form-data'
|
|
||||||
)
|
|
||||||
assert response.status_code == 200
|
|
||||||
assert rmock.called
|
|
||||||
assert rmock.request_history[0].url == endpoint
|
|
||||||
|
|
||||||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
|
||||||
if passed_validation:
|
|
||||||
assert page.find('div', class_=expected_class).text.strip() == message
|
|
||||||
else:
|
|
||||||
assert page.find('div', class_=expected_class).find('h1', {"data-error-type": message})
|
|
||||||
|
|
||||||
|
|
||||||
def test_letter_validation_preview_doesnt_call_template_preview_when_no_file(mocker, platform_admin_client):
|
|
||||||
antivirus_scan = mocker.patch('app.main.views.platform_admin.antivirus_client.scan')
|
|
||||||
validate_letter = mocker.patch('app.main.views.platform_admin.validate_letter')
|
|
||||||
response = platform_admin_client.post(
|
|
||||||
url_for('main.platform_admin_letter_validation_preview'),
|
|
||||||
data={"file": ""},
|
|
||||||
content_type='multipart/form-data'
|
|
||||||
)
|
|
||||||
assert response.status_code == 200
|
|
||||||
antivirus_scan.assert_not_called()
|
|
||||||
validate_letter.assert_not_called()
|
|
||||||
|
|
||||||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
|
||||||
assert page.find('span', class_='error-message').text.strip() == "You need to choose a file to upload"
|
|
||||||
|
|
||||||
|
|
||||||
def test_letter_validation_preview_doesnt_call_template_preview_when_file_not_pdf(mocker, platform_admin_client):
|
|
||||||
antivirus_scan = mocker.patch('app.main.views.platform_admin.antivirus_client.scan')
|
|
||||||
validate_letter = mocker.patch('app.main.views.platform_admin.validate_letter')
|
|
||||||
with open('tests/non_spreadsheet_files/actually_a_png.csv', 'rb') as file:
|
|
||||||
response = platform_admin_client.post(
|
|
||||||
url_for('main.platform_admin_letter_validation_preview'),
|
|
||||||
data={"file": file},
|
|
||||||
content_type='multipart/form-data'
|
|
||||||
)
|
|
||||||
assert response.status_code == 200
|
|
||||||
antivirus_scan.assert_not_called()
|
|
||||||
validate_letter.assert_not_called()
|
|
||||||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
|
||||||
assert page.find('span', class_='error-message').text.strip() == "Save your letter as a PDF and try again."
|
|
||||||
|
|
||||||
|
|
||||||
def test_letter_validation_preview_doesnt_call_template_preview_when_file_doesnt_pass_virus_scan(
|
|
||||||
mocker,
|
|
||||||
platform_admin_client
|
|
||||||
):
|
|
||||||
antivirus_scan = mocker.patch('app.main.views.platform_admin.antivirus_client.scan', return_value=False)
|
|
||||||
validate_letter = mocker.patch('app.main.views.platform_admin.validate_letter')
|
|
||||||
|
|
||||||
with open('tests/test_pdf_files/multi_page_pdf.pdf', 'rb') as file:
|
|
||||||
response = platform_admin_client.post(
|
|
||||||
url_for('main.platform_admin_letter_validation_preview'),
|
|
||||||
data={"file": file},
|
|
||||||
content_type='multipart/form-data'
|
|
||||||
)
|
|
||||||
assert response.status_code == 400
|
|
||||||
assert antivirus_scan.called is True
|
|
||||||
validate_letter.assert_not_called()
|
|
||||||
|
|
||||||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
|
||||||
assert page.find('div', class_='banner-dangerous').text.strip() == "Document did not pass the virus scan"
|
|
||||||
|
|
||||||
|
|
||||||
def test_clear_cache_shows_form(client_request, platform_admin_user, mocker):
|
def test_clear_cache_shows_form(client_request, platform_admin_user, mocker):
|
||||||
redis = mocker.patch('app.main.views.platform_admin.redis_client')
|
redis = mocker.patch('app.main.views.platform_admin.redis_client')
|
||||||
client_request.login(platform_admin_user)
|
client_request.login(platform_admin_user)
|
||||||
|
|||||||
Reference in New Issue
Block a user