Skip to content

Commit

Permalink
Merge branch 'main' into andres/HJ-300
Browse files Browse the repository at this point in the history
  • Loading branch information
andres-torres-marroquin committed Dec 10, 2024
2 parents 83faf44 + 8610b3f commit bd16b0a
Show file tree
Hide file tree
Showing 76 changed files with 4,184 additions and 3,733 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@ The types of changes are:

### Added
- New page in the Cookie House sample app to demonstrate the use of embedding the FidesJS SDK on the page [#5564](https://github.com/ethyca/fides/pull/5564)
- Adding `dsr_testing_tools_enabled` security setting [#5573](https://github.com/ethyca/fides/pull/5573)


### Fixed
- SaaS integrations using `oauth_client_credentials` now properly update their access token when editing the secrets.
- Saas integrations using `oauth_client_credentials` now properly refresh their access token when the current token expires

## [2.51.0](https://github.com/ethyca/fides/compare/2.50.0...2.51.0)

Expand All @@ -44,6 +47,7 @@ The types of changes are:
- Updating dataset PUT to allow deleting all datasets [#5524](https://github.com/ethyca/fides/pull/5524)
- Adds support for fides_key generation when parent_key is provided in Taxonomy create endpoints [#5542](https://github.com/ethyca/fides/pull/5542)
- An integration will no longer re-enable after saving the connection form [#5555](https://github.com/ethyca/fides/pull/5555)
- Fixed positioning of Fides brand link in privacy center [#5572](https://github.com/ethyca/fides/pull/5572)

### Removed
- Removed unnecessary debug logging from the load_file config helper [#5544](https://github.com/ethyca/fides/pull/5544)
Expand Down
10 changes: 8 additions & 2 deletions clients/fides-js/src/components/Overlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ const Overlay: FunctionComponent<Props> = ({
}, [showBanner, setBannerIsOpen]);

useEffect(() => {
if (!experience || options.modalLinkId === "") {
if (options.fidesEmbed || !experience || options.modalLinkId === "") {
// If empty string is explicitly set, do not attempt to bind the modal link to the click handler.
// developers using `Fides.showModal();` can use this to prevent polling for the modal link.
return () => {};
Expand Down Expand Up @@ -211,7 +211,13 @@ const Overlay: FunctionComponent<Props> = ({
}
window.Fides.showModal = defaultShowModal;
};
}, [options.modalLinkId, options.debug, handleOpenModal, experience]);
}, [
options.fidesEmbed,
options.modalLinkId,
options.debug,
handleOpenModal,
experience,
]);

const handleManagePreferencesClick = (): void => {
handleOpenModal();
Expand Down
6 changes: 3 additions & 3 deletions clients/fides-js/src/components/fides.css
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ div#fides-consent-content .fides-modal-description {
justify-content: center;
}

.fides-modal-container .fides-button-group-brand {
.fides-modal-footer .fides-button-group-brand {
min-height: var(--fides-overlay-modal-secondary-button-group-height);
}

Expand Down Expand Up @@ -1023,13 +1023,13 @@ div#fides-overlay-wrapper .fides-toggle .fides-toggle-display {
position: relative;
}

.fides-modal-container .fides-i18n-menu {
.fides-modal-footer .fides-i18n-menu {
position: absolute;
left: var(--fides-overlay-padding);
bottom: var(--fides-overlay-padding);
}

.fides-modal-container .fides-button-group-i18n {
.fides-modal-footer .fides-button-group-i18n {
min-height: var(--fides-overlay-modal-secondary-button-group-height);
}

Expand Down
40 changes: 28 additions & 12 deletions clients/privacy-center/components/BrandLink.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
import { EthycaLogo, Link, LinkProps } from "fidesui";

const BrandLink = (props: LinkProps) => (
<Link
fontSize="8px"
color="gray.400"
isExternal
textDecoration="none"
_hover={{ textDecoration: "none" }}
{...props}
>
Powered by <EthycaLogo color="minos.500" h="20px" w="31px" />
</Link>
);
import { useSettings } from "~/features/common/settings.slice";

const BrandLink = ({
position = "absolute",
right = 6,
...props
}: LinkProps) => {
const { SHOW_BRAND_LINK } = useSettings();

if (!SHOW_BRAND_LINK) {
return null;
}

return (
<Link
fontSize="8px"
color="gray.400"
isExternal
position={position}
right={right}
textDecoration="none"
_hover={{ textDecoration: "none" }}
{...props}
>
Powered by <EthycaLogo color="minos.500" h="20px" w="31px" />
</Link>
);
};

export default BrandLink;
15 changes: 1 addition & 14 deletions clients/privacy-center/components/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@ import { Flex } from "fidesui";
import Head from "next/head";
import React, { ReactNode } from "react";

import BrandLink from "~/components/BrandLink";
import Logo from "~/components/Logo";
import { useConfig } from "~/features/common/config.slice";
import { useSettings } from "~/features/common/settings.slice";
import { useStyles } from "~/features/common/styles.slice";

const Layout = ({ children }: { children: ReactNode }) => {
const config = useConfig();
const styles = useStyles();
const { SHOW_BRAND_LINK } = useSettings();
return (
<>
<Head>
Expand All @@ -32,17 +29,7 @@ const Layout = ({ children }: { children: ReactNode }) => {
<Logo src={config.logo_path ?? ""} href={config.logo_url ?? ""} />
</Flex>
</header>
<div>
{children}
{SHOW_BRAND_LINK && (
<BrandLink
position="absolute"
bottom={16}
right={6}
href="https://fid.es/powered"
/>
)}
</div>
<div>{children}</div>
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { useAppDispatch, useAppSelector } from "~/app/hooks";
import { inspectForBrowserIdentities } from "~/common/browser-identities";
import { useLocalStorage } from "~/common/hooks";
import { ErrorToastOptions, SuccessToastOptions } from "~/common/toast-options";
import BrandLink from "~/components/BrandLink";
import { useConfig } from "~/features/common/config.slice";
import {
changeConsent,
Expand Down Expand Up @@ -209,6 +210,7 @@ const ConfigDrivenConsent = ({
cancelLabel="Cancel"
saveLabel="Save"
/>
<BrandLink bottom={0} />
</Stack>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { inspectForBrowserIdentities } from "~/common/browser-identities";
import { useLocalStorage } from "~/common/hooks";
import useI18n from "~/common/hooks/useI18n";
import { ErrorToastOptions, SuccessToastOptions } from "~/common/toast-options";
import BrandLink from "~/components/BrandLink";
import { useProperty } from "~/features/common/property.slice";
import {
selectPrivacyExperience,
Expand Down Expand Up @@ -400,7 +401,10 @@ const NoticeDrivenConsent = ({ base64Cookie }: { base64Cookie: boolean }) => {
onCancel={handleCancel}
justifyContent="center"
/>
<PrivacyPolicyLink alignSelf="center" experience={experience} />
<Stack flexDirection="row" alignItems="center">
<PrivacyPolicyLink experience={experience} />
<BrandLink />
</Stack>
</Box>
);
};
Expand Down
42 changes: 28 additions & 14 deletions clients/privacy-center/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import React, { useEffect, useState } from "react";

import { useAppDispatch, useAppSelector } from "~/app/hooks";
import { ConfigErrorToastOptions } from "~/common/toast-options";
import BrandLink from "~/components/BrandLink";
import ConsentCard from "~/components/consent/ConsentCard";
import {
ConsentRequestModal,
Expand All @@ -25,7 +26,10 @@ import {
} from "~/components/modals/privacy-request-modal/PrivacyRequestModal";
import PrivacyCard from "~/components/PrivacyCard";
import { useConfig } from "~/features/common/config.slice";
import { selectIsNoticeDriven } from "~/features/common/settings.slice";
import {
selectIsNoticeDriven,
useSettings,
} from "~/features/common/settings.slice";
import {
clearLocation,
selectPrivacyExperience,
Expand Down Expand Up @@ -68,6 +72,10 @@ const Home: NextPage = () => {
let isConsentModalOpen = isConsentModalOpenConst;
const getIdVerificationConfigQuery = useGetIdVerificationConfigQuery();

const { SHOW_BRAND_LINK } = useSettings();
const showPrivacyPolicyLink =
!!config.privacy_policy_url && !!config.privacy_policy_url_text;

// Subscribe to experiences just to see if there are any notices.
// The subscription automatically handles skipping if overlay is not enabled
useSubscribeToPrivacyExperienceQuery();
Expand Down Expand Up @@ -214,19 +222,25 @@ const Home: NextPage = () => {
{paragraph}
</Text>
))}
{config.privacy_policy_url && config.privacy_policy_url_text ? (
<Link
fontSize={["small", "medium"]}
fontWeight="medium"
textAlign="center"
textDecoration="underline"
color="gray.600"
href={config.privacy_policy_url}
isExternal
>
{config.privacy_policy_url_text}
</Link>
) : null}

{(SHOW_BRAND_LINK || showPrivacyPolicyLink) && (
<Stack flexDirection="row">
{showPrivacyPolicyLink && (
<Link
fontSize={["small", "medium"]}
fontWeight="medium"
textAlign="center"
textDecoration="underline"
color="gray.600"
href={config.privacy_policy_url!}
isExternal
>
{config.privacy_policy_url_text}
</Link>
)}
<BrandLink />
</Stack>
)}
</Stack>
<PrivacyRequestModal
isOpen={isPrivacyModalOpen}
Expand Down
12 changes: 11 additions & 1 deletion clients/sample-app/src/pages/embedded-consent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,17 @@ const IndexPage = ({ gtmContainerId, privacyCenterUrl }: Props) => {
{/* Require FidesJS to "embed" it's UI onto the page, instead of as an overlay over the <body> itself. (see https://ethyca.com/docs/dev-docs/js/reference/interfaces/FidesOptions#fides_embed) */}
<script>{`window.fides_overrides = { fides_embed: true, fides_disable_banner: true }`}</script>
{/* Allow the embedded consent modal to fill the screen */}
<style>{`#fides-embed-container { --fides-overlay-width: 'auto' }`}</style>
<style>{`
#fides-embed-container {
--fides-overlay-width: 'auto'
}
body {
font-family: "Inter", sans-serif;
color: #171923;
font-size: 14px;
}
`}</style>
</Head>
{/**
Insert the fides.js script and run the GTM integration once ready
Expand Down
9 changes: 9 additions & 0 deletions src/fides/api/api/v1/endpoints/dataset_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
HTTP_200_OK,
HTTP_204_NO_CONTENT,
HTTP_400_BAD_REQUEST,
HTTP_403_FORBIDDEN,
HTTP_404_NOT_FOUND,
HTTP_415_UNSUPPORTED_MEDIA_TYPE,
HTTP_422_UNPROCESSABLE_ENTITY,
Expand Down Expand Up @@ -82,6 +83,7 @@
V1_URL_PREFIX,
YAML_DATASETS,
)
from fides.config import CONFIG

from fides.api.models.sql_models import ( # type: ignore[attr-defined] # isort: skip
Dataset as CtlDataset,
Expand Down Expand Up @@ -856,6 +858,13 @@ def test_connection_datasets(
fides_key: FidesKey,
unlabeled_identities: UnlabeledIdentities,
) -> Dict[str, Any]:

if not CONFIG.security.dsr_testing_tools_enabled:
raise HTTPException(
status_code=HTTP_403_FORBIDDEN,
detail="DSR testing tools are not enabled.",
)

dataset_config = DatasetConfig.filter(
db=db,
conditions=(
Expand Down
13 changes: 12 additions & 1 deletion src/fides/api/api/v1/endpoints/privacy_request_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import csv
import io
import json
from collections import defaultdict
from datetime import datetime
from typing import (
Expand Down Expand Up @@ -148,6 +149,7 @@
from fides.api.util.enums import ColumnSort
from fides.api.util.fuzzy_search_utils import get_decrypted_identities_automaton
from fides.api.util.logger import Pii
from fides.api.util.storage_util import storage_json_encoder
from fides.common.api.scope_registry import (
PRIVACY_REQUEST_CALLBACK_RESUME,
PRIVACY_REQUEST_CREATE,
Expand Down Expand Up @@ -2657,8 +2659,17 @@ def get_test_privacy_request_results(
)
privacy_request.save(db=db)

# Escape datetime and ObjectId values
raw_data = privacy_request.get_raw_access_results()
escaped_json = json.dumps(raw_data, indent=2, default=storage_json_encoder)
results = json.loads(escaped_json)

return {
"privacy_request_id": privacy_request.id,
"status": privacy_request.status,
"results": privacy_request.get_raw_access_results(),
"results": (
results
if CONFIG.security.dsr_testing_tools_enabled
else "DSR testing tools are not enabled, results will not be shown."
),
}
7 changes: 5 additions & 2 deletions src/fides/api/models/connectionconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,10 +220,13 @@ def authorized(self) -> bool:
return False

# hard-coding to avoid cyclic dependency
if authentication.strategy != "oauth2_authorization_code":
if authentication.strategy not in [
"oauth2_authorization_code",
"oauth2_client_credentials",
]:
return False

return bool(self.secrets and self.secrets.get("access_token"))
return bool(self.secrets and "access_token" in self.secrets.keys())

@property
def name_or_key(self) -> str:
Expand Down
2 changes: 1 addition & 1 deletion src/fides/api/schemas/privacy_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,4 +401,4 @@ class FilteredPrivacyRequestResults(FidesSchema):

privacy_request_id: str
status: PrivacyRequestStatus
results: Dict[str, Any]
results: Union[Dict[str, Any], str]
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,22 @@ def add_authentication(
# add access_token to request
request.headers["Authorization"] = "Bearer " + access_token
return request

def _refresh_token(self, connection_config: ConnectionConfig) -> str:
"""
Persists and returns a refreshed access_token if the token is close to expiring.
Otherwise just returns the existing access_token.
For the Client Credentials OAuth flow we reuse the access request to get a new token.
"""

expires_at = connection_config.secrets.get("expires_at") # type: ignore
if self._close_to_expiration(expires_at, connection_config):
refresh_response = self._call_token_request(
"refresh", self.token_request, connection_config
)
return self._validate_and_store_response(
refresh_response, connection_config
)

return connection_config.secrets.get("access_token") # type: ignore
Loading

0 comments on commit bd16b0a

Please sign in to comment.