Skip to content

Commit bb14848

Browse files
committed
Cherry-picking consent model changes
1 parent 5349c21 commit bb14848

9 files changed

Lines changed: 54 additions & 37 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Changes can also be flagged with a GitHub label for tracking purposes. The URL o
3838
- Updated bulk ignore assets toast message [#6043](https://github.com/ethyca/fides/pull/6043)
3939
- Updated UI behavior for editing languages in the Experience config for consistency and clarity [#6055](https://github.com/ethyca/fides/pull/6055)
4040
- Moved detection & discovery features out of beta [#6059](https://github.com/ethyca/fides/pull/6059)
41+
- Updated consent automation models to support echo detection in Fidesplus [#6054](https://github.com/ethyca/fides/pull/6054)
4142

4243
### Developer Experience
4344
- Reduced animations on Cypress tests in Privacy Center for quicker results [#5976](https://github.com/ethyca/fides/pull/5976)

src/fides/api/schemas/consentable_item.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from pydantic import BaseModel, Field
44

55
from fides.api.models.consent_automation import ConsentableItem as ConsentableItemModel
6-
from fides.api.models.privacy_notice import UserConsentPreference
76
from fides.api.schemas.base_class import FidesSchema
87

98

@@ -85,10 +84,8 @@ class ConsentWebhookResult(BaseModel):
8584

8685
identity_map: Dict[
8786
Literal["email", "phone_number", "fides_user_device", "external_id"], str
88-
] = {}
89-
notice_map: Dict[str, UserConsentPreference] = {}
90-
91-
@property
92-
def success(self) -> bool:
93-
"""Returns true if both the identity map and notice map are not empty."""
94-
return bool(self.identity_map) and bool(self.notice_map)
87+
] = Field(default_factory=dict, description="The identity of the user.")
88+
notice_id_map: Dict[str, str] = Field(
89+
default_factory=dict,
90+
description="A map of privacy notice IDs to user consent preferences.",
91+
)

src/fides/api/service/connectors/saas_connector.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from typing import Any, Dict, List, Optional, Tuple, Union, cast
55

66
import pydash
7+
from fideslang.validation import FidesKey
78
from loguru import logger
89
from requests import Response
910
from sqlalchemy.orm import Session
@@ -18,7 +19,6 @@
1819
from fides.api.graph.execution import ExecutionNode
1920
from fides.api.models.connectionconfig import ConnectionConfig, ConnectionTestStatus
2021
from fides.api.models.policy import Policy
21-
from fides.api.models.privacy_notice import UserConsentPreference
2222
from fides.api.models.privacy_request import PrivacyRequest, RequestTask
2323
from fides.api.schemas.consentable_item import (
2424
ConsentableItem,
@@ -687,15 +687,16 @@ def run_consent_request(
687687

688688
if notice_based_override_function:
689689
# follow the notice-based SaaS consent flow
690-
notice_id_to_preference_map, filtered_preferences = (
691-
build_user_consent_and_filtered_preferences_for_service(
692-
self.configuration.system,
693-
privacy_request,
694-
session,
695-
True,
696-
)
690+
(
691+
notice_preference_map,
692+
filtered_preferences,
693+
) = build_user_consent_and_filtered_preferences_for_service(
694+
self.configuration.system,
695+
privacy_request,
696+
session,
697+
True,
697698
)
698-
if not notice_id_to_preference_map:
699+
if not notice_preference_map:
699700
logger.info(
700701
"Skipping consent requests on node {}: No actionable consent preferences to propagate",
701702
node.address.value,
@@ -723,12 +724,13 @@ def run_consent_request(
723724
)
724725
consent_propagation_status = self._invoke_consent_request_override(
725726
notice_based_override_function,
727+
self.configuration.key,
726728
self.create_client(),
727729
policy,
728730
privacy_request,
729731
self.secrets,
730732
identity_data,
731-
notice_id_to_preference_map, # type: ignore[arg-type]
733+
notice_preference_map, # type: ignore[arg-type]
732734
notice_based_consentable_item_hierarchy,
733735
)
734736
if consent_propagation_status == ConsentPropagationStatus.no_update_needed:
@@ -800,6 +802,7 @@ def run_consent_request(
800802
)
801803
consent_propagation_status = self._invoke_consent_request_override(
802804
override_function,
805+
self.configuration.key,
803806
self.create_client(),
804807
policy,
805808
privacy_request,
@@ -997,12 +1000,13 @@ def _invoke_masking_request_override(
9971000
@staticmethod
9981001
def _invoke_consent_request_override(
9991002
override_function: RequestOverrideFunction,
1003+
connection_key: FidesKey,
10001004
client: AuthenticatedClient,
10011005
policy: Policy,
10021006
privacy_request: PrivacyRequest,
10031007
secrets: Any,
10041008
identity_data: Optional[Dict[str, Any]] = None,
1005-
notice_id_to_preference_map: Optional[Dict[str, UserConsentPreference]] = None,
1009+
notice_preference_map: Optional[Dict[str, Dict[str, Any]]] = None,
10061010
consentable_items_hierarchy: Optional[List[ConsentableItem]] = None,
10071011
) -> ConsentPropagationStatus:
10081012
"""
@@ -1011,13 +1015,14 @@ def _invoke_consent_request_override(
10111015
"""
10121016
try:
10131017
logger.info("Invoking consent request override function...")
1014-
if notice_id_to_preference_map:
1018+
if notice_preference_map:
10151019
# At this point, we've already validated the override function signature to take these params
10161020
return override_function(
1021+
connection_key,
10171022
client,
10181023
secrets,
10191024
identity_data,
1020-
notice_id_to_preference_map,
1025+
notice_preference_map,
10211026
consentable_items_hierarchy,
10221027
) # type: ignore
10231028
return override_function(

src/fides/api/service/saas_request/saas_request_override_factory.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ def validate_update_consent_function(f: Callable) -> None:
248248
)
249249
if len(sig.parameters) < 5:
250250
raise InvalidSaaSRequestOverrideException(
251-
"Provided SaaS update consent function must declare at least 4 parameters"
251+
"Provided SaaS update consent function must declare at least 5 parameters"
252252
)
253253

254254

@@ -258,9 +258,9 @@ def validate_process_consent_webhook_function(f: Callable) -> None:
258258
raise InvalidSaaSRequestOverrideException(
259259
"Provided SaaS process consent webhook function must return a ConsentWebhookResult"
260260
)
261-
if len(sig.parameters) < 5:
261+
if len(sig.parameters) < 4:
262262
raise InvalidSaaSRequestOverrideException(
263-
"Provided SaaS process consent webhook function must declare at least 5 parameters"
263+
"Provided SaaS process consent webhook function must declare at least 4 parameters"
264264
)
265265

266266

src/fides/api/task/graph_task.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,16 +125,15 @@ def result(*args: Any, **kwargs: Any) -> Any:
125125
ActionDisabled,
126126
NotSupportedForCollection,
127127
) as exc:
128-
traceback.print_exc()
129128
logger.warning(
130-
"Skipping collection {} for privacy_request: {}",
129+
"{} - Skipping collection {} for privacy_request: {}",
130+
exc.__class__.__name__,
131131
self.execution_node.address,
132132
self.resources.request.id,
133133
)
134134
self.log_skipped(action_type, exc)
135135
return default_return
136136
except SkippingConsentPropagation as exc:
137-
traceback.print_exc()
138137
logger.warning(
139138
"Skipping consent propagation on collection {} for privacy_request: {}",
140139
self.execution_node.address,

src/fides/api/util/consent_util.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def build_user_consent_and_filtered_preferences_for_service(
6464
session: Session,
6565
is_notice_based: bool = False,
6666
) -> Tuple[
67-
Optional[Union[bool, Dict[str, UserConsentPreference]]],
67+
Optional[Union[bool, Dict[str, Dict[str, Any]]]],
6868
List[PrivacyPreferenceHistory],
6969
]:
7070
"""
@@ -109,7 +109,7 @@ def build_user_consent_and_filtered_preferences_for_service(
109109

110110
# 1. NOTICE-BASED WORKFLOW
111111
if is_notice_based:
112-
notice_id_to_preference_map: Dict[str, UserConsentPreference] = {}
112+
notice_preference_map: Dict[str, Dict[str, Any]] = {}
113113
# retrieve notices from the DB if they are associated with a relevant preference
114114
notices_with_preference: Query = session.query(PrivacyNotice).filter(
115115
PrivacyNotice.notice_key.in_(
@@ -125,10 +125,16 @@ def build_user_consent_and_filtered_preferences_for_service(
125125
]
126126
# we only expect max 1 preference in this list
127127
if preference and preference[0]:
128-
notice_id_to_preference_map[notice.id] = preference[0].preference # type: ignore[assignment]
128+
notice_preference_map[notice.id] = {
129+
"preference": preference[0].preference,
130+
"notice_key": notice.notice_key,
131+
}
129132
filtered_preferences.append(preference[0])
130133

131-
return notice_id_to_preference_map, filtered_preferences
134+
return (
135+
notice_preference_map,
136+
filtered_preferences,
137+
)
132138

133139
# 2. GLOBAL (OPT-IN/OUT) WORKFLOW
134140
preference_to_propagate: UserConsentPreference = (

tests/ops/service/connectors/test_saas_connector.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from uuid import uuid4
77

88
import pytest
9+
from fideslang.models import FidesKey
910
from requests import Response
1011
from sqlalchemy.orm import Session
1112
from starlette.status import HTTP_200_OK, HTTP_204_NO_CONTENT, HTTP_404_NOT_FOUND
@@ -50,10 +51,11 @@ def uuid():
5051

5152

5253
def valid_consent_update_override(
54+
connection_key: FidesKey,
5355
client: AuthenticatedClient,
5456
secrets: Dict[str, Any],
5557
input_data: Dict[str, List[Any]],
56-
notice_id_to_preference_map: Dict[str, UserConsentPreference],
58+
notice_preference_map: Dict[str, Dict[str, Any]],
5759
consentable_items_hierarchy: List[ConsentableItem],
5860
) -> ConsentPropagationStatus:
5961
"""

tests/ops/service/saas_request/test_saas_request_override_factory.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from uuid import uuid4
33

44
import pytest
5+
from fideslang.validation import FidesKey
56

67
from fides.api.common_exceptions import (
78
InvalidSaaSRequestOverrideException,
@@ -91,6 +92,7 @@ def valid_consent_override(
9192

9293

9394
def valid_consent_update_override(
95+
connection_key: FidesKey,
9496
client: AuthenticatedClient,
9597
secrets: Dict[str, Any],
9698
input_data: Dict[str, List[Any]],
@@ -107,7 +109,6 @@ def valid_process_consent_webhook_override(
107109
client: AuthenticatedClient,
108110
secrets: Dict[str, Any],
109111
payload: Any,
110-
notice_id_to_preference_map: Dict[str, UserConsentPreference],
111112
consentable_items: List[ConsentableItem],
112113
) -> ConsentWebhookResult:
113114
"""

tests/ops/util/test_consent_util.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,17 +163,23 @@ def test_notice_based_consent_multiple_preferences(
163163
pref_4.privacy_request_id = privacy_request_with_consent_policy.id
164164
pref_4.save(db)
165165

166-
notice_id_to_preference_map, filtered_preferences = (
166+
notice_preference_map, filtered_preferences = (
167167
build_user_consent_and_filtered_preferences_for_service(
168168
system,
169169
privacy_request_with_consent_policy,
170170
db,
171171
True, # signal notice-based consent
172172
)
173173
)
174-
assert notice_id_to_preference_map == {
175-
privacy_notice.id: UserConsentPreference.opt_in,
176-
privacy_notice_2.id: UserConsentPreference.opt_out,
174+
assert notice_preference_map == {
175+
privacy_notice.id: {
176+
"preference": UserConsentPreference.opt_in,
177+
"notice_key": privacy_notice.notice_key,
178+
},
179+
privacy_notice_2.id: {
180+
"preference": UserConsentPreference.opt_out,
181+
"notice_key": privacy_notice_2.notice_key,
182+
},
177183
}
178184
assert filtered_preferences == [pref_1, pref_2]
179185

0 commit comments

Comments
 (0)