def test_get_letter_validation_error_for_known_errors(
    client_request,
    error_message,
    invalid_pages,
    expected_title,
    expected_content,
    expected_summary,
):
    error = get_letter_validation_error(error_message,
                                        invalid_pages=invalid_pages,
                                        page_count=13)
    detail = BeautifulSoup(error['detail'], 'html.parser')
    summary = BeautifulSoup(error['summary'], 'html.parser')

    assert error['title'] == expected_title

    assert detail.text == expected_content
    if detail.select_one('a'):
        assert detail.select_one('a')['href'] == url_for(
            '.letter_specification')

    assert summary.text == expected_summary
    if summary.select_one('a'):
        assert summary.select_one('a')['href'] == url_for(
            '.letter_specification')
Пример #2
0
def uploaded_letter_preview(service_id, file_id):
    re_upload_form = PDFUploadForm()

    try:
        metadata = get_letter_metadata(service_id, file_id)
    except ClientError as e:
        # if the file's not there, it's probably because we've already created the notification and the letter has been
        # moved to the normal letters-pdf bucket. So lets just bounce out to the notification page
        if e.response['Error']['Code'] == 'NoSuchKey':
            return redirect(
                url_for(
                    '.view_notification',
                    service_id=service_id,
                    notification_id=file_id,
                ))
        else:
            raise

    original_filename = metadata.get('filename')
    page_count = metadata.get('page_count')
    status = metadata.get('status')
    error_shortcode = metadata.get('message')
    invalid_pages = metadata.get('invalid_pages')
    postal_address = PostalAddress(metadata.get('recipient', ''))

    if invalid_pages:
        invalid_pages = json.loads(invalid_pages)

    error_message = get_letter_validation_error(error_shortcode, invalid_pages,
                                                page_count)
    template_dict = service_api_client.get_precompiled_template(service_id)
    # Override pre compiled letter template postage to none as it has not yet been picked even though
    # the pre compiled letter template has its postage set as second class as the DB currently requires
    # a non null value of postage for letter templates
    template_dict['postage'] = None

    form = LetterUploadPostageForm(postage_zone=postal_address.postage)

    template = get_template(template_dict,
                            service_id,
                            letter_preview_url=url_for(
                                '.view_letter_upload_as_preview',
                                service_id=service_id,
                                file_id=file_id),
                            page_count=page_count)

    return render_template(
        'views/uploads/preview.html',
        original_filename=original_filename,
        template=template,
        status=status,
        file_id=file_id,
        message=error_message,
        error_code=error_shortcode,
        form=form,
        allowed_file_extensions=Spreadsheet.ALLOWED_FILE_EXTENSIONS,
        postal_address=postal_address,
        re_upload_form=re_upload_form)
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
    )
Пример #4
0
def uploaded_letter_preview(service_id, file_id):
    re_upload_form = PDFUploadForm()

    metadata = get_letter_metadata(service_id, file_id)
    original_filename = metadata.get('filename')
    page_count = metadata.get('page_count')
    status = metadata.get('status')
    error_shortcode = metadata.get('message')
    invalid_pages = metadata.get('invalid_pages')
    recipient = format_recipient(metadata.get('recipient', ''))

    if invalid_pages:
        invalid_pages = json.loads(invalid_pages)

    error_message = get_letter_validation_error(error_shortcode, invalid_pages, page_count)
    template_dict = service_api_client.get_precompiled_template(service_id)
    # Override pre compiled letter template postage to none as it has not yet been picked even though
    # the pre compiled letter template has its postage set as second class as the DB currently requires
    # a non null value of postage for letter templates
    template_dict['postage'] = None

    form = LetterUploadPostageForm()

    template = get_template(
        template_dict,
        service_id,
        letter_preview_url=url_for(
            '.view_letter_upload_as_preview',
            service_id=service_id,
            file_id=file_id
        ),
        page_count=page_count
    )

    return render_template(
        'views/uploads/preview.html',
        original_filename=original_filename,
        template=template,
        status=status,
        file_id=file_id,
        message=error_message,
        error_code=error_shortcode,
        form=form,
        recipient=recipient,
        re_upload_form=re_upload_form
    )
