Skip to content

Commit

Permalink
PROD-2202: Allow property-specific messaging to work with non-custom …
Browse files Browse the repository at this point in the history
…templates (#4986)
  • Loading branch information
eastandwestwind authored Jun 18, 2024
1 parent 24e2539 commit 29305c1
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ The types of changes are:
- Masked "Keyfile credentials" input on integration config form [#4971](https://github.com/ethyca/fides/pull/4971)
- Fixed ability to update consent preferences after they've previously been set [#4984](https://github.com/ethyca/fides/pull/4984)
- Fixed validations for privacy declaration taxonomy labels when creating/updating a System [#4982](https://github.com/ethyca/fides/pull/4982)
- Allow property-specific messaging to work with non-custom templates [#4986](https://github.com/ethyca/fides/pull/4986)

## [2.38.0](https://github.com/ethyca/fides/compare/2.37.0...2.38.0)

Expand Down
12 changes: 12 additions & 0 deletions src/fides/api/schemas/messaging/messaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,18 @@ class MessagingActionType(str, Enum):
TEST_MESSAGE = "test_message"


CONFIGURABLE_MESSAGING_ACTION_TYPES: Tuple[str, ...] = (
# These messaging action types are configurable in Admin-UI, and thus are the only templates that apply to the
# property-specific messaging feature. The other action types as associated with hard-coded templates in Fides.
MessagingActionType.SUBJECT_IDENTITY_VERIFICATION.value,
MessagingActionType.PRIVACY_REQUEST_RECEIPT.value,
MessagingActionType.PRIVACY_REQUEST_COMPLETE_ACCESS.value,
MessagingActionType.PRIVACY_REQUEST_COMPLETE_DELETION.value,
MessagingActionType.PRIVACY_REQUEST_REVIEW_DENY.value,
MessagingActionType.PRIVACY_REQUEST_REVIEW_APPROVE.value
)


class ErrorNotificationBodyParams(BaseModel):
"""Body params required for privacy request error notifications."""

Expand Down
14 changes: 11 additions & 3 deletions src/fides/api/service/messaging/message_dispatch_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
RequestReceiptBodyParams,
RequestReviewDenyBodyParams,
SubjectIdentityVerificationBodyParams,
CONFIGURABLE_MESSAGING_ACTION_TYPES,
)
from fides.api.schemas.redis_cache import Identity
from fides.api.service.connectors.base_email_connector import (
Expand Down Expand Up @@ -175,6 +176,9 @@ def message_send_enabled(
) -> bool:
"""
Determines whether sending messages from Fides is enabled or disabled.
Assumes action_type is one of CONFIGURABLE_MESSAGING_ACTION_TYPES.
Property-specific messaging, if enabled, always takes precedence, and requires checking "enabled" templates for the
given action type and property.
"""
Expand Down Expand Up @@ -242,8 +246,12 @@ def dispatch_message(
message: Optional[Union[EmailForActionType, str]] = None
messaging_template: Optional[MessagingTemplate] = None

# If property-specific messaging is enabled, we switch over to this mode, regardless of other ENV vars
if ConfigProxy(db).notifications.enable_property_specific_messaging:
# If property-specific messaging is enabled and message type is one of the configurable templates,
# we switch over to this mode, regardless of other ENV vars
if (
ConfigProxy(db).notifications.enable_property_specific_messaging
and action_type in CONFIGURABLE_MESSAGING_ACTION_TYPES
):
property_specific_messaging_template = get_property_specific_messaging_template(
db, property_id, action_type
)
Expand Down Expand Up @@ -392,7 +400,7 @@ def _build_email( # pylint: disable=too-many-return-statements
body_params (Any): Parameters used to populate the email body, such as verification codes.
messaging_template (Optional[MessagingTemplate]): An optional custom messaging template for the email wording.
This parameter is used to define the subject and body of the email, and its rendered output is
passed to the HTML templates. Only applicable for specific action types.
passed to the HTML templates. Only applicable for action types in CONFIGURABLE_MESSAGING_ACTION_TYPES.
Returns:
EmailForActionType: The constructed email object with the subject and body populated based on the action type.
Expand Down
74 changes: 74 additions & 0 deletions tests/ops/integration_tests/test_integration_generic_email.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,80 @@ async def test_erasure_email(
mock_requeue_privacy_requests.assert_called()


@pytest.mark.integration
@pytest.mark.asyncio
@pytest.mark.parametrize(
"dsr_version",
["use_dsr_3_0", "use_dsr_2_0"],
)
@mock.patch(
"fides.api.service.privacy_request.email_batch_service.requeue_privacy_requests_after_email_send",
)
@mock.patch("fides.api.service.messaging.message_dispatch_service._mailgun_dispatcher")
async def test_erasure_email_property_specific_messaging(
mock_mailgun_dispatcher: Mock,
mock_requeue_privacy_requests: Mock,
db,
dsr_version,
request,
erasure_policy,
generic_erasure_email_connection_config,
set_property_specific_messaging_enabled,
run_privacy_request_task,
test_fides_org,
messaging_config,
) -> None:
"""
Run an erasure privacy request with only a generic erasure email connector.
Verify the privacy request is set to "awaiting email send" and that one email
is sent when the send_email_batch job is executed manually
"""
request.getfixturevalue(dsr_version) # REQUIRED to test both DSR 3.0 and 2.0

pr = get_privacy_request_results(
db,
erasure_policy,
run_privacy_request_task,
{
"requested_at": "2021-08-30T16:09:37.359Z",
"policy_key": erasure_policy.key,
"identity": {"email": "[email protected]"},
},
)

db.refresh(pr)

# the privacy request will be in an "awaiting email send" state until the "send email batch" job executes
assert pr.status == PrivacyRequestStatus.awaiting_email_send
assert pr.awaiting_email_send_at is not None

# execute send email batch job without waiting for it to be scheduled
exit_state = send_email_batch.delay().get()
assert exit_state == EmailExitState.complete

# verify the email was sent
erasure_email_template = get_email_template(
MessagingActionType.MESSAGE_ERASURE_REQUEST_FULFILLMENT
)
mock_mailgun_dispatcher.assert_called_once_with(
ANY,
EmailForActionType(
subject="Notification of user erasure requests from Test Org",
body=erasure_email_template.render(
{
"controller": "Test Org",
"third_party_vendor_name": "Attentive",
"identities": ["[email protected]"],
}
),
),
"[email protected]",
)

# verify the privacy request was queued for further processing
mock_requeue_privacy_requests.assert_called()


@pytest.mark.integration
@pytest.mark.asyncio
@mock.patch(
Expand Down

0 comments on commit 29305c1

Please sign in to comment.