Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

release 2.45.0 #5280

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,15 @@ The types of changes are:
- Validate no path in `server_host` var for CLI config; if there is one then take only up until the first forward slash
- Update the Datamap report's Data categories column to support better expand/collapse behavior [#5265](https://github.com/ethyca/fides/pull/5265)
- Rename/refactor Privacy Notice Properties to support performance improvements [#5259](https://github.com/ethyca/fides/pull/5259)
- Improved logging and error visibility for TraversalErrors [#5263](https://github.com/ethyca/fides/pull/5263)

### Developer Experience
- Added performance mark timings to debug logs for fides.js [#5245](https://github.com/ethyca/fides/pull/5245)

### Fixed
- Fix wording in tooltip for Yotpo Reviews [#5274](https://github.com/ethyca/fides/pull/5274)
- Hardcode ConnectionConfigurationResponse.secrets [#5283](https://github.com/ethyca/fides/pull/5283)
- Fix Fides.shouldShouldShowExperience() to return false for modal-only experiences [#5281](https://github.com/ethyca/fides/pull/5281)


## [2.44.0](https://github.com/ethyca/fides/compare/2.43.1...2.44.0)
Expand All @@ -47,6 +50,7 @@ The types of changes are:
- Adding erasure support for Microsoft Advertising [#5197](https://github.com/ethyca/fides/pull/5197)
- Implements fuzzy search for identities in Admin-UI Request Manager [#5232](https://github.com/ethyca/fides/pull/5232)
- New purpose header field for TCF banner [#5246](https://github.com/ethyca/fides/pull/5246)
- `fides` subcommand `pull` has resource name subcommands that take a `fides_key` argument allowing you to pull only one resource by name and type [#5260](https://github.com/ethyca/fides/pull/5260)

### Changed
- Removed unused `username` parameter from the Delighted integration configuration [#5220](https://github.com/ethyca/fides/pull/5220)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export type ConnectionConfigurationResponse = {
last_test_timestamp?: string | null;
last_test_succeeded?: boolean | null;
saas_config?: SaaSConfigBase | null;
secrets?: null;
secrets?: any;
authorized?: boolean | null;
enabled_actions?: Array<ActionType> | null;
};
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export type PrivacyNoticeResponse = {
created_at: string;
updated_at: string;
cookies?: Array<Cookies>;
calculated_systems_applicable?: boolean;
systems_applicable?: boolean;
translations?: Array<NoticeTranslationResponse>;
gpp_field_mapping?: Array<GPPFieldMapping> | null;
};
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export type PrivacyNoticeResponseWithRegions = {
/**
* A property calculated by observing which Experiences have linked this Notice
*/
configured_regions_for_notice?: Array<PrivacyNoticeRegion>;
configured_regions?: Array<PrivacyNoticeRegion>;
data_uses: Array<string>;
enforcement_level: EnforcementLevel;
has_gpc_flag: boolean;
Expand Down
6 changes: 5 additions & 1 deletion clients/fides-js/src/lib/consent-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,13 +238,17 @@ export const shouldResurfaceConsent = (
cookie: FidesCookie,
savedConsent: NoticeConsent,
): boolean => {
// Always resurface consent for TCF unless the saved version_hash matches
if (experience.experience_config?.component === ComponentType.TCF_OVERLAY) {
if (experience.meta?.version_hash) {
return experience.meta.version_hash !== cookie.tcf_version_hash;
}
// Ensure we always resurface consent for TCF if for some reason experience does not have version_hash
return true;
}
// Never surface consent for modal-only experiences
if (experience.experience_config?.component === ComponentType.MODAL) {
return false;
}
// Do not surface consent for null or empty notices
if (!(experience as PrivacyExperience)?.privacy_notices?.length) {
return false;
Expand Down
5 changes: 5 additions & 0 deletions clients/fides-js/src/lib/cookie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,11 @@ export const updateExperienceFromCookieConsentNotices = ({
cookie: FidesCookie;
debug?: boolean;
}): PrivacyExperience => {
// If the given experience has no notices, return immediately and do not mutate
// the experience object in any way
if (!experience.privacy_notices) {
return experience;
}
// DEFER (PROD-1568) - instead of updating experience here, push this logic into UI
const noticesWithConsent: PrivacyNoticeWithPreference[] | undefined =
experience.privacy_notices?.map((notice) => {
Expand Down
150 changes: 150 additions & 0 deletions clients/privacy-center/cypress/e2e/should-show-experience.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import {
CONSENT_COOKIE_NAME,
NoticeConsent,
PrivacyExperience,
} from "fides-js";

import { mockCookie } from "../support/mocks";
import { OVERRIDE, stubConfig, stubTCFExperience } from "../support/stubs";

describe("Fides.shouldShowExperience()", () => {
interface TestCaseOptions {
fixture:
| "experience_modal.json"
| "experience_banner_modal.json"
| "experience_tcf_minimal.json"
| "experience_none.json";
savedConsent: boolean;
expiredTcfVersionHash?: boolean;
shouldShowExperience: boolean;
}

const testCases: TestCaseOptions[] = [
{
fixture: "experience_modal.json",
savedConsent: false,
shouldShowExperience: false,
},
{
fixture: "experience_modal.json",
savedConsent: true,
shouldShowExperience: false,
},
{
fixture: "experience_banner_modal.json",
savedConsent: false,
shouldShowExperience: true,
},
{
fixture: "experience_banner_modal.json",
savedConsent: true,
shouldShowExperience: false,
},
{
fixture: "experience_tcf_minimal.json",
savedConsent: false,
shouldShowExperience: true,
},
{
fixture: "experience_tcf_minimal.json",
savedConsent: true,
shouldShowExperience: false,
},
{
fixture: "experience_tcf_minimal.json",
savedConsent: true,
expiredTcfVersionHash: true,
shouldShowExperience: true,
},
{
fixture: "experience_none.json",
savedConsent: false,
shouldShowExperience: false,
},
{
fixture: "experience_none.json",
savedConsent: true,
shouldShowExperience: false,
},
];

testCases.forEach(
({
fixture,
savedConsent,
expiredTcfVersionHash,
shouldShowExperience,
}) => {
describe(`when rendering ${fixture} and saved consent ${savedConsent ? "exists" : "does not exist"} ${expiredTcfVersionHash ? "(with expired tcf_version_hash)" : ""}`, () => {
it(`Fides.shouldShowExperience() returns ${shouldShowExperience}`, () => {
cy.fixture(`consent/${fixture}`).then((data) => {
let experience: PrivacyExperience = data.items[0] || OVERRIDE.EMPTY;
const tcfEnabled = /tcf/.test(fixture);

// If the test requires it, generate and save a prior consent cookie
if (savedConsent) {
// Mock an opt-out consent for each notice, plus an "example" other notice
const notices = [
...(experience.privacy_notices || []),
...[{ notice_key: "example" }],
];
const consent: NoticeConsent = Object.fromEntries(
notices.map((e) => [e.notice_key, false]),
);

// Mock a saved fides_string if tcf is enabled
const fides_string = tcfEnabled
? "CPzevcAPzevcAGXABBENATEIAAIAAAAAAAAAAAAAAAAA"
: undefined;

// Save a tcf_version_hash that matches the experience
let tcf_version_hash = experience.meta?.version_hash;

// Mock an "expired" hash, if the test demands it
if (expiredTcfVersionHash) {
tcf_version_hash = "1a2a3a";
}

// Save the mock cookie
const cookie = mockCookie({
consent,
fides_string,
tcf_version_hash,
});
cy.setCookie(CONSENT_COOKIE_NAME, JSON.stringify(cookie));
}

// Load the demo page with our stubbed config
cy.log("using experience = ", experience);
if (!tcfEnabled) {
stubConfig({ experience, options: { isOverlayEnabled: true } });
} else {
stubTCFExperience({});
}
});
cy.waitUntilFidesInitialized();

// Check that our test saved the consent cookie correctly
if (savedConsent) {
cy.getCookie(CONSENT_COOKIE_NAME).should("exist");
} else {
cy.getCookie(CONSENT_COOKIE_NAME).should("not.exist");
}

// Check if shouldShowExperience() returns the expected value
cy.window()
.its("Fides")
.invoke("shouldShowExperience")
.should("eql", shouldShowExperience);

// If shouldShowExperience() is true, the banner should show as well
if (shouldShowExperience) {
cy.get("div#fides-banner").should("be.visible");
} else {
cy.get("div#fides-banner").should("not.exist");
}
});
});
},
);
});
6 changes: 0 additions & 6 deletions clients/privacy-center/cypress/e2e/show-modal.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ describe("Fides.showModal", () => {
options: {
isOverlayEnabled: true,
},
experience: {
show_banner: false,
},
});
});

Expand Down Expand Up @@ -53,9 +50,6 @@ describe("Fides.showModal", () => {
options: {
isOverlayEnabled: false,
},
experience: {
show_banner: false,
},
});
});

Expand Down
121 changes: 121 additions & 0 deletions clients/privacy-center/cypress/fixtures/consent/experience_modal.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
{
"items": [
{
"region": "us_ca",
"available_locales": ["en", "es", "fr-CA"],
"experience_config": {
"translations": [
{
"language": "en",
"accept_button_label": "Opt in to all",
"acknowledge_button_label": "OK",
"banner_description": "[banner] We use cookies and similar methods to recognize visitors and remember their preferences. We may also use them to measure ad campaign effectiveness, target ads, and analyze site traffic. Depending on your location, you may opt-in or opt out of the use of these technologies.",
"banner_title": "[banner] Manage your consent preferences",
"description": "We use cookies and similar methods to recognize visitors and remember their preferences. We may also use them to measure ad campaign effectiveness, target ads, and analyze site traffic. Depending on your location, you may opt-in or opt out of the use of these technologies.",
"modal_link_label": "Manage my consent preferences",
"is_default": true,
"privacy_policy_link_label": "Privacy Policy",
"privacy_policy_url": "https://privacy.example.com/",
"privacy_preferences_link_label": "Manage preferences",
"reject_button_label": "Opt out of all",
"save_button_label": "Save",
"title": "Manage your consent preferences",
"privacy_experience_config_history_id": "pri_exp-history-modal-en-000"
},
{
"language": "es",
"accept_button_label": "Participar en todo",
"acknowledge_button_label": "Aceptar",
"banner_description": "[banner] Usamos cookies y métodos similares para reconocer a los visitantes y recordar sus preferencias. También podemos usarlos para medir la eficacia de campañas publicitarias, dirigir anuncios y analizar el tráfico del sitio. En función de su ubicación, puede optar por participar o no en el uso de estas tecnologías.",
"banner_title": "[banner] Administrar sus preferencias de consentimiento",
"description": "Usamos cookies y métodos similares para reconocer a los visitantes y recordar sus preferencias. También podemos usarlos para medir la eficacia de campañas publicitarias, dirigir anuncios y analizar el tráfico del sitio. En función de su ubicación, puede optar por participar o no en el uso de estas tecnologías.",
"modal_link_label": "Administrar mis preferencias de consentimiento",
"is_default": false,
"privacy_policy_link_label": "Política de privacidad",
"privacy_policy_url": "https://privacy.example.com/",
"privacy_preferences_link_label": "Administrar preferencias",
"reject_button_label": "No participar en nada",
"save_button_label": "Guardar",
"title": "Administrar sus preferencias de consentimiento",
"privacy_experience_config_history_id": "pri_exp-history-modal-es-000"
},
{
"language": "fr-CA",
"accept_button_label": "Tout activer",
"acknowledge_button_label": "OK",
"banner_description": "[banner] Nous utilisons des témoins et des méthodes similaires pour reconnaitre les visiteurs et se souvenir de leurs préférences. Nous pouvons également les utiliser pour mesurer l’efficacité des campagnes de publicité, cibler les annonces et analyser le trafic du site. Selon votre emplacement, vous pouvez activer ou désactiver l’utilisation de ces technologies.",
"banner_title": "[banner] Gestion de vos préférences de consentement",
"description": "Nous utilisons des témoins et des méthodes similaires pour reconnaitre les visiteurs et se souvenir de leurs préférences. Nous pouvons également les utiliser pour mesurer l’efficacité des campagnes de publicité, cibler les annonces et analyser le trafic du site. Selon votre emplacement, vous pouvez activer ou désactiver l’utilisation de ces technologies.",
"modal_link_label": "Gérer mes préférences de consentement",
"is_default": false,
"privacy_policy_link_label": "Politique de confidentialité",
"privacy_preferences_link_label": "Gestion des préférences",
"reject_button_label": "Tout désactiver",
"save_button_label": "Sauvegarder",
"title": "Gestion de vos préférences de consentement",
"privacy_experience_config_history_id": "pri_exp-history-modal-fr-ca-000"
}
],
"language": "en",
"dismissable": true,
"show_layer1_notices": false,
"layer1_button_options": "opt_in_opt_out",
"allow_language_selection": true,
"auto_detect_language": true,
"disabled": false,
"id": "pri_exp-modal-000",
"component": "modal",
"created_at": "2024-01-01T12:00:00.000000+00:00",
"updated_at": "2024-01-01T12:00:00.000000+00:00"
},
"id": "pri_exp-003-exp_modal",
"created_at": "2024-01-01T12:00:00.000000+00:00",
"updated_at": "2024-01-01T12:00:00.000000+00:00",
"privacy_notices": [
{
"name": "Data Sales and Sharing",
"notice_key": "data_sales_and_sharing",
"internal_description": null,
"origin": null,
"consent_mechanism": "opt_out",
"data_uses": [
"marketing.advertising.first_party.targeted",
"marketing.advertising.third_party.targeted"
],
"enforcement_level": "frontend",
"disabled": false,
"has_gpc_flag": false,
"id": "pri_notice-data-sales-000",
"created_at": "2024-01-01T12:00:00.000000+00:00",
"updated_at": "2024-01-01T12:00:00.000000+00:00",
"default_preference": "opt_in",
"cookies": [],
"translations": [
{
"language": "en",
"title": "Data Sales and Sharing",
"description": "We may transfer or share your personal information to third parties in exchange for monetary or other valuable consideration or for the purposes of cross-contextual targeted advertising. You can learn more about what information is used for this purpose in our privacy notice.",
"privacy_notice_history_id": "pri_notice-history-data-sales-en-000"
},
{
"language": "es",
"title": "Venta e intercambio de datos",
"description": "Podemos transferir o compartir su información personal con terceros a cambio de una contraprestación monetaria u otro tipo de valor o con fines de publicidad dirigida en contextos cruzados. En nuestra política de privacidad encontrará más detalles sobre qué tipo de información se usa para este fin.",
"privacy_notice_history_id": "pri_notice-history-data-sales-es-000"
},
{
"language": "fr-CA",
"title": "Ventes et partage de données",
"description": "Nous pouvons transférer à ou partager vos informations personnelles avec des parties tierces en échange de contrepartie monétaire ou d’autres facteurs valables ou encore dans le but de publicité ciblée contextuelle croisée. Vous pouvez en apprendre plus sur l’information utilisée à ces fins dans notre avis de confidentialité.",
"privacy_notice_history_id": "pri_notice-history-data-sales-fr-ca-000"
}
]
}
],
"gvl": {}
}
],
"total": 1,
"page": 1,
"size": 50
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"items": [],
"total": 0,
"page": 1,
"size": 50
}
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ module = [
"cassandra.*",
"celery.*",
"citext.*",
"click_default_group.*",
"dask.*",
"deepdiff.*",
"defusedxml.ElementTree.*",
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ APScheduler==3.9.1.post1
asyncpg==0.27.0
boto3==1.26.1
celery[pytest]==5.2.7
click_default_group==1.2.2
cloud-sql-python-connector==1.9.2
colorama>=0.4.3
cryptography==42.0.0
Expand Down
Loading
Loading