Пример #5
0
def view_notification(service_id, notification_id):
    notification = notification_api_client.get_notification(
        service_id, str(notification_id))
    notification['template'].update(
        {'reply_to_text': notification['reply_to_text']})

    personalisation = get_all_personalisation_from_notification(notification)
    error_message = None
    if notification['template']['is_precompiled_letter']:
        try:
            file_contents, metadata = get_letter_file_data(service_id,
                                                           notification_id,
                                                           "pdf",
                                                           with_metadata=True)
            page_count = int(metadata["page_count"]) if metadata.get(
                "page_count") else pdf_page_count(io.BytesIO(file_contents))
            if notification["status"] == "validation-failed":
                invalid_pages = metadata.get("invalid_pages")
                invalid_pages = json.loads(
                    invalid_pages) if invalid_pages else invalid_pages
                error_message = get_letter_validation_error(
                    metadata.get("message"), invalid_pages, page_count)
        except PdfReadError:
            return render_template(
                'views/notifications/invalid_precompiled_letter.html',
                created_at=notification['created_at'])
    else:
        page_count = get_page_count_for_letter(notification['template'],
                                               values=personalisation)

    if notification.get('postage'):
        if notification["status"] == "validation-failed":
            notification['template']['postage'] = None
        else:
            notification['template']['postage'] = notification['postage']
    template = get_template(
        notification['template'],
        current_service,
        letter_preview_url=url_for(
            '.view_letter_notification_as_preview',
            service_id=service_id,
            notification_id=notification_id,
            filetype='png',
        ),
        page_count=page_count,
        show_recipient=True,
        redact_missing_personalisation=True,
    )
    template.values = personalisation
    if notification['job']:
        job = job_api_client.get_job(service_id,
                                     notification['job']['id'])['data']
    else:
        job = None

    letter_print_day = get_letter_printing_statement(
        notification['status'], notification['created_at'])

    notification_created = parser.parse(
        notification['created_at']).replace(tzinfo=None)

    show_cancel_button = notification['notification_type'] == 'letter' and \
        letter_can_be_cancelled(notification['status'], notification_created)

    if get_help_argument() or request.args.get('help') == '0':
        # help=0 is set when you’ve just sent a notification. We
        # only want to show the back link when you’ve navigated to a
        # notification, not when you’ve just sent it.
        back_link = None
    elif request.args.get('from_job'):
        back_link = url_for(
            'main.view_job',
            service_id=current_service.id,
            job_id=request.args.get('from_job'),
        )
    elif request.args.get('from_uploaded_letters'):
        back_link = url_for(
            'main.uploaded_letters',
            service_id=current_service.id,
            letter_print_day=request.args.get('from_uploaded_letters'),
        )
    else:
        back_link = url_for(
            'main.view_notifications',
            service_id=current_service.id,
            message_type=template.template_type,
            status='sending,delivered,failed',
        )

    if notification['notification_type'] == 'letter':
        estimated_letter_delivery_date = get_letter_timings(
            notification['created_at'],
            postage=notification['postage']).earliest_delivery
    else:
        estimated_letter_delivery_date = None

    return render_template(
        'views/notifications/notification.html',
        finished=(notification['status']
                  in (DELIVERED_STATUSES + FAILURE_STATUSES)),
        notification_status=notification['status'],
        message=error_message,
        uploaded_file_name='Report',
        template=template,
        job=job,
        updates_url=url_for(".view_notification_updates",
                            service_id=service_id,
                            notification_id=notification['id'],
                            status=request.args.get('status'),
                            help=get_help_argument()),
        partials=get_single_notification_partials(notification),
        created_by=notification.get('created_by'),
        created_at=notification['created_at'],
        updated_at=notification['updated_at'],
        help=get_help_argument(),
        estimated_letter_delivery_date=estimated_letter_delivery_date,
        notification_id=notification['id'],
        postage=notification['postage'],
        can_receive_inbound=(current_service.has_permission('inbound_sms')),
        is_precompiled_letter=notification['template']
        ['is_precompiled_letter'],
        letter_print_day=letter_print_day,
        show_cancel_button=show_cancel_button,
        sent_with_test_key=(notification.get('key_type') == KEY_TYPE_TEST),
        back_link=back_link,
    )
def test_get_letter_validation_error_for_unknown_error():
    assert get_letter_validation_error('Unknown error') == {
        'title': 'Validation failed'
    }