Skip to content

Commit

Permalink
Mobile Native POC support work (#5541)
Browse files Browse the repository at this point in the history
  • Loading branch information
gilluminate authored Dec 3, 2024
1 parent a601fbe commit 8723d84
Show file tree
Hide file tree
Showing 33 changed files with 2,036 additions and 736 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ The types of changes are:

### Added
- Added new column for Action Type in privacy request event logs [#5546](https://github.com/ethyca/fides/pull/5546)
- Added `fides_consent_override` option in FidesJS SDK [#5541](https://github.com/ethyca/fides/pull/5541)
- Added new `script` ConsentMethod in FidesJS SDK for tracking automated consent [#5541](https://github.com/ethyca/fides/pull/5541)

### Changed
- Adding hashes to system tab URLs [#5535](https://github.com/ethyca/fides/pull/5535)
- Updated Cookie House to be responsive [#5541](https://github.com/ethyca/fides/pull/5541)

### Developer Experience
- Migrated remaining instances of Chakra's Select component to use Ant's Select component [#5502](https://github.com/ethyca/fides/pull/5502)
Expand Down
2 changes: 0 additions & 2 deletions clients/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# Clients

The clients directory houses all front-end packages and shared code amongst clients, and also includes e2e tests.

See the [UI Contribution Guide](http://localhost:8000/fides/development/ui/overview/) for more information
1 change: 1 addition & 0 deletions clients/admin-ui/src/types/api/models/ConsentMethod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export enum ConsentMethod {
BUTTON = "button",
REJECT = "reject",
ACCEPT = "accept",
SCRIPT = "script",
SAVE = "save",
DISMISS = "dismiss",
GPC = "gpc",
Expand Down
16 changes: 15 additions & 1 deletion clients/fides-js/docs/interfaces/FidesOptions.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Interface: FidesOptions

FidesJS supports a variety of custom options to modify it's behavior or
enabled more advanced usage. For example, the `fides_locale` option can be
enable more advanced usage. For example, the `fides_locale` option can be
provided to override the browser locale. See the properties list below for
the supported options and example usage for each.

Expand Down Expand Up @@ -160,3 +160,17 @@ overriden at the page-level as needed. Only applicable to a TCF experience.
For more details, see the [TCF CMP API technical specification](https://github.com/InteractiveAdvertisingBureau/GDPR-Transparency-and-Consent-Framework/blob/master/TCFv2/IAB%20Tech%20Lab%20-%20CMP%20API%20v2.md#what-does-the-gdprapplies-value-mean) *

Defaults to `true`.

***

### fides\_consent\_override

> **fides\_consent\_override**: `"accept"` \| `"reject"`
FidesJS will automatically opt in or out of all notices with this option and
only show the consent modal upon user request. This is useful for any
scenario where the user has previously provided consent in a different
context (e.g. a native app, another website, etc.) and you want to ensure
that those preferences are respected.

Defaults to `undefined`.
2 changes: 1 addition & 1 deletion clients/fides-js/rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const GZIP_SIZE_ERROR_KB = 45; // fail build if bundle size exceeds this
const GZIP_SIZE_WARN_KB = 35; // log a warning if bundle size exceeds this

// TCF
const GZIP_SIZE_TCF_ERROR_KB = 85;
const GZIP_SIZE_TCF_ERROR_KB = 85.5;
const GZIP_SIZE_TCF_WARN_KB = 75;

const preactAliases = {
Expand Down
25 changes: 6 additions & 19 deletions clients/fides-js/src/components/ConsentButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { useEffect, useState } from "preact/hooks";

import {
ButtonType,
ConsentMechanism,
ConsentMethod,
FidesInitOptions,
PrivacyExperience,
Expand Down Expand Up @@ -139,6 +138,8 @@ type NoticeKeys = Array<PrivacyNotice["notice_key"]>;

interface NoticeConsentButtonProps {
experience: PrivacyExperience;
onAcceptAll: () => void;
onRejectAll: () => void;
onSave: (consentMethod: ConsentMethod, noticeKeys: NoticeKeys) => void;
onManagePreferencesClick?: () => void;
enabledKeys: NoticeKeys;
Expand All @@ -150,6 +151,8 @@ interface NoticeConsentButtonProps {

export const NoticeConsentButtons = ({
experience,
onAcceptAll,
onRejectAll,
onSave,
onManagePreferencesClick,
enabledKeys,
Expand All @@ -164,29 +167,13 @@ export const NoticeConsentButtons = ({
}
const { privacy_notices: notices } = experience;

const handleAcceptAll = () => {
onSave(
ConsentMethod.ACCEPT,
notices.map((n) => n.notice_key),
);
};

const handleAcknowledgeNotices = () => {
onSave(
ConsentMethod.ACKNOWLEDGE,
notices.map((n) => n.notice_key),
);
};

const handleRejectAll = () => {
onSave(
ConsentMethod.REJECT,
notices
.filter((n) => n.consent_mechanism === ConsentMechanism.NOTICE_ONLY)
.map((n) => n.notice_key),
);
};

const handleSave = () => {
onSave(ConsentMethod.SAVE, enabledKeys);
};
Expand Down Expand Up @@ -219,8 +206,8 @@ export const NoticeConsentButtons = ({
<ConsentButtons
availableLocales={experience.available_locales}
onManagePreferencesClick={onManagePreferencesClick}
onAcceptAll={handleAcceptAll}
onRejectAll={handleRejectAll}
onAcceptAll={onAcceptAll}
onRejectAll={onRejectAll}
isInModal={isInModal}
renderFirstButton={renderFirstButton}
hideOptInOut={hideOptInOut}
Expand Down
9 changes: 4 additions & 5 deletions clients/fides-js/src/components/Overlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from "preact/hooks";

import { useA11yDialog } from "../lib/a11y-dialog";
import { isConsentOverride } from "../lib/common-utils";
import { FIDES_OVERLAY_WRAPPER } from "../lib/consent-constants";
import {
ComponentType,
Expand All @@ -32,7 +33,6 @@ interface RenderBannerProps {
isOpen: boolean;
isEmbedded: boolean;
onClose: () => void;
onSave: () => void;
onManagePreferencesClick: () => void;
}

Expand Down Expand Up @@ -72,13 +72,15 @@ const Overlay: FunctionComponent<Props> = ({
const delayBannerMilliseconds = 100;
const delayModalLinkMilliseconds = 200;
const hasMounted = useHasMounted();
const isAutomatedConsent = isConsentOverride(options);

const showBanner = useMemo(
() =>
!isAutomatedConsent &&
!options.fidesDisableBanner &&
experience.experience_config?.component !== ComponentType.MODAL &&
shouldResurfaceConsent(experience, cookie, savedConsent),
[cookie, savedConsent, experience, options],
[cookie, savedConsent, experience, options, isAutomatedConsent],
);

const [bannerIsOpen, setBannerIsOpen] = useState(
Expand Down Expand Up @@ -237,9 +239,6 @@ const Overlay: FunctionComponent<Props> = ({
onClose: () => {
setBannerIsOpen(false);
},
onSave: () => {
setBannerIsOpen(false);
},
onManagePreferencesClick: handleManagePreferencesClick,
})
: null}
Expand Down
61 changes: 59 additions & 2 deletions clients/fides-js/src/components/notices/NoticeOverlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import "../fides.css";
import { FunctionComponent, h } from "preact";
import { useCallback, useEffect, useMemo, useState } from "preact/hooks";

import { isConsentOverride } from "../../lib/common-utils";
import { getConsentContext } from "../../lib/consent-context";
import {
ConsentMechanism,
Expand Down Expand Up @@ -229,6 +230,47 @@ const NoticeOverlay: FunctionComponent<OverlayProps> = ({
],
);

const handleAcceptAll = useCallback(
(wasAutomated?: boolean) => {
handleUpdatePreferences(
wasAutomated ? ConsentMethod.SCRIPT : ConsentMethod.ACCEPT,
privacyNoticeItems.map((n) => n.notice.notice_key),
);
},
[handleUpdatePreferences, privacyNoticeItems],
);

const handleRejectAll = useCallback(
(wasAutomated?: boolean) => {
handleUpdatePreferences(
wasAutomated ? ConsentMethod.SCRIPT : ConsentMethod.REJECT,
privacyNoticeItems
.filter(
(n) => n.notice.consent_mechanism === ConsentMechanism.NOTICE_ONLY,
)
.map((n) => n.notice.notice_key),
);
},
[handleUpdatePreferences, privacyNoticeItems],
);

useEffect(() => {
if (isConsentOverride(options) && experience.privacy_notices) {
if (options.fidesConsentOverride === ConsentMethod.ACCEPT) {
fidesDebugger(
"Consent automatically accepted by fides_accept_all override!",
);
handleAcceptAll(true);
} else if (options.fidesConsentOverride === ConsentMethod.REJECT) {
fidesDebugger(
"Consent automatically rejected by fides_reject_all override!",
);
handleRejectAll(true);
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [experience.privacy_notices, options.fidesConsentOverride]);

const dispatchOpenBannerEvent = useCallback(() => {
dispatchFidesEvent("FidesUIShown", cookie, options.debug, {
servingComponent: ServingComponent.BANNER,
Expand Down Expand Up @@ -268,7 +310,6 @@ const NoticeOverlay: FunctionComponent<OverlayProps> = ({
isEmbedded,
isOpen,
onClose,
onSave,
onManagePreferencesClick,
}) => {
const isAcknowledge =
Expand All @@ -290,12 +331,20 @@ const NoticeOverlay: FunctionComponent<OverlayProps> = ({
experience={experience}
onManagePreferencesClick={onManagePreferencesClick}
enabledKeys={draftEnabledNoticeKeys}
onAcceptAll={() => {
handleAcceptAll();
onClose();
}}
onRejectAll={() => {
handleRejectAll();
onClose();
}}
onSave={(
consentMethod: ConsentMethod,
keys: Array<PrivacyNotice["notice_key"]>,
) => {
handleUpdatePreferences(consentMethod, keys);
onSave();
onClose();
}}
isAcknowledge={isAcknowledge}
hideOptInOut={isAcknowledge}
Expand Down Expand Up @@ -323,6 +372,14 @@ const NoticeOverlay: FunctionComponent<OverlayProps> = ({
<NoticeConsentButtons
experience={experience}
enabledKeys={draftEnabledNoticeKeys}
onAcceptAll={() => {
handleAcceptAll();
onClose();
}}
onRejectAll={() => {
handleRejectAll();
onClose();
}}
onSave={(
consentMethod: ConsentMethod,
keys: Array<PrivacyNotice["notice_key"]>,
Expand Down
79 changes: 6 additions & 73 deletions clients/fides-js/src/components/tcf/TcfConsentButtons.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,27 @@
import { h, VNode } from "preact";

import {
ConsentMethod,
FidesInitOptions,
PrivacyExperience,
PrivacyExperienceMinimal,
} from "../../lib/consent-types";
import type { EnabledIds, TcfModels } from "../../lib/tcf/types";
import { ConsentButtons } from "../ConsentButtons";

interface TcfConsentButtonProps {
experience: PrivacyExperience | PrivacyExperienceMinimal;
options: FidesInitOptions;
onManagePreferencesClick?: () => void;
onSave: (consentMethod: ConsentMethod, keys: EnabledIds) => void;
onRejectAll: () => void;
onAcceptAll: () => void;
renderFirstButton?: () => VNode;
isInModal?: boolean;
}

const getAllIds = (modelList: TcfModels) => {
if (!modelList) {
return [];
}
return modelList.map((m) => `${m.id}`);
};

export const TcfConsentButtons = ({
experience,
onManagePreferencesClick,
onSave,
onRejectAll,
onAcceptAll,
renderFirstButton,
isInModal,
options,
Expand All @@ -39,72 +32,12 @@ export const TcfConsentButtons = ({

const isGVLLoading = Object.keys(experience.gvl || {}).length === 0;

const handleAcceptAll = () => {
let allIds: EnabledIds;
if (!experience.minimal_tcf) {
// eslint-disable-next-line no-param-reassign
experience = experience as PrivacyExperience;
allIds = {
purposesConsent: getAllIds(experience.tcf_purpose_consents),
purposesLegint: getAllIds(experience.tcf_purpose_legitimate_interests),
specialPurposes: getAllIds(experience.tcf_special_purposes),
features: getAllIds(experience.tcf_features),
specialFeatures: getAllIds(experience.tcf_special_features),
vendorsConsent: getAllIds([
...(experience.tcf_vendor_consents || []),
...(experience.tcf_system_consents || []),
]),
vendorsLegint: getAllIds([
...(experience.tcf_vendor_legitimate_interests || []),
...(experience.tcf_system_legitimate_interests || []),
]),
};
} else {
// eslint-disable-next-line no-param-reassign
experience = experience as PrivacyExperienceMinimal;
allIds = {
purposesConsent:
experience.tcf_purpose_consent_ids?.map((id) => `${id}`) || [],
purposesLegint:
experience.tcf_purpose_legitimate_interest_ids?.map(
(id) => `${id}`,
) || [],
specialPurposes:
experience.tcf_special_purpose_ids?.map((id) => `${id}`) || [],
features: experience.tcf_feature_ids?.map((id) => `${id}`) || [],
specialFeatures:
experience.tcf_special_feature_ids?.map((id) => `${id}`) || [],
vendorsConsent: [
...(experience.tcf_vendor_consent_ids || []),
...(experience.tcf_system_consent_ids || []),
],
vendorsLegint: [
...(experience.tcf_vendor_legitimate_interest_ids || []),
...(experience.tcf_system_legitimate_interest_ids || []),
],
};
}
onSave(ConsentMethod.ACCEPT, allIds);
};
const handleRejectAll = () => {
const emptyIds: EnabledIds = {
purposesConsent: [],
purposesLegint: [],
specialPurposes: [],
features: [],
specialFeatures: [],
vendorsConsent: [],
vendorsLegint: [],
};
onSave(ConsentMethod.REJECT, emptyIds);
};

return (
<ConsentButtons
availableLocales={experience.available_locales}
onManagePreferencesClick={onManagePreferencesClick}
onAcceptAll={handleAcceptAll}
onRejectAll={handleRejectAll}
onAcceptAll={onAcceptAll}
onRejectAll={onRejectAll}
renderFirstButton={renderFirstButton}
isInModal={isInModal}
options={options}
Expand Down
Loading

0 comments on commit 8723d84

Please sign in to comment.