From 3a13c8273db2c74b0e9f40f381609b8db8736402 Mon Sep 17 00:00:00 2001 From: --show-origin <tom.meyer@isst.fraunhofer.de> Date: Sun, 3 Dec 2023 01:58:14 -0800 Subject: [PATCH 1/7] feat: added keycloak idp --- DEPENDENCIES_FRONTEND | 62 +- docs/DEVELOPMENT.md | 18 +- docs/README.md | 11 + docs/adminGuide/Admin_Guide.md | 104 + docs/arc42/05_building_block_view.md | 1 + docs/arc42/puml/05-level-0.puml | 11 +- docs/interfaceDoc/Interface_Doc.md | 32 + frontend/.env | 6 + frontend/.env.dockerbuild | 6 + frontend/DEPENDENCIES | 66 +- frontend/package-lock.json | 809 +++++--- frontend/package.json | 7 +- frontend/src/App.vue | 326 ++- frontend/src/config.json | 7 +- frontend/src/main.js | 31 +- frontend/src/router/index.js | 132 +- frontend/src/services/AccessService.js | 51 + frontend/src/services/AuthenticationConfig.js | 42 + .../src/services/AuthenticationService.js | 100 + frontend/src/views/Unauthorized.vue | 31 + local/keycloak/INSTALL.md | 13 + local/keycloak/puris-config/.gitignore | 1 + .../keycloak/puris-config/Catena-X-realm.json | 1773 +++++++++++++++++ .../puris-config/Catena-X-users-0.json | 27 + local/miw/keycloak-setup.json | 52 - 25 files changed, 3080 insertions(+), 639 deletions(-) create mode 100644 docs/adminGuide/Admin_Guide.md create mode 100644 docs/interfaceDoc/Interface_Doc.md create mode 100644 frontend/src/services/AccessService.js create mode 100644 frontend/src/services/AuthenticationConfig.js create mode 100644 frontend/src/services/AuthenticationService.js create mode 100644 frontend/src/views/Unauthorized.vue create mode 100644 local/keycloak/INSTALL.md create mode 100644 local/keycloak/puris-config/.gitignore create mode 100644 local/keycloak/puris-config/Catena-X-realm.json create mode 100644 local/keycloak/puris-config/Catena-X-users-0.json diff --git a/DEPENDENCIES_FRONTEND b/DEPENDENCIES_FRONTEND index 0acae6b3..14658c90 100644 --- a/DEPENDENCIES_FRONTEND +++ b/DEPENDENCIES_FRONTEND @@ -2,7 +2,7 @@ npm/npmjs/-/acorn-jsx/5.3.2, MIT, approved, clearlydefined npm/npmjs/-/acorn-node/1.8.2, Apache-2.0, approved, clearlydefined npm/npmjs/-/acorn-walk/7.2.0, MIT, approved, clearlydefined npm/npmjs/-/acorn/7.4.1, MIT, approved, clearlydefined -npm/npmjs/-/acorn/8.7.1, MIT, approved, clearlydefined +npm/npmjs/-/acorn/8.11.2, MIT, approved, clearlydefined npm/npmjs/-/ajv/6.12.6, MIT, approved, #979 npm/npmjs/-/ansi-regex/5.0.1, MIT, approved, clearlydefined npm/npmjs/-/ansi-styles/4.3.0, MIT, approved, clearlydefined @@ -11,6 +11,7 @@ npm/npmjs/-/arg/5.0.2, MIT, approved, clearlydefined npm/npmjs/-/argparse/2.0.1, Python-2.0, approved, CQ22954 npm/npmjs/-/autoprefixer/10.4.7, MIT, approved, #7494 npm/npmjs/-/balanced-match/1.0.2, MIT, approved, clearlydefined +npm/npmjs/-/base64-js/1.5.1, MIT, approved, clearlydefined npm/npmjs/-/binary-extensions/2.2.0, MIT, approved, clearlydefined npm/npmjs/-/boolbase/1.0.0, ISC, approved, clearlydefined npm/npmjs/-/brace-expansion/1.1.11, MIT, approved, clearlydefined @@ -62,14 +63,12 @@ npm/npmjs/-/escalade/3.1.1, MIT, approved, clearlydefined npm/npmjs/-/escape-string-regexp/4.0.0, MIT, approved, clearlydefined npm/npmjs/-/eslint-config-prettier/8.5.0, MIT, approved, clearlydefined npm/npmjs/-/eslint-plugin-prettier/4.2.1, MIT, approved, clearlydefined -npm/npmjs/-/eslint-plugin-vue/9.1.1, MIT, approved, #5872 -npm/npmjs/-/eslint-scope/7.1.1, BSD-2-Clause, approved, clearlydefined -npm/npmjs/-/eslint-utils/3.0.0, MIT, approved, #2431 -npm/npmjs/-/eslint-visitor-keys/2.1.0, Apache-2.0, approved, #2433 -npm/npmjs/-/eslint-visitor-keys/3.3.0, Apache-2.0, approved, #2696 -npm/npmjs/-/eslint/8.19.0, MIT, approved, #5874 -npm/npmjs/-/espree/9.3.2, BSD-2-Clause AND BSD-3-Clause AND MIT, approved, #2697 -npm/npmjs/-/esquery/1.4.0, BSD-3-Clause, approved, #1100 +npm/npmjs/-/eslint-plugin-vue/9.18.1, MIT, approved, #11440 +npm/npmjs/-/eslint-scope/7.2.2, BSD-2-Clause, approved, #9916 +npm/npmjs/-/eslint-visitor-keys/3.4.3, Apache-2.0, approved, #7729 +npm/npmjs/-/eslint/8.54.0, MIT AND (LGPL-2.0-or-later AND MIT) AND ISC AND OFL-1.1 AND CC-BY-SA-2.0 AND (LicenseRef-scancode-proprietary-license AND MIT), restricted, #11618 +npm/npmjs/-/espree/9.6.1, BSD-2-Clause AND BSD-3-Clause AND MIT AND BSD-2-Clause, approved, #9308 +npm/npmjs/-/esquery/1.5.0, BSD-3-Clause, approved, #7469 npm/npmjs/-/esrecurse/4.3.0, BSD-2-Clause, approved, clearlydefined npm/npmjs/-/estraverse/5.3.0, BSD-2-Clause AND MIT, approved, #1557 npm/npmjs/-/estree-walker/2.0.2, MIT, approved, clearlydefined @@ -82,21 +81,22 @@ npm/npmjs/-/fast-levenshtein/2.0.6, MIT, approved, #2428 npm/npmjs/-/fastq/1.13.0, ISC, approved, clearlydefined npm/npmjs/-/file-entry-cache/6.0.1, MIT, approved, clearlydefined npm/npmjs/-/fill-range/7.0.1, MIT, approved, clearlydefined +npm/npmjs/-/find-up/5.0.0, MIT, approved, clearlydefined npm/npmjs/-/flat-cache/3.0.4, MIT, approved, clearlydefined npm/npmjs/-/flatted/3.2.6, ISC AND (ISC AND MIT), approved, #2430 npm/npmjs/-/fraction.js/4.2.0, MIT, approved, clearlydefined npm/npmjs/-/fs.realpath/1.0.0, ISC, approved, clearlydefined npm/npmjs/-/fsevents/2.3.2, MIT, approved, #2967 npm/npmjs/-/function-bind/1.1.1, MIT, approved, #11063 -npm/npmjs/-/functional-red-black-tree/1.0.1, MIT, approved, clearlydefined npm/npmjs/-/glob-parent/5.1.2, ISC, approved, clearlydefined npm/npmjs/-/glob-parent/6.0.2, ISC, approved, clearlydefined npm/npmjs/-/glob/7.2.3, ISC, approved, clearlydefined -npm/npmjs/-/globals/13.16.0, MIT, approved, clearlydefined +npm/npmjs/-/globals/13.23.0, MIT, approved, clearlydefined npm/npmjs/-/good-listener/1.2.2, MIT, approved, clearlydefined +npm/npmjs/-/graphemer/1.4.0, MIT, approved, clearlydefined npm/npmjs/-/has-flag/4.0.0, MIT, approved, clearlydefined npm/npmjs/-/has/1.0.3, MIT, approved, #10930 -npm/npmjs/-/ignore/5.2.0, MIT, approved, #5907 +npm/npmjs/-/ignore/5.3.0, MIT, approved, #11665 npm/npmjs/-/import-fresh/3.3.0, MIT, approved, clearlydefined npm/npmjs/-/imurmurhash/0.1.4, MIT, approved, clearlydefined npm/npmjs/-/inflight/1.0.6, ISC, approved, clearlydefined @@ -106,12 +106,17 @@ npm/npmjs/-/is-core-module/2.9.0, MIT, approved, clearlydefined npm/npmjs/-/is-extglob/2.1.1, MIT, approved, clearlydefined npm/npmjs/-/is-glob/4.0.3, MIT, approved, clearlydefined npm/npmjs/-/is-number/7.0.0, MIT, approved, clearlydefined +npm/npmjs/-/is-path-inside/3.0.3, MIT, approved, clearlydefined npm/npmjs/-/isexe/2.0.0, ISC, approved, clearlydefined +npm/npmjs/-/js-sha256/0.10.1, MIT, approved, clearlydefined npm/npmjs/-/js-yaml/4.1.0, MIT, approved, clearlydefined npm/npmjs/-/json-schema-traverse/0.4.1, MIT, approved, clearlydefined npm/npmjs/-/json-stable-stringify-without-jsonify/1.0.1, MIT, approved, clearlydefined +npm/npmjs/-/jwt-decode/4.0.0, MIT, approved, clearlydefined +npm/npmjs/-/keycloak-js/23.0.0, Apache-2.0 AND (Apache-2.0 AND GPL-2.0-or-later) AND LicenseRef-scancode-public-domain-disclaimer AND MIT AND (BSD-2-Clause AND BSD-3-Clause AND CC-BY-2.5 AND FSFAP AND MPL-2.0) AND (BSD-3-Clause AND MIT) AND (Apache-2.0 AND LGPL-2.0-or-later) AND (AFL-2.1 AND AFL-3.0 AND LGPL-2.0-only) AND EPL-1.0 AND W3C-19980720 AND LicenseRef-scancode-oasis-ws-security-spec AND W3C AND LicenseRef-scancode-ws-policy-specification AND (Apache-2.0 AND LicenseRef-scancode-bitzi-pd) AND (Apache-2.0 AND MIT) AND (Apache-2.0 AND MIT AND MPL-1.0), restricted, #11737 npm/npmjs/-/levn/0.4.1, MIT, approved, clearlydefined npm/npmjs/-/lilconfig/2.0.5, MIT, approved, clearlydefined +npm/npmjs/-/locate-path/6.0.0, MIT, approved, clearlydefined npm/npmjs/-/lodash.merge/4.6.2, MIT, approved, clearlydefined npm/npmjs/-/lodash/4.17.21, CC0-1.0 AND MIT, approved, #2096 npm/npmjs/-/lru-cache/6.0.0, ISC, approved, clearlydefined @@ -121,7 +126,7 @@ npm/npmjs/-/micromatch/4.0.5, MIT, approved, clearlydefined npm/npmjs/-/minimatch/3.1.2, ISC, approved, clearlydefined npm/npmjs/-/minimist/1.2.6, MIT, approved, #5886 npm/npmjs/-/ms/2.1.2, MIT, approved, #5895 -npm/npmjs/-/nanoid/3.3.4, MIT, approved, #7571 +npm/npmjs/-/nanoid/3.3.7, MIT, approved, #7571 npm/npmjs/-/natural-compare/1.4.0, MIT, approved, clearlydefined npm/npmjs/-/node-releases/2.0.5, MIT, approved, #1954 npm/npmjs/-/normalize-path/3.0.0, MIT, approved, clearlydefined @@ -129,8 +134,11 @@ npm/npmjs/-/normalize-range/0.1.2, MIT, approved, clearlydefined npm/npmjs/-/nth-check/2.1.1, BSD-2-Clause, approved, clearlydefined npm/npmjs/-/object-hash/3.0.0, MIT, approved, clearlydefined npm/npmjs/-/once/1.4.0, ISC, approved, clearlydefined -npm/npmjs/-/optionator/0.9.1, MIT, approved, #9208 +npm/npmjs/-/optionator/0.9.3, MIT, approved, #9208 +npm/npmjs/-/p-limit/3.1.0, MIT, approved, clearlydefined +npm/npmjs/-/p-locate/5.0.0, MIT, approved, clearlydefined npm/npmjs/-/parent-module/1.0.1, MIT, approved, clearlydefined +npm/npmjs/-/path-exists/4.0.0, MIT, approved, clearlydefined npm/npmjs/-/path-is-absolute/1.0.1, MIT, approved, clearlydefined npm/npmjs/-/path-key/3.1.1, MIT, approved, clearlydefined npm/npmjs/-/path-parse/1.0.7, MIT, approved, clearlydefined @@ -141,18 +149,17 @@ npm/npmjs/-/postcss-import/14.1.0, MIT, approved, clearlydefined npm/npmjs/-/postcss-js/4.0.0, MIT, approved, clearlydefined npm/npmjs/-/postcss-load-config/3.1.4, MIT, approved, clearlydefined npm/npmjs/-/postcss-nested/5.0.6, MIT, approved, clearlydefined -npm/npmjs/-/postcss-selector-parser/6.0.10, MIT, approved, #5056 +npm/npmjs/-/postcss-selector-parser/6.0.13, MIT, approved, #5056 npm/npmjs/-/postcss-value-parser/4.2.0, MIT, approved, clearlydefined -npm/npmjs/-/postcss/8.4.14, MIT, approved, #3545 +npm/npmjs/-/postcss/8.4.31, MIT, approved, #3545 npm/npmjs/-/prelude-ls/1.2.1, MIT, approved, clearlydefined npm/npmjs/-/prettier-linter-helpers/1.0.0, MIT, approved, clearlydefined npm/npmjs/-/prettier/2.7.1, MIT AND (0BSD AND Apache-2.0 AND BSD-2-Clause AND BSD-3-Clause AND CC-BY-SA-4.0 AND ISC AND MIT) AND BSD-2-Clause, approved, #3238 -npm/npmjs/-/punycode/2.1.1, MIT, approved, clearlydefined +npm/npmjs/-/punycode/2.3.1, MIT, approved, #6373 npm/npmjs/-/queue-microtask/1.2.3, MIT, approved, clearlydefined npm/npmjs/-/quick-lru/5.1.1, MIT, approved, clearlydefined npm/npmjs/-/read-cache/1.0.0, MIT, approved, clearlydefined npm/npmjs/-/readdirp/3.6.0, MIT, approved, #2977 -npm/npmjs/-/regexpp/3.2.0, MIT, approved, clearlydefined npm/npmjs/-/resolve-from/4.0.0, MIT, approved, clearlydefined npm/npmjs/-/resolve/1.22.1, MIT AND ISC, approved, #2409 npm/npmjs/-/reusify/1.0.4, MIT, approved, clearlydefined @@ -179,34 +186,39 @@ npm/npmjs/-/type-fest/0.20.2, MIT OR (CC0-1.0 AND MIT), approved, clearlydefined npm/npmjs/-/update-browserslist-db/1.0.4, MIT, approved, #8237 npm/npmjs/-/uri-js/4.4.1, BSD-2-Clause, approved, #1086 npm/npmjs/-/util-deprecate/1.0.2, MIT, approved, #5885 -npm/npmjs/-/v8-compile-cache/2.3.0, MIT, approved, clearlydefined npm/npmjs/-/vite/2.9.16, MIT AND ISC AND Apache-2.0 AND BSD-2-Clause AND CC0-1.0 AND (BSD-3-Clause OR GPL-2.0-only), approved, #5873 -npm/npmjs/-/vue-eslint-parser/9.0.3, MIT, approved, #5871 +npm/npmjs/-/vue-eslint-parser/9.3.2, MIT, approved, #11439 npm/npmjs/-/vue-json-viewer/3.0.4, MIT, approved, #5870 npm/npmjs/-/vue-router/4.1.0, MIT, approved, clearlydefined npm/npmjs/-/vue/3.2.37, MIT, approved, #7094 npm/npmjs/-/which/2.0.2, ISC, approved, clearlydefined -npm/npmjs/-/word-wrap/1.2.5, MIT, approved, clearlydefined npm/npmjs/-/wrappy/1.0.2, ISC, approved, clearlydefined npm/npmjs/-/xml-name-validator/4.0.0, Apache-2.0, approved, clearlydefined npm/npmjs/-/xtend/4.0.2, MIT, approved, clearlydefined npm/npmjs/-/yallist/4.0.0, ISC, approved, clearlydefined npm/npmjs/-/yaml/1.10.2, ISC, approved, clearlydefined +npm/npmjs/-/yocto-queue/0.1.0, MIT, approved, clearlydefined +npm/npmjs/@aashutoshrathi/word-wrap/1.2.6, MIT, approved, #9212 npm/npmjs/@babel/parser/7.18.6, MIT, approved, clearlydefined -npm/npmjs/@eslint/eslintrc/1.3.0, MIT, approved, clearlydefined -npm/npmjs/@humanwhocodes/config-array/0.9.5, Apache-2.0, approved, clearlydefined -npm/npmjs/@humanwhocodes/object-schema/1.2.1, BSD-3-Clause, approved, clearlydefined +npm/npmjs/@eslint-community/eslint-utils/4.4.0, MIT, approved, #8032 +npm/npmjs/@eslint-community/regexpp/4.10.0, MIT, approved, clearlydefined +npm/npmjs/@eslint/eslintrc/2.1.3, MIT, approved, #9908 +npm/npmjs/@eslint/js/8.54.0, MIT AND (LGPL-2.0-or-later AND MIT) AND ISC AND OFL-1.1 AND CC-BY-SA-2.0 AND (LicenseRef-scancode-proprietary-license AND MIT), restricted, #11617 +npm/npmjs/@humanwhocodes/config-array/0.11.13, Apache-2.0, approved, #5876 +npm/npmjs/@humanwhocodes/module-importer/1.0.1, Apache-2.0, approved, clearlydefined +npm/npmjs/@humanwhocodes/object-schema/2.0.1, BSD-3-Clause, approved, clearlydefined npm/npmjs/@nodelib/fs.scandir/2.1.5, MIT, approved, clearlydefined npm/npmjs/@nodelib/fs.stat/2.0.5, MIT, approved, clearlydefined npm/npmjs/@nodelib/fs.walk/1.2.8, MIT, approved, clearlydefined npm/npmjs/@rushstack/eslint-patch/1.1.4, MIT, approved, clearlydefined +npm/npmjs/@ungap/structured-clone/1.2.0, ISC, approved, clearlydefined npm/npmjs/@vitejs/plugin-vue/2.3.3, MIT, approved, clearlydefined npm/npmjs/@vue/compiler-core/3.2.37, MIT, approved, #7097 npm/npmjs/@vue/compiler-dom/3.2.37, MIT, approved, #7093 npm/npmjs/@vue/compiler-sfc/3.2.37, MIT, approved, #3104 npm/npmjs/@vue/compiler-ssr/3.2.37, MIT, approved, #7098 npm/npmjs/@vue/devtools-api/6.2.0, MIT, approved, clearlydefined -npm/npmjs/@vue/eslint-config-prettier/7.0.0, MIT, approved, clearlydefined +npm/npmjs/@vue/eslint-config-prettier/7.1.0, MIT, approved, clearlydefined npm/npmjs/@vue/reactivity-transform/3.2.37, MIT, approved, #3096 npm/npmjs/@vue/reactivity/3.2.37, MIT, approved, #7088 npm/npmjs/@vue/runtime-core/3.2.37, MIT, approved, #7086 diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 8ac79129..fa4765f9 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -1,14 +1,14 @@ ## Keeping dependencies-files up to date ### Backend -Navigate to the ./backend folder and run: +Navigate to the `./backend` folder and run: ``` mvn org.eclipse.dash:license-tool-plugin:license-check cp DEPENDENCIES ../DEPENDENCIES_BACKEND ``` The first line runs the maven license tool with the parameters specified in the -./backend/pom.xml and produces a DEPENDENCIES file in the ./backend folder. -Then this file gets copied to the PURIS-project root folder under the name DEPENDENCIES_BACKEND. +`./backend/pom.xml` and produces a DEPENDENCIES file in the .`/backend` folder. +Then this file gets copied to the PURIS-project root folder under the name `DEPENDENCIES_BACKEND`. Both files should be updated prior to any pull request. ### Frontend @@ -28,18 +28,18 @@ eclipseDashTool package-lock.json -project automotive.tractusx -summary ../DEPEN ## Frontend container building workaround to use environment variables for vue ### The mechanism for docker is the following: -- .env has vite variables -- .env.dockerbuild has the vite variable that maps on an environment variable (VITE_BACKEND_BASE_URL=$BACKEND_BASE_URL) -- src/config.json has the environment variable names and the environment variable to substring in a json format. +- `.env` has vite variables +- `.env.dockerbuild` has the vite variable that maps on an environment variable (`VITE_BACKEND_BASE_URL=$BACKEND_BASE_URL`) +- `src/config.json` has the environment variable names and the environment variable to substring in a json format. ### When building the container: -1. .env.dockerbuild is used +1. `.env.dockerbuild` is used 2. vite / vue builds the application into a dest folder, that will be served by nginx > Result for the .env: <br> VITE_BACKEND_BASE_URL won't write a variable value BUT a placeholder into the built files ($BACKEND_BASE_URL) ### When building the container, there is a "start-nginx.sh" file that does the following -1. Collects the environment variables (set for the docker container / set via helm as BACKEND_BASE_URL) -2. Looks-up the "to replace string" from config.json (for BACKEND_BASE_URL, it will search for $BACKEND_BASE-URL in the built files) +1. Collects the environment variables (set for the docker container / set via helm as `BACKEND_BASE_URL`) +2. Looks-up the "to replace string" from `config.json` (e.g., for `BACKEND_BASE_URL`, it will search for `$BACKEND_BASE-URL` in the built files) 3. Does the replacement in the built files 4. Starts nginx diff --git a/docs/README.md b/docs/README.md index 2748e590..0adf5b4d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,3 +1,14 @@ # Introduction + This repository provides the frontend and backend of the puris demonstrator. It allows to exchange data according to puris related standards to fulfill short-term information needs. + +The following table links you to the respective documentations. + +| Documentation | Purpose | +|------------------------------------------------------------|-----------------------------------------------------------------| +| [Arc42](./arc42/Index.md) | Architecture Documentation of Frontend and Backend. | +| [DEVELOPMENT.MD](./DEVELOPMENT.md) | Information relevant, if you contribute in PURIS development. | +| [Administration Guide](./adminGuide/Admin_Guide.md) | Information relevant, if you want to use the PURIS application. | +| [Interface Documentation](./interfaceDoc/Interface_Doc.md) | Information about the interfaces. | +| User Manual | TODO | diff --git a/docs/adminGuide/Admin_Guide.md b/docs/adminGuide/Admin_Guide.md new file mode 100644 index 00000000..496690fb --- /dev/null +++ b/docs/adminGuide/Admin_Guide.md @@ -0,0 +1,104 @@ +# Getting started + +To start the application refer to the [Install.md](../../INSTALL.md). +It provides information on different deployments for first tests till full deployment via helm. + +# Technical Deployment + +The application mainly has the following components that need to be configured. + +The subchapters give you an overview of needed configurations and how to get the software running. It links to the +respective deployment scenarios for further information. + +| Deployment Scenario | File | +|--------------------------------------|-----------------------------------------------------------------------------------| +| Local / Spring | [application.properties](../../backend/src/main/resources/application.properties) | +| Local / Docker Compose (Integration) | [docker-compose.yaml](../../local/docker-compose.yaml) | +| Kubernetes / Helm | [README.md](../../charts/puris/README.md) | + +## Configure Frontend to use Backend + +Mainly one needs to configure the Frontend to reach the Backend. Thus, the Backend must be exposed or at least reachable +for the Frontend. + +Mainly the environment variables with the prefixes `BACKEND_` and `ENDPOINT_` are needed for configuration. Please refer +to the respective deployments for exact information. + +The Backend secures all APIs except for the swagger ui with a backend key. +This api key must be configured in the `application.properties` with the `puris.api.key` property. +Additionally spring provides the context path that adds a path for the backend servlets. + +The Frontend therefore needs the following two variables: +- `BACKEND_BASE_URL` - used to assemble requests to the backend in format: `http://<hostname:port>/<context path>` +- `BACKEND_API_KEY `- the api key used in the backend +- `ENDPOINT_XYZ` - endpoints of the backend used. But they are hardcoded in the backend. + +_Note: The API key header is hard coded to `X-API-KEY`._ + +## Configure EDC in Backend + +Configuration of EDC, see e.g. [Tractus-EDC repository](https://github.com/eclipse-tractusx/tractusx-edc). Refer to the +[local deployment with docker compose](../../local/docker-compose.yaml) for an example configuration. + +Configure EDC addresses in the Backend with prefix `edc.`. Refer to the respective deployments for more information. + +## Integrate Keycloak into Frontend + +The Frontend provides a keycloak integration: + +It restricts the accessible views based on the client roles: +- `PURIS_USER` - Common views related to short-term information needs +- `PURIS_ADMIN` - EDC related views (may be used for debugging) + +All variables with the `IDP_` prefix are needed for configuration. `IDP_DISABLE` can be set to `true` to not use an idp +(only recommended for development purposes). Refer to the respective deployment specific files. + +Configuration and example: + +To host an example keycloak instance, configure the following: + +- `Realm` with name `Catena-X` +- Create `Client` with name `Cl3-PURIS` + - `Client authentication` = false + - `Authentication flow `> `Standard flow` = `true` (rest `false`) + - `Access settings` + - `Valid redirect URIs` = `http:<frontend hostname with port>/*` + - `Valid post logout redirect URIs` = `http:<frontend hostname with port>` + - `Web origins` = `http://<frontend hostname with port>` + - `Roles`: Create `PURIS_ADMIN`, `PURIS_USER` +- Create `users` as wanted + - puris_test with same password (see credentials tab) + - add roles in client + +_Note: The application does NOT make use of the `Client Authentication` (private) feature of Keycloak Clients._ + +## Onboarding Your Data + +The application, per solution strategy, tries to provide visualization and manipulation capabilities to exchange only +production related information. + +_Note: The routes in the following always need to be used based on your backend address configuration including the +context path._ + +### Onboard Master Data + +The application provides the following endpoints to update master data for your partner. This data may not be entered manually. + +You can use this collection as an example for the REST API calls. + +| Interface | Route | Purpose | +|---------------------------------|---------------------------|----------------------------------------------------------------------------------------------------------------| +| Material | /materials | Add materials that are flagged as material or product with your material number | +| Partner | /partner | Add partners (customers / suppliers) with sites and addresses and edc Urls | +| Site | /partners/putSite | Adds a site to a partner including addresses | +| Relationship Partner & Material | /materialpartnerrelations | Connect material and partner incl. partner-related material numbers and wether they supply or buy the material | + +### Onboard Stock Information + +One may use the `StockView` related interfaces to add stocks after adding the master data to e.g. regularly update / +overwrite the existing stocks. + +| Interface | Route | Purpose | +|----------------|----------------------------|---------------------------------------| +| Product Stock | /stockView/product-stocks | Add stocks allocated to your customer | +| Material Stock | /stockView/material-stocks | Add stocks allocated to your supplier | diff --git a/docs/arc42/05_building_block_view.md b/docs/arc42/05_building_block_view.md index 02a9f79d..bfca9155 100644 --- a/docs/arc42/05_building_block_view.md +++ b/docs/arc42/05_building_block_view.md @@ -11,6 +11,7 @@ been omitted for readability. | PURIS FOSS Backend | This system represents the PURIS FOSS application's logic. It handles the data exchange. | | PURIS FOSS Frontend | This system represents the PURIS FOSS user interface. It handles the data visualization. | | EDC | The Eclipse Dataspace Components Connector (EDC) is the component allowing PURIS FOSS to participate in the IDS. It is used to provide and consume data assets following policy information. Any data transfer is routed through the EDC. | +| Keycloak | Keycloak is an identity provider that can manage multiple clients (applications). Catena-X allows the usage of a shared identity provider. | ## Level 1 White Boxes diff --git a/docs/arc42/puml/05-level-0.puml b/docs/arc42/puml/05-level-0.puml index 33ff587e..f300a18e 100644 --- a/docs/arc42/puml/05-level-0.puml +++ b/docs/arc42/puml/05-level-0.puml @@ -1,11 +1,9 @@ @startuml - [Data Provisioning & Transformation] as data_prov - -data_prov -> "Interface internal systems" - [Eclipse DataSpace Components Connector] as edc +[Keycloak] as idp +data_prov -( "Interface internal systems" edc -- "EDC APIs" package "<<system>> PURIS"{ @@ -13,9 +11,10 @@ package "<<system>> PURIS"{ [PURIS FOSS Backend] as puris_backend [PURIS FOSS Frontend] as puris_frontend - "EDC APIs" -- "provide and pull data\naccording to standards" puris_backend + "EDC APIs" )-- "provide and pull data\naccording to standards" puris_backend "Interface internal systems" - puris_backend - puris_backend -- puris_frontend + puris_backend <-- puris_frontend + idp <- puris_frontend } diff --git a/docs/interfaceDoc/Interface_Doc.md b/docs/interfaceDoc/Interface_Doc.md new file mode 100644 index 00000000..f51abeae --- /dev/null +++ b/docs/interfaceDoc/Interface_Doc.md @@ -0,0 +1,32 @@ +# Interface Documentation + +This document provides information on the interfaces. It more or less links you to the relevant sections in other +documentations. + +## Overview of Data Exchange Interfaces + +The [arc42 documentation](../arc42/Index.md) provides an overview based on the following chapters: + +- [Building Block View](../arc42/05_building_block_view.md) shows which kind of interfaces are present +- [Runtime View](../arc42/06_runtime_view.md) shows how data with participants is exchanged + +## Swagger documentation + +You can refer to the INT environment application to view the swagger ui. + +``` +http://puris-customer.int.demo.catena-x.net/swagger-ui/index.html +``` + +If not reachable, you can also deploy the backend application according to the [Install.md](../../backend/INSTALL.md) in +the backend and use the following path. + +``` +http://localhost:8081/catena/swagger-ui/index.html +``` + +_Note: The port and the path depend on the configuration of the spring backend (`port` and `context path`)._ + +## Postman + +TODO diff --git a/frontend/.env b/frontend/.env index 11b19bf6..aad61513 100644 --- a/frontend/.env +++ b/frontend/.env @@ -9,3 +9,9 @@ VITE_ENDPOINT_PRODUCT_STOCKS=stockView/product-stocks VITE_ENDPOINT_CUSTOMER=stockView/customer?ownMaterialNumber= VITE_ENDPOINT_PARTNER_PRODUCT_STOCKS=stockView/partner-product-stocks?ownMaterialNumber= VITE_ENDPOINT_UPDATE_PARTNER_PRODUCT_STOCK=stockView/update-partner-product-stock?ownMaterialNumber= + +VITE_IDP_DISABLE=true +VITE_IDP_URL=http://localhost:10081/ +VITE_IDP_REALM=Catena-X +VITE_IDP_CLIENT_ID=Cl3-PURIS +VITE_IDP_REDIRECT_URL_FRONTEND=http://localhost:3000/ diff --git a/frontend/.env.dockerbuild b/frontend/.env.dockerbuild index 5f2f36ec..d2bf8ead 100644 --- a/frontend/.env.dockerbuild +++ b/frontend/.env.dockerbuild @@ -8,3 +8,9 @@ VITE_ENDPOINT_PRODUCT_STOCKS=\$ENDPOINT_PRODUCT_STOCKS VITE_ENDPOINT_CUSTOMER=\$ENDPOINT_CUSTOMER VITE_ENDPOINT_PARTNER_PRODUCT_STOCKS=\$ENDPOINT_PARTNER_PRODUCT_STOCKS VITE_ENDPOINT_UPDATE_PARTNER_PRODUCT_STOCK=\$ENDPOINT_UPDATE_PARTNER_PRODUCT_STOCK + +VITE_IDP_DISABLE=\$IDP_DISABLE +VITE_IDP_URL=\$IDP_URL +VITE_IDP_REALM=\$IDP_REALM +VITE_IDP_CLIENT_ID=\$IDP_CLIENT_ID +VITE_IDP_REDIRECT_URL_FRONTEND=\$IDP_REDIRECT_URL_FRONTEND diff --git a/frontend/DEPENDENCIES b/frontend/DEPENDENCIES index 4f6d4895..14658c90 100644 --- a/frontend/DEPENDENCIES +++ b/frontend/DEPENDENCIES @@ -2,7 +2,7 @@ npm/npmjs/-/acorn-jsx/5.3.2, MIT, approved, clearlydefined npm/npmjs/-/acorn-node/1.8.2, Apache-2.0, approved, clearlydefined npm/npmjs/-/acorn-walk/7.2.0, MIT, approved, clearlydefined npm/npmjs/-/acorn/7.4.1, MIT, approved, clearlydefined -npm/npmjs/-/acorn/8.7.1, MIT, approved, clearlydefined +npm/npmjs/-/acorn/8.11.2, MIT, approved, clearlydefined npm/npmjs/-/ajv/6.12.6, MIT, approved, #979 npm/npmjs/-/ansi-regex/5.0.1, MIT, approved, clearlydefined npm/npmjs/-/ansi-styles/4.3.0, MIT, approved, clearlydefined @@ -11,6 +11,7 @@ npm/npmjs/-/arg/5.0.2, MIT, approved, clearlydefined npm/npmjs/-/argparse/2.0.1, Python-2.0, approved, CQ22954 npm/npmjs/-/autoprefixer/10.4.7, MIT, approved, #7494 npm/npmjs/-/balanced-match/1.0.2, MIT, approved, clearlydefined +npm/npmjs/-/base64-js/1.5.1, MIT, approved, clearlydefined npm/npmjs/-/binary-extensions/2.2.0, MIT, approved, clearlydefined npm/npmjs/-/boolbase/1.0.0, ISC, approved, clearlydefined npm/npmjs/-/brace-expansion/1.1.11, MIT, approved, clearlydefined @@ -62,14 +63,12 @@ npm/npmjs/-/escalade/3.1.1, MIT, approved, clearlydefined npm/npmjs/-/escape-string-regexp/4.0.0, MIT, approved, clearlydefined npm/npmjs/-/eslint-config-prettier/8.5.0, MIT, approved, clearlydefined npm/npmjs/-/eslint-plugin-prettier/4.2.1, MIT, approved, clearlydefined -npm/npmjs/-/eslint-plugin-vue/9.1.1, MIT, approved, #5872 -npm/npmjs/-/eslint-scope/7.1.1, BSD-2-Clause, approved, clearlydefined -npm/npmjs/-/eslint-utils/3.0.0, MIT, approved, #2431 -npm/npmjs/-/eslint-visitor-keys/2.1.0, Apache-2.0, approved, #2433 -npm/npmjs/-/eslint-visitor-keys/3.3.0, Apache-2.0, approved, #2696 -npm/npmjs/-/eslint/8.19.0, MIT, approved, #5874 -npm/npmjs/-/espree/9.3.2, BSD-2-Clause AND BSD-3-Clause AND MIT, approved, #2697 -npm/npmjs/-/esquery/1.4.0, BSD-3-Clause, approved, #1100 +npm/npmjs/-/eslint-plugin-vue/9.18.1, MIT, approved, #11440 +npm/npmjs/-/eslint-scope/7.2.2, BSD-2-Clause, approved, #9916 +npm/npmjs/-/eslint-visitor-keys/3.4.3, Apache-2.0, approved, #7729 +npm/npmjs/-/eslint/8.54.0, MIT AND (LGPL-2.0-or-later AND MIT) AND ISC AND OFL-1.1 AND CC-BY-SA-2.0 AND (LicenseRef-scancode-proprietary-license AND MIT), restricted, #11618 +npm/npmjs/-/espree/9.6.1, BSD-2-Clause AND BSD-3-Clause AND MIT AND BSD-2-Clause, approved, #9308 +npm/npmjs/-/esquery/1.5.0, BSD-3-Clause, approved, #7469 npm/npmjs/-/esrecurse/4.3.0, BSD-2-Clause, approved, clearlydefined npm/npmjs/-/estraverse/5.3.0, BSD-2-Clause AND MIT, approved, #1557 npm/npmjs/-/estree-walker/2.0.2, MIT, approved, clearlydefined @@ -82,21 +81,22 @@ npm/npmjs/-/fast-levenshtein/2.0.6, MIT, approved, #2428 npm/npmjs/-/fastq/1.13.0, ISC, approved, clearlydefined npm/npmjs/-/file-entry-cache/6.0.1, MIT, approved, clearlydefined npm/npmjs/-/fill-range/7.0.1, MIT, approved, clearlydefined +npm/npmjs/-/find-up/5.0.0, MIT, approved, clearlydefined npm/npmjs/-/flat-cache/3.0.4, MIT, approved, clearlydefined npm/npmjs/-/flatted/3.2.6, ISC AND (ISC AND MIT), approved, #2430 npm/npmjs/-/fraction.js/4.2.0, MIT, approved, clearlydefined npm/npmjs/-/fs.realpath/1.0.0, ISC, approved, clearlydefined npm/npmjs/-/fsevents/2.3.2, MIT, approved, #2967 -npm/npmjs/-/function-bind/1.1.1, MIT, approved, clearlydefined -npm/npmjs/-/functional-red-black-tree/1.0.1, MIT, approved, clearlydefined +npm/npmjs/-/function-bind/1.1.1, MIT, approved, #11063 npm/npmjs/-/glob-parent/5.1.2, ISC, approved, clearlydefined npm/npmjs/-/glob-parent/6.0.2, ISC, approved, clearlydefined npm/npmjs/-/glob/7.2.3, ISC, approved, clearlydefined -npm/npmjs/-/globals/13.16.0, MIT, approved, clearlydefined +npm/npmjs/-/globals/13.23.0, MIT, approved, clearlydefined npm/npmjs/-/good-listener/1.2.2, MIT, approved, clearlydefined +npm/npmjs/-/graphemer/1.4.0, MIT, approved, clearlydefined npm/npmjs/-/has-flag/4.0.0, MIT, approved, clearlydefined -npm/npmjs/-/has/1.0.3, MIT, approved, clearlydefined -npm/npmjs/-/ignore/5.2.0, MIT, approved, #5907 +npm/npmjs/-/has/1.0.3, MIT, approved, #10930 +npm/npmjs/-/ignore/5.3.0, MIT, approved, #11665 npm/npmjs/-/import-fresh/3.3.0, MIT, approved, clearlydefined npm/npmjs/-/imurmurhash/0.1.4, MIT, approved, clearlydefined npm/npmjs/-/inflight/1.0.6, ISC, approved, clearlydefined @@ -106,12 +106,17 @@ npm/npmjs/-/is-core-module/2.9.0, MIT, approved, clearlydefined npm/npmjs/-/is-extglob/2.1.1, MIT, approved, clearlydefined npm/npmjs/-/is-glob/4.0.3, MIT, approved, clearlydefined npm/npmjs/-/is-number/7.0.0, MIT, approved, clearlydefined +npm/npmjs/-/is-path-inside/3.0.3, MIT, approved, clearlydefined npm/npmjs/-/isexe/2.0.0, ISC, approved, clearlydefined +npm/npmjs/-/js-sha256/0.10.1, MIT, approved, clearlydefined npm/npmjs/-/js-yaml/4.1.0, MIT, approved, clearlydefined npm/npmjs/-/json-schema-traverse/0.4.1, MIT, approved, clearlydefined npm/npmjs/-/json-stable-stringify-without-jsonify/1.0.1, MIT, approved, clearlydefined +npm/npmjs/-/jwt-decode/4.0.0, MIT, approved, clearlydefined +npm/npmjs/-/keycloak-js/23.0.0, Apache-2.0 AND (Apache-2.0 AND GPL-2.0-or-later) AND LicenseRef-scancode-public-domain-disclaimer AND MIT AND (BSD-2-Clause AND BSD-3-Clause AND CC-BY-2.5 AND FSFAP AND MPL-2.0) AND (BSD-3-Clause AND MIT) AND (Apache-2.0 AND LGPL-2.0-or-later) AND (AFL-2.1 AND AFL-3.0 AND LGPL-2.0-only) AND EPL-1.0 AND W3C-19980720 AND LicenseRef-scancode-oasis-ws-security-spec AND W3C AND LicenseRef-scancode-ws-policy-specification AND (Apache-2.0 AND LicenseRef-scancode-bitzi-pd) AND (Apache-2.0 AND MIT) AND (Apache-2.0 AND MIT AND MPL-1.0), restricted, #11737 npm/npmjs/-/levn/0.4.1, MIT, approved, clearlydefined npm/npmjs/-/lilconfig/2.0.5, MIT, approved, clearlydefined +npm/npmjs/-/locate-path/6.0.0, MIT, approved, clearlydefined npm/npmjs/-/lodash.merge/4.6.2, MIT, approved, clearlydefined npm/npmjs/-/lodash/4.17.21, CC0-1.0 AND MIT, approved, #2096 npm/npmjs/-/lru-cache/6.0.0, ISC, approved, clearlydefined @@ -121,7 +126,7 @@ npm/npmjs/-/micromatch/4.0.5, MIT, approved, clearlydefined npm/npmjs/-/minimatch/3.1.2, ISC, approved, clearlydefined npm/npmjs/-/minimist/1.2.6, MIT, approved, #5886 npm/npmjs/-/ms/2.1.2, MIT, approved, #5895 -npm/npmjs/-/nanoid/3.3.4, MIT, approved, #7571 +npm/npmjs/-/nanoid/3.3.7, MIT, approved, #7571 npm/npmjs/-/natural-compare/1.4.0, MIT, approved, clearlydefined npm/npmjs/-/node-releases/2.0.5, MIT, approved, #1954 npm/npmjs/-/normalize-path/3.0.0, MIT, approved, clearlydefined @@ -129,8 +134,11 @@ npm/npmjs/-/normalize-range/0.1.2, MIT, approved, clearlydefined npm/npmjs/-/nth-check/2.1.1, BSD-2-Clause, approved, clearlydefined npm/npmjs/-/object-hash/3.0.0, MIT, approved, clearlydefined npm/npmjs/-/once/1.4.0, ISC, approved, clearlydefined -npm/npmjs/-/optionator/0.9.1, MIT, approved, #9208 +npm/npmjs/-/optionator/0.9.3, MIT, approved, #9208 +npm/npmjs/-/p-limit/3.1.0, MIT, approved, clearlydefined +npm/npmjs/-/p-locate/5.0.0, MIT, approved, clearlydefined npm/npmjs/-/parent-module/1.0.1, MIT, approved, clearlydefined +npm/npmjs/-/path-exists/4.0.0, MIT, approved, clearlydefined npm/npmjs/-/path-is-absolute/1.0.1, MIT, approved, clearlydefined npm/npmjs/-/path-key/3.1.1, MIT, approved, clearlydefined npm/npmjs/-/path-parse/1.0.7, MIT, approved, clearlydefined @@ -141,18 +149,17 @@ npm/npmjs/-/postcss-import/14.1.0, MIT, approved, clearlydefined npm/npmjs/-/postcss-js/4.0.0, MIT, approved, clearlydefined npm/npmjs/-/postcss-load-config/3.1.4, MIT, approved, clearlydefined npm/npmjs/-/postcss-nested/5.0.6, MIT, approved, clearlydefined -npm/npmjs/-/postcss-selector-parser/6.0.10, MIT, approved, #5056 +npm/npmjs/-/postcss-selector-parser/6.0.13, MIT, approved, #5056 npm/npmjs/-/postcss-value-parser/4.2.0, MIT, approved, clearlydefined -npm/npmjs/-/postcss/8.4.14, MIT, approved, #3545 +npm/npmjs/-/postcss/8.4.31, MIT, approved, #3545 npm/npmjs/-/prelude-ls/1.2.1, MIT, approved, clearlydefined npm/npmjs/-/prettier-linter-helpers/1.0.0, MIT, approved, clearlydefined npm/npmjs/-/prettier/2.7.1, MIT AND (0BSD AND Apache-2.0 AND BSD-2-Clause AND BSD-3-Clause AND CC-BY-SA-4.0 AND ISC AND MIT) AND BSD-2-Clause, approved, #3238 -npm/npmjs/-/punycode/2.1.1, MIT, approved, clearlydefined +npm/npmjs/-/punycode/2.3.1, MIT, approved, #6373 npm/npmjs/-/queue-microtask/1.2.3, MIT, approved, clearlydefined npm/npmjs/-/quick-lru/5.1.1, MIT, approved, clearlydefined npm/npmjs/-/read-cache/1.0.0, MIT, approved, clearlydefined npm/npmjs/-/readdirp/3.6.0, MIT, approved, #2977 -npm/npmjs/-/regexpp/3.2.0, MIT, approved, clearlydefined npm/npmjs/-/resolve-from/4.0.0, MIT, approved, clearlydefined npm/npmjs/-/resolve/1.22.1, MIT AND ISC, approved, #2409 npm/npmjs/-/reusify/1.0.4, MIT, approved, clearlydefined @@ -179,34 +186,39 @@ npm/npmjs/-/type-fest/0.20.2, MIT OR (CC0-1.0 AND MIT), approved, clearlydefined npm/npmjs/-/update-browserslist-db/1.0.4, MIT, approved, #8237 npm/npmjs/-/uri-js/4.4.1, BSD-2-Clause, approved, #1086 npm/npmjs/-/util-deprecate/1.0.2, MIT, approved, #5885 -npm/npmjs/-/v8-compile-cache/2.3.0, MIT, approved, clearlydefined npm/npmjs/-/vite/2.9.16, MIT AND ISC AND Apache-2.0 AND BSD-2-Clause AND CC0-1.0 AND (BSD-3-Clause OR GPL-2.0-only), approved, #5873 -npm/npmjs/-/vue-eslint-parser/9.0.3, MIT, approved, #5871 +npm/npmjs/-/vue-eslint-parser/9.3.2, MIT, approved, #11439 npm/npmjs/-/vue-json-viewer/3.0.4, MIT, approved, #5870 npm/npmjs/-/vue-router/4.1.0, MIT, approved, clearlydefined npm/npmjs/-/vue/3.2.37, MIT, approved, #7094 npm/npmjs/-/which/2.0.2, ISC, approved, clearlydefined -npm/npmjs/-/word-wrap/1.2.5, MIT, approved, clearlydefined npm/npmjs/-/wrappy/1.0.2, ISC, approved, clearlydefined npm/npmjs/-/xml-name-validator/4.0.0, Apache-2.0, approved, clearlydefined npm/npmjs/-/xtend/4.0.2, MIT, approved, clearlydefined npm/npmjs/-/yallist/4.0.0, ISC, approved, clearlydefined npm/npmjs/-/yaml/1.10.2, ISC, approved, clearlydefined +npm/npmjs/-/yocto-queue/0.1.0, MIT, approved, clearlydefined +npm/npmjs/@aashutoshrathi/word-wrap/1.2.6, MIT, approved, #9212 npm/npmjs/@babel/parser/7.18.6, MIT, approved, clearlydefined -npm/npmjs/@eslint/eslintrc/1.3.0, MIT, approved, clearlydefined -npm/npmjs/@humanwhocodes/config-array/0.9.5, Apache-2.0, approved, clearlydefined -npm/npmjs/@humanwhocodes/object-schema/1.2.1, BSD-3-Clause, approved, clearlydefined +npm/npmjs/@eslint-community/eslint-utils/4.4.0, MIT, approved, #8032 +npm/npmjs/@eslint-community/regexpp/4.10.0, MIT, approved, clearlydefined +npm/npmjs/@eslint/eslintrc/2.1.3, MIT, approved, #9908 +npm/npmjs/@eslint/js/8.54.0, MIT AND (LGPL-2.0-or-later AND MIT) AND ISC AND OFL-1.1 AND CC-BY-SA-2.0 AND (LicenseRef-scancode-proprietary-license AND MIT), restricted, #11617 +npm/npmjs/@humanwhocodes/config-array/0.11.13, Apache-2.0, approved, #5876 +npm/npmjs/@humanwhocodes/module-importer/1.0.1, Apache-2.0, approved, clearlydefined +npm/npmjs/@humanwhocodes/object-schema/2.0.1, BSD-3-Clause, approved, clearlydefined npm/npmjs/@nodelib/fs.scandir/2.1.5, MIT, approved, clearlydefined npm/npmjs/@nodelib/fs.stat/2.0.5, MIT, approved, clearlydefined npm/npmjs/@nodelib/fs.walk/1.2.8, MIT, approved, clearlydefined npm/npmjs/@rushstack/eslint-patch/1.1.4, MIT, approved, clearlydefined +npm/npmjs/@ungap/structured-clone/1.2.0, ISC, approved, clearlydefined npm/npmjs/@vitejs/plugin-vue/2.3.3, MIT, approved, clearlydefined npm/npmjs/@vue/compiler-core/3.2.37, MIT, approved, #7097 npm/npmjs/@vue/compiler-dom/3.2.37, MIT, approved, #7093 npm/npmjs/@vue/compiler-sfc/3.2.37, MIT, approved, #3104 npm/npmjs/@vue/compiler-ssr/3.2.37, MIT, approved, #7098 npm/npmjs/@vue/devtools-api/6.2.0, MIT, approved, clearlydefined -npm/npmjs/@vue/eslint-config-prettier/7.0.0, MIT, approved, clearlydefined +npm/npmjs/@vue/eslint-config-prettier/7.1.0, MIT, approved, clearlydefined npm/npmjs/@vue/reactivity-transform/3.2.37, MIT, approved, #3096 npm/npmjs/@vue/reactivity/3.2.37, MIT, approved, #7088 npm/npmjs/@vue/runtime-core/3.2.37, MIT, approved, #7086 diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 39a83792..0007c0e4 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -8,6 +8,7 @@ "name": "vue-frontend", "version": "0.0.1", "dependencies": { + "keycloak-js": "^23.0.0", "vue": "^3.2.37", "vue-json-viewer": "^3.0.4", "vue-router": "^4.0.16" @@ -15,16 +16,25 @@ "devDependencies": { "@rushstack/eslint-patch": "^1.1.0", "@vitejs/plugin-vue": "^2.3.3", - "@vue/eslint-config-prettier": "^7.0.0", + "@vue/eslint-config-prettier": "^7.1.0", "autoprefixer": "^10.4.7", - "eslint": "^8.5.0", - "eslint-plugin-vue": "^9.0.0", + "eslint": "^8.54.0", + "eslint-plugin-vue": "^9.18.1", "postcss": "^8.4.14", "prettier": "^2.5.1", "tailwindcss": "^3.1.4", "vite": "^2.9.12" } }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@babel/parser": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.6.tgz", @@ -36,44 +46,93 @@ "node": ">=6.0.0" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", - "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.3.2", - "globals": "^13.15.0", + "espree": "^9.6.0", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", + "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", + "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, "node_modules/@nodelib/fs.scandir": { @@ -117,6 +176,12 @@ "integrity": "sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA==", "dev": true }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "node_modules/@vitejs/plugin-vue": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.3.3.tgz", @@ -182,9 +247,9 @@ "integrity": "sha512-pF1G4wky+hkifDiZSWn8xfuLOJI1ZXtuambpBEYaf7Xaf6zC/pM29rvAGpd3qaGXnr4BAXU1Pxz/VfvBGwexGA==" }, "node_modules/@vue/eslint-config-prettier": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-7.0.0.tgz", - "integrity": "sha512-/CTc6ML3Wta1tCe1gUeO0EYnVXfo3nJXsIhZ8WJr3sov+cGASr6yuiibJTL6lmIBm7GobopToOuB3B6AWyV0Iw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-7.1.0.tgz", + "integrity": "sha512-Pv/lVr0bAzSIHLd9iz0KnvAr4GKyCEl+h52bc4e5yWuDVtLgFwycF7nrbWTAQAS+FU6q1geVd07lc6EWfJiWKQ==", "dev": true, "dependencies": { "eslint-config-prettier": "^8.3.0", @@ -252,9 +317,9 @@ "integrity": "sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw==" }, "node_modules/acorn": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -408,6 +473,25 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -1085,46 +1169,49 @@ } }, "node_modules/eslint": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.19.0.tgz", - "integrity": "sha512-SXOPj3x9VKvPe81TjjUJCYlV4oJjQw68Uek+AM0X4p+33dj2HY5bpTZOgnQHcG2eAm1mtCU9uNMnJi7exU/kYw==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", + "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.3.0", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.54.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.2", - "esquery": "^1.4.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "text-table": "^0.2.0" }, "bin": { "eslint": "bin/eslint.js" @@ -1170,17 +1257,17 @@ } }, "node_modules/eslint-plugin-vue": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.1.1.tgz", - "integrity": "sha512-W9n5PB1X2jzC7CK6riG0oAcxjmKrjTF6+keL1rni8n57DZeilx/Fulz+IRJK3lYseLNAygN0I62L7DvioW40Tw==", + "version": "9.18.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.18.1.tgz", + "integrity": "sha512-7hZFlrEgg9NIzuVik2I9xSnJA5RsmOfueYgsUGUokEDLJ1LHtxO0Pl4duje1BriZ/jDWb+44tcIlC3yi0tdlZg==", "dev": true, "dependencies": { - "eslint-utils": "^3.0.0", + "@eslint-community/eslint-utils": "^4.4.0", "natural-compare": "^1.4.0", - "nth-check": "^2.0.1", - "postcss-selector-parser": "^6.0.9", - "semver": "^7.3.5", - "vue-eslint-parser": "^9.0.1", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^6.0.13", + "semver": "^7.5.4", + "vue-eslint-parser": "^9.3.1", "xml-name-validator": "^4.0.0" }, "engines": { @@ -1191,9 +1278,9 @@ } }, "node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -1201,62 +1288,44 @@ }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" }, "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/espree": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", - "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "dependencies": { - "acorn": "^8.7.1", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -1385,6 +1454,22 @@ "node": ">=8" } }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -1443,12 +1528,6 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true - }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -1482,9 +1561,9 @@ } }, "node_modules/globals": { - "version": "13.16.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.16.0.tgz", - "integrity": "sha512-A1lrQfpNF+McdPOnnFqY3kSN0AFTy485bTi1bkLk4mVPODIUEcSfhHgRqA+QdXPksrSTTztYXx37NFV+GpGk3Q==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -1504,6 +1583,12 @@ "delegate": "^3.1.2" } }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -1526,9 +1611,9 @@ } }, "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true, "engines": { "node": ">= 4" @@ -1629,12 +1714,26 @@ "node": ">=0.12.0" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/js-sha256": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.10.1.tgz", + "integrity": "sha512-5obBtsz9301ULlsgggLg542s/jqtddfOpV5KJc4hajc9JV8GeY2gZHSVpYBn4nWqAUTJ9v+xwtbJ1mIBgIH5Vw==" + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -1659,6 +1758,24 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "engines": { + "node": ">=18" + } + }, + "node_modules/keycloak-js": { + "version": "23.0.0", + "resolved": "https://registry.npmjs.org/keycloak-js/-/keycloak-js-23.0.0.tgz", + "integrity": "sha512-2IbXr92uOaIiujzopYqo2Gg0gmYsMztq32K42nmnN2u464ws9nZbclR76Csil0S/Si8314mx+Ji0yv6Q9w1wYQ==", + "dependencies": { + "base64-js": "^1.5.1", + "js-sha256": "^0.10.1", + "jwt-decode": "^4.0.0" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -1681,6 +1798,21 @@ "node": ">=10" } }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -1760,9 +1892,15 @@ "dev": true }, "node_modules/nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -1831,22 +1969,52 @@ } }, "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "type-check": "^0.4.0" }, "engines": { "node": ">= 0.8.0" } }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -1859,6 +2027,15 @@ "node": ">=6" } }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -1910,9 +2087,9 @@ } }, "node_modules/postcss": { - "version": "8.4.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", - "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "funding": [ { "type": "opencollective", @@ -1921,10 +2098,14 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -2017,9 +2198,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", "dev": true, "dependencies": { "cssesc": "^3.0.0", @@ -2072,9 +2253,9 @@ } }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { "node": ">=6" @@ -2133,18 +2314,6 @@ "node": ">=8.10.0" } }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, "node_modules/resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -2472,12 +2641,6 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, "node_modules/vite": { "version": "2.9.16", "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.16.tgz", @@ -2528,9 +2691,9 @@ } }, "node_modules/vue-eslint-parser": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.0.3.tgz", - "integrity": "sha512-yL+ZDb+9T0ELG4VIFo/2anAOz8SvBdlqEnQnvJ3M7Scq56DvtjY0VY88bByRZB0D4J0u8olBcfrXTVONXsh4og==", + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.3.2.tgz", + "integrity": "sha512-q7tWyCVaV9f8iQyIA5Mkj/S6AoJ9KBN8IeUSf3XEmBrOtxOZnfTg5s4KClbZBCK3GtnT/+RyCLZyDHuZwTuBjg==", "dev": true, "dependencies": { "debug": "^4.3.4", @@ -2591,15 +2754,6 @@ "node": ">= 8" } }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -2638,24 +2792,57 @@ "engines": { "node": ">= 6" } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } }, "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, "@babel/parser": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.6.tgz", "integrity": "sha512-uQVSa9jJUe/G/304lXspfWVpKpK4euFLgGiMQFOCpM/bgcAdeoHwi/OQz23O9GK2osz26ZiXRRV9aV+Yl1O8tw==" }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true + }, "@eslint/eslintrc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", - "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.3.2", - "globals": "^13.15.0", + "espree": "^9.6.0", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -2663,21 +2850,33 @@ "strip-json-comments": "^3.1.1" } }, + "@eslint/js": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", + "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", + "dev": true + }, "@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "requires": { - "@humanwhocodes/object-schema": "^1.2.1", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" } }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, "@nodelib/fs.scandir": { @@ -2712,6 +2911,12 @@ "integrity": "sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA==", "dev": true }, + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "@vitejs/plugin-vue": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.3.3.tgz", @@ -2771,9 +2976,9 @@ "integrity": "sha512-pF1G4wky+hkifDiZSWn8xfuLOJI1ZXtuambpBEYaf7Xaf6zC/pM29rvAGpd3qaGXnr4BAXU1Pxz/VfvBGwexGA==" }, "@vue/eslint-config-prettier": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-7.0.0.tgz", - "integrity": "sha512-/CTc6ML3Wta1tCe1gUeO0EYnVXfo3nJXsIhZ8WJr3sov+cGASr6yuiibJTL6lmIBm7GobopToOuB3B6AWyV0Iw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-7.1.0.tgz", + "integrity": "sha512-Pv/lVr0bAzSIHLd9iz0KnvAr4GKyCEl+h52bc4e5yWuDVtLgFwycF7nrbWTAQAS+FU6q1geVd07lc6EWfJiWKQ==", "dev": true, "requires": { "eslint-config-prettier": "^8.3.0", @@ -2834,9 +3039,9 @@ "integrity": "sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw==" }, "acorn": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true }, "acorn-jsx": { @@ -2940,6 +3145,11 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -3336,46 +3546,49 @@ "dev": true }, "eslint": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.19.0.tgz", - "integrity": "sha512-SXOPj3x9VKvPe81TjjUJCYlV4oJjQw68Uek+AM0X4p+33dj2HY5bpTZOgnQHcG2eAm1mtCU9uNMnJi7exU/kYw==", + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", + "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", "dev": true, "requires": { - "@eslint/eslintrc": "^1.3.0", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.54.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.2", - "esquery": "^1.4.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "text-table": "^0.2.0" } }, "eslint-config-prettier": { @@ -3395,68 +3608,51 @@ } }, "eslint-plugin-vue": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.1.1.tgz", - "integrity": "sha512-W9n5PB1X2jzC7CK6riG0oAcxjmKrjTF6+keL1rni8n57DZeilx/Fulz+IRJK3lYseLNAygN0I62L7DvioW40Tw==", + "version": "9.18.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.18.1.tgz", + "integrity": "sha512-7hZFlrEgg9NIzuVik2I9xSnJA5RsmOfueYgsUGUokEDLJ1LHtxO0Pl4duje1BriZ/jDWb+44tcIlC3yi0tdlZg==", "dev": true, "requires": { - "eslint-utils": "^3.0.0", + "@eslint-community/eslint-utils": "^4.4.0", "natural-compare": "^1.4.0", - "nth-check": "^2.0.1", - "postcss-selector-parser": "^6.0.9", - "semver": "^7.3.5", - "vue-eslint-parser": "^9.0.1", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^6.0.13", + "semver": "^7.5.4", + "vue-eslint-parser": "^9.3.1", "xml-name-validator": "^4.0.0" } }, "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "requires": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true }, "espree": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", - "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "requires": { - "acorn": "^8.7.1", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.1" } }, "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "requires": { "estraverse": "^5.1.0" @@ -3563,6 +3759,16 @@ "to-regex-range": "^5.0.1" } }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, "flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -3604,12 +3810,6 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true - }, "glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -3634,9 +3834,9 @@ } }, "globals": { - "version": "13.16.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.16.0.tgz", - "integrity": "sha512-A1lrQfpNF+McdPOnnFqY3kSN0AFTy485bTi1bkLk4mVPODIUEcSfhHgRqA+QdXPksrSTTztYXx37NFV+GpGk3Q==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -3650,6 +3850,12 @@ "delegate": "^3.1.2" } }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -3666,9 +3872,9 @@ "dev": true }, "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true }, "import-fresh": { @@ -3742,12 +3948,23 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "js-sha256": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.10.1.tgz", + "integrity": "sha512-5obBtsz9301ULlsgggLg542s/jqtddfOpV5KJc4hajc9JV8GeY2gZHSVpYBn4nWqAUTJ9v+xwtbJ1mIBgIH5Vw==" + }, "js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -3769,6 +3986,21 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==" + }, + "keycloak-js": { + "version": "23.0.0", + "resolved": "https://registry.npmjs.org/keycloak-js/-/keycloak-js-23.0.0.tgz", + "integrity": "sha512-2IbXr92uOaIiujzopYqo2Gg0gmYsMztq32K42nmnN2u464ws9nZbclR76Csil0S/Si8314mx+Ji0yv6Q9w1wYQ==", + "requires": { + "base64-js": "^1.5.1", + "js-sha256": "^0.10.1", + "jwt-decode": "^4.0.0" + } + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -3785,6 +4017,15 @@ "integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==", "dev": true }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -3852,9 +4093,9 @@ "dev": true }, "nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==" }, "natural-compare": { "version": "1.4.0", @@ -3905,17 +4146,35 @@ } }, "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "type-check": "^0.4.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" } }, "parent-module": { @@ -3927,6 +4186,12 @@ "callsites": "^3.0.0" } }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -3963,11 +4228,11 @@ "dev": true }, "postcss": { - "version": "8.4.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", - "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "requires": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } @@ -4012,9 +4277,9 @@ } }, "postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", "dev": true, "requires": { "cssesc": "^3.0.0", @@ -4049,9 +4314,9 @@ } }, "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true }, "queue-microtask": { @@ -4084,12 +4349,6 @@ "picomatch": "^2.2.1" } }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, "resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -4304,12 +4563,6 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, "vite": { "version": "2.9.16", "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.16.tgz", @@ -4336,9 +4589,9 @@ } }, "vue-eslint-parser": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.0.3.tgz", - "integrity": "sha512-yL+ZDb+9T0ELG4VIFo/2anAOz8SvBdlqEnQnvJ3M7Scq56DvtjY0VY88bByRZB0D4J0u8olBcfrXTVONXsh4og==", + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.3.2.tgz", + "integrity": "sha512-q7tWyCVaV9f8iQyIA5Mkj/S6AoJ9KBN8IeUSf3XEmBrOtxOZnfTg5s4KClbZBCK3GtnT/+RyCLZyDHuZwTuBjg==", "dev": true, "requires": { "debug": "^4.3.4", @@ -4375,12 +4628,6 @@ "isexe": "^2.0.0" } }, - "word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -4410,6 +4657,12 @@ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } } diff --git a/frontend/package.json b/frontend/package.json index d0429267..842c052b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -13,6 +13,7 @@ "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore" }, "dependencies": { + "keycloak-js": "^23.0.0", "vue": "^3.2.37", "vue-json-viewer": "^3.0.4", "vue-router": "^4.0.16" @@ -20,10 +21,10 @@ "devDependencies": { "@rushstack/eslint-patch": "^1.1.0", "@vitejs/plugin-vue": "^2.3.3", - "@vue/eslint-config-prettier": "^7.0.0", + "@vue/eslint-config-prettier": "^7.1.0", "autoprefixer": "^10.4.7", - "eslint": "^8.5.0", - "eslint-plugin-vue": "^9.0.0", + "eslint": "^8.54.0", + "eslint-plugin-vue": "^9.18.1", "postcss": "^8.4.14", "prettier": "^2.5.1", "tailwindcss": "^3.1.4", diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 270be6b5..c50d3ec0 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -20,238 +20,182 @@ --> <script setup> -import { RouterLink, RouterView } from "vue-router"; +import {RouterLink, RouterView} from "vue-router"; </script> <template> - <div class="flex"> - <div - class="flex flex-col overflow-y-auto border-r w-64 fixed left-0 top-0 h-screen p-10" - > - <div> - <h2 class="text-3xl font-semibold text-center text-blue-800"> - PURIS - </h2> - </div> - <div class="flex flex-col justify-between mt-6"> - <aside> - <ul class="space-y-2"> - <li> - <RouterLink - class="flex items-center px-4 py-2 text-gray-700 bg-gray-100 dark:text-gray-100 dark:bg-gray-700 rounded-md" - to="/" - ><img - class="mr-2" - src="@/assets/icons/home.svg" - alt="Icon" - />Dashboard</RouterLink - > - </li> - <li> - <RouterLink - class="flex items-center px-4 py-2 text-gray-700 bg-gray-100 dark:text-gray-100 dark:bg-gray-700 rounded-md" - to="/createOrder" - ><img - class="mr-2" - src="@/assets/icons/create.svg" - alt="Icon" - />Create</RouterLink - > - </li> - <li> - <RouterLink - class="flex items-center px-4 py-2 text-gray-700 bg-gray-100 dark:text-gray-100 dark:bg-gray-700 rounded-md" - to="/stocks" - ><img - class="mr-2" - src="@/assets/icons/stock.svg" - alt="Icon" - />Stocks</RouterLink - > - </li> - <li> - <RouterLink - class="flex items-center px-4 py-2 text-gray-700 bg-gray-100 dark:text-gray-100 dark:bg-gray-700 rounded-md" - to="/manageOrders" - ><img - class="mr-2" - src="@/assets/icons/manage.svg" - alt="Icon" - />Manage</RouterLink - > - </li> - <li> - <RouterLink - class="flex items-center px-4 py-2 text-gray-700 bg-gray-100 dark:text-gray-100 dark:bg-gray-700 rounded-md" - to="/connectors" - ><img - class="mr-2" - src="@/assets/icons/manage.svg" - alt="Icon" - />Connectors</RouterLink - > - </li> - <li> - <RouterLink - class="flex items-center px-4 py-2 text-gray-700 bg-gray-100 dark:text-gray-100 dark:bg-gray-700 rounded-md" - to="/catalog" - ><img - class="mr-2" - src="@/assets/icons/catalog.svg" - alt="Icon" - />Catalog</RouterLink - > - </li> - <li> - <RouterLink - class="flex items-center px-4 py-2 text-gray-700 bg-gray-100 dark:text-gray-100 dark:bg-gray-700 rounded-md" - to="/negotiations" - ><img - class="mr-2" - src="@/assets/icons/catalog.svg" - alt="Icon" - />Negotiations</RouterLink - > - </li> - <li> - <RouterLink - class="flex items-center px-4 py-2 text-gray-700 bg-gray-100 dark:text-gray-100 dark:bg-gray-700 rounded-md" - to="/transfers" - ><img - class="mr-2" - src="@/assets/icons/catalog.svg" - alt="Icon" - />Transfers</RouterLink - > - </li> - <li> - <RouterLink - class="flex items-center px-4 py-2 text-gray-700 bg-gray-100 dark:text-gray-100 dark:bg-gray-700 rounded-md" - to="/responses" - ><img - class="mr-2" - src="@/assets/icons/responses.svg" - alt="Icon" - />Responses</RouterLink - > - </li> - <li> - <RouterLink - class="flex items-center px-4 py-2 text-gray-700 bg-gray-100 dark:text-gray-100 dark:bg-gray-700 rounded-md" - to="/supplierDashboard" - ><img - class="mr-2" - src="@/assets/icons/home.svg" - alt="Icon" - />Supplier Dashboard</RouterLink - > - </li> - </ul> - </aside> - </div> + <div class="flex"> + <div + class="flex flex-col overflow-y-auto border-r w-64 fixed left-0 top-0 h-screen p-10" + > + <div> + <h2 class="text-3xl font-semibold text-center text-blue-800"> + PURIS + </h2> + </div> + <div class="flex flex-col justify-between mt-6"> + <aside> + <ul class="space-y-2"> + <li + v-for="route in this.viewsWithAccess" + key="route.name" + > + <RouterLink + class="flex items-center px-4 py-2 text-gray-700 bg-gray-100 dark:text-gray-100 dark:bg-gray-700 rounded-md" + :to="route.path" + ><img + class="mr-2" + :src="getImagePath(route.name)" + alt="Icon" + />{{ route.name }}</RouterLink + > + </li> + </ul> + </aside> + </div> + </div> + <div class="sm:ml-64 lg:ml-0 content-center overflow-auto"> + <RouterView /> + </div> </div> - <div class="sm:ml-64 lg:ml-0 content-center overflow-auto"> - <RouterView /> - </div> - </div> </template> <style> @import "@/assets/base.css"; #app { - max-width: 1280px; - margin: 0px auto 0px 16rem; - padding: 2rem; + max-width: 1280px; + margin: 0px auto 0px 16rem; + padding: 2rem; - font-weight: normal; + font-weight: normal; } header { - line-height: 1.5; - max-height: 100vh; + line-height: 1.5; + max-height: 100vh; } .logo { - display: block; - margin: 0 auto 2rem; + display: block; + margin: 0 auto 2rem; } a, .green { - text-decoration: none; - color: hsla(160, 100%, 37%, 1); - transition: 0.4s; + text-decoration: none; + color: hsla(160, 100%, 37%, 1); + transition: 0.4s; } @media (hover: hover) { - a:hover { - background-color: hsla(160, 100%, 37%, 0.2); - } + a:hover { + background-color: hsla(160, 100%, 37%, 0.2); + } } nav { - width: 100%; - font-size: 12px; - text-align: center; - margin-top: 2rem; + width: 100%; + font-size: 12px; + text-align: center; + margin-top: 2rem; } nav a.router-link-exact-active { - color: var(--color-text); + color: var(--color-text); } nav a.router-link-exact-active:hover { - background-color: transparent; + background-color: transparent; } nav a { - display: inline-block; - padding: 0 1rem; - border-left: 1px solid var(--color-border); + display: inline-block; + padding: 0 1rem; + border-left: 1px solid var(--color-border); } nav a:first-of-type { - border: 0; + border: 0; } @media (min-width: 1500px) { - body { - display: flex; - place-items: center; - } - - #app { - //display: grid; - //grid-template-columns: 1fr 1fr; - margin: 0 auto; - max-width: calc(100% - 32rem); - padding: 0 2rem; - } - - header { - display: flex; - place-items: center; - padding-right: calc(var(--section-gap) / 2); - } - - header .wrapper { - display: flex; - place-items: flex-start; - flex-wrap: wrap; - } - - .logo { - margin: 0 2rem 0 0; - } - - nav { - text-align: left; - margin-left: -1rem; - font-size: 1rem; - - padding: 1rem 0; - margin-top: 1rem; - } + body { + display: flex; + place-items: center; + } + + #app { + //display: grid; + //grid-template-columns: 1fr 1fr; + margin: 0 auto; + max-width: calc(100% - 32rem); + padding: 0 2rem; + } + + header { + display: flex; + place-items: center; + padding-right: calc(var(--section-gap) / 2); + } + + header .wrapper { + display: flex; + place-items: flex-start; + flex-wrap: wrap; + } + + .logo { + margin: 0 2rem 0 0; + } + + nav { + text-align: left; + margin-left: -1rem; + font-size: 1rem; + + padding: 1rem 0; + margin-top: 1rem; + } } </style> +<script> +import AccessService from "./services/AccessService.js"; +import HomeIcon from "@/assets/icons/home.svg"; +import CreateIcon from "@/assets/icons/create.svg"; +import ManageIcon from "@/assets/icons/manage.svg"; +import CatalogIcon from "@/assets/icons/catalog.svg"; +import ResponsesIcon from "@/assets/icons/responses.svg"; +import StockIcon from "@/assets/icons/stock.svg"; + + +export default { + name: "StockView", + components: {}, + data() { + return { + viewsWithAccess: [], + }; + }, + mounted() { + this.viewsWithAccess = AccessService.getViewsWithAccess(); + }, + methods: { + getImagePath(routeName) { + const imageMap = { + dashboard: HomeIcon, + "create order": CreateIcon, + "manage orders": ManageIcon, + catalog: CatalogIcon, + negotiations: CatalogIcon, + transfers: CatalogIcon, + responses: ResponsesIcon, + connectors: ManageIcon, + stocks: StockIcon, + "supplier dashboard": HomeIcon, + }; + return imageMap[routeName.toLowerCase()]; + }, + }, +}; +</script> diff --git a/frontend/src/config.json b/frontend/src/config.json index 26c7f3cf..ed3a5675 100644 --- a/frontend/src/config.json +++ b/frontend/src/config.json @@ -8,5 +8,10 @@ "ENDPOINT_PRODUCT_STOCKS": "$ENDPOINT_PRODUCT_STOCKS", "ENDPOINT_CUSTOMER": "$ENDPOINT_CUSTOMER", "ENDPOINT_PARTNER_PRODUCT_STOCKS": "$ENDPOINT_PARTNER_PRODUCT_STOCKS", - "ENDPOINT_UPDATE_PARTNER_PRODUCT_STOCK":" $ENDPOINT_UPDATE_PARTNER_PRODUCT_STOCK" + "ENDPOINT_UPDATE_PARTNER_PRODUCT_STOCK":" $ENDPOINT_UPDATE_PARTNER_PRODUCT_STOCK", + "IDP_DISABLE": "$IDP_DISABLE", + "IDP_URL": "$IDP_URL", + "IDP_REALM": "$IDP_REALM", + "IDP_CLIENT_ID": "$IDP_CLIENT_ID", + "IDP_REDIRECT_URL_FRONTEND": "$IDP_URL_REDIRECT_FRONTEND" } diff --git a/frontend/src/main.js b/frontend/src/main.js index b54baa7d..01ffac75 100644 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -24,16 +24,29 @@ import App from "./App.vue"; import router from "./router"; import "./index.css"; import JsonViewer from "vue-json-viewer"; -import Config from "./config.json" +import Config from "./config.json"; -const app = createApp(App); -const publicEnvVar = import.meta.env.VITE_BASE_URL; +import AuthenticationService from "./services/AuthenticationService.js"; -app.use(router); -app.use(JsonViewer); +AuthenticationService + .init() + .then(() => { + console.info("User is authenticated, init application"); -console.log("config.json BACKEND_BASE_URL=" + Config.BACKEND_BASE_URL); -console.log(".env.x VITE_BASE_URL=" + import.meta.env.VITE_BASE_URL); + const app = createApp(App); + const publicEnvVar = import.meta.env.VITE_BASE_URL; -app.mount("#app"); -app.provide("baseUrl", publicEnvVar); + app.use(router); + app.use(JsonViewer); + + console.debug("config.json BACKEND_BASE_URL=" + Config.BACKEND_BASE_URL); + console.debug(".env.x VITE_BASE_URL=" + import.meta.env.VITE_BASE_URL); + + app.mount("#app"); + app.provide("baseUrl", publicEnvVar); + }) + .catch((error) => { + console.log(error); + }); + +window.authService = AuthenticationService; diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js index 7b824939..b9bb2f62 100644 --- a/frontend/src/router/index.js +++ b/frontend/src/router/index.js @@ -19,66 +19,122 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { createRouter, createWebHistory } from "vue-router"; +import {createRouter, createWebHistory} from "vue-router"; import HomeView from "../views/HomeView.vue"; +import AuthenticationService from "@/services/AuthenticationService"; -const router = createRouter({ - history: createWebHistory(import.meta.env.BASE_URL), - routes: [ +export const ALL_ROUTES = [ + { + path: "/", + name: "Dashboard", + component: HomeView, + meta: { + requiredRoles: ["PURIS_USER"], + }, + }, { - path: "/", - name: "home", - component: HomeView, + path: "/createOrder", + name: "Create Order", + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import("../views/CreateOrderView.vue"), + meta: { + requiredRoles: ["PURIS_ADMIN"], + }, }, { - path: "/createOrder", - name: "createOrder", - // route level code-splitting - // this generates a separate chunk (About.[hash].js) for this route - // which is lazy-loaded when the route is visited. - component: () => import("../views/CreateOrderView.vue"), + path: "/manageOrders", + name: "Manage Orders", + component: () => import("../views/ManageOrderView.vue"), + meta: { + requiredRoles: ["PURIS_ADMIN"], + }, }, { - path: "/manageOrders", - name: "manageOrders", - component: () => import("../views/ManageOrderView.vue"), + path: "/catalog", + name: "Catalog", + component: () => import("../views/CatalogView.vue"), + meta: { + requiredRoles: ["PURIS_ADMIN"], + }, }, { - path: "/catalog", - name: "catalog", - component: () => import("../views/CatalogView.vue"), + path: "/negotiations", + name: "Negotiations", + component: () => import("../views/NegotiationView.vue"), + meta: { + requiredRoles: ["PURIS_ADMIN"], + }, }, { - path: "/negotiations", - name: "negotitations", - component: () => import("../views/NegotiationView.vue"), + path: "/transfers", + name: "Transfers", + component: () => import("../views/TransferView.vue"), + meta: { + requiredRoles: ["PURIS_ADMIN"], + }, }, { - path: "/transfers", - name: "transfers", - component: () => import("../views/TransferView.vue"), + path: "/responses", + name: "Responses", + component: () => import("../views/OrderResponseView.vue"), + meta: { + requiredRoles: ["PURIS_ADMIN"], + }, }, { - path: "/responses", - name: "responses", - component: () => import("../views/OrderResponseView.vue"), + path: "/connectors", + name: "Connectors", + component: () => import("../views/ConnectorView.vue"), + meta: { + requiredRoles: ["PURIS_ADMIN"], + }, }, { - path: "/connectors", - name: "connectors", - component: () => import("../views/ConnectorView.vue"), + path: "/stocks", + name: "Stocks", + component: () => import("../views/StockView.vue"), + meta: { + requiredRoles: ["PURIS_USER"], + }, }, { - path: "/stocks", - name: "stocks", - component: () => import("../views/StockView.vue") + path: "/supplierDashboard", + name: "Supplier Dashboard", + component: () => import("../views/SupplierDashboard.vue"), + meta: { + requiredRoles: ["PURIS_USER"], + }, }, { - path: "/supplierDashboard", - name: "supplierDashboard", - component: () => import("../views/SupplierDashboard.vue"), + path: "/unauthorized", + name: "Unauthorized", + component: () => import("../views/Unauthorized.vue"), }, - ], +]; + +const requireRole = (to, from, next) => { + const requiredRoles = to.meta.requiredRoles; + + if (!requiredRoles) { + next(); + } + + if (AuthenticationService.userHasRole(requiredRoles)) { + next(); + } else { + next("/unauthorized"); + } +}; + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: ALL_ROUTES, +}); + +router.beforeEach((to, from, next) => { + requireRole(to, from, next); }); export default router; diff --git a/frontend/src/services/AccessService.js b/frontend/src/services/AccessService.js new file mode 100644 index 00000000..624fd2aa --- /dev/null +++ b/frontend/src/services/AccessService.js @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023 Volkswagen AG + * Copyright (c) 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +import {ALL_ROUTES} from "@/router"; +import AuthenticationService from "./AuthenticationService.js"; + +const getViewsWithAccess = () => { + let views = []; + + if (!AuthenticationService.isEnabled) { + return ALL_ROUTES; + } + + ALL_ROUTES.forEach((item) => { + if ( + item.name !== "Unauthorized" && + item.meta && + item.meta.requiredRoles + ) { + if (AuthenticationService.userHasRole(item.meta.requiredRoles)) { + views.push({ + path: item.path, + name: item.name, + }); + } + } + }); + return views; +}; + +const AccessService = { + getViewsWithAccess, +}; + +export default AccessService; diff --git a/frontend/src/services/AuthenticationConfig.js b/frontend/src/services/AuthenticationConfig.js new file mode 100644 index 00000000..8a4f533a --- /dev/null +++ b/frontend/src/services/AuthenticationConfig.js @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023 Volkswagen AG + * Copyright (c) 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +export const isDisabled = + import.meta.env.VITE_IDP_DISABLE === true || + import.meta.env.VITE_IDP_DISABLE === "true"; + +export const getIdpUrl = import.meta.env.VITE_IDP_URL; + +export const getIdpRealm = import.meta.env.VITE_IDP_REALM; + +export const getIdpClientId = import.meta.env.VITE_IDP_CLIENT_ID; + +export const getIdpRedirectUrlFrontend = import.meta.env + .VITE_IDP_REDIRECT_URL_FRONTEND; + +const AuthenticationConfig = { + isDisabled, + getIdpUrl, + getIdpRealm, + getIdpClientId, + getIdpRedirectUrlFrontend, +}; + +export default AuthenticationConfig; diff --git a/frontend/src/services/AuthenticationService.js b/frontend/src/services/AuthenticationService.js new file mode 100644 index 00000000..db592687 --- /dev/null +++ b/frontend/src/services/AuthenticationService.js @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2023 Volkswagen AG + * Copyright (c) 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +import Keycloak from "keycloak-js"; +import AuthenticationConfig, { + getIdpClientId, + getIdpRealm, + getIdpRedirectUrlFrontend, + getIdpUrl, +} from "@/services/AuthenticationConfig"; + +const keycloak = new Keycloak({ + onLoad: "login-required", + url: getIdpUrl, + realm: getIdpRealm, + clientId: getIdpClientId, + redirectUri: getIdpRedirectUrlFrontend, +}); + +const isEnabled = AuthenticationConfig.isDisabled !== true; + +const init = () => { + return new Promise((resolve, reject) => { + console.log(AuthenticationConfig.isDisabled); + console.log(isEnabled); + if (!isEnabled) { + return resolve(); + } + keycloak + .init({ onLoad: "login-required" }) + .then((authenticated) => { + if (!authenticated) { + // User is not authenticated + reject(); + } else { + // authenticated + resolve(); + } + }) + .catch((error) => { + console.error("Not authenticated:", error); + reject(error); + }); + }); +}; + +const isAuthenticated = () => { + if (!isEnabled) { + return true; + } + return keycloak.authenticated; +}; + +const userHasRole = (requiredRoles) => { + if (!isEnabled) { + return true; + } + // client roles + const rolesPerClient = keycloak.tokenParsed.resource_access; + const userRoles = rolesPerClient[getIdpClientId].roles; + // require every role, not some + return requiredRoles.every((role) => userRoles.includes(role)); +}; + +const logout = () => { + keycloak + .logout() + .then((success) => { + console.info("Logged out: ", success); + }) + .catch((error) => { + console.error("Logout failed: ", error); + }); +}; + +const AuthenticationService = { + isEnabled, + init, + logout, + isAuthenticated, + userHasRole, +}; + +export default AuthenticationService; diff --git a/frontend/src/views/Unauthorized.vue b/frontend/src/views/Unauthorized.vue new file mode 100644 index 00000000..66269dcf --- /dev/null +++ b/frontend/src/views/Unauthorized.vue @@ -0,0 +1,31 @@ +<!-- + Copyright (c) 2023 Volkswagen AG + Copyright (c) 2023 Contributors to the Eclipse Foundation + + See the NOTICE file(s) distributed with this work for additional + information regarding copyright ownership. + + This program and the accompanying materials are made available under the + terms of the Apache License, Version 2.0 which is available at + https://www.apache.org/licenses/LICENSE-2.0. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + License for the specific language governing permissions and limitations + under the License. + + SPDX-License-Identifier: Apache-2.0 +--> +<template> + <main> + <h1 class="w-full text-center bold text-5xl mb-6 pb-6"> + You're not allowed to see the requested dialog. + </h1> + <p> + Please contact your application administrator to request further + rights. + </p> + </main> +</template> +<script setup></script> diff --git a/local/keycloak/INSTALL.md b/local/keycloak/INSTALL.md new file mode 100644 index 00000000..c5e47d19 --- /dev/null +++ b/local/keycloak/INSTALL.md @@ -0,0 +1,13 @@ +# Running the Keyckloak with a Sample Realm + +Runs a Keycloak with an `admin` user overall and a user `puris_user` with the roles `PURIS_ADMIN` and `PURIS_USER` in +the client `Cl3-PURIS`. Username = Password. + +```sh +cd local/keycloak +docker run -p 10081:8080 --name keycloak \ +-e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin \ +-v ./puris-config/:/opt/keycloak/data/import \ +quay.io/keycloak/keycloak:23.0 \ +start-dev --import-realm +``` diff --git a/local/keycloak/puris-config/.gitignore b/local/keycloak/puris-config/.gitignore new file mode 100644 index 00000000..b14951a0 --- /dev/null +++ b/local/keycloak/puris-config/.gitignore @@ -0,0 +1 @@ +h2/* diff --git a/local/keycloak/puris-config/Catena-X-realm.json b/local/keycloak/puris-config/Catena-X-realm.json new file mode 100644 index 00000000..e72076bf --- /dev/null +++ b/local/keycloak/puris-config/Catena-X-realm.json @@ -0,0 +1,1773 @@ +{ + "id" : "be3d4b77-098b-4ae2-b9dd-4f8e42a2462b", + "realm" : "Catena-X", + "notBefore" : 0, + "defaultSignatureAlgorithm" : "RS256", + "revokeRefreshToken" : false, + "refreshTokenMaxReuse" : 0, + "accessTokenLifespan" : 300, + "accessTokenLifespanForImplicitFlow" : 900, + "ssoSessionIdleTimeout" : 1800, + "ssoSessionMaxLifespan" : 36000, + "ssoSessionIdleTimeoutRememberMe" : 0, + "ssoSessionMaxLifespanRememberMe" : 0, + "offlineSessionIdleTimeout" : 2592000, + "offlineSessionMaxLifespanEnabled" : false, + "offlineSessionMaxLifespan" : 5184000, + "clientSessionIdleTimeout" : 0, + "clientSessionMaxLifespan" : 0, + "clientOfflineSessionIdleTimeout" : 0, + "clientOfflineSessionMaxLifespan" : 0, + "accessCodeLifespan" : 60, + "accessCodeLifespanUserAction" : 300, + "accessCodeLifespanLogin" : 1800, + "actionTokenGeneratedByAdminLifespan" : 43200, + "actionTokenGeneratedByUserLifespan" : 300, + "oauth2DeviceCodeLifespan" : 600, + "oauth2DevicePollingInterval" : 5, + "enabled" : true, + "sslRequired" : "external", + "registrationAllowed" : false, + "registrationEmailAsUsername" : false, + "rememberMe" : false, + "verifyEmail" : false, + "loginWithEmailAllowed" : true, + "duplicateEmailsAllowed" : false, + "resetPasswordAllowed" : false, + "editUsernameAllowed" : false, + "bruteForceProtected" : false, + "permanentLockout" : false, + "maxFailureWaitSeconds" : 900, + "minimumQuickLoginWaitSeconds" : 60, + "waitIncrementSeconds" : 60, + "quickLoginCheckMilliSeconds" : 1000, + "maxDeltaTimeSeconds" : 43200, + "failureFactor" : 30, + "roles" : { + "realm" : [ { + "id" : "a7d49e7b-4554-4e59-a68d-51212d31f66a", + "name" : "offline_access", + "description" : "${role_offline-access}", + "composite" : false, + "clientRole" : false, + "containerId" : "be3d4b77-098b-4ae2-b9dd-4f8e42a2462b", + "attributes" : { } + }, { + "id" : "a2157cee-c377-409f-8d0c-74a1dd61f960", + "name" : "default-roles-catena-x", + "description" : "${role_default-roles}", + "composite" : true, + "composites" : { + "realm" : [ "offline_access", "uma_authorization" ], + "client" : { + "account" : [ "view-profile", "manage-account" ] + } + }, + "clientRole" : false, + "containerId" : "be3d4b77-098b-4ae2-b9dd-4f8e42a2462b", + "attributes" : { } + }, { + "id" : "2a4b277c-5f71-4ad6-a2e2-419171dfd6a9", + "name" : "uma_authorization", + "description" : "${role_uma_authorization}", + "composite" : false, + "clientRole" : false, + "containerId" : "be3d4b77-098b-4ae2-b9dd-4f8e42a2462b", + "attributes" : { } + } ], + "client" : { + "realm-management" : [ { + "id" : "3c6b3c11-59cb-40ec-bc11-8172bf949286", + "name" : "query-users", + "description" : "${role_query-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "5a19b4b7-0fa2-49ce-9d52-4b215cb7387f", + "attributes" : { } + }, { + "id" : "810cc6d8-5f7c-411f-852b-4086ea7c30cb", + "name" : "realm-admin", + "description" : "${role_realm-admin}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-users", "create-client", "view-realm", "query-clients", "manage-identity-providers", "manage-users", "view-users", "query-groups", "view-events", "view-clients", "impersonation", "manage-realm", "view-authorization", "manage-events", "manage-clients", "manage-authorization", "view-identity-providers", "query-realms" ] + } + }, + "clientRole" : true, + "containerId" : "5a19b4b7-0fa2-49ce-9d52-4b215cb7387f", + "attributes" : { } + }, { + "id" : "9ea2abea-9309-4d4b-a953-643f27093d71", + "name" : "create-client", + "description" : "${role_create-client}", + "composite" : false, + "clientRole" : true, + "containerId" : "5a19b4b7-0fa2-49ce-9d52-4b215cb7387f", + "attributes" : { } + }, { + "id" : "b56d9f23-3484-4a87-8d75-3ae3833c936e", + "name" : "view-realm", + "description" : "${role_view-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "5a19b4b7-0fa2-49ce-9d52-4b215cb7387f", + "attributes" : { } + }, { + "id" : "53a7054d-7ed8-433f-b6e2-876fac99712e", + "name" : "query-clients", + "description" : "${role_query-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "5a19b4b7-0fa2-49ce-9d52-4b215cb7387f", + "attributes" : { } + }, { + "id" : "b1166840-946f-44f7-9201-ea99bc48ad2d", + "name" : "manage-identity-providers", + "description" : "${role_manage-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "5a19b4b7-0fa2-49ce-9d52-4b215cb7387f", + "attributes" : { } + }, { + "id" : "2c153bc0-0bd7-4214-a09c-607a13855cec", + "name" : "manage-users", + "description" : "${role_manage-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "5a19b4b7-0fa2-49ce-9d52-4b215cb7387f", + "attributes" : { } + }, { + "id" : "53e57dcc-0358-4461-a952-748bcff94d73", + "name" : "view-users", + "description" : "${role_view-users}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-users", "query-groups" ] + } + }, + "clientRole" : true, + "containerId" : "5a19b4b7-0fa2-49ce-9d52-4b215cb7387f", + "attributes" : { } + }, { + "id" : "6cbbaac9-ad06-4f22-aef9-31df9701322d", + "name" : "query-groups", + "description" : "${role_query-groups}", + "composite" : false, + "clientRole" : true, + "containerId" : "5a19b4b7-0fa2-49ce-9d52-4b215cb7387f", + "attributes" : { } + }, { + "id" : "e014856d-dad8-484a-a969-73aefef33665", + "name" : "impersonation", + "description" : "${role_impersonation}", + "composite" : false, + "clientRole" : true, + "containerId" : "5a19b4b7-0fa2-49ce-9d52-4b215cb7387f", + "attributes" : { } + }, { + "id" : "d371af2b-9fe1-485f-a629-a64ddfd54022", + "name" : "view-clients", + "description" : "${role_view-clients}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-clients" ] + } + }, + "clientRole" : true, + "containerId" : "5a19b4b7-0fa2-49ce-9d52-4b215cb7387f", + "attributes" : { } + }, { + "id" : "c91ff348-3248-40b3-8e5a-1c7157e12ac5", + "name" : "view-events", + "description" : "${role_view-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "5a19b4b7-0fa2-49ce-9d52-4b215cb7387f", + "attributes" : { } + }, { + "id" : "5fb4579b-5a88-4fac-ab57-1aa316c779a3", + "name" : "manage-realm", + "description" : "${role_manage-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "5a19b4b7-0fa2-49ce-9d52-4b215cb7387f", + "attributes" : { } + }, { + "id" : "e90258d7-4ac4-4a2e-9d5c-c86d6ccaef8e", + "name" : "view-authorization", + "description" : "${role_view-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "5a19b4b7-0fa2-49ce-9d52-4b215cb7387f", + "attributes" : { } + }, { + "id" : "84fd7be8-b2b9-46ce-85e7-0d2885e928c9", + "name" : "manage-clients", + "description" : "${role_manage-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "5a19b4b7-0fa2-49ce-9d52-4b215cb7387f", + "attributes" : { } + }, { + "id" : "5f826230-ae91-4e37-88dd-12b7f2e9c9c1", + "name" : "manage-events", + "description" : "${role_manage-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "5a19b4b7-0fa2-49ce-9d52-4b215cb7387f", + "attributes" : { } + }, { + "id" : "26a48b73-2032-45e9-85df-85c97d98aee3", + "name" : "manage-authorization", + "description" : "${role_manage-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "5a19b4b7-0fa2-49ce-9d52-4b215cb7387f", + "attributes" : { } + }, { + "id" : "2b2296c7-7d62-4c52-85e9-36bcbdae402e", + "name" : "view-identity-providers", + "description" : "${role_view-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "5a19b4b7-0fa2-49ce-9d52-4b215cb7387f", + "attributes" : { } + }, { + "id" : "ef97f160-4996-486f-acf4-08d853136781", + "name" : "query-realms", + "description" : "${role_query-realms}", + "composite" : false, + "clientRole" : true, + "containerId" : "5a19b4b7-0fa2-49ce-9d52-4b215cb7387f", + "attributes" : { } + } ], + "security-admin-console" : [ ], + "admin-cli" : [ ], + "Cl3-PURIS" : [ { + "id" : "c2b56263-30f6-40ad-a946-25914617a153", + "name" : "PURIS_ADMIN", + "description" : "", + "composite" : false, + "clientRole" : true, + "containerId" : "dd367f8e-cbaf-4fa1-902d-b4ec0a5347ac", + "attributes" : { } + }, { + "id" : "ab05490d-50dd-46c9-9843-87cdee3cfe37", + "name" : "PURIS_USER", + "description" : "", + "composite" : false, + "clientRole" : true, + "containerId" : "dd367f8e-cbaf-4fa1-902d-b4ec0a5347ac", + "attributes" : { } + } ], + "account-console" : [ ], + "broker" : [ { + "id" : "f2391498-2b41-4ba4-8863-b9419549d3da", + "name" : "read-token", + "description" : "${role_read-token}", + "composite" : false, + "clientRole" : true, + "containerId" : "ecf8a290-3181-4cae-9595-694fc1193c01", + "attributes" : { } + } ], + "account" : [ { + "id" : "6407638a-ec04-4379-9f9c-c752da4c5eaf", + "name" : "view-groups", + "description" : "${role_view-groups}", + "composite" : false, + "clientRole" : true, + "containerId" : "3e1b31f2-b262-44f6-a4b3-52d2abb1fe25", + "attributes" : { } + }, { + "id" : "0d4f1e45-11f2-4141-82d6-3ef8e6472fbe", + "name" : "view-consent", + "description" : "${role_view-consent}", + "composite" : false, + "clientRole" : true, + "containerId" : "3e1b31f2-b262-44f6-a4b3-52d2abb1fe25", + "attributes" : { } + }, { + "id" : "5f6f6481-3b52-450c-96c3-2e495d5ecb45", + "name" : "view-profile", + "description" : "${role_view-profile}", + "composite" : false, + "clientRole" : true, + "containerId" : "3e1b31f2-b262-44f6-a4b3-52d2abb1fe25", + "attributes" : { } + }, { + "id" : "c34824e6-d04f-46ae-bf1a-5af2d2c42010", + "name" : "manage-consent", + "description" : "${role_manage-consent}", + "composite" : true, + "composites" : { + "client" : { + "account" : [ "view-consent" ] + } + }, + "clientRole" : true, + "containerId" : "3e1b31f2-b262-44f6-a4b3-52d2abb1fe25", + "attributes" : { } + }, { + "id" : "a81a858a-4692-46aa-8180-9d44352b2a28", + "name" : "view-applications", + "description" : "${role_view-applications}", + "composite" : false, + "clientRole" : true, + "containerId" : "3e1b31f2-b262-44f6-a4b3-52d2abb1fe25", + "attributes" : { } + }, { + "id" : "e4e587c6-a262-4747-bf01-a89e972789c6", + "name" : "manage-account", + "description" : "${role_manage-account}", + "composite" : true, + "composites" : { + "client" : { + "account" : [ "manage-account-links" ] + } + }, + "clientRole" : true, + "containerId" : "3e1b31f2-b262-44f6-a4b3-52d2abb1fe25", + "attributes" : { } + }, { + "id" : "5e2fd496-f7e3-43a1-bb68-2691c9669c67", + "name" : "delete-account", + "description" : "${role_delete-account}", + "composite" : false, + "clientRole" : true, + "containerId" : "3e1b31f2-b262-44f6-a4b3-52d2abb1fe25", + "attributes" : { } + }, { + "id" : "08491cb8-671e-4b69-9d00-adf54f8e031e", + "name" : "manage-account-links", + "description" : "${role_manage-account-links}", + "composite" : false, + "clientRole" : true, + "containerId" : "3e1b31f2-b262-44f6-a4b3-52d2abb1fe25", + "attributes" : { } + } ] + } + }, + "groups" : [ ], + "defaultRole" : { + "id" : "a2157cee-c377-409f-8d0c-74a1dd61f960", + "name" : "default-roles-catena-x", + "description" : "${role_default-roles}", + "composite" : true, + "clientRole" : false, + "containerId" : "be3d4b77-098b-4ae2-b9dd-4f8e42a2462b" + }, + "requiredCredentials" : [ "password" ], + "otpPolicyType" : "totp", + "otpPolicyAlgorithm" : "HmacSHA1", + "otpPolicyInitialCounter" : 0, + "otpPolicyDigits" : 6, + "otpPolicyLookAheadWindow" : 1, + "otpPolicyPeriod" : 30, + "otpPolicyCodeReusable" : false, + "otpSupportedApplications" : [ "totpAppFreeOTPName", "totpAppGoogleName", "totpAppMicrosoftAuthenticatorName" ], + "localizationTexts" : { }, + "webAuthnPolicyRpEntityName" : "keycloak", + "webAuthnPolicySignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicyRpId" : "", + "webAuthnPolicyAttestationConveyancePreference" : "not specified", + "webAuthnPolicyAuthenticatorAttachment" : "not specified", + "webAuthnPolicyRequireResidentKey" : "not specified", + "webAuthnPolicyUserVerificationRequirement" : "not specified", + "webAuthnPolicyCreateTimeout" : 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister" : false, + "webAuthnPolicyAcceptableAaguids" : [ ], + "webAuthnPolicyExtraOrigins" : [ ], + "webAuthnPolicyPasswordlessRpEntityName" : "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicyPasswordlessRpId" : "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference" : "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment" : "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey" : "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement" : "not specified", + "webAuthnPolicyPasswordlessCreateTimeout" : 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister" : false, + "webAuthnPolicyPasswordlessAcceptableAaguids" : [ ], + "webAuthnPolicyPasswordlessExtraOrigins" : [ ], + "scopeMappings" : [ { + "clientScope" : "offline_access", + "roles" : [ "offline_access" ] + } ], + "clientScopeMappings" : { + "account" : [ { + "client" : "account-console", + "roles" : [ "manage-account", "view-groups" ] + } ] + }, + "clients" : [ { + "id" : "dd367f8e-cbaf-4fa1-902d-b4ec0a5347ac", + "clientId" : "Cl3-PURIS", + "name" : "", + "description" : "", + "rootUrl" : "", + "adminUrl" : "", + "baseUrl" : "", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "http://localhost:3000/*" ], + "webOrigins" : [ "http://localhost:3000" ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : true, + "protocol" : "openid-connect", + "attributes" : { + "client.secret.creation.time" : "1701016951", + "post.logout.redirect.uris" : "http://localhost:10081", + "oauth2.device.authorization.grant.enabled" : "false", + "backchannel.logout.revoke.offline.tokens" : "false", + "use.refresh.tokens" : "true", + "oidc.ciba.grant.enabled" : "false", + "backchannel.logout.session.required" : "true", + "client_credentials.use_refresh_token" : "false", + "tls.client.certificate.bound.access.tokens" : "false", + "require.pushed.authorization.requests" : "false", + "acr.loa.map" : "{}", + "display.on.consent.screen" : "false", + "token.response.type.bearer.lower-case" : "false" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : true, + "nodeReRegistrationTimeout" : -1, + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "3e1b31f2-b262-44f6-a4b3-52d2abb1fe25", + "clientId" : "account", + "name" : "${client_account}", + "rootUrl" : "${authBaseUrl}", + "baseUrl" : "/realms/Catena-X/account/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/realms/Catena-X/account/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "2d57edc7-5839-4254-a7dc-07b5b187c92e", + "clientId" : "account-console", + "name" : "${client_account-console}", + "rootUrl" : "${authBaseUrl}", + "baseUrl" : "/realms/Catena-X/account/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/realms/Catena-X/account/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+", + "pkce.code.challenge.method" : "S256" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "protocolMappers" : [ { + "id" : "3f177bd5-fa01-4ef2-8228-9e1c742c079d", + "name" : "audience resolve", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-audience-resolve-mapper", + "consentRequired" : false, + "config" : { } + } ], + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "5ea83b86-4cf4-4562-b565-f691af2af82f", + "clientId" : "admin-cli", + "name" : "${client_admin-cli}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : false, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : true, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "ecf8a290-3181-4cae-9595-694fc1193c01", + "clientId" : "broker", + "name" : "${client_broker}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : true, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "5a19b4b7-0fa2-49ce-9d52-4b215cb7387f", + "clientId" : "realm-management", + "name" : "${client_realm-management}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : true, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "7cd3e481-e507-4120-9593-15a7e145ebe9", + "clientId" : "security-admin-console", + "name" : "${client_security-admin-console}", + "rootUrl" : "${authAdminUrl}", + "baseUrl" : "/admin/Catena-X/console/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/admin/Catena-X/console/*" ], + "webOrigins" : [ "+" ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+", + "pkce.code.challenge.method" : "S256" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "protocolMappers" : [ { + "id" : "cf64f966-1e38-4d24-bcff-4fc6baba35bf", + "name" : "locale", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "locale", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "locale", + "jsonType.label" : "String" + } + } ], + "defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + } ], + "clientScopes" : [ { + "id" : "c3c225b3-f984-46cd-b13f-3691afaa951e", + "name" : "roles", + "description" : "OpenID Connect scope for add user roles to the access token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${rolesScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "6e5a2508-842c-4f52-a992-98f229e5b468", + "name" : "audience resolve", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-audience-resolve-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "access.token.claim" : "true" + } + }, { + "id" : "0153d146-07a1-4d39-80aa-23087a0733b5", + "name" : "realm roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "multivalued" : "true", + "user.attribute" : "foo", + "access.token.claim" : "true", + "claim.name" : "realm_access.roles", + "jsonType.label" : "String" + } + }, { + "id" : "fda19761-3ada-4dc0-8080-0a829d354b79", + "name" : "client roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-client-role-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "multivalued" : "true", + "user.attribute" : "foo", + "access.token.claim" : "true", + "claim.name" : "resource_access.${client_id}.roles", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "97c066f1-c23f-42de-a6a7-97cefe03e974", + "name" : "offline_access", + "description" : "OpenID Connect built-in scope: offline_access", + "protocol" : "openid-connect", + "attributes" : { + "consent.screen.text" : "${offlineAccessScopeConsentText}", + "display.on.consent.screen" : "true" + } + }, { + "id" : "38da5ece-b8a9-4a64-8613-e80da7d49045", + "name" : "microprofile-jwt", + "description" : "Microprofile - JWT built-in scope", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "775a26d0-2282-4803-8e14-d6ed53af1dad", + "name" : "groups", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "multivalued" : "true", + "user.attribute" : "foo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "groups", + "jsonType.label" : "String" + } + }, { + "id" : "a1862766-36b9-480d-991a-43aa10dd749a", + "name" : "upn", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "upn", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "0c2f213d-47fa-40ef-acf3-124595908624", + "name" : "profile", + "description" : "OpenID Connect built-in scope: profile", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${profileScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "2768c793-36e2-4b7c-8d35-4a9b839302b1", + "name" : "username", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "preferred_username", + "jsonType.label" : "String" + } + }, { + "id" : "fa373770-9f00-4990-b48a-a0859fdd38f3", + "name" : "nickname", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "nickname", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "nickname", + "jsonType.label" : "String" + } + }, { + "id" : "75bfb247-a344-4b0c-9b53-5711438871b9", + "name" : "picture", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "picture", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "picture", + "jsonType.label" : "String" + } + }, { + "id" : "ec4568a3-355b-4ec5-b35a-9595baf4cf09", + "name" : "middle name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "middleName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "middle_name", + "jsonType.label" : "String" + } + }, { + "id" : "7cdc5b47-efd1-41b1-8109-c7ffcb8c5fbd", + "name" : "profile", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "profile", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "profile", + "jsonType.label" : "String" + } + }, { + "id" : "aa3e582d-7de3-4e20-b947-78e376972975", + "name" : "updated at", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "updatedAt", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "updated_at", + "jsonType.label" : "long" + } + }, { + "id" : "bbc2be47-abfc-4043-be6a-a87b452bffef", + "name" : "locale", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "locale", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "locale", + "jsonType.label" : "String" + } + }, { + "id" : "65263902-1164-4275-bd1e-ea96cce73ed1", + "name" : "given name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "firstName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "given_name", + "jsonType.label" : "String" + } + }, { + "id" : "fa4d4853-b99d-4e1f-8cbf-4b1e424c2eec", + "name" : "family name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "lastName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "family_name", + "jsonType.label" : "String" + } + }, { + "id" : "3f87cb75-101a-4a41-bc92-fb694a642e27", + "name" : "zoneinfo", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "zoneinfo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "zoneinfo", + "jsonType.label" : "String" + } + }, { + "id" : "78f5d1e5-dc8a-4bab-9a70-44c897fb158d", + "name" : "birthdate", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "birthdate", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "birthdate", + "jsonType.label" : "String" + } + }, { + "id" : "43f6eee2-e803-43d5-8df1-f49c5976895e", + "name" : "website", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "website", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "website", + "jsonType.label" : "String" + } + }, { + "id" : "2a51bb3f-940d-46a9-a7b1-666a9f84e268", + "name" : "gender", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "gender", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "gender", + "jsonType.label" : "String" + } + }, { + "id" : "cfecaebb-5b5c-41aa-b816-8d9ed6cdd54e", + "name" : "full name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-full-name-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "true", + "introspection.token.claim" : "true", + "access.token.claim" : "true", + "userinfo.token.claim" : "true" + } + } ] + }, { + "id" : "3fb68918-5fa7-408a-8a41-d99954e9f2df", + "name" : "email", + "description" : "OpenID Connect built-in scope: email", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${emailScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "7fe2ef56-8d0d-4ac4-aac7-6e833b875213", + "name" : "email", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "email", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "email", + "jsonType.label" : "String" + } + }, { + "id" : "03050ffb-5a1e-40c3-bfc7-c42b27b75772", + "name" : "email verified", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "emailVerified", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "email_verified", + "jsonType.label" : "boolean" + } + } ] + }, { + "id" : "e9a065ed-9aad-41df-95ec-f2c8c56cfedf", + "name" : "phone", + "description" : "OpenID Connect built-in scope: phone", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${phoneScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "f74bafdd-a85f-4869-a05b-0e880162f354", + "name" : "phone number", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "phoneNumber", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "phone_number", + "jsonType.label" : "String" + } + }, { + "id" : "eb04f9bd-e338-4798-bf5b-5e3e01c084bf", + "name" : "phone number verified", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "phoneNumberVerified", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "phone_number_verified", + "jsonType.label" : "boolean" + } + } ] + }, { + "id" : "8eb41c72-9d49-4951-814c-c0f610122d5d", + "name" : "web-origins", + "description" : "OpenID Connect scope for add allowed web origins to the access token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "false", + "consent.screen.text" : "" + }, + "protocolMappers" : [ { + "id" : "277c0779-35c1-4851-95f1-deab14447840", + "name" : "allowed web origins", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-allowed-origins-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "access.token.claim" : "true" + } + } ] + }, { + "id" : "10376144-40f1-46c2-aa55-1833e8756138", + "name" : "acr", + "description" : "OpenID Connect scope for add acr (authentication context class reference) to the token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "8bd44f1d-c469-4f3e-8178-39212f666d74", + "name" : "acr loa level", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-acr-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "true", + "introspection.token.claim" : "true", + "access.token.claim" : "true" + } + } ] + }, { + "id" : "67040209-32ce-4623-a119-e88b709cfd20", + "name" : "role_list", + "description" : "SAML role list", + "protocol" : "saml", + "attributes" : { + "consent.screen.text" : "${samlRoleListScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "fdb9b44b-41c4-4e97-9a25-5715a591e5b5", + "name" : "role list", + "protocol" : "saml", + "protocolMapper" : "saml-role-list-mapper", + "consentRequired" : false, + "config" : { + "single" : "false", + "attribute.nameformat" : "Basic", + "attribute.name" : "Role" + } + } ] + }, { + "id" : "82bd6c53-5bcf-4312-a124-fea75b0ab26d", + "name" : "address", + "description" : "OpenID Connect built-in scope: address", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${addressScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "dbde7272-d7b6-4db3-ac4b-14bde36199a9", + "name" : "address", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-address-mapper", + "consentRequired" : false, + "config" : { + "user.attribute.formatted" : "formatted", + "user.attribute.country" : "country", + "introspection.token.claim" : "true", + "user.attribute.postal_code" : "postal_code", + "userinfo.token.claim" : "true", + "user.attribute.street" : "street", + "id.token.claim" : "true", + "user.attribute.region" : "region", + "access.token.claim" : "true", + "user.attribute.locality" : "locality" + } + } ] + } ], + "defaultDefaultClientScopes" : [ "role_list", "profile", "email", "roles", "web-origins", "acr" ], + "defaultOptionalClientScopes" : [ "offline_access", "address", "phone", "microprofile-jwt" ], + "browserSecurityHeaders" : { + "contentSecurityPolicyReportOnly" : "", + "xContentTypeOptions" : "nosniff", + "referrerPolicy" : "no-referrer", + "xRobotsTag" : "none", + "xFrameOptions" : "SAMEORIGIN", + "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection" : "1; mode=block", + "strictTransportSecurity" : "max-age=31536000; includeSubDomains" + }, + "smtpServer" : { }, + "eventsEnabled" : false, + "eventsListeners" : [ "jboss-logging" ], + "enabledEventTypes" : [ ], + "adminEventsEnabled" : false, + "adminEventsDetailsEnabled" : false, + "identityProviders" : [ ], + "identityProviderMappers" : [ ], + "components" : { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ { + "id" : "59b98094-0626-4bd9-990b-7c8532d4c7d0", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allow-default-scopes" : [ "true" ] + } + }, { + "id" : "9dd3682b-79e7-4720-9abb-2681c1cce4ad", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allow-default-scopes" : [ "true" ] + } + }, { + "id" : "0f476557-19c4-4065-b178-baaa3fec1b7a", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "oidc-address-mapper", "oidc-usermodel-property-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-property-mapper", "oidc-usermodel-attribute-mapper", "oidc-full-name-mapper", "saml-role-list-mapper", "saml-user-attribute-mapper" ] + } + }, { + "id" : "e4b4318d-3cdc-4b3e-98bf-f8b7cdeccd97", + "name" : "Full Scope Disabled", + "providerId" : "scope", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + }, { + "id" : "941b0de9-ae9c-44fd-a7f5-e067c83d67f3", + "name" : "Consent Required", + "providerId" : "consent-required", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + }, { + "id" : "2ab90d45-8b37-47cd-8beb-c256e45098f1", + "name" : "Max Clients Limit", + "providerId" : "max-clients", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "max-clients" : [ "200" ] + } + }, { + "id" : "1512ca77-1b2d-4cee-83b3-920a5d8d8e38", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "oidc-usermodel-attribute-mapper", "saml-user-property-mapper", "oidc-full-name-mapper", "saml-role-list-mapper", "oidc-address-mapper", "oidc-usermodel-property-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-attribute-mapper" ] + } + }, { + "id" : "cf67ce32-0ed5-407a-9285-8d6b742124a2", + "name" : "Trusted Hosts", + "providerId" : "trusted-hosts", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "host-sending-registration-request-must-match" : [ "true" ], + "client-uris-must-match" : [ "true" ] + } + } ] + }, + "internationalizationEnabled" : false, + "supportedLocales" : [ ], + "authenticationFlows" : [ { + "id" : "de7b472e-9144-4360-aff6-e181195c5901", + "alias" : "Account verification options", + "description" : "Method with which to verity the existing account", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-email-verification", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Verify Existing Account by Re-authentication", + "userSetupAllowed" : false + } ] + }, { + "id" : "935d23cc-d8a1-41b5-94fc-bbe2f138e735", + "alias" : "Browser - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-otp-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "66c641cc-7867-4df8-831c-f108d83e20ee", + "alias" : "Direct Grant - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "direct-grant-validate-otp", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "430ba95d-19d0-4127-a551-5b53364e3ae1", + "alias" : "First broker login - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-otp-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "6cf39c2b-50b5-4c48-9e77-60e9e97a7cee", + "alias" : "Handle Existing Account", + "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-confirm-link", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Account verification options", + "userSetupAllowed" : false + } ] + }, { + "id" : "2865c7ea-de6c-42c8-969e-9063cf8f7921", + "alias" : "Reset - Conditional OTP", + "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-otp", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "b021f8a5-8203-4cef-8e29-a4bdf1d7d7e0", + "alias" : "User creation or linking", + "description" : "Flow for the existing/non-existing user alternatives", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorConfig" : "create unique user config", + "authenticator" : "idp-create-user-if-unique", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Handle Existing Account", + "userSetupAllowed" : false + } ] + }, { + "id" : "0ebb639a-37d9-4fa2-850b-89bbc0e3b36a", + "alias" : "Verify Existing Account by Re-authentication", + "description" : "Reauthentication of existing account", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-username-password-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "First broker login - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "6ee4ef30-837c-48a1-8aa6-cf102e02dc68", + "alias" : "browser", + "description" : "browser based authentication", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "auth-cookie", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-spnego", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "identity-provider-redirector", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 25, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 30, + "autheticatorFlow" : true, + "flowAlias" : "forms", + "userSetupAllowed" : false + } ] + }, { + "id" : "b2411720-7368-4f2b-9311-d2a154bdce4e", + "alias" : "clients", + "description" : "Base authentication for clients", + "providerId" : "client-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "client-secret", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-jwt", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-secret-jwt", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 30, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-x509", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 40, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "bee41ff8-2f71-40a2-a868-17850b9ad4f0", + "alias" : "direct grant", + "description" : "OpenID Connect Resource Owner Grant", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "direct-grant-validate-username", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "direct-grant-validate-password", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 30, + "autheticatorFlow" : true, + "flowAlias" : "Direct Grant - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "a71def74-9bd3-4559-8129-89b264ad490b", + "alias" : "docker auth", + "description" : "Used by Docker clients to authenticate against the IDP", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "docker-http-basic-authenticator", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "f582a78b-c909-403f-8700-4cb9b2e2587f", + "alias" : "first broker login", + "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorConfig" : "review profile config", + "authenticator" : "idp-review-profile", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "User creation or linking", + "userSetupAllowed" : false + } ] + }, { + "id" : "f3483166-d549-46e1-b897-891232b31d71", + "alias" : "forms", + "description" : "Username, password, otp and other auth forms.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "auth-username-password-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Browser - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "7dccd7cc-57d5-453a-a3d2-941ee78b031e", + "alias" : "registration", + "description" : "registration flow", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "registration-page-form", + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : true, + "flowAlias" : "registration form", + "userSetupAllowed" : false + } ] + }, { + "id" : "fdcdd8fb-1fa0-4fbd-a951-1ed9d18d3c8c", + "alias" : "registration form", + "description" : "registration form", + "providerId" : "form-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "registration-user-creation", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-password-action", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 50, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-recaptcha-action", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 60, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "527b33c8-c7f4-4972-b2a6-9008924b515a", + "alias" : "reset credentials", + "description" : "Reset credentials for a user if they forgot their password or something", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "reset-credentials-choose-user", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-credential-email", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-password", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 30, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 40, + "autheticatorFlow" : true, + "flowAlias" : "Reset - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "c0da09f3-5c27-482b-8d86-3f05fc8cd3bf", + "alias" : "saml ecp", + "description" : "SAML ECP Profile Authentication Flow", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "http-basic-authenticator", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + } ], + "authenticatorConfig" : [ { + "id" : "6a1caf93-c329-45a5-a187-261221bbe2c9", + "alias" : "create unique user config", + "config" : { + "require.password.update.after.registration" : "false" + } + }, { + "id" : "fe3d90d4-4c54-444c-9492-f513adff85eb", + "alias" : "review profile config", + "config" : { + "update.profile.on.first.login" : "missing" + } + } ], + "requiredActions" : [ { + "alias" : "CONFIGURE_TOTP", + "name" : "Configure OTP", + "providerId" : "CONFIGURE_TOTP", + "enabled" : true, + "defaultAction" : false, + "priority" : 10, + "config" : { } + }, { + "alias" : "TERMS_AND_CONDITIONS", + "name" : "Terms and Conditions", + "providerId" : "TERMS_AND_CONDITIONS", + "enabled" : false, + "defaultAction" : false, + "priority" : 20, + "config" : { } + }, { + "alias" : "UPDATE_PASSWORD", + "name" : "Update Password", + "providerId" : "UPDATE_PASSWORD", + "enabled" : true, + "defaultAction" : false, + "priority" : 30, + "config" : { } + }, { + "alias" : "UPDATE_PROFILE", + "name" : "Update Profile", + "providerId" : "UPDATE_PROFILE", + "enabled" : true, + "defaultAction" : false, + "priority" : 40, + "config" : { } + }, { + "alias" : "VERIFY_EMAIL", + "name" : "Verify Email", + "providerId" : "VERIFY_EMAIL", + "enabled" : true, + "defaultAction" : false, + "priority" : 50, + "config" : { } + }, { + "alias" : "delete_account", + "name" : "Delete Account", + "providerId" : "delete_account", + "enabled" : false, + "defaultAction" : false, + "priority" : 60, + "config" : { } + }, { + "alias" : "webauthn-register", + "name" : "Webauthn Register", + "providerId" : "webauthn-register", + "enabled" : true, + "defaultAction" : false, + "priority" : 70, + "config" : { } + }, { + "alias" : "webauthn-register-passwordless", + "name" : "Webauthn Register Passwordless", + "providerId" : "webauthn-register-passwordless", + "enabled" : true, + "defaultAction" : false, + "priority" : 80, + "config" : { } + }, { + "alias" : "update_user_locale", + "name" : "Update User Locale", + "providerId" : "update_user_locale", + "enabled" : true, + "defaultAction" : false, + "priority" : 1000, + "config" : { } + } ], + "browserFlow" : "browser", + "registrationFlow" : "registration", + "directGrantFlow" : "direct grant", + "resetCredentialsFlow" : "reset credentials", + "clientAuthenticationFlow" : "clients", + "dockerAuthenticationFlow" : "docker auth", + "attributes" : { + "cibaBackchannelTokenDeliveryMode" : "poll", + "cibaExpiresIn" : "120", + "cibaAuthRequestedUserHint" : "login_hint", + "oauth2DeviceCodeLifespan" : "600", + "oauth2DevicePollingInterval" : "5", + "parRequestUriLifespan" : "60", + "cibaInterval" : "5", + "realmReusableOtpCode" : "false" + }, + "keycloakVersion" : "23.0.0", + "userManagedAccessAllowed" : false, + "clientProfiles" : { + "profiles" : [ ] + }, + "clientPolicies" : { + "policies" : [ ] + } +} diff --git a/local/keycloak/puris-config/Catena-X-users-0.json b/local/keycloak/puris-config/Catena-X-users-0.json new file mode 100644 index 00000000..5863b667 --- /dev/null +++ b/local/keycloak/puris-config/Catena-X-users-0.json @@ -0,0 +1,27 @@ +{ + "realm" : "Catena-X", + "users" : [ { + "id" : "57f7531a-3bc8-4f9c-90b3-2f4cdd3183e8", + "createdTimestamp" : 1701016987726, + "username" : "puris_user", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "id" : "6788c4bc-5d9f-4aa3-b7fa-60ed8ec5acda", + "type" : "password", + "userLabel" : "My password", + "createdDate" : 1701016999312, + "secretData" : "{\"value\":\"ZBchRqn06xTlyJ+YMzfQOmCY88SkMKoJHVOYPa2RGis=\",\"salt\":\"YZQCSYYtQSPKQ8J83HJUHA==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-catena-x" ], + "clientRoles" : { + "Cl3-PURIS" : [ "PURIS_ADMIN", "PURIS_USER" ] + }, + "notBefore" : 0, + "groups" : [ ] + } ] +} \ No newline at end of file diff --git a/local/miw/keycloak-setup.json b/local/miw/keycloak-setup.json index 5ab364f8..180b2b88 100644 --- a/local/miw/keycloak-setup.json +++ b/local/miw/keycloak-setup.json @@ -2045,58 +2045,6 @@ "config": {} } ], - "org.keycloak.keys.KeyProvider": [ - { - "id": "f19c25ec-b555-4a60-8d98-fa41190c58d8", - "name": "hmac-generated", - "providerId": "hmac-generated", - "subComponents": {}, - "config": { - "priority": [ - "100" - ], - "algorithm": [ - "HS256" - ] - } - }, - { - "id": "25496642-de17-48e8-8b48-49982e3e0bff", - "name": "aes-generated", - "providerId": "aes-generated", - "subComponents": {}, - "config": { - "priority": [ - "100" - ] - } - }, - { - "id": "31fc839e-8c60-48b7-b9a2-66ecaa0902e5", - "name": "rsa-enc-generated", - "providerId": "rsa-enc-generated", - "subComponents": {}, - "config": { - "priority": [ - "100" - ], - "algorithm": [ - "RSA-OAEP" - ] - } - }, - { - "id": "c09f0435-5a5c-4ee6-af62-6bc7db9fbc88", - "name": "rsa-generated", - "providerId": "rsa-generated", - "subComponents": {}, - "config": { - "priority": [ - "100" - ] - } - } - ] }, "internationalizationEnabled": false, "supportedLocales": [], From d15c151d684a4054c601f287196a7526bf8927b9 Mon Sep 17 00:00:00 2001 From: --show-origin <tom.meyer@isst.fraunhofer.de> Date: Sun, 3 Dec 2023 05:16:12 -0800 Subject: [PATCH 2/7] ci: added disabled idp version to local compose --- frontend/src/App.vue | 2 +- frontend/src/services/AccessService.js | 2 +- frontend/src/services/AuthenticationConfig.js | 10 +++++----- frontend/src/services/AuthenticationService.js | 3 +-- local/docker-compose.yaml | 2 ++ 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/frontend/src/App.vue b/frontend/src/App.vue index c50d3ec0..201596b8 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -37,7 +37,7 @@ import {RouterLink, RouterView} from "vue-router"; <aside> <ul class="space-y-2"> <li - v-for="route in this.viewsWithAccess" + v-for="route in viewsWithAccess" key="route.name" > <RouterLink diff --git a/frontend/src/services/AccessService.js b/frontend/src/services/AccessService.js index 624fd2aa..cacaf7f7 100644 --- a/frontend/src/services/AccessService.js +++ b/frontend/src/services/AccessService.js @@ -24,7 +24,7 @@ const getViewsWithAccess = () => { let views = []; if (!AuthenticationService.isEnabled) { - return ALL_ROUTES; + return ALL_ROUTES.filter(route=> route.name !== "Unauthorized"); } ALL_ROUTES.forEach((item) => { diff --git a/frontend/src/services/AuthenticationConfig.js b/frontend/src/services/AuthenticationConfig.js index 8a4f533a..2119a1db 100644 --- a/frontend/src/services/AuthenticationConfig.js +++ b/frontend/src/services/AuthenticationConfig.js @@ -20,16 +20,16 @@ export const isDisabled = import.meta.env.VITE_IDP_DISABLE === true || - import.meta.env.VITE_IDP_DISABLE === "true"; + import.meta.env.VITE_IDP_DISABLE.trim().toLowerCase() === "true"; -export const getIdpUrl = import.meta.env.VITE_IDP_URL; +export const getIdpUrl = import.meta.env.VITE_IDP_URL.trim(); -export const getIdpRealm = import.meta.env.VITE_IDP_REALM; +export const getIdpRealm = import.meta.env.VITE_IDP_REALM.trim(); -export const getIdpClientId = import.meta.env.VITE_IDP_CLIENT_ID; +export const getIdpClientId = import.meta.env.VITE_IDP_CLIENT_ID.trim(); export const getIdpRedirectUrlFrontend = import.meta.env - .VITE_IDP_REDIRECT_URL_FRONTEND; + .VITE_IDP_REDIRECT_URL_FRONTEND.trim(); const AuthenticationConfig = { isDisabled, diff --git a/frontend/src/services/AuthenticationService.js b/frontend/src/services/AuthenticationService.js index db592687..4698c3e7 100644 --- a/frontend/src/services/AuthenticationService.js +++ b/frontend/src/services/AuthenticationService.js @@ -37,8 +37,7 @@ const isEnabled = AuthenticationConfig.isDisabled !== true; const init = () => { return new Promise((resolve, reject) => { - console.log(AuthenticationConfig.isDisabled); - console.log(isEnabled); + console.log("Auth is disabled: ", AuthenticationConfig.isDisabled); if (!isEnabled) { return resolve(); } diff --git a/local/docker-compose.yaml b/local/docker-compose.yaml index 5fe64a5f..09579e9d 100644 --- a/local/docker-compose.yaml +++ b/local/docker-compose.yaml @@ -37,6 +37,7 @@ services: - ENDPOINT_CUSTOMER=stockView/customer?ownMaterialNumber= - ENDPOINT_PARTNER_PRODUCT_STOCKS=stockView/partner-product-stocks?ownMaterialNumber= - ENDPOINT_UPDATE_PARTNER_PRODUCT_STOCK=stockView/update-partner-product-stock?ownMaterialNumber= + - IDP_DISABLE=true networks: - miw-net extra_hosts: @@ -111,6 +112,7 @@ services: - ENDPOINT_CUSTOMER=stockView/customer?ownMaterialNumber= - ENDPOINT_PARTNER_PRODUCT_STOCKS=stockView/partner-product-stocks?ownMaterialNumber= - ENDPOINT_UPDATE_PARTNER_PRODUCT_STOCK=stockView/update-partner-product-stock?ownMaterialNumber= + - IDP_DISABLE=true networks: - miw-net extra_hosts: From cddb61f7afa33ffa99266538507c92992195a594 Mon Sep 17 00:00:00 2001 From: --show-origin <tom.meyer@isst.fraunhofer.de> Date: Sun, 10 Dec 2023 03:58:31 -0800 Subject: [PATCH 3/7] feat: added configuration examples for frontend with tls --- docs/Security.md | 78 +++++++++++++++++++++++++++++++++++++++++ frontend/nginx.conf | 50 ++++++++++++++++++++++++++ frontend/vite.config.js | 27 +++++++------- 3 files changed, 142 insertions(+), 13 deletions(-) create mode 100644 docs/Security.md create mode 100644 frontend/nginx.conf diff --git a/docs/Security.md b/docs/Security.md new file mode 100644 index 00000000..f5699087 --- /dev/null +++ b/docs/Security.md @@ -0,0 +1,78 @@ +# Serving with HTTPS + +Serving with SSL is available for Docker and Helm Deployment. In local deployment directly with mvn (backend) and +npm (frontend) it can be configured, too. + +For docker configurations, see below. For helm, additionally set the related ingress (frontend, backend) as needed to +enabled and configure it. + +## Frontend + +The Frontend uses a nginx-unprivileged image restricting access heavily. One can use the following configuration as a +starting point. + +Let's assume the following structure: +```shell +ls +>> / +>> /ssl-certificates +>> /ssl-certificates/localhost.crt +>> /ssl-certificates/localhost.key +>> /nginx.conf +``` + +For testing purposes, create self-signed certificates: +``` sh +mkdir ssl-certificates +cd ssl-certificates + +openssl req -x509 -out localhost.crt -keyout localhost.key \ + -newkey rsa:2048 -nodes -sha256 \ + -subj '/CN=localhost' -extensions EXT -config <( \ + printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth") +``` +_NOTE: For productive use, you can use certificates provided by a Certificate Authority._ + + +Create a nginx.conf to provide certificates for listening on 443 for tls. You can find an example +[here](../frontend/nginx.conf). +``` conf +http { + # other configurations + server { + listen 443 ssl; + server_name local-puris-frontend.com; + + ssl_certificate /etc/nginx/ssl/localhost.crt; + ssl_certificate_key /etc/nginx/ssl/localhost.key; + + # TLS version >= 1.2 + ssl_protocols TLSv1.2 TLSv1.3; + + location / { + root /usr/share/nginx/html; + index index.html; + } + } +} +``` + +Start the docker image mounting the certificates and the nginx.conf as follows: +``` sh + +docker run --rm --name frontend \ + -v $(pwd)/ssl-certificates:/etc/nginx/ssl \ + -v $(pwd)/nginx.conf:/etc/nginx/nginx.conf \ + puris-frontend:dev +>> exposes at 8080, 443 +``` + +If you want to use of the dns alias for localhost:443, make sure to edit your /etc/hosts file: +```sh +docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container_name_or_id> + +sudo vim /etc/hosts +>>add entry like 172.17.0.2 local-puris-frontend.com +# :wq! (write and quit) +``` + diff --git a/frontend/nginx.conf b/frontend/nginx.conf new file mode 100644 index 00000000..f158a807 --- /dev/null +++ b/frontend/nginx.conf @@ -0,0 +1,50 @@ +worker_processes auto; + +error_log /var/log/nginx/error.log notice; +pid /tmp/nginx.pid; + + +events { + worker_connections 1024; +} + +http{ + proxy_temp_path /tmp/proxy_temp; + client_body_temp_path /tmp/client_temp; + fastcgi_temp_path /tmp/fastcgi_temp; + uwsgi_temp_path /tmp/uwsgi_temp; + scgi_temp_path /tmp/scgi_temp; + + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + #gzip on; + + include /etc/nginx/conf.d/*.conf; + + server { + listen 443 ssl; + server_name local-puris-frontend.com; + + ssl_certificate /etc/nginx/ssl/localhost.crt; + ssl_certificate_key /etc/nginx/ssl/localhost.key; + + ssl_protocols TLSv1.2 TLSv1.3; + + location / { + root /usr/share/nginx/html; + index index.html; + } + } +} diff --git a/frontend/vite.config.js b/frontend/vite.config.js index 7cd68a41..98cc3bb1 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -1,17 +1,18 @@ -import { fileURLToPath, URL } from 'url' +import {fileURLToPath, URL} from "url"; -import { defineConfig } from 'vite' -import vue from '@vitejs/plugin-vue' +import {defineConfig} from "vite"; +import vue from "@vitejs/plugin-vue"; // https://vitejs.dev/config/ export default defineConfig({ - plugins: [vue()], - resolve: { - alias: { - '@': fileURLToPath(new URL('./src', import.meta.url)) - } - }, - server: { - port: 3000 - } -}) + plugins: [vue()], + resolve: { + alias: { + "@": fileURLToPath(new URL("./src", import.meta.url)), + }, + }, + server: { + port: 3000, + https: true, + }, +}); From e58b868579c8cba3ee1db1cbe73f4a787c32bfd0 Mon Sep 17 00:00:00 2001 From: --show-origin <tom.meyer@isst.fraunhofer.de> Date: Sun, 10 Dec 2023 06:43:18 -0800 Subject: [PATCH 4/7] feat: added configuration examples for backend with tls --- .../src/main/resources/application.properties | 8 ++++ docs/Security.md | 44 ++++++++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 1c6dc77a..00133e6f 100755 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -44,5 +44,13 @@ own.default.streetandnumber=${OWN_DEFAULT_STREETANDNUMBER:Musterstrasse 35b} own.default.zipcodeandcity=${OWN_DEFAULT_ZIPCODEANDCITY:77777 Musterhausen} own.default.country=${OWN_DEFAULT_COUNTRY:Germany} +server.ssl.enabled=false +#server.port=8443 +#server.ssl.bundle=server +#spring.ssl.bundle.jks.server.key.alias=application +#spring.ssl.bundle.jks.server.keystore.location=file:ssl-certificates/application.p12 +#spring.ssl.bundle.jks.server.keystore.password=testtest +#spring.ssl.bundle.jks.server.keystore.type=PKCS12 + # run with: # ./mvnw spring-boot:run -Dspring-boot.run.arguments=--spring.config.location="./src/main/resources/application.properties" diff --git a/docs/Security.md b/docs/Security.md index f5699087..9b98e5b4 100644 --- a/docs/Security.md +++ b/docs/Security.md @@ -33,7 +33,6 @@ openssl req -x509 -out localhost.crt -keyout localhost.key \ ``` _NOTE: For productive use, you can use certificates provided by a Certificate Authority._ - Create a nginx.conf to provide certificates for listening on 443 for tls. You can find an example [here](../frontend/nginx.conf). ``` conf @@ -76,3 +75,46 @@ sudo vim /etc/hosts # :wq! (write and quit) ``` +## Backend + +Spring provides the possibility to provide ssl certificates. + +Let's assume the following structure: +```shell +ls +>> / +>> /ssl-certificates +>> /ssl-certificates/application.p12 +>> /applicaiton-with-ssl.properties +``` + +For testing purposes, create self-signed certificates using java keytool and follow the prompts. +Remember the password. They generated key file is a pkcs12 keystore. +``` sh +mkdir ssl-certificates +cd ssl-certificates + +keytool -genkeypair -alias application -keyalg RSA -keysize 4096 -storetype PKCS12 -keystore application.p12 -validity 3650 +``` +_NOTE: For productive use, you can use certificates provided by a Certificate Authority._ + +Use your common application.properties and add the following section to the file. Name it e.g., +application-with-ssl.properties. +```application.properties +server.ssl.enabled=false +#server.port=8443 +server.ssl.bundle=server +spring.ssl.bundle.jks.server.key.alias=application +spring.ssl.bundle.jks.server.keystore.location=file:/opt/app/ssl-certificates/application.p12 +spring.ssl.bundle.jks.server.keystore.password= +spring.ssl.bundle.jks.server.keystore.type=PKCS12 +``` + +Finally pass the created keystore and properties file via docker: +```shell +docker run --rm -d -p 8433:8433 --name backend \ + -v $(pwd)/ssl-certificates/application.p12:/opt/app/ssl-certificates/application.p12 \ + -v $(pwd)/test.properties:/opt/app/test.properties \ + -e SPRING_CONFIG_LOCATION=/opt/app/test.properties \ + puris-backend:dev +``` From e88f7e5a887378fb3a89c023034b0c26dc2b184e Mon Sep 17 00:00:00 2001 From: --show-origin <tom.meyer@isst.fraunhofer.de> Date: Mon, 11 Dec 2023 09:32:32 -0800 Subject: [PATCH 5/7] feat(cors): configured cors in backend globally --- .../common/edc/controller/EdcController.java | 7 ++++--- .../common/security/SecurityConfig.java | 21 +++++++++++++++++++ .../ExternalConnectorController.java | 2 -- .../backend/controller/HealthController.java | 4 +--- .../backend/controller/OrderController.java | 11 +++------- .../controller/MaterialController.java | 4 ---- .../MaterialPartnerRelationsController.java | 2 -- .../controller/PartnerController.java | 6 ------ .../stock/controller/StockViewController.java | 12 ----------- 9 files changed, 29 insertions(+), 40 deletions(-) diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/common/edc/controller/EdcController.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/common/edc/controller/EdcController.java index c9db0d38..50f47a5b 100644 --- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/common/edc/controller/EdcController.java +++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/common/edc/controller/EdcController.java @@ -24,7 +24,10 @@ import org.eclipse.tractusx.puris.backend.common.edc.logic.service.EdcAdapterService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; import java.io.IOException; import java.util.List; @@ -47,7 +50,6 @@ public class EdcController { * @return catalog of the requested edc. */ @GetMapping("/catalog") - @CrossOrigin public ResponseEntity<String> getCatalog(@RequestParam String dspUrl) { try { var catalog = edcAdapter.getCatalog(dspUrl); @@ -65,7 +67,6 @@ public ResponseEntity<String> getCatalog(@RequestParam String dspUrl) { * @return response from own EDC. */ @GetMapping("/assets") - @CrossOrigin public ResponseEntity<String> getAssets(@RequestParam String assetId) { try { var result = edcAdapter.sendGetRequest(List.of("v3", "assets", assetId)); diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/common/security/SecurityConfig.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/common/security/SecurityConfig.java index 1e90210d..2edf584a 100644 --- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/common/security/SecurityConfig.java +++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/common/security/SecurityConfig.java @@ -21,6 +21,7 @@ import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.eclipse.tractusx.puris.backend.common.security.logic.ApiKeyAuthenticationFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -31,14 +32,33 @@ import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +import java.util.List; @Configuration @EnableWebSecurity @AllArgsConstructor +@Slf4j public class SecurityConfig { private final ApiKeyAuthenticationFilter apiKeyAuthenticationFilter; + @Bean + public CorsConfigurationSource corsConfigurationSource() { + CorsConfiguration configuration = new CorsConfiguration(); + configuration.setAllowedOrigins(List.of("*")); + configuration.setAllowedHeaders(List.of("*")); + configuration.setAllowedMethods(List.of("*")); + + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", configuration); + + return source; + } + /** * Configuration of API Key Authentication for all routes except docker */ @@ -59,6 +79,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { ) .cors(Customizer.withDefaults()); + http.addFilterBefore(apiKeyAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); return http.build(); diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/controller/ExternalConnectorController.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/controller/ExternalConnectorController.java index b59cde31..f53739b1 100644 --- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/controller/ExternalConnectorController.java +++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/controller/ExternalConnectorController.java @@ -56,7 +56,6 @@ public ExternalConnectorController(ExternalConnectorService externalConnectorSer * @return the created connector, if it was created. */ @PostMapping("create") - @CrossOrigin public ResponseEntity<ExternalConnector> createConnector(@RequestBody String content){ try { var connector = MAPPER.readValue(content, ExternalConnector.class); @@ -75,7 +74,6 @@ public ResponseEntity<ExternalConnector> createConnector(@RequestBody String con * @return list of all currently known external connectors. */ @GetMapping("all") - @CrossOrigin public List<ExternalConnector> getAll() { return externalConnectorService.getAll(); } diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/controller/HealthController.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/controller/HealthController.java index 79c4496f..d1dc5771 100644 --- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/controller/HealthController.java +++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/controller/HealthController.java @@ -21,7 +21,6 @@ package org.eclipse.tractusx.puris.backend.controller; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -39,9 +38,8 @@ public class HealthController { * @return 200 OK if healthy. */ @GetMapping("/") - @CrossOrigin public ResponseEntity<?> getHealth() { return ResponseEntity.ok().build(); } -} \ No newline at end of file +} diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/controller/OrderController.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/controller/OrderController.java index d614acc5..82d12179 100644 --- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/controller/OrderController.java +++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/controller/OrderController.java @@ -25,12 +25,13 @@ import org.eclipse.tractusx.puris.backend.model.Order; import org.eclipse.tractusx.puris.backend.model.repo.OrderPositionRepository; import org.eclipse.tractusx.puris.backend.model.repo.OrderRepository; -import java.util.List; -import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.util.List; +import java.util.stream.Collectors; + /** * Controller for creating and managing Orders/Call-offs. */ @@ -50,7 +51,6 @@ public class OrderController { * @return List of all orders. */ @GetMapping("order") - @CrossOrigin public ResponseEntity<List<Order>> getAllOrders() { return ResponseEntity.ok(orderRepository.findAll()); } @@ -61,7 +61,6 @@ public ResponseEntity<List<Order>> getAllOrders() { * @return list of all orders where sent=true. */ @GetMapping("orders/sent") - @CrossOrigin public ResponseEntity<List<Order>> getSentOrders() { return ResponseEntity.ok( orderRepository.findAll().stream().filter(Order::isSent).collect(Collectors.toList())); @@ -73,7 +72,6 @@ public ResponseEntity<List<Order>> getSentOrders() { * @return list of all orders where sent=false. */ @GetMapping("orders/pending") - @CrossOrigin public ResponseEntity<List<Order>> getNotSentOrder() { return ResponseEntity.ok( orderRepository.findAll().stream() @@ -88,7 +86,6 @@ public ResponseEntity<List<Order>> getNotSentOrder() { * @return requested order or 404 not found. */ @GetMapping("order/id/{id}") - @CrossOrigin public ResponseEntity<?> getOrder(@PathVariable String id) { var order = orderRepository.findByOrderId(id); if (order.isEmpty()) { @@ -106,7 +103,6 @@ public ResponseEntity<?> getOrder(@PathVariable String id) { * @return OK if order was created, or information about why order could not be created. */ @PostMapping("order") - @CrossOrigin public ResponseEntity<?> createOrder(@RequestBody String content) { try { var order = MAPPER.readValue(content, Order.class); @@ -137,7 +133,6 @@ public ResponseEntity<?> createOrder(@RequestBody String content) { * @return OK or info why order could not be deleted. */ @DeleteMapping("order") - @CrossOrigin public ResponseEntity<?> deleteOrder(@RequestParam String id) { var toDelete = orderRepository.findByOrderId(id); if (toDelete.isEmpty()) { diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/masterdata/controller/MaterialController.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/masterdata/controller/MaterialController.java index 61b0d16a..cc2bf19e 100644 --- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/masterdata/controller/MaterialController.java +++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/masterdata/controller/MaterialController.java @@ -46,7 +46,6 @@ public class MaterialController { private final ModelMapper modelMapper = new ModelMapper(); @PostMapping - @CrossOrigin @Operation(description = "Creates a new Material entity with the data given in the request body. As a bare minimum, " + "it must contain a new, unique ownMaterialNumber.") @ApiResponses(value = { @@ -80,7 +79,6 @@ public ResponseEntity<?> createMaterial(@RequestBody MaterialEntityDto materialD } @PutMapping - @CrossOrigin @Operation(description = "Updates an existing Material entity with the data given in the request body.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Update was accepted."), @@ -113,7 +111,6 @@ public ResponseEntity<?> updateMaterial(@RequestBody MaterialEntityDto materialD } @GetMapping - @CrossOrigin @Operation(description = "Returns the requested Material dto, specified by the given ownMaterialNumber.") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Returns the requested Material."), @@ -131,7 +128,6 @@ public ResponseEntity<MaterialEntityDto> getMaterial(@Parameter(name = "ownMater return new ResponseEntity<>(dto, HttpStatusCode.valueOf(200)); } - @CrossOrigin @GetMapping("/all") @Operation(description = "Returns a list of all Materials and Products.") public ResponseEntity<List<MaterialEntityDto>> listMaterials() { diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/masterdata/controller/MaterialPartnerRelationsController.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/masterdata/controller/MaterialPartnerRelationsController.java index 763bee90..b1180c54 100644 --- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/masterdata/controller/MaterialPartnerRelationsController.java +++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/masterdata/controller/MaterialPartnerRelationsController.java @@ -51,7 +51,6 @@ public class MaterialPartnerRelationsController { private MaterialPartnerRelationService mprService; @PostMapping - @CrossOrigin @Operation(description = "Creates a new MaterialPartnerRelation with the given parameter data. " + "Please note that this is only possible, if the designated Material " + "and Partner entities have already been created before this request. ") @@ -98,7 +97,6 @@ public ResponseEntity<?> createMaterialPartnerRelation( } @PutMapping - @CrossOrigin @Operation(description = "Updates an existing MaterialPartnerRelation. You have to specify the ownMaterialNumber and " + "the partnerBpnl. The other three parameters are genuinely optional. Provide them only if you want to change their values. ") @ApiResponses(value = { diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/masterdata/controller/PartnerController.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/masterdata/controller/PartnerController.java index 828d8c2d..ed174ce0 100644 --- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/masterdata/controller/PartnerController.java +++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/masterdata/controller/PartnerController.java @@ -50,7 +50,6 @@ public class PartnerController { private PartnerService partnerService; private final ModelMapper modelMapper = new ModelMapper(); - @CrossOrigin @PostMapping @Operation(description = "Creates a new Partner entity with the data given in the request body. Please note that no " + "UUID can be assigned to a Partner that wasn't created before. So the request body must not contain a UUID.") @@ -89,7 +88,6 @@ public ResponseEntity<?> createPartner(@RequestBody PartnerDto partnerDto) { } @PutMapping("putAddress") - @CrossOrigin @Operation(description = "Updates an existing Partner by adding a new Address. If that Partner already has " + "an Address with the BPNA given in the request body, that existing Address will be overwritten. ") @ApiResponses(value = { @@ -124,7 +122,6 @@ public ResponseEntity<?> addAddress( } @PutMapping("putSite") - @CrossOrigin @Operation(description = "Updates an existing Partner by adding a new Site. If that Partner already has " + "a Site with the BPNS given in the request body, that existing Site will be overwritten. ") @ApiResponses(value = { @@ -159,8 +156,6 @@ public ResponseEntity<?> addSite( return new ResponseEntity<>(HttpStatusCode.valueOf(200)); } - - @CrossOrigin @GetMapping @Operation(description = "Returns the requested PartnerDto.") @ApiResponses(value = { @@ -183,7 +178,6 @@ public ResponseEntity<PartnerDto> getPartner( } } - @CrossOrigin @GetMapping("/all") @Operation(description = "Returns a list of all Partners. ") public ResponseEntity<List<PartnerDto>> listPartners() { diff --git a/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/controller/StockViewController.java b/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/controller/StockViewController.java index 69d2346c..92720ade 100644 --- a/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/controller/StockViewController.java +++ b/backend/src/main/java/org/eclipse/tractusx/puris/backend/stock/controller/StockViewController.java @@ -87,7 +87,6 @@ public class StockViewController { @Autowired private ModelMapper modelMapper; - @CrossOrigin @GetMapping("materials") @ResponseBody @Operation(description = "Returns a list of all materials (excluding products)") @@ -98,7 +97,6 @@ public List<FrontendMaterialDto> getMaterials() { .collect(Collectors.toList()); } - @CrossOrigin @GetMapping("materialnumbers-mapping") @ResponseBody @Operation(description = "Returns a mapping of all material numbers, that others partners are using" + @@ -112,7 +110,6 @@ public Map<String, String> getMaterialNumbers(@RequestParam String ownMaterialNu return mprService.getBPNL_To_MaterialNumberMap(ownMaterialNumber); } - @CrossOrigin @GetMapping("products") @ResponseBody @Operation(description = "Returns a list of all products (excluding materials)") @@ -123,7 +120,6 @@ public List<FrontendMaterialDto> getProducts() { .collect(Collectors.toList()); } - @CrossOrigin @GetMapping("product-stocks") @ResponseBody @Operation(description = "Returns a list of all product-stocks") @@ -133,7 +129,6 @@ public List<ProductStockDto> getProductStocks() { .collect(Collectors.toList()); } - @CrossOrigin @PostMapping("product-stocks") @ResponseBody @Operation(description = "Creates a new product-stock") @@ -152,7 +147,6 @@ public ProductStockDto createProductStocks(@RequestBody ProductStockDto productS return convertToDto(createdProductStock); } - @CrossOrigin @PutMapping("product-stocks") @ResponseBody @Operation(description = "Updates an existing product-stock") @@ -187,7 +181,6 @@ private ProductStock convertToEntity(ProductStockDto dto) { return productStock; } - @CrossOrigin @GetMapping("material-stocks") @ResponseBody @Operation(description = "Returns a list of all material-stocks") @@ -199,7 +192,6 @@ public List<MaterialStockDto> getMaterialStocks() { return allMaterialStocks; } - @CrossOrigin @PostMapping("material-stocks") @ResponseBody @Operation(description = "Creates a new material-stock") @@ -213,7 +205,6 @@ public MaterialStockDto createMaterialStocks(@RequestBody MaterialStockDto mater return convertToDto(createdMaterialStock); } - @CrossOrigin @PutMapping("material-stocks") @ResponseBody @Operation(description = "Updates an existing material-stock") @@ -245,7 +236,6 @@ private MaterialStock convertToEntity(MaterialStockDto dto) { return stock; } - @CrossOrigin @GetMapping("partner-product-stocks") @ResponseBody @Operation(description = "Returns a list of all partner-product-stocks that refer to the given material number") @@ -268,7 +258,6 @@ private PartnerProductStockDto convertToDto(PartnerProductStock entity) { return dto; } - @CrossOrigin @GetMapping("customer") @ResponseBody @Operation(description = "Returns a list of all Partners that are ordering the given material") @@ -278,7 +267,6 @@ public List<PartnerDto> getCustomerPartnersOrderingMaterial(@RequestParam String .collect(Collectors.toList()); } - @CrossOrigin @GetMapping("update-partner-product-stock") @ResponseBody @Operation(description = "For the given material, all known suppliers will be requested to report their" + From 6cafb03b4b4abd4767529f753dfd238a5863149c Mon Sep 17 00:00:00 2001 From: --show-origin <tom.meyer@isst.fraunhofer.de> Date: Mon, 11 Dec 2023 09:44:08 -0800 Subject: [PATCH 6/7] docs(adminGuide): added ssl configuration and troubleshooting --- docs/Security.md | 120 ------------------------------- docs/adminGuide/Admin_Guide.md | 128 +++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+), 120 deletions(-) delete mode 100644 docs/Security.md diff --git a/docs/Security.md b/docs/Security.md deleted file mode 100644 index 9b98e5b4..00000000 --- a/docs/Security.md +++ /dev/null @@ -1,120 +0,0 @@ -# Serving with HTTPS - -Serving with SSL is available for Docker and Helm Deployment. In local deployment directly with mvn (backend) and -npm (frontend) it can be configured, too. - -For docker configurations, see below. For helm, additionally set the related ingress (frontend, backend) as needed to -enabled and configure it. - -## Frontend - -The Frontend uses a nginx-unprivileged image restricting access heavily. One can use the following configuration as a -starting point. - -Let's assume the following structure: -```shell -ls ->> / ->> /ssl-certificates ->> /ssl-certificates/localhost.crt ->> /ssl-certificates/localhost.key ->> /nginx.conf -``` - -For testing purposes, create self-signed certificates: -``` sh -mkdir ssl-certificates -cd ssl-certificates - -openssl req -x509 -out localhost.crt -keyout localhost.key \ - -newkey rsa:2048 -nodes -sha256 \ - -subj '/CN=localhost' -extensions EXT -config <( \ - printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth") -``` -_NOTE: For productive use, you can use certificates provided by a Certificate Authority._ - -Create a nginx.conf to provide certificates for listening on 443 for tls. You can find an example -[here](../frontend/nginx.conf). -``` conf -http { - # other configurations - server { - listen 443 ssl; - server_name local-puris-frontend.com; - - ssl_certificate /etc/nginx/ssl/localhost.crt; - ssl_certificate_key /etc/nginx/ssl/localhost.key; - - # TLS version >= 1.2 - ssl_protocols TLSv1.2 TLSv1.3; - - location / { - root /usr/share/nginx/html; - index index.html; - } - } -} -``` - -Start the docker image mounting the certificates and the nginx.conf as follows: -``` sh - -docker run --rm --name frontend \ - -v $(pwd)/ssl-certificates:/etc/nginx/ssl \ - -v $(pwd)/nginx.conf:/etc/nginx/nginx.conf \ - puris-frontend:dev ->> exposes at 8080, 443 -``` - -If you want to use of the dns alias for localhost:443, make sure to edit your /etc/hosts file: -```sh -docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container_name_or_id> - -sudo vim /etc/hosts ->>add entry like 172.17.0.2 local-puris-frontend.com -# :wq! (write and quit) -``` - -## Backend - -Spring provides the possibility to provide ssl certificates. - -Let's assume the following structure: -```shell -ls ->> / ->> /ssl-certificates ->> /ssl-certificates/application.p12 ->> /applicaiton-with-ssl.properties -``` - -For testing purposes, create self-signed certificates using java keytool and follow the prompts. -Remember the password. They generated key file is a pkcs12 keystore. -``` sh -mkdir ssl-certificates -cd ssl-certificates - -keytool -genkeypair -alias application -keyalg RSA -keysize 4096 -storetype PKCS12 -keystore application.p12 -validity 3650 -``` -_NOTE: For productive use, you can use certificates provided by a Certificate Authority._ - -Use your common application.properties and add the following section to the file. Name it e.g., -application-with-ssl.properties. -```application.properties -server.ssl.enabled=false -#server.port=8443 -server.ssl.bundle=server -spring.ssl.bundle.jks.server.key.alias=application -spring.ssl.bundle.jks.server.keystore.location=file:/opt/app/ssl-certificates/application.p12 -spring.ssl.bundle.jks.server.keystore.password= -spring.ssl.bundle.jks.server.keystore.type=PKCS12 -``` - -Finally pass the created keystore and properties file via docker: -```shell -docker run --rm -d -p 8433:8433 --name backend \ - -v $(pwd)/ssl-certificates/application.p12:/opt/app/ssl-certificates/application.p12 \ - -v $(pwd)/test.properties:/opt/app/test.properties \ - -e SPRING_CONFIG_LOCATION=/opt/app/test.properties \ - puris-backend:dev -``` diff --git a/docs/adminGuide/Admin_Guide.md b/docs/adminGuide/Admin_Guide.md index 496690fb..792d6142 100644 --- a/docs/adminGuide/Admin_Guide.md +++ b/docs/adminGuide/Admin_Guide.md @@ -72,6 +72,134 @@ To host an example keycloak instance, configure the following: _Note: The application does NOT make use of the `Client Authentication` (private) feature of Keycloak Clients._ +## Serving with HTTPS / SSL + +Serving with SSL is available for Docker and Helm Deployment. In local deployment directly with mvn (backend) and +npm (frontend) it can be configured, too. + +For docker configurations, see below. For helm, additionally set the related ingress (frontend, backend) as needed to +enabled and configure it. + +### Frontend SSL Configuration + +The Frontend uses a nginx-unprivileged image restricting access heavily. One can use the following configuration as a +starting point. + +Let's assume the following structure: +```shell +ls +>> / +>> /ssl-certificates +>> /ssl-certificates/localhost.crt +>> /ssl-certificates/localhost.key +>> /nginx.conf +``` + +For testing purposes, create self-signed certificates: +``` sh +mkdir ssl-certificates +cd ssl-certificates + +openssl req -x509 -out localhost.crt -keyout localhost.key \ + -newkey rsa:2048 -nodes -sha256 \ + -subj '/CN=localhost' -extensions EXT -config <( \ + printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth") +``` +_NOTE: For productive use, you can use certificates provided by a Certificate Authority._ + +Create a nginx.conf to provide certificates for listening on 443 for tls. You can find an example +[here](../frontend/nginx.conf). +``` conf +http { + # other configurations + server { + listen 443 ssl; + server_name local-puris-frontend.com; + + ssl_certificate /etc/nginx/ssl/localhost.crt; + ssl_certificate_key /etc/nginx/ssl/localhost.key; + + # TLS version >= 1.2 + ssl_protocols TLSv1.2 TLSv1.3; + + location / { + root /usr/share/nginx/html; + index index.html; + } + } +} +``` + +Start the docker image mounting the certificates and the nginx.conf as follows: +``` sh + +docker run --rm --name frontend \ + -v $(pwd)/ssl-certificates:/etc/nginx/ssl \ + -v $(pwd)/nginx.conf:/etc/nginx/nginx.conf \ + puris-frontend:dev +>> exposes at 8080, 443 +``` + +If you want to use of the dns alias for localhost:443, make sure to edit your /etc/hosts file: +```sh +docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container_name_or_id> + +sudo vim /etc/hosts +>>add entry like 172.17.0.2 local-puris-frontend.com +# :wq! (write and quit) +``` + +### Backend SSL Configuration + +Spring provides the possibility to provide ssl certificates. + +Let's assume the following structure: +```shell +ls +>> / +>> /ssl-certificates +>> /ssl-certificates/application.p12 +>> /applicaiton-with-ssl.properties +``` + +For testing purposes, create self-signed certificates using java keytool and follow the prompts. +Remember the password. They generated key file is a pkcs12 keystore. +``` sh +mkdir ssl-certificates +cd ssl-certificates + +keytool -genkeypair -alias application -keyalg RSA -keysize 4096 -storetype PKCS12 -keystore application.p12 -validity 3650 +``` +_NOTE: For productive use, you can use certificates provided by a Certificate Authority._ + +Use your common application.properties and add the following section to the file. Name it e.g., +application-with-ssl.properties. +```application.properties +server.ssl.enabled=false +#server.port=8443 +server.ssl.bundle=server +spring.ssl.bundle.jks.server.key.alias=application +spring.ssl.bundle.jks.server.keystore.location=file:/opt/app/ssl-certificates/application.p12 +spring.ssl.bundle.jks.server.keystore.password= +spring.ssl.bundle.jks.server.keystore.type=PKCS12 +``` + +Finally pass the created keystore and properties file via docker: +```shell +docker run --rm -d -p 8433:8433 --name backend \ + -v $(pwd)/ssl-certificates/application.p12:/opt/app/ssl-certificates/application.p12 \ + -v $(pwd)/test.properties:/opt/app/test.properties \ + -e SPRING_CONFIG_LOCATION=/opt/app/test.properties \ + puris-backend:dev +``` + +### Troubleshooting SSL + +When using self-signed certificates, the frontend may result in a CORS error. The error is likely no CORS related +problem. Please check if you created exceptions for both certificates, the frontend's and backend's certificates. You +can see a related error in the Developer Tools (F12) > Network tab > select preflight header > tab security. + + ## Onboarding Your Data The application, per solution strategy, tries to provide visualization and manipulation capabilities to exchange only From c86c1f070164ccaca7893302287f545a142a65a1 Mon Sep 17 00:00:00 2001 From: --show-origin <tom.meyer@isst.fraunhofer.de> Date: Mon, 18 Dec 2023 01:24:30 -0800 Subject: [PATCH 7/7] chore(tls): removed sample nginx config --- docs/adminGuide/Admin_Guide.md | 3 +- frontend/nginx.conf | 50 ---------------------------------- 2 files changed, 1 insertion(+), 52 deletions(-) delete mode 100644 frontend/nginx.conf diff --git a/docs/adminGuide/Admin_Guide.md b/docs/adminGuide/Admin_Guide.md index 792d6142..619022e1 100644 --- a/docs/adminGuide/Admin_Guide.md +++ b/docs/adminGuide/Admin_Guide.md @@ -107,8 +107,7 @@ openssl req -x509 -out localhost.crt -keyout localhost.key \ ``` _NOTE: For productive use, you can use certificates provided by a Certificate Authority._ -Create a nginx.conf to provide certificates for listening on 443 for tls. You can find an example -[here](../frontend/nginx.conf). +Create a nginx.conf to provide certificates for listening on 443 for tls. ``` conf http { # other configurations diff --git a/frontend/nginx.conf b/frontend/nginx.conf deleted file mode 100644 index f158a807..00000000 --- a/frontend/nginx.conf +++ /dev/null @@ -1,50 +0,0 @@ -worker_processes auto; - -error_log /var/log/nginx/error.log notice; -pid /tmp/nginx.pid; - - -events { - worker_connections 1024; -} - -http{ - proxy_temp_path /tmp/proxy_temp; - client_body_temp_path /tmp/client_temp; - fastcgi_temp_path /tmp/fastcgi_temp; - uwsgi_temp_path /tmp/uwsgi_temp; - scgi_temp_path /tmp/scgi_temp; - - include /etc/nginx/mime.types; - default_type application/octet-stream; - - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - - access_log /var/log/nginx/access.log main; - - sendfile on; - #tcp_nopush on; - - keepalive_timeout 65; - - #gzip on; - - include /etc/nginx/conf.d/*.conf; - - server { - listen 443 ssl; - server_name local-puris-frontend.com; - - ssl_certificate /etc/nginx/ssl/localhost.crt; - ssl_certificate_key /etc/nginx/ssl/localhost.key; - - ssl_protocols TLSv1.2 TLSv1.3; - - location / { - root /usr/share/nginx/html; - index index.html; - } - } -}