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

Add Google Tag Manager and Privacy Center ENV vars to sample app, plus the ability to pass ENV vars to both privacy center and sample app during fides deploy via .env #2949

Merged
merged 14 commits into from
May 30, 2023
Merged
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
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,18 @@ The types of changes are:

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

## Added

- Add Google Tag Manager and Privacy Center ENV vars to sample app [#2949](https://github.com/ethyca/fides/pull/2949)

### Changed

- Enabled Privacy Experience beta flag [#3364](https://github.com/ethyca/fides/pull/3364)

## Developer Experience

- Add ability to pass ENV vars to both privacy center and sample app during `fides deploy` via `.env` [#2949](https://github.com/ethyca/fides/pull/2949)

## [2.14.0](https://github.com/ethyca/fides/compare/2.13.0...2.14.0)

### Added
Expand Down
10 changes: 5 additions & 5 deletions clients/sample-app/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
FROM node:16-alpine as prod

ENV DATABASE_HOST localhost
ENV DATABASE_PORT 5432
ENV DATABASE_USER postgres
ENV DATABASE_PASSWORD postgres
ENV DATABASE_DB postgres_example
ENV FIDES_SAMPLE_APP__DATABASE_HOST localhost
ENV FIDES_SAMPLE_APP__DATABASE_PORT 5432
ENV FIDES_SAMPLE_APP__DATABASE_USER postgres
ENV FIDES_SAMPLE_APP__DATABASE_PASSWORD postgres
ENV FIDES_SAMPLE_APP__DATABASE_DB postgres_example

RUN mkdir /home/node/app
WORKDIR /home/node/app
Expand Down
55 changes: 55 additions & 0 deletions clients/sample-app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Fides Sample App

"Cookie House", a sample web application to help demonstrate some of the features of Fides!

## Configuration

This app requires zero configuration, but does support the following ENV vars to override defaults:

| ENV var | Description | Default |
| --------------------------------------------------- | ------------------------------------------------------------------------ | --------------------- |
| FIDES_SAMPLE_APP\_\_DATABASE_HOST | Sample database host name | localhost |
| FIDES_SAMPLE_APP\_\_DATABASE_PORT | Sample database port | 5432 |
| FIDES_SAMPLE_APP\_\_DATABASE_USER | Sample database username | postgres |
| FIDES_SAMPLE_APP\_\_DATABASE_PASSWORD | Sample database password | postgres |
| FIDES_SAMPLE_APP\_\_DATABASE_DB | Sample database name | postgres_example |
| FIDES_SAMPLE_APP\_\_GOOGLE_TAG_MANAGER_CONTAINER_ID | (optional) Google Tag Manager Container ID to inject, e.g. "GTM-ABCD123" | null |
| FIDES_SAMPLE_APP\_\_PRIVACY_CENTER_URL | Fides Privacy Center URL | http://localhost:3001 |

## Development

To run locally, follow these steps:

In `/clients/sample-app`:

```bash
npm install
npm run dev
```

This will automatically bring up a Docker Compose project to create a sample app database containing the Cookie House products data, so ensure you also have `docker` running locally.

Once running successfully, open http://localhost:3000 to see the Cookie House!

## Pre-commit

Before committing any changes, run the following:

```bash
npm run format
npm run lint
npm run test
```

## Testing

This app (currently!) does not have any automated tests. However, it is used in the following automated E2E suites:

- `clients/cypress-e2e/cypress/e2e`
- `clients/privacy-center/cypress/e2e`

These Cypress suites will automatically run in CI to ensure any changes to this app continue to work as expected.

## Deployment

To deploy this app, typically you should use the published `ethyca/fides-sample-app` Docker image which is production-built Next.js image. See https://docs.ethyca.com for more!
20 changes: 15 additions & 5 deletions clients/sample-app/src/lib/db.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
import { Pool } from "pg";

// Load the DB configuration from ENV vars
const {
FIDES_SAMPLE_APP__DATABASE_HOST: host,
FIDES_SAMPLE_APP__DATABASE_PORT: port,
FIDES_SAMPLE_APP__DATABASE_USER: user,
FIDES_SAMPLE_APP__DATABASE_PASSWORD: password,
FIDES_SAMPLE_APP__DATABASE_DB: db,
} = process.env;

// For backwards-compatibility, also support unprefixed versions
const {
DATABASE_HOST,
DATABASE_PORT,
Expand All @@ -9,11 +19,11 @@ const {
} = process.env;

const pool = new Pool({
host: DATABASE_HOST || "localhost",
port: Number(DATABASE_PORT) || 5432,
user: DATABASE_USER || "postgres",
password: DATABASE_PASSWORD || "postgres",
database: DATABASE_DB || "postgres_example",
host: host || DATABASE_HOST || "localhost",
port: Number(port || DATABASE_PORT || 5432),
user: user || DATABASE_USER || "postgres",

Check failure

Code scanning / CodeQL

Hard-coded credentials

The hard-coded value "postgres" is used as [user name](1).
password: password || DATABASE_PASSWORD || "postgres",

Check failure

Code scanning / CodeQL

Hard-coded credentials

The hard-coded value "postgres" is used as [password](1).
database: db || DATABASE_DB || "postgres_example",
});

export default pool;
54 changes: 50 additions & 4 deletions clients/sample-app/src/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,56 @@
/* eslint-disable @next/next/no-sync-scripts */
import { GetServerSideProps } from "next";
import Head from "next/head";
import Script from "next/script";
import { useRouter } from "next/router";
import { Product } from "../types";

import Home from "../components/Home";
import pool from "../lib/db";

interface Props {
gtmContainerId: string | null;
privacyCenterUrl: string;
products: Product[];
}

// Regex to ensure the provided GTM container ID appears valid (e.g. "GTM-ABCD123")
// NOTE: this also protects against XSS since this ID is added to a script template
const VALID_GTM_REGEX = /^[0-9a-zA-Z-]+$/;

/**
* Pass the following server-side ENV variables to the page:
* - FIDES_SAMPLE_APP__GOOGLE_TAG_MANAGER_CONTAINER_ID: configure a GTM container, e.g. "GTM-ABCD123"
* - FIDES_SAMPLE_APP__PRIVACY_CENTER_URL: configure Privacy Center URL, e.g. "http://localhost:3001"
*/
export const getServerSideProps: GetServerSideProps<Props> = async () => {
// Check for a valid FIDES_SAMPLE_APP__GOOGLE_TAG_MANAGER_CONTAINER_ID
let gtmContainerId = null;
if (
process.env.FIDES_SAMPLE_APP__GOOGLE_TAG_MANAGER_CONTAINER_ID?.match(
VALID_GTM_REGEX
)
) {
gtmContainerId =
process.env.FIDES_SAMPLE_APP__GOOGLE_TAG_MANAGER_CONTAINER_ID;
}

// Check for a valid FIDES_SAMPLE_APP__PRIVACY_CENTER_URL
const privacyCenterUrl =
process.env.FIDES_SAMPLE_APP__PRIVACY_CENTER_URL || "http://localhost:3001";

// Query the database for the active products
const results = await pool.query<Product>("SELECT * FROM public.product;");
return { props: { products: results.rows } };
const products = results.rows;

// Pass the server-side props to the page
return { props: { gtmContainerId, privacyCenterUrl, products } };
};

const IndexPage = ({ products }: Props) => {
const IndexPage = ({ gtmContainerId, privacyCenterUrl, products }: Props) => {
// Load the fides.js script from the Fides Privacy Center, assumed to be
// running at http://localhost:3001
let fidesScriptTagUrl = "http://localhost:3001/fides.js";
let fidesScriptTagUrl = `${privacyCenterUrl}/fides.js`;
const router = useRouter();
const { geolocation } = router.query;

Expand All @@ -38,9 +69,24 @@ const IndexPage = ({ products }: Props) => {
/>
<link rel="icon" href="/favicon.ico" />
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
{/* Insert the fides.js script */}
<script src={fidesScriptTagUrl} />
</Head>

{/* Insert the GTM script, if a container ID was provided */}
<Script id="google-tag-manager" strategy="afterInteractive">
{`
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','${gtmContainerId}');
`}
{`
if (window.Fides) {
window.Fides.gtm();
}
`}
</Script>
<Home products={products} />
</>
);
Expand Down
18 changes: 13 additions & 5 deletions src/fides/data/sample_project/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,16 @@ services:
sample-app:
container_name: sample-app
image: ethyca/fides-sample-app:local
env_file:
- ${FIDES_DEPLOY_ENV_FILE:-sample.env}
environment:
- PORT=3000
- DATABASE_HOST=postgres-test
- DATABASE_PORT=5432
- DATABASE_USER=postgres
- DATABASE_PASSWORD=postgres
- DATABASE_DB=postgres_example
- FIDES_SAMPLE_APP__DATABASE_HOST=postgres-test
- FIDES_SAMPLE_APP__DATABASE_PORT=5432
- FIDES_SAMPLE_APP__DATABASE_USER=postgres
- FIDES_SAMPLE_APP__DATABASE_PASSWORD=postgres
- FIDES_SAMPLE_APP__DATABASE_DB=postgres_example
- FIDES_SAMPLE_APP__PRIVACY_CENTER_URL=http://localhost:3001
ports:
- 3000:3000
depends_on:
Expand All @@ -67,6 +70,11 @@ services:
fides-pc:
container_name: fides-privacy-center
image: ethyca/fides-privacy-center:local
env_file:
- ${FIDES_DEPLOY_ENV_FILE:-sample.env}
environment:
- FIDES_PRIVACY_CENTER__FIDES_API_URL=http://localhost:8080/api/v1
- FIDES_PRIVACY_CENTER__PRIVACY_CENTER_URL=http://localhost:3001
ports:
- "3001:3000"
volumes:
Expand Down
2 changes: 1 addition & 1 deletion src/fides/data/sample_project/fides.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ db_index = 0

[security]
env = "prod"
cors_origins = [ "http://localhost:8080", "http://localhost:3001",]
cors_origins = [ "http://localhost:8080", "http://localhost:3001", "http://localhost:3000" ]
app_encryption_key = "examplevalidprojectencryptionkey"
oauth_root_client_id = "fidesadmin"
oauth_root_client_secret = "fidesadminsecret"
Expand Down