diff --git a/CHANGELOG.md b/CHANGELOG.md index 4799ceaae5..3fb55e7d8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,9 +26,8 @@ The types of changes are: ### Changed - Upgrade to use Fideslang `3.0.0` and remove associated concepts [#4502](https://github.com/ethyca/fides/pull/4502) - -### Changed - `fides.js` now sets `supportsOOB` to `false` [#4516](https://github.com/ethyca/fides/pull/4516) +- Save consent method ("accept", "reject", "save", etc.) to `fides_consent` cookie as extra metadata [#4529](https://github.com/ethyca/fides/pull/4529) ## [2.26.0](https://github.com/ethyca/fides/compare/2.25.0...main) diff --git a/clients/admin-ui/src/types/api/models/ConsentMethod.ts b/clients/admin-ui/src/types/api/models/ConsentMethod.ts index 91835a30d3..359761155a 100644 --- a/clients/admin-ui/src/types/api/models/ConsentMethod.ts +++ b/clients/admin-ui/src/types/api/models/ConsentMethod.ts @@ -6,7 +6,7 @@ * An enumeration. */ export enum ConsentMethod { - BUTTON = "button", + BUTTON = "button", // deprecated- keeping for backwards-compatibility REJECT = "reject", ACCEPT = "accept", SAVE = "save", diff --git a/clients/fides-js/__tests__/lib/cookie.test.ts b/clients/fides-js/__tests__/lib/cookie.test.ts index 05403d1942..96f0be6237 100644 --- a/clients/fides-js/__tests__/lib/cookie.test.ts +++ b/clients/fides-js/__tests__/lib/cookie.test.ts @@ -3,6 +3,7 @@ import * as uuid from "uuid"; import { CookieAttributes } from "typescript-cookie/dist/types"; import { CookieKeyConsent, + CookieMeta, FidesCookie, getOrMakeFidesCookie, isNewFidesCookie, @@ -96,6 +97,7 @@ describe("getOrMakeFidesCookie", () => { it("makes and returns a default cookie", () => { const cookie: FidesCookie = getOrMakeFidesCookie(); expect(cookie.consent).toEqual({}); + expect(cookie.fides_meta.consentMethod).toEqual(undefined); expect(cookie.fides_meta.createdAt).toEqual(MOCK_DATE); expect(cookie.fides_meta.updatedAt).toEqual(""); expect(cookie.identity.fides_user_device_id).toEqual(MOCK_UUID); @@ -109,7 +111,7 @@ describe("getOrMakeFidesCookie", () => { const SAVED_CONSENT = { data_sales: false, performance: true }; describe("in v0.9.0 format", () => { - const V090_COOKIE = JSON.stringify({ + const V090_COOKIE_OBJECT: FidesCookie = { consent: SAVED_CONSENT, identity: { fides_user_device_id: SAVED_UUID }, fides_meta: { @@ -117,15 +119,39 @@ describe("getOrMakeFidesCookie", () => { updatedAt: UPDATED_DATE, version: "0.9.0", }, - }); - beforeEach(() => mockGetCookie.mockReturnValue(V090_COOKIE)); + tcf_consent: {}, + }; it("returns the saved cookie", () => { + mockGetCookie.mockReturnValue(JSON.stringify(V090_COOKIE_OBJECT)); + const cookie: FidesCookie = getOrMakeFidesCookie(); + expect(cookie.consent).toEqual(SAVED_CONSENT); + expect(cookie.fides_meta.consentMethod).toEqual(undefined); + expect(cookie.fides_meta.createdAt).toEqual(CREATED_DATE); + expect(cookie.fides_meta.updatedAt).toEqual(UPDATED_DATE); + expect(cookie.identity.fides_user_device_id).toEqual(SAVED_UUID); + expect(cookie.tcf_consent).toEqual({}); + }); + + it("returns the saved cookie including optional fides_meta details like consentMethod", () => { + // extend the cookie object with some extra details on fides_meta + const extendedFidesMeta: CookieMeta = { + ...V090_COOKIE_OBJECT.fides_meta, + ...{ consentMethod: "accept", otherMetadata: "foo" }, + }; + const cookieObject = { + ...V090_COOKIE_OBJECT, + ...{ fides_meta: extendedFidesMeta }, + }; + mockGetCookie.mockReturnValue(JSON.stringify(cookieObject)); const cookie: FidesCookie = getOrMakeFidesCookie(); expect(cookie.consent).toEqual(SAVED_CONSENT); + expect(cookie.fides_meta.consentMethod).toEqual("accept"); + expect(cookie.fides_meta.otherMetadata).toEqual("foo"); expect(cookie.fides_meta.createdAt).toEqual(CREATED_DATE); expect(cookie.fides_meta.updatedAt).toEqual(UPDATED_DATE); expect(cookie.identity.fides_user_device_id).toEqual(SAVED_UUID); + expect(cookie.tcf_consent).toEqual({}); }); }); @@ -137,8 +163,10 @@ describe("getOrMakeFidesCookie", () => { it("returns the saved cookie and converts to new 0.9.0 format", () => { const cookie: FidesCookie = getOrMakeFidesCookie(); expect(cookie.consent).toEqual(SAVED_CONSENT); + expect(cookie.fides_meta.consentMethod).toEqual(undefined); expect(cookie.fides_meta.createdAt).toEqual(MOCK_DATE); expect(cookie.identity.fides_user_device_id).toEqual(MOCK_UUID); + expect(cookie.tcf_consent).toEqual({}); }); }); }); @@ -154,6 +182,18 @@ describe("saveFidesCookie", () => { expect(cookie.fides_meta.updatedAt).toEqual(MOCK_DATE); }); + it("saves optional fides_meta details like consentMethod", () => { + const cookie: FidesCookie = getOrMakeFidesCookie(); + cookie.fides_meta.consentMethod = "dismiss"; + saveFidesCookie(cookie); + expect(mockSetCookie.mock.calls).toHaveLength(1); + expect(mockSetCookie.mock.calls[0][0]).toEqual("fides_consent"); // name + const cookieValue = mockSetCookie.mock.calls[0][1]; + const cookieParsed = JSON.parse(cookieValue); + expect(cookieParsed.fides_meta).toHaveProperty("consentMethod"); + expect(cookieParsed.fides_meta.consentMethod).toEqual("dismiss"); + }); + it("sets a cookie on the root domain with 1 year expiry date", () => { const cookie: FidesCookie = getOrMakeFidesCookie(); saveFidesCookie(cookie); @@ -274,19 +314,23 @@ describe("isNewFidesCookie", () => { }); describe("when a saved cookie exists", () => { + const CONSENT_METHOD = "accept"; const CREATED_DATE = "2022-12-24T12:00:00.000Z"; const UPDATED_DATE = "2022-12-25T12:00:00.000Z"; const SAVED_UUID = "8a46c3ee-d6c3-4518-9b6c-074528b7bfd0"; const SAVED_CONSENT = { data_sales: false, performance: true }; - const V090_COOKIE = JSON.stringify({ + const V090_COOKIE_OBJECT: FidesCookie = { consent: SAVED_CONSENT, identity: { fides_user_device_id: SAVED_UUID }, fides_meta: { + consentMethod: CONSENT_METHOD, createdAt: CREATED_DATE, updatedAt: UPDATED_DATE, version: "0.9.0", }, - }); + tcf_consent: {}, + }; + const V090_COOKIE = JSON.stringify(V090_COOKIE_OBJECT); beforeEach(() => mockGetCookie.mockReturnValue(V090_COOKIE)); it("returns false for saved cookies", () => { diff --git a/clients/fides-js/src/components/ConsentButtons.tsx b/clients/fides-js/src/components/ConsentButtons.tsx index d51c22d7fe..f19c3ccdfa 100644 --- a/clients/fides-js/src/components/ConsentButtons.tsx +++ b/clients/fides-js/src/components/ConsentButtons.tsx @@ -99,14 +99,14 @@ export const NoticeConsentButtons = ({ const handleAcceptAll = () => { onSave( - ConsentMethod.accept, + ConsentMethod.ACCEPT, notices.map((n) => n.notice_key) ); }; const handleRejectAll = () => { onSave( - ConsentMethod.reject, + ConsentMethod.REJECT, notices .filter((n) => n.consent_mechanism === ConsentMechanism.NOTICE_ONLY) .map((n) => n.notice_key) @@ -114,7 +114,7 @@ export const NoticeConsentButtons = ({ }; const handleSave = () => { - onSave(ConsentMethod.save, enabledKeys); + onSave(ConsentMethod.SAVE, enabledKeys); }; if (isAcknowledge) { diff --git a/clients/fides-js/src/components/notices/NoticeOverlay.tsx b/clients/fides-js/src/components/notices/NoticeOverlay.tsx index 8bd437ef4e..1e6236a55d 100644 --- a/clients/fides-js/src/components/notices/NoticeOverlay.tsx +++ b/clients/fides-js/src/components/notices/NoticeOverlay.tsx @@ -135,7 +135,7 @@ const NoticeOverlay: FunctionComponent = ({ }, [cookie, options.debug]); const handleDismiss = useCallback(() => { - handleUpdatePreferences(ConsentMethod.dismiss, initialEnabledNoticeKeys); + handleUpdatePreferences(ConsentMethod.DISMISS, initialEnabledNoticeKeys); }, [handleUpdatePreferences, initialEnabledNoticeKeys]); if (!experience.experience_config) { diff --git a/clients/fides-js/src/components/tcf/TcfConsentButtons.tsx b/clients/fides-js/src/components/tcf/TcfConsentButtons.tsx index d77eb95d1d..898517dc80 100644 --- a/clients/fides-js/src/components/tcf/TcfConsentButtons.tsx +++ b/clients/fides-js/src/components/tcf/TcfConsentButtons.tsx @@ -48,7 +48,7 @@ export const TcfConsentButtons = ({ ...(experience.tcf_system_legitimate_interests || []), ]), }; - onSave(ConsentMethod.accept, allIds); + onSave(ConsentMethod.ACCEPT, allIds); }; const handleRejectAll = () => { const emptyIds: EnabledIds = { @@ -60,7 +60,7 @@ export const TcfConsentButtons = ({ vendorsConsent: [], vendorsLegint: [], }; - onSave(ConsentMethod.reject, emptyIds); + onSave(ConsentMethod.REJECT, emptyIds); }; return ( diff --git a/clients/fides-js/src/components/tcf/TcfOverlay.tsx b/clients/fides-js/src/components/tcf/TcfOverlay.tsx index 6cbc0e675b..5bf8daaa7d 100644 --- a/clients/fides-js/src/components/tcf/TcfOverlay.tsx +++ b/clients/fides-js/src/components/tcf/TcfOverlay.tsx @@ -331,7 +331,7 @@ const TcfOverlay: FunctionComponent = ({ }, [cookie, options.debug]); const handleDismiss = useCallback(() => { - handleUpdateAllPreferences(ConsentMethod.dismiss, initialEnabledIds); + handleUpdateAllPreferences(ConsentMethod.DISMISS, initialEnabledIds); }, [handleUpdateAllPreferences, initialEnabledIds]); if (!experience.experience_config) { @@ -415,7 +415,7 @@ const TcfOverlay: FunctionComponent = ({