From ddc755d460d41bfc700e3f66e5bdbfb16f21f7be Mon Sep 17 00:00:00 2001 From: Kelsey Thomas <101993653+Kelsey-Ethyca@users.noreply.github.com> Date: Wed, 8 Nov 2023 17:21:33 -0500 Subject: [PATCH 1/7] empty commit to start release 2.24.0 From c9a465d790fb15756a739f2979aceb6c0ae6c0c4 Mon Sep 17 00:00:00 2001 From: jpople Date: Thu, 9 Nov 2023 12:53:51 -0500 Subject: [PATCH 2/7] Disable editing fields for GVL vendors (#4327) --- CHANGELOG.md | 29 ++++- .../admin-ui/cypress/e2e/systems-plus.cy.ts | 5 + .../admin-ui/src/features/plus/plus.slice.ts | 1 + .../src/features/system/GVLNotice.tsx | 28 +++++ .../src/features/system/SystemFormTabs.tsx | 6 + .../features/system/SystemInformationForm.tsx | 104 ++++++++++++++++-- .../src/features/system/VendorSelector.tsx | 4 +- .../dictionary-form/DictSuggestionInputs.tsx | 6 + .../dictionary-form/dict-suggestion.slice.ts | 12 +- .../PrivacyDeclarationDisplayGroup.tsx | 54 +++++---- .../PrivacyDeclarationForm.tsx | 53 +++++++-- .../admin-ui/src/pages/add-systems/manual.tsx | 6 + .../src/pages/systems/configure/[id].tsx | 24 +++- 13 files changed, 278 insertions(+), 54 deletions(-) create mode 100644 clients/admin-ui/src/features/system/GVLNotice.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index eeb6914383..692b26cd55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,10 @@ The types of changes are: - Erasure support for Ada Chatbot [#4382](https://github.com/ethyca/fides/pull/4382) - Erasure support for Typeform [#4366](https://github.com/ethyca/fides/pull/4366) +## Added + +- Added notice that a system is GVL when adding/editing from system form [#4327](https://github.com/ethyca/fides/pull/4327) + ### Changed - Add filtering and pagination to bulk vendor add table [#4351](https://github.com/ethyca/fides/pull/4351) - Determine if the TCF overlay needs to surface based on backend calculated version hash [#4356](https://github.com/ethyca/fides/pull/4356) @@ -62,6 +66,7 @@ The types of changes are: - Updated double toggle styling in favor of single toggles with a radio group to select legal basis [#4376](https://github.com/ethyca/fides/pull/4376) ### Fixed + - Handle invalid `fides_string` when passed in as an override [#4350](https://github.com/ethyca/fides/pull/4350) - Bug where vendor opt-ins would not initialize properly based on a `fides_string` in the TCF overlay [#4368](https://github.com/ethyca/fides/pull/4368) @@ -97,6 +102,7 @@ The types of changes are: - Removes overflow styling for embedded modal in Fides.js [#4345](https://github.com/ethyca/fides/pull/4345) ### Changed + - Derive cookie storage info, privacy policy and legitimate interest disclosure URLs, and data retention data from the data map instead of directly from gvl.json [#4286](https://github.com/ethyca/fides/pull/4286) - Updated TCF Version for backend consent reporting [#4305](https://github.com/ethyca/fides/pull/4305) - Update Version Hash Contents [#4313](https://github.com/ethyca/fides/pull/4313) @@ -106,9 +112,11 @@ The types of changes are: ## [2.22.1](https://github.com/ethyca/fides/compare/2.22.0...2.22.1) ### Added + - Custom fields are now included in system history change tracking [#4294](https://github.com/ethyca/fides/pull/4294) ### Security + - Added hostname checks for external SaaS connector URLs [CVE-2023-46124](https://github.com/ethyca/fides/security/advisories/GHSA-jq3w-9mgf-43m4) - Use a Pydantic URL type for privacy policy URLs [CVE-2023-46126](https://github.com/ethyca/fides/security/advisories/GHSA-fgjj-5jmr-gh83) - Remove the CONFIG_READ scope from the Viewer role [CVE-2023-46125](https://github.com/ethyca/fides/security/advisories/GHSA-rjxg-rpg3-9r89) @@ -116,6 +124,7 @@ The types of changes are: ## [2.22.0](https://github.com/ethyca/fides/compare/2.21.0...2.22.0) ### Added + - Added an option to link to vendor tab from an experience config description [#4191](https://github.com/ethyca/fides/pull/4191) - Added two toggles for vendors in the TCF overlay, one for Consent, and one for Legitimate Interest [#4189](https://github.com/ethyca/fides/pull/4189) - Added two toggles for purposes in the TCF overlay, one for Consent, and one for Legitimate Interest [#4234](https://github.com/ethyca/fides/pull/4234) @@ -124,6 +133,7 @@ The types of changes are: - Support for `gvl` prefixed vendor IDs [#4247](https://github.com/ethyca/fides/pull/4247) ### Changed + - Removed `TCF_ENABLED` environment variable from the privacy center in favor of dynamically figuring out which `fides-js` bundle to send [#4131](https://github.com/ethyca/fides/pull/4131) - Updated copy of info boxes on each TCF tab [#4191](https://github.com/ethyca/fides/pull/4191) - Clarified messages for error messages presented during connector upload [#4198](https://github.com/ethyca/fides/pull/4198) @@ -143,6 +153,7 @@ The types of changes are: - Changed naming convention "fides_string" instead of "tc_string" for developer friendly consent API's [#4267](https://github.com/ethyca/fides/pull/4267) ### Fixed + - TCF overlay can initialize its consent preferences from a cookie [#4124](https://github.com/ethyca/fides/pull/4124) - Various improvements to the TCF modal such as vendor storage disclosures, vendor counts, privacy policies, etc. [#4167](https://github.com/ethyca/fides/pull/4167) - An issue where Braze could not mask an email due to formatting [#4187](https://github.com/ethyca/fides/pull/4187) @@ -157,6 +168,7 @@ The types of changes are: ## [2.21.0](https://github.com/ethyca/fides/compare/2.20.2...2.21.0) ### Added + - "Add a vendor" flow to configuring consent page [#4107](https://github.com/ethyca/fides/pull/4107) - Initial TCF Backend Support [#3804](https://github.com/ethyca/fides/pull/3804) - Add initial layer to TCF modal [#3956](https://github.com/ethyca/fides/pull/3956) @@ -174,6 +186,7 @@ The types of changes are: - Added fides.css customization for Plus users [#4136](https://github.com/ethyca/fides/pull/4136) ### Changed + - Added further config options to customize the privacy center [#4090](https://github.com/ethyca/fides/pull/4090) - CORS configuration page [#4073](https://github.com/ethyca/fides/pull/4073) - Refactored `fides.js` components so that they can take data structures that are not necessarily privacy notices [#3870](https://github.com/ethyca/fides/pull/3870) @@ -183,12 +196,14 @@ The types of changes are: - Misc copy changes for the system history table and modal [#4146](https://github.com/ethyca/fides/pull/4146) ### Fixed -- Allows CDN to cache empty experience responses from fides.js API [#4113](https://github.com/ethyca/fides/pull/4113) + +- Allows CDN to cache empty experience responses from fides.js API [#4113](https://github.com/ethyca/fides/pull/4113) - Fixed `identity_special_purpose` unique constraint definition [#4174](https://github.com/ethyca/fides/pull/4174/files) ## [2.20.2](https://github.com/ethyca/fides/compare/2.20.1...2.20.2) ### Fixed + - added version_added, version_deprecated, and replaced_by to data use, data subject, and data category APIs [#4135](https://github.com/ethyca/fides/pull/4135) - Update fides.js to not fetch experience client-side if pre-fetched experience is empty [#4149](https://github.com/ethyca/fides/pull/4149) - Erasure privacy requests now pause for input if there are any manual process integrations [#4115](https://github.com/ethyca/fides/pull/4115) @@ -203,6 +218,7 @@ The types of changes are: ## [2.20.0](https://github.com/ethyca/fides/compare/2.19.1...2.20.0) ### Added + - Initial page for configuring consent [#4069](https://github.com/ethyca/fides/pull/4069) - Vendor cookie table for configuring consent [#4082](https://github.com/ethyca/fides/pull/4082) @@ -239,7 +255,6 @@ The types of changes are: - System history UI with diff modal [#4021](https://github.com/ethyca/fides/pull/4021) - Relax system legal basis for transfers to be any string [#4049](https://github.com/ethyca/fides/pull/4049) - ## [2.19.0](https://github.com/ethyca/fides/compare/2.18.0...2.19.0) ### Added @@ -258,7 +273,7 @@ The types of changes are: - Fixed dataset issue that was preventing the Vend connector from loading during server startup [#3923](https://github.com/ethyca/fides/pull/3923) - Adding version check to version-dependent migration script [#3951](https://github.com/ethyca/fides/pull/3951) - Fixed a bug where some fields were not saving correctly on the system form [#3975](https://github.com/ethyca/fides/pull/3975) -- Changed "retention period" field in privacy declaration form from number input to text input [#3980](https://github.com/ethyca/fides/pull/3980) +- Changed "retention period" field in privacy declaration form from number input to text input [#3980](https://github.com/ethyca/fides/pull/3980) - Fixed issue where unsaved changes modal appears incorrectly [#4005](https://github.com/ethyca/fides/pull/4005) - Fixed banner resurfacing after user consent for pre-fetch experience [#4009](https://github.com/ethyca/fides/pull/4009) @@ -272,6 +287,7 @@ The types of changes are: - Admin ui supports fides cloud config API [#4034](https://github.com/ethyca/fides/pull/4034) ### Security + - Resolve custom integration upload RCE vulnerability [CVE-2023-41319](https://github.com/ethyca/fides/security/advisories/GHSA-p6p2-qq95-vq5h) ## [2.18.0](https://github.com/ethyca/fides/compare/2.17.0...2.18.0) @@ -286,6 +302,7 @@ The types of changes are: - Changes in the `data` directory now trigger a server reload (for local development) [#3874](https://github.com/ethyca/fides/pull/3874) ### Fixed + - Fix datamap zoom for low system counts [#3835](https://github.com/ethyca/fides/pull/3835) - Fixed connector forms with external dataset reference fields [#3873](https://github.com/ethyca/fides/pull/3873) - Fix ability to make server side API calls from privacy-center [#3895](https://github.com/ethyca/fides/pull/3895) @@ -332,6 +349,7 @@ The types of changes are: - Erasure support for Heap [#3599](https://github.com/ethyca/fides/pull/3599) ### Fixed + - Privacy notice UI's list of possible regions now matches the backend's list [#3787](https://github.com/ethyca/fides/pull/3787) - Admin UI "property does not existing" build issue [#3831](https://github.com/ethyca/fides/pull/3831) - Flagging sensitive inputs as passwords to mask values during entry [#3843](https://github.com/ethyca/fides/pull/3843) @@ -376,23 +394,28 @@ The types of changes are: - Enable privacy notice and privacy experience feature flags by default [#3773](https://github.com/ethyca/fides/pull/3773) ### Security + - Resolve Zip bomb file upload vulnerability [CVE-2023-37480](https://github.com/ethyca/fides/security/advisories/GHSA-g95c-2jgm-hqc6) - Resolve SVG bomb (billion laughs) file upload vulnerability [CVE-2023-37481](https://github.com/ethyca/fides/security/advisories/GHSA-3rw2-wfc8-wmj5) ## [2.15.1](https://github.com/ethyca/fides/compare/2.15.0...2.15.1) ### Added + - Set `sslmode` to `prefer` if connecting to Redshift via ssh [#3685](https://github.com/ethyca/fides/pull/3685) ### Changed + - Privacy center action cards are now able to expand to accommodate longer text [#3669](https://github.com/ethyca/fides/pull/3669) - Update integration endpoint permissions [#3707](https://github.com/ethyca/fides/pull/3707) ### Fixed + - Handle names with a double underscore when processing access and erasure requests [#3688](https://github.com/ethyca/fides/pull/3688) - Allow Privacy Notices banner and modal to scroll as needed [#3713](https://github.com/ethyca/fides/pull/3713) ### Security + - Resolve path traversal vulnerability in webserver API [CVE-2023-36827](https://github.com/ethyca/fides/security/advisories/GHSA-r25m-cr6v-p9hq) ## [2.15.0](https://github.com/ethyca/fides/compare/2.14.1...2.15.0) diff --git a/clients/admin-ui/cypress/e2e/systems-plus.cy.ts b/clients/admin-ui/cypress/e2e/systems-plus.cy.ts index 6434a74930..f4591dd41b 100644 --- a/clients/admin-ui/cypress/e2e/systems-plus.cy.ts +++ b/clients/admin-ui/cypress/e2e/systems-plus.cy.ts @@ -55,6 +55,11 @@ describe("System management with Plus features", () => { ); }); + it("locks editing for a GVL vendor when TCF is enabled", () => { + cy.getSelectValueContainer("input-vendor_id").type("Aniview{enter}"); + cy.getByTestId("locked-for-GVL-notice"); + }); + // some DictSuggestionTextInputs don't get populated right, causing // the form to be mistakenly marked as dirty and the "unsaved changes" // modal to pop up incorrectly when switching tabs diff --git a/clients/admin-ui/src/features/plus/plus.slice.ts b/clients/admin-ui/src/features/plus/plus.slice.ts index 4054572e0e..788bd9bf17 100644 --- a/clients/admin-ui/src/features/plus/plus.slice.ts +++ b/clients/admin-ui/src/features/plus/plus.slice.ts @@ -355,6 +355,7 @@ export const { useGetAllDictionaryEntriesQuery, useGetFidesCloudConfigQuery, useGetDictionaryDataUsesQuery, + useLazyGetDictionaryDataUsesQuery, useGetAllSystemVendorsQuery, usePostSystemVendorsMutation, useGetSystemHistoryQuery, diff --git a/clients/admin-ui/src/features/system/GVLNotice.tsx b/clients/admin-ui/src/features/system/GVLNotice.tsx new file mode 100644 index 0000000000..38a57e92ea --- /dev/null +++ b/clients/admin-ui/src/features/system/GVLNotice.tsx @@ -0,0 +1,28 @@ +import { Box, Link } from "@fidesui/react"; + +import EmptyTableState from "~/features/common/table/EmptyTableState"; + +const GVLNotice = () => ( + + + As a result, the system fields are not editable as they come directly + from Fides Compass and the Global Vendor List (GVL). In some cases + where the legal basis has been declared to be flexible, you may update + the legal basis for particular data uses.{" "} + + For more information on the Global Vendor List, click here. + + + } + /> + +); + +export default GVLNotice; diff --git a/clients/admin-ui/src/features/system/SystemFormTabs.tsx b/clients/admin-ui/src/features/system/SystemFormTabs.tsx index ab62b8fcde..efc236e089 100644 --- a/clients/admin-ui/src/features/system/SystemFormTabs.tsx +++ b/clients/admin-ui/src/features/system/SystemFormTabs.tsx @@ -14,6 +14,10 @@ import { import { useSystemOrDatamapRoute } from "~/features/common/hooks/useSystemOrDatamapRoute"; import { DEFAULT_TOAST_PARAMS } from "~/features/common/toast"; import ConnectionForm from "~/features/datastore-connections/system_portal_config/ConnectionForm"; +import { + setLockedForGVL, + setSuggestions, +} from "~/features/system/dictionary-form/dict-suggestion.slice"; import PrivacyDeclarationStep from "~/features/system/privacy-declarations/PrivacyDeclarationStep"; import { SystemResponse } from "~/types/api"; @@ -145,6 +149,8 @@ const SystemFormTabs = ({ */ if (isCreate) { dispatch(setActiveSystem(undefined)); + dispatch(setSuggestions("initial")); + dispatch(setLockedForGVL(false)); } return () => { // on unmount, unset the active system diff --git a/clients/admin-ui/src/features/system/SystemInformationForm.tsx b/clients/admin-ui/src/features/system/SystemInformationForm.tsx index e0a56a144a..7aa8262f3f 100644 --- a/clients/admin-ui/src/features/system/SystemInformationForm.tsx +++ b/clients/admin-ui/src/features/system/SystemInformationForm.tsx @@ -25,13 +25,23 @@ import { CustomSwitch, CustomTextInput, } from "~/features/common/form/inputs"; -import { getErrorMessage, isErrorResult } from "~/features/common/helpers"; +import { + extractVendorSource, + getErrorMessage, + isErrorResult, + VendorSources, +} from "~/features/common/helpers"; import { FormGuard } from "~/features/common/hooks/useIsAnyFormDirty"; import { selectAllDictEntries, useGetAllDictionaryEntriesQuery, + useLazyGetDictionaryDataUsesQuery, } from "~/features/plus/plus.slice"; -import { setSuggestions } from "~/features/system/dictionary-form/dict-suggestion.slice"; +import { + selectLockedForGVL, + setLockedForGVL, + setSuggestions, +} from "~/features/system/dictionary-form/dict-suggestion.slice"; import { DictSuggestionNumberInput, DictSuggestionSelect, @@ -39,6 +49,7 @@ import { DictSuggestionTextArea, DictSuggestionTextInput, } from "~/features/system/dictionary-form/DictSuggestionInputs"; +import { transformDictDataUseToDeclaration } from "~/features/system/dictionary-form/helpers"; import { defaultInitialValues, FormValues, @@ -123,8 +134,10 @@ const SystemInformationForm = ({ useGetAllDictionaryEntriesQuery(undefined, { skip: !features.dictionaryService, }); + const [getDictionaryDataUseTrigger] = useLazyGetDictionaryDataUsesQuery(); const dictionaryOptions = useAppSelector(selectAllDictEntries); + const lockedForGVL = useAppSelector(selectLockedForGVL); const systems = useAppSelector(selectAllSystems); const isEditing = useMemo( @@ -153,7 +166,35 @@ const SystemInformationForm = ({ values: FormValues, formikHelpers: FormikHelpers ) => { - const systemBody = transformFormValuesToSystem(values); + let dictionaryDeclarations; + if (lockedForGVL && values.privacy_declarations.length === 0) { + const dataUseQueryResult = await getDictionaryDataUseTrigger({ + vendor_id: values.vendor_id!, + }); + if (dataUseQueryResult.isError) { + const dataUseErrorMsg = getErrorMessage( + dataUseQueryResult.error, + `A problem occurred while fetching data uses from the GVL for your system. Please try again.` + ); + toast({ status: "error", description: dataUseErrorMsg }); + } else if ( + dataUseQueryResult.data && + dataUseQueryResult.data.items.length > 0 + ) { + dictionaryDeclarations = dataUseQueryResult.data.items.map((dec) => ({ + ...transformDictDataUseToDeclaration(dec), + name: dec.name ?? "", + })); + } + } + + const valuesToSubmit = { + ...values, + privacy_declarations: + dictionaryDeclarations ?? values.privacy_declarations, + }; + + const systemBody = transformFormValuesToSystem(valuesToSubmit); const handleResult = ( result: @@ -191,6 +232,19 @@ const SystemInformationForm = ({ handleResult(result); }; + const handleVendorSelected = (newVendorId: string) => { + console.log("hello from handleVendorSelected"); + if ( + features.tcf && + extractVendorSource(newVendorId) === VendorSources.GVL + ) { + dispatch(setSuggestions("showing")); + dispatch(setLockedForGVL(true)); + } else { + dispatch(setLockedForGVL(false)); + } + }; + const isLoading = updateSystemMutationResult.isLoading || createSystemMutationResult.isLoading || @@ -219,7 +273,10 @@ const SystemInformationForm = ({ {features.dictionaryService ? ( - + ) : null} {passedInSystem?.fides_key && ( @@ -270,26 +330,26 @@ const SystemInformationForm = ({ tooltip="Is there a dataset configured for this system?" isMulti variant="stacked" + isDisabled={lockedForGVL} /> - - @@ -323,6 +384,7 @@ const SystemInformationForm = ({ name="uses_profiling" label="This system performs profiling" tooltip="Does this system perform profiling that could have a legal effect?" + disabled={lockedForGVL} /> @@ -348,6 +411,7 @@ const SystemInformationForm = ({ name="does_international_transfers" label="This system transfers data" tooltip="Does this system transfer data to other countries or international organizations?" + disabled={lockedForGVL} /> @@ -374,6 +439,7 @@ const SystemInformationForm = ({ label="This system requires Data Privacy Assessments" tooltip="Does this system require (DPA/DPIA) assessments?" variant="stacked" + isDisabled={lockedForGVL} /> @@ -438,18 +509,21 @@ const SystemInformationForm = ({ name="privacy_policy" label="Privacy policy URL" tooltip="Where can the privacy policy be located?" + disabled={lockedForGVL} /> {values.fides_key ? ( diff --git a/clients/admin-ui/src/features/system/VendorSelector.tsx b/clients/admin-ui/src/features/system/VendorSelector.tsx index e460d81a67..090686631b 100644 --- a/clients/admin-ui/src/features/system/VendorSelector.tsx +++ b/clients/admin-ui/src/features/system/VendorSelector.tsx @@ -11,9 +11,10 @@ import { DictSuggestionToggle } from "~/features/system/dictionary-form/ToggleDi interface Props { disabled?: boolean; options: DictOption[]; + onVendorSelected: (vendorId: string) => void; } -const VendorSelector = ({ disabled, options }: Props) => { +const VendorSelector = ({ disabled, options, onVendorSelected }: Props) => { const [initialField, meta, { setValue }] = useField({ name: "vendor_id" }); const isInvalid = !!(meta.touched && meta.error); const field = { ...initialField, value: initialField.value ?? "" }; @@ -35,6 +36,7 @@ const VendorSelector = ({ disabled, options }: Props) => { const handleChange = (newValue: SingleValue