From 7591e3fb388c67b856f3d0e537fc79fda8338b76 Mon Sep 17 00:00:00 2001 From: jpople Date: Wed, 16 Oct 2024 10:57:14 -0500 Subject: [PATCH] Fix cookies not deleting on opt-out (#5338) Co-authored-by: eastandwestwind --- .fides/db_dataset.yml | 6 ++ .../cypress/e2e/privacy-experiences.cy.ts | 1 + .../privacy-experiences/experienceConfig.json | 1 + .../PrivacyExperienceForm.tsx | 7 ++ .../privacy-experience/form/helpers.tsx | 1 + .../privacy-experience/preview/helpers.ts | 1 + .../api/models/ExperienceConfigCreate.ts | 1 + .../api/models/ExperienceConfigResponse.ts | 1 + .../ExperienceConfigResponseNoNotices.ts | 1 + .../api/models/ExperienceConfigUpdate.ts | 1 + .../api/models/MinimalTCFExperienceConfig.ts | 1 + .../__fixtures__/mock_experience.json | 1 + clients/fides-js/__tests__/lib/cookie.test.ts | 75 +++++++++++++++---- clients/fides-js/src/lib/consent-types.ts | 6 +- clients/fides-js/src/lib/cookie.ts | 10 ++- clients/fides-js/src/lib/preferences.ts | 5 +- .../consent/experience_banner_modal.json | 1 + .../experience_banner_modal_notice_only.json | 1 + .../fixtures/consent/experience_gpp.json | 1 + .../fixtures/consent/experience_modal.json | 1 + .../consent/experience_privacy_center.json | 1 + ...xperience_privacy_center_hierarchical.json | 1 + .../fixtures/consent/experience_tcf.json | 1 + .../consent/experience_tcf_minimal.json | 1 + .../consent/fidesjs_options_banner_modal.json | 1 + .../public/fides-js-components-demo.html | 1 + .../api/models/ExperienceConfigCreate.ts | 1 + .../api/models/ExperienceConfigResponse.ts | 1 + .../ExperienceConfigResponseNoNotices.ts | 1 + .../api/models/ExperienceConfigUpdate.ts | 1 + ...adds_auto_subdomain_cookie_deletion_on_.py | 60 +++++++++++++++ src/fides/api/models/privacy_experience.py | 12 +++ 32 files changed, 187 insertions(+), 18 deletions(-) create mode 100644 src/fides/api/alembic/migrations/versions/36ad82edb38e_adds_auto_subdomain_cookie_deletion_on_.py diff --git a/.fides/db_dataset.yml b/.fides/db_dataset.yml index b8cee7ddfa..ef1638597c 100644 --- a/.fides/db_dataset.yml +++ b/.fides/db_dataset.yml @@ -1064,6 +1064,8 @@ dataset: data_categories: [ system.operations ] - name: auto_detect_language data_categories: [ system.operations ] + - name: auto_subdomain_cookie_deletion + data_categories: [ system.operations ] - name: id data_categories: [system.operations] - name: name @@ -1105,6 +1107,8 @@ dataset: data_categories: [ system.operations ] - name: auto_detect_language data_categories: [ system.operations ] + - name: auto_subdomain_cookie_deletion + data_categories: [ system.operations ] - name: id data_categories: [system.operations] - name: is_default @@ -2001,6 +2005,8 @@ dataset: data_categories: [ system.operations ] - name: auto_detect_language data_categories: [ system.operations ] + - name: auto_subdomain_cookie_deletion + data_categories: [ system.operations ] - name: id data_categories: [system.operations] - name: name diff --git a/clients/admin-ui/cypress/e2e/privacy-experiences.cy.ts b/clients/admin-ui/cypress/e2e/privacy-experiences.cy.ts index 1dd2f27e96..e039267cc2 100644 --- a/clients/admin-ui/cypress/e2e/privacy-experiences.cy.ts +++ b/clients/admin-ui/cypress/e2e/privacy-experiences.cy.ts @@ -207,6 +207,7 @@ describe("Privacy experiences", () => { expect(body).to.eql({ allow_language_selection: false, auto_detect_language: true, + auto_subdomain_cookie_deletion: true, component: "banner_and_modal", disabled: true, dismissable: true, diff --git a/clients/admin-ui/cypress/fixtures/privacy-experiences/experienceConfig.json b/clients/admin-ui/cypress/fixtures/privacy-experiences/experienceConfig.json index 2c754eff6c..923e92678e 100644 --- a/clients/admin-ui/cypress/fixtures/privacy-experiences/experienceConfig.json +++ b/clients/admin-ui/cypress/fixtures/privacy-experiences/experienceConfig.json @@ -6,6 +6,7 @@ "layer1_button_options": "opt_in_opt_out", "allow_language_selection": false, "auto_detect_language": true, + "auto_subdomain_cookie_deletion": true, "regions": ["us_ca", "us_co", "us_ct", "us_ut", "us_va"], "id": "pri_001", "created_at": "2024-03-22T20:06:27.119285+00:00", diff --git a/clients/admin-ui/src/features/privacy-experience/PrivacyExperienceForm.tsx b/clients/admin-ui/src/features/privacy-experience/PrivacyExperienceForm.tsx index 350ff158ec..3d23aad000 100644 --- a/clients/admin-ui/src/features/privacy-experience/PrivacyExperienceForm.tsx +++ b/clients/admin-ui/src/features/privacy-experience/PrivacyExperienceForm.tsx @@ -315,6 +315,13 @@ export const PrivacyExperienceForm = ({ Edit experience text )} + ); }; diff --git a/clients/admin-ui/src/features/privacy-experience/form/helpers.tsx b/clients/admin-ui/src/features/privacy-experience/form/helpers.tsx index 1b7d9be9f5..9b4961e8d9 100644 --- a/clients/admin-ui/src/features/privacy-experience/form/helpers.tsx +++ b/clients/admin-ui/src/features/privacy-experience/form/helpers.tsx @@ -48,6 +48,7 @@ export const defaultInitialValues: Omit = { regions: [], translations: defaultTranslations, auto_detect_language: true, + auto_subdomain_cookie_deletion: true, }; // utility type to pass as a prop to the translation form export type TranslationWithLanguageName = ExperienceTranslation & diff --git a/clients/admin-ui/src/features/privacy-experience/preview/helpers.ts b/clients/admin-ui/src/features/privacy-experience/preview/helpers.ts index 4b810387ed..9f95af6c96 100644 --- a/clients/admin-ui/src/features/privacy-experience/preview/helpers.ts +++ b/clients/admin-ui/src/features/privacy-experience/preview/helpers.ts @@ -72,6 +72,7 @@ export const buildBaseConfig = ( layer1_button_options: Layer1ButtonOption.OPT_IN_OPT_OUT, allow_language_selection: true, auto_detect_language: true, + auto_subdomain_cookie_deletion: true, language: "en", // in preview mode, we show the first translation in the main window, even when multiple translations are configured translations: [buildExperienceTranslation(experienceConfig)], diff --git a/clients/admin-ui/src/types/api/models/ExperienceConfigCreate.ts b/clients/admin-ui/src/types/api/models/ExperienceConfigCreate.ts index cde3b792ca..6269cfe67d 100644 --- a/clients/admin-ui/src/types/api/models/ExperienceConfigCreate.ts +++ b/clients/admin-ui/src/types/api/models/ExperienceConfigCreate.ts @@ -21,6 +21,7 @@ export type ExperienceConfigCreate = { layer1_button_options?: Layer1ButtonOption | null; allow_language_selection?: boolean | null; auto_detect_language?: boolean | null; + auto_subdomain_cookie_deletion?: boolean | null; regions?: Array; component: ComponentType; privacy_notice_ids?: Array; diff --git a/clients/admin-ui/src/types/api/models/ExperienceConfigResponse.ts b/clients/admin-ui/src/types/api/models/ExperienceConfigResponse.ts index 2b0b50345e..39bd043dc9 100644 --- a/clients/admin-ui/src/types/api/models/ExperienceConfigResponse.ts +++ b/clients/admin-ui/src/types/api/models/ExperienceConfigResponse.ts @@ -20,6 +20,7 @@ export type ExperienceConfigResponse = { layer1_button_options?: Layer1ButtonOption | null; allow_language_selection?: boolean | null; auto_detect_language?: boolean | null; + auto_subdomain_cookie_deletion?: boolean | null; regions: Array; id: string; created_at: string; diff --git a/clients/admin-ui/src/types/api/models/ExperienceConfigResponseNoNotices.ts b/clients/admin-ui/src/types/api/models/ExperienceConfigResponseNoNotices.ts index 13fd88140f..fc501361c3 100644 --- a/clients/admin-ui/src/types/api/models/ExperienceConfigResponseNoNotices.ts +++ b/clients/admin-ui/src/types/api/models/ExperienceConfigResponseNoNotices.ts @@ -21,6 +21,7 @@ export type ExperienceConfigResponseNoNotices = { layer1_button_options?: Layer1ButtonOption | null; allow_language_selection?: boolean | null; auto_detect_language?: boolean | null; + auto_subdomain_cookie_deletion?: boolean | null; regions: Array; id: string; created_at: string; diff --git a/clients/admin-ui/src/types/api/models/ExperienceConfigUpdate.ts b/clients/admin-ui/src/types/api/models/ExperienceConfigUpdate.ts index 6705ed489b..3438fff6c0 100644 --- a/clients/admin-ui/src/types/api/models/ExperienceConfigUpdate.ts +++ b/clients/admin-ui/src/types/api/models/ExperienceConfigUpdate.ts @@ -25,6 +25,7 @@ export type ExperienceConfigUpdate = { layer1_button_options?: Layer1ButtonOption | null; allow_language_selection?: boolean | null; auto_detect_language?: boolean | null; + auto_subdomain_cookie_deletion?: boolean | null; regions: Array; translations: Array; privacy_notice_ids: Array; diff --git a/clients/admin-ui/src/types/api/models/MinimalTCFExperienceConfig.ts b/clients/admin-ui/src/types/api/models/MinimalTCFExperienceConfig.ts index 19f99726d9..2a3c63d098 100644 --- a/clients/admin-ui/src/types/api/models/MinimalTCFExperienceConfig.ts +++ b/clients/admin-ui/src/types/api/models/MinimalTCFExperienceConfig.ts @@ -11,6 +11,7 @@ import type { MinimalTCFBannerTranslation } from "./MinimalTCFBannerTranslation" */ export type MinimalTCFExperienceConfig = { auto_detect_language?: boolean | null; + auto_subdomain_cookie_deletion?: boolean | null; component: ComponentType; dismissable?: boolean | null; translations?: Array; diff --git a/clients/fides-js/__tests__/__fixtures__/mock_experience.json b/clients/fides-js/__tests__/__fixtures__/mock_experience.json index acf6f9e4f2..5d647b2e06 100644 --- a/clients/fides-js/__tests__/__fixtures__/mock_experience.json +++ b/clients/fides-js/__tests__/__fixtures__/mock_experience.json @@ -18,6 +18,7 @@ "layer1_button_options": "opt_in_opt_out", "allow_language_selection": true, "auto_detect_language": true, + "auto_subdomain_cookie_deletion": true, "language": "en", "accept_button_label": "Accept Test", "acknowledge_button_label": "Acknowledge Test", diff --git a/clients/fides-js/__tests__/lib/cookie.test.ts b/clients/fides-js/__tests__/lib/cookie.test.ts index 576083b1c3..d6b822098e 100644 --- a/clients/fides-js/__tests__/lib/cookie.test.ts +++ b/clients/fides-js/__tests__/lib/cookie.test.ts @@ -395,35 +395,80 @@ describe("cookies", () => { afterEach(() => mockRemoveCookie.mockClear()); it.each([ - { cookies: [], expectedAttributes: [] }, - { cookies: [{ name: "_ga123" }], expectedAttributes: [{ path: "/" }] }, + { cookies: [], removeSubdomainCookies: false, expectedAttributes: [] }, + { cookies: [], removeSubdomainCookies: true, expectedAttributes: [] }, { - cookies: [{ name: "_ga123", path: "" }], - expectedAttributes: [{ path: "" }], + cookies: [{ name: "_ga123" }], + removeSubdomainCookies: false, + expectedAttributes: [{ domain: undefined, path: "/" }], }, { - cookies: [{ name: "_ga123", path: "/subpage" }], - expectedAttributes: [{ path: "/subpage" }], + cookies: [{ name: "_ga123" }], + removeSubdomainCookies: true, + expectedAttributes: [ + { domain: undefined, path: "/" }, + { domain: ".example.co.jp" }, + ], + }, + { + cookies: [{ name: "aax-uid" }, { name: "pixel" }], + removeSubdomainCookies: false, + expectedAttributes: [ + { domain: undefined, path: "/" }, + { domain: undefined, path: "/" }, + ], + }, + { + cookies: [{ name: "aax-uid" }, { name: "pixel" }], + removeSubdomainCookies: true, + expectedAttributes: [ + { domain: undefined, path: "/" }, + { domain: ".example.co.jp" }, + ], }, + // these cookies won't actually end up being deleted in the browser + // https://ethyca.atlassian.net/browse/PROD-2830 { - cookies: [{ name: "_ga123" }, { name: "shopify" }], - expectedAttributes: [{ path: "/" }, { path: "/" }], + cookies: [{ name: "test-cookie", domain: `"[*]"` }], + removeSubdomainCookies: false, + expectedAttributes: [{ domain: `"[*]"`, path: "/" }], + }, + { + cookies: [{ name: "test-cookie", domain: `"[*]"` }], + removeSubdomainCookies: true, + expectedAttributes: [ + { domain: `"[*]"`, path: "/" }, + { domain: ".example.co.jp" }, + ], }, ])( "should remove a list of cookies", ({ cookies, + removeSubdomainCookies, expectedAttributes, }: { cookies: CookiesType[]; - expectedAttributes: CookieAttributes[]; + removeSubdomainCookies?: boolean; + expectedAttributes: Array; }) => { - removeCookiesFromBrowser(cookies); - expect(mockRemoveCookie.mock.calls).toHaveLength(cookies.length); - cookies.forEach((cookie, idx) => { - const [name, attributes] = mockRemoveCookie.mock.calls[idx]; - expect(name).toEqual(cookie.name); - expect(attributes).toEqual(expectedAttributes[idx]); + removeCookiesFromBrowser(cookies, removeSubdomainCookies); + const expectedLength = removeSubdomainCookies + ? cookies.length * 2 + : cookies.length; + expect(mockRemoveCookie.mock.calls).toHaveLength(expectedLength); + cookies.forEach((cookie, cookieIdx) => { + const calls = removeSubdomainCookies + ? mockRemoveCookie.mock.calls.slice( + cookieIdx * 2, + cookieIdx * 2 + 2, + ) + : mockRemoveCookie.mock.calls.slice(cookieIdx, cookieIdx + 1); + calls.forEach((call, i) => { + const [name, attributes] = call; + expect(name).toEqual(cookie.name); + expect(attributes).toEqual(expectedAttributes[i]); + }); }); }, ); diff --git a/clients/fides-js/src/lib/consent-types.ts b/clients/fides-js/src/lib/consent-types.ts index d56d012dc4..4ee70e4eb6 100644 --- a/clients/fides-js/src/lib/consent-types.ts +++ b/clients/fides-js/src/lib/consent-types.ts @@ -433,7 +433,10 @@ interface ExperienceConfigTranslationMinimal export interface ExperienceConfigMinimal extends Pick< ExperienceConfig, - "component" | "auto_detect_language" | "dismissable" + | "component" + | "auto_detect_language" + | "dismissable" + | "auto_subdomain_cookie_deletion" > { translations: ExperienceConfigTranslationMinimal[]; } @@ -481,6 +484,7 @@ export type ExperienceConfig = { allow_language_selection?: boolean; auto_detect_language?: boolean; modal_link_label?: string; + auto_subdomain_cookie_deletion?: boolean; /** * List of regions that apply to this ExperienceConfig. diff --git a/clients/fides-js/src/lib/cookie.ts b/clients/fides-js/src/lib/cookie.ts index 0c0f103410..c4785e313a 100644 --- a/clients/fides-js/src/lib/cookie.ts +++ b/clients/fides-js/src/lib/cookie.ts @@ -331,13 +331,21 @@ export const makeConsentDefaultsLegacy = ( /** * Given a list of cookies, deletes them from the browser + * Optionally removes subdomain cookies as well */ -export const removeCookiesFromBrowser = (cookiesToRemove: CookiesType[]) => { +export const removeCookiesFromBrowser = ( + cookiesToRemove: CookiesType[], + removeSubdomainCookies: boolean = true, +) => { cookiesToRemove.forEach((cookie) => { cookies.remove(cookie.name, { path: cookie.path ?? "/", domain: cookie.domain, }); + if (removeSubdomainCookies) { + const { hostname } = window.location; + cookies.remove(cookie.name, { domain: `.${hostname}` }); + } }); }; diff --git a/clients/fides-js/src/lib/preferences.ts b/clients/fides-js/src/lib/preferences.ts index ef63a60aa1..def22f2029 100644 --- a/clients/fides-js/src/lib/preferences.ts +++ b/clients/fides-js/src/lib/preferences.ts @@ -144,7 +144,10 @@ export const updateConsentPreferences = async ({ ) .forEach((preference) => { if (preference.notice?.cookies) { - removeCookiesFromBrowser(preference.notice.cookies); + removeCookiesFromBrowser( + preference.notice.cookies, + experience.experience_config?.auto_subdomain_cookie_deletion, + ); } }); } diff --git a/clients/privacy-center/cypress/fixtures/consent/experience_banner_modal.json b/clients/privacy-center/cypress/fixtures/consent/experience_banner_modal.json index 1e2d1ff9db..203c717156 100644 --- a/clients/privacy-center/cypress/fixtures/consent/experience_banner_modal.json +++ b/clients/privacy-center/cypress/fixtures/consent/experience_banner_modal.json @@ -62,6 +62,7 @@ "layer1_button_options": "opt_in_opt_out", "allow_language_selection": true, "auto_detect_language": true, + "auto_subdomain_cookie_deletion": true, "disabled": false, "id": "pri_exp-banner-modal-000", "component": "banner_and_modal", diff --git a/clients/privacy-center/cypress/fixtures/consent/experience_banner_modal_notice_only.json b/clients/privacy-center/cypress/fixtures/consent/experience_banner_modal_notice_only.json index 4bc7ab3af3..db38447a9c 100644 --- a/clients/privacy-center/cypress/fixtures/consent/experience_banner_modal_notice_only.json +++ b/clients/privacy-center/cypress/fixtures/consent/experience_banner_modal_notice_only.json @@ -61,6 +61,7 @@ "layer1_button_options": "opt_in_opt_out", "allow_language_selection": true, "auto_detect_language": true, + "auto_subdomain_cookie_deletion": true, "disabled": false, "id": "pri_exp-banner-modal-000", "component": "banner_and_modal", diff --git a/clients/privacy-center/cypress/fixtures/consent/experience_gpp.json b/clients/privacy-center/cypress/fixtures/consent/experience_gpp.json index 71137c0bc9..b2dc1f6bbe 100644 --- a/clients/privacy-center/cypress/fixtures/consent/experience_gpp.json +++ b/clients/privacy-center/cypress/fixtures/consent/experience_gpp.json @@ -54,6 +54,7 @@ "layer1_button_options": "opt_in_opt_out", "allow_language_selection": true, "auto_detect_language": true, + "auto_subdomain_cookie_deletion": true, "disabled": false, "id": "pri_exp-gpp-banner-modal-000", "component": "banner_and_modal", diff --git a/clients/privacy-center/cypress/fixtures/consent/experience_modal.json b/clients/privacy-center/cypress/fixtures/consent/experience_modal.json index 3598c0e932..bb2138d052 100644 --- a/clients/privacy-center/cypress/fixtures/consent/experience_modal.json +++ b/clients/privacy-center/cypress/fixtures/consent/experience_modal.json @@ -62,6 +62,7 @@ "layer1_button_options": "opt_in_opt_out", "allow_language_selection": true, "auto_detect_language": true, + "auto_subdomain_cookie_deletion": true, "disabled": false, "id": "pri_exp-modal-000", "component": "modal", diff --git a/clients/privacy-center/cypress/fixtures/consent/experience_privacy_center.json b/clients/privacy-center/cypress/fixtures/consent/experience_privacy_center.json index 0bf463d1dd..ad57ee34e4 100644 --- a/clients/privacy-center/cypress/fixtures/consent/experience_privacy_center.json +++ b/clients/privacy-center/cypress/fixtures/consent/experience_privacy_center.json @@ -62,6 +62,7 @@ "layer1_button_options": "opt_in_opt_out", "allow_language_selection": true, "auto_detect_language": true, + "auto_subdomain_cookie_deletion": true, "disabled": false, "id": "pri_exp-privacy-center-000", "component": "privacy_center", diff --git a/clients/privacy-center/cypress/fixtures/consent/experience_privacy_center_hierarchical.json b/clients/privacy-center/cypress/fixtures/consent/experience_privacy_center_hierarchical.json index 06314f9b8a..7a6b611b6f 100644 --- a/clients/privacy-center/cypress/fixtures/consent/experience_privacy_center_hierarchical.json +++ b/clients/privacy-center/cypress/fixtures/consent/experience_privacy_center_hierarchical.json @@ -62,6 +62,7 @@ "layer1_button_options": "opt_in_opt_out", "allow_language_selection": true, "auto_detect_language": true, + "auto_subdomain_cookie_deletion": true, "disabled": false, "id": "pri_exp-privacy-center-000", "component": "privacy_center", diff --git a/clients/privacy-center/cypress/fixtures/consent/experience_tcf.json b/clients/privacy-center/cypress/fixtures/consent/experience_tcf.json index d47272928f..75660b614e 100644 --- a/clients/privacy-center/cypress/fixtures/consent/experience_tcf.json +++ b/clients/privacy-center/cypress/fixtures/consent/experience_tcf.json @@ -73,6 +73,7 @@ "layer1_button_options": "opt_in_opt_out", "allow_language_selection": true, "auto_detect_language": true, + "auto_subdomain_cookie_deletion": true, "disabled": false, "id": "pri_exp-tcf-overlay-000", "component": "tcf_overlay", diff --git a/clients/privacy-center/cypress/fixtures/consent/experience_tcf_minimal.json b/clients/privacy-center/cypress/fixtures/consent/experience_tcf_minimal.json index d68a4d987e..46e75319b3 100644 --- a/clients/privacy-center/cypress/fixtures/consent/experience_tcf_minimal.json +++ b/clients/privacy-center/cypress/fixtures/consent/experience_tcf_minimal.json @@ -12,6 +12,7 @@ "experience_config": { "dismissable": true, "auto_detect_language": true, + "auto_subdomain_cookie_deletion": true, "component": "tcf_overlay", "translations": [ { diff --git a/clients/privacy-center/cypress/fixtures/consent/fidesjs_options_banner_modal.json b/clients/privacy-center/cypress/fixtures/consent/fidesjs_options_banner_modal.json index 52c90eaa5d..429b2f2264 100644 --- a/clients/privacy-center/cypress/fixtures/consent/fidesjs_options_banner_modal.json +++ b/clients/privacy-center/cypress/fixtures/consent/fidesjs_options_banner_modal.json @@ -74,6 +74,7 @@ "layer1_button_options": "opt_in_opt_out", "allow_language_selection": true, "auto_detect_language": true, + "auto_subdomain_cookie_deletion": true, "disabled": false, "id": "pri_exp-banner-modal-000", "component": "banner_and_modal", diff --git a/clients/privacy-center/public/fides-js-components-demo.html b/clients/privacy-center/public/fides-js-components-demo.html index 4427b96319..7818a6ef95 100644 --- a/clients/privacy-center/public/fides-js-components-demo.html +++ b/clients/privacy-center/public/fides-js-components-demo.html @@ -70,6 +70,7 @@ layer1_button_options: "opt_in_opt_out", allow_language_selection: true, auto_detect_language: true, + auto_subdomain_cookie_deletion: true, language: "en", accept_button_label: "Accept Test", acknowledge_button_label: "Acknowledge Test", diff --git a/clients/privacy-center/types/api/models/ExperienceConfigCreate.ts b/clients/privacy-center/types/api/models/ExperienceConfigCreate.ts index cde3b792ca..6269cfe67d 100644 --- a/clients/privacy-center/types/api/models/ExperienceConfigCreate.ts +++ b/clients/privacy-center/types/api/models/ExperienceConfigCreate.ts @@ -21,6 +21,7 @@ export type ExperienceConfigCreate = { layer1_button_options?: Layer1ButtonOption | null; allow_language_selection?: boolean | null; auto_detect_language?: boolean | null; + auto_subdomain_cookie_deletion?: boolean | null; regions?: Array; component: ComponentType; privacy_notice_ids?: Array; diff --git a/clients/privacy-center/types/api/models/ExperienceConfigResponse.ts b/clients/privacy-center/types/api/models/ExperienceConfigResponse.ts index 2b0b50345e..39bd043dc9 100644 --- a/clients/privacy-center/types/api/models/ExperienceConfigResponse.ts +++ b/clients/privacy-center/types/api/models/ExperienceConfigResponse.ts @@ -20,6 +20,7 @@ export type ExperienceConfigResponse = { layer1_button_options?: Layer1ButtonOption | null; allow_language_selection?: boolean | null; auto_detect_language?: boolean | null; + auto_subdomain_cookie_deletion?: boolean | null; regions: Array; id: string; created_at: string; diff --git a/clients/privacy-center/types/api/models/ExperienceConfigResponseNoNotices.ts b/clients/privacy-center/types/api/models/ExperienceConfigResponseNoNotices.ts index 13fd88140f..fc501361c3 100644 --- a/clients/privacy-center/types/api/models/ExperienceConfigResponseNoNotices.ts +++ b/clients/privacy-center/types/api/models/ExperienceConfigResponseNoNotices.ts @@ -21,6 +21,7 @@ export type ExperienceConfigResponseNoNotices = { layer1_button_options?: Layer1ButtonOption | null; allow_language_selection?: boolean | null; auto_detect_language?: boolean | null; + auto_subdomain_cookie_deletion?: boolean | null; regions: Array; id: string; created_at: string; diff --git a/clients/privacy-center/types/api/models/ExperienceConfigUpdate.ts b/clients/privacy-center/types/api/models/ExperienceConfigUpdate.ts index 6705ed489b..3438fff6c0 100644 --- a/clients/privacy-center/types/api/models/ExperienceConfigUpdate.ts +++ b/clients/privacy-center/types/api/models/ExperienceConfigUpdate.ts @@ -25,6 +25,7 @@ export type ExperienceConfigUpdate = { layer1_button_options?: Layer1ButtonOption | null; allow_language_selection?: boolean | null; auto_detect_language?: boolean | null; + auto_subdomain_cookie_deletion?: boolean | null; regions: Array; translations: Array; privacy_notice_ids: Array; diff --git a/src/fides/api/alembic/migrations/versions/36ad82edb38e_adds_auto_subdomain_cookie_deletion_on_.py b/src/fides/api/alembic/migrations/versions/36ad82edb38e_adds_auto_subdomain_cookie_deletion_on_.py new file mode 100644 index 0000000000..1d0ffd585a --- /dev/null +++ b/src/fides/api/alembic/migrations/versions/36ad82edb38e_adds_auto_subdomain_cookie_deletion_on_.py @@ -0,0 +1,60 @@ +"""adds auto_subdomain_cookie_deletion on experience config, migrate to write initial val of false + +Revision ID: 36ad82edb38e +Revises: 5dafbc1818ae +Create Date: 2024-10-07 19:30:03.559747 + +""" + +import sqlalchemy as sa +from alembic import op + +# revision identifiers, used by Alembic. +revision = "36ad82edb38e" +down_revision = "5dafbc1818ae" +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column( + "experienceconfigtemplate", + sa.Column( + "auto_subdomain_cookie_deletion", + sa.Boolean(), + server_default="t", + nullable=False, + ), + ) + op.add_column( + "privacyexperienceconfig", + sa.Column( + "auto_subdomain_cookie_deletion", + sa.Boolean(), + server_default="t", + nullable=False, + ), + ) + op.add_column( + "privacyexperienceconfighistory", + sa.Column( + "auto_subdomain_cookie_deletion", + sa.Boolean(), + nullable=True, + ), + ) + + # Updates all existing privacy experience configs to be False. Moving forward this will be set to True by default. + op.execute( + "UPDATE privacyexperienceconfig SET auto_subdomain_cookie_deletion = FALSE" + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column("privacyexperienceconfig", "auto_subdomain_cookie_deletion") + op.drop_column("experienceconfigtemplate", "auto_subdomain_cookie_deletion") + op.drop_column("privacyexperienceconfighistory", "auto_subdomain_cookie_deletion") + # ### end Alembic commands ### diff --git a/src/fides/api/models/privacy_experience.py b/src/fides/api/models/privacy_experience.py index da4814c8b1..c275b208b3 100644 --- a/src/fides/api/models/privacy_experience.py +++ b/src/fides/api/models/privacy_experience.py @@ -77,6 +77,12 @@ class PrivacyExperienceConfigBase: auto_detect_language = Column( Boolean, ) + auto_subdomain_cookie_deletion = Column( + Boolean, + nullable=True, + default=True, + ) # base is nullable for privacy experience config history + disabled = Column(Boolean, nullable=False, default=True) dismissable = Column(Boolean) @@ -111,6 +117,9 @@ class ExperienceConfigTemplate(PrivacyExperienceConfigBase, Base): auto_detect_language = Column( Boolean, nullable=False, default=True, server_default="t" ) # Overrides PrivacyExperienceConfigBase to make non-nullable + auto_subdomain_cookie_deletion = Column( + Boolean, nullable=False, default=True, server_default="t" + ) # Overrides PrivacyExperienceConfigBase to make non-nullable dismissable = Column( Boolean, nullable=False, default=True, server_default="t" ) # Overrides PrivacyExperienceConfigBase to make non-nullable @@ -175,6 +184,9 @@ class PrivacyExperienceConfig(PrivacyExperienceConfigBase, Base): auto_detect_language = Column( Boolean, nullable=False, default=True, server_default="t" ) # Overrides PrivacyExperienceConfigBase to make non-nullable + auto_subdomain_cookie_deletion = Column( + Boolean, nullable=False, default=True, server_default="t" + ) # Overrides PrivacyExperienceConfigBase to make non-nullable disabled = Column( Boolean, nullable=False, default=True, index=True ) # Overridding PrivacyExperienceConfigBase to index