Skip to content

Commit

Permalink
Update to not fetch experience if it is empty (#4149)
Browse files Browse the repository at this point in the history
Co-authored-by: Neville Samuell <[email protected]>
  • Loading branch information
eastandwestwind and NevilleS authored Sep 25, 2023
1 parent 28a9021 commit 6035252
Show file tree
Hide file tree
Showing 8 changed files with 231 additions and 34 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ The types of changes are:
### Fixed
- Allows CDN to cache empty experience responses from fides.js API [#4113](https://github.com/ethyca/fides/pull/4113)
- added version_added, version_deprecated, and replaced_by to data use, data subject, and data category APIs [#4135](https://github.com/ethyca/fides/pull/4135)
- Update fides.js to not fetch experience client-side if pre-fetched experience is empty [#4149](https://github.com/ethyca/fides/pull/4149)

## [2.20.1](https://github.com/ethyca/fides/compare/2.20.0...2.20.1)

Expand Down
104 changes: 104 additions & 0 deletions clients/fides-js/__tests__/lib/consent-utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { isPrivacyExperience } from "../../src/lib/consent-utils";

const MOCK_EXPERIENCE = {
id: "132345243",
region: "us_ca",
show_banner: true,
component: "overlay",
created_at: "2023-04-24T21:29:08.870351+00:00",
updated_at: "2023-04-24T21:29:08.870351+00:00",
experience_config: {
accept_button_label: "Accept Test",
acknowledge_button_label: "OK",
banner_enabled: "enabled_where_required",
disabled: false,
description:
"We use cookies and similar methods to recognize visitors and remember their preferences. We also use them to measure ad campaign effectiveness, target ads and analyze site traffic. Learn more about these methods, including how to manage them, by clicking ‘Manage Preferences.’ By clicking ‘accept’ you consent to the of these methods by us and our third parties. By clicking ‘reject’ you decline the use of these methods.",
reject_button_label: "Reject Test",
is_default: false,
save_button_label: "Save test",
title: "Manage your consent",
component: "overlay",
version: 2.0,
privacy_policy_link_label: "Privacy policy",
privacy_policy_url: "https://privacy.ethyca.com/",
privacy_preferences_link_label: "Manage preferences",
created_at: "2023-04-24T21:29:08.870351+00:00",
updated_at: "2023-04-24T21:29:08.870351+00:00",
id: "2348571y34",
regions: ["us_ca"],
},
privacy_notices: [
{
name: "Test privacy notice",
disabled: false,
origin: "12435134",
description: "a test sample privacy notice configuration",
internal_description:
"a test sample privacy notice configuration for internal use",
regions: ["us_ca"],
consent_mechanism: "opt_in",
default_preference: "opt_out",
current_preference: null,
outdated_preference: null,
has_gpc_flag: true,
data_uses: ["advertising", "third_party_sharing"],
enforcement_level: "system_wide",
displayed_in_overlay: true,
displayed_in_api: true,
displayed_in_privacy_center: false,
id: "pri_4bed96d0-b9e3-4596-a807-26b783836374",
created_at: "2023-04-24T21:29:08.870351+00:00",
updated_at: "2023-04-24T21:29:08.870351+00:00",
version: 1.0,
privacy_notice_history_id: "pri_b09058a7-9f54-4360-8da5-4521e8975d4f",
notice_key: "advertising",
cookies: [{ name: "testCookie", path: "/", domain: null }],
},
{
name: "Essential",
description:
"Notify the user about data processing activities that are essential to your services functionality. Typically consent is not required for this.",
regions: ["us_ca"],
consent_mechanism: "notice_only",
default_preference: "opt_in",
current_preference: null,
outdated_preference: null,
has_gpc_flag: true,
data_uses: ["provide.service"],
enforcement_level: "system_wide",
displayed_in_overlay: true,
displayed_in_api: true,
displayed_in_privacy_center: false,
id: "pri_4bed96d0-b9e3-4596-a807-26b783836375",
created_at: "2023-04-24T21:29:08.870351+00:00",
updated_at: "2023-04-24T21:29:08.870351+00:00",
version: 1.0,
privacy_notice_history_id: "pri_b09058a7-9f54-4360-8da5-4521e8975d4e",
notice_key: "essential",
cookies: [],
},
],
};

describe("isPrivacyExperience", () => {
it.each([
{ label: "undefined", obj: undefined, expected: false },
{ label: "a number", obj: 7, expected: false },
{ label: "an object", obj: { foo: "bar" }, expected: false },
{ label: "a string", obj: "foo", expected: false },
{ label: "an empty object", obj: {}, expected: true },
{
label: "an object with 'id'",
obj: { id: "123456", foo: "bar" },
expected: true,
},
{
label: "a full 'experience' object",
obj: MOCK_EXPERIENCE,
expected: true,
},
])("returns $expected when input is $label", ({ obj, expected }) => {
expect(isPrivacyExperience(obj as any)).toBe(expected);
});
});
4 changes: 2 additions & 2 deletions clients/fides-js/src/lib/consent-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ export interface FidesConfig {
// Set the consent defaults from a "legacy" Privacy Center config.json.
consent?: LegacyConsentConfig;
// Set the "experience" to be used for this Fides.js instance -- overrides the "legacy" config.
// If set, Fides.js will fetch neither experience config nor user geolocation.
// If not set or is empty, Fides.js will attempt to fetch its own experience config.
// If defined or is empty, Fides.js will not fetch experience config.
// If undefined, Fides.js will attempt to fetch its own experience config.
experience?: PrivacyExperience | EmptyExperience;
// Set the geolocation for this Fides.js instance. If *not* set, Fides.js will fetch its own geolocation.
geolocation?: UserGeolocation;
Expand Down
16 changes: 14 additions & 2 deletions clients/fides-js/src/lib/consent-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,26 @@ export const debugLog = (
};

/**
* Returns true if privacy experience is null or empty
* Returns true if the provided input is a valid PrivacyExperience object.
*
* This includes the special case where the input is an empty object ({}), which
* is a valid response when the API does not find a PrivacyExperience configured
* for the given geolocation.
*/
export const isPrivacyExperience = (
obj: PrivacyExperience | undefined | EmptyExperience
): obj is PrivacyExperience => {
if (!obj) {
// Return false for all non-object types
if (!obj || typeof obj !== "object") {
return false;
}

// Treat an empty object ({}) as a valid experience
if (Object.keys(obj).length === 0) {
return true;
}

// Require at least an "id" field to be considered an experience
if ("id" in obj) {
return true;
}
Expand Down
4 changes: 3 additions & 1 deletion clients/fides-js/src/lib/initialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,9 @@ export const initialize = async ({
`User location could not be obtained. Skipping overlay initialization.`
);
shouldInitOverlay = false;
} else if (!isPrivacyExperience(experience)) {
} else if (!isPrivacyExperience(effectiveExperience)) {
// If no effective PrivacyExperience was pre-fetched, fetch one now from
// the Fides API using the current region string
effectiveExperience = await fetchExperience(
fidesRegionString,
options.fidesApiUrl,
Expand Down
Loading

0 comments on commit 6035252

Please sign in to comment.