Skip to content
Draft
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
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@ Changes can also be flagged with a GitHub label for tracking purposes. The URL o
- https://github.com/ethyca/fides/labels/high-risk: to indicate that a change is a "high-risk" change that could potentially lead to unanticipated regressions or degradations
- https://github.com/ethyca/fides/labels/db-migration: to indicate that a given change includes a DB migration

## [Unreleased](https://github.com/ethyca/fides/compare/2.81.0..main)
## [Unreleased](https://github.com/ethyca/fides/compare/2.81.1..main)

## [2.81.1](https://github.com/ethyca/fides/compare/2.81.0..2.81.1)

### Fixed
- Fixed privacy center cards sharing a policy key routing to the wrong action [#7711](https://github.com/ethyca/fides/pull/7711)

## [2.81.0](https://github.com/ethyca/fides/compare/2.80.1..2.81.0)

Expand Down
4 changes: 4 additions & 0 deletions changelog/7292-add-resurface-behavior.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
type: Added
description: Added resurface_behavior configuration to privacy experience configs to control when consent banners are reshown after user interaction
pr: 7292
labels: ["db-migration"]
4 changes: 4 additions & 0 deletions changelog/7601-bump-tinycss.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
type: Changed
description: Bump tinycss2 from 1.2.1 to >=1.5.0
pr: 7601
labels: []
9 changes: 6 additions & 3 deletions clients/privacy-center/components/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,17 @@ const HomePage: NextPage = () => {

const content: ReactNode[] = [];

config.actions.forEach((action) => {
config.actions.forEach((action, index) => {
content.push(
<PrivacyCard
key={action.policy_key}
// eslint-disable-next-line react/no-array-index-key
key={index}
title={action.title}
iconPath={action.icon_path}
description={action.description}
onClick={() => handlePrivacyRequestOpen(action.policy_key)}
onClick={() =>
handlePrivacyRequestOpen(`${index}:${action.policy_key}`)
}
/>,
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useMessage } from "fidesui";
import { useParams, useRouter } from "next/navigation";
import React, { useEffect, useState } from "react";

import { decodePolicyKey, encodePolicyKey } from "~/common/policy-key";
import { decodePolicyKey } from "~/common/policy-key";
import { useConfig } from "~/features/common/config.slice";
import { useGetIdVerificationConfigQuery } from "~/features/id-verification";
import { PrivacyRequestOption } from "~/types/config";
Expand All @@ -27,11 +27,18 @@ const PrivacyRequestFormPage = ({ actionKey }: PrivacyRequestFormPageProps) => {

const messageApi = useMessage();

const policyKey = decodePolicyKey(actionKey);
const decoded = decodePolicyKey(actionKey);
const colonIndex = decoded.indexOf(":");
const actionIndex =
colonIndex !== -1 ? parseInt(decoded.slice(0, colonIndex), 10) : NaN;
const policyKey = colonIndex !== -1 ? decoded.slice(colonIndex + 1) : decoded;

const action = config.actions.find((a) => a.policy_key === policyKey) as
| PrivacyRequestOption
| undefined;
const selectedAction = (
!Number.isNaN(actionIndex) &&
config.actions[actionIndex]?.policy_key === policyKey
? config.actions[actionIndex]
: config.actions.find((action) => action.policy_key === policyKey)
) as PrivacyRequestOption | undefined;

// Update verification requirement from API
useEffect(() => {
Expand All @@ -43,21 +50,19 @@ const PrivacyRequestFormPage = ({ actionKey }: PrivacyRequestFormPageProps) => {
}, [getIdVerificationConfigQuery]);

useEffect(() => {
if (!action) {
if (!selectedAction) {
messageApi.error(`Invalid action key "${policyKey}" for privacy request`);
router.push(basePath || "/");
}
}, [action, policyKey, messageApi, router, basePath]);
}, [selectedAction, policyKey, messageApi, router, basePath]);

const handleExit = () => {
router.push(basePath || "/");
};

const handleSetCurrentView = (view: string) => {
if (view === "identityVerification") {
router.push(
`${basePath}/privacy-request/${encodePolicyKey(policyKey)}/verify`,
);
router.push(`${basePath}/privacy-request/${actionKey}/verify`);
}
};

Expand All @@ -68,15 +73,13 @@ const PrivacyRequestFormPage = ({ actionKey }: PrivacyRequestFormPageProps) => {
};

const handleSuccessWithoutVerification = () => {
router.push(
`${basePath}/privacy-request/${encodePolicyKey(policyKey)}/success`,
);
router.push(`${basePath}/privacy-request/${actionKey}/success`);
};

return (
<PrivacyRequestForm
onExit={handleExit}
openAction={action}
openAction={selectedAction}
setCurrentView={handleSetCurrentView}
setPrivacyRequestId={handleSetPrivacyRequestId}
isVerificationRequired={isVerificationRequired}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { Flex } from "fidesui";
import { useParams, useRouter } from "next/navigation";
import React, { useEffect, useState } from "react";

import { decodePolicyKey, encodePolicyKey } from "~/common/policy-key";
import { ModalViews, VerificationType } from "~/components/modals/types";

import VerificationForm from "../modals/verification-request/VerificationForm";
Expand All @@ -20,20 +19,16 @@ const VerificationPage = ({ actionKey }: VerificationPageProps) => {
const basePath = propertyPath ? `/${propertyPath}` : "";
const [privacyRequestId, setPrivacyRequestId] = useState<string>("");

const policyKey = decodePolicyKey(actionKey);

useEffect(() => {
if (typeof window !== "undefined") {
const storedId = sessionStorage.getItem("privacyRequestId");
if (storedId) {
setPrivacyRequestId(storedId);
} else {
router.push(
`${basePath}/privacy-request/${encodePolicyKey(policyKey)}`,
);
router.push(`${basePath}/privacy-request/${actionKey}`);
}
}
}, [policyKey, router, basePath]);
}, [actionKey, router, basePath]);

if (!privacyRequestId) {
return null;
Expand All @@ -45,14 +40,12 @@ const VerificationPage = ({ actionKey }: VerificationPageProps) => {

const handleSetCurrentView = (view: string) => {
if (view === "privacyRequest") {
router.push(`${basePath}/privacy-request/${encodePolicyKey(policyKey)}`);
router.push(`${basePath}/privacy-request/${actionKey}`);
}
};

const handleSuccess = () => {
router.push(
`${basePath}/privacy-request/${encodePolicyKey(policyKey)}/success`,
);
router.push(`${basePath}/privacy-request/${actionKey}/success`);
};

return (
Expand Down
4 changes: 2 additions & 2 deletions clients/privacy-center/cypress/support/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ export const TEST_OVERRIDE_WINDOW_PATH = "window.config.overrides";

// URL-safe base64 encoded policy keys used in test URLs.
// These correspond to encodePolicyKey() in common/policy-key.ts.
export const ENCODED_ACCESS_POLICY = "ZGVmYXVsdF9hY2Nlc3NfcG9saWN5"; // default_access_policy
export const ENCODED_ERASURE_POLICY = "ZGVmYXVsdF9lcmFzdXJlX3BvbGljeQ"; // default_erasure_policy
export const ENCODED_ACCESS_POLICY = "MDpkZWZhdWx0X2FjY2Vzc19wb2xpY3k"; // 0:default_access_policy
export const ENCODED_ERASURE_POLICY = "MTpkZWZhdWx0X2VyYXN1cmVfcG9saWN5"; // 1:default_erasure_policy
Loading