From 33d6342ded90be480b5942c7229b8ca994bd4382 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Fri, 27 May 2022 13:09:12 -0400 Subject: [PATCH 01/19] Switch to Chakra image instead of nextjs --- clients/admin-ui/src/features/common/Header.tsx | 4 ++-- clients/admin-ui/src/pages/404.tsx | 7 +++---- clients/admin-ui/src/pages/login.tsx | 6 +++--- clients/privacy-center/pages/404.tsx | 7 +++---- clients/privacy-center/pages/index.tsx | 6 +++--- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/clients/admin-ui/src/features/common/Header.tsx b/clients/admin-ui/src/features/common/Header.tsx index 6e286b68e..2de832e82 100644 --- a/clients/admin-ui/src/features/common/Header.tsx +++ b/clients/admin-ui/src/features/common/Header.tsx @@ -9,8 +9,8 @@ import { MenuList, Stack, Text, + Image } from '@fidesui/react'; -import Image from 'next/image'; import NextLink from 'next/link'; import { signOut } from 'next-auth/react'; import React from 'react'; @@ -34,7 +34,7 @@ const Header: React.FC = ({ username }) => ( {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} - FidesOps Logo + FidesOps Logo diff --git a/clients/admin-ui/src/pages/404.tsx b/clients/admin-ui/src/pages/404.tsx index 9ee1615a3..460afd903 100644 --- a/clients/admin-ui/src/pages/404.tsx +++ b/clients/admin-ui/src/pages/404.tsx @@ -1,6 +1,5 @@ -import { Box, Button, Heading, Stack, Text } from '@fidesui/react'; +import { Box, Button, Heading, Stack, Text, Image } from '@fidesui/react'; import Head from 'next/head'; -import Image from 'next/image'; import NextLink from 'next/link'; const Custom404 = () => ( @@ -55,7 +54,7 @@ const Custom404 = () => ( FidesUI logo @@ -65,7 +64,7 @@ const Custom404 = () => ( FidesUI logo diff --git a/clients/admin-ui/src/pages/login.tsx b/clients/admin-ui/src/pages/login.tsx index 296d698a4..1bfdbcbe0 100644 --- a/clients/admin-ui/src/pages/login.tsx +++ b/clients/admin-ui/src/pages/login.tsx @@ -10,11 +10,11 @@ import { Input, Stack, useToast, + Image } from '@fidesui/react'; import { useFormik } from 'formik'; import type { NextPage } from 'next'; import Head from 'next/head'; -import Image from 'next/image'; import { useRouter } from 'next/router'; import { signIn } from 'next-auth/react'; import React, { useState } from 'react'; @@ -108,7 +108,7 @@ const Login: NextPage = () => { FidesUI logo @@ -139,7 +139,7 @@ const Login: NextPage = () => { FidesUI logo diff --git a/clients/privacy-center/pages/404.tsx b/clients/privacy-center/pages/404.tsx index 95bd8f62c..f422a22f6 100644 --- a/clients/privacy-center/pages/404.tsx +++ b/clients/privacy-center/pages/404.tsx @@ -1,7 +1,6 @@ import Head from 'next/head'; -import Image from 'next/image'; import NextLink from 'next/link'; -import { Stack, Heading, Box, Text, Button, Link } from '@fidesui/react'; +import { Stack, Heading, Box, Text, Button, Link, Image } from '@fidesui/react'; const Custom404 = () => (
@@ -55,7 +54,7 @@ const Custom404 = () => ( FidesUI logo @@ -68,7 +67,7 @@ const Custom404 = () => ( FidesUI logo diff --git a/clients/privacy-center/pages/index.tsx b/clients/privacy-center/pages/index.tsx index c0fed2b7f..a69605b53 100644 --- a/clients/privacy-center/pages/index.tsx +++ b/clients/privacy-center/pages/index.tsx @@ -11,8 +11,8 @@ import { AlertIcon, AlertDescription, CloseButton, + Image } from "@fidesui/react"; -import Image from "next/image"; import { useRequestModal, RequestModal } from "../components/RequestModal"; import type { AlertState } from "../types/AlertState"; @@ -123,8 +123,8 @@ const Home: NextPage = () => { {action.description} Date: Fri, 27 May 2022 15:02:26 -0400 Subject: [PATCH 02/19] checking in progress towards static build --- Dockerfile | 22 ++++++ clients/admin-ui/.eslintrc.json | 1 + clients/admin-ui/.gitignore | 3 + clients/admin-ui/package.json | 7 +- .../admin-ui/src/features/common/Header.tsx | 5 +- clients/admin-ui/src/pages/404.tsx | 2 +- clients/admin-ui/src/pages/index.tsx | 46 +++++------ clients/admin-ui/src/pages/login.tsx | 5 +- .../src/pages/user-management/index.tsx | 40 +++++----- .../src/pages/user-management/new.tsx | 38 +++++----- .../pages/user-management/profile/[id].tsx | 76 ++++++++++--------- 11 files changed, 138 insertions(+), 107 deletions(-) diff --git a/Dockerfile b/Dockerfile index 34567a2ff..dc6c5efd4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,15 @@ +FROM node:16 as frontend + +WORKDIR /fides/clients/admin-ui + +# install node modules +COPY clients/admin-ui/ . +RUN npm install + +# Build the frontend static files +RUN npm run export + + FROM --platform=linux/amd64 python:3.9.6-slim-buster ARG MSSQL_REQUIRED @@ -38,9 +50,19 @@ RUN pip install -U pip \ RUN if [ "$MSSQL_REQUIRED" = "true" ] ; then pip install -U pip -r mssql-requirements.txt ; fi + +RUN pwd +# Make a static files directory +RUN mkdir -p src/fidesops/build/static +# Copy frontend build over +COPY --from=frontend clients/admin-ui/out/ src/fidesops/build/static/ + # Copy in the application files and install it locally COPY . /fidesops WORKDIR /fidesops RUN pip install -e . + + + CMD [ "fidesops", "webserver" ] \ No newline at end of file diff --git a/clients/admin-ui/.eslintrc.json b/clients/admin-ui/.eslintrc.json index dedadab6a..1c47c6165 100644 --- a/clients/admin-ui/.eslintrc.json +++ b/clients/admin-ui/.eslintrc.json @@ -22,6 +22,7 @@ ], "react/jsx-filename-extension": [1, { "extensions": [".tsx"] }], "react/jsx-props-no-spreading": [0], + "no-restricted-imports": [0], "simple-import-sort/imports": "error", "simple-import-sort/exports": "error" } diff --git a/clients/admin-ui/.gitignore b/clients/admin-ui/.gitignore index df790c256..c6c78d095 100644 --- a/clients/admin-ui/.gitignore +++ b/clients/admin-ui/.gitignore @@ -106,3 +106,6 @@ dist # msw web worker script public/mockServiceWorker.js + + +out/ \ No newline at end of file diff --git a/clients/admin-ui/package.json b/clients/admin-ui/package.json index 741e5fc76..e5f873b62 100644 --- a/clients/admin-ui/package.json +++ b/clients/admin-ui/package.json @@ -6,12 +6,15 @@ "dev:mock": "echo '🚨 Running with mock API'; NEXT_PUBLIC_MOCK_API=true next dev", "build": "next build", "start": "next start", - "lint": "eslint . --ext .ts,.tsx", + "lint": "eslint . --fix --ext .ts,.tsx ", "test": "jest --watch", "test:ci": "jest", "analyze": "cross-env ANALYZE=true next build", "analyze:server": "cross-env BUNDLE_ANALYZE=server next build", - "analyze:browser": "cross-env BUNDLE_ANALYZE=browser next build" + "analyze:browser": "cross-env BUNDLE_ANALYZE=browser next build", + "export": "next build && next export", + "copy-export": "rsync -a --delete out/ ../../src/fidesapi/build/static/", + "prod-export": "npm run export && npm run copy-export" }, "dependencies": { "@chakra-ui/react": "^1.8.0", diff --git a/clients/admin-ui/src/features/common/Header.tsx b/clients/admin-ui/src/features/common/Header.tsx index 2de832e82..bdbaf4c71 100644 --- a/clients/admin-ui/src/features/common/Header.tsx +++ b/clients/admin-ui/src/features/common/Header.tsx @@ -1,6 +1,7 @@ import { Button, Flex, + Image, Link, Menu, MenuButton, @@ -8,9 +9,7 @@ import { MenuItem, MenuList, Stack, - Text, - Image -} from '@fidesui/react'; + Text} from '@fidesui/react'; import NextLink from 'next/link'; import { signOut } from 'next-auth/react'; import React from 'react'; diff --git a/clients/admin-ui/src/pages/404.tsx b/clients/admin-ui/src/pages/404.tsx index 460afd903..5a8007144 100644 --- a/clients/admin-ui/src/pages/404.tsx +++ b/clients/admin-ui/src/pages/404.tsx @@ -1,4 +1,4 @@ -import { Box, Button, Heading, Stack, Text, Image } from '@fidesui/react'; +import { Box, Button, Heading, Image,Stack, Text } from '@fidesui/react'; import Head from 'next/head'; import NextLink from 'next/link'; diff --git a/clients/admin-ui/src/pages/index.tsx b/clients/admin-ui/src/pages/index.tsx index 4560a0cb0..337f8a786 100644 --- a/clients/admin-ui/src/pages/index.tsx +++ b/clients/admin-ui/src/pages/index.tsx @@ -1,13 +1,13 @@ import { Box, Heading } from '@fidesui/react'; import type { NextPage } from 'next'; import Head from 'next/head'; -import { getSession } from 'next-auth/react'; -import { wrapper } from '../app/store'; +// import { getSession } from 'next-auth/react'; +// import { wrapper } from '../app/store'; import NavBar from '../features/common/NavBar'; import RequestFilters from '../features/privacy-requests/RequestFilters'; import RequestTable from '../features/privacy-requests/RequestTable'; -import { assignToken, setUser } from '../features/user/user.slice'; +// import { assignToken, setUser } from '../features/user/user.slice'; const Home: NextPage = () => (
@@ -31,23 +31,25 @@ const Home: NextPage = () => (
); -export const getServerSideProps = wrapper.getServerSideProps( - (store) => async (context) => { - const session = await getSession(context); - - if (session && typeof session.accessToken !== 'undefined') { - await store.dispatch(assignToken(session.accessToken)); - await store.dispatch(setUser(session.user)); - return { props: {} }; - } - - return { - redirect: { - destination: '/login', - permanent: false, - }, - }; - } -); - export default Home; + +// export const getServerSideProps = wrapper.getServerSideProps( +// (store) => async (context) => { +// const session = await getSession(context); + +// if (session && typeof session.accessToken !== 'undefined') { +// await store.dispatch(assignToken(session.accessToken)); +// await store.dispatch(setUser(session.user)); +// return { props: {} }; +// } + +// return { +// redirect: { +// destination: '/login', +// permanent: false, +// }, +// }; +// } +// ); + +// export default Home; diff --git a/clients/admin-ui/src/pages/login.tsx b/clients/admin-ui/src/pages/login.tsx index 1bfdbcbe0..927015458 100644 --- a/clients/admin-ui/src/pages/login.tsx +++ b/clients/admin-ui/src/pages/login.tsx @@ -7,11 +7,10 @@ import { FormErrorMessage, FormLabel, Heading, + Image, Input, Stack, - useToast, - Image -} from '@fidesui/react'; + useToast} from '@fidesui/react'; import { useFormik } from 'formik'; import type { NextPage } from 'next'; import Head from 'next/head'; diff --git a/clients/admin-ui/src/pages/user-management/index.tsx b/clients/admin-ui/src/pages/user-management/index.tsx index 61c6c119d..19e4cbcbc 100644 --- a/clients/admin-ui/src/pages/user-management/index.tsx +++ b/clients/admin-ui/src/pages/user-management/index.tsx @@ -1,12 +1,12 @@ import { Box, Heading } from '@fidesui/react'; import type { NextPage } from 'next'; import Head from 'next/head'; -import { getSession } from 'next-auth/react'; +// import { getSession } from 'next-auth/react'; import React from 'react'; -import { wrapper } from '../../app/store'; +// import { wrapper } from '../../app/store'; import NavBar from '../../features/common/NavBar'; -import { assignToken } from '../../features/user/user.slice'; +// import { assignToken } from '../../features/user/user.slice'; import UserManagementTable from '../../features/user-management/UserManagementTable'; import UserManagementTableActions from '../../features/user-management/UserManagementTableActions'; @@ -34,20 +34,20 @@ const UserManagement: NextPage = () => ( export default UserManagement; -export const getServerSideProps = wrapper.getServerSideProps( - (store) => async (context) => { - const session = await getSession(context); - - if (session && typeof session.accessToken !== 'undefined') { - await store.dispatch(assignToken(session.accessToken)); - return { props: { session } }; - } - - return { - redirect: { - destination: '/login', - permanent: false, - }, - }; - } -); +// export const getServerSideProps = wrapper.getServerSideProps( +// (store) => async (context) => { +// const session = await getSession(context); + +// if (session && typeof session.accessToken !== 'undefined') { +// await store.dispatch(assignToken(session.accessToken)); +// return { props: { session } }; +// } + +// return { +// redirect: { +// destination: '/login', +// permanent: false, +// }, +// }; +// } +// ); diff --git a/clients/admin-ui/src/pages/user-management/new.tsx b/clients/admin-ui/src/pages/user-management/new.tsx index 5124b5a80..4118cff58 100644 --- a/clients/admin-ui/src/pages/user-management/new.tsx +++ b/clients/admin-ui/src/pages/user-management/new.tsx @@ -6,12 +6,12 @@ import { Heading } from '@fidesui/react'; import type { NextPage } from 'next'; -import { getSession } from 'next-auth/react'; +// import { getSession } from 'next-auth/react'; import React from 'react'; -import { wrapper } from '../../app/store'; +// import { wrapper } from '../../app/store'; import NavBar from '../../features/common/NavBar'; -import { assignToken, setUser } from '../../features/user/user.slice'; +// import { assignToken, setUser } from '../../features/user/user.slice'; import NewUserForm from '../../features/user-management/NewUserForm'; const CreateNewUser: NextPage = () => ( @@ -43,21 +43,21 @@ const CreateNewUser: NextPage = () => ( export default CreateNewUser; -export const getServerSideProps = wrapper.getServerSideProps( - (store) => async (context) => { - const session = await getSession(context); +// export const getServerSideProps = wrapper.getServerSideProps( +// (store) => async (context) => { +// const session = await getSession(context); - if (session && typeof session.accessToken !== 'undefined') { - await store.dispatch(assignToken(session.accessToken)); - await store.dispatch(setUser(session.user)); - return { props: { session } }; - } +// if (session && typeof session.accessToken !== 'undefined') { +// await store.dispatch(assignToken(session.accessToken)); +// await store.dispatch(setUser(session.user)); +// return { props: { session } }; +// } - return { - redirect: { - destination: '/login', - permanent: false, - }, - }; - } -); +// return { +// redirect: { +// destination: '/login', +// permanent: false, +// }, +// }; +// } +// ); diff --git a/clients/admin-ui/src/pages/user-management/profile/[id].tsx b/clients/admin-ui/src/pages/user-management/profile/[id].tsx index bae3cb755..0e39d0a89 100644 --- a/clients/admin-ui/src/pages/user-management/profile/[id].tsx +++ b/clients/admin-ui/src/pages/user-management/profile/[id].tsx @@ -6,20 +6,21 @@ import { Heading, } from '@fidesui/react'; import type { NextPage } from 'next'; -import { getSession } from 'next-auth/react'; +// import { getSession } from 'next-auth/react'; import React from 'react'; -import { wrapper } from '../../../app/store'; +// import { wrapper } from '../../../app/store'; import NavBar from '../../../features/common/NavBar'; -import { User } from '../../../features/user/types'; -import { - assignToken, - setUser, - userApi, -} from '../../../features/user/user.slice'; +// import { User } from '../../../features/user/types'; +// import { +// assignToken, +// setUser, +// userApi, +// } from '../../../features/user/user.slice'; import EditUserForm from '../../../features/user-management/EditUserForm'; -const Profile: NextPage<{ session: { user: User } }> = ({ session }) => ( +// const Profile: NextPage<{ session: { user: User } }> = ({ session }) => ( +const Profile: NextPage = () => (
@@ -41,7 +42,8 @@ const Profile: NextPage<{ session: { user: User } }> = ({ session }) => ( {/* @ts-ignore */} - + {/* */} +
@@ -49,32 +51,32 @@ const Profile: NextPage<{ session: { user: User } }> = ({ session }) => ( export default Profile; -export const getServerSideProps = wrapper.getServerSideProps( - (store) => async (context) => { - const session = await getSession(context); - if (session && typeof session.accessToken !== 'undefined') { - await store.dispatch(assignToken(session.accessToken)); - await store.dispatch(setUser(session.user)); +// export const getServerSideProps = wrapper.getServerSideProps( +// (store) => async (context) => { +// const session = await getSession(context); +// if (session && typeof session.accessToken !== 'undefined') { +// await store.dispatch(assignToken(session.accessToken)); +// await store.dispatch(setUser(session.user)); - if (context.query.id) { - store.dispatch( - userApi.endpoints.getUserById.initiate(context.query.id as string) - ); - store.dispatch( - userApi.endpoints.getUserPermissions.initiate( - context.query.id as string - ) - ); - await Promise.all(userApi.util.getRunningOperationPromises()); - } - return { props: { session, query: context.query } }; - } +// if (context.query.id) { +// store.dispatch( +// userApi.endpoints.getUserById.initiate(context.query.id as string) +// ); +// store.dispatch( +// userApi.endpoints.getUserPermissions.initiate( +// context.query.id as string +// ) +// ); +// await Promise.all(userApi.util.getRunningOperationPromises()); +// } +// return { props: { session, query: context.query } }; +// } - return { - redirect: { - destination: '/login', - permanent: false, - }, - }; - } -); +// return { +// redirect: { +// destination: '/login', +// permanent: false, +// }, +// }; +// } +// ); From 943fd5eb57c3d80a90cc78d7942b3e19adabc314 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Mon, 6 Jun 2022 09:39:33 -0400 Subject: [PATCH 03/19] Mount static file directory --- src/fidesops/main.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/fidesops/main.py b/src/fidesops/main.py index c44bff86d..7c8efbb20 100644 --- a/src/fidesops/main.py +++ b/src/fidesops/main.py @@ -2,6 +2,7 @@ import uvicorn from fastapi import FastAPI +from fastapi.staticfiles import StaticFiles from starlette.middleware.cors import CORSMiddleware from fidesops.api.v1.api import api_router @@ -13,6 +14,7 @@ from fidesops.tasks.scheduled.scheduler import scheduler from fidesops.tasks.scheduled.tasks import initiate_scheduled_request_intake from fidesops.util.logger import get_fides_log_record_factory +from pathlib import Path logging.basicConfig(level=config.security.LOG_LEVEL) logging.setLogRecordFactory(get_fides_log_record_factory()) @@ -35,6 +37,20 @@ app.add_exception_handler(FunctionalityNotConfigured, handler) +@app.on_event("startup") +async def create_webapp_dir_if_not_exists() -> None: + """Creates the webapp directory if it doesn't exist.""" + WEBAPP_DIRECTORY = Path("src/fidesops/build/static") + WEBAPP_INDEX = WEBAPP_DIRECTORY / "index.html" + if not WEBAPP_INDEX.is_file(): + WEBAPP_DIRECTORY.mkdir(parents=True, exist_ok=True) + with open(WEBAPP_DIRECTORY / "index.html", "w") as index_file: + index_file.write("

Privacy is a Human Right!

") + + app.mount("/static", StaticFiles(directory=WEBAPP_DIRECTORY), name="static") + logger.info("Mounted static file directory...") + + def start_webserver() -> None: """Run any pending DB migrations and start the webserver.""" logger.info("****************fidesops****************") From 29baceef9380a30d8f3ea57986cbc3190a0eb906 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Mon, 6 Jun 2022 11:37:57 -0400 Subject: [PATCH 04/19] Update Dockerfile --- Dockerfile | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index dc6c5efd4..a1bcaad7c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,16 +1,15 @@ FROM node:16 as frontend -WORKDIR /fides/clients/admin-ui - +WORKDIR clients/hello_world # install node modules -COPY clients/admin-ui/ . +COPY clients/hello_world/ . RUN npm install # Build the frontend static files RUN npm run export -FROM --platform=linux/amd64 python:3.9.6-slim-buster +FROM --platform=linux/amd64 python:3.9.13-slim-buster as backend ARG MSSQL_REQUIRED @@ -55,7 +54,7 @@ RUN pwd # Make a static files directory RUN mkdir -p src/fidesops/build/static # Copy frontend build over -COPY --from=frontend clients/admin-ui/out/ src/fidesops/build/static/ +COPY --from=frontend clients/hello_world/out/ src/fidesops/build/static/ # Copy in the application files and install it locally COPY . /fidesops From eb0d3dda1177fd1bc412b515bdfbd9700797df3e Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Mon, 6 Jun 2022 11:38:16 -0400 Subject: [PATCH 05/19] Add dockerignore file --- .dockerignore | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..d67925787 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,13 @@ +.idea +.vscode +.DS_Store +.git +.mypy_cache + +venv/ +clients/admin-ui/node_modules +clients/admin-ui/.next +clients/privacy-center/node_modules +clients/privacy-center/.next +clients/hello_world/node_modules +clients/hello_world/.next From 0f72b888afec49c169d248b2539b09d39c5dd08d Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Mon, 6 Jun 2022 15:28:07 -0400 Subject: [PATCH 06/19] Fix file path --- clients/admin-ui/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/admin-ui/package.json b/clients/admin-ui/package.json index e5f873b62..427a94f68 100644 --- a/clients/admin-ui/package.json +++ b/clients/admin-ui/package.json @@ -13,7 +13,7 @@ "analyze:server": "cross-env BUNDLE_ANALYZE=server next build", "analyze:browser": "cross-env BUNDLE_ANALYZE=browser next build", "export": "next build && next export", - "copy-export": "rsync -a --delete out/ ../../src/fidesapi/build/static/", + "copy-export": "rsync -a --delete out/ ../../src/fidesops/build/static/", "prod-export": "npm run export && npm run copy-export" }, "dependencies": { From f0b0126424e3298317870e3c31114efa8c0ec63e Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Tue, 7 Jun 2022 11:36:55 -0400 Subject: [PATCH 07/19] Update Dockerfile --- Dockerfile | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/Dockerfile b/Dockerfile index a1bcaad7c..4cc317528 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM node:16 as frontend -WORKDIR clients/hello_world +WORKDIR /fidesops/clients/hello_world # install node modules COPY clients/hello_world/ . RUN npm install @@ -9,7 +9,7 @@ RUN npm install RUN npm run export -FROM --platform=linux/amd64 python:3.9.13-slim-buster as backend +FROM --platform=linux/amd64 python:3.9.6-slim-buster as backend ARG MSSQL_REQUIRED @@ -50,18 +50,16 @@ RUN pip install -U pip \ RUN if [ "$MSSQL_REQUIRED" = "true" ] ; then pip install -U pip -r mssql-requirements.txt ; fi -RUN pwd -# Make a static files directory -RUN mkdir -p src/fidesops/build/static -# Copy frontend build over -COPY --from=frontend clients/hello_world/out/ src/fidesops/build/static/ - # Copy in the application files and install it locally COPY . /fidesops WORKDIR /fidesops RUN pip install -e . +# Make a static files directory +RUN mkdir -p /fidesops/src/fidesops/build/static/ +# Copy frontend build over +COPY --from=frontend /fidesops/clients/hello_world/out/ /fidesops/src/fidesops/build/static/ +CMD [ "fidesops", "webserver" ] -CMD [ "fidesops", "webserver" ] \ No newline at end of file From a07c9ba2bd015b00d66f34b386bfc385fb90ae4a Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Wed, 8 Jun 2022 16:00:06 -0400 Subject: [PATCH 08/19] Add admin ui config model --- fidesops.toml | 3 +++ src/fidesops/core/config.py | 10 ++++++++++ src/fidesops/main.py | 19 ++++++++++--------- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/fidesops.toml b/fidesops.toml index a098b6789..18c820254 100644 --- a/fidesops.toml +++ b/fidesops.toml @@ -37,3 +37,6 @@ MASKING_STRICT = true [root_user] ANALYTICS_OPT_OUT = false + +[admin_ui] +ENABLED = true \ No newline at end of file diff --git a/src/fidesops/core/config.py b/src/fidesops/core/config.py index 4e44d8de6..5a6ca83d2 100644 --- a/src/fidesops/core/config.py +++ b/src/fidesops/core/config.py @@ -249,6 +249,15 @@ class Config: env_prefix = "FIDESOPS__ROOT_USER__" +class AdminUiSettings(FidesSettings): + """Configuration settings for Analytics variables.""" + + ENABLED: bool + + class Config: + env_prefix = "FIDESOPS__ADMINUI__" + + class FidesopsConfig(FidesSettings): """Configuration variables for the FastAPI project""" @@ -258,6 +267,7 @@ class FidesopsConfig(FidesSettings): security: SecuritySettings execution: ExecutionSettings root_user: RootUserSettings + admin_ui: AdminUiSettings PORT: int is_test_mode: bool = os.getenv("TESTING") == "True" diff --git a/src/fidesops/main.py b/src/fidesops/main.py index 48272b02e..3a55a325a 100644 --- a/src/fidesops/main.py +++ b/src/fidesops/main.py @@ -48,15 +48,16 @@ @app.on_event("startup") async def create_webapp_dir_if_not_exists() -> None: """Creates the webapp directory if it doesn't exist.""" - WEBAPP_DIRECTORY = Path("src/fidesops/build/static") - WEBAPP_INDEX = WEBAPP_DIRECTORY / "index.html" - if not WEBAPP_INDEX.is_file(): - WEBAPP_DIRECTORY.mkdir(parents=True, exist_ok=True) - with open(WEBAPP_DIRECTORY / "index.html", "w") as index_file: - index_file.write("

Privacy is a Human Right!

") - - app.mount("/static", StaticFiles(directory=WEBAPP_DIRECTORY), name="static") - logger.info("Mounted static file directory...") + if config.admin_ui.ENABLED: + WEBAPP_DIRECTORY = Path("src/fidesops/build/static") + WEBAPP_INDEX = WEBAPP_DIRECTORY / "index.html" + if not WEBAPP_INDEX.is_file(): + WEBAPP_DIRECTORY.mkdir(parents=True, exist_ok=True) + with open(WEBAPP_DIRECTORY / "index.html", "w") as index_file: + index_file.write("

Privacy is a Human Right!

") + + app.mount("/static", StaticFiles(directory=WEBAPP_DIRECTORY), name="static") + logger.info("Mounted static file directory...") def start_webserver() -> None: From 3c67fc1301d795f8e0e4e16b3e645a1908032aed Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Thu, 9 Jun 2022 12:15:51 -0400 Subject: [PATCH 09/19] Conditionally build the UI --- Dockerfile | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index a18579feb..3bc28ea53 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,15 @@ FROM node:16 as frontend -WORKDIR /fidesops/clients/hello_world +RUN if [ "$FIDESOPS__ADMINUI__ENABLED" = "true" ] ; then WORKDIR /fidesops/clients/hello_world ; fi # install node modules -COPY clients/hello_world/ . -RUN npm install +RUN if [ "$FIDESOPS__ADMINUI__ENABLED" = "true" ] ; then COPY clients/hello_world/ . ; fi +RUN if [ "$FIDESOPS__ADMINUI__ENABLED" = "true" ] ; then npm install ; fi # Build the frontend static files -RUN npm run export +RUN if [ "$FIDESOPS__ADMINUI__ENABLED" = "true" ] ; then npm run export ; fi + +# Seed empty directory so copy works in the next layer +RUN if [ "$FIDESOPS__ADMINUI__ENABLED" != "true" ] ; then mkdir -p /fidesops/clients/hello_world/out/ ; fi FROM --platform=linux/amd64 python:3.9.6-slim-buster as backend @@ -57,7 +60,7 @@ RUN pip install -e . # Make a static files directory RUN mkdir -p /fidesops/src/fidesops/build/static/ -# Copy frontend build over +# Copy frontend build over. If UI is toggled off this copies over an empty folder COPY --from=frontend /fidesops/clients/hello_world/out/ /fidesops/src/fidesops/build/static/ # Enable detection of running within Docker From 0be87a49110ef2f46856bbd6743f8feb669b1634 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Thu, 9 Jun 2022 12:16:04 -0400 Subject: [PATCH 10/19] Fix env_prefix --- src/fidesops/core/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fidesops/core/config.py b/src/fidesops/core/config.py index 5a6ca83d2..dc0256c05 100644 --- a/src/fidesops/core/config.py +++ b/src/fidesops/core/config.py @@ -255,7 +255,7 @@ class AdminUiSettings(FidesSettings): ENABLED: bool class Config: - env_prefix = "FIDESOPS__ADMINUI__" + env_prefix = "FIDESOPS__ADMIN_UI__" class FidesopsConfig(FidesSettings): From d3c8205a56c9eae5d4bf5c5d8482324e562fd315 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Thu, 9 Jun 2022 12:17:47 -0400 Subject: [PATCH 11/19] Remove hello_world placeholder --- .dockerignore | 2 -- Dockerfile | 8 ++++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.dockerignore b/.dockerignore index d67925787..f02cf8797 100644 --- a/.dockerignore +++ b/.dockerignore @@ -9,5 +9,3 @@ clients/admin-ui/node_modules clients/admin-ui/.next clients/privacy-center/node_modules clients/privacy-center/.next -clients/hello_world/node_modules -clients/hello_world/.next diff --git a/Dockerfile b/Dockerfile index 3bc28ea53..9f2148357 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,15 +1,15 @@ FROM node:16 as frontend -RUN if [ "$FIDESOPS__ADMINUI__ENABLED" = "true" ] ; then WORKDIR /fidesops/clients/hello_world ; fi +RUN if [ "$FIDESOPS__ADMINUI__ENABLED" = "true" ] ; then WORKDIR /fidesops/clients/admin-ui ; fi # install node modules -RUN if [ "$FIDESOPS__ADMINUI__ENABLED" = "true" ] ; then COPY clients/hello_world/ . ; fi +RUN if [ "$FIDESOPS__ADMINUI__ENABLED" = "true" ] ; then COPY clients/admin-ui/ . ; fi RUN if [ "$FIDESOPS__ADMINUI__ENABLED" = "true" ] ; then npm install ; fi # Build the frontend static files RUN if [ "$FIDESOPS__ADMINUI__ENABLED" = "true" ] ; then npm run export ; fi # Seed empty directory so copy works in the next layer -RUN if [ "$FIDESOPS__ADMINUI__ENABLED" != "true" ] ; then mkdir -p /fidesops/clients/hello_world/out/ ; fi +RUN if [ "$FIDESOPS__ADMINUI__ENABLED" != "true" ] ; then mkdir -p /fidesops/clients/admin-ui/out/ ; fi FROM --platform=linux/amd64 python:3.9.6-slim-buster as backend @@ -61,7 +61,7 @@ RUN pip install -e . # Make a static files directory RUN mkdir -p /fidesops/src/fidesops/build/static/ # Copy frontend build over. If UI is toggled off this copies over an empty folder -COPY --from=frontend /fidesops/clients/hello_world/out/ /fidesops/src/fidesops/build/static/ +COPY --from=frontend /fidesops/clients/admin-ui/out/ /fidesops/src/fidesops/build/static/ # Enable detection of running within Docker ENV RUNNING_IN_DOCKER=true From ef24232120074347011d717ae32d9fd10aabd3f5 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Thu, 9 Jun 2022 15:47:07 -0400 Subject: [PATCH 12/19] Remove if logic from Dockerfile --- Dockerfile | 15 +++++---------- clients/admin-ui/.env.development | 1 - clients/admin-ui/src/types/environment.d.ts | 10 ---------- 3 files changed, 5 insertions(+), 21 deletions(-) delete mode 100644 clients/admin-ui/.env.development delete mode 100644 clients/admin-ui/src/types/environment.d.ts diff --git a/Dockerfile b/Dockerfile index 9f2148357..2b74b8a70 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,15 +1,10 @@ FROM node:16 as frontend -RUN if [ "$FIDESOPS__ADMINUI__ENABLED" = "true" ] ; then WORKDIR /fidesops/clients/admin-ui ; fi -# install node modules -RUN if [ "$FIDESOPS__ADMINUI__ENABLED" = "true" ] ; then COPY clients/admin-ui/ . ; fi -RUN if [ "$FIDESOPS__ADMINUI__ENABLED" = "true" ] ; then npm install ; fi - +WORKDIR /fidesops/clients/admin-ui +COPY clients/admin-ui/ . +RUN npm install # Build the frontend static files -RUN if [ "$FIDESOPS__ADMINUI__ENABLED" = "true" ] ; then npm run export ; fi - -# Seed empty directory so copy works in the next layer -RUN if [ "$FIDESOPS__ADMINUI__ENABLED" != "true" ] ; then mkdir -p /fidesops/clients/admin-ui/out/ ; fi +RUN npm run export FROM --platform=linux/amd64 python:3.9.6-slim-buster as backend @@ -60,7 +55,7 @@ RUN pip install -e . # Make a static files directory RUN mkdir -p /fidesops/src/fidesops/build/static/ -# Copy frontend build over. If UI is toggled off this copies over an empty folder +# Copy frontend build over COPY --from=frontend /fidesops/clients/admin-ui/out/ /fidesops/src/fidesops/build/static/ # Enable detection of running within Docker diff --git a/clients/admin-ui/.env.development b/clients/admin-ui/.env.development deleted file mode 100644 index cc988907f..000000000 --- a/clients/admin-ui/.env.development +++ /dev/null @@ -1 +0,0 @@ -NEXT_PUBLIC_FIDESOPS_API=http://0.0.0.0:8080/api/v1 \ No newline at end of file diff --git a/clients/admin-ui/src/types/environment.d.ts b/clients/admin-ui/src/types/environment.d.ts deleted file mode 100644 index ea6b3b4a3..000000000 --- a/clients/admin-ui/src/types/environment.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -declare global { - namespace NodeJS { - interface ProcessEnv { - NEXT_PUBLIC_AUTH_ENDPOINT: string; - NODE_ENV: 'development' | 'production'; - PORT?: string; - PWD: string; - } - } -} From d9952d37762647e9635c4bf66fcbc7c0e0b02432 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Thu, 9 Jun 2022 16:11:46 -0400 Subject: [PATCH 13/19] Fix issues with BASE_URL --- clients/admin-ui/src/constants.ts | 2 ++ clients/admin-ui/src/features/auth/auth.slice.ts | 4 ++-- clients/admin-ui/src/features/common/Header.tsx | 3 ++- .../features/privacy-requests/privacy-requests.slice.ts | 7 +++---- .../src/features/user-management/user-management.slice.ts | 3 ++- clients/admin-ui/src/pages/index.tsx | 3 ++- 6 files changed, 13 insertions(+), 9 deletions(-) diff --git a/clients/admin-ui/src/constants.ts b/clients/admin-ui/src/constants.ts index ac7d1c561..684be8644 100644 --- a/clients/admin-ui/src/constants.ts +++ b/clients/admin-ui/src/constants.ts @@ -1,5 +1,7 @@ import { UserPrivileges } from './features/user-management/types'; +export const BASE_URL = '/api/v1'; + export const STORED_CREDENTIALS_KEY = 'auth.fidesops-admin-ui'; export const USER_PRIVILEGES: UserPrivileges[] = [ diff --git a/clients/admin-ui/src/features/auth/auth.slice.ts b/clients/admin-ui/src/features/auth/auth.slice.ts index 87d44fa3a..3762d51bd 100644 --- a/clients/admin-ui/src/features/auth/auth.slice.ts +++ b/clients/admin-ui/src/features/auth/auth.slice.ts @@ -6,7 +6,7 @@ import { import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; import type { RootState } from '../../app/store'; -import { STORED_CREDENTIALS_KEY } from '../../constants'; +import { BASE_URL, STORED_CREDENTIALS_KEY } from '../../constants'; import { User } from '../user-management/types'; import { LoginRequest, LoginResponse } from './types'; @@ -74,7 +74,7 @@ credentialStorage.startListening({ export const authApi = createApi({ reducerPath: 'authApi', baseQuery: fetchBaseQuery({ - baseUrl: process.env.NEXT_PUBLIC_FIDESOPS_API!, + baseUrl: BASE_URL, prepareHeaders: (headers, { getState }) => { const token = selectToken(getState() as RootState); headers.set('Access-Control-Allow-Origin', '*'); diff --git a/clients/admin-ui/src/features/common/Header.tsx b/clients/admin-ui/src/features/common/Header.tsx index 265d30393..1bb45bc35 100644 --- a/clients/admin-ui/src/features/common/Header.tsx +++ b/clients/admin-ui/src/features/common/Header.tsx @@ -17,6 +17,7 @@ import { useDispatch, useSelector } from 'react-redux'; import { logout, selectUser } from '../auth'; import { UserIcon } from './Icon'; import Image from './Image'; +import { BASE_URL } from "../../constants" const useHeader = () => { const dispatch = useDispatch(); @@ -43,7 +44,7 @@ const Header: React.FC = () => { {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} - FidesOps Logo + FidesOps Logo diff --git a/clients/admin-ui/src/features/privacy-requests/privacy-requests.slice.ts b/clients/admin-ui/src/features/privacy-requests/privacy-requests.slice.ts index ded4e8671..e097ed1f6 100644 --- a/clients/admin-ui/src/features/privacy-requests/privacy-requests.slice.ts +++ b/clients/admin-ui/src/features/privacy-requests/privacy-requests.slice.ts @@ -2,6 +2,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; import type { RootState } from '../../app/store'; +import { BASE_URL } from '../../constants'; import { selectToken } from '../auth'; import { DenyPrivacyRequest, @@ -49,7 +50,7 @@ export function mapFiltersToSearchParams({ export const privacyRequestApi = createApi({ reducerPath: 'privacyRequestApi', baseQuery: fetchBaseQuery({ - baseUrl: process.env.NEXT_PUBLIC_FIDESOPS_API!, + baseUrl: BASE_URL, prepareHeaders: (headers, { getState }) => { const token = selectToken(getState() as RootState); headers.set('Access-Control-Allow-Origin', '*'); @@ -116,9 +117,7 @@ export const requestCSVDownload = async ({ } return fetch( - `${ - process.env.NEXT_PUBLIC_FIDESOPS_API - }/privacy-request?${new URLSearchParams({ + `${BASE_URL}/privacy-request?${new URLSearchParams({ ...mapFiltersToSearchParams({ id, from, diff --git a/clients/admin-ui/src/features/user-management/user-management.slice.ts b/clients/admin-ui/src/features/user-management/user-management.slice.ts index fdb05f307..f55310c44 100644 --- a/clients/admin-ui/src/features/user-management/user-management.slice.ts +++ b/clients/admin-ui/src/features/user-management/user-management.slice.ts @@ -2,6 +2,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; import type { RootState } from '../../app/store'; +import { BASE_URL } from '../../constants'; import { selectToken } from '../auth'; import { User, @@ -78,7 +79,7 @@ export const mapFiltersToSearchParams = ({ export const userApi = createApi({ reducerPath: 'userApi', baseQuery: fetchBaseQuery({ - baseUrl: process.env.NEXT_PUBLIC_FIDESOPS_API!, + baseUrl: BASE_URL, prepareHeaders: (headers, { getState }) => { const token = selectToken(getState() as RootState); headers.set('Access-Control-Allow-Origin', '*'); diff --git a/clients/admin-ui/src/pages/index.tsx b/clients/admin-ui/src/pages/index.tsx index b52ae60aa..615e4c507 100644 --- a/clients/admin-ui/src/pages/index.tsx +++ b/clients/admin-ui/src/pages/index.tsx @@ -2,6 +2,7 @@ import { Box, Heading } from '@fidesui/react'; import type { NextPage } from 'next'; import Head from 'next/head'; +import { BASE_URL } from '../constants'; import ProtectedRoute from '../features/auth/ProtectedRoute'; import NavBar from '../features/common/NavBar'; import RequestFilters from '../features/privacy-requests/RequestFilters'; @@ -13,7 +14,7 @@ const Home: NextPage = () => ( Fides Admin UI - + From d03d0032d27a36f00599efdc6ae3650ef7f7eb2d Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Thu, 9 Jun 2022 18:20:07 -0400 Subject: [PATCH 14/19] Refactor Head into component & update URNs --- clients/admin-ui/src/constants.ts | 3 ++- .../admin-ui/src/features/auth/auth.slice.ts | 4 ++-- clients/admin-ui/src/features/common/Head.tsx | 18 ++++++++++++++++++ .../admin-ui/src/features/common/Header.tsx | 4 ++-- .../privacy-requests/privacy-requests.slice.ts | 6 +++--- .../user-management/user-management.slice.ts | 4 ++-- clients/admin-ui/src/pages/404.tsx | 9 ++------- clients/admin-ui/src/pages/index.tsx | 10 ++-------- clients/admin-ui/src/pages/login.tsx | 11 ++--------- .../src/pages/subject-request/[id].tsx | 10 +++------- .../src/pages/user-management/index.tsx | 8 ++------ 11 files changed, 40 insertions(+), 47 deletions(-) create mode 100644 clients/admin-ui/src/features/common/Head.tsx diff --git a/clients/admin-ui/src/constants.ts b/clients/admin-ui/src/constants.ts index 684be8644..4c7058b79 100644 --- a/clients/admin-ui/src/constants.ts +++ b/clients/admin-ui/src/constants.ts @@ -1,6 +1,7 @@ import { UserPrivileges } from './features/user-management/types'; -export const BASE_URL = '/api/v1'; +export const BASE_API_URN = '/api/v1'; +export const BASE_ASSET_URN = '/static'; export const STORED_CREDENTIALS_KEY = 'auth.fidesops-admin-ui'; diff --git a/clients/admin-ui/src/features/auth/auth.slice.ts b/clients/admin-ui/src/features/auth/auth.slice.ts index 3762d51bd..ade09a94c 100644 --- a/clients/admin-ui/src/features/auth/auth.slice.ts +++ b/clients/admin-ui/src/features/auth/auth.slice.ts @@ -6,7 +6,7 @@ import { import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; import type { RootState } from '../../app/store'; -import { BASE_URL, STORED_CREDENTIALS_KEY } from '../../constants'; +import { BASE_API_URN, STORED_CREDENTIALS_KEY } from '../../constants'; import { User } from '../user-management/types'; import { LoginRequest, LoginResponse } from './types'; @@ -74,7 +74,7 @@ credentialStorage.startListening({ export const authApi = createApi({ reducerPath: 'authApi', baseQuery: fetchBaseQuery({ - baseUrl: BASE_URL, + baseUrl: BASE_API_URN, prepareHeaders: (headers, { getState }) => { const token = selectToken(getState() as RootState); headers.set('Access-Control-Allow-Origin', '*'); diff --git a/clients/admin-ui/src/features/common/Head.tsx b/clients/admin-ui/src/features/common/Head.tsx new file mode 100644 index 000000000..33bda2053 --- /dev/null +++ b/clients/admin-ui/src/features/common/Head.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import Head from 'next/head'; +import {BASE_ASSET_URN} from "../../constants" + + + +const FidesHead = () => { + + return( + + fidesops + + + + ); +}; + +export default FidesHead; diff --git a/clients/admin-ui/src/features/common/Header.tsx b/clients/admin-ui/src/features/common/Header.tsx index 1bb45bc35..a88c8b8ef 100644 --- a/clients/admin-ui/src/features/common/Header.tsx +++ b/clients/admin-ui/src/features/common/Header.tsx @@ -17,7 +17,7 @@ import { useDispatch, useSelector } from 'react-redux'; import { logout, selectUser } from '../auth'; import { UserIcon } from './Icon'; import Image from './Image'; -import { BASE_URL } from "../../constants" +import { BASE_ASSET_URN } from "../../constants" const useHeader = () => { const dispatch = useDispatch(); @@ -44,7 +44,7 @@ const Header: React.FC = () => { {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} - FidesOps Logo + FidesOps Logo diff --git a/clients/admin-ui/src/features/privacy-requests/privacy-requests.slice.ts b/clients/admin-ui/src/features/privacy-requests/privacy-requests.slice.ts index e097ed1f6..ec4fe50ee 100644 --- a/clients/admin-ui/src/features/privacy-requests/privacy-requests.slice.ts +++ b/clients/admin-ui/src/features/privacy-requests/privacy-requests.slice.ts @@ -2,7 +2,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; import type { RootState } from '../../app/store'; -import { BASE_URL } from '../../constants'; +import { BASE_API_URN } from '../../constants'; import { selectToken } from '../auth'; import { DenyPrivacyRequest, @@ -50,7 +50,7 @@ export function mapFiltersToSearchParams({ export const privacyRequestApi = createApi({ reducerPath: 'privacyRequestApi', baseQuery: fetchBaseQuery({ - baseUrl: BASE_URL, + baseUrl: BASE_API_URN, prepareHeaders: (headers, { getState }) => { const token = selectToken(getState() as RootState); headers.set('Access-Control-Allow-Origin', '*'); @@ -117,7 +117,7 @@ export const requestCSVDownload = async ({ } return fetch( - `${BASE_URL}/privacy-request?${new URLSearchParams({ + `${BASE_API_URN}/privacy-request?${new URLSearchParams({ ...mapFiltersToSearchParams({ id, from, diff --git a/clients/admin-ui/src/features/user-management/user-management.slice.ts b/clients/admin-ui/src/features/user-management/user-management.slice.ts index f55310c44..b4a3bd8e9 100644 --- a/clients/admin-ui/src/features/user-management/user-management.slice.ts +++ b/clients/admin-ui/src/features/user-management/user-management.slice.ts @@ -2,7 +2,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; import type { RootState } from '../../app/store'; -import { BASE_URL } from '../../constants'; +import { BASE_API_URN } from '../../constants'; import { selectToken } from '../auth'; import { User, @@ -79,7 +79,7 @@ export const mapFiltersToSearchParams = ({ export const userApi = createApi({ reducerPath: 'userApi', baseQuery: fetchBaseQuery({ - baseUrl: BASE_URL, + baseUrl: BASE_API_URN, prepareHeaders: (headers, { getState }) => { const token = selectToken(getState() as RootState); headers.set('Access-Control-Allow-Origin', '*'); diff --git a/clients/admin-ui/src/pages/404.tsx b/clients/admin-ui/src/pages/404.tsx index eaef1049e..7090f1bd8 100644 --- a/clients/admin-ui/src/pages/404.tsx +++ b/clients/admin-ui/src/pages/404.tsx @@ -1,16 +1,11 @@ import { Box, Button, Heading, Stack, Text } from '@fidesui/react'; -import Head from 'next/head'; import NextLink from 'next/link'; - +import Head from '../features/common/Head' import Image from '../features/common/Image'; const Custom404 = () => (
- - FidesUI App - - - +
diff --git a/clients/admin-ui/src/pages/index.tsx b/clients/admin-ui/src/pages/index.tsx index 615e4c507..cd6bc16b4 100644 --- a/clients/admin-ui/src/pages/index.tsx +++ b/clients/admin-ui/src/pages/index.tsx @@ -1,22 +1,16 @@ import { Box, Heading } from '@fidesui/react'; import type { NextPage } from 'next'; -import Head from 'next/head'; -import { BASE_URL } from '../constants'; import ProtectedRoute from '../features/auth/ProtectedRoute'; import NavBar from '../features/common/NavBar'; import RequestFilters from '../features/privacy-requests/RequestFilters'; import RequestTable from '../features/privacy-requests/RequestTable'; +import Head from '../features/common/Head' const Home: NextPage = () => ( <> - - Fides Admin UI - - - - +
diff --git a/clients/admin-ui/src/pages/login.tsx b/clients/admin-ui/src/pages/login.tsx index 0a62d6561..69a590bf2 100644 --- a/clients/admin-ui/src/pages/login.tsx +++ b/clients/admin-ui/src/pages/login.tsx @@ -13,13 +13,13 @@ import { } from '@fidesui/react'; import { Formik } from 'formik'; import type { NextPage } from 'next'; -import Head from 'next/head'; import { useRouter } from 'next/router'; import React from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { login, selectToken, useLoginMutation } from '../features/auth'; import Image from '../features/common/Image'; +import Head from '../features/common/Head'; const useLogin = () => { const [loginRequest, { isLoading }] = useLoginMutation(); @@ -94,14 +94,7 @@ const Login: NextPage = () => { values, }) => (
- - FidesUI App - - - +
{ const router = useRouter(); @@ -49,11 +49,7 @@ const SubjectRequestDetails: NextPage = () => { return (
- - Fides Admin UI - Subject Request Details - - - + diff --git a/clients/admin-ui/src/pages/user-management/index.tsx b/clients/admin-ui/src/pages/user-management/index.tsx index 812afc0ab..c8da36409 100644 --- a/clients/admin-ui/src/pages/user-management/index.tsx +++ b/clients/admin-ui/src/pages/user-management/index.tsx @@ -1,21 +1,17 @@ import { Box, Heading } from '@fidesui/react'; import type { NextPage } from 'next'; -import Head from 'next/head'; import React from 'react'; import ProtectedRoute from '../../features/auth/ProtectedRoute'; import NavBar from '../../features/common/NavBar'; import UserManagementTable from '../../features/user-management/UserManagementTable'; import UserManagementTableActions from '../../features/user-management/UserManagementTableActions'; +import Head from '../../features/common/Head' const UserManagement: NextPage = () => (
- - Fides Admin UI - User Management - - - + From f0985cf16c32bdb434c3c1f5ac78f8f97640c804 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Thu, 9 Jun 2022 18:22:40 -0400 Subject: [PATCH 15/19] Fix import order --- clients/admin-ui/src/features/common/Head.tsx | 8 +++----- clients/admin-ui/src/features/common/Header.tsx | 2 +- clients/admin-ui/src/pages/404.tsx | 1 + clients/admin-ui/src/pages/index.tsx | 2 +- clients/admin-ui/src/pages/login.tsx | 2 +- clients/admin-ui/src/pages/subject-request/[id].tsx | 4 ++-- clients/admin-ui/src/pages/user-management/index.tsx | 2 +- 7 files changed, 10 insertions(+), 11 deletions(-) diff --git a/clients/admin-ui/src/features/common/Head.tsx b/clients/admin-ui/src/features/common/Head.tsx index 33bda2053..6f3ace6ec 100644 --- a/clients/admin-ui/src/features/common/Head.tsx +++ b/clients/admin-ui/src/features/common/Head.tsx @@ -1,18 +1,16 @@ -import React from 'react'; import Head from 'next/head'; -import {BASE_ASSET_URN} from "../../constants" +import React from 'react'; +import {BASE_ASSET_URN} from "../../constants" -const FidesHead = () => { - return( +const FidesHead = () => ( fidesops ); -}; export default FidesHead; diff --git a/clients/admin-ui/src/features/common/Header.tsx b/clients/admin-ui/src/features/common/Header.tsx index a88c8b8ef..bb9fd52b8 100644 --- a/clients/admin-ui/src/features/common/Header.tsx +++ b/clients/admin-ui/src/features/common/Header.tsx @@ -14,10 +14,10 @@ import NextLink from 'next/link'; import React from 'react'; import { useDispatch, useSelector } from 'react-redux'; +import { BASE_ASSET_URN } from "../../constants" import { logout, selectUser } from '../auth'; import { UserIcon } from './Icon'; import Image from './Image'; -import { BASE_ASSET_URN } from "../../constants" const useHeader = () => { const dispatch = useDispatch(); diff --git a/clients/admin-ui/src/pages/404.tsx b/clients/admin-ui/src/pages/404.tsx index 7090f1bd8..3884dbb1d 100644 --- a/clients/admin-ui/src/pages/404.tsx +++ b/clients/admin-ui/src/pages/404.tsx @@ -1,5 +1,6 @@ import { Box, Button, Heading, Stack, Text } from '@fidesui/react'; import NextLink from 'next/link'; + import Head from '../features/common/Head' import Image from '../features/common/Image'; diff --git a/clients/admin-ui/src/pages/index.tsx b/clients/admin-ui/src/pages/index.tsx index cd6bc16b4..2b1186772 100644 --- a/clients/admin-ui/src/pages/index.tsx +++ b/clients/admin-ui/src/pages/index.tsx @@ -2,10 +2,10 @@ import { Box, Heading } from '@fidesui/react'; import type { NextPage } from 'next'; import ProtectedRoute from '../features/auth/ProtectedRoute'; +import Head from '../features/common/Head' import NavBar from '../features/common/NavBar'; import RequestFilters from '../features/privacy-requests/RequestFilters'; import RequestTable from '../features/privacy-requests/RequestTable'; -import Head from '../features/common/Head' const Home: NextPage = () => ( diff --git a/clients/admin-ui/src/pages/login.tsx b/clients/admin-ui/src/pages/login.tsx index 69a590bf2..845c33b38 100644 --- a/clients/admin-ui/src/pages/login.tsx +++ b/clients/admin-ui/src/pages/login.tsx @@ -18,8 +18,8 @@ import React from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { login, selectToken, useLoginMutation } from '../features/auth'; -import Image from '../features/common/Image'; import Head from '../features/common/Head'; +import Image from '../features/common/Image'; const useLogin = () => { const [loginRequest, { isLoading }] = useLoginMutation(); diff --git a/clients/admin-ui/src/pages/subject-request/[id].tsx b/clients/admin-ui/src/pages/subject-request/[id].tsx index 7ff248cc6..e3905dee8 100644 --- a/clients/admin-ui/src/pages/subject-request/[id].tsx +++ b/clients/admin-ui/src/pages/subject-request/[id].tsx @@ -7,15 +7,15 @@ import { Spinner, Text, } from '@fidesui/react'; -import type { NextPage } from 'next';; +import type { NextPage } from 'next'; import { useRouter } from 'next/router'; import React from 'react'; import ProtectedRoute from '../../features/auth/ProtectedRoute'; +import Head from '../../features/common/Head'; import NavBar from '../../features/common/NavBar'; import { useGetAllPrivacyRequestsQuery } from '../../features/privacy-requests'; import SubjectRequest from '../../features/subject-request/SubjectRequest'; -import Head from '../../features/common/Head' const useSubjectRequestDetails = () => { const router = useRouter(); diff --git a/clients/admin-ui/src/pages/user-management/index.tsx b/clients/admin-ui/src/pages/user-management/index.tsx index c8da36409..a228ff306 100644 --- a/clients/admin-ui/src/pages/user-management/index.tsx +++ b/clients/admin-ui/src/pages/user-management/index.tsx @@ -3,10 +3,10 @@ import type { NextPage } from 'next'; import React from 'react'; import ProtectedRoute from '../../features/auth/ProtectedRoute'; +import Head from '../../features/common/Head' import NavBar from '../../features/common/NavBar'; import UserManagementTable from '../../features/user-management/UserManagementTable'; import UserManagementTableActions from '../../features/user-management/UserManagementTableActions'; -import Head from '../../features/common/Head' const UserManagement: NextPage = () => ( From 73ab9c69f90fd0b78bdac9a80dae4e9df955a0ad Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Thu, 9 Jun 2022 18:42:32 -0400 Subject: [PATCH 16/19] Update test URL path --- clients/admin-ui/__tests__/pages/login.test.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clients/admin-ui/__tests__/pages/login.test.tsx b/clients/admin-ui/__tests__/pages/login.test.tsx index 1538ad875..c3384394e 100644 --- a/clients/admin-ui/__tests__/pages/login.test.tsx +++ b/clients/admin-ui/__tests__/pages/login.test.tsx @@ -1,6 +1,7 @@ import { rest } from 'msw'; import { setupServer } from 'msw/node'; +import { BASE_API_URN } from '../../src/constants' import LoginPage from '../../src/pages/login'; import { act, fireEvent, render, screen, waitFor } from '../test-utils'; @@ -13,7 +14,7 @@ afterAll(() => { describe('/login', () => { it('Should redirect when the user logs in successfully', async () => { const server = setupServer( - rest.post(`/login`, (req, res, ctx) => + rest.post(`${BASE_API_URN}/login`, (req, res, ctx) => res( ctx.json({ user_data: { From 18e7eb9fb7bc519642a54c6927c4197e91379065 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Fri, 10 Jun 2022 08:42:38 -0400 Subject: [PATCH 17/19] Fix isort lint issue --- src/fidesops/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fidesops/main.py b/src/fidesops/main.py index 3a55a325a..a60266350 100644 --- a/src/fidesops/main.py +++ b/src/fidesops/main.py @@ -1,5 +1,6 @@ import logging from datetime import datetime, timezone +from pathlib import Path import uvicorn from fastapi import FastAPI @@ -22,7 +23,6 @@ from fidesops.tasks.scheduled.scheduler import scheduler from fidesops.tasks.scheduled.tasks import initiate_scheduled_request_intake from fidesops.util.logger import get_fides_log_record_factory -from pathlib import Path logging.basicConfig(level=config.security.LOG_LEVEL) logging.setLogRecordFactory(get_fides_log_record_factory()) From 285030943bce5b50ad7d6f6a688726bea06d0723 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Fri, 10 Jun 2022 09:07:22 -0400 Subject: [PATCH 18/19] Fix unit test failure --- data/config/fidesops.toml | 3 +++ tests/core/test_config.py | 1 + 2 files changed, 4 insertions(+) diff --git a/data/config/fidesops.toml b/data/config/fidesops.toml index 3c143a882..551a2d0e1 100644 --- a/data/config/fidesops.toml +++ b/data/config/fidesops.toml @@ -35,3 +35,6 @@ MASKING_STRICT = true [root_user] ANALYTICS_OPT_OUT = true ANALYTICS_ID = "internal" + +[admin_ui] +ENABLED = true diff --git a/tests/core/test_config.py b/tests/core/test_config.py index 626d8aca3..29fa6b4a6 100644 --- a/tests/core/test_config.py +++ b/tests/core/test_config.py @@ -30,6 +30,7 @@ def test_config_from_path() -> None: assert config.database.SERVER == "testserver" assert config.redis.HOST == "testredis" assert config.security.APP_ENCRYPTION_KEY == "atestencryptionkeythatisvalidlen" + assert config.admin_ui.ENABLED == True @patch.dict( From 69da8634a70cfc0b410c8bba5f556bed7d69bb77 Mon Sep 17 00:00:00 2001 From: Andrew Jackson Date: Fri, 10 Jun 2022 09:38:40 -0400 Subject: [PATCH 19/19] Update docs and changelog --- CHANGELOG.md | 1 + docs/fidesops/docs/guides/configuration_reference.md | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d380b35c..9ddb973c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ The types of changes are: * Restart Graph from Failure [#578](https://github.com/ethyca/fidesops/pull/578) * Redis SSL Support [#611](https://github.com/ethyca/fidesops/pull/611) * Cache and Surface Resume/Restart Instructions [#591](https://github.com/ethyca/fidesops/pull/591) +* Build and deploy Admin UI from webserver [#625](https://github.com/ethyca/fidesops/pull/625) ### Changed diff --git a/docs/fidesops/docs/guides/configuration_reference.md b/docs/fidesops/docs/guides/configuration_reference.md index 2a34e188d..c13a66da8 100644 --- a/docs/fidesops/docs/guides/configuration_reference.md +++ b/docs/fidesops/docs/guides/configuration_reference.md @@ -60,8 +60,8 @@ The `fidesops.toml` file should specify the following variables: |`MASKING_STRICT` | `FIDESOPS__EXECUTION__MASKING_STRICT` | bool | True | True | If MASKING_STRICT is True, we only use "update" requests to mask data. (For third-party integrations, you should define an `update` endpoint to use.) If MASKING_STRICT is False, you are allowing fidesops to use any defined DELETE or GDPR DELETE endpoints to remove PII. In this case, you should define `delete` or `data_protection_request` endpoints for your third-party integrations. Note that setting MASKING_STRICT to False means that data may be deleted beyond the specific data categories that you've configured in your Policy. |---|---|---|---|---|---| |`ANALYTICS_OPT_OUT` | `FIDESOPS__USER__ANALYTICS_OPT_OUT` | bool | False | False | Opt out of sending anonymous usage data to Ethyca to improve the product experience - - +| Admin UI Variables|---|---|---|---|---| +|`ENABLED` | `FIDESOPS__ADMIN_UI__ENABLED` | bool | False | True | Toggle whether the `/static` file directory is mounted to serve the Admin UI ## An example `fidesops.toml` configuration file @@ -101,6 +101,9 @@ MASKING_STRICT=true [root_user] ANALYTICS_OPT_OUT=false + +[admin_ui] +ENABLED = true ``` Please note: The configuration is case-sensitive, so the variables must be specified in UPPERCASE.