mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-07-02 07:27:35 -04:00
Add antivirus scan to letter validation preview view
This commit is contained in:
@@ -25,6 +25,7 @@ from functools import partial
|
||||
|
||||
from notifications_python_client.errors import HTTPError
|
||||
from notifications_utils import logging, request_helper, formatters
|
||||
from notifications_utils.clients.antivirus.antivirus_client import AntivirusClient
|
||||
from notifications_utils.clients.zendesk.zendesk_client import ZendeskClient
|
||||
from notifications_utils.clients.statsd.statsd_client import StatsdClient
|
||||
from notifications_utils.recipients import (
|
||||
@@ -86,6 +87,7 @@ email_branding_client = EmailBrandingClient()
|
||||
organisations_client = OrganisationsClient()
|
||||
org_invite_api_client = OrgInviteApiClient()
|
||||
asset_fingerprinter = AssetFingerprinter()
|
||||
antivirus_client = AntivirusClient()
|
||||
statsd_client = StatsdClient()
|
||||
zendesk_client = ZendeskClient()
|
||||
letter_jobs_client = LetterJobsClient()
|
||||
@@ -121,6 +123,7 @@ def create_app(application):
|
||||
application.config.from_object(configs[notify_environment])
|
||||
|
||||
init_app(application)
|
||||
antivirus_client.init_app(application)
|
||||
statsd_client.init_app(application)
|
||||
zendesk_client.init_app(application)
|
||||
logging.init_app(application, statsd_client)
|
||||
|
||||
@@ -28,6 +28,10 @@ class Config(object):
|
||||
NOTIFY_LOG_PATH = os.getenv('NOTIFY_LOG_PATH')
|
||||
|
||||
ADMIN_CLIENT_USER_NAME = 'notify-admin'
|
||||
|
||||
ANTIVIRUS_API_HOST = os.environ.get('ANTIVIRUS_API_HOST')
|
||||
ANTIVIRUS_API_KEY = os.environ.get('ANTIVIRUS_API_KEY')
|
||||
|
||||
ASSETS_DEBUG = False
|
||||
AWS_REGION = 'eu-west-1'
|
||||
DEFAULT_SERVICE_LIMIT = 50
|
||||
@@ -85,6 +89,8 @@ class Development(Config):
|
||||
API_HOST_NAME = 'http://localhost:6011'
|
||||
DANGEROUS_SALT = 'dev-notify-salt'
|
||||
SECRET_KEY = 'dev-notify-secret-key'
|
||||
ANTIVIRUS_API_HOST = 'http://localhost:6016'
|
||||
ANTIVIRUS_API_KEY = 'test-key'
|
||||
|
||||
|
||||
class Test(Development):
|
||||
@@ -98,6 +104,8 @@ class Test(Development):
|
||||
NOTIFY_ENVIRONMENT = 'test'
|
||||
API_HOST_NAME = 'http://you-forgot-to-mock-an-api-call-to'
|
||||
TEMPLATE_PREVIEW_API_HOST = 'http://localhost:9999'
|
||||
ANTIVIRUS_API_HOST = 'https://test-antivirus'
|
||||
ANTIVIRUS_API_KEY = 'test-antivirus-secret'
|
||||
|
||||
|
||||
class Preview(Config):
|
||||
|
||||
@@ -5,8 +5,12 @@ from datetime import datetime
|
||||
from flask import abort, flash, redirect, render_template, request, url_for
|
||||
from flask_login import login_required
|
||||
from notifications_python_client.errors import HTTPError
|
||||
from notifications_utils.clients.antivirus.antivirus_client import (
|
||||
AntivirusError,
|
||||
)
|
||||
|
||||
from app import (
|
||||
antivirus_client,
|
||||
complaint_api_client,
|
||||
letter_jobs_client,
|
||||
platform_stats_api_client,
|
||||
@@ -247,14 +251,24 @@ def platform_admin_returned_letters():
|
||||
def platform_admin_letter_validation_preview():
|
||||
message, pages, result = None, [], None
|
||||
form = PDFUploadForm()
|
||||
|
||||
if form.validate_on_submit():
|
||||
pdf_file = form.file.data
|
||||
|
||||
try:
|
||||
virus_free = antivirus_client.scan(pdf_file)
|
||||
except AntivirusError:
|
||||
flash("Antivirus API error")
|
||||
abort(503)
|
||||
|
||||
if not virus_free:
|
||||
flash("Document didn't pass the virus scan")
|
||||
abort(400)
|
||||
|
||||
try:
|
||||
response = validate_letter(pdf_file)
|
||||
if response.status_code == 200:
|
||||
pages = response.json()["pages"]
|
||||
message = response.json()["message"]
|
||||
result = response.json()["result"]
|
||||
pages, message, result = response.json()["pages"], response.json()["message"], response.json()["result"]
|
||||
except HTTPError as error:
|
||||
if error.status_code == 400:
|
||||
flash("Something was wrong with the file you tried to upload. Please upload a valid PDF file.")
|
||||
@@ -263,10 +277,7 @@ def platform_admin_letter_validation_preview():
|
||||
|
||||
return render_template(
|
||||
'views/platform-admin/letter-validation-preview.html',
|
||||
form=form,
|
||||
message=message,
|
||||
pages=pages,
|
||||
result=result
|
||||
form=form, message=message, pages=pages, result=result
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -29,6 +29,9 @@ env:
|
||||
AWS_ACCESS_KEY_ID: null
|
||||
AWS_SECRET_ACCESS_KEY: null
|
||||
|
||||
ANTIVIRUS_API_HOST: null
|
||||
ANTIVIRUS_API_KEY: null
|
||||
|
||||
STATSD_PREFIX: null
|
||||
|
||||
ZENDESK_API_KEY: null
|
||||
|
||||
@@ -7,7 +7,7 @@ from unittest.mock import ANY
|
||||
import pytest
|
||||
import requests_mock
|
||||
from bs4 import BeautifulSoup
|
||||
from flask import url_for, current_app
|
||||
from flask import current_app, url_for
|
||||
from freezegun import freeze_time
|
||||
|
||||
from app.main.views.platform_admin import (
|
||||
@@ -779,6 +779,8 @@ def test_letter_validation_preview_calls_template_preview_when_data_correct_and_
|
||||
mock_get_user(mocker, user=platform_admin_user)
|
||||
client.login(platform_admin_user)
|
||||
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",
|
||||
@@ -803,6 +805,7 @@ def test_letter_validation_preview_calls_template_preview_when_data_correct_and_
|
||||
def test_letter_validation_preview_doesnt_call_template_preview_when_no_file(mocker, client, platform_admin_user):
|
||||
mock_get_user(mocker, user=platform_admin_user)
|
||||
client.login(platform_admin_user)
|
||||
antivirus_scan = mocker.patch('app.main.views.platform_admin.antivirus_client.scan')
|
||||
validate_letter = mocker.patch('app.main.views.platform_admin.validate_letter')
|
||||
response = client.post(
|
||||
url_for('main.platform_admin_letter_validation_preview'),
|
||||
@@ -810,6 +813,7 @@ def test_letter_validation_preview_doesnt_call_template_preview_when_no_file(moc
|
||||
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')
|
||||
@@ -819,6 +823,7 @@ def test_letter_validation_preview_doesnt_call_template_preview_when_no_file(moc
|
||||
def test_letter_validation_preview_doesnt_call_template_preview_when_file_not_pdf(mocker, client, platform_admin_user):
|
||||
mock_get_user(mocker, user=platform_admin_user)
|
||||
client.login(platform_admin_user)
|
||||
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 = client.post(
|
||||
@@ -827,6 +832,29 @@ def test_letter_validation_preview_doesnt_call_template_preview_when_file_not_pd
|
||||
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() == "PDF documents only!"
|
||||
|
||||
|
||||
def test_letter_validation_preview_doesnt_call_template_preview_when_file_doesnt_pass_virus_scan(
|
||||
mocker, client, platform_admin_user
|
||||
):
|
||||
mock_get_user(mocker, user=platform_admin_user)
|
||||
client.login(platform_admin_user)
|
||||
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 = 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 didn't pass the virus scan"
|
||||
|
||||
Reference in New Issue
Block a user