From 5f43fe23a795e6b816f0041856e8cf5c9e6c63db Mon Sep 17 00:00:00 2001 From: Katie Smith Date: Wed, 25 Apr 2018 16:34:36 +0100 Subject: [PATCH] Add DAO function and endpoint for archiving email reply_to addresses Added a new DAO function which archives email reply_to addresses by setting archived to True. This raises a new type of error, an ArchiveValidationError, if trying to archive a default reply_to address. Added a new endpoint for archiving email reply_to addresses. --- app/dao/service_email_reply_to_dao.py | 17 ++++++++ app/errors.py | 6 +++ app/exceptions.py | 4 ++ app/service/rest.py | 8 ++++ .../dao/test_service_email_reply_to_dao.py | 43 ++++++++++++++++++- tests/app/service/test_rest.py | 34 +++++++++++++++ 6 files changed, 111 insertions(+), 1 deletion(-) diff --git a/app/dao/service_email_reply_to_dao.py b/app/dao/service_email_reply_to_dao.py index 7ecc2a43b..86169e3c7 100644 --- a/app/dao/service_email_reply_to_dao.py +++ b/app/dao/service_email_reply_to_dao.py @@ -3,6 +3,7 @@ from sqlalchemy import desc from app import db from app.dao.dao_utils import transactional from app.errors import InvalidRequest +from app.exceptions import ArchiveValidationError from app.models import ServiceEmailReplyTo @@ -56,6 +57,22 @@ def update_reply_to_email_address(service_id, reply_to_id, email_address, is_def return reply_to_update +@transactional +def archive_reply_to_email_address(service_id, reply_to_id): + reply_to_archive = ServiceEmailReplyTo.query.filter_by( + id=reply_to_id, + service_id=service_id + ).one() + + if reply_to_archive.is_default: + raise ArchiveValidationError("You cannot delete a default email reply to address") + + reply_to_archive.archived = True + + db.session.add(reply_to_archive) + return reply_to_archive + + def _get_existing_default(service_id): existing_reply_to = dao_get_reply_to_by_service_id(service_id=service_id) if existing_reply_to: diff --git a/app/errors.py b/app/errors.py index c5df8892f..67448e1fb 100644 --- a/app/errors.py +++ b/app/errors.py @@ -8,6 +8,7 @@ from sqlalchemy.orm.exc import NoResultFound from marshmallow import ValidationError from jsonschema import ValidationError as JsonSchemaValidationError from app.authentication.auth import AuthError +from app.exceptions import ArchiveValidationError class VirusScanError(Exception): @@ -67,6 +68,11 @@ def register_errors(blueprint): current_app.logger.info(error) return jsonify(json.loads(error.message)), 400 + @blueprint.errorhandler(ArchiveValidationError) + def archive_validation_error(error): + current_app.logger.info(error) + return jsonify(result='error', message=str(error)), 400 + @blueprint.errorhandler(InvalidRequest) def invalid_data(error): response = jsonify(error.to_dict()) diff --git a/app/exceptions.py b/app/exceptions.py index 6f43f10ea..9332a2afa 100644 --- a/app/exceptions.py +++ b/app/exceptions.py @@ -6,3 +6,7 @@ class DVLAException(Exception): class NotificationTechnicalFailureException(Exception): def __init__(self, message): self.message = message + + +class ArchiveValidationError(Exception): + pass diff --git a/app/service/rest.py b/app/service/rest.py index a36b50664..756d81915 100644 --- a/app/service/rest.py +++ b/app/service/rest.py @@ -52,6 +52,7 @@ from app.dao.service_whitelist_dao import ( ) from app.dao.service_email_reply_to_dao import ( add_reply_to_email_address_for_service, + archive_reply_to_email_address, dao_get_reply_to_by_id, dao_get_reply_to_by_service_id, update_reply_to_email_address @@ -594,6 +595,13 @@ def update_service_reply_to_email_address(service_id, reply_to_email_id): return jsonify(data=new_reply_to.serialize()), 200 +@service_blueprint.route('//email-reply-to//archive', methods=['POST']) +def delete_service_reply_to_email_address(service_id, reply_to_email_id): + archived_reply_to = archive_reply_to_email_address(service_id, reply_to_email_id) + + return jsonify(data=archived_reply_to.serialize()), 200 + + @service_blueprint.route('//letter-contact', methods=["GET"]) def get_letter_contacts(service_id): result = dao_get_letter_contacts_by_service_id(service_id) diff --git a/tests/app/dao/test_service_email_reply_to_dao.py b/tests/app/dao/test_service_email_reply_to_dao.py index df6aed6f0..cbaa4ee54 100644 --- a/tests/app/dao/test_service_email_reply_to_dao.py +++ b/tests/app/dao/test_service_email_reply_to_dao.py @@ -4,9 +4,13 @@ import pytest from sqlalchemy.exc import SQLAlchemyError from app.dao.service_email_reply_to_dao import ( + add_reply_to_email_address_for_service, + archive_reply_to_email_address, + dao_get_reply_to_by_id, dao_get_reply_to_by_service_id, - add_reply_to_email_address_for_service, update_reply_to_email_address, dao_get_reply_to_by_id) + update_reply_to_email_address) from app.errors import InvalidRequest +from app.exceptions import ArchiveValidationError from app.models import ServiceEmailReplyTo from tests.app.db import create_reply_to_email, create_service @@ -196,3 +200,40 @@ def test_dao_get_reply_to_by_id_raises_sqlalchemy_error_when_service_does_not_ex reply_to = create_reply_to_email(service=sample_service, email_address='email@address.com') with pytest.raises(SQLAlchemyError): dao_get_reply_to_by_id(service_id=uuid.uuid4(), reply_to_id=reply_to.id) + + +def test_archive_reply_to_email_address(sample_service): + create_reply_to_email(service=sample_service, email_address="first@address.com") + second_reply_to = create_reply_to_email( + service=sample_service, + email_address="second@address.com", + is_default=False) + + archive_reply_to_email_address(sample_service.id, second_reply_to.id) + + assert second_reply_to.archived is True + assert second_reply_to.updated_at is not None + + +def test_archive_reply_to_email_address_does_not_archive_a_reply_to_for_a_different_service(sample_service): + service = create_service(service_name="First service") + reply_to = create_reply_to_email(service=sample_service, email_address="first@address.com", is_default=False) + + with pytest.raises(SQLAlchemyError): + archive_reply_to_email_address(service.id, reply_to.id) + + assert not reply_to.archived + + +def test_archive_reply_to_email_address_raises_an_error_if_attempting_to_archive_a_default(sample_service): + create_reply_to_email( + service=sample_service, + email_address="first@address.com", + is_default=False) + default_reply_to = create_reply_to_email(service=sample_service, email_address="first@address.com") + + with pytest.raises(ArchiveValidationError) as e: + archive_reply_to_email_address(sample_service.id, default_reply_to.id) + + assert 'You cannot delete a default email reply to address' in str(e.value) + assert not default_reply_to.archived diff --git a/tests/app/service/test_rest.py b/tests/app/service/test_rest.py index eb6907850..ff0571466 100644 --- a/tests/app/service/test_rest.py +++ b/tests/app/service/test_rest.py @@ -2525,6 +2525,40 @@ def test_update_service_reply_to_email_address_404s_when_invalid_service_id(clie assert result['message'] == 'No result found' +def test_delete_service_reply_to_email_address_archives_an_email_reply_to( + sample_service, + admin_request, + notify_db_session +): + create_reply_to_email(service=sample_service, email_address="some@email.com") + reply_to = create_reply_to_email(service=sample_service, email_address="some@email.com", is_default=False) + + admin_request.post( + 'service.delete_service_reply_to_email_address', + service_id=sample_service.id, + reply_to_email_id=reply_to.id, + ) + assert reply_to.archived is True + + +def test_delete_service_reply_to_email_address_returns_400_if_archiving_default_reply_to( + admin_request, + notify_db_session, + sample_service +): + reply_to = create_reply_to_email(service=sample_service, email_address="some@email.com") + + response = admin_request.post( + 'service.delete_service_reply_to_email_address', + service_id=sample_service.id, + reply_to_email_id=reply_to.id, + _expected_status=400 + ) + + assert response == {'message': 'You cannot delete a default email reply to address', 'result': 'error'} + assert reply_to.archived is False + + def test_get_email_reply_to_address(client, notify_db, notify_db_session): service = create_service() reply_to = create_reply_to_email(service, 'test_a@mail.com')