Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 2.16.0 #3743

Closed
wants to merge 9 commits into from
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@ The types of changes are:
- `Fixed` for any bug fixes.
- `Security` in case of vulnerabilities.

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

## [2.16.0](https://github.com/ethyca/fides/compare/2.15.1...2.16.0)

### Added

- Empty state for when there are no relevant privacy notices in the privacy center [#3640](https://github.com/ethyca/fides/pull/3640)
- GPC indicators in fides-js banner and modal [#3673](https://github.com/ethyca/fides/pull/3673)
- Include `data_use` and `data_category` metadata in `upload` of access results [#3674](https://github.com/ethyca/fides/pull/3674)
- Add enable/disable toggle to integration tab [#3593] (https://github.com/ethyca/fides/pull/3593)

### Fixed

Expand All @@ -30,12 +33,17 @@ The types of changes are:
- Add Systems Applicable Filter to Privacy Experience List [#3654](https://github.com/ethyca/fides/pull/3654)
- Privacy center and fides-js now pass in `Unescape-Safestr` as a header so that special characters can be rendered properly [#3706](https://github.com/ethyca/fides/pull/3706)
- Fixed ValidationError for saving PrivacyPreferences [#3719](https://github.com/ethyca/fides/pull/3719)
- Fixed issue preventing ConnectionConfigs with duplicate names from saving [#3770](https://github.com/ethyca/fides/pull/3770)
- Fixed creating and editing manual integrations [#3772](https://github.com/ethyca/fides/pull/3772)
- Fix lingering integration artifacts by cascading deletes from System [#3771](https://github.com/ethyca/fides/pull/3771)

### Developer Experience

- Reorganized some `api.api.v1` code to avoid circular dependencies on `quickstart` [#3692](https://github.com/ethyca/fides/pull/3692)
- Treat underscores as special characters in user passwords [#3717](https://github.com/ethyca/fides/pull/3717)
- Allow Privacy Notices banner and modal to scroll as needed [#3713](https://github.com/ethyca/fides/pull/3713)
- Make malicious url test more robust to environmental differences [#3748](https://github.com/ethyca/fides/pull/3748)
- Ignore type checker on click decorators to bypass known issue with `click` version `8.1.4` [#3746](https://github.com/ethyca/fides/pull/3746)

### Changed

Expand All @@ -46,6 +54,7 @@ The types of changes are:
- Update EU PrivacyNoticeRegion codes and allow experience filtering to drop back to country filtering if region not found [#3630](https://github.com/ethyca/fides/pull/3630)
- Fields with default fields are now flagged as required in the front-end [#3694](https://github.com/ethyca/fides/pull/3694)
- In "view systems", system cards can now be clicked and link to that system's `configure/[id]` page [#3734](https://github.com/ethyca/fides/pull/3734)
- Enable privacy notice and privacy experience feature flags by default [#3773](https://github.com/ethyca/fides/pull/3773)


## [2.15.1](https://github.com/ethyca/fides/compare/2.15.0...2.15.1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ const ConnectionMenu: React.FC<ConnectionMenuProps> = ({
connection_type={connection_type}
access_type={access_type}
name={name}
isSwitch={false}
/>
<DeleteConnectionModal connection_key={connection_key} />
</MenuList>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import {
ModalFooter,
ModalHeader,
ModalOverlay,
Spacer,
Stack,
Switch,
Text,
useDisclosure,
} from "@fidesui/react";
Expand All @@ -25,6 +27,7 @@ type DataConnectionProps = {
name: string;
access_type: AccessLevel;
connection_type: ConnectionType;
isSwitch: boolean;
};

const DisableConnectionModal: React.FC<DataConnectionProps> = ({
Expand All @@ -33,20 +36,22 @@ const DisableConnectionModal: React.FC<DataConnectionProps> = ({
name,
access_type,
connection_type,
isSwitch,
}) => {
const { isOpen, onOpen, onClose } = useDisclosure();
const [patchConnection, patchConnectionResult] =
usePatchDatastoreConnectionsMutation();

const handleDisableConnection = async () => {
const shouldDisable = !disabled;
patchConnection({
await patchConnection({
key: connection_key,
name,
disabled: shouldDisable,
access: access_type,
connection_type,
});
onClose();
};

const closeIfComplete = () => {
Expand All @@ -57,12 +62,24 @@ const DisableConnectionModal: React.FC<DataConnectionProps> = ({

return (
<>
<MenuItem
_focus={{ color: "complimentary.500", bg: "gray.100" }}
onClick={onOpen}
>
<Text fontSize="sm">{disabled ? "Enable" : "Disable"}</Text>
</MenuItem>
{isSwitch ? (
<>
<Spacer />
<Text fontSize="md">{disabled ? "Enable" : "Disable"}</Text>
<Switch
colorScheme="complimentary"
isChecked={!disabled}
onChange={onOpen}
/>
</>
) : (
<MenuItem
_focus={{ color: "complimentary.500", bg: "gray.100" }}
onClick={onOpen}
>
<Text fontSize="sm">{disabled ? "Enable" : "Disable"}</Text>
</MenuItem>
)}
<Modal isCentered isOpen={isOpen} onClose={closeIfComplete}>
<ModalOverlay />
<ModalContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ export const datastoreConnectionApi = baseApi.injectEndpoints({
method: "PATCH",
body: [{ key, name, disabled, connection_type, access }],
}),
invalidatesTags: () => ["Datastore Connection", "Datasets"],
invalidatesTags: () => ["Datastore Connection", "Datasets", "System"],
}),
updateDatastoreConnectionSecrets: build.mutation<
DatastoreConnectionSecretsResponse,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ export const patchConnectionConfig = async (
patchFunc: any
) => {
const key =
[SystemType.DATABASE, SystemType.EMAIL].indexOf(connectionOption.type) > -1
[SystemType.DATABASE, SystemType.EMAIL, SystemType.MANUAL].indexOf(
connectionOption.type
) > -1
? formatKey(values.instance_key as string)
: connectionConfig?.key;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { Field, FieldInputProps, Form, Formik, FormikProps } from "formik";
import React from "react";
import { DatastoreConnectionStatus } from "src/features/datastore-connections/types";

import DisableConnectionModal from "~/features/datastore-connections/DisableConnectionModal";
import DatasetConfigField from "~/features/datastore-connections/system_portal_config/forms/fields/DatasetConfigField/DatasetConfigField";
import {
ConnectionConfigurationResponse,
Expand Down Expand Up @@ -249,6 +250,8 @@ const ConnectorParametersForm: React.FC<ConnectorParametersFormProps> = ({
onTestConnectionClick(result);
};

const isDisabledConnection = connectionConfig?.disabled || false;

return (
<Formik
enableReinitialize
Expand All @@ -262,54 +265,52 @@ const ConnectorParametersForm: React.FC<ConnectorParametersFormProps> = ({
<Form noValidate>
<VStack align="stretch" gap="16px">
{/* Connection Identifier */}
{connectionOption.type !== SystemType.MANUAL ? (
<Field
id="instance_key"
name="instance_key"
validate={validateConnectionIdentifier}
>
{({ field }: { field: FieldInputProps<string> }) => (
<FormControl
display="flex"
isRequired
isInvalid={
props.errors.instance_key && props.touched.instance_key
}
<Field
id="instance_key"
name="instance_key"
validate={validateConnectionIdentifier}
>
{({ field }: { field: FieldInputProps<string> }) => (
<FormControl
display="flex"
isRequired
isInvalid={
props.errors.instance_key && props.touched.instance_key
}
>
{getFormLabel("instance_key", "Integration Identifier")}
<VStack align="flex-start" w="inherit">
<Input
{...field}
autoComplete="off"
color="gray.700"
isDisabled={!!connectionConfig?.key}
placeholder={`A unique identifier for your new ${
connectionOption!.human_readable
} integration`}
size="sm"
/>
<FormErrorMessage>
{props.errors.instance_key}
</FormErrorMessage>
</VStack>
<Tooltip
aria-label="The fides_key will allow fidesops to associate dataset field references appropriately. Must be a unique alphanumeric value with no spaces (underscores allowed) to represent this integration."
hasArrow
label="The fides_key will allow fidesops to associate dataset field references appropriately. Must be a unique alphanumeric value with no spaces (underscores allowed) to represent this integration."
placement="right-start"
openDelay={500}
>
{getFormLabel("instance_key", "Integration Identifier")}
<VStack align="flex-start" w="inherit">
<Input
{...field}
autoComplete="off"
color="gray.700"
isDisabled={!!connectionConfig?.key}
placeholder={`A unique identifier for your new ${
connectionOption!.human_readable
} integration`}
size="sm"
<Flex alignItems="center" h="32px">
<CircleHelpIcon
marginLeft="8px"
_hover={{ cursor: "pointer" }}
/>
<FormErrorMessage>
{props.errors.instance_key}
</FormErrorMessage>
</VStack>
<Tooltip
aria-label="The fides_key will allow fidesops to associate dataset field references appropriately. Must be a unique alphanumeric value with no spaces (underscores allowed) to represent this integration."
hasArrow
label="The fides_key will allow fidesops to associate dataset field references appropriately. Must be a unique alphanumeric value with no spaces (underscores allowed) to represent this integration."
placement="right-start"
openDelay={500}
>
<Flex alignItems="center" h="32px">
<CircleHelpIcon
marginLeft="8px"
_hover={{ cursor: "pointer" }}
/>
</Flex>
</Tooltip>
</FormControl>
)}
</Field>
) : null}
</Flex>
</Tooltip>
</FormControl>
)}
</Field>
{/* Dynamic connector secret fields */}

{connectionOption.type !== SystemType.MANUAL && secretsSchema
Expand Down Expand Up @@ -343,8 +344,7 @@ const ConnectorParametersForm: React.FC<ConnectorParametersFormProps> = ({
>
{testButtonLabel}
</Button>
{connectionOption.type === SystemType.MANUAL &&
connectionConfig ? (
{connectionOption.type === SystemType.MANUAL ? (
<DSRCustomizationModal connectionConfig={connectionConfig} />
) : null}
<Button
Expand All @@ -361,6 +361,16 @@ const ConnectorParametersForm: React.FC<ConnectorParametersFormProps> = ({
>
Save
</Button>
{connectionConfig ? (
<DisableConnectionModal
connection_key={connectionConfig?.key}
disabled={isDisabledConnection}
connection_type={connectionConfig?.connection_type}
access_type={connectionConfig?.access}
name={connectionConfig?.name}
isSwitch
/>
) : null}
{connectionConfig ? (
<DeleteConnectionModal
connectionKey={connectionConfig.key}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
ModalHeader,
ModalOverlay,
Spinner,
Tooltip,
useDisclosure,
VStack,
} from "@fidesui/react";
Expand All @@ -30,7 +31,7 @@ import DSRCustomizationForm from "./DSRCustomizationForm";
import { Field } from "./types";

type Props = {
connectionConfig: ConnectionConfigurationResponse;
connectionConfig?: ConnectionConfigurationResponse;
};

const DSRCustomizationModal: React.FC<Props> = ({ connectionConfig }) => {
Expand All @@ -43,7 +44,9 @@ const DSRCustomizationModal: React.FC<Props> = ({ connectionConfig }) => {
const { isOpen, onOpen, onClose } = useDisclosure();

const { data, isFetching, isLoading, isSuccess } =
useGetAccessManualHookQuery(connectionConfig.key);
useGetAccessManualHookQuery(connectionConfig ? connectionConfig.key : "", {
skip: !connectionConfig,
});

const [createAccessManualWebhook] = useCreateAccessManualWebhookMutation();
const [patchAccessManualWebhook] = usePatchAccessManualWebhookMutation();
Expand All @@ -55,7 +58,7 @@ const DSRCustomizationModal: React.FC<Props> = ({ connectionConfig }) => {
const params:
| CreateAccessManualWebhookRequest
| PatchAccessManualWebhookRequest = {
connection_key: connectionConfig.key as string,
connection_key: connectionConfig!.key as string,
body: { ...values } as any,
};
if (fields.length > 0) {
Expand Down Expand Up @@ -83,22 +86,36 @@ const DSRCustomizationModal: React.FC<Props> = ({ connectionConfig }) => {
};
}, [data, isSuccess]);

const DSRButton = (
<Button
bg="primary.800"
color="white"
isDisabled={!connectionConfig || isSubmitting}
isLoading={isSubmitting}
loadingText="Submitting"
size="sm"
variant="solid"
onClick={onOpen}
_active={{ bg: "primary.500" }}
_hover={{ bg: "primary.400" }}
>
Customize DSR
</Button>
);

return (
<>
<Button
bg="primary.800"
color="white"
isDisabled={isSubmitting}
isLoading={isSubmitting}
loadingText="Submitting"
size="sm"
variant="solid"
onClick={onOpen}
_active={{ bg: "primary.500" }}
_hover={{ bg: "primary.400" }}
>
Customize DSR
</Button>
{!connectionConfig ? (
<Tooltip
label="Save an Integration first to customize the DSR"
placement="top"
shouldWrapChildren
>
{DSRButton}
</Tooltip>
) : (
DSRButton
)}
<Modal isCentered isOpen={isOpen} size="lg" onClose={onClose}>
<ModalOverlay />
<ModalContent minWidth="775px">
Expand Down
4 changes: 2 additions & 2 deletions clients/admin-ui/src/flags.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@
"description": "Page to configure consent privacy notices",
"development": true,
"test": true,
"production": false
"production": true
},
"privacyExperience": {
"description": "Page to configure consent privacy experiences",
"development": true,
"test": true,
"production": false
"production": true
},
"standaloneConnections": {
"description": "Allow the creation of standalone connections for testing",
Expand Down
Loading