diff --git a/.github/workflows/app-test-coverage-pr.yml b/.github/workflows/app-test-coverage-pr.yml new file mode 100644 index 000000000..f0e56fb9f --- /dev/null +++ b/.github/workflows/app-test-coverage-pr.yml @@ -0,0 +1,66 @@ +# /******************************************************************************** +# * 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 +# ********************************************************************************/ + +name: Application test and coverage -- PR context + +on: + pull_request: + paths: + - 'src/**' + +jobs: + test-app: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up Java 17 + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '17' + + - name: Test app + run: ./gradlew test + + - name: Get coverage + if: always() + run: ./gradlew jacocoTestReport + + - name: Upload test results + uses: actions/upload-artifact@v3 + if: always() + with: + name: test-results + path: ${{ github.workspace }}/build/ + + - name: Publish code coverage report as PR comment + uses: madrapps/jacoco-report@v1.6.1 + if: always() + with: + paths: | + ${{ github.workspace }}/build/reports/xml/jacoco.xml + token: ${{ secrets.GITHUB_TOKEN }} + min-coverage-overall: 80 + min-coverage-changed-files: 80 + title: Coverage Report diff --git a/.github/workflows/app-test-coverage-repo.yml b/.github/workflows/app-test-coverage-repo.yml new file mode 100644 index 000000000..c52a486f0 --- /dev/null +++ b/.github/workflows/app-test-coverage-repo.yml @@ -0,0 +1,68 @@ +# /******************************************************************************** +# * 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 +# ********************************************************************************/ + +name: Application test and coverage -- Repository context + +on: + workflow_run: + workflows: [ 'Application test and coverage -- PR context' ] + types: + - completed + +permissions: + contents: read + actions: read + checks: write + +jobs: + test-app: + runs-on: ubuntu-latest + + steps: + - name: Download test results + uses: actions/download-artifact@v3 + with: + name: test-results + path: ${{ github.workspace }}/ + + - name: Setup .NET Core # Required to execute ReportGenerator + uses: actions/setup-dotnet@v3 + with: + dotnet-version: 6.x + dotnet-quality: 'ga' + + - name: Generate test report + uses: dorny/test-reporter@v1.6.0 + with: + name: Test results + path: 'test-results/test/*.xml' + reporter: java-junit + fail-on-error: false + + - name: Create Markdown from code coverage report + uses: danielpalme/ReportGenerator-GitHub-Action@5.1.25 + with: + reports: reports/xml/jacoco.xml + targetdir: coveragereport + reporttypes: MarkdownSummaryGithub + sourcedirs: src/main/java + title: 'Code Coverage' + + - name: Publish Markdown code coverage report as job summary + run: cat coveragereport/SummaryGithub.md >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/app-test-coverage.yml b/.github/workflows/app-test-coverage.yml deleted file mode 100644 index 887589282..000000000 --- a/.github/workflows/app-test-coverage.yml +++ /dev/null @@ -1,101 +0,0 @@ -# Disabled until is is runnable on github - -## /******************************************************************************** -## * 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 -## ********************************************************************************/ -# -#name: Test application (test + coverage) -# -#on: -# workflow_dispatch: -# pull_request: -# paths: -# - 'src/**' -# -#permissions: -# id-token: write -# statuses: write -# checks: write -# # may also be read -# contents: write -# pull-requests: write -# actions: write -# -#jobs: -# test-app: -# runs-on: ubuntu-latest -# -# steps: -# - name: Checkout -# uses: actions/checkout@v3 -# with: -# fetch-depth: 0 -# -# - name: Set up Java 17 -# uses: actions/setup-java@v3 -# with: -# distribution: 'temurin' -# java-version: '17' -# -# - name: Setup .NET Core # Required to execute ReportGenerator -# uses: actions/setup-dotnet@v3 -# if: success() || failure() -# with: -# dotnet-version: 6.x -# dotnet-quality: 'ga' -# -# - name: Test app -# run: ORG_GRADLE_PROJECT_githubToken=${{ secrets.GITHUB_TOKEN }} ./gradlew test -# -# - name: Get coverage -# if: success() || failure() -# run: ORG_GRADLE_PROJECT_githubToken=${{ secrets.GITHUB_TOKEN }} ./gradlew jacocoTestReport -# -# - name: Generate test report -# uses: dorny/test-reporter@v1.6.0 -# if: success() || failure() -# with: -# name: Test results -# path: 'build/test-results/test/*.xml' -# reporter: java-junit -# fail-on-error: false -# -# - name: Generate code coverage report -# uses: danielpalme/ReportGenerator-GitHub-Action@5.1.25 -# if: success() || failure() -# with: -# reports: build/reports/xml/jacoco -# targetdir: coveragereport -# reporttypes: MarkdownSummaryGithub -# sourcedirs: src/main/java -# title: 'Code Coverage' -# -# - name: Publish code coverage report as job summary -# if: success() || failure() -# run: cat coveragereport/SummaryGithub.md >> $GITHUB_STEP_SUMMARY -# -# - name: Publish code coverage report as PR comment -# uses: madrapps/jacoco-report@v1.6.1 -# if: github.event_name == 'pull_request' && (success() || failure()) -# with: -# paths: | -# ${{ github.workspace }}/build/reports/xml/jacoco -# token: ${{ secrets.GITHUB_TOKEN }} -# min-coverage-overall: 80 -# min-coverage-changed-files: 80 -# title: Coverage Report diff --git a/.github/workflows/chart-lint-test.yml b/.github/workflows/chart-verification.yml similarity index 84% rename from .github/workflows/chart-lint-test.yml rename to .github/workflows/chart-verification.yml index 620586d1f..9442c63c1 100644 --- a/.github/workflows/chart-lint-test.yml +++ b/.github/workflows/chart-verification.yml @@ -17,7 +17,7 @@ # * SPDX-License-Identifier: Apache-2.0 # ********************************************************************************/ -name: Lint and Test Charts +name: Verify and Test Helm Chart on: workflow_dispatch: @@ -44,7 +44,7 @@ jobs: - name: Add bitnami repo run: | - helm repo add bitnami https://charts.bitnami.com/bitnami + helm repo add bitnami https://charts.bitnami.com/bitnami helm repo update - name: Update Helm dependencies @@ -63,6 +63,29 @@ jobs: - name: Run linting run: ct lint --config charts/chart-testing-config.yaml --charts ./charts/managed-identity-wallet + verify-helm-docs: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Run helm docs command + uses: addnab/docker-run-action@v3 + with: + image: jnorwood/helm-docs:v1.11.3 + options: -v ${{ github.workspace }}/charts:/helm-docs + run: helm-docs + + - name: Verify that no changes are required + run: | + if $(git diff --quiet --exit-code); then + echo "Helm chart docs up to date" + else + echo "Helm chart docs not up to date:" + git diff + exit 1 + fi + chart-test: runs-on: ubuntu-latest steps: @@ -86,7 +109,7 @@ jobs: - name: Add bitnami repo run: | - helm repo add bitnami https://charts.bitnami.com/bitnami + helm repo add bitnami https://charts.bitnami.com/bitnami helm repo update - name: Update Helm dependencies @@ -103,8 +126,6 @@ jobs: - name: Build app env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_USERNAME: ${{ github.actor }} SKIP_GRADLE_TASKS_PARAM: "-x jacocoTestCoverageVerification -x test" run: task app:build diff --git a/.github/workflows/dast-scan.yaml b/.github/workflows/dast-scan.yaml index c628f7af2..d94c66d8b 100644 --- a/.github/workflows/dast-scan.yaml +++ b/.github/workflows/dast-scan.yaml @@ -62,8 +62,6 @@ jobs: - name: Build app env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_USERNAME: ${{ github.actor }} SKIP_GRADLE_TASKS_PARAM: "-x jacocoTestCoverageVerification -x test" run: task app:build diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 071b5c825..5dd2573a5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -64,8 +64,6 @@ jobs: - name: Run semantic release if: github.event_name != 'pull_request' env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_USERNAME: ${{ github.actor }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npx --yes -p @semantic-release/exec -p @semantic-release/changelog -p @semantic-release/git -p @semantic-release/commit-analyzer -p @semantic-release/release-notes-generator semantic-release @@ -73,16 +71,11 @@ jobs: - name: Run semantic release (dry run) if: github.event_name == 'pull_request' env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_USERNAME: ${{ github.actor }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npx --yes -p @semantic-release/exec -p @semantic-release/github -p @semantic-release/changelog -p @semantic-release/git -p @semantic-release/commit-analyzer -p @semantic-release/release-notes-generator semantic-release --dry-run - name: Execute Gradle build - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITHUB_USERNAME: ${{ github.actor }} run: ./gradlew build - name: Upload build artifact diff --git a/.github/workflows/veracode.yaml b/.github/workflows/veracode.yaml index 2b8d2a211..c6430dc0c 100644 --- a/.github/workflows/veracode.yaml +++ b/.github/workflows/veracode.yaml @@ -63,7 +63,7 @@ jobs: - name: Build with Gradle uses: gradle/gradle-build-action@v2 with: - arguments: build -PgithubToken=${{ secrets.GITHUB_TOKEN }} + arguments: build - name: Veracode Upload And Scan uses: veracode/veracode-uploadandscan-action@0.2.6 diff --git a/.gitignore b/.gitignore index b355ac349..4bbae21a7 100644 --- a/.gitignore +++ b/.gitignore @@ -64,6 +64,8 @@ dev-assets/env-files/env.local dev-assets/env-files/env.docker dev-assets/env-files/env.environment dev-assets/docker-environment/postgres/db.sh +dev-assets/docker-environment/pgAdmin/servers.json +dev-assets/docker-environment/pgAdmin/storage/* .java-version diff --git a/CHANGELOG.md b/CHANGELOG.md index 2117fa570..4f0249c80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,30 @@ -# [0.2.0](https://github.com/eclipse-tractusx/managed-identity-wallet/compare/v0.1.1...v0.2.0) (2023-10-23) +# [0.3.0-develop.1](https://github.com/eclipse-tractusx/managed-identity-wallet/compare/v0.2.0...v0.3.0-develop.1) (2023-12-07) +### Bug Fixes + +* **ci:** separate workflow "Test application (test + coverage)" for PR and repo ([6de785b](https://github.com/eclipse-tractusx/managed-identity-wallet/commit/6de785b670bdede6e55559ce461fb76d05f2ecc8)) +* **dev:** add file extension and refactor called method in gradle ([6811a8b](https://github.com/eclipse-tractusx/managed-identity-wallet/commit/6811a8b025b76f5998b1c2fd65b5f679e28468d3)) +* **dev:** add important notes to INSTALL.md ([a7c1b71](https://github.com/eclipse-tractusx/managed-identity-wallet/commit/a7c1b711ac402cbead4e10e5c79d6ba318eaacdb)) +* **dev:** adjust port to request against keycloak ([4a3d317](https://github.com/eclipse-tractusx/managed-identity-wallet/commit/4a3d317363690c78897c5db77a60fc716cd91b42)) +* **dev:** small adjustment to INSTALL.md ([59b6df4](https://github.com/eclipse-tractusx/managed-identity-wallet/commit/59b6df484bd31905f43d8bc9c83e44f0992839fb)) +* manually change the Helm chart version ([1ad16ed](https://github.com/eclipse-tractusx/managed-identity-wallet/commit/1ad16ed064d69214bc87d65f76740c2ecaa6b539)) +* method name from the cx-ssi-lib has been renamed ([b46d084](https://github.com/eclipse-tractusx/managed-identity-wallet/commit/b46d0846f6b9ccc6b439c82ffec783cd8b933e08)) +* remove filter for org.eclipse packages ([af9a9e5](https://github.com/eclipse-tractusx/managed-identity-wallet/commit/af9a9e50a9c15b16c8346561bc7ccb87a45df39d)) + + +### Features + +* add initContainers ([#142](https://github.com/eclipse-tractusx/managed-identity-wallet/issues/142)) ([7317800](https://github.com/eclipse-tractusx/managed-identity-wallet/commit/731780075ca5e1a707c8834013c4c98348e9c269)) +* add tpl to miw ingress ([#143](https://github.com/eclipse-tractusx/managed-identity-wallet/issues/143)) ([c56d133](https://github.com/eclipse-tractusx/managed-identity-wallet/commit/c56d1330f2df1a3468c1e680bcc4fe50898ca6bd)) +* **dev:** add pgAdmin to local dev env ([#144](https://github.com/eclipse-tractusx/managed-identity-wallet/issues/144)) ([d7f2bbe](https://github.com/eclipse-tractusx/managed-identity-wallet/commit/d7f2bbe2900322bb5ecba94aa1ab4fafad5cf21c)) +* **devel:** make application port dynamic (parameter) ([8816c89](https://github.com/eclipse-tractusx/managed-identity-wallet/commit/8816c899e8aa2170e753f3250c74552d898520c2)) +* **dev:** update README.md and introduce INSTALL.md for usage ([54b8d4a](https://github.com/eclipse-tractusx/managed-identity-wallet/commit/54b8d4ae9c859db2216ac3f85cbc56ab3cf6b950)) +* **helm:** Make liveness & readiness probes configurable ([#99](https://github.com/eclipse-tractusx/managed-identity-wallet/issues/99)) ([252eed1](https://github.com/eclipse-tractusx/managed-identity-wallet/commit/252eed1b15289740ba953861076de86ddc99fe4a)) +* **readme:** add "usage" section [WIP] ([6919b71](https://github.com/eclipse-tractusx/managed-identity-wallet/commit/6919b71870e9265ae09a66e3354ec43bf7d1d088)) + +# [0.2.0](https://github.com/eclipse-tractusx/managed-identity-wallet/compare/v0.1.1...v0.2.0) (2023-10-23) + ### Bug Fixes * CGD-468: Application starts with corrupted data in case of invalid AES key ([c734946](https://github.com/eclipse-tractusx/managed-identity-wallet/commit/c734946abfc1c34f1710f74e1329505dafa2fa00)) @@ -10,7 +34,6 @@ * typo in Bearer ([754b90a](https://github.com/eclipse-tractusx/managed-identity-wallet/commit/754b90a9fa90a308584949a6bf8085b6b27d8a19)) * Typo in Bearer ([#102](https://github.com/eclipse-tractusx/managed-identity-wallet/issues/102)) ([3765c68](https://github.com/eclipse-tractusx/managed-identity-wallet/commit/3765c689fcadc29f663c0521c3b9cc072ee8e779)) - ### Features * add Eclipse Copyright header to CHANGELOG.md.jinja ([dd53533](https://github.com/eclipse-tractusx/managed-identity-wallet/commit/dd53533bc6ccb9a160e4c51c46438321ed2b2be7)) diff --git a/DEPENDENCIES b/DEPENDENCIES index a26164cf8..b1ca06d1b 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -1,27 +1,27 @@ -maven/mavencentral/ch.qos.logback/logback-classic/1.4.8, EPL-1.0 OR LGPL-2.1-only, approved, #3435 -maven/mavencentral/ch.qos.logback/logback-core/1.4.8, EPL-1.0 OR LGPL-2.1-only, approved, #3373 +maven/mavencentral/ch.qos.logback/logback-classic/1.4.12, EPL-1.0 OR LGPL-2.1-only, approved, #3435 +maven/mavencentral/ch.qos.logback/logback-core/1.4.12, EPL-1.0 OR LGPL-2.1-only, approved, #3373 maven/mavencentral/com.apicatalog/titanium-json-ld-jre8/1.3.1, Apache-2.0, approved, #10237 -maven/mavencentral/com.apicatalog/titanium-json-ld/1.3.2, Apache-2.0, approved, #8912 -maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.15.2, Apache-2.0, approved, #7947 -maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.15.2, MIT AND Apache-2.0, approved, #7932 -maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.15.2, Apache-2.0, approved, #7934 -maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-xml/2.15.2, Apache-2.0, approved, #9237 -maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.15.2, Apache-2.0, approved, #8802 -maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jdk8/2.15.2, Apache-2.0, approved, #8808 -maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.15.2, Apache-2.0, approved, #7930 -maven/mavencentral/com.fasterxml.jackson.jaxrs/jackson-jaxrs-base/2.15.2, Apache-2.0, approved, #11061 -maven/mavencentral/com.fasterxml.jackson.jaxrs/jackson-jaxrs-json-provider/2.15.2, Apache-2.0, approved, #9101 -maven/mavencentral/com.fasterxml.jackson.module/jackson-module-jaxb-annotations/2.15.2, Apache-2.0, approved, #9100 -maven/mavencentral/com.fasterxml.jackson.module/jackson-module-parameter-names/2.15.2, Apache-2.0, approved, #8803 -maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.15.2, Apache-2.0, approved, #7929 +maven/mavencentral/com.apicatalog/titanium-json-ld/1.3.3, Apache-2.0, approved, #8912 +maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.15.3, Apache-2.0, approved, #7947 +maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.15.3, MIT AND Apache-2.0, approved, #7932 +maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.15.3, Apache-2.0, approved, #7934 +maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-xml/2.15.3, Apache-2.0, approved, #9237 +maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.15.3, Apache-2.0, approved, #8802 +maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jdk8/2.15.3, Apache-2.0, approved, #8808 +maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.15.3, Apache-2.0, approved, #7930 +maven/mavencentral/com.fasterxml.jackson.jaxrs/jackson-jaxrs-base/2.15.3, Apache-2.0, approved, #11061 +maven/mavencentral/com.fasterxml.jackson.jaxrs/jackson-jaxrs-json-provider/2.15.3, Apache-2.0, approved, #9101 +maven/mavencentral/com.fasterxml.jackson.module/jackson-module-jaxb-annotations/2.15.3, Apache-2.0, approved, #9100 +maven/mavencentral/com.fasterxml.jackson.module/jackson-module-parameter-names/2.15.3, Apache-2.0, approved, #8803 +maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.15.3, Apache-2.0, approved, #7929 maven/mavencentral/com.fasterxml.woodstox/woodstox-core/6.5.1, Apache-2.0, approved, #7950 maven/mavencentral/com.fasterxml/classmate/1.5.1, Apache-2.0, approved, clearlydefined -maven/mavencentral/com.github.ben-manes.caffeine/caffeine/3.1.6, Apache-2.0, approved, clearlydefined +maven/mavencentral/com.github.ben-manes.caffeine/caffeine/3.1.8, Apache-2.0, approved, clearlydefined maven/mavencentral/com.github.curious-odd-man/rgxgen/1.4, Apache-2.0, approved, clearlydefined maven/mavencentral/com.github.dasniko/testcontainers-keycloak/2.5.0, Apache-2.0, approved, #9175 -maven/mavencentral/com.github.docker-java/docker-java-api/3.3.0, Apache-2.0, approved, #10346 -maven/mavencentral/com.github.docker-java/docker-java-transport-zerodep/3.3.0, Apache-2.0 AND (Apache-2.0 AND BSD-3-Clause), approved, #7946 -maven/mavencentral/com.github.docker-java/docker-java-transport/3.3.0, Apache-2.0, approved, #7942 +maven/mavencentral/com.github.docker-java/docker-java-api/3.3.4, Apache-2.0, approved, #10346 +maven/mavencentral/com.github.docker-java/docker-java-transport-zerodep/3.3.4, Apache-2.0 AND (Apache-2.0 AND BSD-3-Clause), approved, #7946 +maven/mavencentral/com.github.docker-java/docker-java-transport/3.3.4, Apache-2.0, approved, #7942 maven/mavencentral/com.github.java-json-tools/btf/1.3, Apache-2.0 OR LGPL-3.0-or-later, approved, #2721 maven/mavencentral/com.github.java-json-tools/jackson-coreutils/2.0, Apache-2.0 OR LGPL-3.0-or-later, approved, #2719 maven/mavencentral/com.github.java-json-tools/json-patch/1.13, Apache-2.0 OR LGPL-3.0-or-later, approved, CQ23929 @@ -30,18 +30,13 @@ maven/mavencentral/com.github.multiformats/java-multibase/v1.1.0, MIT AND BSD-3- maven/mavencentral/com.github.stephenc.jcip/jcip-annotations/1.0-1, Apache-2.0, approved, CQ21949 maven/mavencentral/com.google.code.findbugs/jsr305/3.0.2, Apache-2.0, approved, #20 maven/mavencentral/com.google.code.gson/gson/2.10.1, Apache-2.0, approved, #6159 -maven/mavencentral/com.google.crypto.tink/tink/1.9.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/com.google.errorprone/error_prone_annotations/2.18.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/com.google.guava/failureaccess/1.0.1, Apache-2.0, approved, CQ22654 -maven/mavencentral/com.google.guava/guava/30.1.1-android, Apache-2.0 AND CC0-1.0 AND LicenseRef-Public-Domain, approved, CQ23244 -maven/mavencentral/com.google.guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava, Apache-2.0, approved, CQ22657 -maven/mavencentral/com.google.http-client/google-http-client/1.43.1, Apache-2.0, approved, clearlydefined -maven/mavencentral/com.google.j2objc/j2objc-annotations/1.3, Apache-2.0, approved, CQ21195 +maven/mavencentral/com.google.crypto.tink/tink/1.11.0, Apache-2.0, approved, #10719 +maven/mavencentral/com.google.errorprone/error_prone_annotations/2.21.1, Apache-2.0, approved, #9834 maven/mavencentral/com.google.protobuf/protobuf-java/3.19.6, BSD-3-Clause, approved, clearlydefined maven/mavencentral/com.h2database/h2/2.2.220, (EPL-1.0 OR MPL-2.0) AND (LGPL-3.0-or-later OR EPL-1.0 OR MPL-2.0), approved, #9322 maven/mavencentral/com.ibm.async/asyncutil/0.1.0, Apache-2.0, approved, clearlydefined maven/mavencentral/com.jayway.jsonpath/json-path/2.8.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.31, Apache-2.0, approved, clearlydefined +maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.37.1, Apache-2.0, approved, #11701 maven/mavencentral/com.opencsv/opencsv/5.7.1, Apache-2.0, approved, clearlydefined maven/mavencentral/com.smartsensesolutions/commons-dao/0.0.5, Apache-2.0, approved, #9176 maven/mavencentral/com.squareup.okhttp3/okhttp/4.10.0, Apache-2.0 AND MPL-2.0, approved, #3057 @@ -64,12 +59,9 @@ maven/mavencentral/io.github.openfeign.form/feign-form-spring/3.8.0, Apache-2.0, maven/mavencentral/io.github.openfeign.form/feign-form/3.8.0, Apache-2.0, approved, clearlydefined maven/mavencentral/io.github.openfeign/feign-core/12.3, Apache-2.0, approved, clearlydefined maven/mavencentral/io.github.openfeign/feign-slf4j/12.3, Apache-2.0, approved, clearlydefined -maven/mavencentral/io.grpc/grpc-context/1.27.2, Apache-2.0, approved, clearlydefined -maven/mavencentral/io.micrometer/micrometer-commons/1.11.2, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #9243 -maven/mavencentral/io.micrometer/micrometer-core/1.11.2, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #9238 -maven/mavencentral/io.micrometer/micrometer-observation/1.11.2, Apache-2.0, approved, #9242 -maven/mavencentral/io.opencensus/opencensus-api/0.31.1, Apache-2.0, approved, clearlydefined -maven/mavencentral/io.opencensus/opencensus-contrib-http-util/0.31.1, Apache-2.0, approved, clearlydefined +maven/mavencentral/io.micrometer/micrometer-commons/1.11.6, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #9243 +maven/mavencentral/io.micrometer/micrometer-core/1.11.6, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #9238 +maven/mavencentral/io.micrometer/micrometer-observation/1.11.6, Apache-2.0, approved, #9242 maven/mavencentral/io.quarkus/quarkus-junit4-mock/2.13.7.Final, Apache-2.0, approved, clearlydefined maven/mavencentral/io.setl/rdf-urdna/1.2, Apache-2.0, approved, clearlydefined maven/mavencentral/io.smallrye.common/smallrye-common-annotation/1.6.0, Apache-2.0, approved, clearlydefined @@ -87,53 +79,56 @@ maven/mavencentral/io.swagger.core.v3/swagger-models-jakarta/2.2.9, Apache-2.0, maven/mavencentral/jakarta.activation/jakarta.activation-api/2.1.2, EPL-2.0 OR BSD-3-Clause OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jaf maven/mavencentral/jakarta.annotation/jakarta.annotation-api/2.1.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.ca maven/mavencentral/jakarta.inject/jakarta.inject-api/2.0.1, Apache-2.0, approved, clearlydefined -maven/mavencentral/jakarta.json/jakarta.json-api/2.1.2, EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0, approved, #7907 +maven/mavencentral/jakarta.json/jakarta.json-api/2.1.3, EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0, approved, #7907 maven/mavencentral/jakarta.persistence/jakarta.persistence-api/3.1.0, EPL-2.0 OR BSD-3-Clause AND (EPL-2.0 OR BSD-3-Clause AND BSD-3-Clause), approved, #7696 maven/mavencentral/jakarta.transaction/jakarta.transaction-api/2.0.1, EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0, approved, #7697 maven/mavencentral/jakarta.validation/jakarta.validation-api/3.0.2, Apache-2.0, approved, ee4j.validation -maven/mavencentral/jakarta.xml.bind/jakarta.xml.bind-api/4.0.0, BSD-3-Clause, approved, ee4j.jaxb +maven/mavencentral/jakarta.xml.bind/jakarta.xml.bind-api/4.0.1, BSD-3-Clause, approved, ee4j.jaxb maven/mavencentral/javax.activation/javax.activation-api/1.2.0, (CDDL-1.1 OR GPL-2.0 WITH Classpath-exception-2.0) AND Apache-2.0, approved, CQ18740 maven/mavencentral/javax.xml.bind/jaxb-api/2.3.1, CDDL-1.1 OR GPL-2.0-only WITH Classpath-exception-2.0, approved, CQ16911 -maven/mavencentral/joda-time/joda-time/2.12.5, Apache-2.0, approved, clearlydefined maven/mavencentral/junit/junit/4.13.2, EPL-2.0, approved, CQ23636 -maven/mavencentral/net.bytebuddy/byte-buddy-agent/1.14.5, Apache-2.0, approved, #7164 -maven/mavencentral/net.bytebuddy/byte-buddy/1.14.5, Apache-2.0 AND BSD-3-Clause, approved, #7163 +maven/mavencentral/net.bytebuddy/byte-buddy-agent/1.14.10, Apache-2.0, approved, #7164 +maven/mavencentral/net.bytebuddy/byte-buddy/1.14.10, Apache-2.0 AND BSD-3-Clause, approved, #7163 maven/mavencentral/net.i2p.crypto/eddsa/0.3.0, CC0-1.0, approved, CQ22537 -maven/mavencentral/net.java.dev.jna/jna/5.12.1, Apache-2.0 OR LGPL-2.1-or-later, approved, #3217 +maven/mavencentral/net.java.dev.jna/jna/5.13.0, Apache-2.0 AND LGPL-2.1-or-later, approved, #6709 maven/mavencentral/net.minidev/accessors-smart/2.4.11, Apache-2.0, approved, #7515 maven/mavencentral/net.minidev/json-smart/2.4.11, Apache-2.0, approved, #3288 maven/mavencentral/org.antlr/antlr4-runtime/4.10.1, BSD-3-Clause AND LicenseRef-Public-domain AND MIT AND LicenseRef-Unicode-TOU, approved, #7065 maven/mavencentral/org.apache.commons/commons-collections4/4.4, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.apache.commons/commons-compress/1.23.0, Apache-2.0 AND BSD-3-Clause, approved, #7506 +maven/mavencentral/org.apache.commons/commons-compress/1.24.0, Apache-2.0 AND BSD-3-Clause AND bzip2-1.0.6 AND LicenseRef-Public-Domain, approved, #10368 maven/mavencentral/org.apache.commons/commons-lang3/3.12.0, Apache-2.0, approved, clearlydefined maven/mavencentral/org.apache.commons/commons-text/1.10.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.apache.httpcomponents/httpclient/4.5.14, Apache-2.0 AND LicenseRef-Public-Domain, approved, CQ23527 +maven/mavencentral/org.apache.httpcomponents/httpclient/4.5.13, Apache-2.0 AND LicenseRef-Public-Domain, approved, CQ23527 maven/mavencentral/org.apache.httpcomponents/httpcore/4.4.16, Apache-2.0, approved, CQ23528 maven/mavencentral/org.apache.james/apache-mime4j-core/0.8.3, Apache-2.0, approved, clearlydefined maven/mavencentral/org.apache.james/apache-mime4j-dom/0.8.3, Apache-2.0, approved, #2340 maven/mavencentral/org.apache.james/apache-mime4j-storage/0.8.3, Apache-2.0, approved, clearlydefined maven/mavencentral/org.apache.logging.log4j/log4j-api/2.20.0, Apache-2.0, approved, clearlydefined maven/mavencentral/org.apache.logging.log4j/log4j-to-slf4j/2.20.0, Apache-2.0, approved, #8799 -maven/mavencentral/org.apache.tomcat.embed/tomcat-embed-core/10.1.11, Apache-2.0 AND (EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0) AND (CDDL-1.0 OR GPL-2.0-only WITH Classpath-exception-2.0) AND W3C AND CC0-1.0, approved, #5949 -maven/mavencentral/org.apache.tomcat.embed/tomcat-embed-el/10.1.11, Apache-2.0, approved, #6997 -maven/mavencentral/org.apache.tomcat.embed/tomcat-embed-websocket/10.1.11, Apache-2.0, approved, #7920 +maven/mavencentral/org.apache.tomcat.embed/tomcat-embed-core/10.1.16, Apache-2.0 AND (EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0) AND (CDDL-1.0 OR GPL-2.0-only WITH Classpath-exception-2.0) AND W3C AND CC0-1.0, approved, #5949 +maven/mavencentral/org.apache.tomcat.embed/tomcat-embed-el/10.1.16, Apache-2.0, approved, #6997 +maven/mavencentral/org.apache.tomcat.embed/tomcat-embed-websocket/10.1.16, Apache-2.0, approved, #7920 maven/mavencentral/org.apiguardian/apiguardian-api/1.1.2, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.aspectj/aspectjweaver/1.9.19, EPL-1.0, approved, tools.aspectj +maven/mavencentral/org.aspectj/aspectjweaver/1.9.20.1, Apache-2.0 AND BSD-3-Clause AND EPL-1.0 AND BSD-3-Clause AND Apache-1.1, approved, #7695 maven/mavencentral/org.assertj/assertj-core/3.24.2, Apache-2.0, approved, #6161 maven/mavencentral/org.bouncycastle/bcpkix-jdk15on/1.69, MIT, approved, clearlydefined -maven/mavencentral/org.bouncycastle/bcprov-jdk15on/1.70, MIT, approved, #1712 +maven/mavencentral/org.bouncycastle/bcprov-jdk15on/1.69, MIT, approved, clearlydefined +maven/mavencentral/org.bouncycastle/bcprov-jdk18on/1.77, MIT AND CC0-1.0, approved, #11595 maven/mavencentral/org.bouncycastle/bcutil-jdk15on/1.69, MIT, approved, clearlydefined -maven/mavencentral/org.checkerframework/checker-compat-qual/2.5.5, MIT, approved, clearlydefined -maven/mavencentral/org.checkerframework/checker-qual/3.33.0, MIT, approved, clearlydefined +maven/mavencentral/org.checkerframework/checker-qual/3.37.0, MIT, approved, clearlydefined maven/mavencentral/org.codehaus.woodstox/stax2-api/4.2.1, BSD-2-Clause, approved, #2670 -maven/mavencentral/org.glassfish.jaxb/jaxb-core/4.0.3, BSD-3-Clause, approved, ee4j.jaxb -maven/mavencentral/org.glassfish.jaxb/jaxb-runtime/4.0.3, BSD-3-Clause, approved, ee4j.jaxb -maven/mavencentral/org.glassfish.jaxb/txw2/4.0.3, BSD-3-Clause, approved, ee4j.jaxb +maven/mavencentral/org.eclipse.angus/angus-activation/2.0.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.angus +maven/mavencentral/org.eclipse.microprofile.config/microprofile-config-api/2.0, Apache-2.0, approved, technology.microprofile +maven/mavencentral/org.eclipse.parsson/parsson/1.1.5, EPL-2.0, approved, ee4j.parsson +maven/mavencentral/org.eclipse.tractusx.ssi/cx-ssi-lib/0.0.18, Apache-2.0, approved, automotive.tractusx +maven/mavencentral/org.glassfish.jaxb/jaxb-core/4.0.4, BSD-3-Clause, approved, ee4j.jaxb +maven/mavencentral/org.glassfish.jaxb/jaxb-runtime/4.0.4, BSD-3-Clause, approved, ee4j.jaxb +maven/mavencentral/org.glassfish.jaxb/txw2/4.0.4, BSD-3-Clause, approved, ee4j.jaxb maven/mavencentral/org.hamcrest/hamcrest-core/2.2, BSD-3-Clause, approved, clearlydefined maven/mavencentral/org.hamcrest/hamcrest/2.2, BSD-3-Clause, approved, clearlydefined maven/mavencentral/org.hdrhistogram/HdrHistogram/2.1.12, BSD-2-Clause OR LicenseRef-Public-Domain, approved, CQ13192 maven/mavencentral/org.hibernate.common/hibernate-commons-annotations/6.0.6.Final, LGPL-2.1-only, approved, #6962 -maven/mavencentral/org.hibernate.orm/hibernate-core/6.2.6.Final, LGPL-2.1-only AND Apache-2.0 AND MIT AND CC-PDDC AND (EPL-2.0 OR BSD-3-Clause), approved, #9121 +maven/mavencentral/org.hibernate.orm/hibernate-core/6.2.13.Final, LGPL-2.1-only AND Apache-2.0 AND MIT AND CC-PDDC AND (EPL-2.0 OR BSD-3-Clause), approved, #9121 maven/mavencentral/org.hibernate.validator/hibernate-validator/8.0.1.Final, Apache-2.0, approved, clearlydefined maven/mavencentral/org.jacoco/org.jacoco.agent/0.8.9, EPL-2.0, approved, CQ23285 maven/mavencentral/org.jacoco/org.jacoco.ant/0.8.9, EPL-2.0, approved, #1068 @@ -183,63 +178,64 @@ maven/mavencentral/org.ow2.asm/asm/9.3, BSD-3-Clause, approved, clearlydefined maven/mavencentral/org.ow2.asm/asm/9.5, BSD-3-Clause, approved, #7554 maven/mavencentral/org.postgresql/postgresql/42.6.0, BSD-2-Clause AND Apache-2.0, approved, #9159 maven/mavencentral/org.projectlombok/lombok/1.18.28, MIT AND LicenseRef-Public-Domain, approved, CQ23907 +maven/mavencentral/org.projectlombok/lombok/1.18.30, MIT AND LicenseRef-Public-Domain, approved, CQ23907 maven/mavencentral/org.reactivestreams/reactive-streams/1.0.4, CC0-1.0, approved, CQ16332 maven/mavencentral/org.rnorth.duct-tape/duct-tape/1.0.8, MIT, approved, clearlydefined maven/mavencentral/org.skyscreamer/jsonassert/1.5.1, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.slf4j/jul-to-slf4j/2.0.7, MIT, approved, #7698 -maven/mavencentral/org.slf4j/slf4j-api/2.0.7, MIT, approved, #5915 +maven/mavencentral/org.slf4j/jul-to-slf4j/2.0.9, MIT, approved, #7698 +maven/mavencentral/org.slf4j/slf4j-api/2.0.9, MIT, approved, #5915 maven/mavencentral/org.springdoc/springdoc-openapi-starter-common/2.1.0, Apache-2.0, approved, clearlydefined maven/mavencentral/org.springdoc/springdoc-openapi-starter-webmvc-api/2.1.0, Apache-2.0, approved, clearlydefined maven/mavencentral/org.springdoc/springdoc-openapi-starter-webmvc-ui/2.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.boot/spring-boot-actuator-autoconfigure/3.1.2, Apache-2.0, approved, #9348 -maven/mavencentral/org.springframework.boot/spring-boot-actuator/3.1.2, Apache-2.0, approved, #9342 -maven/mavencentral/org.springframework.boot/spring-boot-autoconfigure/3.1.2, Apache-2.0, approved, #9341 -maven/mavencentral/org.springframework.boot/spring-boot-devtools/3.1.2, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.springframework.boot/spring-boot-starter-actuator/3.1.2, Apache-2.0, approved, #9344 -maven/mavencentral/org.springframework.boot/spring-boot-starter-aop/3.1.2, Apache-2.0, approved, #9338 -maven/mavencentral/org.springframework.boot/spring-boot-starter-data-jpa/3.1.2, Apache-2.0, approved, #9733 -maven/mavencentral/org.springframework.boot/spring-boot-starter-jdbc/3.1.2, Apache-2.0, approved, #9737 -maven/mavencentral/org.springframework.boot/spring-boot-starter-json/3.1.2, Apache-2.0, approved, #9336 -maven/mavencentral/org.springframework.boot/spring-boot-starter-logging/3.1.2, Apache-2.0, approved, #9343 -maven/mavencentral/org.springframework.boot/spring-boot-starter-security/3.1.2, Apache-2.0, approved, #9337 -maven/mavencentral/org.springframework.boot/spring-boot-starter-test/3.1.2, Apache-2.0, approved, #9353 -maven/mavencentral/org.springframework.boot/spring-boot-starter-tomcat/3.1.2, Apache-2.0, approved, #9351 -maven/mavencentral/org.springframework.boot/spring-boot-starter-validation/3.1.2, Apache-2.0, approved, #9335 -maven/mavencentral/org.springframework.boot/spring-boot-starter-web/3.1.2, Apache-2.0, approved, #9347 -maven/mavencentral/org.springframework.boot/spring-boot-starter/3.1.2, Apache-2.0, approved, #9349 -maven/mavencentral/org.springframework.boot/spring-boot-test-autoconfigure/3.1.2, Apache-2.0, approved, #9339 -maven/mavencentral/org.springframework.boot/spring-boot-test/3.1.2, Apache-2.0, approved, #9346 -maven/mavencentral/org.springframework.boot/spring-boot/3.1.2, Apache-2.0, approved, #9352 +maven/mavencentral/org.springframework.boot/spring-boot-actuator-autoconfigure/3.1.6, Apache-2.0, approved, #9348 +maven/mavencentral/org.springframework.boot/spring-boot-actuator/3.1.6, Apache-2.0, approved, #9342 +maven/mavencentral/org.springframework.boot/spring-boot-autoconfigure/3.1.6, Apache-2.0, approved, #9341 +maven/mavencentral/org.springframework.boot/spring-boot-devtools/3.1.5, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.springframework.boot/spring-boot-starter-actuator/3.1.6, Apache-2.0, approved, #9344 +maven/mavencentral/org.springframework.boot/spring-boot-starter-aop/3.1.6, Apache-2.0, approved, #9338 +maven/mavencentral/org.springframework.boot/spring-boot-starter-data-jpa/3.1.6, Apache-2.0, approved, #9733 +maven/mavencentral/org.springframework.boot/spring-boot-starter-jdbc/3.1.6, Apache-2.0, approved, #9737 +maven/mavencentral/org.springframework.boot/spring-boot-starter-json/3.1.6, Apache-2.0, approved, #9336 +maven/mavencentral/org.springframework.boot/spring-boot-starter-logging/3.1.6, Apache-2.0, approved, #9343 +maven/mavencentral/org.springframework.boot/spring-boot-starter-security/3.1.6, Apache-2.0, approved, #9337 +maven/mavencentral/org.springframework.boot/spring-boot-starter-test/3.1.6, Apache-2.0, approved, #9353 +maven/mavencentral/org.springframework.boot/spring-boot-starter-tomcat/3.1.6, Apache-2.0, approved, #9351 +maven/mavencentral/org.springframework.boot/spring-boot-starter-validation/3.1.6, Apache-2.0, approved, #9335 +maven/mavencentral/org.springframework.boot/spring-boot-starter-web/3.1.6, Apache-2.0, approved, #9347 +maven/mavencentral/org.springframework.boot/spring-boot-starter/3.1.6, Apache-2.0, approved, #9349 +maven/mavencentral/org.springframework.boot/spring-boot-test-autoconfigure/3.1.6, Apache-2.0, approved, #9339 +maven/mavencentral/org.springframework.boot/spring-boot-test/3.1.6, Apache-2.0, approved, #9346 +maven/mavencentral/org.springframework.boot/spring-boot/3.1.6, Apache-2.0, approved, #9352 maven/mavencentral/org.springframework.cloud/spring-cloud-commons/4.0.3, Apache-2.0, approved, #7292 maven/mavencentral/org.springframework.cloud/spring-cloud-context/4.0.3, Apache-2.0, approved, #7306 maven/mavencentral/org.springframework.cloud/spring-cloud-openfeign-core/4.0.3, Apache-2.0, approved, #7305 maven/mavencentral/org.springframework.cloud/spring-cloud-starter-openfeign/4.0.3, Apache-2.0, approved, #7302 maven/mavencentral/org.springframework.cloud/spring-cloud-starter/4.0.3, Apache-2.0, approved, #7299 -maven/mavencentral/org.springframework.data/spring-data-commons/3.1.2, Apache-2.0, approved, #8805 -maven/mavencentral/org.springframework.data/spring-data-jpa/3.1.2, Apache-2.0, approved, #9120 -maven/mavencentral/org.springframework.security/spring-security-config/6.1.2, Apache-2.0, approved, #9736 -maven/mavencentral/org.springframework.security/spring-security-core/6.1.2, Apache-2.0, approved, #9801 -maven/mavencentral/org.springframework.security/spring-security-crypto/6.1.2, Apache-2.0 AND ISC, approved, #9735 -maven/mavencentral/org.springframework.security/spring-security-oauth2-core/6.1.2, Apache-2.0, approved, #9741 -maven/mavencentral/org.springframework.security/spring-security-oauth2-jose/6.1.2, Apache-2.0, approved, #9345 -maven/mavencentral/org.springframework.security/spring-security-oauth2-resource-server/6.1.2, Apache-2.0, approved, #8798 +maven/mavencentral/org.springframework.data/spring-data-commons/3.1.6, Apache-2.0, approved, #8805 +maven/mavencentral/org.springframework.data/spring-data-jpa/3.1.6, Apache-2.0, approved, #9120 +maven/mavencentral/org.springframework.security/spring-security-config/6.1.5, Apache-2.0, approved, #9736 +maven/mavencentral/org.springframework.security/spring-security-core/6.1.5, Apache-2.0, approved, #9801 +maven/mavencentral/org.springframework.security/spring-security-crypto/6.1.5, Apache-2.0 AND ISC, approved, #9735 +maven/mavencentral/org.springframework.security/spring-security-oauth2-core/6.1.5, Apache-2.0, approved, #9741 +maven/mavencentral/org.springframework.security/spring-security-oauth2-jose/6.1.5, Apache-2.0, approved, #9345 +maven/mavencentral/org.springframework.security/spring-security-oauth2-resource-server/6.1.5, Apache-2.0, approved, #8798 maven/mavencentral/org.springframework.security/spring-security-rsa/1.0.11.RELEASE, Apache-2.0, approved, CQ20647 -maven/mavencentral/org.springframework.security/spring-security-web/6.1.2, Apache-2.0, approved, #9800 -maven/mavencentral/org.springframework/spring-aop/6.0.11, Apache-2.0, approved, #5940 -maven/mavencentral/org.springframework/spring-aspects/6.0.11, Apache-2.0, approved, #5930 -maven/mavencentral/org.springframework/spring-beans/6.0.11, Apache-2.0, approved, #5937 -maven/mavencentral/org.springframework/spring-context/6.0.11, Apache-2.0, approved, #5936 -maven/mavencentral/org.springframework/spring-core/6.0.11, Apache-2.0 AND BSD-3-Clause, approved, #5948 -maven/mavencentral/org.springframework/spring-expression/6.0.11, Apache-2.0, approved, #3284 -maven/mavencentral/org.springframework/spring-jcl/6.0.11, Apache-2.0, approved, #3283 -maven/mavencentral/org.springframework/spring-jdbc/6.0.11, Apache-2.0, approved, #5924 -maven/mavencentral/org.springframework/spring-orm/6.0.11, Apache-2.0, approved, #5925 -maven/mavencentral/org.springframework/spring-test/6.0.11, Apache-2.0, approved, #7003 -maven/mavencentral/org.springframework/spring-tx/6.0.11, Apache-2.0, approved, #5926 -maven/mavencentral/org.springframework/spring-web/6.0.11, Apache-2.0, approved, #5942 -maven/mavencentral/org.springframework/spring-webmvc/6.0.11, Apache-2.0, approved, #5944 -maven/mavencentral/org.testcontainers/junit-jupiter/1.18.3, MIT, approved, #7941 -maven/mavencentral/org.testcontainers/testcontainers/1.18.3, MIT, approved, #7938 +maven/mavencentral/org.springframework.security/spring-security-web/6.1.5, Apache-2.0, approved, #9800 +maven/mavencentral/org.springframework/spring-aop/6.0.14, Apache-2.0, approved, #5940 +maven/mavencentral/org.springframework/spring-aspects/6.0.14, Apache-2.0, approved, #5930 +maven/mavencentral/org.springframework/spring-beans/6.0.14, Apache-2.0, approved, #5937 +maven/mavencentral/org.springframework/spring-context/6.0.14, Apache-2.0, approved, #5936 +maven/mavencentral/org.springframework/spring-core/6.0.14, Apache-2.0 AND BSD-3-Clause, approved, #5948 +maven/mavencentral/org.springframework/spring-expression/6.0.14, Apache-2.0, approved, #3284 +maven/mavencentral/org.springframework/spring-jcl/6.0.14, Apache-2.0, approved, #3283 +maven/mavencentral/org.springframework/spring-jdbc/6.0.14, Apache-2.0, approved, #5924 +maven/mavencentral/org.springframework/spring-orm/6.0.14, Apache-2.0, approved, #5925 +maven/mavencentral/org.springframework/spring-test/6.0.14, Apache-2.0, approved, #7003 +maven/mavencentral/org.springframework/spring-tx/6.0.14, Apache-2.0, approved, #5926 +maven/mavencentral/org.springframework/spring-web/6.0.14, Apache-2.0, approved, #5942 +maven/mavencentral/org.springframework/spring-webmvc/6.0.14, Apache-2.0, approved, #5944 +maven/mavencentral/org.testcontainers/junit-jupiter/1.19.3, MIT, approved, #10344 +maven/mavencentral/org.testcontainers/testcontainers/1.19.3, Apache-2.0 AND MIT, approved, #10347 maven/mavencentral/org.webjars/swagger-ui/4.18.2, Apache-2.0, approved, #7850 maven/mavencentral/org.xmlunit/xmlunit-core/2.9.1, Apache-2.0, approved, #6272 maven/mavencentral/org.yaml/snakeyaml/2.0, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #7275 diff --git a/Dockerfile b/Dockerfile index 40e66bd21..1dccce7af 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ RUN apk add curl USER miw -COPY /build/libs/miw-latest.jar /app/ +COPY LICENSE NOTICE.md DEPENDENCIES SECURITY.md /build/libs/miw-latest.jar /app/ WORKDIR /app diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 000000000..0d3c96cbf --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,40 @@ +# Managed Identity Wallets + +If you just want to try out MIW (without any developer setup), then you can find a quick start guide here: + +(It will only work on macOS or GNU/Linux - For Windows, +you need to use the [WSL](https://learn.microsoft.com/de-de/windows/wsl/install)) + +- You need to install these tools: + - [Docker](https://docs.docker.com/desktop/) (or from your package manager) + -> Configure it to run without root permission + - Docker [compose plugin](https://docs.docker.com/compose/) + - [Taskfile](https://taskfile.dev) + - [jq](https://jqlang.github.io/jq/) +- Clone this repo +- (Optional) Checkout main (stable) or develop (latest), if not already checked out +- Copy `dev-assets/env-files/env.docker.dist` to `dev-assets/env-files/env.docker` +- Set these variables in `env.docker` + - POSTGRES_PASSWORD + - POSTGRES_PASSWORD_MIW + - KEYCLOAK_ADMIN_PASSWORD + - ENCRYPTION_KEY (32 random alphanumeric characters) +- Follow the "docker" path of the "Development setup" to get it up and running: + 1. Run `task docker:start-app` and wait until it shows "Started ManagedIdentityWalletsApplication in ... seconds" + 2. Run `task app:get-token` in another shell and copy the token (including "BEARER" prefix) (Mac users have the token already in their clipboard :) ) + 3. Open API doc on http://localhost:8000 + 4. Click on Authorize on Swagger UI and on the dialog paste the token (incl. "Bearer") into the "value" input + 5. Click on "Authorize" and "close" + 6. MIW is up, running, and you are authorized to fire requests in the Swagger UI + 7. If you're done, then run `task docker:stop-app` to clean up everything + +> [!IMPORTANT] +> You need to use Java 17! + +> [!WARNING] +> If you encounter some kind of database connection errors, then execute `task docker:stop-app`. +> This will remove all existing Docker volumes, which may cause this error. + +> [!IMPORTANT] +> Ensure you have exactly 32 random alphanumeric characters set +> for `ENCRYPTION_KEY` in `dev-assets/env-files/env.docker` diff --git a/NOTICE.md b/NOTICE.md index afa85bb03..b589e03db 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -36,13 +36,6 @@ This project leverages the following third party content. See DEPENDENCIES file. -cx-ssi-lib-0.0.16.jar (0.0.16) - - License:   Apache-2.0 - - Licence Path: - - Project URL:  - - Source URL:   - - Download URL:  - ## Cryptography Content may contain encryption software. The country in which you are currently diff --git a/README.md b/README.md index 97b62258a..396475d29 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,10 @@ The Managed Identity Wallets (MIW) service implements the Self-Sovereign-Identity (SSI) using `did:web`. +# Usage + +See [INSTALL.md](INSTALL.md) + # Developer Documentation To run MIW locally, this section describes the tooling as well as the local development setup. @@ -151,27 +155,23 @@ directory, but without ".dist" at the end. Description of the env files: -- **env.local**: Setup everything to get ready for flow "local". You need to fill in the passwords. -- **env.docker**: Setup everything to get ready for flow "docker". You need to fill in the passwords. +- **env.local**: Set up everything to get ready for flow "local". You need to fill in the passwords. +- **env.docker**: Set up everything to get ready for flow "docker". You need to fill in the passwords. -> **IMPORTANT**: ssi-lib is resolving DID documents over network. There are two endpoints that rely on this resolution: +> **IMPORTANT**: ssi-lib is resolving DID documents over the network. There are two endpoints that rely on this resolution: > - Verifiable Credentials - Validation > - Verifiable Presentations - Validation -> -> The following parameters must be added or changed in env.local or env.docker file to ensure that these endpoints work -> as intended in local development environment: -> Add: ENFORCE_HTTPS_IN_DID_RESOLUTION=false -> Change: MIW_HOST_NAME from miw to localhost -> Change: APPLICATION_PORT from 8000 to 80 - -> **IMPORTANT**: When you are using MacOS and the MIW docker container won't start up (stuck somewhere or doesn't start +> +> The following parameters are set in env.local or env.docker file per default: +> ENFORCE_HTTPS_IN_DID_RESOLUTION=false +> MIW_HOST_NAME=localhost +> APPLICATION_PORT=80 +> If you intend to change them, the DID resolving may not work properly anymore! + +> **IMPORTANT**: When you are using macOS and the MIW docker container won't start up (stuck somewhere or doesn't start > at all), you can enable the docker-desktop feature "Use Rosetta for x86/amd64 emulation on Apple Silicon" in your > Docker settings (under "features in development"). This should fix the issue. -In both env files (env.local and env.docker) you need to set *GITHUB_USERNAME* and *GITHUB_TOKEN* in order to be able to -build the app, because the SSI lib is stored in a private repo (you also need the proper rights to access the repo). -The access token need to have `read:packages` access. (ref: https://github.com/settings/tokens/new) - Note: *SKIP_GRADLE_TASKS_PARAM* is used to pass parameters to the build process of the MIW jar. Currently, it skips the tests and code coverage, but speeds up the build time. If you want to activate it, just comment it out like `SKIP_GRADLE_TASKS_PARAM="" #"-x jacocoTestCoverageVerification -x test"` @@ -206,6 +206,27 @@ When you just run `task` without parameters, you will see all tasks available. 5. Click on "Authorize" and "close" 6. MIW is up and running +### pgAdmin + +This local environment contains [pgAdmin](https://www.pgadmin.org/), which is also started (default: http://localhost:8888). +The default login is: + +``` +user: pg@admin.com (you can change it in the env.* files) +password: the one you set for "POSTGRES_PASSWORD" in the env.* files +``` + +#### DB connection password + +When you log in into pgAdmin, the local Postgresql server is already configured. +But you will be asked to enter the DB password on the first time you connect to the DB. +(password: POSTGRES_PASSWORD in the env.* files) + +#### Storage folder + +The storage folder of pgAdmin is mounted to `dev-assets/docker-environment/pgAdmin/storage/`. +For example, You can save DB backups there, so you can access them on your local machine. + # End Users See OpenAPI documentation, which is automatically created from the source and available on each deployment at @@ -344,4 +365,4 @@ See [Docker-hub-notice.md](./Docker-hub-notice.md) We would like to give credit to these projects, which we use in our project. -[![semantic-release: angular](https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release)](https://github.com/semantic-release/semantic-release) \ No newline at end of file +[![semantic-release: angular](https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release)](https://github.com/semantic-release/semantic-release) diff --git a/SECURITY.md b/SECURITY.md index 7d8fced73..bd15e824c 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,6 +1,17 @@ -# Security Policy - ## Reporting a Vulnerability -Please report a found vulnerability here: -[https://www.eclipse.org/security/](https://www.eclipse.org/security/) \ No newline at end of file +Please do **not** report security vulnerabilities through public GitHub issues. + +Please report vulnerabilities to this repository via **GitHub security advisories** instead. + +How? Inside affected repository → security tab + +For contributors: +→ Report a vulnerability + +For committers: +→ Advisories → New draft security advisory + +In severe cases, you can also report a found vulnerability via mail or eclipse issue here: https://www.eclipse.org/security/ + +See [Eclipse Foundation Vulnerability Reporting Policy](https://www.eclipse.org/projects/handbook/#vulnerability) \ No newline at end of file diff --git a/build.gradle b/build.gradle index aa3ac6f31..68734b53b 100644 --- a/build.gradle +++ b/build.gradle @@ -8,22 +8,11 @@ plugins { // used to download the 'dash.jar' for license checks // docs: https://github.com/michel-kraemer/gradle-download-task id "de.undercouch.download" version "5.5.0" - - // used to convert .env variables to gradle env variables - // docs: https://github.com/uzzu/dotenv-gradle - id "co.uzzu.dotenv.gradle" version "2.0.0" } group = "${groupName}" version = "${applicationVersion}" sourceCompatibility = JavaVersion.VERSION_17 -// Fetch the environment variables GITHUB_USERNAME, GITHUB_TOKEN -// these can be set in /.env -// or export GITHUB_USERNAME=... -// export GITHUB_TOKEN=... -// When using `task ...` this is not necessary -def githubUserName = "${githubUserName}" ? "${githubUserName}" : env.fetch('GITHUB_USERNAME') -def githubToken = "${githubToken}" ? "${githubToken}" : env.fetch('GITHUB_TOKEN') // alias for Project.getConfigurations() configurations { @@ -35,6 +24,22 @@ configurations { compileOnly.extendsFrom(annotaionProcessor) } +// this needs to be done, as we're using the org.springframework.boot plugin +// with native Gradle bom resolution +// docs: https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/htmlsingle/#managing-dependencies.gradle-bom-support.customizing +// docs: https://docs.gradle.org/7.6/dsl/org.gradle.api.artifacts.ResolutionStrategy.html +configurations.configureEach { + resolutionStrategy.eachDependency { DependencyResolveDetails details -> + if (details.requested.group == 'ch.qos.logback') { + details.useVersion '1.4.12' + } + // avoid a license issue + if (details.requested.name == 'spring-boot-devtools') { + details.useVersion '3.1.5' + } + } +} + repositories { // delegate is RepositoryHandler // docs: https://docs.gradle.org/7.6/dsl/org.gradle.api.artifacts.dsl.RepositoryHandler.html @@ -44,13 +49,6 @@ repositories { url = uri("https://repo.danubetech.com/repository/maven-public") } maven { url 'https://jitpack.io' } - maven { - url = uri("https://maven.pkg.github.com/catenax-ng/product-lab-ssi") - credentials { - username = "${githubUserName}" - password = "${githubToken}" - } - } maven { // Used to resolve Dash License Tool // Dash has a maven plugin, BUT is not resolvable through mavenCentral() @@ -79,7 +77,7 @@ dependencies { implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:${openApiVersion}" implementation group: 'com.smartsensesolutions', name: 'commons-dao', version: '0.0.5' implementation 'org.liquibase:liquibase-core' - implementation 'org.eclipse.tractusx.ssi:cx-ssi-lib:0.0.17' + implementation 'org.eclipse.tractusx.ssi:cx-ssi-lib:0.0.18' //Added explicitly to mitigate CVE 2022-1471 implementation group: 'org.yaml', name: 'snakeyaml', version: '2.0' @@ -152,9 +150,9 @@ tasks.register('dashDependencies') { dashDependencies -> } } - def filtered = deps.findAll(d -> !d.startsWith('org.eclipse')).unique().sort() - filtered.each { logger.quiet("{}", it) } - file("deps.txt").write(filtered.join('\n')) + def uniqueSorted = deps.unique().sort() + uniqueSorted.each { logger.quiet("{}", it) } + file("deps.txt").write(uniqueSorted.join('\n')) } } @@ -183,10 +181,6 @@ dependencyManagement { } } -tasks.named('test', Test) { - useJUnitPlatform() -} - // 'build' task comes from the 'java' plugin // docs: https://docs.gradle.org/current/userguide/java_plugin.html build { @@ -209,6 +203,7 @@ bootJar { // 'test' comes from the 'java' plugin // docs: https://docs.gradle.org/current/userguide/java_plugin.html test { + useJUnitPlatform() finalizedBy jacocoTestReport } @@ -221,12 +216,15 @@ htmlDependencyReport { // 'jacocoTestReport' is provided by the 'jacoco' plugin // docs: https://docs.gradle.org/current/userguide/jacoco_plugin.html jacocoTestReport { - dependsOn test reports { - xml.required = false - csv.required = false - html.required = true + xml.enabled true + xml.outputLocation = file("./build/reports/xml/jacoco.xml") + + csv.enabled false + + html.enabled true + html.outputLocation = file("./build/reports/html/jacoco") } afterEvaluate { @@ -245,7 +243,6 @@ jacocoTestReport { // docs: https://docs.gradle.org/current/userguide/jacoco_plugin.html#sec:configuring_the_jacoco_plugin jacoco { toolVersion = "${jacocoVersion}" - } diff --git a/charts/managed-identity-wallet/Chart.yaml b/charts/managed-identity-wallet/Chart.yaml index 291132cea..dfa8c0038 100644 --- a/charts/managed-identity-wallet/Chart.yaml +++ b/charts/managed-identity-wallet/Chart.yaml @@ -25,8 +25,8 @@ description: | type: application -version: 0.2.0 -appVersion: 0.2.0 +version: 0.3.0-develop.1 +appVersion: 0.3.0-develop.1 home: https://github.com/eclipse-tractusx/managed-identity-wallet keywords: @@ -37,6 +37,9 @@ sources: - https://github.com/eclipse-tractusx/managed-identity-wallet maintainers: + - name: Dominik Pinsel + email: dominik.pinsel@mercedes-benz.com + url: https://github.com/DominikPinsel - name: Peter Motzko email: peter.motzko@volkswagen.de url: https://github.com/pmoscode diff --git a/charts/managed-identity-wallet/README.md b/charts/managed-identity-wallet/README.md index 95158bb53..bf1616852 100644 --- a/charts/managed-identity-wallet/README.md +++ b/charts/managed-identity-wallet/README.md @@ -2,7 +2,7 @@ # managed-identity-wallet -![Version: 0.1.0-rc.2](https://img.shields.io/badge/Version-0.1.0--rc.2-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.1.0-rc.2](https://img.shields.io/badge/AppVersion-0.1.0--rc.2-informational?style=flat-square) +![Version: 0.2.0-develop.11](https://img.shields.io/badge/Version-0.2.0--develop.11-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.2.0-develop.11](https://img.shields.io/badge/AppVersion-0.2.0--develop.11-informational?style=flat-square) Managed Identity Wallet is supposed to supply a secure data source and data sink for Digital Identity Documents (DID), in order to enable Self-Sovereign Identity founding on those DIDs. And at the same it shall support an uninterrupted tracking and tracing and documenting the usage of those DIDs, e.g. within logistical supply chains. @@ -97,11 +97,15 @@ See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command document | ingress.enabled | bool | `false` | Enable ingress controller resource | | ingress.hosts | list | `[]` | Ingress accepted hostnames | | ingress.tls | list | `[]` | Ingress TLS configuration | +| initContainers | list | `[]` | add initContainers to the miw deployment | | keycloak.auth.adminPassword | string | `""` | Keycloak admin password | | keycloak.auth.adminUser | string | `"admin"` | Keycloak admin user | | keycloak.enabled | bool | `true` | Enable to deploy Keycloak | -| keycloak.extraEnvVars[0].name | string | `"KEYCLOAK_HOSTNAME"` | | -| keycloak.extraEnvVars[0].value | string | `"{{ .Release.Name }}-keycloak"` | | +| keycloak.extraEnvVars | list | `[]` | | +| keycloak.ingress.annotations | object | `{}` | | +| keycloak.ingress.enabled | bool | `false` | | +| keycloak.ingress.hosts | list | `[]` | | +| keycloak.ingress.tls | list | `[]` | | | keycloak.keycloakConfigCli.backoffLimit | int | `2` | Number of retries before considering a Job as failed | | keycloak.keycloakConfigCli.enabled | bool | `true` | Enable to create the miw playground realm | | keycloak.keycloakConfigCli.existingConfigmap | string | `"keycloak-realm-config"` | Existing configmap name for the realm configuration | @@ -110,6 +114,12 @@ See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command document | keycloak.postgresql.auth.username | string | `"miw_keycloak"` | Keycloak PostgreSQL user | | keycloak.postgresql.enabled | bool | `true` | Enable to deploy PostgreSQL | | keycloak.postgresql.nameOverride | string | `"keycloak-postgresql"` | Name of the PostgreSQL chart to deploy. Mandatory when the MIW deploys a PostgreSQL chart, too. | +| livenessProbe | object | `{"enabled":true,"failureThreshold":3,"initialDelaySeconds":20,"periodSeconds":5,"timeoutSeconds":15}` | Kubernetes [liveness-probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) | +| livenessProbe.enabled | bool | `true` | Enables/Disables the livenessProbe at all | +| livenessProbe.failureThreshold | int | `3` | When a probe fails, Kubernetes will try failureThreshold times before giving up. Giving up in case of liveness probe means restarting the container. | +| livenessProbe.initialDelaySeconds | int | `20` | Number of seconds after the container has started before readiness probe are initiated. | +| livenessProbe.periodSeconds | int | `5` | How often (in seconds) to perform the probe | +| livenessProbe.timeoutSeconds | int | `15` | Number of seconds after which the probe times out. | | miw.authorityWallet.bpn | string | `"BPNL000000000000"` | Authority Wallet BPNL | | miw.authorityWallet.name | string | `""` | Authority Wallet Name | | miw.database.encryptionKey.secret | string | `""` | Existing secret for database encryption key | @@ -128,7 +138,7 @@ See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command document | miw.keycloak.realm | string | `"miw_test"` | Keycloak realm | | miw.keycloak.url | string | `"http://{{ .Release.Name }}-keycloak"` | Keycloak URL | | miw.logging.level | string | `"INFO"` | Log level. Should be ether ERROR, WARN, INFO, DEBUG, or TRACE. | -| miw.ssi.enforceHttpsInDidWebResolution | bool | `false` | Enable to use HTTPS in DID Web Resolution | +| miw.ssi.enforceHttpsInDidWebResolution | bool | `true` | Enable to use HTTPS in DID Web Resolution | | miw.ssi.vcExpiryDate | string | `""` | Verifiable Credential expiry date. Format 'dd-MM-yyyy'. If empty it is set to 31-12- | | nameOverride | string | `""` | String to partially override common.names.fullname template (will maintain the release name) | | nodeSelector | object | `{"kubernetes.io/os":"linux"}` | NodeSelector configuration | @@ -144,6 +154,13 @@ See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command document | postgresql.backup.conjob.storage.size | string | `"8Gi"` | PVC Storage Request for the backup data volume | | postgresql.backup.enabled | bool | `false` | Enable to create a backup cronjob | | postgresql.enabled | bool | `true` | Enable to deploy Postgresql | +| readinessProbe | object | `{"enabled":true,"failureThreshold":3,"initialDelaySeconds":30,"periodSeconds":5,"successThreshold":1,"timeoutSeconds":5}` | Kubernetes [readiness-probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) | +| readinessProbe.enabled | bool | `true` | Enables/Disables the readinessProbe at all | +| readinessProbe.failureThreshold | int | `3` | When a probe fails, Kubernetes will try failureThreshold times before giving up. In case of readiness probe the Pod will be marked Unready. | +| readinessProbe.initialDelaySeconds | int | `30` | Number of seconds after the container has started before readiness probe are initiated. | +| readinessProbe.periodSeconds | int | `5` | How often (in seconds) to perform the probe | +| readinessProbe.successThreshold | int | `1` | Minimum consecutive successes for the probe to be considered successful after having failed. | +| readinessProbe.timeoutSeconds | int | `5` | Number of seconds after which the probe times out. | | replicaCount | int | `1` | The amount of replicas to run | | resources.limits.cpu | int | `2` | CPU resource limits | | resources.limits.memory | string | `"1Gi"` | Memory resource limits | @@ -230,9 +247,10 @@ when deploying the MIW in a production environment: | Name | Email | Url | | ---- | ------ | --- | +| Dominik Pinsel | | | | Peter Motzko | | |

