diff --git a/.fides/db_dataset.yml b/.fides/db_dataset.yml index 001fabf84a..a73b4c3261 100644 --- a/.fides/db_dataset.yml +++ b/.fides/db_dataset.yml @@ -2240,4 +2240,41 @@ dataset: description: 'The name of the organization this Fides deployment belongs to' data_categories: - user.workplace + data_qualifier: aggregated.anonymized.unlinked_pseudonymized.pseudonymized.identified + - name: cookies + description: 'Fides Generated Description for Table: cookies' + data_categories: [] + data_qualifier: aggregated.anonymized.unlinked_pseudonymized.pseudonymized.identified + fields: + - name: created_at + data_categories: + - system.operations + data_qualifier: aggregated.anonymized.unlinked_pseudonymized.pseudonymized.identified + - name: domain + data_categories: + - system.operations + data_qualifier: aggregated.anonymized.unlinked_pseudonymized.pseudonymized.identified + - name: id + data_categories: + - system.operations + data_qualifier: aggregated.anonymized.unlinked_pseudonymized.pseudonymized.identified + - name: name + data_categories: + - system.operations + data_qualifier: aggregated.anonymized.unlinked_pseudonymized.pseudonymized.identified + - name: path + data_categories: + - system.operations + data_qualifier: aggregated.anonymized.unlinked_pseudonymized.pseudonymized.identified + - name: privacy_declaration_id + data_categories: + - system.operations + data_qualifier: aggregated.anonymized.unlinked_pseudonymized.pseudonymized.identified + - name: system_id + data_categories: + - system.operations + data_qualifier: aggregated.anonymized.unlinked_pseudonymized.pseudonymized.identified + - name: updated_at + data_categories: + - system.operations data_qualifier: aggregated.anonymized.unlinked_pseudonymized.pseudonymized.identified \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index c5d51be76e..40729f8683 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,13 @@ The types of changes are: - `Fixed` for any bug fixes. - `Security` in case of vulnerabilities. -## [Unreleased](https://github.com/ethyca/fides/compare/2.15.0...main) +## [Unreleased](https://github.com/ethyca/fides/compare/2.15.1...main) + +## [2.15.1](https://github.com/ethyca/fides/compare/2.15.0...2.15.1) + +### Changed +- Privacy center action cards are now able to expand to accommodate longer text [#3669](https://github.com/ethyca/fides/pull/3669) +- Allow Privacy Notices banner and modal to scroll as needed [#3713](https://github.com/ethyca/fides/pull/3713) ## [2.15.0](https://github.com/ethyca/fides/compare/2.14.1...2.15.0) @@ -44,6 +50,9 @@ The types of changes are: - HTML format for privacy request storage destinations [#3427](https://github.com/ethyca/fides/pull/3427) - Persistent message showing result and timestamp of last integration test to "Integrations" tab in system view [#3628](https://github.com/ethyca/fides/pull/3628) - Access and erasure support for SurveyMonkey [#3590](https://github.com/ethyca/fides/pull/3590) +- New Cookies Table for storing cookies associated with systems and privacy declarations [#3572](https://github.com/ethyca/fides/pull/3572) +- `fides-js` and privacy center now delete cookies associated with notices that were opted out of [#3569](https://github.com/ethyca/fides/pull/3569) +- Cookie input field on system data use tab [#3571](https://github.com/ethyca/fides/pull/3571) ### Fixed @@ -66,6 +75,10 @@ The types of changes are: - Update to latest asyncpg dependency to avoid build error [#3614](https://github.com/ethyca/fides/pull/3614) - Fix bug where editing a data use on a system could delete existing data uses [#3627](https://github.com/ethyca/fides/pull/3627) - Restrict Privacy Center debug logging to development-only [#3638](https://github.com/ethyca/fides/pull/3638) +- Fix bug where linking an integration would not update the tab when creating a new system [#3662](https://github.com/ethyca/fides/pull/3662) +- Fix dataset yaml not properly reflecting the dataset in the dropdown of system integrations tab [#3666](https://github.com/ethyca/fides/pull/3666) +- Fix privacy notices not being able to be edited via the UI after the addition of the `cookies` field [#3670](https://github.com/ethyca/fides/pull/3670) +- Add a transform in the case of `null` name fields in privacy declarations for the data use forms [#3683](https://github.com/ethyca/fides/pull/3683) ### Changed @@ -198,7 +211,7 @@ The types of changes are: ### Developer Experience -- Use prettier to format *all* source files in client packages [#3240](https://github.com/ethyca/fides/pull/3240) +- Use prettier to format _all_ source files in client packages [#3240](https://github.com/ethyca/fides/pull/3240) ### Deprecated diff --git a/clients/admin-ui/cypress/e2e/privacy-notices.cy.ts b/clients/admin-ui/cypress/e2e/privacy-notices.cy.ts index 15af445a26..8f3123e844 100644 --- a/clients/admin-ui/cypress/e2e/privacy-notices.cy.ts +++ b/clients/admin-ui/cypress/e2e/privacy-notices.cy.ts @@ -227,23 +227,41 @@ describe("Privacy notices", () => { }); it("can make an edit", () => { - cy.visit(`${PRIVACY_NOTICES_ROUTE}/${ESSENTIAL_NOTICE_ID}`); - cy.wait("@getNoticeDetail"); - const newName = "new name"; - cy.getByTestId("input-name").clear().type(newName); - // should not reflect the new name since this is the edit form - cy.getByTestId("input-notice_key").should("have.value", "essential"); - // but we can still update it - const newKey = "custom_key"; - cy.getByTestId("input-notice_key").clear().type(newKey); - - cy.getByTestId("save-btn").click(); - cy.wait("@patchNotices").then((interception) => { - const { body } = interception.request; - expect(body[0].name).to.eql(newName); - expect(body[0].notice_key).to.eql(newKey); + cy.fixture("privacy-notices/notice.json").then((notice) => { + cy.visit(`${PRIVACY_NOTICES_ROUTE}/${ESSENTIAL_NOTICE_ID}`); + cy.wait("@getNoticeDetail"); + const newName = "new name"; + cy.getByTestId("input-name").clear().type(newName); + // should not reflect the new name since this is the edit form + cy.getByTestId("input-notice_key").should("have.value", "essential"); + // but we can still update it + const newKey = "custom_key"; + cy.getByTestId("input-notice_key").clear().type(newKey); + + cy.getByTestId("save-btn").click(); + cy.wait("@patchNotices").then((interception) => { + const { body } = interception.request; + const expected = { + name: newName, + notice_key: newKey, + consent_mechanism: notice.consent_mechanism, + data_uses: notice.data_uses, + description: notice.description, + disabled: notice.disabled, + displayed_in_api: notice.displayed_in_api, + displayed_in_overlay: notice.displayed_in_overlay, + displayed_in_privacy_center: notice.displayed_in_privacy_center, + enforcement_level: notice.enforcement_level, + has_gpc_flag: notice.has_gpc_flag, + id: notice.id, + internal_description: notice.internal_description, + origin: notice.origin, + regions: notice.regions, + }; + expect(body[0]).to.eql(expected); + }); + cy.wait("@getNoticeDetail"); }); - cy.wait("@getNoticeDetail"); }); }); diff --git a/clients/admin-ui/cypress/e2e/systems.cy.ts b/clients/admin-ui/cypress/e2e/systems.cy.ts index 7974b0ceab..a3f9c03e1d 100644 --- a/clients/admin-ui/cypress/e2e/systems.cy.ts +++ b/clients/admin-ui/cypress/e2e/systems.cy.ts @@ -111,6 +111,9 @@ describe("System management page", () => { it("Can step through the flow", () => { cy.fixture("systems/system.json").then((system) => { + cy.intercept("GET", "/api/v1/system/*", { + body: { ...system, privacy_declarations: [] }, + }).as("getDemoSystem"); // Fill in the describe form based on fixture data cy.visit(ADD_SYSTEMS_ROUTE); cy.getByTestId("manual-btn").click(); @@ -145,6 +148,7 @@ describe("System management page", () => { "@getDataSubjects", "@getDataUses", "@getFilteredDatasets", + "@getDemoSystem", ]); cy.getByTestId("new-declaration-form"); const declaration = system.privacy_declarations[0]; @@ -172,38 +176,49 @@ describe("System management page", () => { data_categories: declaration.data_categories, data_subjects: declaration.data_subjects, dataset_references: ["demo_users_dataset_2"], + cookies: [], + id: "", }); }); }); }); it("can render a warning when there is unsaved data", () => { - cy.visit(ADD_SYSTEMS_MANUAL_ROUTE); - cy.wait("@getSystems"); - cy.wait("@getConnectionTypes"); - cy.getByTestId("create-system-btn").click(); - cy.getByTestId("input-name").type("test"); - cy.getByTestId("input-fides_key").type("test"); - cy.getByTestId("save-btn").click(); - cy.wait("@postSystem"); + cy.fixture("systems/system.json").then((system) => { + cy.intercept("GET", "/api/v1/system/*", { + body: { ...system, privacy_declarations: [] }, + }).as("getDemoSystem"); + cy.visit(ADD_SYSTEMS_MANUAL_ROUTE); + cy.wait("@getSystems"); + cy.wait("@getConnectionTypes"); + cy.getByTestId("create-system-btn").click(); + cy.getByTestId("input-name").type(system.name); + cy.getByTestId("input-fides_key").type(system.fides_key); + cy.getByTestId("input-description").type(system.description); + cy.getByTestId("save-btn").click(); + cy.wait("@postSystem"); - // start typing a description - const description = "half formed thought"; - cy.getByTestId("input-description").type(description); - // then try navigating to the privacy declarations tab - cy.getByTestId("tab-Data uses").click(); - cy.getByTestId("confirmation-modal"); - // make sure canceling works - cy.getByTestId("cancel-btn").click(); - cy.getByTestId("input-description").should("have.value", description); - // now actually discard - cy.getByTestId("tab-Data uses").click(); - cy.getByTestId("continue-btn").click(); - // should load the privacy declarations page - cy.getByTestId("privacy-declaration-step"); - // navigate back - cy.getByTestId("tab-System information").click(); - cy.getByTestId("input-description").should("have.value", ""); + // start typing a description + const description = "half formed thought"; + cy.getByTestId("input-description").clear().type(description); + // then try navigating to the privacy declarations tab + cy.getByTestId("tab-Data uses").click(); + cy.getByTestId("confirmation-modal"); + // make sure canceling works + cy.getByTestId("cancel-btn").click(); + cy.getByTestId("input-description").should("have.value", description); + // now actually discard + cy.getByTestId("tab-Data uses").click(); + cy.getByTestId("continue-btn").click(); + // should load the privacy declarations page + cy.getByTestId("privacy-declaration-step"); + // navigate back and make sure description has the original description + cy.getByTestId("tab-System information").click(); + cy.getByTestId("input-description").should( + "have.value", + system.description + ); + }); }); }); }); @@ -309,6 +324,7 @@ describe("System management page", () => { const { body } = interception.request; expect(body.joint_controller.name).to.eql(controllerName); }); + cy.wait("@getFidesctlSystem"); // Switch to the Data Uses tab cy.getByTestId("tab-Data uses").click(); @@ -334,15 +350,15 @@ describe("System management page", () => { // edit the existing declaration cy.getByTestId("accordion-header-improve.system").click(); cy.getByTestId("improve.system-form").within(() => { - cy.getByTestId("input-data_subjects").type(`anonymous{enter}`); + cy.getByTestId("input-data_subjects").type(`customer{enter}`); cy.getByTestId("save-btn").click(); }); cy.wait("@putSystem").then((interception) => { const { body } = interception.request; expect(body.privacy_declarations.length).to.eql(1); expect(body.privacy_declarations[0].data_subjects).to.eql([ - "customer", "anonymous_user", + "customer", ]); }); cy.getByTestId("saved-indicator"); diff --git a/clients/admin-ui/cypress/fixtures/systems/system.json b/clients/admin-ui/cypress/fixtures/systems/system.json index 5929eb18dd..09e930e287 100644 --- a/clients/admin-ui/cypress/fixtures/systems/system.json +++ b/clients/admin-ui/cypress/fixtures/systems/system.json @@ -16,7 +16,9 @@ "data_use": "improve.system", "data_qualifier": "aggregated.anonymized.unlinked_pseudonymized.pseudonymized.identified", "data_subjects": ["customer"], - "dataset_references": ["demo_users_dataset"] + "dataset_references": ["demo_users_dataset"], + "cookies": [], + "id": "pri_ac9d4dfb-d033-4b06-bc7f-968df8d125ff" } ], "joint_controller": { "name": "Sally Controller" }, diff --git a/clients/admin-ui/cypress/fixtures/systems/systems.json b/clients/admin-ui/cypress/fixtures/systems/systems.json index a73c0d419f..6e9e6aa264 100644 --- a/clients/admin-ui/cypress/fixtures/systems/systems.json +++ b/clients/admin-ui/cypress/fixtures/systems/systems.json @@ -17,7 +17,9 @@ "data_use": "improve.system", "data_qualifier": "aggregated.anonymized.unlinked_pseudonymized.pseudonymized.identified", "data_subjects": ["anonymous_user"], - "dataset_references": ["public"] + "dataset_references": ["public"], + "cookies": [], + "id": "pri_ac9d4dfb-d033-4b06-bc7f-968df8d125ff" } ], "joint_controller": null, @@ -59,7 +61,9 @@ "data_subjects": ["customer"], "dataset_references": ["demo_users_dataset"], "egress": null, - "ingress": null + "ingress": null, + "cookies": [], + "id": "pri_ac9d4dfb-d033-4b06-bc7f-968df8d125ff" } ], "joint_controller": null, @@ -99,7 +103,9 @@ "data_subjects": ["customer"], "dataset_references": null, "egress": null, - "ingress": null + "ingress": null, + "cookies": [], + "id": "pri_06430a1c-1365-422e-90a7-d444ddb32181" } ], "joint_controller": null, diff --git a/clients/admin-ui/cypress/fixtures/systems/systems_with_data_uses.json b/clients/admin-ui/cypress/fixtures/systems/systems_with_data_uses.json index 533a20f7d9..37c89489c3 100644 --- a/clients/admin-ui/cypress/fixtures/systems/systems_with_data_uses.json +++ b/clients/admin-ui/cypress/fixtures/systems/systems_with_data_uses.json @@ -17,7 +17,9 @@ "data_use": "improve.system", "data_qualifier": "aggregated.anonymized.unlinked_pseudonymized.pseudonymized.identified", "data_subjects": ["anonymous_user"], - "dataset_references": ["public"] + "dataset_references": ["public"], + "cookies": [], + "id": "pri_ac9d4dfb-d033-4b06-bc7f-968df8d125ff" }, { "name": "Collect data for marketing", @@ -27,7 +29,9 @@ "data_subjects": ["customer"], "dataset_references": null, "egress": null, - "ingress": null + "ingress": null, + "cookies": [], + "id": "pri_bc6e6efe-f122-3e33-ac9a-732ae8b437bb" } ], "joint_controller": null, diff --git a/clients/admin-ui/src/features/common/form/inputs.tsx b/clients/admin-ui/src/features/common/form/inputs.tsx index d242550648..7f6de443f1 100644 --- a/clients/admin-ui/src/features/common/form/inputs.tsx +++ b/clients/admin-ui/src/features/common/form/inputs.tsx @@ -316,21 +316,26 @@ const CreatableSelectInput = ({ size={size} classNamePrefix="custom-creatable-select" chakraStyles={{ - container: (provided) => ({ ...provided, flexGrow: 1 }), + container: (provided) => ({ + ...provided, + flexGrow: 1, + backgroundColor: "white", + }), dropdownIndicator: (provided) => ({ ...provided, - background: "white", + bg: "transparent", + px: 2, + cursor: "inherit", + }), + indicatorSeparator: (provided) => ({ + ...provided, + display: "none", }), multiValue: (provided) => ({ ...provided, background: "primary.400", color: "white", }), - multiValueRemove: (provided) => ({ - ...provided, - display: "none", - visibility: "hidden", - }), }} components={components} isSearchable={isSearchable} diff --git a/clients/admin-ui/src/features/datastore-connections/system_portal_config/forms/ConnectorParametersForm.tsx b/clients/admin-ui/src/features/datastore-connections/system_portal_config/forms/ConnectorParametersForm.tsx index db35b8d5be..84bf04d062 100644 --- a/clients/admin-ui/src/features/datastore-connections/system_portal_config/forms/ConnectorParametersForm.tsx +++ b/clients/admin-ui/src/features/datastore-connections/system_portal_config/forms/ConnectorParametersForm.tsx @@ -382,7 +382,10 @@ const ConnectorParametersForm: React.FC = ({ : null} {SystemType.DATABASE === connectionOption.type && !isCreatingConnectionConfig ? ( - + ) : null}