(back to top)

---------------------------------------------- -Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) +Autogenerated from chart metadata using [helm-docs](https://github.com/norwoodj/helm-docs/) diff --git a/charts/managed-identity-wallet/README.md.gotmpl b/charts/managed-identity-wallet/README.md.gotmpl index 6263c171f..eb9cfa76a 100644 --- a/charts/managed-identity-wallet/README.md.gotmpl +++ b/charts/managed-identity-wallet/README.md.gotmpl @@ -155,4 +155,5 @@ when deploying the MIW in a production environment:

(back to top)

-{{ template "helm-docs.versionFooter" . }} +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs](https://github.com/norwoodj/helm-docs/) diff --git a/charts/managed-identity-wallet/templates/deployment.yaml b/charts/managed-identity-wallet/templates/deployment.yaml index 9a1aa38ae..40426b7aa 100644 --- a/charts/managed-identity-wallet/templates/deployment.yaml +++ b/charts/managed-identity-wallet/templates/deployment.yaml @@ -44,6 +44,10 @@ spec: serviceAccountName: {{ include "managed-identity-wallet.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- if .Values.initContainers }} + initContainers: + {{- tpl (.Values.initContainers | toYaml) $ | nindent 8 }} + {{- end }} containers: - name: {{ .Chart.Name }} securityContext: @@ -113,26 +117,33 @@ spec: - name: http containerPort: 8080 protocol: TCP + {{- with .Values.livenessProbe }} + {{- if .enabled }} livenessProbe: - failureThreshold: 3 httpGet: path: /actuator/health/liveness port: 8090 scheme: HTTP - periodSeconds: 5 - successThreshold: 1 - timeoutSeconds: 5 - initialDelaySeconds: 30 + failureThreshold: {{ .failureThreshold }} + initialDelaySeconds: {{ .initialDelaySeconds }} + periodSeconds: {{ .periodSeconds }} + timeoutSeconds: {{ .timeoutSeconds }} + {{- end }} + {{- end }} + {{- with .Values.readinessProbe }} + {{- if .enabled }} readinessProbe: - failureThreshold: 3 httpGet: path: /actuator/health/readiness port: 8090 scheme: HTTP - periodSeconds: 5 - successThreshold: 1 - timeoutSeconds: 5 - initialDelaySeconds: 30 + failureThreshold: {{ .failureThreshold }} + initialDelaySeconds: {{ .initialDelaySeconds }} + periodSeconds: {{ .periodSeconds }} + successThreshold: {{ .successThreshold }} + timeoutSeconds: {{ .timeoutSeconds }} + {{- end }} + {{- end }} resources: {{- toYaml .Values.resources | nindent 12 }} diff --git a/charts/managed-identity-wallet/templates/ingress.yaml b/charts/managed-identity-wallet/templates/ingress.yaml index 50a965ff1..a550fece2 100644 --- a/charts/managed-identity-wallet/templates/ingress.yaml +++ b/charts/managed-identity-wallet/templates/ingress.yaml @@ -50,14 +50,14 @@ spec: {{- range .Values.ingress.tls }} - hosts: {{- range .hosts }} - - {{ . | quote }} + - {{ tpl . $ | quote }} {{- end }} secretName: "{{ $fullName }}-{{ .secretName }}" {{- end }} {{- end }} rules: {{- range .Values.ingress.hosts }} - - host: {{ .host | quote }} + - host: {{ tpl .host $ | quote }} http: paths: {{- range .paths }} diff --git a/charts/managed-identity-wallet/values.yaml b/charts/managed-identity-wallet/values.yaml index 414099293..b627e1961 100644 --- a/charts/managed-identity-wallet/values.yaml +++ b/charts/managed-identity-wallet/values.yaml @@ -61,6 +61,10 @@ ingress: annotations: {} # -- Ingress accepted hostnames hosts: [] + # - host: chart-example.local + # paths: + # - path: / + # pathType: Prefix # -- Ingress TLS configuration tls: [] # - secretName: chart-example-tls @@ -82,6 +86,34 @@ securityContext: # -- Enable to run the container as a non-root user runAsNonRoot: true +# -- Kubernetes [liveness-probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) +livenessProbe: + # -- Enables/Disables the livenessProbe at all + enabled: true + # -- When a probe fails, Kubernetes will try failureThreshold times before giving up. Giving up in case of liveness probe means restarting the container. + failureThreshold: 3 + # -- Number of seconds after the container has started before readiness probe are initiated. + initialDelaySeconds: 20 + # -- Number of seconds after which the probe times out. + timeoutSeconds: 15 + # -- How often (in seconds) to perform the probe + periodSeconds: 5 + +# -- Kubernetes [readiness-probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) +readinessProbe: + # -- Enables/Disables the readinessProbe at all + enabled: true + # -- When a probe fails, Kubernetes will try failureThreshold times before giving up. In case of readiness probe the Pod will be marked Unready. + failureThreshold: 3 + # -- Number of seconds after the container has started before readiness probe are initiated. + initialDelaySeconds: 30 + # -- How often (in seconds) to perform the probe + periodSeconds: 5 + # -- Minimum consecutive successes for the probe to be considered successful after having failed. + successThreshold: 1 + # -- Number of seconds after which the probe times out. + timeoutSeconds: 5 + resources: requests: # -- CPU resource requests @@ -107,6 +139,9 @@ affinity: {} # -- PodAnnotation configuration podAnnotations: {} +# -- add initContainers to the miw deployment +initContainers: [] + ## @section Managed Identity Wallet Primary Parameters ## miw: diff --git a/dev-assets/docker-environment/docker-compose.yaml b/dev-assets/docker-environment/docker-compose.yaml index aa092e263..ba28cf286 100644 --- a/dev-assets/docker-environment/docker-compose.yaml +++ b/dev-assets/docker-environment/docker-compose.yaml @@ -28,13 +28,13 @@ services: env_file: - ../env-files/env.$DEV_ENVIRONMENT ports: - - "8000:8000" + - "$APPLICATION_PORT:$APPLICATION_PORT" - "8090:8090" networks: - miw-net postgres: - image: postgres:15.3-alpine3.18 + image: postgres:14.5-alpine3.16 volumes: - postgres_data:/var/lib/postgresql/data - ./postgres/db.sh:/docker-entrypoint-initdb.d/init-database.sh @@ -63,10 +63,30 @@ services: networks: - miw-net + pgadmin: + image: dpage/pgadmin4 + ports: + - "8888:80" + user: root # If removed, the storage mount won't work + env_file: + - ../env-files/env.$DEV_ENVIRONMENT + environment: + PGADMIN_DISABLE_POSTFIX: true + volumes: + - pgadmin_data:/var/lib/pgadmin + - ./pgAdmin/servers.json:/pgadmin4/servers.json + - ./pgAdmin/storage/:/var/lib/pgadmin/storage/pg_admin.com/ + depends_on: + - postgres + networks: + - miw-net + volumes: postgres_data: driver: local + pgadmin_data: + driver: local networks: miw-net: - name: miw-net \ No newline at end of file + name: miw-net diff --git a/dev-assets/docker-environment/pgAdmin/servers.json.tpl b/dev-assets/docker-environment/pgAdmin/servers.json.tpl new file mode 100755 index 000000000..ac34530a5 --- /dev/null +++ b/dev-assets/docker-environment/pgAdmin/servers.json.tpl @@ -0,0 +1,22 @@ +{ + "Servers": { + "1": { + "Name": "Local", + "Group": "Servers", + "Host": "postgres", + "Port": 5432, + "MaintenanceDB": "postgres", + "Username": "$POSTGRES_USER", + "UseSSHTunnel": 0, + "TunnelPort": "22", + "TunnelAuthentication": 0, + "KerberosAuthentication": false, + "ConnectionParameters": { + "sslmode": "prefer", + "connect_timeout": 10, + "sslcert": "/.postgresql/postgresql.crt", + "sslkey": "/.postgresql/postgresql.key" + } + } + } +} diff --git a/dev-assets/docker-environment/pgAdmin/storage/.git-keep b/dev-assets/docker-environment/pgAdmin/storage/.git-keep new file mode 100755 index 000000000..1f8f00cda --- /dev/null +++ b/dev-assets/docker-environment/pgAdmin/storage/.git-keep @@ -0,0 +1,22 @@ +# +# /******************************************************************************** +# Copyright (c) 2021,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 +# ********************************************************************************/ +# + +Is mounted as storage folder inside the pgAdmin container. diff --git a/dev-assets/docker-environment/postgres/init.sql b/dev-assets/docker-environment/postgres/init.sql deleted file mode 100644 index 64f272cf7..000000000 --- a/dev-assets/docker-environment/postgres/init.sql +++ /dev/null @@ -1,21 +0,0 @@ -/* - * ******************************************************************************* - * Copyright (c) 2021,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 - * ****************************************************************************** - */ - diff --git a/dev-assets/env-files/env.docker.dist b/dev-assets/env-files/env.docker.dist index aec3b1b29..d6c8204c8 100644 --- a/dev-assets/env-files/env.docker.dist +++ b/dev-assets/env-files/env.docker.dist @@ -1,7 +1,3 @@ -# Personal development data -GITHUB_USERNAME= -GITHUB_TOKEN= - # Build SKIP_GRADLE_TASKS_PARAM="-x jacocoTestCoverageVerification -x test" DEV_ENVIRONMENT=docker @@ -14,6 +10,9 @@ POSTGRES_DB_NAME_MIW=miw POSTGRES_USERNAME_MIW=miw_user POSTGRES_PASSWORD_MIW= +# Docker: pgAdmin config +PGADMIN_DEFAULT_EMAIL=pg@admin.com + # Docker: Keycloak config KEYCLOAK_MIW_PUBLIC_CLIENT=miw_public DB_DATABASE=keycloak @@ -31,7 +30,8 @@ KEYCLOAK_REALM=miw_test VC_SCHEMA_LINK="https://www.w3.org/2018/credentials/v1, https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json" VC_EXPIRY_DATE=01-01-2025 SUPPORTED_FRAMEWORK_VC_TYPES="PcfCredential, SustainabilityCredential, QualityCredential, TraceabilityCredential, BehaviorTwinCredential, ResiliencyCredential" -MIW_HOST_NAME=miw +MIW_HOST_NAME=localhost +ENFORCE_HTTPS_IN_DID_RESOLUTION=false ######### DON'T MODIFY ANYTHING BELOW THIS LINE !!! ######### AUTH_SERVER_URL=http://keycloak:8080 @@ -45,5 +45,4 @@ DB_USER=${POSTGRES_USER} DB_NAME=${POSTGRES_DB_NAME_MIW} DB_USER_NAME=${POSTGRES_USERNAME_MIW} DB_PASSWORD=${POSTGRES_PASSWORD_MIW} -ORG_GRADLE_PROJECT_githubUserName=${GITHUB_USERNAME} -ORG_GRADLE_PROJECT_githubToken=${GITHUB_TOKEN} +PGADMIN_DEFAULT_PASSWORD=${POSTGRES_PASSWORD} diff --git a/dev-assets/env-files/env.local.dist b/dev-assets/env-files/env.local.dist index 039992bbf..68ffa0547 100644 --- a/dev-assets/env-files/env.local.dist +++ b/dev-assets/env-files/env.local.dist @@ -1,7 +1,3 @@ -# Personal development data -GITHUB_USERNAME= -GITHUB_TOKEN= - # Build SKIP_GRADLE_TASKS_PARAM="-x jacocoTestCoverageVerification -x test" DEV_ENVIRONMENT=local @@ -14,6 +10,9 @@ POSTGRES_DB_NAME_MIW=miw POSTGRES_USERNAME_MIW=miw_user POSTGRES_PASSWORD_MIW= +# Docker: pgAdmin config +PGADMIN_DEFAULT_EMAIL=pg@admin.com + # Docker: Keycloak config KEYCLOAK_MIW_PUBLIC_CLIENT=miw_public DB_DATABASE=keycloak @@ -31,7 +30,8 @@ KEYCLOAK_REALM=miw_test VC_SCHEMA_LINK="https://www.w3.org/2018/credentials/v1, https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json" VC_EXPIRY_DATE=01-01-2025 SUPPORTED_FRAMEWORK_VC_TYPES="PcfCredential, SustainabilityCredential, QualityCredential, TraceabilityCredential, BehaviorTwinCredential, ResiliencyCredential" -MIW_HOST_NAME=miw +MIW_HOST_NAME=localhost +ENFORCE_HTTPS_IN_DID_RESOLUTION=false ######### DON'T MODIFY ANYTHING BELOW THIS LINE !!! ######### AUTH_SERVER_URL=http://localhost:8080 @@ -45,5 +45,4 @@ DB_USER=${POSTGRES_USER} DB_NAME=${POSTGRES_DB_NAME_MIW} DB_USER_NAME=${POSTGRES_USERNAME_MIW} DB_PASSWORD=${POSTGRES_PASSWORD_MIW} -ORG_GRADLE_PROJECT_githubUserName=${GITHUB_USERNAME} -ORG_GRADLE_PROJECT_githubToken=${GITHUB_TOKEN} +PGADMIN_DEFAULT_PASSWORD=${POSTGRES_PASSWORD} diff --git a/dev-assets/scripts/get_Token.sh b/dev-assets/scripts/get_Token.sh index de719990f..46c172d4f 100755 --- a/dev-assets/scripts/get_Token.sh +++ b/dev-assets/scripts/get_Token.sh @@ -20,11 +20,11 @@ # ********************************************************************************/ # -curl --location 'http://localhost:8080/realms/miw_test/protocol/openid-connect/token' \ - --header 'Content-Type: application/x-www-form-urlencoded' \ - --data-urlencode 'client_id=miw_private_client' \ - --data-urlencode 'client_secret=miw_private_client' \ - --data-urlencode 'grant_type=password' \ - --data-urlencode 'username=catena-x' \ - --data-urlencode 'password=password' \ - | jq -r '.access_token' \ No newline at end of file +curl --location "http://localhost:8080/realms/miw_test/protocol/openid-connect/token" \ + --header "Content-Type: application/x-www-form-urlencoded" \ + --data-urlencode "client_id=miw_private_client" \ + --data-urlencode "client_secret=miw_private_client" \ + --data-urlencode "grant_type=password" \ + --data-urlencode "username=catena-x" \ + --data-urlencode "password=password" \ + | jq -r ".access_token" diff --git a/dev-assets/tasks/darwin/app.yaml b/dev-assets/tasks/darwin/app.yaml index 38d7ff285..8928b350f 100644 --- a/dev-assets/tasks/darwin/app.yaml +++ b/dev-assets/tasks/darwin/app.yaml @@ -23,7 +23,7 @@ tasks: build: desc: Build the whole app cmds: - - ./gradlew build -PgithubToken=$GITHUB_TOKEN $SKIP_GRADLE_TASKS_PARAM + - ./gradlew build $SKIP_GRADLE_TASKS_PARAM get-token: desc: Obtain a BEARER token from Keycloak to access the MIW API @@ -38,15 +38,18 @@ tasks: test-report: desc: Generates the test report for MIW + ignore_error: true cmds: + - ./gradlew test - ./gradlew jacocoTestReport coverage: desc: Runs the coverage check cmds: + - task: test-report - ./gradlew jacocoTestCoverageVerification clean: desc: Cleans the build directory cmds: - - ./gradlew clean \ No newline at end of file + - ./gradlew clean diff --git a/dev-assets/tasks/darwin/docker.yaml b/dev-assets/tasks/darwin/docker.yaml index cd3fa1fd5..a7af6cbf2 100644 --- a/dev-assets/tasks/darwin/docker.yaml +++ b/dev-assets/tasks/darwin/docker.yaml @@ -32,9 +32,10 @@ tasks: ignore_error: true vars: OPTIONS: '{{ default "" .OPTIONS }}' - CONTAINERS: '{{ default "postgres keycloak" .CONTAINERS }}' + CONTAINERS: '{{ default "postgres keycloak pgadmin" .CONTAINERS }}' cmds: - cat postgres/db.sh.tpl | envsubst > postgres/db.sh + - cat pgAdmin/servers.json.tpl | envsubst > pgAdmin/servers.json - chmod +x postgres/db.sh - "docker compose up {{.OPTIONS}} {{.CONTAINERS}}" @@ -43,9 +44,10 @@ tasks: dir: dev-assets/docker-environment cmds: - docker compose down - - cmd: docker volume remove docker-environment_postgres_data + - cmd: docker volume remove docker-environment_postgres_data docker-environment_pgadmin_data ignore_error: true - rm -f postgres/db.sh + - rm -f pgAdmin/servers.json start-app: desc: Run the app in a container environment (including middleware aka Postgresql and Keycloak) diff --git a/dev-assets/tasks/linux/app.yaml b/dev-assets/tasks/linux/app.yaml index 91d94813a..690e0db66 100644 --- a/dev-assets/tasks/linux/app.yaml +++ b/dev-assets/tasks/linux/app.yaml @@ -23,7 +23,7 @@ tasks: build: desc: Build the whole app cmds: - - ./gradlew build -PgithubToken=$GITHUB_TOKEN $SKIP_GRADLE_TASKS_PARAM + - ./gradlew build $SKIP_GRADLE_TASKS_PARAM get-token: desc: Obtain a BEARER token from Keycloak to access the MIW API @@ -33,12 +33,15 @@ tasks: test-report: desc: Generates the test report for MIW + ignore_error: true cmds: + - ./gradlew test - ./gradlew jacocoTestReport coverage: desc: Runs the coverage check cmds: + - task: test-report - ./gradlew jacocoTestCoverageVerification clean: diff --git a/dev-assets/tasks/linux/docker.yaml b/dev-assets/tasks/linux/docker.yaml index cd3fa1fd5..a7af6cbf2 100644 --- a/dev-assets/tasks/linux/docker.yaml +++ b/dev-assets/tasks/linux/docker.yaml @@ -32,9 +32,10 @@ tasks: ignore_error: true vars: OPTIONS: '{{ default "" .OPTIONS }}' - CONTAINERS: '{{ default "postgres keycloak" .CONTAINERS }}' + CONTAINERS: '{{ default "postgres keycloak pgadmin" .CONTAINERS }}' cmds: - cat postgres/db.sh.tpl | envsubst > postgres/db.sh + - cat pgAdmin/servers.json.tpl | envsubst > pgAdmin/servers.json - chmod +x postgres/db.sh - "docker compose up {{.OPTIONS}} {{.CONTAINERS}}" @@ -43,9 +44,10 @@ tasks: dir: dev-assets/docker-environment cmds: - docker compose down - - cmd: docker volume remove docker-environment_postgres_data + - cmd: docker volume remove docker-environment_postgres_data docker-environment_pgadmin_data ignore_error: true - rm -f postgres/db.sh + - rm -f pgAdmin/servers.json start-app: desc: Run the app in a container environment (including middleware aka Postgresql and Keycloak) diff --git a/dev-assets/tasks/windows/app.yaml b/dev-assets/tasks/windows/app.yaml index 0b48893c8..fea255705 100644 --- a/dev-assets/tasks/windows/app.yaml +++ b/dev-assets/tasks/windows/app.yaml @@ -23,7 +23,7 @@ tasks: build: desc: Build the whole app cmds: - - ./gradlew build -PgithubToken=$GITHUB_TOKEN $SKIP_GRADLE_TASKS_PARAM + - ./gradlew build $SKIP_GRADLE_TASKS_PARAM get-token: desc: Obtain a BEARER token from Keycloak to access the MIW API @@ -44,4 +44,4 @@ tasks: clean: desc: Cleans the build directory cmds: - - .\gradlew.bat clean \ No newline at end of file + - .\gradlew.bat clean diff --git a/docs/security-assessment/dfd_23-12.png b/docs/security-assessment/dfd_23-12.png new file mode 100644 index 000000000..faaf29b2e Binary files /dev/null and b/docs/security-assessment/dfd_23-12.png differ diff --git a/docs/security-assessment/security-assessment-23-12.md b/docs/security-assessment/security-assessment-23-12.md new file mode 100644 index 000000000..14145f1b4 --- /dev/null +++ b/docs/security-assessment/security-assessment-23-12.md @@ -0,0 +1,67 @@ +# Security Assessment Managed Identity Wallet (MIW) + +| | | +| --- | --- | +| Contact for product | [@OSchlienz](https://github.com/github)
[@borisrizov-zf](https://github.com/borisrizov-zf) | +| Security responsible | [@pablosec](https://github.com/pablosec)
[@SSIRKC](https://github.com/SSIRKC) | +| Version number of product | 23.12 | +| Dates of assessment | 2023-11-21: Re-assessment for release 23.12 | +| Status of assessment | RE-ASSESSMENT DRAFT | + +## Product Description + +The Managed Identity Wallet (MIW) service implements the Self-Sovereign-Identity (SSI) readiness by providing a wallet hosting platform including a DID resolver, service endpoints and the company wallets itself. + +### Important Links +* [MIW: README.md](https://github.com/eclipse-tractusx/managed-identity-wallet/blob/main/README.md) +* [SSI: Technical Debts.md](https://github.com/eclipse-tractusx/ssi-docu/blob/main/docs/architecture/cx-3-2/6.%20Technical%20Debts/Technical%20Debts.md) – partly outdated at date of security assessment + + + +## Existing Security Controls + +ℹ️ Only controls added since last security assessment (2023-06) are listed below + +* Role-based access control + [README.md → Manual Keycloak Configuration](https://github.com/eclipse-tractusx/managed-identity-wallet/blob/main/README.md#manual-keycloak-configuration) + * MIW provides 7 roles: + * `add_wallets` + * `view_wallets` + * `view_wallet` + * `update_wallets` + * `update_wallet` + * `manage_app` +* Logging is implemented with levels `OFF`, `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE` + * Currently there is no description of the events logged for the different levels + + +## Architecture/Data Flow Diagram (DFD) + +![MIW in a single instance view](dfd_23-12.png) + +Source: https://github.com/pablosec/managed-identity-wallet/tree/main/docs + +### Changes compared to last Security Assessment +[Security Assessment 2023-06, Release 3.2](https://confluence.catena-x.net/pages/viewpage.action?pageId=90482695) (Link only available to Catena-X Consortium Members) +* No architectural changes in codebase compared to last security assessment, performed in June 2023. +* Product team currently working on STS (Secure Token Service) and Presentation Flow for VC/VP, planned for rollout in version *24.05*. + +### Features for upcoming versions + +See also [SSI: Technical Debts.md](https://github.com/eclipse-tractusx/ssi-docu/blob/main/docs/architecture/cx-3-2/6.%20Technical%20Debts/Technical%20Debts.md) + +* Revocation Service and substituting Summary Credentials (→ 24.05) +* Use of key rotation (→ 24.05) +* Switch to actually decentralized DID documents (→ will be implemented, but not scheduled at the moment) +* Create credentials outside of MIW (→ will be implemented, but not scheduled at the moment) + +⚠️ Multi-tenancy will not be implemented as part of the development during the Catena-X consortium phase. Security risk associated with lack of multi-tenancy is accepted. + +## Threats & Risks +The threats and risks identified during this security assessment can be found in the following issues: +* eclipse-tractusx/managed-identity-wallet#164 +* eclipse-tractusx/managed-identity-wallet#165 +* eclipse-tractusx/managed-identity-wallet#86 (finding was already created as issue before assessment) +* eclipse-tractusx/managed-identity-wallet#166 + +Security-relevant threats are reported as security advisories and thus only visible to contributers. \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 0bb2f6277..65723c879 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,10 +1,8 @@ springCloudVersion=2022.0.3 -testContainerVersion=1.18.3 +testContainerVersion=1.19.3 jacocoVersion=0.8.9 -springBootVersion=3.1.2 +springBootVersion=3.1.6 springDependencyVersion=1.1.0 groupName=org.eclipse.tractusx -applicationVersion=0.2.0 +applicationVersion=0.3.0-develop.1 openApiVersion=2.1.0 -githubUserName= -githubToken= \ No newline at end of file diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/apidocs/DidDocumentControllerApiDocs.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/apidocs/DidDocumentControllerApiDocs.java new file mode 100644 index 000000000..1a53d27de --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/apidocs/DidDocumentControllerApiDocs.java @@ -0,0 +1,157 @@ +package org.eclipse.tractusx.managedidentitywallets.apidocs; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.Parameter; + +public class DidDocumentControllerApiDocs { + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + @ApiResponses(value = { + @ApiResponse(responseCode = "500", description = "Any other internal server error", content = { + @Content(examples = { + @ExampleObject(name = "Internal server error", value = """ + { + "type": "about:blank", + "title": "Error Title", + "status": 500, + "detail": "Error Details", + "instance": "API endpoint", + "properties": { + "timestamp": 1689762476720 + } + } + """) + }) }), + @ApiResponse(responseCode = "404", description = "Wallet not found with provided bpn", content = { + @Content(examples = { + @ExampleObject(name = "Wallet not found with provided bpn", value = """ + { + "type": "about:blank", + "title": "Wallet not found for identifier BPNL00000000000", + "status": 404, + "detail": "Wallet not found for identifier BPNL00000000000", + "instance": "/BPNL00000000000/did.json", + "properties": { + "timestamp": 1689767698010 + } + } + """) + }) }), + @ApiResponse(responseCode = "200", description = "DID document", content = { + @Content(examples = { + @ExampleObject(name = " DID document", value = """ + { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3c.github.io/vc-jws-2020/contexts/v1" + ], + "id": "did:web:localhost:BPNL000000000000", + "verificationMethod": [ + { + "controller": "did:web:localhost:BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "publicKeyJwk": { + "crv": "Ed25519", + "kty": "OKP", + "x": "wAOQvr92L1m7RwrpeOrgWByVYvWmhRr4fJbiMwHEIdY" + }, + "type": "JsonWebKey2020" + } + ] + } + """) + }) + }) }) + @Operation(description = "Resolve the DID document for a given DID or BPN", summary = "Resolve DID Document") + public @interface GetDidDocumentApiDocs { + } + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + @ApiResponses(value = { + @ApiResponse(responseCode = "500", description = "Any other internal server error", content = { + @Content(examples = { + @ExampleObject(name = "Internal server error", value = """ + { + "type": "about:blank", + "title": "Error Title", + "status": 500, + "detail": "Error Details", + "instance": "API endpoint", + "properties": { + "timestamp": 1689762476720 + } + } + """) + }) }), + @ApiResponse(responseCode = "404", description = "Wallet not found with provided bpn", content = { + @Content(examples = { + @ExampleObject(name = "Wallet not found with provided bpn", value = """ + { + "type": "about:blank", + "title": "Wallet not found for identifier BPNL00000000000", + "status": 404, + "detail": "Wallet not found for identifier BPNL00000000000", + "instance": "/BPNL00000000000/did.json", + "properties": { + "timestamp": 1689767698010 + } + } + """) + }) }), + @ApiResponse(responseCode = "200", description = "DID document", content = { + @Content(examples = { + @ExampleObject(name = " DID document", value = """ + { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3c.github.io/vc-jws-2020/contexts/v1" + ], + "id": "did:web:localhost:BPNL000000000000", + "verificationMethod": [ + { + "controller": "did:web:localhost:BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "publicKeyJwk": { + "crv": "Ed25519", + "kty": "OKP", + "x": "wAOQvr92L1m7RwrpeOrgWByVYvWmhRr4fJbiMwHEIdY" + }, + "type": "JsonWebKey2020" + } + ] + } + """) + }) + }) + }) + @Operation(description = "Resolve the DID document for a given BPN", summary = "Resolve DID Document") + public @interface GetDidResolveApiDocs { + } + + @Parameter(description = "Did or BPN", examples = { + @ExampleObject(name = "bpn", value = "BPNL000000000000", description = "bpn"), + @ExampleObject(description = "did", name = "did", value = "did:web:localhost:BPNL000000000000") }) + @Target(ElementType.PARAMETER) + @Retention(RetentionPolicy.RUNTIME) + public @interface DidOrBpnParameterDoc { + } + + @Parameter(description = "BPN", examples = { + @ExampleObject(name = "bpn", value = "BPNL000000000000", description = "bpn") }) + @Target(ElementType.PARAMETER) + @Retention(RetentionPolicy.RUNTIME) + public @interface BpnParameterDoc { + } + +} diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/apidocs/HoldersCredentialControllerApiDocs.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/apidocs/HoldersCredentialControllerApiDocs.java new file mode 100644 index 000000000..ef5c2ead5 --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/apidocs/HoldersCredentialControllerApiDocs.java @@ -0,0 +1,285 @@ +package org.eclipse.tractusx.managedidentitywallets.apidocs; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.parameters.RequestBody; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +public class HoldersCredentialControllerApiDocs { + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + @ApiResponses(value = { + @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "500", description = "Any other internal server error", content = { + @Content(examples = { + @ExampleObject(name = "Internal server error", value = """ + { + "type": "about:blank", + "title": "Error Title", + "status": 500, + "detail": "Error Details", + "instance": "API endpoint", + "properties": { + "timestamp": 1689762476720 + } + } + """) + }) }), + @ApiResponse(responseCode = "404", description = "Wallet not found with caller BPN", content = { + @Content(examples = { + @ExampleObject(name = "Wallet not found with caller BPN", value = """ + { + "type": "about:blank", + "title": "Wallet not found for identifier did:web:localhost:BPNL0000000", + "status": 404, + "detail": "Wallet not found for identifier did:web:localhost:BPNL0000000", + "instance": "/api/wallets/did%3Aweb%3Alocalhost%3ABPNL0000000/credentials", + "properties": { + "timestamp": 1689765541959 + } + } + """) + }) }), + @ApiResponse(responseCode = "400", description = "The input does not comply to the syntax requirements", content = { + @Content(examples = { + @ExampleObject(name = "Response in case of invalid data provided", value = """ + { + "type": "about:blank", + "title": "title", + "status": 400, + "detail": "details", + "instance": "API endpoint", + "properties": + { + "timestamp": 1689760833962, + "errors": + { + } + } + } + """) + }) + }), + @ApiResponse(responseCode = "200", description = "Credential list", content = { + @Content(examples = { + @ExampleObject(name = "Credential list", value = """ + { + "content": + [ + { + "@context": + [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/SummaryVC.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:web:localhost:BPNL000000000000#954d43de-ebed-481d-9e35-e3bbb311b8f5", + "type": + [ + "VerifiableCredential", + "SummaryCredential" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "issuanceDate": "2023-07-14T11:05:48Z", + "expirationDate": "2023-09-30T18:30:00Z", + "credentialSubject": + [ + { + "contractTemplate": "https://public.catena-x.org/contracts/", + "holderIdentifier": "BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "items": + [ + "BpnCredential" + ], + "type": "SummaryCredential" + } + ], + "proof": + { + "created": "2023-07-14T11:05:50Z", + "jws": "eyJhbGciOiJFZERTQSJ9..4xwFUCtP0xXVEo5_lXd90Vv-TWO2FijZut-HZ5cozAQseexj8EpTkK1erhFbf2Ua1kb8pi_H5At5HiPkTxSIAQ", + "proofPurpose": "proofPurpose", + "type": "JsonWebSignature2020", + "verificationMethod": "did:web:localhost:BPNL000000000000#" + } + } + ], + "pageable": + { + "sort": + { + "empty": false, + "sorted": true, + "unsorted": false + }, + "offset": 0, + "pageNumber": 0, + "pageSize": 2147483647, + "paged": true, + "unpaged": false + }, + "totalElements": 1, + "totalPages": 1, + "last": true, + "size": 2147483647, + "number": 0, + "sort": + { + "empty": false, + "sorted": true, + "unsorted": false + }, + "first": true, + "numberOfElements": 1, + "empty": false + } + """) + }) + }) }) + @Operation(description = "Permission: **view_wallets** OR **view_wallet** (The BPN of holderIdentifier must equal BPN of caller)\n\n Search verifiable credentials with filter criteria", summary = "Query Verifiable Credentials") + public @interface GetCredentialsApiDocs { + } + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + @ApiResponses(value = { + @ApiResponse(responseCode = "201", description = "Success Response", content = { @Content(examples = { + @ExampleObject(name = "Success Response", value = """ + { + "@context": + [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:web:localhost:BPNL000000000000#319a2641-9407-4c39-bf51-a4a109b59604", + "type": + [ + "VerifiableCredential", + "BankDetails" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "issuanceDate": "2023-07-19T13:41:52Z", + "expirationDate": "2024-12-31T18:30:00Z", + "credentialSubject": + [ + { + "bpn": "BPNL000000000000", + "bankName": "Dummy Bank", + "id": "did:web:localhost:BPNL000000000000", + "type": "BankDetails", + "accountNumber": "123456789" + } + ], + "proof": + { + "proofPurpose": "proofPurpose", + "verificationMethod": "did:web:localhost:BPNL000000000000#", + "type": "JsonWebSignature2020", + "created": "2023-07-19T13:41:54Z", + "jws": "eyJhbGciOiJFZERTQSJ9..fdqaAsPhQ5xZhQiRvWliDVXX-R9NzCvFXGUAOyQ8yE1hmf_4cvxS7JFuEojjsi3V-n66iiRCUFEXsnv56XPgDA" + } + } + """) + }) }), + @ApiResponse(responseCode = "404", description = "Wallet not found with caller BPN", content = { + @Content(examples = { + @ExampleObject(name = "Wallet not found with caller BPN", value = """ + { + "type": "about:blank", + "title": "Wallet not found for identifier did:web:localhost:BPNL0000000501", + "status": 404, + "detail": "Wallet not found for identifier did:web:localhost:BPNL0000000501", + "instance": "/api/wallets/did%3Aweb%3Alocalhost%3ABPNL0000000501", + "properties": { + "timestamp": 1689764377224 + } + } + """) + }) }), + @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "500", description = "Any other internal server error", content = { + @Content(examples = { + @ExampleObject(name = "Internal server error", value = """ + { + "type": "about:blank", + "title": "Error Title", + "status": 500, + "detail": "Error Details", + "instance": "API endpoint", + "properties": { + "timestamp": 1689762476720 + } + } + """) + }) }), + @ApiResponse(responseCode = "400", description = "The input does not comply to the syntax requirements", content = { + @Content(examples = { + @ExampleObject(name = "Response in case of invalid data provided", value = """ + { + "type": "about:blank", + "title": "Invalid data provided", + "status": 400, + "detail": "details", + "instance": "API endpoint", + "properties": + { + "timestamp": 1689760833962, + "errors": + { + "filed": "filed error message" + } + } + } + """) + }) + }) + }) + @RequestBody(content = { + @Content(examples = @ExampleObject(""" + { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:web:localhost:BPNL000000000000#f73e3631-ba87-4a03-bea3-b28700056879", + "type": [ + "VerifiableCredential", + "BankDetails" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "expirationDate": "2024-12-31T18:30:00Z", + "issuanceDate": "2023-07-19T09:11:34Z", + "credentialSubject": [ + { + "bpn": "BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "type": "BankDetails", + "accountNumber": "123456789", + "bankName":"Dummy Bank" + } + ] + } + """)) + }) + @Operation(summary = "Issue Verifiable Credential", description = "Permission: **update_wallets** OR **update_wallet** (The BPN of the issuer of the Verifiable Credential must equal BPN of caller)\nIssue a verifiable credential with a given issuer DID") + public @interface IssueCredentialApiDoc { + } + +} diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/apidocs/IssuersCredentialControllerApiDocs.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/apidocs/IssuersCredentialControllerApiDocs.java new file mode 100644 index 000000000..a137f6d85 --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/apidocs/IssuersCredentialControllerApiDocs.java @@ -0,0 +1,1106 @@ +package org.eclipse.tractusx.managedidentitywallets.apidocs; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.parameters.RequestBody; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; + +public class IssuersCredentialControllerApiDocs { + /** + * The constant API_TAG_VERIFIABLE_CREDENTIAL_ISSUER. + */ + public static final String API_TAG_VERIFIABLE_CREDENTIAL_ISSUER = "Verifiable Credential - Issuer"; + /** + * The constant API_TAG_VERIFIABLE_CREDENTIAL_VALIDATION. + */ + public static final String API_TAG_VERIFIABLE_CREDENTIAL_VALIDATION = "Verifiable Credential - Validation"; + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + @Tag(name = API_TAG_VERIFIABLE_CREDENTIAL_ISSUER) + @ApiResponses(value = { + @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "500", description = "Any other internal server error", content = { + @Content(examples = { + @ExampleObject(name = "Internal server error", value = """ + { + "type": "about:blank", + "title": "Error Title", + "status": 500, + "detail": "Error Details", + "instance": "API endpoint", + "properties": { + "timestamp": 1689762476720 + } + } + """) + }) }), + @ApiResponse(responseCode = "400", description = "The input does not comply to the syntax requirements", content = { + @Content(examples = { + @ExampleObject(name = "Response in case of invalid data provided", value = """ + { + "type": "about:blank", + "title": "title", + "status": 400, + "detail": "details", + "instance": "API endpoint", + "properties": + { + "timestamp": 1689760833962, + "errors": + { + } + } + } + """) + }) + }), + @ApiResponse(responseCode = "200", description = "Issuer credential list", content = { + @Content(examples = { + @ExampleObject(name = "Issuer credential list", value = """ + { + "content": [ + { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:web:localhost:BPNL000000000000#ae364f71-f054-4d91-b579-f001bcb3e59e", + "type": [ + "VerifiableCredential", + "BpnCredential" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "issuanceDate": "2023-07-19T09:27:42Z", + "expirationDate": "2024-12-31T18:30:00Z", + "credentialSubject": [ + { + "bpn": "BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "type": "BpnCredential" + } + ], + "proof": { + "created": "2023-07-19T09:27:44Z", + "jws": "eyJhbGciOiJFZERTQSJ9..evDHQfW4EzJUt2HnS_WlmO8FFtywTGnwyywtCE7WP41my4Iscpqr4tbuVOqnZg85b4U8L3_ut8_pEONIhbExCQ", + "proofPurpose": "proofPurpose", + "type": "JsonWebSignature2020", + "verificationMethod": "did:web:localhost:BPNL000000000000#" + } + }, + { + "type": [ + "VerifiableCredential", + "SummaryCredential" + ], + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/SummaryVC.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "issuanceDate": "2023-07-19T09:11:39Z", + "expirationDate": "2024-12-31T18:30:00Z", + "credentialSubject": [ + { + "contractTemplate": "https://public.catena-x.org/contracts/", + "holderIdentifier": "BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "items": [ + "BpnCredential" + ], + "type": "SummaryCredential" + } + ], + "proof": { + "created": "2023-07-19T09:11:41Z", + "jws": "eyJhbGciOiJFZERTQSJ9..YvoFhDip3TQAfZUIu0yc843oA4uGTg049dMFt_GoaMmPjiNB_B1EFOL-gDpwjIxTYNlGOO_CLp9qStbzlDTNBg", + "proofPurpose": "proofPurpose", + "type": "JsonWebSignature2020", + "verificationMethod": "did:web:localhost:BPNL000000000000#" + } + }, + { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:web:localhost:BPNL000000000000#f73e3631-ba87-4a03-bea3-b28700056879", + "type": [ + "VerifiableCredential", + "BpnCredential" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "issuanceDate": "2023-07-19T09:11:34Z", + "expirationDate": "2024-12-31T18:30:00Z", + "credentialSubject": [ + { + "bpn": "BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "type": "BpnCredential" + } + ], + "proof": { + "created": "2023-07-19T09:11:39Z", + "jws": "eyJhbGciOiJFZERTQSJ9..fdn2qU85auOltdHDLdHI7sJVV1ZPdftpiXd_ndXN0dFgSDWiIrScdD03wtvKLq_H-shQWfh2RYeMmrlEzAhfDw", + "proofPurpose": "proofPurpose", + "type": "JsonWebSignature2020", + "verificationMethod": "did:web:localhost:BPNL000000000000#" + } + } + ], + "pageable": { + "sort": { + "empty": false, + "unsorted": false, + "sorted": true + }, + "offset": 0, + "pageNumber": 0, + "pageSize": 2147483647, + "paged": true, + "unpaged": false + }, + "last": true, + "totalPages": 1, + "totalElements": 3, + "first": true, + "size": 2147483647, + "number": 0, + "sort": { + "empty": false, + "unsorted": false, + "sorted": true + }, + "numberOfElements": 3, + "empty": false + } + """) + }) + }), + }) + @Operation(description = "Permission: **view_wallets** (The BPN of holderIdentifier must equal BPN of caller)\n\n Search verifiable credentials with filter criteria", summary = "Query Verifiable Credentials") + public @interface GetCredentialsApiDocs { + } + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + @RequestBody(content = { + @Content(examples = @ExampleObject(""" + { + "bpn": "BPNL000000000000" + } + """)) + }) + @Tag(name = API_TAG_VERIFIABLE_CREDENTIAL_ISSUER) + @ApiResponses(value = { + @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "500", description = "Any other internal server error", content = { + @Content(examples = { + @ExampleObject(name = "Internal server error", value = """ + { + "type": "about:blank", + "title": "Error Title", + "status": 500, + "detail": "Error Details", + "instance": "API endpoint", + "properties": { + "timestamp": 1689762476720 + } + } + """) + }) }), + @ApiResponse(responseCode = "409", description = "The request could not be completed due to a conflict.", content = { + @Content(examples = { + @ExampleObject(name = "MembershipCredential already exist", value = """ + { + "type": "about:blank", + "title": "Credential of type MembershipCredential is already exists ", + "status": 409, + "detail": "Credential of type MembershipCredential is already exists ", + "instance": "/api/credentials/issuer/membership", + "properties": { + "timestamp": 1689772483831 + } + } + """) + }) }), + @ApiResponse(responseCode = "404", description = "Wallet not found with provided identifier", content = { + @Content(examples = { + @ExampleObject(name = "Wallet not found with provided identifier", value = """ + { + "type": "about:blank", + "title": "Error Title", + "status": 404, + "detail": "Error Details", + "instance": "API endpoint", + "properties": { + "timestamp": 1689762476720 + } + } + """) + }) }), + @ApiResponse(responseCode = "400", description = "The input does not comply to the syntax requirements", content = { + @Content(examples = { + @ExampleObject(name = "Response in case of invalid data provided", value = """ + { + "type": "about:blank", + "title": "Invalid data provided", + "status": 400, + "detail": "details", + "instance": "API endpoint", + "properties": + { + "timestamp": 1689760833962, + "errors": + { + "filed": "filed error message" + } + } + } + """) + }) + }), + @ApiResponse(responseCode = "201", description = "Issuer credential", content = { + @Content(examples = { + @ExampleObject(name = "Membership credential", value = """ + { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:web:localhost:BPNL000000000000#0d6b6447-99de-4bc5-94f3-3ac0ae8ee188", + "type": [ + "VerifiableCredential", + "MembershipCredential" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "issuanceDate": "2023-07-19T13:13:53Z", + "expirationDate": "2024-12-31T18:30:00Z", + "credentialSubject": [ + { + "holderIdentifier": "BPNL000000000000", + "startTime": "2023-07-19T13:13:53.581081Z", + "memberOf": "Catena-X", + "id": "did:web:localhost:BPNL000000000000", + "type": "MembershipCredential", + "status": "Active" + } + ], + "proof": { + "proofPurpose": "proofPurpose", + "verificationMethod": "did:web:localhost:BPNL000000000000#", + "type": "JsonWebSignature2020", + "created": "2023-07-19T13:13:57Z", + "jws": "eyJhbGciOiJFZERTQSJ9..zt7SyONY1shO7N6KrabQJr9uNrToM1Bc4eagTQc1LxAfZ1v-SSp9Y-2cpZNDV8AR08r4L8VbtWrR9t2dNoAfDw" + } + } + """) + }) + }) }) + @Operation(summary = "Issue a Membership Verifiable Credential with base wallet issuer", description = "Permission: **update_wallets** (The BPN of base wallet must equal BPN of caller)\n\n Issue a verifiable credential by base wallet") + public @interface IssueMembershipCredentialApiDoc { + } + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + @RequestBody(content = { + @Content(examples = @ExampleObject(""" + { + "bpn": "BPNL000000000000", + "activityType": "vehicleDismantle", + "allowedVehicleBrands": [ + "Audi", "Abarth", "Alfa Romeo", "Chrysler" + ] + } + """)) + }) + @Tag(name = API_TAG_VERIFIABLE_CREDENTIAL_ISSUER) + @ApiResponses(value = { + @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "500", description = "Any other internal server error", content = { + @Content(examples = { + @ExampleObject(name = "Internal server error", value = """ + { + "type": "about:blank", + "title": "Error Title", + "status": 500, + "detail": "Error Details", + "instance": "API endpoint", + "properties": { + "timestamp": 1689762476720 + } + } + """) + }) }), + @ApiResponse(responseCode = "409", description = "The request could not be completed due to a conflict.", content = { + @Content(examples = { + @ExampleObject(name = "DismantlerCredential already exist", value = """ + { + "type": "about:blank", + "title": "Credential of type DismantlerCredential is already exists ", + "status": 409, + "detail": "Credential of type DismantlerCredential is already exists ", + "instance": "/api/credentials/issuer/dismantler", + "properties": { + "timestamp": 1689773804746 + } + } + """) + }) }), + @ApiResponse(responseCode = "404", description = "Wallet not found with provided identifier", content = { + @Content(examples = { + @ExampleObject(name = "Wallet not found with provided identifier", value = """ + { + "type": "about:blank", + "title": "Error Title", + "status": 404, + "detail": "Error Details", + "instance": "API endpoint", + "properties": { + "timestamp": 1689762476720 + } + } + """) + }) }), + @ApiResponse(responseCode = "400", description = "The input does not comply to the syntax requirements", content = { + @Content(examples = { + @ExampleObject(name = "Response in case of invalid data provided", value = """ + { + "type": "about:blank", + "title": "Invalid data provided", + "status": 400, + "detail": "details", + "instance": "API endpoint", + "properties": + { + "timestamp": 1689760833962, + "errors": + { + "filed": "filed error message" + } + } + } + """) + }) + }), + @ApiResponse(responseCode = "201", description = "Dismantler Credential", content = { + @Content(examples = { + @ExampleObject(name = "Dismantler Credential", value = """ + { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:web:localhost:BPNL000000000000#5caac86c-8ef8-4aab-9d2b-fb18c62560a9", + "type": [ + "VerifiableCredential", + "DismantlerCredential" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "issuanceDate": "2023-07-19T13:35:33Z", + "expirationDate": "2024-12-31T18:30:00Z", + "credentialSubject": [ + { + "holderIdentifier": "BPNL000000000000", + "allowedVehicleBrands": [ + "Audi", + "Abarth", + "Alfa Romeo", + "Chrysler" + ], + "id": "did:web:localhost:BPNL000000000000", + "activityType": "vehicleDismantle", + "type": "DismantlerCredential" + } + ], + "proof": { + "proofPurpose": "proofPurpose", + "verificationMethod": "did:web:localhost:BPNL000000000000#", + "type": "JsonWebSignature2020", + "created": "2023-07-19T13:35:38Z", + "jws": "eyJhbGciOiJFZERTQSJ9..UI82uq6iyqoaKjZIhJiV24v_Bqnj_7EqWiqZ3VWjqkoHLnr7JDtW5KVywWPl27j_baLBxxnM5jqjQdSK4rfbBg" + } + } + """) + }) + }) + }) + @Operation(summary = "Issue a Dismantler Verifiable Credential with base wallet issuer", description = "Permission: **update_wallets** (The BPN of base wallet must equal BPN of caller)\n\n Issue a verifiable credential by base wallet") + public @interface IssueDismantlerCredentialApiDoc { + } + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + @RequestBody(content = { + @Content(examples = { + @ExampleObject(name = "BehaviorTwinCredential", value = """ + { + "holderIdentifier": "BPNL000000000000", + "type": "BehaviorTwinCredential", + "contract-template": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", + "contract-version": "1.0.0" + } + """), + @ExampleObject(name = "PcfCredential", value = """ + { + "holderIdentifier": "BPNL000000000000", + "type": "PcfCredential", + "contract-template": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", + "contract-version": "1.0.0" + } + """), + @ExampleObject(name = "SustainabilityCredential", value = """ + { + "holderIdentifier": "BPNL000000000000", + "type": "SustainabilityCredential", + "contract-template": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", + "contract-version": "1.0.0" + } + """), + @ExampleObject(name = "QualityCredential", value = """ + { + "holderIdentifier": "BPNL000000000000", + "type": "QualityCredential", + "contract-template": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", + "contract-version": "1.0.0" + } + """), + @ExampleObject(name = "TraceabilityCredential", value = """ + { + "holderIdentifier": "BPNL000000000000", + "type": "TraceabilityCredential", + "contract-template": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", + "contract-version": "1.0.0" + } + """), + @ExampleObject(name = "BehaviorTwinCredential", value = """ + { + "holderIdentifier": "BPNL000000000000", + "type": "BehaviorTwinCredential", + "contract-template": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", + "contract-version": "1.0.0" + } + """), + @ExampleObject(name = "ResiliencyCredential", value = """ + { + "holderIdentifier": "BPNL000000000000", + "type": "ResiliencyCredential", + "contract-template": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", + "contract-version": "1.0.0" + } + """) + + }) + }) + @Tag(name = API_TAG_VERIFIABLE_CREDENTIAL_ISSUER) + @Operation(summary = "Issue a Use Case Verifiable Credential with base wallet issuer", description = "Permission: **update_wallets** (The BPN of base wallet must equal BPN of caller)\n\n Issue a verifiable credential by base wallet") + @ApiResponses(value = { + @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "500", description = "Any other internal server error", content = { + @Content(examples = { + @ExampleObject(name = "Internal server error", value = """ + { + "type": "about:blank", + "title": "Error Title", + "status": 500, + "detail": "Error Details", + "instance": "API endpoint", + "properties": { + "timestamp": 1689762476720 + } + } + """) + }) }), + @ApiResponse(responseCode = "404", description = "Wallet not found with provided identifier", content = { + @Content(examples = { + @ExampleObject(name = "Wallet not found with provided identifier", value = """ + { + "type": "about:blank", + "title": "Error Title", + "status": 404, + "detail": "Error Details", + "instance": "API endpoint", + "properties": { + "timestamp": 1689762476720 + } + } + """) + }) }), + @ApiResponse(responseCode = "400", description = "The input does not comply to the syntax requirements", content = { + @Content(examples = { + @ExampleObject(name = "Response in case of invalid data provided", value = """ + { + "type": "about:blank", + "title": "Invalid data provided", + "status": 400, + "detail": "details", + "instance": "API endpoint", + "properties": + { + "timestamp": 1689760833962, + "errors": + { + "filed": "filed error message" + } + } + } + """) + }) + }), + @ApiResponse(responseCode = "201", description = "Framework credential", content = { + @Content(examples = { + @ExampleObject(name = "BehaviorTwin credential", value = """ + { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:web:localhost:BPNL000000000000#46a8c5e6-b195-4ec9-85cd-665c57d296ab", + "type": [ + "VerifiableCredential", + "UseCaseFrameworkCondition" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "issuanceDate": "2023-07-19T13:49:58Z", + "expirationDate": "2024-12-31T18:30:00Z", + "credentialSubject": [ + { + "holderIdentifier": "BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "type": "BehaviorTwinCredential", + "contractTemplate": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", + "contractVersion": "1.0.0" + } + ], + "proof": { + "proofPurpose": "proofPurpose", + "type": "JsonWebSignature2020", + "verificationMethod": "did:web:localhost:BPNL000000000000#", + "created": "2023-07-19T13:50:02Z", + "jws": "eyJhbGciOiJFZERTQSJ9..IkfgC6Gn9sOT1uu1zMiDIIqw6pV4Z8axkKvphegsCVWT9uo0HZp4J9L1ILxR-huINGR5QlGIKiVuLGB5kKDOAQ" + } + } + """), + @ExampleObject(name = "Pcf Credential", value = """ + { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:web:localhost:BPNL000000000000#46a8c5e6-b195-4ec9-85cd-665c57d296ab", + "type": [ + "VerifiableCredential", + "UseCaseFrameworkCondition" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "issuanceDate": "2023-07-19T13:49:58Z", + "expirationDate": "2024-12-31T18:30:00Z", + "credentialSubject": [ + { + "holderIdentifier": "BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "type": "PcfCredential", + "contractTemplate": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", + "contractVersion": "1.0.0" + } + ], + "proof": { + "proofPurpose": "proofPurpose", + "type": "JsonWebSignature2020", + "verificationMethod": "did:web:localhost:BPNL000000000000#", + "created": "2023-07-19T13:50:02Z", + "jws": "eyJhbGciOiJFZERTQSJ9..IkfgC6Gn9sOT1uu1zMiDIIqw6pV4Z8axkKvphegsCVWT9uo0HZp4J9L1ILxR-huINGR5QlGIKiVuLGB5kKDOAQ" + } + } + """), + @ExampleObject(name = "Sustainability Credential", value = """ + { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:web:localhost:BPNL000000000000#46a8c5e6-b195-4ec9-85cd-665c57d296ab", + "type": [ + "VerifiableCredential", + "UseCaseFrameworkCondition" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "issuanceDate": "2023-07-19T13:49:58Z", + "expirationDate": "2024-12-31T18:30:00Z", + "credentialSubject": [ + { + "holderIdentifier": "BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "type": "SustainabilityCredential", + "contractTemplate": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", + "contractVersion": "1.0.0" + } + ], + "proof": { + "proofPurpose": "proofPurpose", + "type": "JsonWebSignature2020", + "verificationMethod": "did:web:localhost:BPNL000000000000#", + "created": "2023-07-19T13:50:02Z", + "jws": "eyJhbGciOiJFZERTQSJ9..IkfgC6Gn9sOT1uu1zMiDIIqw6pV4Z8axkKvphegsCVWT9uo0HZp4J9L1ILxR-huINGR5QlGIKiVuLGB5kKDOAQ" + } + } + """), + @ExampleObject(name = "Quality Credential", value = """ + { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:web:localhost:BPNL000000000000#46a8c5e6-b195-4ec9-85cd-665c57d296ab", + "type": [ + "VerifiableCredential", + "UseCaseFrameworkCondition" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "issuanceDate": "2023-07-19T13:49:58Z", + "expirationDate": "2024-12-31T18:30:00Z", + "credentialSubject": [ + { + "holderIdentifier": "BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "type": "QualityCredential", + "contractTemplate": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", + "contractVersion": "1.0.0" + } + ], + "proof": { + "proofPurpose": "proofPurpose", + "type": "JsonWebSignature2020", + "verificationMethod": "did:web:localhost:BPNL000000000000#", + "created": "2023-07-19T13:50:02Z", + "jws": "eyJhbGciOiJFZERTQSJ9..IkfgC6Gn9sOT1uu1zMiDIIqw6pV4Z8axkKvphegsCVWT9uo0HZp4J9L1ILxR-huINGR5QlGIKiVuLGB5kKDOAQ" + } + } + """), + @ExampleObject(name = "Traceability Credential", value = """ + { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:web:localhost:BPNL000000000000#46a8c5e6-b195-4ec9-85cd-665c57d296ab", + "type": [ + "VerifiableCredential", + "UseCaseFrameworkCondition" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "issuanceDate": "2023-07-19T13:49:58Z", + "expirationDate": "2024-12-31T18:30:00Z", + "credentialSubject": [ + { + "holderIdentifier": "BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "type": "TraceabilityCredential", + "contractTemplate": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", + "contractVersion": "1.0.0" + } + ], + "proof": { + "proofPurpose": "proofPurpose", + "type": "JsonWebSignature2020", + "verificationMethod": "did:web:localhost:BPNL000000000000#", + "created": "2023-07-19T13:50:02Z", + "jws": "eyJhbGciOiJFZERTQSJ9..IkfgC6Gn9sOT1uu1zMiDIIqw6pV4Z8axkKvphegsCVWT9uo0HZp4J9L1ILxR-huINGR5QlGIKiVuLGB5kKDOAQ" + } + } + """), + @ExampleObject(name = "Resiliency Credential", value = """ + { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:web:localhost:BPNL000000000000#46a8c5e6-b195-4ec9-85cd-665c57d296ab", + "type": [ + "VerifiableCredential", + "UseCaseFrameworkCondition" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "issuanceDate": "2023-07-19T13:49:58Z", + "expirationDate": "2024-12-31T18:30:00Z", + "credentialSubject": [ + { + "holderIdentifier": "BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "type": "ResiliencyCredential", + "contractTemplate": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", + "contractVersion": "1.0.0" + } + ], + "proof": { + "proofPurpose": "proofPurpose", + "type": "JsonWebSignature2020", + "verificationMethod": "did:web:localhost:BPNL000000000000#", + "created": "2023-07-19T13:50:02Z", + "jws": "eyJhbGciOiJFZERTQSJ9..IkfgC6Gn9sOT1uu1zMiDIIqw6pV4Z8axkKvphegsCVWT9uo0HZp4J9L1ILxR-huINGR5QlGIKiVuLGB5kKDOAQ" + } + } + """) + }) + }) + }) + public @interface IssueFrameworkCredentialApiDocs { + } + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + @Tag(name = API_TAG_VERIFIABLE_CREDENTIAL_VALIDATION) + @ApiResponses(value = { + @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "500", description = "Any other internal server error", content = { + @Content(examples = { + @ExampleObject(name = "Internal server error", value = """ + { + "type": "about:blank", + "title": "Error Title", + "status": 500, + "detail": "Error Details", + "instance": "API endpoint", + "properties": { + "timestamp": 1689762476720 + } + } + """) + }) }), + @ApiResponse(responseCode = "200", description = "Validate Verifiable Credentials", content = { + @Content(examples = { + @ExampleObject(name = "Verifiable Credentials without check expiry", value = """ + { + "valid": true, + "vc": { + "issuanceDate": "2023-07-19T09:11:34Z", + "credentialSubject": [ + { + "bpn": "BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "type": "BpnCredential" + } + ], + "id": "did:web:localhost:BPNL000000000000#f73e3631-ba87-4a03-bea3-b28700056879", + "proof": { + "created": "2023-07-19T09:11:39Z", + "jws": "eyJhbGciOiJFZERTQSJ9..fdn2qU85auOltdHDLdHI7sJVV1ZPdftpiXd_ndXN0dFgSDWiIrScdD03wtvKLq_H-shQWfh2RYeMmrlEzAhfDw", + "proofPurpose": "proofPurpose", + "type": "JsonWebSignature2020", + "verificationMethod": "did:web:localhost:BPNL000000000000#" + }, + "type": [ + "VerifiableCredential", + "BpnCredential" + ], + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "expirationDate": "2024-12-31T18:30:00Z" + } + } + """), + @ExampleObject(name = "Verifiable Credentials with check expiry", value = """ + { + "valid": true, + "validateExpiryDate": true, + "vc": { + "issuanceDate": "2023-07-19T09:11:34Z", + "credentialSubject": [ + { + "bpn": "BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "type": "BpnCredential" + } + ], + "id": "did:web:localhost:BPNL000000000000#f73e3631-ba87-4a03-bea3-b28700056879", + "proof": { + "created": "2023-07-19T09:11:39Z", + "jws": "eyJhbGciOiJFZERTQSJ9..fdn2qU85auOltdHDLdHI7sJVV1ZPdftpiXd_ndXN0dFgSDWiIrScdD03wtvKLq_H-shQWfh2RYeMmrlEzAhfDw", + "proofPurpose": "proofPurpose", + "type": "JsonWebSignature2020", + "verificationMethod": "did:web:localhost:BPNL000000000000#" + }, + "type": [ + "VerifiableCredential", + "BpnCredential" + ], + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "expirationDate": "2024-12-31T18:30:00Z" + } + } + """), + @ExampleObject(name = "Verifiable expired credentials with check expiry ", value = """ + { + "valid": false, + "validateExpiryDate": false, + "vc": { + "issuanceDate": "2023-07-19T09:11:34Z", + "credentialSubject": [ + { + "bpn": "BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "type": "BpnCredential" + } + ], + "id": "did:web:localhost:BPNL000000000000#f73e3631-ba87-4a03-bea3-b28700056879", + "proof": { + "created": "2023-07-19T09:11:39Z", + "jws": "eyJhbGciOiJFZERTQSJ9..fdn2qU85auOltdHDLdHI7sJVV1ZPdftpiXd_ndXN0dFgSDWiIrScdD03wtvKLq_H-shQWfh2RYeMmrlEzAhfDw", + "proofPurpose": "proofPurpose", + "type": "JsonWebSignature2020", + "verificationMethod": "did:web:localhost:BPNL000000000000#" + }, + "type": [ + "VerifiableCredential", + "BpnCredential" + ], + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "expirationDate": "2022-12-31T18:30:00Z" + } + } + """), + @ExampleObject(name = "Verifiable Credentials with invalid signature", value = """ + { + "valid": false, + "vc": { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:web:localhost:BPNL000000000000#f73e3631-ba87-4a03-bea3-b28700056879", + "type": [ + "VerifiableCredential", + "BpnCredential" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "expirationDate": "2024-12-31T18:30:00Z" + "issuanceDate": "2023-07-19T09:11:34Z", + "credentialSubject": [ + { + "bpn": "BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "type": "BpnCredential" + } + ], + "proof": { + "created": "2023-07-19T09:11:39Z", + "jws": "eyJhbGciOiJFZERTQSJ9..fdn2qU85auOltdHDLdHI7sJVV1ZPdftpiXd_ndXN0dFgSDWiIrScdD03wtvKLq_H-shQWfh2RYeMmrlEzAhf", + "proofPurpose": "proofPurpose", + "type": "JsonWebSignature2020", + "verificationMethod": "did:web:localhost:BPNL000000000000#" + }, + } + } + """) + }) + }) }) + @Operation(summary = "Validate Verifiable Credentials", description = "Permission: **view_wallets** OR **view_wallet** \n\n Validate Verifiable Credentials") + @RequestBody(content = { + @Content(examples = @ExampleObject(""" + { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:web:localhost:BPNL000000000000#f73e3631-ba87-4a03-bea3-b28700056879", + "type": [ + "VerifiableCredential", + "BpnCredential" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "issuanceDate": "2023-07-19T09:11:34Z", + "expirationDate": "2024-12-31T18:30:00Z", + "credentialSubject": [ + { + "bpn": "BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "type": "BpnCredential" + } + ], + "proof": { + "created": "2023-07-19T09:11:39Z", + "jws": "eyJhbGciOiJFZERTQSJ9..fdn2qU85auOltdHDLdHI7sJVV1ZPdftpiXd_ndXN0dFgSDWiIrScdD03wtvKLq_H-shQWfh2RYeMmrlEzAhfDw", + "proofPurpose": "proofPurpose", + "type": "JsonWebSignature2020", + "verificationMethod": "did:web:localhost:BPNL000000000000#" + } + } + """)) + }) + public @interface ValidateVerifiableCredentialApiDocs { + } + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + @Tag(name = API_TAG_VERIFIABLE_CREDENTIAL_ISSUER) + @ApiResponses(value = { + @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "500", description = "Any other internal server error", content = { + @Content(examples = { + @ExampleObject(name = "Internal server error", value = """ + { + "type": "about:blank", + "title": "Error Title", + "status": 500, + "detail": "Error Details", + "instance": "API endpoint", + "properties": { + "timestamp": 1689762476720 + } + } + """) + }) }), + @ApiResponse(responseCode = "404", description = "Wallet not found with provided identifier", content = { + @Content(examples = { + @ExampleObject(name = "Wallet not found with provided identifier", value = """ + { + "type": "about:blank", + "title": "Error Title", + "status": 404, + "detail": "Error Details", + "instance": "API endpoint", + "properties": { + "timestamp": 1689762476720 + } + } + """) + }) }), + @ApiResponse(responseCode = "400", description = "The input does not comply to the syntax requirements", content = { + @Content(examples = { + @ExampleObject(name = "Response in case of invalid data provided", value = """ + { + "type": "about:blank", + "title": "Invalid data provided", + "status": 400, + "detail": "details", + "instance": "API endpoint", + "properties": + { + "timestamp": 1689760833962, + "errors": + { + "filed": "filed error message" + } + } + } + """) + }) + }), + @ApiResponse(responseCode = "201", description = "Issuer credential", content = { + @Content(examples = { + @ExampleObject(name = "Issuer credential", value = """ + { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:web:localhost:BPNL000000000000#ff084e7a-1b46-4a2f-a78d-3d701a0bd6e4", + "type": [ + "VerifiableCredential", + "BpnCredential" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "issuanceDate": "2023-07-19T12:18:30Z", + "expirationDate": "2024-12-31T18:30:00Z", + "credentialSubject": [ + { + "bpn": "BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "type": "BpnCredential" + } + ], + "proof": { + "proofPurpose": "proofPurpose", + "type": "JsonWebSignature2020", + "verificationMethod": "did:web:localhost:BPNL000000000000#", + "created": "2023-07-19T12:18:34Z", + "jws": "eyJhbGciOiJFZERTQSJ9..0Ua1vcTQAYwQY3PPuHr4RQxqW6iIngrHQQx1oPgk2uzqUpcbfY2YUxXAnbNA333-lSuvNhiV_1NLfBnCEcI2DQ" + } + } + """) + }) + }) }) + @Operation(summary = "Issue Verifiable Credential", description = "Permission: **update_wallets** (The BPN of the base wallet must equal BPN of caller)\nIssue a verifiable credential with a given issuer DID") + @RequestBody(content = { + @Content(examples = @ExampleObject(""" + { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:web:localhost:BPNL000000000000#f73e3631-ba87-4a03-bea3-b28700056879", + "type": [ + "VerifiableCredential", + "BpnCredential" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "issuanceDate": "2023-07-19T09:11:34Z", + "expirationDate": "2024-12-31T18:30:00Z", + "credentialSubject": [ + { + "bpn": "BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "type": "BpnCredential" + } + ] + } + """)) + }) + public @interface IssueVerifiableCredentialUsingBaseWalletApiDocs { + } +} diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/apidocs/PresentationControllerApiDocs.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/apidocs/PresentationControllerApiDocs.java new file mode 100644 index 000000000..06a072e3a --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/apidocs/PresentationControllerApiDocs.java @@ -0,0 +1,289 @@ +package org.eclipse.tractusx.managedidentitywallets.apidocs; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.parameters.RequestBody; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; + +public class PresentationControllerApiDocs { + public static final String API_TAG_VERIFIABLE_PRESENTATIONS_GENERATION = "Verifiable Presentations - Generation"; + public static final String API_TAG_VERIFIABLE_PRESENTATIONS_VALIDATION = "Verifiable Presentations - Validation"; + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + @Tag(name = API_TAG_VERIFIABLE_PRESENTATIONS_GENERATION) + @Operation(summary = "Create Verifiable Presentation", description = "Permission: **update_wallets** OR **update_wallet** (The BPN of the issuer of the Verifiable Presentation must equal to BPN of caller) \n\n Create a verifiable presentation from a list of verifiable credentials, signed by the holder") + @ApiResponses(value = { + + @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "500", description = "Any other internal server error", content = { + @Content(examples = { + @ExampleObject(name = "Internal server error", value = """ + { + "type": "about:blank", + "title": "Error Title", + "status": 500, + "detail": "Error Details", + "instance": "API endpoint", + "properties": { + "timestamp": 1689762476720 + } + } + """) + }) }), + @ApiResponse(responseCode = "404", description = "Wallet not found with provided identifier", content = { + @Content(examples = { + @ExampleObject(name = "Wallet not found with provided identifier", value = """ + { + "type": "about:blank", + "title": "Error Title", + "status": 404, + "detail": "Error Details", + "instance": "API endpoint", + "properties": { + "timestamp": 1689762476720 + } + } + """) + }) }), + @ApiResponse(responseCode = "200", description = "Verifiable Presentation", content = { + @Content(examples = { + @ExampleObject(name = "VP as Json-LD", value = """ + { + "vp": { + "@context": [ + "https://www.w3.org/2018/credentials/v1" + ], + "id": "did:web:localhost:BPNL000000000000#b2e69e47-95f3-48ff-af30-eaaab36431d5", + "type": [ + "VerifiablePresentation" + ], + "verifiableCredential": [ + { + "id": "did:web:localhost:BPNL000000000000#f73e3631-ba87-4a03-bea3-b28700056879", + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "type": [ + "VerifiableCredential", + "BpnCredential" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "expirationDate": "2024-12-31T18:30:00Z", + "issuanceDate": "2023-07-19T09:11:34Z", + "credentialSubject": [ + { + "bpn": "BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "type": "BpnCredential" + } + ], + "proof": { + "created": "2023-07-19T09:11:39Z", + "jws": "eyJhbGciOiJFZERTQSJ9..fdn2qU85auOltdHDLdHI7sJVV1ZPdftpiXd_ndXN0dFgSDWiIrScdD03wtvKLq_H-shQWfh2RYeMmrlEzAhfDw", + "proofPurpose": "proofPurpose", + "type": "JsonWebSignature2020", + "verificationMethod": "did:web:localhost:BPNL000000000000#" + } + } + ] + } + } + """), + @ExampleObject(name = "VP as JWT", value = """ + { + "vp": "eyJraWQiOiJkaWQ6d2ViOmxvY2FsaG9zdDpCUE5MMDAwMDAwMDAwMDAwIiwidHlwIjoiSldUIiwiYWxnIjoiRWREU0EifQ.eyJzdWIiOiJkaWQ6d2ViOmxvY2FsaG9zdDpCUE5MMDAwMDAwMDAwMDAwIiwiYXVkIjoic21hcnQiLCJpc3MiOiJkaWQ6d2ViOmxvY2FsaG9zdDpCUE5MMDAwMDAwMDAwMDAwIiwidnAiOnsiaWQiOiJkaWQ6d2ViOmxvY2FsaG9zdDpCUE5MMDAwMDAwMDAwMDAwIzM4ZTU2ZTg1LTNkODQtNGEyNS1iZjg1LWFiMjRlYzY4MmMwOSIsInR5cGUiOlsiVmVyaWZpYWJsZVByZXNlbnRhdGlvbiJdLCJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJ2ZXJpZmlhYmxlQ3JlZGVudGlhbCI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vY2F0ZW5heC1uZy5naXRodWIuaW8vcHJvZHVjdC1jb3JlLXNjaGVtYXMvYnVzaW5lc3NQYXJ0bmVyRGF0YS5qc29uIiwiaHR0cHM6Ly93M2lkLm9yZy9zZWN1cml0eS9zdWl0ZXMvandzLTIwMjAvdjEiXSwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCIsIkJwbkNyZWRlbnRpYWwiXSwiaWQiOiJkaWQ6d2ViOmxvY2FsaG9zdDpCUE5MMDAwMDAwMDAwMDAwI2Y3M2UzNjMxLWJhODctNGEwMy1iZWEzLWIyODcwMDA1Njg3OSIsImlzc3VlciI6ImRpZDp3ZWI6bG9jYWxob3N0OkJQTkwwMDAwMDAwMDAwMDAiLCJpc3N1YW5jZURhdGUiOiIyMDIzLTA3LTE5VDA5OjExOjM0WiIsImV4cGlyYXRpb25EYXRlIjoiMjAyNC0xMi0zMVQxODozMDowMFoiLCJjcmVkZW50aWFsU3ViamVjdCI6eyJpZCI6ImRpZDp3ZWI6bG9jYWxob3N0OkJQTkwwMDAwMDAwMDAwMDAiLCJicG4iOiJCUE5MMDAwMDAwMDAwMDAwIiwidHlwZSI6IkJwbkNyZWRlbnRpYWwifSwicHJvb2YiOnsicHJvb2ZQdXJwb3NlIjoicHJvb2ZQdXJwb3NlIiwidHlwZSI6Ikpzb25XZWJTaWduYXR1cmUyMDIwIiwidmVyaWZpY2F0aW9uTWV0aG9kIjoiZGlkOndlYjpsb2NhbGhvc3Q6QlBOTDAwMDAwMDAwMDAwMCMiLCJjcmVhdGVkIjoiMjAyMy0wNy0xOVQwOToxMTozOVoiLCJqd3MiOiJleUpoYkdjaU9pSkZaRVJUUVNKOS4uZmRuMnFVODVhdU9sdGRIRExkSEk3c0pWVjFaUGRmdHBpWGRfbmRYTjBkRmdTRFdpSXJTY2REMDN3dHZLTHFfSC1zaFFXZmgyUlllTW1ybEV6QWhmRHcifX19LCJleHAiOjE2ODk4MzQ4MDUsImp0aSI6ImIwODYzOWZiLWQ5MWEtNGUwZS1iNmY4LTYzYjdhMzQ1ZTRhZiJ9.80x0AB-OauefdeZfx1cwhitdVKRvCRFeFzYwU73DL7y4w34vu6BdfHWLBGjkwELxkQEoFfiTPOqtuyqhtsyDBg" + } + """) + }) + }) + }) + @RequestBody(content = { + @Content(examples = @ExampleObject(""" + { + "verifiableCredentials": + [ + { + "id": "did:web:localhost:BPNL000000000000#f73e3631-ba87-4a03-bea3-b28700056879", + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "type": [ + "VerifiableCredential", + "BpnCredential" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "expirationDate": "2024-12-31T18:30:00Z", + "issuanceDate": "2023-07-19T09:11:34Z", + "credentialSubject": [ + { + "bpn": "BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "type": "BpnCredential" + } + ], + "proof": { + "created": "2023-07-19T09:11:39Z", + "jws": "eyJhbGciOiJFZERTQSJ9..fdn2qU85auOltdHDLdHI7sJVV1ZPdftpiXd_ndXN0dFgSDWiIrScdD03wtvKLq_H-shQWfh2RYeMmrlEzAhfDw", + "proofPurpose": "proofPurpose", + "type": "JsonWebSignature2020", + "verificationMethod": "did:web:localhost:BPNL000000000000#" + } + } + ] + } + """)) + }) + public @interface PostVerifiablePresentationApiDocs { + } + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + @Tag(name = API_TAG_VERIFIABLE_PRESENTATIONS_VALIDATION) + @Operation(summary = "Validate Verifiable Presentation", description = "Permission: **view_wallets** OR **view_wallet** \n\n Validate Verifiable Presentation with all included credentials") + @ApiResponses(value = { + @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "500", description = "Any other internal server error", content = { + @Content(examples = { + @ExampleObject(name = "Internal server error", value = """ + { + "type": "about:blank", + "title": "Error Title", + "status": 500, + "detail": "Error Details", + "instance": "API endpoint", + "properties": { + "timestamp": 1689762476720 + } + } + """) + }) }), + @ApiResponse(responseCode = "400", description = "The input does not comply to the syntax requirements", content = { + @Content(examples = { + @ExampleObject(name = "Validation of VP in form of JSON-LD is not supported", value = """ + { + "type": "about:blank", + "title": "Validation of VP in form of JSON-LD is not supported", + "status": 400, + "detail": "Validation of VP in form of JSON-LD is not supported", + "instance": "/api/presentations/validation", + "properties": { + "timestamp": 1689835085703 + } + } + """), + @ExampleObject(name = "Response in case of invalid data provided", value = """ + { + "type": "about:blank", + "title": "Invalid data provided", + "status": 400, + "detail": "details", + "instance": "API endpoint", + "properties": + { + "timestamp": 1689760833962, + "errors": + { + "filed": "filed error message" + } + } + } + """) + }) }), + @ApiResponse(responseCode = "200", description = "Verifiable presentation validate", content = { + @Content(examples = { + @ExampleObject(name = "VP as JWT", value = """ + { + "valid": true, + "validateJWTExpiryDate": true, + "validateAudience": true, + "vp": "eyJraWQiOiJkaWQ6d2ViOmxvY2FsaG9zdDpCUE5MMDAwMDAwMDAwMDAwIiwidHlwIjoiSldUIiwiYWxnIjoiRWREU0EifQ.eyJzdWIiOiJkaWQ6d2ViOmxvY2FsaG9zdDpCUE5MMDAwMDAwMDAwMDAwIiwiYXVkIjoic21hcnQiLCJpc3MiOiJkaWQ6d2ViOmxvY2FsaG9zdDpCUE5MMDAwMDAwMDAwMDAwIiwidnAiOnsiaWQiOiJkaWQ6d2ViOmxvY2FsaG9zdDpCUE5MMDAwMDAwMDAwMDAwIzM4ZTU2ZTg1LTNkODQtNGEyNS1iZjg1LWFiMjRlYzY4MmMwOSIsInR5cGUiOlsiVmVyaWZpYWJsZVByZXNlbnRhdGlvbiJdLCJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJ2ZXJpZmlhYmxlQ3JlZGVudGlhbCI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vY2F0ZW5heC1uZy5naXRodWIuaW8vcHJvZHVjdC1jb3JlLXNjaGVtYXMvYnVzaW5lc3NQYXJ0bmVyRGF0YS5qc29uIiwiaHR0cHM6Ly93M2lkLm9yZy9zZWN1cml0eS9zdWl0ZXMvandzLTIwMjAvdjEiXSwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCIsIkJwbkNyZWRlbnRpYWwiXSwiaWQiOiJkaWQ6d2ViOmxvY2FsaG9zdDpCUE5MMDAwMDAwMDAwMDAwI2Y3M2UzNjMxLWJhODctNGEwMy1iZWEzLWIyODcwMDA1Njg3OSIsImlzc3VlciI6ImRpZDp3ZWI6bG9jYWxob3N0OkJQTkwwMDAwMDAwMDAwMDAiLCJpc3N1YW5jZURhdGUiOiIyMDIzLTA3LTE5VDA5OjExOjM0WiIsImV4cGlyYXRpb25EYXRlIjoiMjAyNC0xMi0zMVQxODozMDowMFoiLCJjcmVkZW50aWFsU3ViamVjdCI6eyJpZCI6ImRpZDp3ZWI6bG9jYWxob3N0OkJQTkwwMDAwMDAwMDAwMDAiLCJicG4iOiJCUE5MMDAwMDAwMDAwMDAwIiwidHlwZSI6IkJwbkNyZWRlbnRpYWwifSwicHJvb2YiOnsicHJvb2ZQdXJwb3NlIjoicHJvb2ZQdXJwb3NlIiwidHlwZSI6Ikpzb25XZWJTaWduYXR1cmUyMDIwIiwidmVyaWZpY2F0aW9uTWV0aG9kIjoiZGlkOndlYjpsb2NhbGhvc3Q6QlBOTDAwMDAwMDAwMDAwMCMiLCJjcmVhdGVkIjoiMjAyMy0wNy0xOVQwOToxMTozOVoiLCJqd3MiOiJleUpoYkdjaU9pSkZaRVJUUVNKOS4uZmRuMnFVODVhdU9sdGRIRExkSEk3c0pWVjFaUGRmdHBpWGRfbmRYTjBkRmdTRFdpSXJTY2REMDN3dHZLTHFfSC1zaFFXZmgyUlllTW1ybEV6QWhmRHcifX19LCJleHAiOjE2ODk4MzQ4MDUsImp0aSI6ImIwODYzOWZiLWQ5MWEtNGUwZS1iNmY4LTYzYjdhMzQ1ZTRhZiJ9.80x0AB-OauefdeZfx1cwhitdVKRvCRFeFzYwU73DL7y4w34vu6BdfHWLBGjkwELxkQEoFfiTPOqtuyqhtsyDBg", + "validateExpiryDate": true + } + """) + }) + }) + }) + @RequestBody(content = { + @Content(examples = { + + @ExampleObject(name = "VP as JWT", value = """ + { + "vp": "eyJraWQiOiJkaWQ6d2ViOmxvY2FsaG9zdDpCUE5MMDAwMDAwMDAwMDAwIiwidHlwIjoiSldUIiwiYWxnIjoiRWREU0EifQ.eyJzdWIiOiJkaWQ6d2ViOmxvY2FsaG9zdDpCUE5MMDAwMDAwMDAwMDAwIiwiYXVkIjoic21hcnQiLCJpc3MiOiJkaWQ6d2ViOmxvY2FsaG9zdDpCUE5MMDAwMDAwMDAwMDAwIiwidnAiOnsiaWQiOiJkaWQ6d2ViOmxvY2FsaG9zdDpCUE5MMDAwMDAwMDAwMDAwIzZmZWRmYWRmLWYxNTItNGNjZS05MWQ1LWNjMjhhNzhlMTExMyIsInR5cGUiOlsiVmVyaWZpYWJsZVByZXNlbnRhdGlvbiJdLCJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJ2ZXJpZmlhYmxlQ3JlZGVudGlhbCI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vY2F0ZW5heC1uZy5naXRodWIuaW8vcHJvZHVjdC1jb3JlLXNjaGVtYXMvYnVzaW5lc3NQYXJ0bmVyRGF0YS5qc29uIiwiaHR0cHM6Ly93M2lkLm9yZy9zZWN1cml0eS9zdWl0ZXMvandzLTIwMjAvdjEiXSwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCIsIkJwbkNyZWRlbnRpYWwiXSwiaWQiOiJkaWQ6d2ViOmxvY2FsaG9zdDpCUE5MMDAwMDAwMDAwMDAwI2Y3M2UzNjMxLWJhODctNGEwMy1iZWEzLWIyODcwMDA1Njg3OSIsImlzc3VlciI6ImRpZDp3ZWI6bG9jYWxob3N0OkJQTkwwMDAwMDAwMDAwMDAiLCJpc3N1YW5jZURhdGUiOiIyMDIzLTA3LTE5VDA5OjExOjM0WiIsImV4cGlyYXRpb25EYXRlIjoiMjAyNC0xMi0zMVQxODozMDowMFoiLCJjcmVkZW50aWFsU3ViamVjdCI6eyJpZCI6ImRpZDp3ZWI6bG9jYWxob3N0OkJQTkwwMDAwMDAwMDAwMDAiLCJicG4iOiJCUE5MMDAwMDAwMDAwMDAwIiwidHlwZSI6IkJwbkNyZWRlbnRpYWwifSwicHJvb2YiOnsicHJvb2ZQdXJwb3NlIjoicHJvb2ZQdXJwb3NlIiwidHlwZSI6Ikpzb25XZWJTaWduYXR1cmUyMDIwIiwidmVyaWZpY2F0aW9uTWV0aG9kIjoiZGlkOndlYjpsb2NhbGhvc3Q6QlBOTDAwMDAwMDAwMDAwMCMiLCJjcmVhdGVkIjoiMjAyMy0wNy0xOVQwOToxMTozOVoiLCJqd3MiOiJleUpoYkdjaU9pSkZaRVJUUVNKOS4uZmRuMnFVODVhdU9sdGRIRExkSEk3c0pWVjFaUGRmdHBpWGRfbmRYTjBkRmdTRFdpSXJTY2REMDN3dHZLTHFfSC1zaFFXZmgyUlllTW1ybEV6QWhmRHcifX19LCJleHAiOjE2ODk3NTg1NDQsImp0aSI6IjdlNWE4MzQ4LTgwZjUtNGIzMS1iMDNlLTBiOTJmNzc4ZTVjZiJ9.c7FS-CLwm3vxfO9847M5sqcVxv3QbwwSmSsFWcGif7MOesjt1pdnARlQ4pvHzgsFj1UqBEvHwZQvyYyPCQg_Cw" + } + """) + + , + @ExampleObject(name = "VP as json-ld", value = """ + { + "vp": + { + "id": "b9d97cef-758d-4a7c-843d-86f17632b08a", + "type": + [ + "VerifiablePresentation" + ], + "@context": + [ + "https://www.w3.org/2018/credentials/v1" + ], + "verifiableCredential": + [ + { + "id": "did:web:localhost:BPNL000000000000#f73e3631-ba87-4a03-bea3-b28700056879", + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "type": [ + "VerifiableCredential", + "BpnCredential" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "expirationDate": "2024-12-31T18:30:00Z", + "issuanceDate": "2023-07-19T09:11:34Z", + "credentialSubject": [ + { + "bpn": "BPNL000000000000", + "id": "did:web:localhost:BPNL000000000000", + "type": "BpnCredential" + } + ], + "proof": { + "created": "2023-07-19T09:11:39Z", + "jws": "eyJhbGciOiJFZERTQSJ9..fdn2qU85auOltdHDLdHI7sJVV1ZPdftpiXd_ndXN0dFgSDWiIrScdD03wtvKLq_H-shQWfh2RYeMmrlEzAhfDw", + "proofPurpose": "proofPurpose", + "type": "JsonWebSignature2020", + "verificationMethod": "did:web:localhost:BPNL000000000000#" + } + } + ] + } + } + """) + + }) + }) + public @interface PostVerifiablePresentationValidationApiDocs { + } + +} diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/apidocs/WalletControllerApiDocs.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/apidocs/WalletControllerApiDocs.java new file mode 100644 index 000000000..e681a14bb --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/apidocs/WalletControllerApiDocs.java @@ -0,0 +1,541 @@ +package org.eclipse.tractusx.managedidentitywallets.apidocs; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.parameters.RequestBody; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +public class WalletControllerApiDocs { + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + @RequestBody(content = { + @Content(examples = { + + @ExampleObject(name = "Create wallet with BPN", value = """ + { + "bpn": "BPNL000000000001", + "name": "companyA" + } + """) + }) + }) + @ApiResponses(value = { + @ApiResponse(responseCode = "400", description = "The input does not comply to the syntax requirements", content = { + @Content(examples = { + @ExampleObject(name = "Response in case of invalid data provided", value = """ + { + "type": "about:blank", + "title": "Invalid data provided", + "status": 400, + "detail": "details", + "instance": "API endpoint", + "properties": + { + "timestamp": 1689760833962, + "errors": + { + "filed": "filed error message" + } + } + } + """) + }) + }), + @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "409", description = "The request could not be completed due to a conflict.", content = { + @Content(examples = { + @ExampleObject(name = "Wallet already exist", value = """ + { + "type": "about:blank", + "title": "Wallet is already exists for bpn BPNL000000000001", + "status": 409, + "detail": "Wallet is already exists for bpn BPNL000000000001", + "instance": "/api/wallets", + "properties": { + "timestamp": 1689762639948 + } + } + """) + }) }), + @ApiResponse(responseCode = "500", description = "Any other internal server error", content = { + @Content(examples = { + @ExampleObject(name = "Internal server error", value = """ + { + "type": "about:blank", + "title": "Error Title", + "status": 500, + "detail": "Error Details", + "instance": "API endpoint", + "properties": { + "timestamp": 1689762476720 + } + } + """) + }) }), + @ApiResponse(responseCode = "201", content = { + @Content(examples = { + @ExampleObject(name = "Success response", value = """ + { + "name": "companyA", + "did": "did:web:localhost:BPNL000000000001", + "bpn": "BPNL000000000501", + "algorithm": "ED25519", + "didDocument": + { + "@context": + [ + "https://www.w3.org/ns/did/v1", + "https://w3c.github.io/vc-jws-2020/contexts/v1" + ], + "id": "did:web:localhost:BPNL000000000001", + "verificationMethod": + [ + { + "controller": "did:web:localhost:BPNL000000000001", + "id": "did:web:localhost:BPNL000000000001#", + "publicKeyJwk": + { + "crv": "Ed25519", + "kty": "OKP", + "x": "0Ap6FsX5UuRBIoOzxWtcFA2ymnqXw0U08Ino_mIuYM4" + }, + "type": "JsonWebKey2020" + } + ] + } + } + """) + }) + }) + }) + @Operation(summary = "Create Wallet", description = "Permission: **add_wallets** (The BPN of the base wallet must equal BPN of caller)\n\n Create a wallet and store it") + public @interface CreateWalletApiDoc { + } + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + @Operation(summary = "Store Verifiable Credential", description = "Permission: **update_wallets** OR **update_wallet** (The BPN of wallet to extract credentials from must equal BPN of caller) \n\n Store a verifiable credential in the wallet of the given identifier") + @RequestBody(content = { + @Content(examples = @ExampleObject(""" + { + "@context": + [ + "https://www.w3.org/2018/credentials/v1", + "https://registry.lab.gaia-x.eu/development/api/trusted-shape-registry/v1/shapes/jsonld/trustframework#" + ], + "id": "did:web:localhost.in#123456789", + "type": + [ + "VerifiableCredential", "LegalParticipant" + ], + "issuer": "did:web:localhost.in", + "issuanceDate": "2023-05-04T07:36:03.633Z", + "credentialSubject": + { + "id": "https://localhost/.well-known/participant.json", + "type": "gx:LegalParticipant", + "gx:legalName": "Sample Company", + "gx:legalRegistrationNumber": + { + "gx:taxID": "113123123" + }, + "gx:headquarterAddress": + { + "gx:countrySubdivisionCode": "BE-BRU" + }, + "gx:legalAddress": + { + "gx:countrySubdivisionCode": "BE-BRU" + }, + "gx-terms-and-conditions:gaiaxTermsAndConditions": "70c1d713215f95191a11d38fe2341faed27d19e083917bc8732ca4fea4976700" + }, + "proof": + { + "type": "JsonWebSignature2020", + "created": "2023-05-04T07:36:04.079Z", + "proofPurpose": "assertionMethod", + "verificationMethod": "did:web:localhost", + "jws": "eyJhbGciOiJQUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..iHki8WC3nPfcSRkC_AV4tXh0ikfT7BLPTGc_0ecI8zontTmJLqwcpPfAt0PFsoo3SkZgc6j636z55jj5tagBc-OKoiDu7diWryNAnL9ASsmWJyrPhOKVARs6x6PxVaTFBuyCfAHZeipxmkcYfNB_jooIXO2HuRcL2odhsQHELkGc5IDD-aBMWyNpfVAaYQ-cCzvDflZQlsowziUKfMkBfwpwgMdXFIgKWYdDIRvzA-U-XiC11-6QV7tPeKsMguEU0F5bh8cCEm2rooqXtENcsM_7cqFdQoOyblJyM-agoz2LUTj9QIdn9_gnNkGN-2U7_qBJWmHkK1Hm_mHqcNeeQw" + } + } + """)) + }) + @ApiResponses(value = { + @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "500", description = "Any other internal server error", content = { + @Content(examples = { + @ExampleObject(name = "Internal server error", value = """ + { + "type": "about:blank", + "title": "Error Title", + "status": 500, + "detail": "Error Details", + "instance": "API endpoint", + "properties": { + "timestamp": 1689762476720 + } + } + """) + }) }), + @ApiResponse(responseCode = "400", description = "The input does not comply to the syntax requirements", content = { + @Content(examples = { + @ExampleObject(name = "Response in case of invalid data provided", value = """ + { + "type": "about:blank", + "title": "title", + "status": 400, + "detail": "details", + "instance": "API endpoint", + "properties": + { + "timestamp": 1689760833962, + "errors": + { + } + } + } + """) + }) + }), + @ApiResponse(responseCode = "404", description = "Wallet not found with provided identifier", content = { + @Content(examples = { + @ExampleObject(name = "Wallet not found with provided identifier", value = """ + { + "type": "about:blank", + "title": "Wallet not found for identifier did:web:localhost:BPNL000000044001", + "status": 404, + "detail": "Wallet not found for identifier did:web:localhost:BPNL000000044001", + "instance": "/api/wallets/did%3Aweb%3Alocalhost%3ABPNL0000000/credentials", + "properties": { + "timestamp": 1689765541959 + } + } + """) + }) }), + @ApiResponse(responseCode = "201", description = "Success Response", content = { @Content(examples = { + @ExampleObject(name = "Success Response", value = """ + { + "message": "Credential with id did:web:localhost#123456789 has been successfully stored" + } + """) + }) + }) + }) + public @interface StoreVerifiableCredentialApiDoc { + } + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + @ApiResponses(value = { + @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "500", description = "Any other internal server error", content = { + @Content(examples = { + @ExampleObject(name = "Internal server error", value = """ + { + "type": "about:blank", + "title": "Error Title", + "status": 500, + "detail": "Error Details", + "instance": "API endpoint", + "properties": { + "timestamp": 1689762476720 + } + } + """) + }) }), + @ApiResponse(responseCode = "400", description = "The input does not comply to the syntax requirements", content = { + @Content(examples = { + @ExampleObject(name = "Response in case of invalid data provided", value = """ + { + "type": "about:blank", + "title": "title", + "status": 400, + "detail": "details", + "instance": "API endpoint", + "properties": + { + "timestamp": 1689760833962, + "errors": + { + } + } + } + """) + }) + }), + @ApiResponse(responseCode = "404", description = "Wallet not found with provided identifier", content = { + @Content(examples = { + @ExampleObject(name = "Wallet not found with provided identifier", value = """ + { + "type": "about:blank", + "title": "Wallet not found for identifier did:web:localhost:BPNL0000000501", + "status": 404, + "detail": "Wallet not found for identifier did:web:localhost:BPNL0000000501", + "instance": "/api/wallets/did%3Aweb%3Alocalhost%3ABPNL0000000501", + "properties": { + "timestamp": 1689764377224 + } + } + """) + }) }), + @ApiResponse(responseCode = "200", description = "Wallet Details", content = { @Content(examples = { + @ExampleObject(name = "Wallet details without with credentials false", value = """ + { + "name": "companyA", + "did": "did:web:localhost:BPNL000000000001", + "bpn": "BPNL000000000001", + "algorithm": "ED25519", + "didDocument": + { + "@context": + [ + "https://www.w3.org/ns/did/v1", + "https://w3c.github.io/vc-jws-2020/contexts/v1" + ], + "id": "did:web:localhost:BPNL000000000001", + "verificationMethod": + [ + { + "controller": "did:web:localhost:BPNL000000000001", + "id": "did:web:localhost:BPNL000000000001#", + "publicKeyJwk": + { + "crv": "Ed25519", + "kty": "OKP", + "x": "mhph0ZSVk7cDVmazbaaC3jBDpphW4eNygAK9gHPlMow" + }, + "type": "JsonWebKey2020" + } + ] + } + } + """), + @ExampleObject(name = "Wallet details without with credentials true", value = """ + { + "name": "companyA", + "did": "did:web:localhost:BPNL000000000001", + "bpn": "BPNL000000000001", + "algorithm": "ED25519", + "didDocument": + { + "@context": + [ + "https://www.w3.org/ns/did/v1", + "https://w3c.github.io/vc-jws-2020/contexts/v1" + ], + "id": "did:web:localhost:BPNL000000000001", + "verificationMethod": + [ + { + "controller": "did:web:localhost:BPNL000000000001", + "id": "did:web:localhost:BPNL000000000001#", + "publicKeyJwk": + { + "crv": "Ed25519", + "kty": "OKP", + "x": "mhph0ZSVk7cDVmazbaaC3jBDpphW4eNygAK9gHPlMow" + }, + "type": "JsonWebKey2020" + } + ] + }, + "verifiableCredentials": + [ + { + "@context": + [ + "https://www.w3.org/2018/credentials/v1", + "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:web:localhost:BPNL000000000000#a1f8ae36-9919-4ed8-8546-535280acc5bf", + "type": + [ + "VerifiableCredential", + "BpnCredential" + ], + "issuer": "did:web:localhost:BPNL000000000000", + "issuanceDate": "2023-07-19T09:14:45Z", + "expirationDate": "2023-09-30T18:30:00Z", + "credentialSubject": + [ + { + "bpn": "BPNL000000000001", + "id": "did:web:localhost:BPNL000000000001", + "type": "BpnCredential" + } + ], + "proof": + { + "created": "2023-07-19T09:14:47Z", + "jws": "eyJhbGciOiJFZERTQSJ9..O69dLGMDVgZQJ7chFx3aUbkJFvibH8WWunw634rIDC77_pdiUHvQpQ0hq15_7OgFMy3dp-9H-pNgxTZ-i4UXCw", + "proofPurpose": "proofPurpose", + "type": "JsonWebSignature2020", + "verificationMethod": "did:web:localhost:BPNL000000000000#" + } + } + ] + } + """) + }) }) }) + @Operation(summary = "Retrieve wallet by BPN", description = "Permission: **view_wallets** OR **view_wallet** (The BPN of Wallet to retrieve must equal the BPN of caller or Base wallet, authority wallet can see all wallets) \n\n Retrieve single wallet by identifier, with or without its credentials") + public @interface RetrieveWalletApiDoc { + } + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + @ApiResponses(value = { + @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = { + @Content(examples = {}) }), + @ApiResponse(responseCode = "500", description = "Any other internal server error", content = { + @Content(examples = { + @ExampleObject(name = "Internal server error", value = """ + { + "type": "about:blank", + "title": "Error Title", + "status": 500, + "detail": "Error Details", + "instance": "API endpoint", + "properties": { + "timestamp": 1689762476720 + } + } + """) + }) }), + @ApiResponse(responseCode = "400", description = "The input does not comply to the syntax requirements", content = { + @Content(examples = { + @ExampleObject(name = "Response in case of invalid data provided", value = """ + { + "type": "about:blank", + "title": "title", + "status": 400, + "detail": "details", + "instance": "API endpoint", + "properties": + { + "timestamp": 1689760833962, + "errors": + { + } + } + } + """) + }) + }), + @ApiResponse(responseCode = "200", description = "Wallet list", content = { + @Content(examples = { + @ExampleObject(name = "Wallet list", value = """ + { + "content": [ + { + "name": "companyA", + "did": "did:web:localhost:BPNL000000000001", + "bpn": "BPNL000000000001", + "algorithm": "ED25519", + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3c.github.io/vc-jws-2020/contexts/v1" + ], + "id": "did:web:localhost:BPNL000000000001", + "verificationMethod": [ + { + "controller": "did:web:localhost:BPNL000000000001", + "id": "did:web:localhost:BPNL000000000001#", + "publicKeyJwk": { + "crv": "Ed25519", + "kty": "OKP", + "x": "mhph0ZSVk7cDVmazbaaC3jBDpphW4eNygAK9gHPlMow" + }, + "type": "JsonWebKey2020" + } + ] + } + } + ], + "pageable": { + "sort": { + "empty": false, + "sorted": true, + "unsorted": false + }, + "offset": 0, + "pageNumber": 0, + "pageSize": 1, + "paged": true, + "unpaged": false + }, + "totalElements": 3, + "totalPages": 3, + "last": false, + "size": 1, + "number": 0, + "sort": { + "empty": false, + "sorted": true, + "unsorted": false + }, + "first": true, + "numberOfElements": 1, + "empty": false + } + """) + }) + }) + }) + @Operation(summary = "List of wallets", description = "Permission: **view_wallets** \n\n Retrieve list of registered wallets") + public @interface RetrieveWalletsApiDoc { + } + + @Target(ElementType.PARAMETER) + @Retention(RetentionPolicy.RUNTIME) + @Parameter(name = "pageNumber", description = "Page number, Page number start with zero") + public @interface PageNumberParameterDoc { + } + + @Target(ElementType.PARAMETER) + @Retention(RetentionPolicy.RUNTIME) + @Parameter(name = "size", description = "Number of records per page") + public @interface SizeParameterDoc { + } + + @Target(ElementType.PARAMETER) + @Retention(RetentionPolicy.RUNTIME) + @Parameter(name = "sortColumn", description = "Sort column name", examples = { + @ExampleObject(value = "createdAt", name = "Creation date"), + @ExampleObject(value = "name", name = "Wallet name"), + @ExampleObject(value = "did", name = "Wallet did"), + @ExampleObject(value = "bpn", name = "Wallet BPN") + }) + public @interface SortColumnParameterDoc { + } + + @Target(ElementType.PARAMETER) + @Retention(RetentionPolicy.RUNTIME) + @Parameter(name = "sortTpe", description = "Sort order", examples = { + @ExampleObject(value = "desc", name = "Descending order"), + @ExampleObject(value = "asc", name = "Ascending order") }) + public @interface SortTypeParameterDoc { + } + +} diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/security/CustomAuthenticationConverter.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/security/CustomAuthenticationConverter.java index 2630d4282..3dc3351ab 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/security/CustomAuthenticationConverter.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/security/CustomAuthenticationConverter.java @@ -21,6 +21,12 @@ package org.eclipse.tractusx.managedidentitywallets.config.security; +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + import org.springframework.core.convert.converter.Converter; import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.core.GrantedAuthority; @@ -29,17 +35,13 @@ import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter; -import java.util.Collection; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - /** * The type Custom authentication converter. */ public class CustomAuthenticationConverter implements Converter { + private static final String ROLE_PREFIX = "ROLE_"; + private final JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter; private final String resourceId; @@ -63,17 +65,15 @@ public AbstractAuthenticationToken convert(Jwt source) { } private Collection extractResourceRoles(Jwt jwt, String resourceId) { - Map resourceAccess = jwt.getClaim("resource_access"); - Map resource = (Map) resourceAccess.get(resourceId); - if (Objects.isNull(resource)) { - return Set.of(); - } - Collection resourceRoles = (Collection) resource.get("roles"); - if (Objects.isNull(resourceRoles)) { - return Set.of(); - } - return resourceRoles.stream() - .map(role -> new SimpleGrantedAuthority("ROLE_" + role)) - .collect(Collectors.toSet()); + return Optional.ofNullable(jwt.getClaim("resource_access")) + .filter(resourceAccess -> resourceAccess instanceof Map) + .map(resourceAccess -> ((Map) resourceAccess).get(resourceId)) + .filter(resource -> resource instanceof Map) + .map(resource -> ((Map) resource).get("roles")) + .filter(resourceRoles -> resourceRoles instanceof Collection) + .map(resourceRoles -> ((Collection) resourceRoles).stream() + .map(role -> new SimpleGrantedAuthority(ROLE_PREFIX + role)) + .collect(Collectors.toSet())) + .orElse(Set.of()); } } \ No newline at end of file diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/DidDocumentController.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/DidDocumentController.java index 496223b89..6869d4532 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/DidDocumentController.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/DidDocumentController.java @@ -21,14 +21,12 @@ package org.eclipse.tractusx.managedidentitywallets.controller; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.ExampleObject; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.eclipse.tractusx.managedidentitywallets.apidocs.DidDocumentControllerApiDocs.BpnParameterDoc; +import org.eclipse.tractusx.managedidentitywallets.apidocs.DidDocumentControllerApiDocs.DidOrBpnParameterDoc; +import org.eclipse.tractusx.managedidentitywallets.apidocs.DidDocumentControllerApiDocs.GetDidDocumentApiDocs; +import org.eclipse.tractusx.managedidentitywallets.apidocs.DidDocumentControllerApiDocs.GetDidResolveApiDocs; import org.eclipse.tractusx.managedidentitywallets.constant.RestURI; import org.eclipse.tractusx.managedidentitywallets.service.DidDocumentService; import org.eclipse.tractusx.ssi.lib.model.did.DidDocument; @@ -38,6 +36,7 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; +import io.swagger.v3.oas.annotations.tags.Tag; /** * The type Did document controller. @@ -55,62 +54,11 @@ public class DidDocumentController extends BaseController { * @param identifier the identifier * @return the did document */ - @ApiResponse(responseCode = "500", description = "Any other internal server error", content = {@Content(examples = { - @ExampleObject(name = "Internal server error", value = """ - { - "type": "about:blank", - "title": "Error Title", - "status": 500, - "detail": "Error Details", - "instance": "API endpoint", - "properties": { - "timestamp": 1689762476720 - } - } - """) - })}) - @ApiResponse(responseCode = "404", description = "Wallet not found with provided bpn", content = {@Content(examples = { - @ExampleObject(name = "Wallet not found with provided bpn", value = """ - { - "type": "about:blank", - "title": "Wallet not found for identifier BPNL00000000000", - "status": 404, - "detail": "Wallet not found for identifier BPNL00000000000", - "instance": "/BPNL00000000000/did.json", - "properties": { - "timestamp": 1689767698010 - } - } - """) - })}) - @ApiResponse(responseCode = "200", description = "DID document", content = { - @Content(examples = { - @ExampleObject(name = " DID document", value = """ - { - "@context": [ - "https://www.w3.org/ns/did/v1", - "https://w3c.github.io/vc-jws-2020/contexts/v1" - ], - "id": "did:web:localhost:BPNL000000000000", - "verificationMethod": [ - { - "controller": "did:web:localhost:BPNL000000000000", - "id": "did:web:localhost:BPNL000000000000", - "publicKeyJwk": { - "crv": "Ed25519", - "kty": "OKP", - "x": "wAOQvr92L1m7RwrpeOrgWByVYvWmhRr4fJbiMwHEIdY" - }, - "type": "JsonWebKey2020" - } - ] - } - """) - }) - }) - @Operation(description = "Resolve the DID document for a given DID or BPN", summary = "Resolve DID Document") + @GetDidDocumentApiDocs @GetMapping(path = RestURI.DID_DOCUMENTS, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity getDidDocument(@Parameter(description = "Did or BPN",examples = {@ExampleObject(name = "bpn", value = "BPNL000000000000", description = "bpn"), @ExampleObject(description = "did", name = "did", value = "did:web:localhost:BPNL000000000000")}) @PathVariable(name = "identifier") String identifier) { + public ResponseEntity getDidDocument( + @DidOrBpnParameterDoc @PathVariable(name = "identifier") String identifier + ) { log.debug("Received request to get DID document for identifier: {}", identifier); return ResponseEntity.status(HttpStatus.OK).body(service.getDidDocument(identifier)); } @@ -121,62 +69,11 @@ public ResponseEntity getDidDocument(@Parameter(description = "Did * @param bpn the bpn * @return the did resolve */ - @ApiResponse(responseCode = "500", description = "Any other internal server error", content = {@Content(examples = { - @ExampleObject(name = "Internal server error", value = """ - { - "type": "about:blank", - "title": "Error Title", - "status": 500, - "detail": "Error Details", - "instance": "API endpoint", - "properties": { - "timestamp": 1689762476720 - } - } - """) - })}) - @ApiResponse(responseCode = "404", description = "Wallet not found with provided bpn", content = {@Content(examples = { - @ExampleObject(name = "Wallet not found with provided bpn", value = """ - { - "type": "about:blank", - "title": "Wallet not found for identifier BPNL00000000000", - "status": 404, - "detail": "Wallet not found for identifier BPNL00000000000", - "instance": "/BPNL00000000000/did.json", - "properties": { - "timestamp": 1689767698010 - } - } - """) - })}) - @ApiResponse(responseCode = "200", description = "DID document", content = { - @Content(examples = { - @ExampleObject(name = " DID document", value = """ - { - "@context": [ - "https://www.w3.org/ns/did/v1", - "https://w3c.github.io/vc-jws-2020/contexts/v1" - ], - "id": "did:web:localhost:BPNL000000000000", - "verificationMethod": [ - { - "controller": "did:web:localhost:BPNL000000000000", - "id": "did:web:localhost:BPNL000000000000", - "publicKeyJwk": { - "crv": "Ed25519", - "kty": "OKP", - "x": "wAOQvr92L1m7RwrpeOrgWByVYvWmhRr4fJbiMwHEIdY" - }, - "type": "JsonWebKey2020" - } - ] - } - """) - }) - }) - @Operation(description = "Resolve the DID document for a given BPN", summary = "Resolve DID Document") + @GetDidResolveApiDocs @GetMapping(path = RestURI.DID_RESOLVE, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity getDidResolve(@Parameter(description = "BPN",examples = {@ExampleObject(name = "bpn", value = "BPNL000000000000", description = "bpn")}) @PathVariable(name = "bpn") String bpn) { + public ResponseEntity getDidResolve( + @BpnParameterDoc @PathVariable(name = "bpn") String bpn + ) { log.debug("Received request to get DID document for identifier: {}", bpn); return ResponseEntity.status(HttpStatus.OK).body(service.getDidDocument(bpn)); } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/HoldersCredentialController.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/HoldersCredentialController.java index 02d293d88..d2d17a20b 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/HoldersCredentialController.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/HoldersCredentialController.java @@ -21,16 +21,13 @@ package org.eclipse.tractusx.managedidentitywallets.controller; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.ExampleObject; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; + import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.eclipse.tractusx.managedidentitywallets.apidocs.HoldersCredentialControllerApiDocs.GetCredentialsApiDocs; +import org.eclipse.tractusx.managedidentitywallets.apidocs.HoldersCredentialControllerApiDocs.IssueCredentialApiDoc; import org.eclipse.tractusx.managedidentitywallets.constant.RestURI; import org.eclipse.tractusx.managedidentitywallets.service.HoldersCredentialService; import org.eclipse.tractusx.ssi.lib.model.verifiable.credential.VerifiableCredential; @@ -39,6 +36,9 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.tags.Tag; import java.security.Principal; import java.util.List; @@ -66,135 +66,8 @@ public class HoldersCredentialController extends BaseController { * @param sortTpe the sort tpe * @param principal the principal * @return the credentials - */ - @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "500", description = "Any other internal server error", content = {@Content(examples = { - @ExampleObject(name = "Internal server error", value = """ - { - "type": "about:blank", - "title": "Error Title", - "status": 500, - "detail": "Error Details", - "instance": "API endpoint", - "properties": { - "timestamp": 1689762476720 - } - } - """) - })}) - @ApiResponse(responseCode = "404", description = "Wallet not found with caller BPN", content = {@Content(examples = { - @ExampleObject(name = "Wallet not found with caller BPN", value = """ - { - "type": "about:blank", - "title": "Wallet not found for identifier did:web:localhost:BPNL0000000", - "status": 404, - "detail": "Wallet not found for identifier did:web:localhost:BPNL0000000", - "instance": "/api/wallets/did%3Aweb%3Alocalhost%3ABPNL0000000/credentials", - "properties": { - "timestamp": 1689765541959 - } - } - """) - })}) - @ApiResponse(responseCode = "400", description = "The input does not comply to the syntax requirements", content = { - @Content(examples = { - @ExampleObject(name = "Response in case of invalid data provided", value = """ - { - "type": "about:blank", - "title": "title", - "status": 400, - "detail": "details", - "instance": "API endpoint", - "properties": - { - "timestamp": 1689760833962, - "errors": - { - } - } - } - """) - }) - }) - @ApiResponse(responseCode = "200", description = "Credential list", content = { - @Content(examples = { - @ExampleObject(name = "Credential list", value = """ - { - "content": - [ - { - "@context": - [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/SummaryVC.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "id": "did:web:localhost:BPNL000000000000#954d43de-ebed-481d-9e35-e3bbb311b8f5", - "type": - [ - "VerifiableCredential", - "SummaryCredential" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "issuanceDate": "2023-07-14T11:05:48Z", - "expirationDate": "2023-09-30T18:30:00Z", - "credentialSubject": - [ - { - "contractTemplate": "https://public.catena-x.org/contracts/", - "holderIdentifier": "BPNL000000000000", - "id": "did:web:localhost:BPNL000000000000", - "items": - [ - "BpnCredential" - ], - "type": "SummaryCredential" - } - ], - "proof": - { - "created": "2023-07-14T11:05:50Z", - "jws": "eyJhbGciOiJFZERTQSJ9..4xwFUCtP0xXVEo5_lXd90Vv-TWO2FijZut-HZ5cozAQseexj8EpTkK1erhFbf2Ua1kb8pi_H5At5HiPkTxSIAQ", - "proofPurpose": "proofPurpose", - "type": "JsonWebSignature2020", - "verificationMethod": "did:web:localhost:BPNL000000000000#" - } - } - ], - "pageable": - { - "sort": - { - "empty": false, - "sorted": true, - "unsorted": false - }, - "offset": 0, - "pageNumber": 0, - "pageSize": 2147483647, - "paged": true, - "unpaged": false - }, - "totalElements": 1, - "totalPages": 1, - "last": true, - "size": 2147483647, - "number": 0, - "sort": - { - "empty": false, - "sorted": true, - "unsorted": false - }, - "first": true, - "numberOfElements": 1, - "empty": false - } - """) - }) - }) - @Operation(description = "Permission: **view_wallets** OR **view_wallet** (The BPN of holderIdentifier must equal BPN of caller)\n\n Search verifiable credentials with filter criteria", summary = "Query Verifiable Credentials") + */ + @GetCredentialsApiDocs @GetMapping(path = RestURI.CREDENTIALS, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity> getCredentials(@Parameter(name = "credentialId", description = "Credential Id", examples = {@ExampleObject(name = "Credential Id", value = "did:web:localhost:BPNL000000000000#12528899-160a-48bd-ba15-f396c3959ae9")}) @RequestParam(required = false) String credentialId, @Parameter(name = "issuerIdentifier", description = "Issuer identifier(did of BPN)", examples = {@ExampleObject(name = "bpn", value = "BPNL000000000000", description = "bpn"), @ExampleObject(description = "did", name = "did", value = "did:web:localhost:BPNL000000000000")}) @RequestParam(required = false) String issuerIdentifier, @@ -225,126 +98,9 @@ public ResponseEntity> getCredentials(@Parameter( * @param principal the principal * @return the response entity */ - @ApiResponse(responseCode = "201", description = "Success Response", content = {@Content(examples = { - @ExampleObject(name = "Success Response", value = """ - { - "@context": - [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "id": "did:web:localhost:BPNL000000000000#319a2641-9407-4c39-bf51-a4a109b59604", - "type": - [ - "VerifiableCredential", - "BankDetails" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "issuanceDate": "2023-07-19T13:41:52Z", - "expirationDate": "2024-12-31T18:30:00Z", - "credentialSubject": - [ - { - "bpn": "BPNL000000000000", - "bankName": "Dummy Bank", - "id": "did:web:localhost:BPNL000000000000", - "type": "BankDetails", - "accountNumber": "123456789" - } - ], - "proof": - { - "proofPurpose": "proofPurpose", - "verificationMethod": "did:web:localhost:BPNL000000000000#", - "type": "JsonWebSignature2020", - "created": "2023-07-19T13:41:54Z", - "jws": "eyJhbGciOiJFZERTQSJ9..fdqaAsPhQ5xZhQiRvWliDVXX-R9NzCvFXGUAOyQ8yE1hmf_4cvxS7JFuEojjsi3V-n66iiRCUFEXsnv56XPgDA" - } - } - """) - })}) - @ApiResponse(responseCode = "404", description = "Wallet not found with caller BPN", content = {@Content(examples = { - @ExampleObject(name = "Wallet not found with caller BPN", value = """ - { - "type": "about:blank", - "title": "Wallet not found for identifier did:web:localhost:BPNL0000000501", - "status": 404, - "detail": "Wallet not found for identifier did:web:localhost:BPNL0000000501", - "instance": "/api/wallets/did%3Aweb%3Alocalhost%3ABPNL0000000501", - "properties": { - "timestamp": 1689764377224 - } - } - """) - })}) - @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "500", description = "Any other internal server error", content = {@Content(examples = { - @ExampleObject(name = "Internal server error", value = """ - { - "type": "about:blank", - "title": "Error Title", - "status": 500, - "detail": "Error Details", - "instance": "API endpoint", - "properties": { - "timestamp": 1689762476720 - } - } - """) - })}) - @ApiResponse(responseCode = "400", description = "The input does not comply to the syntax requirements", content = { - @Content(examples = { - @ExampleObject(name = "Response in case of invalid data provided", value = """ - { - "type": "about:blank", - "title": "Invalid data provided", - "status": 400, - "detail": "details", - "instance": "API endpoint", - "properties": - { - "timestamp": 1689760833962, - "errors": - { - "filed": "filed error message" - } - } - } - """) - }) - }) - @Operation(summary = "Issue Verifiable Credential", description = "Permission: **update_wallets** OR **update_wallet** (The BPN of the issuer of the Verifiable Credential must equal BPN of caller)\nIssue a verifiable credential with a given issuer DID") + + @IssueCredentialApiDoc @PostMapping(path = RestURI.CREDENTIALS, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @io.swagger.v3.oas.annotations.parameters.RequestBody(content = { - @Content(examples = @ExampleObject(""" - { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "id": "did:web:localhost:BPNL000000000000#f73e3631-ba87-4a03-bea3-b28700056879", - "type": [ - "VerifiableCredential", - "BankDetails" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "expirationDate": "2024-12-31T18:30:00Z", - "issuanceDate": "2023-07-19T09:11:34Z", - "credentialSubject": [ - { - "bpn": "BPNL000000000000", - "id": "did:web:localhost:BPNL000000000000", - "type": "BankDetails", - "accountNumber": "123456789", - "bankName":"Dummy Bank" - } - ] - } - """)) - }) public ResponseEntity issueCredential(@RequestBody Map data, Principal principal) { log.debug("Received request to issue credential. BPN: {}", getBPNFromToken(principal)); return ResponseEntity.status(HttpStatus.CREATED).body(holdersCredentialService.issueCredential(data, getBPNFromToken(principal))); diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/IssuersCredentialController.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/IssuersCredentialController.java index 5e8f7b677..90ff993e3 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/IssuersCredentialController.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/IssuersCredentialController.java @@ -21,17 +21,20 @@ package org.eclipse.tractusx.managedidentitywallets.controller; -import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.ExampleObject; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; + +import org.eclipse.tractusx.managedidentitywallets.apidocs.IssuersCredentialControllerApiDocs.GetCredentialsApiDocs; +import org.eclipse.tractusx.managedidentitywallets.apidocs.IssuersCredentialControllerApiDocs.IssueDismantlerCredentialApiDoc; +import org.eclipse.tractusx.managedidentitywallets.apidocs.IssuersCredentialControllerApiDocs.IssueMembershipCredentialApiDoc; +import org.eclipse.tractusx.managedidentitywallets.apidocs.IssuersCredentialControllerApiDocs.IssueFrameworkCredentialApiDocs; +import org.eclipse.tractusx.managedidentitywallets.apidocs.IssuersCredentialControllerApiDocs.IssueVerifiableCredentialUsingBaseWalletApiDocs; +import org.eclipse.tractusx.managedidentitywallets.apidocs.IssuersCredentialControllerApiDocs.ValidateVerifiableCredentialApiDocs; import org.eclipse.tractusx.managedidentitywallets.constant.RestURI; import org.eclipse.tractusx.managedidentitywallets.dto.IssueDismantlerCredentialRequest; import org.eclipse.tractusx.managedidentitywallets.dto.IssueFrameworkCredentialRequest; @@ -81,169 +84,7 @@ public class IssuersCredentialController extends BaseController { * @param principal the principal * @return the credentials */ - @Tag(name = API_TAG_VERIFIABLE_CREDENTIAL_ISSUER) - @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "500", description = "Any other internal server error", content = {@Content(examples = { - @ExampleObject(name = "Internal server error", value = """ - { - "type": "about:blank", - "title": "Error Title", - "status": 500, - "detail": "Error Details", - "instance": "API endpoint", - "properties": { - "timestamp": 1689762476720 - } - } - """) - })}) - @ApiResponse(responseCode = "400", description = "The input does not comply to the syntax requirements", content = { - @Content(examples = { - @ExampleObject(name = "Response in case of invalid data provided", value = """ - { - "type": "about:blank", - "title": "title", - "status": 400, - "detail": "details", - "instance": "API endpoint", - "properties": - { - "timestamp": 1689760833962, - "errors": - { - } - } - } - """) - }) - }) - @ApiResponse(responseCode = "200", description = "Issuer credential list", content = { - @Content(examples = { - @ExampleObject(name = "Issuer credential list", value = """ - { - "content": [ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "id": "did:web:localhost:BPNL000000000000#ae364f71-f054-4d91-b579-f001bcb3e59e", - "type": [ - "VerifiableCredential", - "BpnCredential" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "issuanceDate": "2023-07-19T09:27:42Z", - "expirationDate": "2024-12-31T18:30:00Z", - "credentialSubject": [ - { - "bpn": "BPNL000000000000", - "id": "did:web:localhost:BPNL000000000000", - "type": "BpnCredential" - } - ], - "proof": { - "created": "2023-07-19T09:27:44Z", - "jws": "eyJhbGciOiJFZERTQSJ9..evDHQfW4EzJUt2HnS_WlmO8FFtywTGnwyywtCE7WP41my4Iscpqr4tbuVOqnZg85b4U8L3_ut8_pEONIhbExCQ", - "proofPurpose": "proofPurpose", - "type": "JsonWebSignature2020", - "verificationMethod": "did:web:localhost:BPNL000000000000#" - } - }, - { - "type": [ - "VerifiableCredential", - "SummaryCredential" - ], - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/SummaryVC.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "issuanceDate": "2023-07-19T09:11:39Z", - "expirationDate": "2024-12-31T18:30:00Z" - "credentialSubject": [ - { - "contractTemplate": "https://public.catena-x.org/contracts/", - "holderIdentifier": "BPNL000000000000", - "id": "did:web:localhost:BPNL000000000000", - "items": [ - "BpnCredential" - ], - "type": "SummaryCredential" - } - ], - "proof": { - "created": "2023-07-19T09:11:41Z", - "jws": "eyJhbGciOiJFZERTQSJ9..YvoFhDip3TQAfZUIu0yc843oA4uGTg049dMFt_GoaMmPjiNB_B1EFOL-gDpwjIxTYNlGOO_CLp9qStbzlDTNBg", - "proofPurpose": "proofPurpose", - "type": "JsonWebSignature2020", - "verificationMethod": "did:web:localhost:BPNL000000000000#" - } - }, - { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "id": "did:web:localhost:BPNL000000000000#f73e3631-ba87-4a03-bea3-b28700056879", - "type": [ - "VerifiableCredential", - "BpnCredential" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "issuanceDate": "2023-07-19T09:11:34Z", - "expirationDate": "2024-12-31T18:30:00Z", - "credentialSubject": [ - { - "bpn": "BPNL000000000000", - "id": "did:web:localhost:BPNL000000000000", - "type": "BpnCredential" - } - ], - "proof": { - "created": "2023-07-19T09:11:39Z", - "jws": "eyJhbGciOiJFZERTQSJ9..fdn2qU85auOltdHDLdHI7sJVV1ZPdftpiXd_ndXN0dFgSDWiIrScdD03wtvKLq_H-shQWfh2RYeMmrlEzAhfDw", - "proofPurpose": "proofPurpose", - "type": "JsonWebSignature2020", - "verificationMethod": "did:web:localhost:BPNL000000000000#" - } - } - ], - "pageable": { - "sort": { - "empty": false, - "unsorted": false, - "sorted": true - }, - "offset": 0, - "pageNumber": 0, - "pageSize": 2147483647, - "paged": true, - "unpaged": false - }, - "last": true, - "totalPages": 1, - "totalElements": 3, - "first": true, - "size": 2147483647, - "number": 0, - "sort": { - "empty": false, - "unsorted": false, - "sorted": true - }, - "numberOfElements": 3, - "empty": false - } - """) - }) - }) - @Operation(description = "Permission: **view_wallets** (The BPN of holderIdentifier must equal BPN of caller)\n\n Search verifiable credentials with filter criteria", summary = "Query Verifiable Credentials") + @GetCredentialsApiDocs @GetMapping(path = RestURI.ISSUERS_CREDENTIALS, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity> getCredentials(@Parameter(name = "credentialId", description = "Credential Id", examples = {@ExampleObject(name = "Credential Id", value = "did:web:localhost:BPNL000000000000#12528899-160a-48bd-ba15-f396c3959ae9")}) @RequestParam(required = false) String credentialId, @Parameter(name = "holderIdentifier", description = "Holder identifier(did of BPN)", examples = {@ExampleObject(name = "bpn", value = "BPNL000000000001", description = "bpn"), @ExampleObject(description = "did", name = "did", value = "did:web:localhost:BPNL000000000001")}) @RequestParam(required = false) String holderIdentifier, @@ -270,118 +111,7 @@ public ResponseEntity> getCredentials(@Parameter( * @param principal the principal * @return the response entity */ - @io.swagger.v3.oas.annotations.parameters.RequestBody(content = { - @Content(examples = @ExampleObject(""" - { - "bpn": "BPNL000000000000" - } - """)) - }) - @Tag(name = API_TAG_VERIFIABLE_CREDENTIAL_ISSUER) - @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "500", description = "Any other internal server error", content = {@Content(examples = { - @ExampleObject(name = "Internal server error", value = """ - { - "type": "about:blank", - "title": "Error Title", - "status": 500, - "detail": "Error Details", - "instance": "API endpoint", - "properties": { - "timestamp": 1689762476720 - } - } - """) - })}) - @ApiResponse(responseCode = "409", description = "The request could not be completed due to a conflict.", content = {@Content(examples = { - @ExampleObject(name = "MembershipCredential already exist", value = """ - { - "type": "about:blank", - "title": "Credential of type MembershipCredential is already exists ", - "status": 409, - "detail": "Credential of type MembershipCredential is already exists ", - "instance": "/api/credentials/issuer/membership", - "properties": { - "timestamp": 1689772483831 - } - } - """) - })}) - @ApiResponse(responseCode = "404", description = "Wallet not found with provided identifier", content = {@Content(examples = { - @ExampleObject(name = "Wallet not found with provided identifier", value = """ - { - "type": "about:blank", - "title": "Error Title", - "status": 404, - "detail": "Error Details", - "instance": "API endpoint", - "properties": { - "timestamp": 1689762476720 - } - } - """) - })}) - @ApiResponse(responseCode = "400", description = "The input does not comply to the syntax requirements", content = { - @Content(examples = { - @ExampleObject(name = "Response in case of invalid data provided", value = """ - { - "type": "about:blank", - "title": "Invalid data provided", - "status": 400, - "detail": "details", - "instance": "API endpoint", - "properties": - { - "timestamp": 1689760833962, - "errors": - { - "filed": "filed error message" - } - } - } - """) - }) - }) - @ApiResponse(responseCode = "201", description = "Issuer credential", content = { - @Content(examples = { - @ExampleObject(name = "Membership credential", value = """ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "id": "did:web:localhost:BPNL000000000000#0d6b6447-99de-4bc5-94f3-3ac0ae8ee188", - "type": [ - "VerifiableCredential", - "MembershipCredential" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "issuanceDate": "2023-07-19T13:13:53Z", - "expirationDate": "2024-12-31T18:30:00Z", - "credentialSubject": [ - { - "holderIdentifier": "BPNL000000000000", - "startTime": "2023-07-19T13:13:53.581081Z", - "memberOf": "Catena-X", - "id": "did:web:localhost:BPNL000000000000", - "type": "MembershipCredential", - "status": "Active" - } - ], - "proof": { - "proofPurpose": "proofPurpose", - "verificationMethod": "did:web:localhost:BPNL000000000000#", - "type": "JsonWebSignature2020", - "created": "2023-07-19T13:13:57Z", - "jws": "eyJhbGciOiJFZERTQSJ9..zt7SyONY1shO7N6KrabQJr9uNrToM1Bc4eagTQc1LxAfZ1v-SSp9Y-2cpZNDV8AR08r4L8VbtWrR9t2dNoAfDw" - } - } - """) - }) - }) - @Operation(summary = "Issue a Membership Verifiable Credential with base wallet issuer", description = "Permission: **update_wallets** (The BPN of base wallet must equal BPN of caller)\n\n Issue a verifiable credential by base wallet") + @IssueMembershipCredentialApiDoc @PostMapping(path = RestURI.CREDENTIALS_ISSUER_MEMBERSHIP, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity issueMembershipCredential(@Valid @RequestBody IssueMembershipCredentialRequest issueMembershipCredentialRequest, Principal principal) { log.debug("Received request to issue membership credential. BPN: {}", getBPNFromToken(principal)); @@ -395,458 +125,21 @@ public ResponseEntity issueMembershipCredential(@Valid @Re * @param principal the principal * @return the response entity */ - @io.swagger.v3.oas.annotations.parameters.RequestBody(content = { - @Content(examples = @ExampleObject(""" - { - "bpn": "BPNL000000000000", - "activityType": "vehicleDismantle", - "allowedVehicleBrands": [ - "Audi", "Abarth", "Alfa Romeo", "Chrysler" - ] - } - """)) - }) - @Tag(name = API_TAG_VERIFIABLE_CREDENTIAL_ISSUER) - @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "500", description = "Any other internal server error", content = {@Content(examples = { - @ExampleObject(name = "Internal server error", value = """ - { - "type": "about:blank", - "title": "Error Title", - "status": 500, - "detail": "Error Details", - "instance": "API endpoint", - "properties": { - "timestamp": 1689762476720 - } - } - """) - })}) - @ApiResponse(responseCode = "409", description = "The request could not be completed due to a conflict.", content = {@Content(examples = { - @ExampleObject(name = "DismantlerCredential already exist", value = """ - { - "type": "about:blank", - "title": "Credential of type DismantlerCredential is already exists ", - "status": 409, - "detail": "Credential of type DismantlerCredential is already exists ", - "instance": "/api/credentials/issuer/dismantler", - "properties": { - "timestamp": 1689773804746 - } - } - """) - })}) - @ApiResponse(responseCode = "404", description = "Wallet not found with provided identifier", content = {@Content(examples = { - @ExampleObject(name = "Wallet not found with provided identifier", value = """ - { - "type": "about:blank", - "title": "Error Title", - "status": 404, - "detail": "Error Details", - "instance": "API endpoint", - "properties": { - "timestamp": 1689762476720 - } - } - """) - })}) - @ApiResponse(responseCode = "400", description = "The input does not comply to the syntax requirements", content = { - @Content(examples = { - @ExampleObject(name = "Response in case of invalid data provided", value = """ - { - "type": "about:blank", - "title": "Invalid data provided", - "status": 400, - "detail": "details", - "instance": "API endpoint", - "properties": - { - "timestamp": 1689760833962, - "errors": - { - "filed": "filed error message" - } - } - } - """) - }) - }) - @ApiResponse(responseCode = "201", description = "Dismantler Credential", content = { - @Content(examples = { - @ExampleObject(name = "Dismantler Credential", value = """ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "id": "did:web:localhost:BPNL000000000000#5caac86c-8ef8-4aab-9d2b-fb18c62560a9", - "type": [ - "VerifiableCredential", - "DismantlerCredential" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "issuanceDate": "2023-07-19T13:35:33Z", - "expirationDate": "2024-12-31T18:30:00Z", - "credentialSubject": [ - { - "holderIdentifier": "BPNL000000000000", - "allowedVehicleBrands": [ - "Audi", - "Abarth", - "Alfa Romeo", - "Chrysler" - ], - "id": "did:web:localhost:BPNL000000000000", - "activityType": "vehicleDismantle", - "type": "DismantlerCredential" - } - ], - "proof": { - "proofPurpose": "proofPurpose", - "verificationMethod": "did:web:localhost:BPNL000000000000#", - "type": "JsonWebSignature2020", - "created": "2023-07-19T13:35:38Z", - "jws": "eyJhbGciOiJFZERTQSJ9..UI82uq6iyqoaKjZIhJiV24v_Bqnj_7EqWiqZ3VWjqkoHLnr7JDtW5KVywWPl27j_baLBxxnM5jqjQdSK4rfbBg" - } - } - """) - }) - }) - @Operation(summary = "Issue a Dismantler Verifiable Credential with base wallet issuer", description = "Permission: **update_wallets** (The BPN of base wallet must equal BPN of caller)\n\n Issue a verifiable credential by base wallet") + @IssueDismantlerCredentialApiDoc @PostMapping(path = RestURI.CREDENTIALS_ISSUER_DISMANTLER, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity issueDismantlerCredential(@Valid @RequestBody IssueDismantlerCredentialRequest request, Principal principal) { log.debug("Received request to issue dismantler credential. BPN: {}", getBPNFromToken(principal)); return ResponseEntity.status(HttpStatus.CREATED).body(issuersCredentialService.issueDismantlerCredential(request, getBPNFromToken(principal))); } - /** + /** * Issue framework credential response entity. * * @param request the request * @param principal the principal * @return the response entity */ - - @io.swagger.v3.oas.annotations.parameters.RequestBody( - content = { - @Content(examples = { - @ExampleObject(name = "BehaviorTwinCredential", value = """ - { - "holderIdentifier": "BPNL000000000000", - "type": "BehaviorTwinCredential", - "contract-template": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", - "contract-version": "1.0.0" - } - """), - @ExampleObject(name = "PcfCredential", value = """ - { - "holderIdentifier": "BPNL000000000000", - "type": "PcfCredential", - "contract-template": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", - "contract-version": "1.0.0" - } - """), - @ExampleObject(name = "SustainabilityCredential", value = """ - { - "holderIdentifier": "BPNL000000000000", - "type": "SustainabilityCredential", - "contract-template": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", - "contract-version": "1.0.0" - } - """), - @ExampleObject(name = "QualityCredential", value = """ - { - "holderIdentifier": "BPNL000000000000", - "type": "QualityCredential", - "contract-template": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", - "contract-version": "1.0.0" - } - """), - @ExampleObject(name = "TraceabilityCredential", value = """ - { - "holderIdentifier": "BPNL000000000000", - "type": "TraceabilityCredential", - "contract-template": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", - "contract-version": "1.0.0" - } - """), - @ExampleObject(name = "BehaviorTwinCredential", value = """ - { - "holderIdentifier": "BPNL000000000000", - "type": "BehaviorTwinCredential", - "contract-template": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", - "contract-version": "1.0.0" - } - """), - @ExampleObject(name = "ResiliencyCredential", value = """ - { - "holderIdentifier": "BPNL000000000000", - "type": "ResiliencyCredential", - "contract-template": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", - "contract-version": "1.0.0" - } - """) - - }) - } - ) - @Tag(name = API_TAG_VERIFIABLE_CREDENTIAL_ISSUER) - @Operation(summary = "Issue a Use Case Verifiable Credential with base wallet issuer", description = "Permission: **update_wallets** (The BPN of base wallet must equal BPN of caller)\n\n Issue a verifiable credential by base wallet") - @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "500", description = "Any other internal server error", content = {@Content(examples = { - @ExampleObject(name = "Internal server error", value = """ - { - "type": "about:blank", - "title": "Error Title", - "status": 500, - "detail": "Error Details", - "instance": "API endpoint", - "properties": { - "timestamp": 1689762476720 - } - } - """) - })}) - @ApiResponse(responseCode = "404", description = "Wallet not found with provided identifier", content = {@Content(examples = { - @ExampleObject(name = "Wallet not found with provided identifier", value = """ - { - "type": "about:blank", - "title": "Error Title", - "status": 404, - "detail": "Error Details", - "instance": "API endpoint", - "properties": { - "timestamp": 1689762476720 - } - } - """) - })}) - @ApiResponse(responseCode = "400", description = "The input does not comply to the syntax requirements", content = { - @Content(examples = { - @ExampleObject(name = "Response in case of invalid data provided", value = """ - { - "type": "about:blank", - "title": "Invalid data provided", - "status": 400, - "detail": "details", - "instance": "API endpoint", - "properties": - { - "timestamp": 1689760833962, - "errors": - { - "filed": "filed error message" - } - } - } - """) - }) - }) - @ApiResponse(responseCode = "201", description = "Framework credential", content = { - @Content(examples = { - @ExampleObject(name = "BehaviorTwin credential", value = """ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "id": "did:web:localhost:BPNL000000000000#46a8c5e6-b195-4ec9-85cd-665c57d296ab", - "type": [ - "VerifiableCredential", - "UseCaseFrameworkCondition" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "issuanceDate": "2023-07-19T13:49:58Z", - "expirationDate": "2024-12-31T18:30:00Z", - "credentialSubject": [ - { - "holderIdentifier": "BPNL000000000000", - "id": "did:web:localhost:BPNL000000000000", - "type": "BehaviorTwinCredential", - "contractTemplate": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", - "contractVersion": "1.0.0" - } - ], - "proof": { - "proofPurpose": "proofPurpose", - "type": "JsonWebSignature2020", - "verificationMethod": "did:web:localhost:BPNL000000000000#", - "created": "2023-07-19T13:50:02Z", - "jws": "eyJhbGciOiJFZERTQSJ9..IkfgC6Gn9sOT1uu1zMiDIIqw6pV4Z8axkKvphegsCVWT9uo0HZp4J9L1ILxR-huINGR5QlGIKiVuLGB5kKDOAQ" - } - } - """), - @ExampleObject(name = "Pcf Credential", value = """ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "id": "did:web:localhost:BPNL000000000000#46a8c5e6-b195-4ec9-85cd-665c57d296ab", - "type": [ - "VerifiableCredential", - "UseCaseFrameworkCondition" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "issuanceDate": "2023-07-19T13:49:58Z", - "expirationDate": "2024-12-31T18:30:00Z", - "credentialSubject": [ - { - "holderIdentifier": "BPNL000000000000", - "id": "did:web:localhost:BPNL000000000000", - "type": "PcfCredential", - "contractTemplate": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", - "contractVersion": "1.0.0" - } - ], - "proof": { - "proofPurpose": "proofPurpose", - "type": "JsonWebSignature2020", - "verificationMethod": "did:web:localhost:BPNL000000000000#", - "created": "2023-07-19T13:50:02Z", - "jws": "eyJhbGciOiJFZERTQSJ9..IkfgC6Gn9sOT1uu1zMiDIIqw6pV4Z8axkKvphegsCVWT9uo0HZp4J9L1ILxR-huINGR5QlGIKiVuLGB5kKDOAQ" - } - } - """), - @ExampleObject(name = "Sustainability Credential", value = """ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "id": "did:web:localhost:BPNL000000000000#46a8c5e6-b195-4ec9-85cd-665c57d296ab", - "type": [ - "VerifiableCredential", - "UseCaseFrameworkCondition" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "issuanceDate": "2023-07-19T13:49:58Z", - "expirationDate": "2024-12-31T18:30:00Z", - "credentialSubject": [ - { - "holderIdentifier": "BPNL000000000000", - "id": "did:web:localhost:BPNL000000000000", - "type": "SustainabilityCredential", - "contractTemplate": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", - "contractVersion": "1.0.0" - } - ], - "proof": { - "proofPurpose": "proofPurpose", - "type": "JsonWebSignature2020", - "verificationMethod": "did:web:localhost:BPNL000000000000#", - "created": "2023-07-19T13:50:02Z", - "jws": "eyJhbGciOiJFZERTQSJ9..IkfgC6Gn9sOT1uu1zMiDIIqw6pV4Z8axkKvphegsCVWT9uo0HZp4J9L1ILxR-huINGR5QlGIKiVuLGB5kKDOAQ" - } - } - """), - @ExampleObject(name = "Quality Credential", value = """ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "id": "did:web:localhost:BPNL000000000000#46a8c5e6-b195-4ec9-85cd-665c57d296ab", - "type": [ - "VerifiableCredential", - "UseCaseFrameworkCondition" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "issuanceDate": "2023-07-19T13:49:58Z", - "expirationDate": "2024-12-31T18:30:00Z", - "credentialSubject": [ - { - "holderIdentifier": "BPNL000000000000", - "id": "did:web:localhost:BPNL000000000000", - "type": "QualityCredential", - "contractTemplate": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", - "contractVersion": "1.0.0" - } - ], - "proof": { - "proofPurpose": "proofPurpose", - "type": "JsonWebSignature2020", - "verificationMethod": "did:web:localhost:BPNL000000000000#", - "created": "2023-07-19T13:50:02Z", - "jws": "eyJhbGciOiJFZERTQSJ9..IkfgC6Gn9sOT1uu1zMiDIIqw6pV4Z8axkKvphegsCVWT9uo0HZp4J9L1ILxR-huINGR5QlGIKiVuLGB5kKDOAQ" - } - } - """), - @ExampleObject(name = "Traceability Credential", value = """ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "id": "did:web:localhost:BPNL000000000000#46a8c5e6-b195-4ec9-85cd-665c57d296ab", - "type": [ - "VerifiableCredential", - "UseCaseFrameworkCondition" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "issuanceDate": "2023-07-19T13:49:58Z", - "expirationDate": "2024-12-31T18:30:00Z", - "credentialSubject": [ - { - "holderIdentifier": "BPNL000000000000", - "id": "did:web:localhost:BPNL000000000000", - "type": "TraceabilityCredential", - "contractTemplate": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", - "contractVersion": "1.0.0" - } - ], - "proof": { - "proofPurpose": "proofPurpose", - "type": "JsonWebSignature2020", - "verificationMethod": "did:web:localhost:BPNL000000000000#", - "created": "2023-07-19T13:50:02Z", - "jws": "eyJhbGciOiJFZERTQSJ9..IkfgC6Gn9sOT1uu1zMiDIIqw6pV4Z8axkKvphegsCVWT9uo0HZp4J9L1ILxR-huINGR5QlGIKiVuLGB5kKDOAQ" - } - } - """), - @ExampleObject(name = "Resiliency Credential", value = """ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "id": "did:web:localhost:BPNL000000000000#46a8c5e6-b195-4ec9-85cd-665c57d296ab", - "type": [ - "VerifiableCredential", - "UseCaseFrameworkCondition" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "issuanceDate": "2023-07-19T13:49:58Z", - "expirationDate": "2024-12-31T18:30:00Z", - "credentialSubject": [ - { - "holderIdentifier": "BPNL000000000000", - "id": "did:web:localhost:BPNL000000000000", - "type": "ResiliencyCredential", - "contractTemplate": "https://public.catena-x.org/contracts/traceabilty.v1.pdf", - "contractVersion": "1.0.0" - } - ], - "proof": { - "proofPurpose": "proofPurpose", - "type": "JsonWebSignature2020", - "verificationMethod": "did:web:localhost:BPNL000000000000#", - "created": "2023-07-19T13:50:02Z", - "jws": "eyJhbGciOiJFZERTQSJ9..IkfgC6Gn9sOT1uu1zMiDIIqw6pV4Z8axkKvphegsCVWT9uo0HZp4J9L1ILxR-huINGR5QlGIKiVuLGB5kKDOAQ" - } - } - """) - }) - }) + @IssueFrameworkCredentialApiDocs @PostMapping(path = RestURI.API_CREDENTIALS_ISSUER_FRAMEWORK, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity issueFrameworkCredential(@Valid @RequestBody IssueFrameworkCredentialRequest request, Principal principal) { log.debug("Received request to issue framework credential. BPN: {}", getBPNFromToken(principal)); @@ -860,200 +153,8 @@ public ResponseEntity issueFrameworkCredential(@Valid @Req * @param withCredentialExpiryDate the with credential expiry date * @return the response entity */ - @Tag(name = API_TAG_VERIFIABLE_CREDENTIAL_VALIDATION) - @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "500", description = "Any other internal server error", content = {@Content(examples = { - @ExampleObject(name = "Internal server error", value = """ - { - "type": "about:blank", - "title": "Error Title", - "status": 500, - "detail": "Error Details", - "instance": "API endpoint", - "properties": { - "timestamp": 1689762476720 - } - } - """) - })}) - @ApiResponse(responseCode = "200", description = "Validate Verifiable Credentials", content = { - @Content(examples = { - @ExampleObject(name = "Verifiable Credentials without check expiry", value = """ - { - "valid": true, - "vc": { - "issuanceDate": "2023-07-19T09:11:34Z", - "credentialSubject": [ - { - "bpn": "BPNL000000000000", - "id": "did:web:localhost:BPNL000000000000", - "type": "BpnCredential" - } - ], - "id": "did:web:localhost:BPNL000000000000#f73e3631-ba87-4a03-bea3-b28700056879", - "proof": { - "created": "2023-07-19T09:11:39Z", - "jws": "eyJhbGciOiJFZERTQSJ9..fdn2qU85auOltdHDLdHI7sJVV1ZPdftpiXd_ndXN0dFgSDWiIrScdD03wtvKLq_H-shQWfh2RYeMmrlEzAhfDw", - "proofPurpose": "proofPurpose", - "type": "JsonWebSignature2020", - "verificationMethod": "did:web:localhost:BPNL000000000000#" - }, - "type": [ - "VerifiableCredential", - "BpnCredential" - ], - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "expirationDate": "2024-12-31T18:30:00Z" - } - } - """), - @ExampleObject(name = "Verifiable Credentials with check expiry", value = """ - { - "valid": true, - "validateExpiryDate": true, - "vc": { - "issuanceDate": "2023-07-19T09:11:34Z", - "credentialSubject": [ - { - "bpn": "BPNL000000000000", - "id": "did:web:localhost:BPNL000000000000", - "type": "BpnCredential" - } - ], - "id": "did:web:localhost:BPNL000000000000#f73e3631-ba87-4a03-bea3-b28700056879", - "proof": { - "created": "2023-07-19T09:11:39Z", - "jws": "eyJhbGciOiJFZERTQSJ9..fdn2qU85auOltdHDLdHI7sJVV1ZPdftpiXd_ndXN0dFgSDWiIrScdD03wtvKLq_H-shQWfh2RYeMmrlEzAhfDw", - "proofPurpose": "proofPurpose", - "type": "JsonWebSignature2020", - "verificationMethod": "did:web:localhost:BPNL000000000000#" - }, - "type": [ - "VerifiableCredential", - "BpnCredential" - ], - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "expirationDate": "2024-12-31T18:30:00Z" - } - } - """), - @ExampleObject(name = "Verifiable expired credentials with check expiry ", value = """ - { - "valid": false, - "validateExpiryDate": false, - "vc": { - "issuanceDate": "2023-07-19T09:11:34Z", - "credentialSubject": [ - { - "bpn": "BPNL000000000000", - "id": "did:web:localhost:BPNL000000000000", - "type": "BpnCredential" - } - ], - "id": "did:web:localhost:BPNL000000000000#f73e3631-ba87-4a03-bea3-b28700056879", - "proof": { - "created": "2023-07-19T09:11:39Z", - "jws": "eyJhbGciOiJFZERTQSJ9..fdn2qU85auOltdHDLdHI7sJVV1ZPdftpiXd_ndXN0dFgSDWiIrScdD03wtvKLq_H-shQWfh2RYeMmrlEzAhfDw", - "proofPurpose": "proofPurpose", - "type": "JsonWebSignature2020", - "verificationMethod": "did:web:localhost:BPNL000000000000#" - }, - "type": [ - "VerifiableCredential", - "BpnCredential" - ], - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "expirationDate": "2022-12-31T18:30:00Z" - } - } - """), - @ExampleObject(name = "Verifiable Credentials with invalid signature", value = """ - { - "valid": false, - "vc": { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "id": "did:web:localhost:BPNL000000000000#f73e3631-ba87-4a03-bea3-b28700056879", - "type": [ - "VerifiableCredential", - "BpnCredential" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "expirationDate": "2024-12-31T18:30:00Z" - "issuanceDate": "2023-07-19T09:11:34Z", - "credentialSubject": [ - { - "bpn": "BPNL000000000000", - "id": "did:web:localhost:BPNL000000000000", - "type": "BpnCredential" - } - ], - "proof": { - "created": "2023-07-19T09:11:39Z", - "jws": "eyJhbGciOiJFZERTQSJ9..fdn2qU85auOltdHDLdHI7sJVV1ZPdftpiXd_ndXN0dFgSDWiIrScdD03wtvKLq_H-shQWfh2RYeMmrlEzAhf", - "proofPurpose": "proofPurpose", - "type": "JsonWebSignature2020", - "verificationMethod": "did:web:localhost:BPNL000000000000#" - }, - } - } - """) - }) - }) - @Operation(summary = "Validate Verifiable Credentials", description = "Permission: **view_wallets** OR **view_wallet** \n\n Validate Verifiable Credentials") @PostMapping(path = RestURI.CREDENTIALS_VALIDATION, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @io.swagger.v3.oas.annotations.parameters.RequestBody(content = { - @Content(examples = @ExampleObject(""" - { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "id": "did:web:localhost:BPNL000000000000#f73e3631-ba87-4a03-bea3-b28700056879", - "type": [ - "VerifiableCredential", - "BpnCredential" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "issuanceDate": "2023-07-19T09:11:34Z", - "expirationDate": "2024-12-31T18:30:00Z", - "credentialSubject": [ - { - "bpn": "BPNL000000000000", - "id": "did:web:localhost:BPNL000000000000", - "type": "BpnCredential" - } - ], - "proof": { - "created": "2023-07-19T09:11:39Z", - "jws": "eyJhbGciOiJFZERTQSJ9..fdn2qU85auOltdHDLdHI7sJVV1ZPdftpiXd_ndXN0dFgSDWiIrScdD03wtvKLq_H-shQWfh2RYeMmrlEzAhfDw", - "proofPurpose": "proofPurpose", - "type": "JsonWebSignature2020", - "verificationMethod": "did:web:localhost:BPNL000000000000#" - } - } - """)) - }) + @ValidateVerifiableCredentialApiDocs public ResponseEntity> credentialsValidation(@RequestBody Map data, @Parameter(description = "Check expiry of VC") @RequestParam(name = "withCredentialExpiryDate", defaultValue = "false", required = false) boolean withCredentialExpiryDate) { log.debug("Received request to validate verifiable credentials"); @@ -1068,121 +169,8 @@ public ResponseEntity> credentialsValidation(@RequestBody Ma * @param principal the principal * @return the response entity */ - @Tag(name = API_TAG_VERIFIABLE_CREDENTIAL_ISSUER) - @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "500", description = "Any other internal server error", content = {@Content(examples = { - @ExampleObject(name = "Internal server error", value = """ - { - "type": "about:blank", - "title": "Error Title", - "status": 500, - "detail": "Error Details", - "instance": "API endpoint", - "properties": { - "timestamp": 1689762476720 - } - } - """) - })}) - @ApiResponse(responseCode = "404", description = "Wallet not found with provided identifier", content = {@Content(examples = { - @ExampleObject(name = "Wallet not found with provided identifier", value = """ - { - "type": "about:blank", - "title": "Error Title", - "status": 404, - "detail": "Error Details", - "instance": "API endpoint", - "properties": { - "timestamp": 1689762476720 - } - } - """) - })}) - @ApiResponse(responseCode = "400", description = "The input does not comply to the syntax requirements", content = { - @Content(examples = { - @ExampleObject(name = "Response in case of invalid data provided", value = """ - { - "type": "about:blank", - "title": "Invalid data provided", - "status": 400, - "detail": "details", - "instance": "API endpoint", - "properties": - { - "timestamp": 1689760833962, - "errors": - { - "filed": "filed error message" - } - } - } - """) - }) - }) - @ApiResponse(responseCode = "201", description = "Issuer credential", content = { - @Content(examples = { - @ExampleObject(name = "Issuer credential", value = """ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "id": "did:web:localhost:BPNL000000000000#ff084e7a-1b46-4a2f-a78d-3d701a0bd6e4", - "type": [ - "VerifiableCredential", - "BpnCredential" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "issuanceDate": "2023-07-19T12:18:30Z", - "expirationDate": "2024-12-31T18:30:00Z", - "credentialSubject": [ - { - "bpn": "BPNL000000000000", - "id": "did:web:localhost:BPNL000000000000", - "type": "BpnCredential" - } - ], - "proof": { - "proofPurpose": "proofPurpose", - "type": "JsonWebSignature2020", - "verificationMethod": "did:web:localhost:BPNL000000000000#", - "created": "2023-07-19T12:18:34Z", - "jws": "eyJhbGciOiJFZERTQSJ9..0Ua1vcTQAYwQY3PPuHr4RQxqW6iIngrHQQx1oPgk2uzqUpcbfY2YUxXAnbNA333-lSuvNhiV_1NLfBnCEcI2DQ" - } - } - """) - }) - }) - @Operation(summary = "Issue Verifiable Credential", description = "Permission: **update_wallets** (The BPN of the base wallet must equal BPN of caller)\nIssue a verifiable credential with a given issuer DID") @PostMapping(path = RestURI.ISSUERS_CREDENTIALS, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @io.swagger.v3.oas.annotations.parameters.RequestBody(content = { - @Content(examples = @ExampleObject(""" - { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "id": "did:web:localhost:BPNL000000000000#f73e3631-ba87-4a03-bea3-b28700056879", - "type": [ - "VerifiableCredential", - "BpnCredential" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "issuanceDate": "2023-07-19T09:11:34Z", - "expirationDate": "2024-12-31T18:30:00Z", - "credentialSubject": [ - { - "bpn": "BPNL000000000000", - "id": "did:web:localhost:BPNL000000000000", - "type": "BpnCredential" - } - ] - } - """)) - }) + @IssueVerifiableCredentialUsingBaseWalletApiDocs public ResponseEntity issueCredentialUsingBaseWallet(@Parameter(description = "Holder DID", examples = {@ExampleObject(description = "did", name = "did", value = "did:web:localhost:BPNL000000000000")}) @RequestParam(name = "holderDid") String holderDid, @RequestBody Map data, Principal principal) { log.debug("Received request to issue verifiable credential. BPN: {}", getBPNFromToken(principal)); return ResponseEntity.status(HttpStatus.CREATED).body(issuersCredentialService.issueCredentialUsingBaseWallet(holderDid, data, getBPNFromToken(principal))); diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/PresentationController.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/PresentationController.java index 5fc63c9c0..fe052f5cf 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/PresentationController.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/PresentationController.java @@ -21,14 +21,12 @@ package org.eclipse.tractusx.managedidentitywallets.controller; -import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.ExampleObject; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; + +import org.eclipse.tractusx.managedidentitywallets.apidocs.PresentationControllerApiDocs.PostVerifiablePresentationApiDocs; +import org.eclipse.tractusx.managedidentitywallets.apidocs.PresentationControllerApiDocs.PostVerifiablePresentationValidationApiDocs; import org.eclipse.tractusx.managedidentitywallets.constant.RestURI; import org.eclipse.tractusx.managedidentitywallets.service.PresentationService; import org.springframework.http.HttpStatus; @@ -63,130 +61,8 @@ public class PresentationController extends BaseController { * @param principal the principal * @return the response entity */ - @Tag(name = API_TAG_VERIFIABLE_PRESENTATIONS_GENERATION) - @Operation(summary = "Create Verifiable Presentation", description = "Permission: **update_wallets** OR **update_wallet** (The BPN of the issuer of the Verifiable Presentation must equal to BPN of caller) \n\n Create a verifiable presentation from a list of verifiable credentials, signed by the holder") - @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "500", description = "Any other internal server error", content = {@Content(examples = { - @ExampleObject(name = "Internal server error", value = """ - { - "type": "about:blank", - "title": "Error Title", - "status": 500, - "detail": "Error Details", - "instance": "API endpoint", - "properties": { - "timestamp": 1689762476720 - } - } - """) - })}) - @ApiResponse(responseCode = "404", description = "Wallet not found with provided identifier", content = {@Content(examples = { - @ExampleObject(name = "Wallet not found with provided identifier", value = """ - { - "type": "about:blank", - "title": "Error Title", - "status": 404, - "detail": "Error Details", - "instance": "API endpoint", - "properties": { - "timestamp": 1689762476720 - } - } - """) - })}) - @ApiResponse(responseCode = "200", description = "Verifiable Presentation", content = { - @Content(examples = { - @ExampleObject(name = "VP as Json-LD", value = """ - { - "vp": { - "@context": [ - "https://www.w3.org/2018/credentials/v1" - ], - "id": "did:web:localhost:BPNL000000000000#b2e69e47-95f3-48ff-af30-eaaab36431d5", - "type": [ - "VerifiablePresentation" - ], - "verifiableCredential": [ - { - "id": "did:web:localhost:BPNL000000000000#f73e3631-ba87-4a03-bea3-b28700056879", - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "type": [ - "VerifiableCredential", - "BpnCredential" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "expirationDate": "2024-12-31T18:30:00Z", - "issuanceDate": "2023-07-19T09:11:34Z", - "credentialSubject": [ - { - "bpn": "BPNL000000000000", - "id": "did:web:localhost:BPNL000000000000", - "type": "BpnCredential" - } - ], - "proof": { - "created": "2023-07-19T09:11:39Z", - "jws": "eyJhbGciOiJFZERTQSJ9..fdn2qU85auOltdHDLdHI7sJVV1ZPdftpiXd_ndXN0dFgSDWiIrScdD03wtvKLq_H-shQWfh2RYeMmrlEzAhfDw", - "proofPurpose": "proofPurpose", - "type": "JsonWebSignature2020", - "verificationMethod": "did:web:localhost:BPNL000000000000#" - } - } - ] - } - } - """), - @ExampleObject(name = "VP as JWT", value = """ - { - "vp": "eyJraWQiOiJkaWQ6d2ViOmxvY2FsaG9zdDpCUE5MMDAwMDAwMDAwMDAwIiwidHlwIjoiSldUIiwiYWxnIjoiRWREU0EifQ.eyJzdWIiOiJkaWQ6d2ViOmxvY2FsaG9zdDpCUE5MMDAwMDAwMDAwMDAwIiwiYXVkIjoic21hcnQiLCJpc3MiOiJkaWQ6d2ViOmxvY2FsaG9zdDpCUE5MMDAwMDAwMDAwMDAwIiwidnAiOnsiaWQiOiJkaWQ6d2ViOmxvY2FsaG9zdDpCUE5MMDAwMDAwMDAwMDAwIzM4ZTU2ZTg1LTNkODQtNGEyNS1iZjg1LWFiMjRlYzY4MmMwOSIsInR5cGUiOlsiVmVyaWZpYWJsZVByZXNlbnRhdGlvbiJdLCJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJ2ZXJpZmlhYmxlQ3JlZGVudGlhbCI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vY2F0ZW5heC1uZy5naXRodWIuaW8vcHJvZHVjdC1jb3JlLXNjaGVtYXMvYnVzaW5lc3NQYXJ0bmVyRGF0YS5qc29uIiwiaHR0cHM6Ly93M2lkLm9yZy9zZWN1cml0eS9zdWl0ZXMvandzLTIwMjAvdjEiXSwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCIsIkJwbkNyZWRlbnRpYWwiXSwiaWQiOiJkaWQ6d2ViOmxvY2FsaG9zdDpCUE5MMDAwMDAwMDAwMDAwI2Y3M2UzNjMxLWJhODctNGEwMy1iZWEzLWIyODcwMDA1Njg3OSIsImlzc3VlciI6ImRpZDp3ZWI6bG9jYWxob3N0OkJQTkwwMDAwMDAwMDAwMDAiLCJpc3N1YW5jZURhdGUiOiIyMDIzLTA3LTE5VDA5OjExOjM0WiIsImV4cGlyYXRpb25EYXRlIjoiMjAyNC0xMi0zMVQxODozMDowMFoiLCJjcmVkZW50aWFsU3ViamVjdCI6eyJpZCI6ImRpZDp3ZWI6bG9jYWxob3N0OkJQTkwwMDAwMDAwMDAwMDAiLCJicG4iOiJCUE5MMDAwMDAwMDAwMDAwIiwidHlwZSI6IkJwbkNyZWRlbnRpYWwifSwicHJvb2YiOnsicHJvb2ZQdXJwb3NlIjoicHJvb2ZQdXJwb3NlIiwidHlwZSI6Ikpzb25XZWJTaWduYXR1cmUyMDIwIiwidmVyaWZpY2F0aW9uTWV0aG9kIjoiZGlkOndlYjpsb2NhbGhvc3Q6QlBOTDAwMDAwMDAwMDAwMCMiLCJjcmVhdGVkIjoiMjAyMy0wNy0xOVQwOToxMTozOVoiLCJqd3MiOiJleUpoYkdjaU9pSkZaRVJUUVNKOS4uZmRuMnFVODVhdU9sdGRIRExkSEk3c0pWVjFaUGRmdHBpWGRfbmRYTjBkRmdTRFdpSXJTY2REMDN3dHZLTHFfSC1zaFFXZmgyUlllTW1ybEV6QWhmRHcifX19LCJleHAiOjE2ODk4MzQ4MDUsImp0aSI6ImIwODYzOWZiLWQ5MWEtNGUwZS1iNmY4LTYzYjdhMzQ1ZTRhZiJ9.80x0AB-OauefdeZfx1cwhitdVKRvCRFeFzYwU73DL7y4w34vu6BdfHWLBGjkwELxkQEoFfiTPOqtuyqhtsyDBg" - } - """) - }) - }) + @PostVerifiablePresentationApiDocs @PostMapping(path = RestURI.API_PRESENTATIONS, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @io.swagger.v3.oas.annotations.parameters.RequestBody(content = { - @Content(examples = @ExampleObject(""" - { - "verifiableCredentials": - [ - { - "id": "did:web:localhost:BPNL000000000000#f73e3631-ba87-4a03-bea3-b28700056879", - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json", - "https://w3id.org/security/suites/jws-2020/v1" - ], - "type": [ - "VerifiableCredential", - "BpnCredential" - ], - "issuer": "did:web:localhost:BPNL000000000000", - "expirationDate": "2024-12-31T18:30:00Z", - "issuanceDate": "2023-07-19T09:11:34Z", - "credentialSubject": [ - { - "bpn": "BPNL000000000000", - "id": "did:web:localhost:BPNL000000000000", - "type": "BpnCredential" - } - ], - "proof": { - "created": "2023-07-19T09:11:39Z", - "jws": "eyJhbGciOiJFZERTQSJ9..fdn2qU85auOltdHDLdHI7sJVV1ZPdftpiXd_ndXN0dFgSDWiIrScdD03wtvKLq_H-shQWfh2RYeMmrlEzAhfDw", - "proofPurpose": "proofPurpose", - "type": "JsonWebSignature2020", - "verificationMethod": "did:web:localhost:BPNL000000000000#" - } - } - ] - } - """)) - }) public ResponseEntity> createPresentation(@RequestBody Map data, @RequestParam(name = "audience", required = false) String audience, @RequestParam(name = "asJwt", required = false, defaultValue = "false") boolean asJwt, Principal principal @@ -204,129 +80,8 @@ public ResponseEntity> createPresentation(@RequestBody Map> validatePresentation(@RequestBody Map data, @Parameter(description = "Audience to validate in VP (Only supported in case of JWT formatted VP)") @RequestParam(name = "audience", required = false) String audience, @Parameter(description = "Pass true in case of VP is in JWT format") @RequestParam(name = "asJwt", required = false, defaultValue = "false") boolean asJwt, diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/WalletController.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/WalletController.java index 53b94c5ee..5cfefb72e 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/WalletController.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/controller/WalletController.java @@ -21,15 +21,20 @@ package org.eclipse.tractusx.managedidentitywallets.controller; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.ExampleObject; -import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; + +import org.eclipse.tractusx.managedidentitywallets.apidocs.DidDocumentControllerApiDocs.DidOrBpnParameterDoc; +import org.eclipse.tractusx.managedidentitywallets.apidocs.WalletControllerApiDocs.CreateWalletApiDoc; +import org.eclipse.tractusx.managedidentitywallets.apidocs.WalletControllerApiDocs.PageNumberParameterDoc; +import org.eclipse.tractusx.managedidentitywallets.apidocs.WalletControllerApiDocs.RetrieveWalletApiDoc; +import org.eclipse.tractusx.managedidentitywallets.apidocs.WalletControllerApiDocs.RetrieveWalletsApiDoc; +import org.eclipse.tractusx.managedidentitywallets.apidocs.WalletControllerApiDocs.SizeParameterDoc; +import org.eclipse.tractusx.managedidentitywallets.apidocs.WalletControllerApiDocs.SortColumnParameterDoc; +import org.eclipse.tractusx.managedidentitywallets.apidocs.WalletControllerApiDocs.SortTypeParameterDoc; +import org.eclipse.tractusx.managedidentitywallets.apidocs.WalletControllerApiDocs.StoreVerifiableCredentialApiDoc; import org.eclipse.tractusx.managedidentitywallets.constant.RestURI; import org.eclipse.tractusx.managedidentitywallets.dao.entity.Wallet; import org.eclipse.tractusx.managedidentitywallets.dto.CreateWalletRequest; @@ -60,104 +65,7 @@ public class WalletController extends BaseController { * @param request the request * @return the response entity */ - @io.swagger.v3.oas.annotations.parameters.RequestBody(content = { - @Content(examples = { - - @ExampleObject(name = "Create wallet with BPN", value = """ - { - "bpn": "BPNL000000000001", - "name": "companyA" - } - """) - }) - }) - @ApiResponse(responseCode = "400", description = "The input does not comply to the syntax requirements", content = { - @Content(examples = { - @ExampleObject(name = "Response in case of invalid data provided", value = """ - { - "type": "about:blank", - "title": "Invalid data provided", - "status": 400, - "detail": "details", - "instance": "API endpoint", - "properties": - { - "timestamp": 1689760833962, - "errors": - { - "filed": "filed error message" - } - } - } - """) - }) - }) - @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "409", description = "The request could not be completed due to a conflict.", content = {@Content(examples = { - @ExampleObject(name = "Wallet already exist", value = """ - { - "type": "about:blank", - "title": "Wallet is already exists for bpn BPNL000000000001", - "status": 409, - "detail": "Wallet is already exists for bpn BPNL000000000001", - "instance": "/api/wallets", - "properties": { - "timestamp": 1689762639948 - } - } - """) - })}) - @ApiResponse(responseCode = "500", description = "Any other internal server error", content = {@Content(examples = { - @ExampleObject(name = "Internal server error", value = """ - { - "type": "about:blank", - "title": "Error Title", - "status": 500, - "detail": "Error Details", - "instance": "API endpoint", - "properties": { - "timestamp": 1689762476720 - } - } - """) - })}) - @ApiResponse(responseCode = "201", content = { - @Content(examples = { - @ExampleObject(name = "Success response", value = """ - { - "name": "companyA", - "did": "did:web:localhost:BPNL000000000001", - "bpn": "BPNL000000000501", - "algorithm": "ED25519", - "didDocument": - { - "@context": - [ - "https://www.w3.org/ns/did/v1", - "https://w3c.github.io/vc-jws-2020/contexts/v1" - ], - "id": "did:web:localhost:BPNL000000000001", - "verificationMethod": - [ - { - "controller": "did:web:localhost:BPNL000000000001", - "id": "did:web:localhost:BPNL000000000001#", - "publicKeyJwk": - { - "crv": "Ed25519", - "kty": "OKP", - "x": "0Ap6FsX5UuRBIoOzxWtcFA2ymnqXw0U08Ino_mIuYM4" - }, - "type": "JsonWebKey2020" - } - ] - } - } - """) - }) - }) - @Operation(summary = "Create Wallet", description = "Permission: **add_wallets** (The BPN of the base wallet must equal BPN of caller)\n\n Create a wallet and store it") + @CreateWalletApiDoc @PostMapping(path = RestURI.WALLETS, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity createWallet(@Valid @RequestBody CreateWalletRequest request, Principal principal) { log.debug("Received request to create wallet with BPN {}. authorized by BPN: {}", request.getBpn(), getBPNFromToken(principal)); @@ -171,112 +79,10 @@ public ResponseEntity createWallet(@Valid @RequestBody CreateWalletReque * @param identifier the identifier * @return the response entity */ - @Operation(summary = "Store Verifiable Credential", description = "Permission: **update_wallets** OR **update_wallet** (The BPN of wallet to extract credentials from must equal BPN of caller) \n\n Store a verifiable credential in the wallet of the given identifier") + @StoreVerifiableCredentialApiDoc @PostMapping(path = RestURI.API_WALLETS_IDENTIFIER_CREDENTIALS, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - @io.swagger.v3.oas.annotations.parameters.RequestBody(content = { - @Content(examples = @ExampleObject(""" - { - "@context": - [ - "https://www.w3.org/2018/credentials/v1", - "https://registry.lab.gaia-x.eu/development/api/trusted-shape-registry/v1/shapes/jsonld/trustframework#" - ], - "id": "did:web:localhost.in#123456789", - "type": - [ - "VerifiableCredential", "LegalParticipant" - ], - "issuer": "did:web:localhost.in", - "issuanceDate": "2023-05-04T07:36:03.633Z", - "credentialSubject": - { - "id": "https://localhost/.well-known/participant.json", - "type": "gx:LegalParticipant", - "gx:legalName": "Sample Company", - "gx:legalRegistrationNumber": - { - "gx:taxID": "113123123" - }, - "gx:headquarterAddress": - { - "gx:countrySubdivisionCode": "BE-BRU" - }, - "gx:legalAddress": - { - "gx:countrySubdivisionCode": "BE-BRU" - }, - "gx-terms-and-conditions:gaiaxTermsAndConditions": "70c1d713215f95191a11d38fe2341faed27d19e083917bc8732ca4fea4976700" - }, - "proof": - { - "type": "JsonWebSignature2020", - "created": "2023-05-04T07:36:04.079Z", - "proofPurpose": "assertionMethod", - "verificationMethod": "did:web:localhost", - "jws": "eyJhbGciOiJQUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..iHki8WC3nPfcSRkC_AV4tXh0ikfT7BLPTGc_0ecI8zontTmJLqwcpPfAt0PFsoo3SkZgc6j636z55jj5tagBc-OKoiDu7diWryNAnL9ASsmWJyrPhOKVARs6x6PxVaTFBuyCfAHZeipxmkcYfNB_jooIXO2HuRcL2odhsQHELkGc5IDD-aBMWyNpfVAaYQ-cCzvDflZQlsowziUKfMkBfwpwgMdXFIgKWYdDIRvzA-U-XiC11-6QV7tPeKsMguEU0F5bh8cCEm2rooqXtENcsM_7cqFdQoOyblJyM-agoz2LUTj9QIdn9_gnNkGN-2U7_qBJWmHkK1Hm_mHqcNeeQw" - } - } - """)) - }) - @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "500", description = "Any other internal server error", content = {@Content(examples = { - @ExampleObject(name = "Internal server error", value = """ - { - "type": "about:blank", - "title": "Error Title", - "status": 500, - "detail": "Error Details", - "instance": "API endpoint", - "properties": { - "timestamp": 1689762476720 - } - } - """) - })}) - @ApiResponse(responseCode = "400", description = "The input does not comply to the syntax requirements", content = { - @Content(examples = { - @ExampleObject(name = "Response in case of invalid data provided", value = """ - { - "type": "about:blank", - "title": "title", - "status": 400, - "detail": "details", - "instance": "API endpoint", - "properties": - { - "timestamp": 1689760833962, - "errors": - { - } - } - } - """) - }) - }) - @ApiResponse(responseCode = "404", description = "Wallet not found with provided identifier", content = {@Content(examples = { - @ExampleObject(name = "Wallet not found with provided identifier", value = """ - { - "type": "about:blank", - "title": "Wallet not found for identifier did:web:localhost:BPNL000000044001", - "status": 404, - "detail": "Wallet not found for identifier did:web:localhost:BPNL000000044001", - "instance": "/api/wallets/did%3Aweb%3Alocalhost%3ABPNL0000000/credentials", - "properties": { - "timestamp": 1689765541959 - } - } - """) - })}) - @ApiResponse(responseCode = "201", description = "Success Response", content = {@Content(examples = { - @ExampleObject(name = "Success Response", value = """ - { - "message": "Credential with id did:web:localhost#123456789 has been successfully stored" - } - """) - })}) public ResponseEntity> storeCredential(@RequestBody Map data, - @Parameter(description = "Did or BPN", examples = {@ExampleObject(name = "bpn", value = "BPNL000000000001", description = "bpn"), @ExampleObject(description = "did", name = "did", value = "did:web:localhost:BPNL000000000001")}) @PathVariable(name = "identifier") String identifier, Principal principal) { + @DidOrBpnParameterDoc @PathVariable(name = "identifier") String identifier, Principal principal) { log.debug("Received request to store credential in wallet with identifier {}. authorized by BPN: {}", identifier, getBPNFromToken(principal)); return ResponseEntity.status(HttpStatus.CREATED).body(service.storeCredential(data, identifier, getBPNFromToken(principal))); } @@ -288,158 +94,9 @@ public ResponseEntity> storeCredential(@RequestBody Map getWalletByIdentifier(@Parameter(description = "Did or BPN", examples = {@ExampleObject(name = "bpn", value = "BPNL000000000001", description = "bpn"), @ExampleObject(description = "did", name = "did", value = "did:web:localhost:BPNL000000000001")}) @PathVariable(name = "identifier") String identifier, +public ResponseEntity getWalletByIdentifier( @DidOrBpnParameterDoc @PathVariable(name = "identifier") String identifier, @RequestParam(name = "withCredentials", defaultValue = "false") boolean withCredentials, Principal principal) { log.debug("Received request to retrieve wallet with identifier {}. authorized by BPN: {}", identifier, getBPNFromToken(principal)); @@ -451,116 +108,15 @@ public ResponseEntity getWalletByIdentifier(@Parameter(description = "Di * * @return the wallets */ - @ApiResponse(responseCode = "401", description = "The request could not be completed due to a failed authorization.", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "403", description = "The request could not be completed due to a forbidden access", content = {@Content(examples = {})}) - @ApiResponse(responseCode = "500", description = "Any other internal server error", content = {@Content(examples = { - @ExampleObject(name = "Internal server error", value = """ - { - "type": "about:blank", - "title": "Error Title", - "status": 500, - "detail": "Error Details", - "instance": "API endpoint", - "properties": { - "timestamp": 1689762476720 - } - } - """) - })}) - @ApiResponse(responseCode = "400", description = "The input does not comply to the syntax requirements", content = { - @Content(examples = { - @ExampleObject(name = "Response in case of invalid data provided", value = """ - { - "type": "about:blank", - "title": "title", - "status": 400, - "detail": "details", - "instance": "API endpoint", - "properties": - { - "timestamp": 1689760833962, - "errors": - { - } - } - } - """) - }) - }) - @ApiResponse(responseCode = "200", description = "Wallet list", content = { - @Content(examples = { - @ExampleObject(name = "Wallet list", value = """ - { - "content": [ - { - "name": "companyA", - "did": "did:web:localhost:BPNL000000000001", - "bpn": "BPNL000000000001", - "algorithm": "ED25519", - "didDocument": { - "@context": [ - "https://www.w3.org/ns/did/v1", - "https://w3c.github.io/vc-jws-2020/contexts/v1" - ], - "id": "did:web:localhost:BPNL000000000001", - "verificationMethod": [ - { - "controller": "did:web:localhost:BPNL000000000001", - "id": "did:web:localhost:BPNL000000000001#", - "publicKeyJwk": { - "crv": "Ed25519", - "kty": "OKP", - "x": "mhph0ZSVk7cDVmazbaaC3jBDpphW4eNygAK9gHPlMow" - }, - "type": "JsonWebKey2020" - } - ] - } - } - ], - "pageable": { - "sort": { - "empty": false, - "sorted": true, - "unsorted": false - }, - "offset": 0, - "pageNumber": 0, - "pageSize": 1, - "paged": true, - "unpaged": false - }, - "totalElements": 3, - "totalPages": 3, - "last": false, - "size": 1, - "number": 0, - "sort": { - "empty": false, - "sorted": true, - "unsorted": false - }, - "first": true, - "numberOfElements": 1, - "empty": false - } - """) - }) - }) - @Operation(summary = "List of wallets", description = "Permission: **view_wallets** \n\n Retrieve list of registered wallets") + @RetrieveWalletsApiDoc @GetMapping(path = RestURI.WALLETS, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity> getWallets(@Parameter(name = "pageNumber", description = "Page number, Page number start with zero") @RequestParam(required = false, defaultValue = "0") int pageNumber, - @Parameter(name = "size", description = "Number of records per page") @RequestParam(required = false, defaultValue = Integer.MAX_VALUE + "") int size, - @Parameter(name = "sortColumn", description = "Sort column name", examples = { - @ExampleObject(value = "createdAt", name = "Creation date"), - @ExampleObject(value = "name", name = "Wallet name"), - @ExampleObject(value = "did", name = "Wallet did"), - @ExampleObject(value = "bpn", name = "Wallet BPN") - } - ) - @RequestParam(required = false, defaultValue = "createdAt") String sortColumn, - @Parameter(name = "sortTpe", description = "Sort order", examples = {@ExampleObject(value = "desc", name = "Descending order"), @ExampleObject(value = "asc", name = "Ascending order")}) @RequestParam(required = false, defaultValue = "desc") String sortTpe) { + public ResponseEntity> getWallets( + @PageNumberParameterDoc @RequestParam(required = false, defaultValue = "0") int pageNumber, + @SizeParameterDoc @RequestParam(required = false, defaultValue = Integer.MAX_VALUE + + "") int size, + @SortColumnParameterDoc @RequestParam(required = false, defaultValue = "createdAt") String sortColumn, + @SortTypeParameterDoc @RequestParam(required = false, defaultValue = "desc") String sortTpe) { log.debug("Received request to retrieve wallets"); return ResponseEntity.status(HttpStatus.OK).body(service.getWallets(pageNumber, size, sortColumn, sortTpe)); } -} \ No newline at end of file +} diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/IssuersCredentialService.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/IssuersCredentialService.java index c59a4569e..683605f99 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/IssuersCredentialService.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/IssuersCredentialService.java @@ -432,7 +432,7 @@ public Map credentialsValidation(Map data, boole LinkedDataProofValidation proofValidation = LinkedDataProofValidation.newInstance(didResolver); - boolean valid = proofValidation.verifiy(verifiableCredential); + boolean valid = proofValidation.verify(verifiableCredential); Map response = new TreeMap<>(); diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/PresentationService.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/PresentationService.java index 2f5625595..75739bdaf 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/PresentationService.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/service/PresentationService.java @@ -267,7 +267,7 @@ private boolean validateAudience(String audience, SignedJWT signedJWT) { private boolean validateCredential(VerifiableCredential credential) { final DidResolver resolver = didDocumentResolverService.getCompositeDidResolver(); final LinkedDataProofValidation linkedDataProofValidation = LinkedDataProofValidation.newInstance(resolver); - final boolean isValid = linkedDataProofValidation.verifiy(credential); + final boolean isValid = linkedDataProofValidation.verify(credential); if (isValid) { log.debug("Credential validation result: (valid: {}, credential-id: {})", isValid, credential.getId()); diff --git a/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/HoldersCredentialTest.java b/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/HoldersCredentialTest.java index 58bf51c44..d7f586b16 100644 --- a/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/HoldersCredentialTest.java +++ b/src/test/java/org/eclipse/tractusx/managedidentitywallets/vc/HoldersCredentialTest.java @@ -215,7 +215,7 @@ void validateCredentialsWithInvalidVC() throws com.fasterxml.jackson.core.JsonPr utils.when(() -> { LinkedDataProofValidation.newInstance(Mockito.any(DidResolver.class)); }).thenReturn(mock); - Mockito.when(mock.verifiy(Mockito.any(VerifiableCredential.class))).thenReturn(false); + Mockito.when(mock.verify(Mockito.any(VerifiableCredential.class))).thenReturn(false); Map stringObjectMap = credentialController.credentialsValidation(map, false).getBody(); Assertions.assertFalse(Boolean.parseBoolean(stringObjectMap.get(StringPool.VALID).toString())); @@ -238,7 +238,7 @@ void validateCredentialsWithExpiryCheckTrue() throws com.fasterxml.jackson.core. utils.when(() -> { LinkedDataProofValidation.newInstance(Mockito.any(DidResolver.class)); }).thenReturn(mock); - Mockito.when(mock.verifiy(Mockito.any(VerifiableCredential.class))).thenReturn(true); + Mockito.when(mock.verify(Mockito.any(VerifiableCredential.class))).thenReturn(true); Map stringObjectMap = credentialController.credentialsValidation(map, true).getBody(); Assertions.assertTrue(Boolean.parseBoolean(stringObjectMap.get(StringPool.VALID).toString())); @@ -265,7 +265,7 @@ void validateCredentialsWithExpiryCheckFalse() throws com.fasterxml.jackson.core utils.when(() -> { LinkedDataProofValidation.newInstance(Mockito.any(DidResolver.class)); }).thenReturn(mock); - Mockito.when(mock.verifiy(Mockito.any(VerifiableCredential.class))).thenReturn(true); + Mockito.when(mock.verify(Mockito.any(VerifiableCredential.class))).thenReturn(true); Map stringObjectMap = credentialController.credentialsValidation(map, false).getBody(); Assertions.assertTrue(Boolean.parseBoolean(stringObjectMap.get(StringPool.VALID).toString())); @@ -291,7 +291,7 @@ void validateExpiredCredentialsWithExpiryCheckTrue() throws com.fasterxml.jackso utils.when(() -> { LinkedDataProofValidation.newInstance(Mockito.any(DidResolver.class)); }).thenReturn(mock); - Mockito.when(mock.verifiy(Mockito.any(VerifiableCredential.class))).thenReturn(true); + Mockito.when(mock.verify(Mockito.any(VerifiableCredential.class))).thenReturn(true); Map stringObjectMap = credentialController.credentialsValidation(map, true).getBody(); Assertions.assertFalse(Boolean.parseBoolean(stringObjectMap.get(StringPool.VALID).toString()));