diff --git a/.github/workflows/chart-release.yaml b/.github/workflows/chart-release.yaml deleted file mode 100644 index a90a0ad..0000000 --- a/.github/workflows/chart-release.yaml +++ /dev/null @@ -1,86 +0,0 @@ -############################################################### -# Copyright (c) 2021, 2024 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: Release Chart - -on: - workflow_dispatch: - push: - paths: - - 'charts/**' - branches: - - main - -jobs: - release: - # depending on default permission settings for your org (contents being read-only or read-write for workloads), you will have to add permissions - # see: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token - permissions: - contents: write - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: Configure Git - run: | - git config user.name "$GITHUB_ACTOR" - git config user.email "$GITHUB_ACTOR@users.noreply.github.com" - - - name: Install Helm - uses: azure/setup-helm@v3 - with: - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Update helm dependencies for policy-hub - run: | - cd charts/policy-hub - helm repo add bitnami https://charts.bitnami.com/bitnami - helm dependency update - - - name: Run chart-releaser - uses: helm/chart-releaser-action@v1.4.1 - env: - CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" - CR_SKIP_EXISTING: "true" - - - name: Get current helm chart version - id: chart-version - run: | - current=$(cat ./charts/policy-hub/Chart.yaml | grep "version:" | head -1 | cut -d ":" -d " " -f2) - echo "current=$current" >> $GITHUB_OUTPUT - echo "Exported $current helm chart version" - - - name: Check for previous version - id: version-check - run: | - exists=$(git tag -l "v${{ steps.chart-version.outputs.current }}") - if [[ -n "$exists" ]]; then - echo "exists=true" >> $GITHUB_OUTPUT - else - echo "exists=false" >> $GITHUB_OUTPUT - fi - - - name: Push git tag for release workflow to be triggered - uses: rickstaa/action-create-tag@a1c7777fcb2fee4f19b0f283ba888afa11678b72 # v1.7.2 - with: - tag: v${{ steps.chart-version.outputs.current }} - if: steps.version-check.outputs.exists == 'false' diff --git a/.github/workflows/policy-hub-chart-test.yml b/.github/workflows/chart-test.yml similarity index 72% rename from .github/workflows/policy-hub-chart-test.yml rename to .github/workflows/chart-test.yml index 845aa33..577f060 100644 --- a/.github/workflows/policy-hub-chart-test.yml +++ b/.github/workflows/chart-test.yml @@ -17,7 +17,7 @@ # SPDX-License-Identifier: Apache-2.0 ############################################################### -name: PolicyHub Lint and Test Chart +name: Lint and Test Chart on: push: @@ -38,7 +38,7 @@ on: upgrade_from: description: 'policyhub chart version to upgrade from' # tbd - default: '0.1.0-rc.2' + default: '0.1.0' required: false type: string @@ -48,12 +48,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: fetch-depth: 0 - name: Kubernetes KinD Cluster - uses: container-tools/kind-action@v1 + uses: container-tools/kind-action@0ad70e2299366b0e1552c7240f4e4567148f723e # v2.0.4 with: # upgrade version, default (v0.17.0) uses node image v1.21.1 and doesn't work with more recent node image versions version: v0.20.0 @@ -62,34 +62,34 @@ jobs: - name: Build migration image id: build-migration-image - uses: docker/build-push-action@v3 + uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0 with: context: . - file: docker/Dockerfile-policy-hub-migrations + file: ./docker/Dockerfile-policy-hub-migrations push: true tags: kind-registry:5000/policy-hub-migrations:testing - name: Build service image id: build-service-image - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v5 with: context: . - file: docker/Dockerfile-policy-hub-service + file: ./docker/Dockerfile-policy-hub-service push: true tags: kind-registry:5000/policy-hub-service:testing - name: Set up Helm - uses: azure/setup-helm@v3 + uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4 with: version: v3.9.3 - - uses: actions/setup-python@v4 + - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 with: python-version: '3.9' check-latest: true - name: Set up chart-testing - uses: helm/chart-testing-action@v2.3.1 + uses: helm/chart-testing-action@e6669bcd63d7cb57cb4380c33043eebe5d111992 # v2.6.1 - name: Run chart-testing (list-changed) id: list-changed @@ -102,8 +102,8 @@ jobs: - name: Run chart-testing (lint) run: ct lint --validate-maintainers=false --check-version-increment=false --target-branch ${{ github.event.repository.default_branch }} - - name: Run service chart-testing (install) - run: ct install --charts charts/policy-hub --config charts/chart-testing-config.yaml --helm-extra-set-args "--set=policyhub.image=kind-registry:5000/policy-hub-service:testing --set=policyhubmigrations.image=kind-registry:5000/policy-hub-migrations:testing" + - name: Run chart-testing (install) + run: ct install --charts charts/policy-hub --config charts/chart-testing-config.yaml --helm-extra-set-args "--set policyhub.image.name=kind-registry:5000/policy-hub-service --set policyhub.image.tag=testing --set policyhubmigrations.image.name=kind-registry:5000/policy-hub-migrations --set policyhubmigrations.image.tag=testing" if: github.event_name != 'pull_request' || steps.list-changed.outputs.changed == 'true' # Upgrade the released chart version with the locally available chart @@ -112,7 +112,7 @@ jobs: run: | helm repo add bitnami https://charts.bitnami.com/bitnami helm repo add tractusx-dev https://eclipse-tractusx.github.io/charts/dev - helm install policy-hub tractusx-dev/policy-hub --version ${{ github.event.inputs.upgrade_from || '0.1.0-rc.2' }} --namespace upgrade --create-namespace + helm install policy-hub tractusx-dev/policy-hub --version ${{ github.event.inputs.upgrade_from || '0.1.0' }} --namespace upgrade --create-namespace helm dependency update charts/policy-hub - helm upgrade policy-hub charts/policy-hub --set policyhub.image=kind-registry:5000/policy-hub-service:testing --set=policyhubmigrations.image=kind-registry:5000/policy-hub-migrations:testing --namespace upgrade + helm upgrade policy-hub charts/policy-hub --set policyhub.image.name=kind-registry:5000/policy-hub-service --set policyhub.image.tag=testing --set policyhubmigrations.image.name=kind-registry:5000/policy-hub-migrations --set policyhubmigrations.image.tag=testing --namespace upgrade if: github.event_name != 'pull_request' || steps.list-changed.outputs.changed == 'true' diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e9347f5..08146a1 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -69,11 +69,11 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@66b90a5db151a8042fa97405c6cf843bbe433f7b # v2.227 + uses: github/codeql-action/init@d39d31e687223d841ef683f52467bd88e9b21c14 # v2.227 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -87,7 +87,7 @@ jobs: # Automates dependency installation for Python, Ruby, and JavaScript, optimizing the CodeQL analysis setup. # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@66b90a5db151a8042fa97405c6cf843bbe433f7b # v2.227 + uses: github/codeql-action/autobuild@d39d31e687223d841ef683f52467bd88e9b21c14 # v2.227 # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -100,6 +100,6 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@66b90a5db151a8042fa97405c6cf843bbe433f7b # v2.227 + uses: github/codeql-action/analyze@d39d31e687223d841ef683f52467bd88e9b21c14 # v2.227 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index a2b1515..ab8f0ce 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -32,23 +32,26 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - dotnet-version: ['7.0'] + # change to preview .NET 9 until fix for https://github.com/NuGet/Home/issues/12954 gets released for .NET 8 + dotnet-version: ['9.0'] steps: - name: Set up JDK 17 - uses: actions/setup-java@v3 + uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 with: distribution: 'temurin' java-version: '17' - name: Setup .NET Core SDK ${{ matrix.dotnet-version }} - uses: actions/setup-dotnet@v2 + uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0 with: dotnet-version: ${{ matrix.dotnet-version }} + # change to preview .NET 9 until fix for https://github.com/NuGet/Home/issues/12954 gets released for .NET 8 + dotnet-quality: 'preview' - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Install dependencies run: dotnet restore src @@ -57,7 +60,7 @@ jobs: run: dotnet list src package --include-transitive --interactive | grep ">" | grep -Pv "\s(Org.Eclipse.TractusX|Microsoft|NuGet|System|runtime|docker|Docker|NETStandard)" | sed -E -e "s/\s+> ([a-zA-Z\.\-]+).+\s([0-9]+\.[0-9]+\.[0-9]+)\s*/nuget\/nuget\/\-\/\1\/\2/g" | awk '!seen[$0]++' > PACKAGES - name: Generate Dependencies file - run: java -jar ./scripts/download/org.eclipse.dash.licenses-1.1.1-20240213.065029-71.jar PACKAGES -project automotive.tractusx -summary DEPENDENCIES || true + run: java -jar ./scripts/download/org.eclipse.dash.licenses-1.1.1.jar PACKAGES -project automotive.tractusx -summary DEPENDENCIES || true - name: Check if dependencies were changed id: dependencies-changed @@ -81,7 +84,7 @@ jobs: if: steps.dependencies-changed.outputs.changed == 'true' - name: Upload DEPENDENCIES file - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: path: DEPENDENCIES if: steps.dependencies-changed.outputs.changed == 'true' diff --git a/.github/workflows/kics.yml b/.github/workflows/kics.yml index 36caacb..7ee9484 100644 --- a/.github/workflows/kics.yml +++ b/.github/workflows/kics.yml @@ -42,10 +42,10 @@ jobs: security-events: write steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: KICS scan - uses: checkmarx/kics-github-action@master + uses: checkmarx/kics-github-action@d1b692d84c536f4e8696954ce7aab6818f95f5bc # v2.0.0 with: # Scanning directory . path: "." @@ -69,7 +69,7 @@ jobs: # Upload findings to GitHub Advanced Security Dashboard - name: Upload SARIF file for GitHub Advanced Security Dashboard if: always() - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 with: sarif_file: kicsResults/results.sarif diff --git a/.github/workflows/lint-pull-request.yml b/.github/workflows/lint-pull-request.yml index 705ef8d..747f909 100644 --- a/.github/workflows/lint-pull-request.yml +++ b/.github/workflows/lint-pull-request.yml @@ -31,12 +31,12 @@ jobs: name: Validate PR title runs-on: ubuntu-latest steps: - - uses: amannn/action-semantic-pull-request@v5 + - uses: amannn/action-semantic-pull-request@cfb60706e18bc85e8aec535e3c577abe8f70378e # v5.5.2 id: lint_pr_title env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - uses: marocchino/sticky-pull-request-comment@v2 + - uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 # v2.9.0 # When the previous steps fail, the workflow would stop. By adding this # condition you can continue the execution with the populated error message. if: always() && (steps.lint_pr_title.outputs.error_message != null) @@ -55,7 +55,7 @@ jobs: # Delete a previous comment when the issue has been resolved - if: ${{ steps.lint_pr_title.outputs.error_message == null }} - uses: marocchino/sticky-pull-request-comment@v2 + uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 # v2.9.0 with: header: pr-title-lint-error delete: true \ No newline at end of file diff --git a/.github/workflows/policy-hub-migrations.yml b/.github/workflows/migrations-docker.yml similarity index 76% rename from .github/workflows/policy-hub-migrations.yml rename to .github/workflows/migrations-docker.yml index d7a2d58..af52472 100644 --- a/.github/workflows/policy-hub-migrations.yml +++ b/.github/workflows/migrations-docker.yml @@ -17,7 +17,7 @@ # SPDX-License-Identifier: Apache-2.0 ############################################################### -name: PolicyHub-Migrations +name: Build Migrations Image on: push: @@ -46,24 +46,24 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Login to DockerHub if: github.event_name != 'pull_request' - uses: docker/login-action@v2 + uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 with: username: ${{ secrets.DOCKER_HUB_USER }} password: ${{ secrets.DOCKER_HUB_TOKEN }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0 - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 - name: Docker meta id: meta - uses: docker/metadata-action@v4 + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 with: images: ${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME }} tags: | @@ -71,10 +71,10 @@ jobs: type=raw,value=${{ github.sha }} - name: Build and push Docker image - uses: docker/build-push-action@v4 + uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0 with: context: . - file: docker/Dockerfile-policy-hub-migrations + file: ./docker/Dockerfile-policy-hub-migrations platforms: linux/amd64, linux/arm64 pull: true push: ${{ github.event_name != 'pull_request' }} @@ -84,9 +84,9 @@ jobs: # https://github.com/peter-evans/dockerhub-description - name: Update Docker Hub description if: github.event_name != 'pull_request' - uses: peter-evans/dockerhub-description@v3 + uses: peter-evans/dockerhub-description@e98e4d1628a5f3be2be7c231e50981aee98723ae # v4.0.0 with: username: ${{ secrets.DOCKER_HUB_USER }} password: ${{ secrets.DOCKER_HUB_TOKEN }} repository: ${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME }} - readme-filepath: "./docker/notice-policy-hub-migrations.md" + readme-filepath: ./docker/notice-policy-hub-migrations.md diff --git a/.github/workflows/owasp-zap.yml b/.github/workflows/owasp-zap.yml index a5e41e2..1a8d702 100644 --- a/.github/workflows/owasp-zap.yml +++ b/.github/workflows/owasp-zap.yml @@ -45,36 +45,36 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: fetch-depth: 0 - name: Kubernetes KinD Cluster - uses: container-tools/kind-action@0fc957b58d9a5bc9ca57a1b419324a2074c7653b # v2.0.3 + uses: container-tools/kind-action@0ad70e2299366b0e1552c7240f4e4567148f723e # v2.0.4 with: node_image: ${{ github.event.inputs.node_image || 'kindest/node:v1.27.3' }} version: v0.20.0 - name: Set up Helm - uses: azure/setup-helm@5119fcb9089d432beecbf79bb2c7915207344b78 # v3.5 + uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4.2.0 with: version: v3.5.0 - name: Build migration image id: build-migration-image - uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 + uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0 with: context: . - file: docker/Dockerfile-policy-hub-migrations + file: ./docker/Dockerfile-policy-hub-migrations push: true tags: kind-registry:5000/policy-hub-migrations:testing - name: Build service image id: build-service-image - uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 + uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0 with: context: . - file: docker/Dockerfile-policy-hub-service + file: ./docker/Dockerfile-policy-hub-service push: true tags: kind-registry:5000/policy-hub-service:testing @@ -89,7 +89,7 @@ jobs: helm dependency build - name: Install the chart on KinD cluster - run: helm install testing -n apps --create-namespace --wait --set policyhub.image=kind-registry:5000/policy-hub-service:testing --set=policyhubmigrations.image=kind-registry:5000/policy-hub-migrations:testing --set=policyhub.swaggerEnabled=true charts/policy-hub + run: helm install testing -n apps --create-namespace --wait --set policyhub.image.name=kind-registry:5000/policy-hub-service --set policyhub.image.tag=testing --set policyhubmigrations.image.name=kind-registry:5000/policy-hub-migrations --set policyhubmigrations.image.tag=testing --set policyhub.swaggerEnabled=true charts/policy-hub - name: Configure port forward to app in KinD run: | @@ -126,7 +126,7 @@ jobs: - name: Upload HTML report if: success() || failure() - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: ZAP scan report path: ./report_html.html diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d6f11fb..aa50c99 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,61 +20,123 @@ name: Release on: - push: - tags: - - 'v*.*.*' workflow_dispatch: - -env: - IMAGE_NAMESPACE: "tractusx" - IMAGE_NAME_SERVICE: "policy-hub-service" - IMAGE_NAME_MIGRATIONS: "policy-hub-migrations" + push: + paths: + - 'charts/**' + branches: + - main jobs: - policy-hub-service-release: + release-helm-chart: + # depending on default permission settings for your org (contents being read-only or read-write for workloads), you will have to add permissions + # see: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token + permissions: + contents: write runs-on: ubuntu-latest + outputs: + app-version: ${{ steps.app-version.outputs.current }} + version-check: ${{ steps.version-check.outputs.exists }} + steps: + - name: Checkout + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + with: + fetch-depth: 0 + + - name: Configure Git + run: | + git config user.name "$GITHUB_ACTOR" + git config user.email "$GITHUB_ACTOR@users.noreply.github.com" + + - name: Install Helm + uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4 + + - name: Update helm dependencies for policy-hub + run: | + cd charts/policy-hub + helm repo add bitnami https://charts.bitnami.com/bitnami + helm dependency update + + - name: Run chart-releaser + uses: helm/chart-releaser-action@v1.6.0 + env: + CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + CR_SKIP_EXISTING: "true" + + - name: Get current appVersion + id: app-version + run: | + current=$(cat ./charts/policy-hub/Chart.yaml | grep "appVersion:" | head -1 | cut -d ":" -d " " -f2) + echo "current=$current" >> $GITHUB_OUTPUT + echo "Exported $current appVersion" + + - name: Check for previous version + id: version-check + run: | + exists=$(git tag -l "v${{ steps.app-version.outputs.current }}") + if [[ -n "$exists" ]]; then + echo "exists=true" >> $GITHUB_OUTPUT + else + echo "exists=false" >> $GITHUB_OUTPUT + fi + + release-images: + needs: release-helm-chart + if: needs.release-helm-chart.outputs.version-check == 'false' permissions: - packages: write - + contents: read + runs-on: ubuntu-latest + strategy: + matrix: + include: + - image: tractusx/policy-hub-service + dockerfile: ./docker/Dockerfile-policy-hub-service + dockernotice: ./docker/notice-policy-hub-service.md + - image: tractusx/policy-hub-migrations + dockerfile: ./docker/Dockerfile-policy-hub-migrations + dockernotice: ./docker/notice-policy-hub-migrations.md + outputs: + app-version: ${{ steps.app-version.outputs.current }} + version-check: ${{ steps.version-check.outputs.exists }} steps: - - name: Checkout repository - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + with: + fetch-depth: 0 - name: Login to DockerHub - if: github.event_name != 'pull_request' - uses: docker/login-action@v2 + uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 with: username: ${{ secrets.DOCKER_HUB_USER }} password: ${{ secrets.DOCKER_HUB_TOKEN }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0 - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 # Create SemVer or ref tags dependent of trigger event - name: Docker meta id: meta - uses: docker/metadata-action@v4 + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 with: - images: | - ${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME_SERVICE }} + images: ${{ matrix.image }} # Automatically prepare image tags; See action docs for more examples. # semver patter will generate tags like these for example :1 :1.2 :1.2.3 tags: | - type=ref,event=branch - type=ref,event=pr - type=raw,value=latest - type=semver,pattern={{version}} - type=semver,pattern={{major}} - type=semver,pattern={{major}}.{{minor}} - - - name: Build and push Docker image - uses: docker/build-push-action@v4 + type=ref,event=branch + type=ref,event=pr + type=raw,value=latest + type=semver,pattern={{version}},value=${{ needs.release-helm-chart.outputs.app-version }} + type=semver,pattern={{major}},value=${{ needs.release-helm-chart.outputs.app-version }} + type=semver,pattern={{major}}.{{minor}},value=${{ needs.release-helm-chart.outputs.app-version }} + + - name: Build and push Docker images + uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0 with: context: . - file: docker/Dockerfile-policy-hub-service + file: {{ matrix.dockerfile }} platforms: linux/amd64, linux/arm64 pull: true push: ${{ github.event_name != 'pull_request' }} @@ -83,70 +145,26 @@ jobs: # https://github.com/peter-evans/dockerhub-description - name: Update Docker Hub description - if: github.event_name != 'pull_request' - uses: peter-evans/dockerhub-description@v3 + uses: peter-evans/dockerhub-description@e98e4d1628a5f3be2be7c231e50981aee98723ae # v4.0.0 with: username: ${{ secrets.DOCKER_HUB_USER }} password: ${{ secrets.DOCKER_HUB_TOKEN }} - repository: ${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME_SERVICE }} - readme-filepath: "./docker/notice-policy-hub-service.md" + repository: ${{ matrix.image }} + readme-filepath: ${{ matrix.dockernotice }} - policy-hub-migrations-release: - runs-on: ubuntu-latest + create-tag: + needs: [release-helm-chart, release-images] + if: needs.release-helm-chart.outputs.version-check == 'false' permissions: - contents: read - + contents: write + runs-on: ubuntu-latest steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Login to DockerHub - if: github.event_name != 'pull_request' - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_TOKEN }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - # Create SemVer or ref tags dependent of trigger event - - name: Docker meta - id: meta - uses: docker/metadata-action@v4 + - name: Checkout + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: - images: | - ${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME_MIGRATIONS }} - # Automatically prepare image tags; See action docs for more examples. - # semver patter will generate tags like these for example :1 :1.2 :1.2.3 - tags: | - type=ref,event=branch - type=ref,event=pr - type=raw,value=latest - type=semver,pattern={{version}} - type=semver,pattern={{major}} - type=semver,pattern={{major}}.{{minor}} - - - name: Build and push Docker image - uses: docker/build-push-action@v4 - with: - context: . - file: docker/Dockerfile-policy-hub-migrations - platforms: linux/amd64, linux/arm64 - pull: true - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} + fetch-depth: 0 - # https://github.com/peter-evans/dockerhub-description - - name: Update Docker Hub description - if: github.event_name != 'pull_request' - uses: peter-evans/dockerhub-description@v3 - with: - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_TOKEN }} - repository: ${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME_MIGRATIONS }} - readme-filepath: "./docker/notice-policy-hub-migrations.md" + - name: Create and push git tag + run: | + git tag v${{ needs.release-helm-chart.outputs.app-version }} + git push origin v${{ needs.release-helm-chart.outputs.app-version }} diff --git a/.github/workflows/release_candidate.yml b/.github/workflows/release_candidate.yml index 19541fa..116df4e 100644 --- a/.github/workflows/release_candidate.yml +++ b/.github/workflows/release_candidate.yml @@ -25,100 +25,53 @@ on: - 'release/v*.*.*-rc*' workflow_dispatch: -env: - IMAGE_NAMESPACE: "tractusx" - IMAGE_NAME_SERVICE: "policy-hub-service" - IMAGE_NAME_MIGRATIONS: "policy-hub-migrations" - jobs: - policy-hub-service-release: + release-images: runs-on: ubuntu-latest permissions: contents: read - + strategy: + matrix: + include: + - image: tractusx/policy-hub-service + dockerfile: ./docker/Dockerfile-policy-hub-service + dockernotice: ./docker/notice-policy-hub-service.md + - image: tractusx/policy-hub-migrations + dockerfile: ./docker/Dockerfile-policy-hub-migrations + dockernotice: ./docker/notice-policy-hub-migrations.md steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Login to DockerHub - if: github.event_name != 'pull_request' - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_TOKEN }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Docker meta - id: meta - uses: docker/metadata-action@v4 - with: - images: ${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME_SERVICE }} - tags: | - type=raw,value=rc - type=raw,value=${{ github.sha }} - - - name: Build and push Docker image - uses: docker/build-push-action@v4 + - name: Checkout + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: - context: . - file: docker/Dockerfile-policy-hub-service - platforms: linux/amd64, linux/arm64 - pull: true - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - - # https://github.com/peter-evans/dockerhub-description - - name: Update Docker Hub description - if: github.event_name != 'pull_request' - uses: peter-evans/dockerhub-description@v3 - with: - username: ${{ secrets.DOCKER_HUB_USER }} - password: ${{ secrets.DOCKER_HUB_TOKEN }} - repository: ${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME_SERVICE }} - readme-filepath: "./docker/notice-policy-hub-service.md" - - policy-hub-migrations-release: - runs-on: ubuntu-latest - permissions: - contents: read - - steps: - - name: Checkout repository - uses: actions/checkout@v3 + fetch-depth: 0 - name: Login to DockerHub if: github.event_name != 'pull_request' - uses: docker/login-action@v2 + uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 with: username: ${{ secrets.DOCKER_HUB_USER }} password: ${{ secrets.DOCKER_HUB_TOKEN }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0 - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 - name: Docker meta id: meta - uses: docker/metadata-action@v4 + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 with: - images: ${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME_MIGRATIONS }} + images: ${{ matrix.image }} tags: | type=raw,value=rc type=raw,value=${{ github.sha }} - - name: Build and push Docker image - uses: docker/build-push-action@v4 + - name: Build and push Docker images + uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0 with: context: . - file: docker/Dockerfile-policy-hub-migrations + file: ${{ matrix.dockerfile }} platforms: linux/amd64, linux/arm64 pull: true push: ${{ github.event_name != 'pull_request' }} @@ -128,9 +81,9 @@ jobs: # https://github.com/peter-evans/dockerhub-description - name: Update Docker Hub description if: github.event_name != 'pull_request' - uses: peter-evans/dockerhub-description@v3 + uses: peter-evans/dockerhub-description@e98e4d1628a5f3be2be7c231e50981aee98723ae # v4.0.0 with: username: ${{ secrets.DOCKER_HUB_USER }} password: ${{ secrets.DOCKER_HUB_TOKEN }} - repository: ${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME_MIGRATIONS }} - readme-filepath: "./docker/notice-policy-hub-migrations.md" + repository: ${{ matrix.image }} + readme-filepath: ${{ matrix.dockernotice }} diff --git a/.github/workflows/policy-hub-service.yml b/.github/workflows/service-docker.yml similarity index 76% rename from .github/workflows/policy-hub-service.yml rename to .github/workflows/service-docker.yml index c9f8add..fea6e68 100644 --- a/.github/workflows/policy-hub-service.yml +++ b/.github/workflows/service-docker.yml @@ -17,7 +17,7 @@ # SPDX-License-Identifier: Apache-2.0 ############################################################### -name: PolicyHub-Service +name: Build Service Image on: push: @@ -45,24 +45,24 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Login to DockerHub if: github.event_name != 'pull_request' - uses: docker/login-action@v2 + uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 with: username: ${{ secrets.DOCKER_HUB_USER }} password: ${{ secrets.DOCKER_HUB_TOKEN }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0 - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 - name: Docker meta id: meta - uses: docker/metadata-action@v4 + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 with: images: ${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME }} tags: | @@ -70,10 +70,10 @@ jobs: type=raw,value=${{ github.sha }} - name: Build and push Docker image - uses: docker/build-push-action@v4 + uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0 with: context: . - file: docker/Dockerfile-policy-hub-service + file: ./docker/Dockerfile-policy-hub-service platforms: linux/amd64, linux/arm64 pull: true push: ${{ github.event_name != 'pull_request' }} @@ -83,9 +83,9 @@ jobs: # https://github.com/peter-evans/dockerhub-description - name: Update Docker Hub description if: github.event_name != 'pull_request' - uses: peter-evans/dockerhub-description@v3 + uses: peter-evans/dockerhub-description@e98e4d1628a5f3be2be7c231e50981aee98723ae # v4.0.0 with: username: ${{ secrets.DOCKER_HUB_USER }} password: ${{ secrets.DOCKER_HUB_TOKEN }} repository: ${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME }} - readme-filepath: "./docker/notice-policy-hub-service.md" + readme-filepath: ./docker/notice-policy-hub-service.md diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index d3149d5..4644aa7 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -21,8 +21,12 @@ name: Sonarcloud on: push: branches: [main, dev] + paths: + - 'src/**' pull_request: types: [opened, synchronize, reopened] + paths: + - 'src/**' workflow_dispatch: jobs: @@ -32,26 +36,26 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - dotnet-version: ['7.0'] + dotnet-version: ['8.0'] steps: - name: Set up JDK 17 - uses: actions/setup-java@v3 + uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 with: distribution: 'temurin' java-version: '17' - - uses: actions/checkout@v3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - name: Cache SonarCloud packages - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/sonar/cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - name: Cache SonarCloud scanner id: cache-sonar-scanner - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ./.sonar/scanner key: ${{ runner.os }}-sonar-scanner diff --git a/.github/workflows/test-automation.yml b/.github/workflows/test-automation.yml index 7f53550..2e09858 100644 --- a/.github/workflows/test-automation.yml +++ b/.github/workflows/test-automation.yml @@ -29,11 +29,11 @@ jobs: environment: ${{ github.event.inputs.environment }} strategy: matrix: - dotnet-version: [ '7.0' ] + dotnet-version: [ '8.0' ] steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Setup JQ run: @@ -53,7 +53,7 @@ jobs: ReportPortal.config.json > temp.json mv temp.json ReportPortal.config.json - name: Setup .NET Core SDK ${{ matrix.dotnet-version }} - uses: actions/setup-dotnet@v2 + uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0 with: dotnet-version: ${{ matrix.dotnet-version }} - name: Install dependencies @@ -69,7 +69,7 @@ jobs: run: dotnet test tests/endToEnd --no-restore --verbosity minimal --logger "html;logfilename=e2ePolicyHub.html" - name: 'Upload Artifact' if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: e2e-policy-hub-report path: tests/endToEnd/TestResults/e2ePolicyHub.html \ No newline at end of file diff --git a/.github/workflows/trivy-dev.yml b/.github/workflows/trivy-dev.yml index 0d67c16..e4bbe04 100644 --- a/.github/workflows/trivy-dev.yml +++ b/.github/workflows/trivy-dev.yml @@ -51,10 +51,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Run Trivy vulnerability scanner in repo mode - uses: aquasecurity/trivy-action@0.14.0 + uses: aquasecurity/trivy-action@d710430a6722f083d3b36b8339ff66b32f22ee55 # v0.19.0 with: scan-type: "config" hide-progress: false @@ -64,7 +64,7 @@ jobs: timeout: "3600s" - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 if: always() with: sarif_file: "trivy-results1.sarif" @@ -78,7 +78,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 # It's also possible to scan your private registry with Trivy's built-in image scan. # All you have to do is set ENV vars. @@ -87,7 +87,7 @@ jobs: # For public images, no ENV vars must be set. - name: Run Trivy vulnerability scanner if: always() - uses: aquasecurity/trivy-action@0.14.0 + uses: aquasecurity/trivy-action@d710430a6722f083d3b36b8339ff66b32f22ee55 # v0.19.0 with: # Path to Docker image image-ref: "${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME }}-service:dev" @@ -97,7 +97,7 @@ jobs: - name: Upload Trivy scan results to GitHub Security tab if: always() - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 with: sarif_file: "trivy-results3.sarif" @@ -110,7 +110,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 # It's also possible to scan your private registry with Trivy's built-in image scan. # All you have to do is set ENV vars. @@ -119,7 +119,7 @@ jobs: # For public images, no ENV vars must be set. - name: Run Trivy vulnerability scanner if: always() - uses: aquasecurity/trivy-action@0.14.0 + uses: aquasecurity/trivy-action@d710430a6722f083d3b36b8339ff66b32f22ee55 # v0.19.0 with: # Path to Docker image image-ref: "${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME }}-migrations:dev" @@ -130,6 +130,6 @@ jobs: - name: Upload Trivy scan results to GitHub Security tab if: always() - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 with: sarif_file: "trivy-results9.sarif" diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index 9145989..2435249 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -51,10 +51,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Run Trivy vulnerability scanner in repo mode - uses: aquasecurity/trivy-action@0.14.0 + uses: aquasecurity/trivy-action@d710430a6722f083d3b36b8339ff66b32f22ee55 # v0.19.0 with: scan-type: "config" hide-progress: false @@ -65,7 +65,7 @@ jobs: timeout: "3600s" - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 if: always() with: sarif_file: "trivy-results1.sarif" @@ -79,7 +79,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 # It's also possible to scan your private registry with Trivy's built-in image scan. # All you have to do is set ENV vars. @@ -88,7 +88,7 @@ jobs: # For public images, no ENV vars must be set. - name: Run Trivy vulnerability scanner if: always() - uses: aquasecurity/trivy-action@0.14.0 + uses: aquasecurity/trivy-action@d710430a6722f083d3b36b8339ff66b32f22ee55 # v0.19.0 with: # Path to Docker image image-ref: "${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME }}-service:latest" @@ -98,7 +98,7 @@ jobs: - name: Upload Trivy scan results to GitHub Security tab if: always() - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 with: sarif_file: "trivy-results3.sarif" @@ -111,7 +111,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 # It's also possible to scan your private registry with Trivy's built-in image scan. # All you have to do is set ENV vars. @@ -120,7 +120,7 @@ jobs: # For public images, no ENV vars must be set. - name: Run Trivy vulnerability scanner if: always() - uses: aquasecurity/trivy-action@0.14.0 + uses: aquasecurity/trivy-action@d710430a6722f083d3b36b8339ff66b32f22ee55 # v0.19.0 with: # Path to Docker image image-ref: "${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME }}-migrations:latest" @@ -130,6 +130,6 @@ jobs: - name: Upload Trivy scan results to GitHub Security tab if: always() - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 with: sarif_file: "trivy-results9.sarif" diff --git a/.github/workflows/unit.tests-formatting.yml b/.github/workflows/unit.tests-formatting.yml index ad33db0..3ecf843 100644 --- a/.github/workflows/unit.tests-formatting.yml +++ b/.github/workflows/unit.tests-formatting.yml @@ -22,8 +22,12 @@ name: Unit-Tests and Formatting on: push: branches: [main, dev] + paths: + - 'src/**' pull_request: types: [opened, synchronize, reopened] + paths: + - 'src/**' workflow_dispatch: jobs: @@ -32,12 +36,12 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - dotnet-version: ['7.0'] + dotnet-version: ['8.0'] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - name: Setup .NET Core SDK ${{ matrix.dotnet-version }} - uses: actions/setup-dotnet@v2 + uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0 with: dotnet-version: ${{ matrix.dotnet-version }} - name: Install dotnet-format diff --git a/CHANGELOG.md b/CHANGELOG.md index 82041e1..09d75f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,33 @@ # Changelog +## [1.0.0-rc.1](https://github.com/eclipse-tractusx/policy-hub/compare/v0.1.0...v1.0.0-rc.1) (2024-04-30) + + +### Features + +* **bpnl:** add bpnl policy handling ([#116](https://github.com/eclipse-tractusx/policy-hub/issues/116)) ([421202b](https://github.com/eclipse-tractusx/policy-hub/commit/421202b80a8916a0747c39135905eea0479a2540)) +* **helm_db-dependency:** change image tag to get latest minor updates ([a2663c1](https://github.com/eclipse-tractusx/policy-hub/commit/a2663c16e260eb33dd969c36d15a1ea77821efd6)) +* **helm:** change image tag retrieval for fallback to appVersion ([39b5b69](https://github.com/eclipse-tractusx/policy-hub/commit/39b5b6953c0a3c72f10c66ecc71b097144ac02ae)) +* **helm:** change ingress according to TRG-5.04 ([b00b25f](https://github.com/eclipse-tractusx/policy-hub/commit/b00b25f1cd684bddbaf2461c1405db3321a929d8)) +* **helm:** consolidate centralidp configuration ([660ad6f](https://github.com/eclipse-tractusx/policy-hub/commit/660ad6faec42d14a9e5d2f139a6a0488506fb06c)) +* **helm:** move health checks to service ([7b92236](https://github.com/eclipse-tractusx/policy-hub/commit/7b9223693fe7a65a33d01fd25ee7c51fa2f788a5)) +* **helm:** move passwords for db dependency to according section ([26b0b4e](https://github.com/eclipse-tractusx/policy-hub/commit/26b0b4e688742f59ead334253a19d9715d04729d)) +* **helm:** set resource limits ([913c837](https://github.com/eclipse-tractusx/policy-hub/commit/913c837a6750eca2362a6197f67cf60e7a9e1e70)) +* **net8:** upgrade to .net8 ([#102](https://github.com/eclipse-tractusx/policy-hub/issues/102)) ([fb9e3c9](https://github.com/eclipse-tractusx/policy-hub/commit/fb9e3c944bbee02f5800ab99095ffb439bc91dd3)), closes [#19](https://github.com/eclipse-tractusx/policy-hub/issues/19) +* **policy:** add value check to post endpoint ([#97](https://github.com/eclipse-tractusx/policy-hub/issues/97)) ([2039af0](https://github.com/eclipse-tractusx/policy-hub/commit/2039af081fe41add04518a0932948e989967dbac)), closes [#68](https://github.com/eclipse-tractusx/policy-hub/issues/68) +* **policy:** policy seeding data update ([#88](https://github.com/eclipse-tractusx/policy-hub/issues/88)) ([10bb931](https://github.com/eclipse-tractusx/policy-hub/commit/10bb931387e93260d84bdacf59f1fcd77b76e169)), closes [#25](https://github.com/eclipse-tractusx/policy-hub/issues/25) +* **template:** policyhub restrict or operand to access policies ([#107](https://github.com/eclipse-tractusx/policy-hub/issues/107)) ([6a4cacd](https://github.com/eclipse-tractusx/policy-hub/commit/6a4cacd607325fecf08ce567c13b2d3bacd2e636)), closes [#43](https://github.com/eclipse-tractusx/policy-hub/issues/43) + + +### Bug Fixes + +* **helm:** fix label and username for external database ([#72](https://github.com/eclipse-tractusx/policy-hub/issues/72)) ([e9817ff](https://github.com/eclipse-tractusx/policy-hub/commit/e9817ffd1d38db9525338e965248f7375a592857)) + + +### Miscellaneous Chores + +* release 1.0.0-rc.1 ([9f1cb78](https://github.com/eclipse-tractusx/policy-hub/commit/9f1cb78344b742bf7a834369d99720a6ff5eeaff)) + ## [0.1.0](https://github.com/eclipse-tractusx/policy-hub/compare/v0.1.0-rc.3...v0.1.0) (2024-03-06) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1915f50..39c3812 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ The companies involved want to increase the automotive industry's competitiveness, improve efficiency through industry-specific cooperation and accelerate company processes through standardization and access to information and data. A special focus is also on SMEs, whose active participation is of -central importance for the network’s success. That is why Catena-X has been +central importance for the network's success. That is why Catena-X has been conceived from the outset as an open network with solutions ready for SMEs, where these companies will be able to participate quickly and with little IT infrastructure investment. Tractus-X is meant to be the PoC project of the @@ -51,6 +51,10 @@ fulfills the DCO's requirement that you sign-off on your contributions. For more information, please see the Eclipse Committer Handbook: https://www.eclipse.org/projects/handbook/#resources-commit +## How To Contribute + +For more practical information, please refer to [Contribution details](/docs/technical-documentation/dev-process/How%20to%20contribute.md). + ## Contact Contact the project developers via the project's "dev" list. diff --git a/DEPENDENCIES b/DEPENDENCIES index aa9dbca..f2aec2a 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -1,49 +1,53 @@ nuget/nuget/-/AutoFixture.AutoFakeItEasy/4.18.0, MIT, approved, #10064 +nuget/nuget/-/AutoFixture.AutoFakeItEasy/4.18.1, MIT, approved, #10064 nuget/nuget/-/AutoFixture.Xunit/4.18.0, MIT, approved, #10082 +nuget/nuget/-/AutoFixture.Xunit/4.18.1, MIT, approved, #10082 nuget/nuget/-/AutoFixture/4.18.0, MIT, approved, #10057 -nuget/nuget/-/Castle.Core/4.3.1, Apache-2.0, approved, clearlydefined -nuget/nuget/-/EFCore.NamingConventions/7.0.2, Apache-2.0, approved, #10067 -nuget/nuget/-/FakeItEasy/7.4.0, MIT, approved, #10080 +nuget/nuget/-/AutoFixture/4.18.1, MIT, approved, #10057 +nuget/nuget/-/BouncyCastle.Cryptography/2.2.1, MIT AND Apache-2.0 AND BSD-3-Clause AND LicenseRef-Permission-Notice, approved, #10066 +nuget/nuget/-/Castle.Core/5.1.1, Apache-2.0, approved, #13966 +nuget/nuget/-/EFCore.NamingConventions/8.0.3, Apache-2.0, approved, #13983 +nuget/nuget/-/FakeItEasy/8.1.0, MIT, approved, #13970 nuget/nuget/-/Fare/2.1.1, MIT, approved, clearlydefined nuget/nuget/-/FluentAssertions/6.11.0, Apache-2.0 AND MIT, approved, #10061 +nuget/nuget/-/FluentAssertions/6.12.0, MIT AND Apache-2.0 AND BSD-3-Clause AND CC-BY-3.0-US AND (GPL-2.0-only OR MIT) AND OFL-1.1 AND WTFPL, approved, #13976 nuget/nuget/-/Flurl.Signed/3.0.6, MIT, approved, #3501 nuget/nuget/-/Humanizer.Core/2.14.1, MIT, approved, #10060 nuget/nuget/-/Mono.TextTemplating/2.2.1, MIT, approved, clearlydefined nuget/nuget/-/Newtonsoft.Json/13.0.1, MIT AND BSD-3-Clause, approved, #3266 nuget/nuget/-/Newtonsoft.Json/13.0.3, MIT AND BSD-3-Clause, approved, #3266 -nuget/nuget/-/Npgsql.EntityFrameworkCore.PostgreSQL/7.0.11, PostgreSQL AND MIT AND Apache-2.0, approved, #10081 -nuget/nuget/-/Npgsql/7.0.6, PostgreSQL, approved, #10062 -nuget/nuget/-/Portable.BouncyCastle/1.9.0, MIT, approved, clearlydefined -nuget/nuget/-/SSH.NET/2020.0.2, MIT AND ISC AND LicenseRef-Public-domain AND (MIT AND MS-PL), approved, #10073 -nuget/nuget/-/Serilog.AspNetCore/7.0.0, Apache-2.0 AND MIT, approved, #10084 +nuget/nuget/-/Npgsql.EntityFrameworkCore.PostgreSQL/8.0.2, PostgreSQL AND MIT, approved, #13972 +nuget/nuget/-/Npgsql/8.0.2, PostgreSQL, approved, #13963 +nuget/nuget/-/SSH.NET/2023.0.0, MIT AND (MIT AND MS-PL) AND ISC, approved, #13965 +nuget/nuget/-/Serilog.AspNetCore/8.0.1, Apache-2.0 AND MIT, approved, #13967 nuget/nuget/-/Serilog.Enrichers.CorrelationId/3.0.1, MIT, approved, clearlydefined -nuget/nuget/-/Serilog.Enrichers.Environment/2.2.0, Apache-2.0, approved, clearlydefined +nuget/nuget/-/Serilog.Enrichers.Environment/2.3.0, Apache-2.0, approved, #13959 nuget/nuget/-/Serilog.Enrichers.Process/2.0.2, Apache-2.0, approved, clearlydefined nuget/nuget/-/Serilog.Enrichers.Sensitive/1.7.3, MIT, approved, clearlydefined nuget/nuget/-/Serilog.Enrichers.Thread/3.1.0, Apache-2.0, approved, clearlydefined -nuget/nuget/-/Serilog.Extensions.Hosting/7.0.0, Apache-2.0, approved, #10078 -nuget/nuget/-/Serilog.Extensions.Logging/7.0.0, Apache-2.0, approved, #10070 -nuget/nuget/-/Serilog.Formatting.Compact/1.1.0, Apache-2.0, approved, #11115 -nuget/nuget/-/Serilog.Settings.Configuration/7.0.0, Apache-2.0, approved, #10069 -nuget/nuget/-/Serilog.Sinks.Console/4.1.0, Apache-2.0, approved, #8434 +nuget/nuget/-/Serilog.Extensions.Hosting/8.0.0, Apache-2.0, approved, #13962 +nuget/nuget/-/Serilog.Extensions.Logging/8.0.0, Apache-2.0, approved, #13985 +nuget/nuget/-/Serilog.Formatting.Compact/2.0.0, Apache-2.0, approved, #13981 +nuget/nuget/-/Serilog.Settings.Configuration/8.0.0, Apache-2.0, approved, #13988 +nuget/nuget/-/Serilog.Sinks.Console/5.0.1, Apache-2.0, approved, #13980 nuget/nuget/-/Serilog.Sinks.Debug/2.0.0, Apache-2.0, approved, clearlydefined nuget/nuget/-/Serilog.Sinks.File/5.0.0, Apache-2.0, approved, #11116 -nuget/nuget/-/Serilog/3.0.1, Apache-2.0, approved, #10063 +nuget/nuget/-/Serilog/3.1.1, Apache-2.0, approved, #13978 nuget/nuget/-/SharpZipLib/1.4.2, MIT AND GFDL-1.3-or-later AND (Apache-2.0 AND MIT) AND WTFPL AND bzip2-1.0.6 AND LicenseRef-Permissive-license-with-conditions AND LicenseRef-Permission-Notice, approved, #10058 nuget/nuget/-/SshNet.Security.Cryptography/1.3.0, MIT, approved, clearlydefined nuget/nuget/-/Swashbuckle.AspNetCore.Swagger/6.5.0, MIT AND Apache-2.0, approved, #7160 nuget/nuget/-/Swashbuckle.AspNetCore.SwaggerGen/6.5.0, MIT AND Apache-2.0, approved, #7156 nuget/nuget/-/Swashbuckle.AspNetCore.SwaggerUI/6.5.0, MIT AND Apache-2.0, approved, #7158 nuget/nuget/-/Swashbuckle.AspNetCore/6.5.0, MIT AND Apache-2.0, approved, #7159 -nuget/nuget/-/Testcontainers.PostgreSql/3.4.0, MIT, approved, #10056 -nuget/nuget/-/Testcontainers/3.4.0, MIT, approved, #10083 +nuget/nuget/-/Testcontainers.PostgreSql/3.7.0, MIT, approved, #13960 +nuget/nuget/-/Testcontainers/3.7.0, MIT, approved, #13982 nuget/nuget/-/Xunit.Extensions.AssemblyFixture/2.4.1, MIT, approved, #3502 -nuget/nuget/-/coverlet.collector/6.0.0, MIT, approved, #10075 +nuget/nuget/-/coverlet.collector/6.0.2, MIT, approved, #10075 nuget/nuget/-/xunit.abstractions/2.0.3, Apache-2.0, approved, clearlydefined -nuget/nuget/-/xunit.analyzers/1.2.0, Apache-2.0 AND MIT, approved, #10068 -nuget/nuget/-/xunit.assert/2.5.0, Apache-2.0 AND MIT, approved, #10071 -nuget/nuget/-/xunit.core/2.5.0, Apache-2.0 AND MIT, approved, #10059 -nuget/nuget/-/xunit.extensibility.core/2.5.0, Apache-2.0 AND MIT, approved, #10077 -nuget/nuget/-/xunit.extensibility.execution/2.5.0, Apache-2.0 AND MIT, approved, #10074 -nuget/nuget/-/xunit.runner.visualstudio/2.5.0, Apache-2.0 AND MIT, approved, #10065 -nuget/nuget/-/xunit/2.5.0, Apache-2.0 AND MIT, approved, #10072 +nuget/nuget/-/xunit.analyzers/1.11.0, Apache-2.0 AND MIT, approved, #14197 +nuget/nuget/-/xunit.assert/2.7.0, Apache-2.0 AND MIT, approved, #13971 +nuget/nuget/-/xunit.core/2.7.0, Apache-2.0, approved, #13979 +nuget/nuget/-/xunit.extensibility.core/2.7.0, Apache-2.0 AND MIT, approved, #13974 +nuget/nuget/-/xunit.extensibility.execution/2.7.0, Apache-2.0, approved, #13977 +nuget/nuget/-/xunit.runner.visualstudio/2.5.7, Apache-2.0 AND MIT, approved, #10065 +nuget/nuget/-/xunit/2.7.0, Apache-2.0 AND MIT, approved, #13969 diff --git a/README.md b/README.md index aa51790..5500c69 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ For **installation** details, please refer to the [README.md](./charts/policy-hu ## How to build and run -Install the [.NET 7.0 SDK](https://www.microsoft.com/net/download). +Install the [.NET 8.0 SDK](https://www.microsoft.com/net/download). Run the following command from the CLI: diff --git a/charts/policy-hub/Chart.yaml b/charts/policy-hub/Chart.yaml index 1b4c3bc..b078511 100644 --- a/charts/policy-hub/Chart.yaml +++ b/charts/policy-hub/Chart.yaml @@ -20,8 +20,8 @@ apiVersion: v2 name: policy-hub type: application -version: 0.1.0 -appVersion: 0.1.0 +version: 1.0.0-rc.1 +appVersion: 1.0.0-rc.1 description: Helm chart for Policy Hub home: https://github.com/eclipse-tractusx/policy-hub dependencies: diff --git a/charts/policy-hub/README.md b/charts/policy-hub/README.md index 6093b26..d929ac7 100644 --- a/charts/policy-hub/README.md +++ b/charts/policy-hub/README.md @@ -27,7 +27,7 @@ To use the helm chart as a dependency: dependencies: - name: policy-hub repository: https://eclipse-tractusx.github.io/charts/dev - version: 0.1.0 + version: 1.0.0-rc.1 ``` ## Requirements @@ -40,48 +40,37 @@ dependencies: | Key | Type | Default | Description | |-----|------|---------|-------------| -| centralidpAddress | string | `"https://centralidp.example.org"` | Provide centralidp base address (CX IAM), without trailing '/auth'. | -| ingress.enabled | bool | `false` | Policy Hub ingress parameters, enable ingress record generation for policy-hub. | -| ingress.className | string | `"nginx"` | | -| ingress.annotations."nginx.ingress.kubernetes.io/use-regex" | string | `"true"` | | -| ingress.annotations."nginx.ingress.kubernetes.io/enable-cors" | string | `"true"` | | -| ingress.annotations."nginx.ingress.kubernetes.io/proxy-body-size" | string | `"8m"` | | -| ingress.annotations."nginx.ingress.kubernetes.io/cors-allow-origin" | string | `"https://*.example.org"` | Provide CORS allowed origin. | -| ingress.tls[0] | object | `{"hosts":["policy-hub.example.org"],"secretName":""}` | Provide tls secret. | -| ingress.tls[0].hosts | list | `["policy-hub.example.org"]` | Provide host for tls secret. | -| ingress.hosts[0] | object | `{"host":"policy-hub.example.org","paths":[{"path":"/api/policy-hub","pathType":"Prefix"}]}` | Provide default path for the ingress record. | -| dotnetEnvironment | string | `"Production"` | | -| dbConnection.schema | string | `"hub"` | | -| dbConnection.sslMode | string | `"Disable"` | | -| keycloak.central.authRealm | string | `"CX-Central"` | | -| keycloak.central.jwtBearerOptions.requireHttpsMetadata | string | `"true"` | | -| keycloak.central.jwtBearerOptions.metadataPath | string | `"/auth/realms/CX-Central/.well-known/openid-configuration"` | | -| keycloak.central.jwtBearerOptions.tokenValidationParameters.validIssuerPath | string | `"/auth/realms/CX-Central"` | | -| keycloak.central.jwtBearerOptions.tokenValidationParameters.validAudience | string | `"Cl23-CX-Policy-Hub"` | | -| keycloak.central.jwtBearerOptions.refreshInterval | string | `"00:00:30"` | | -| keycloak.central.tokenPath | string | `"/auth/realms/CX-Central/protocol/openid-connect/token"` | | -| keycloak.central.useAuthTrail | bool | `true` | Flag if the api should be used with an leading /auth path | -| healthChecks.startup.path | string | `"/health/startup"` | | -| healthChecks.liveness.path | string | `"/healthz"` | | -| healthChecks.readyness.path | string | `"/ready"` | | -| policyhub.image | string | `"docker.io/tractusx/policy-hub-service:0.1.0"` | | +| policyhub.image.name | string | `"docker.io/tractusx/policy-hub-service"` | | +| policyhub.image.tag | string | `""` | | | policyhub.imagePullPolicy | string | `"IfNotPresent"` | | -| policyhub.resources | object | `{"requests":{"cpu":"15m","memory":"300M"}}` | We recommend not to specify default resource limits and to leave this as a conscious choice for the user. If you do want to specify resource limits, uncomment the following lines and adjust them as necessary. | +| policyhub.resources | object | `{"limits":{"cpu":"45m","memory":"300M"},"requests":{"cpu":"15m","memory":"300M"}}` | We recommend to review the default resource limits as this should a conscious choice. | | policyhub.logging.businessLogic | string | `"Information"` | | | policyhub.logging.default | string | `"Information"` | | +| policyhub.healthChecks.startup.path | string | `"/health/startup"` | | | policyhub.healthChecks.startup.tags[0].name | string | `"HEALTHCHECKS__0__TAGS__1"` | | | policyhub.healthChecks.startup.tags[0].value | string | `"policyhubdb"` | | +| policyhub.healthChecks.liveness.path | string | `"/healthz"` | | +| policyhub.healthChecks.readyness.path | string | `"/ready"` | | | policyhub.swaggerEnabled | bool | `false` | | -| policyhubmigrations.image | string | `"docker.io/tractusx/policy-hub-migrations:0.1.0"` | | +| policyhubmigrations.image.name | string | `"docker.io/tractusx/policy-hub-migrations"` | | +| policyhubmigrations.image.tag | string | `""` | | | policyhubmigrations.imagePullPolicy | string | `"IfNotPresent"` | | -| policyhubmigrations.resources | object | `{"requests":{"cpu":"15m","memory":"105M"}}` | We recommend not to specify default resource limits and to leave this as a conscious choice for the user. If you do want to specify resource limits, uncomment the following lines and adjust them as necessary. | +| policyhubmigrations.resources | object | `{"limits":{"cpu":"45m","memory":"105M"},"requests":{"cpu":"15m","memory":"105M"}}` | We recommend to review the default resource limits as this should a conscious choice. | | policyhubmigrations.seeding.testDataEnvironments | string | `""` | | | policyhubmigrations.seeding.testDataPaths | string | `"Seeder/Data"` | | | policyhubmigrations.logging.default | string | `"Information"` | | +| dotnetEnvironment | string | `"Production"` | | +| dbConnection.schema | string | `"hub"` | | +| dbConnection.sslMode | string | `"Disable"` | | | postgresql.enabled | bool | `true` | PostgreSQL chart configuration; default configurations: host: "policy-hub-postgresql-primary", port: 5432; Switch to enable or disable the PostgreSQL helm chart. | +| postgresql.image | object | `{"tag":"15-debian-11"}` | Setting image tag to major to get latest minor updates | +| postgresql.commonLabels."app.kubernetes.io/version" | string | `"15"` | | | postgresql.auth.username | string | `"hub"` | Non-root username. | | postgresql.auth.database | string | `"policy-hub"` | Database name. | | postgresql.auth.existingSecret | string | `"{{ .Release.Name }}-phub-postgres"` | Secret containing the passwords for root usernames postgres and non-root username hub. Should not be changed without changing the "phub-postgresSecretName" template as well. | +| postgresql.auth.postgrespassword | string | `""` | Password for the root username 'postgres'. Secret-key 'postgres-password'. | +| postgresql.auth.password | string | `""` | Password for the non-root username 'hub'. Secret-key 'password'. | +| postgresql.auth.replicationPassword | string | `""` | Password for the non-root username 'repl_user'. Secret-key 'replication-password'. | | postgresql.architecture | string | `"replication"` | | | postgresql.audit.pgAuditLog | string | `"write, ddl"` | | | postgresql.audit.logLinePrefix | string | `"%m %u %d "` | | @@ -90,14 +79,17 @@ dependencies: | postgresql.readReplicas.extendedConfiguration | string | `""` | Extended PostgreSQL read only replicas configuration (increase of max_connections recommended - default is 100) | | externalDatabase.host | string | `"phub-postgres-ext"` | External PostgreSQL configuration IMPORTANT: non-root db user needs to be created beforehand on external database. And the init script (02-init-db.sql) available in templates/configmap-postgres-init.yaml needs to be executed beforehand. Database host ('-primary' is added as postfix). | | externalDatabase.port | int | `5432` | Database port number. | -| externalDatabase.user | string | `"hub"` | Non-root username for policy-hub. | +| externalDatabase.username | string | `"hub"` | Non-root username for policy-hub. | | externalDatabase.database | string | `"policy-hub"` | Database name. | | externalDatabase.password | string | `""` | Password for the non-root username (default 'hub'). Secret-key 'password'. | | externalDatabase.existingSecret | string | `"policy-hub-external-db"` | Secret containing the password non-root username, (default 'hub'). | -| externalDatabase.existingSecretPasswordKey | string | `"password"` | Name of an existing secret key containing the database credentials. | -| secrets.postgresql.auth.existingSecret.postgrespassword | string | `""` | Password for the root username 'postgres'. Secret-key 'postgres-password'. | -| secrets.postgresql.auth.existingSecret.password | string | `""` | Password for the non-root username 'hub'. Secret-key 'password'. | -| secrets.postgresql.auth.existingSecret.replicationPassword | string | `""` | Password for the non-root username 'repl_user'. Secret-key 'replication-password'. | +| centralidp | object | `{"address":"https://centralidp.example.org","authRealm":"CX-Central","jwtBearerOptions":{"metadataPath":"/auth/realms/CX-Central/.well-known/openid-configuration","refreshInterval":"00:00:30","requireHttpsMetadata":"true","tokenValidationParameters":{"validAudience":"Cl23-CX-Policy-Hub","validIssuerPath":"/auth/realms/CX-Central"}},"tokenPath":"/auth/realms/CX-Central/protocol/openid-connect/token","useAuthTrail":true}` | Provide details about centralidp (CX IAM) Keycloak instance. | +| centralidp.address | string | `"https://centralidp.example.org"` | Provide centralidp base address (CX IAM), without trailing '/auth'. | +| centralidp.useAuthTrail | bool | `true` | Flag if the api should be used with an leading /auth path | +| ingress.enabled | bool | `false` | Policy Hub ingress parameters, enable ingress record generation for policy-hub. | +| ingress.tls[0] | object | `{"hosts":[""],"secretName":""}` | Provide tls secret. | +| ingress.tls[0].hosts | list | `[""]` | Provide host for tls secret. | +| ingress.hosts[0] | object | `{"host":"","paths":[{"path":"/api/policy-hub","pathType":"Prefix"}]}` | Provide default path for the ingress record. | | portContainer | int | `8080` | | | portService | int | `8080` | | | replicaCount | int | `3` | | diff --git a/charts/policy-hub/templates/_helpers.tpl b/charts/policy-hub/templates/_helpers.tpl index 7d7c033..aa57569 100644 --- a/charts/policy-hub/templates/_helpers.tpl +++ b/charts/policy-hub/templates/_helpers.tpl @@ -1,3 +1,22 @@ +{{- /* +* 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 +*/}} + {{/* Expand the name of the chart. */}} diff --git a/charts/policy-hub/templates/deployment-hub.yaml b/charts/policy-hub/templates/deployment-hub.yaml index dddacb5..eb5ceb6 100644 --- a/charts/policy-hub/templates/deployment-hub.yaml +++ b/charts/policy-hub/templates/deployment-hub.yaml @@ -45,7 +45,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "{{ .Values.policyhub.image }}" + image: "{{ .Values.policyhub.image.name }}:{{ .Values.policyhub.image.tag | default .Chart.AppVersion }}" imagePullPolicy: "{{ .Values.policyhub.imagePullPolicy }}" env: - name: DOTNET_ENVIRONMENT @@ -69,24 +69,24 @@ spec: value: "Server={{ .Values.externalDatabase.host }};Database={{ .Values.externalDatabase.database }};Port={{ .Values.externalDatabase.port }};User Id={{ .Values.externalDatabase.username }};Password=$(POLICY_HUB_PASSWORD);Ssl Mode={{ .Values.dbConnection.sslMode }};" {{- end }} - name: "HEALTHCHECKS__0__PATH" - value: "{{ .Values.healthChecks.startup.path}}" + value: "{{ .Values.policyhub.healthChecks.startup.path}}" {{- if .Values.policyhub.healthChecks.startup.tags }} {{- toYaml .Values.policyhub.healthChecks.startup.tags | nindent 8 }} {{- end }} - name: "HEALTHCHECKS__1__PATH" - value: "{{ .Values.healthChecks.readyness.path}}" + value: "{{ .Values.policyhub.healthChecks.readyness.path}}" - name: "HEALTHCHECKS__2__PATH" - value: "{{ .Values.healthChecks.liveness.path}}" + value: "{{ .Values.policyhub.healthChecks.liveness.path}}" - name: "JWTBEAREROPTIONS__METADATAADDRESS" - value: "{{ .Values.centralidpAddress }}{{ .Values.keycloak.central.jwtBearerOptions.metadataPath }}" + value: "{{ .Values.centralidp.address }}{{ .Values.centralidp.jwtBearerOptions.metadataPath }}" - name: "JWTBEAREROPTIONS__REQUIREHTTPSMETADATA" - value: "{{ .Values.keycloak.central.jwtBearerOptions.requireHttpsMetadata }}" + value: "{{ .Values.centralidp.jwtBearerOptions.requireHttpsMetadata }}" - name: "JWTBEAREROPTIONS__TOKENVALIDATIONPARAMETERS__VALIDAUDIENCE" - value: "{{ .Values.keycloak.central.jwtBearerOptions.tokenValidationParameters.validAudience }}" + value: "{{ .Values.centralidp.jwtBearerOptions.tokenValidationParameters.validAudience }}" - name: "JWTBEAREROPTIONS__TOKENVALIDATIONPARAMETERS__VALIDISSUER" - value: "{{ .Values.centralidpAddress }}{{ .Values.keycloak.central.jwtBearerOptions.tokenValidationParameters.validIssuerPath }}" + value: "{{ .Values.centralidp.address }}{{ .Values.centralidp.jwtBearerOptions.tokenValidationParameters.validIssuerPath }}" - name: "JWTBEAREROPTIONS__REFRESHINTERVAL" - value: "{{ .Values.keycloak.central.jwtBearerOptions.refreshInterval }}" + value: "{{ .Values.centralidp.jwtBearerOptions.refreshInterval }}" - name: "SERILOG__MINIMUMLEVEL__Default" value: "{{ .Values.policyhub.logging.default }}" - name: "SERILOG__MINIMUMLEVEL__OVERRIDE__Org.Eclipse.TractusX.PolicyHub.Service" @@ -99,7 +99,7 @@ spec: protocol: TCP startupProbe: httpGet: - path: {{ .Values.healthChecks.startup.path }} + path: {{ .Values.policyhub.healthChecks.startup.path }} port: {{ .Values.portContainer }} scheme: HTTP initialDelaySeconds: {{ .Values.startupProbe.initialDelaySeconds }} @@ -109,7 +109,7 @@ spec: failureThreshold: {{ .Values.startupProbe.failureThreshold }} livenessProbe: httpGet: - path: {{ .Values.healthChecks.liveness.path }} + path: {{ .Values.policyhub.healthChecks.liveness.path }} port: {{ .Values.portContainer }} scheme: HTTP initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} @@ -119,7 +119,7 @@ spec: failureThreshold: {{ .Values.livenessProbe.failureThreshold }} readinessProbe: httpGet: - path: {{ .Values.healthChecks.readyness.path }} + path: {{ .Values.policyhub.healthChecks.readyness.path }} port: {{ .Values.portContainer }} scheme: HTTP initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} diff --git a/charts/policy-hub/templates/job-policy-hub-migrations.yaml b/charts/policy-hub/templates/job-policy-hub-migrations.yaml index 518b570..ebc785b 100644 --- a/charts/policy-hub/templates/job-policy-hub-migrations.yaml +++ b/charts/policy-hub/templates/job-policy-hub-migrations.yaml @@ -43,7 +43,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: "{{ .Values.policyhubmigrations.image }}" + image: "{{ .Values.policyhubmigrations.image.name }}:{{ .Values.policyhubmigrations.image.tag | default .Chart.AppVersion }}" imagePullPolicy: "{{ .Values.policyhubmigrations.imagePullPolicy }}" env: - name: DOTNET_ENVIRONMENT diff --git a/charts/policy-hub/templates/secret-external-db.yaml b/charts/policy-hub/templates/secret-external-db.yaml index 550d37a..a740c9e 100644 --- a/charts/policy-hub/templates/secret-external-db.yaml +++ b/charts/policy-hub/templates/secret-external-db.yaml @@ -24,7 +24,7 @@ metadata: name: {{ .Values.externalDatabase.existingSecret }} namespace: {{ .Release.Namespace }} labels: - {{- include "portal.labels" . | nindent 4 }} + {{- include "phub.labels" . | nindent 4 }} type: Opaque # use lookup function to check if secret exists {{- $secret := (lookup "v1" "Secret" .Release.Namespace .Values.externalDatabase.existingSecret) }} diff --git a/charts/policy-hub/templates/secret-postgres.yaml b/charts/policy-hub/templates/secret-postgres.yaml index 4606147..acd4f48 100644 --- a/charts/policy-hub/templates/secret-postgres.yaml +++ b/charts/policy-hub/templates/secret-postgres.yaml @@ -34,14 +34,14 @@ data: # if secret exists, use value provided from values file (to cover update scenario) or existing value from secret # use data map instead of stringData to prevent base64 encoding of already base64-encoded existing value from secret # use index function for secret keys with hyphen otherwise '$secret.data.secretKey' works too - postgres-password: {{ ( .Values.secrets.postgresql.auth.existingSecret.postgrespassword | b64enc ) | default ( index $secret.data "postgres-password" ) | quote }} - password: {{ ( .Values.secrets.postgresql.auth.existingSecret.password | b64enc ) | default $secret.data.password | quote }} - replication-password: {{ ( .Values.secrets.postgresql.auth.existingSecret.replicationPassword | b64enc ) | default ( index $secret.data "replication-password" ) | quote}} + postgres-password: {{ ( .Values.postgresql.auth.postgrespassword | b64enc ) | default ( index $secret.data "postgres-password" ) | quote }} + password: {{ ( .Values.postgresql.auth.password | b64enc ) | default $secret.data.password | quote }} + replication-password: {{ ( .Values.postgresql.auth.replicationPassword | b64enc ) | default ( index $secret.data "replication-password" ) | quote}} {{ else -}} stringData: # if secret doesn't exist, use provided value from values file or generate a random one - postgres-password: {{ .Values.secrets.postgresql.auth.existingSecret.postgrespassword | default ( randAlphaNum 32 ) | quote }} - password: {{ .Values.secrets.postgresql.auth.existingSecret.password | default ( randAlphaNum 32 ) | quote }} - replication-password: {{ .Values.secrets.postgresql.auth.existingSecret.replicationPassword | default ( randAlphaNum 32 ) | quote }} + postgres-password: {{ .Values.postgresql.auth.postgrespassword | default ( randAlphaNum 32 ) | quote }} + password: {{ .Values.postgresql.auth.password | default ( randAlphaNum 32 ) | quote }} + replication-password: {{ .Values.postgresql.auth.replicationPassword | default ( randAlphaNum 32 ) | quote }} {{ end }} {{- end -}} diff --git a/charts/policy-hub/values.yaml b/charts/policy-hub/values.yaml index c4c51c8..c9a9a77 100644 --- a/charts/policy-hub/values.yaml +++ b/charts/policy-hub/values.yaml @@ -17,100 +17,59 @@ # SPDX-License-Identifier: Apache-2.0 ############################################################### -# -- Provide centralidp base address (CX IAM), without trailing '/auth'. -centralidpAddress: "https://centralidp.example.org" - -ingress: - # -- Policy Hub ingress parameters, - # enable ingress record generation for policy-hub. - enabled: false - className: "nginx" - annotations: - nginx.ingress.kubernetes.io/use-regex: "true" - nginx.ingress.kubernetes.io/enable-cors: "true" - nginx.ingress.kubernetes.io/proxy-body-size: "8m" - # -- Provide CORS allowed origin. - nginx.ingress.kubernetes.io/cors-allow-origin: "https://*.example.org" - tls: - # -- Provide tls secret. - - secretName: "" - # -- Provide host for tls secret. - hosts: - - "policy-hub.example.org" - hosts: - # -- Provide default path for the ingress record. - - host: "policy-hub.example.org" - paths: - - path: "/api/policy-hub" - pathType: "Prefix" - -dotnetEnvironment: "Production" - -dbConnection: - schema: "hub" - sslMode: "Disable" - -keycloak: - central: - authRealm: "CX-Central" - jwtBearerOptions: - requireHttpsMetadata: "true" - metadataPath: "/auth/realms/CX-Central/.well-known/openid-configuration" - tokenValidationParameters: - validIssuerPath: "/auth/realms/CX-Central" - validAudience: "Cl23-CX-Policy-Hub" - refreshInterval: "00:00:30" - tokenPath: "/auth/realms/CX-Central/protocol/openid-connect/token" - # -- Flag if the api should be used with an leading /auth path - useAuthTrail: true -healthChecks: - startup: - path: "/health/startup" - liveness: - path: "/healthz" - readyness: - path: "/ready" - policyhub: - image: "docker.io/tractusx/policy-hub-service:0.1.0" + image: + name: "docker.io/tractusx/policy-hub-service" + tag: "" imagePullPolicy: "IfNotPresent" - # -- We recommend not to specify default resource limits and to leave this as a conscious choice for the user. - # If you do want to specify resource limits, uncomment the following lines and adjust them as necessary. + # -- We recommend to review the default resource limits as this should a conscious choice. resources: requests: cpu: 15m memory: 300M - # limits: - # cpu: 45m - # memory: 400M + limits: + cpu: 45m + memory: 300M logging: businessLogic: "Information" default: "Information" healthChecks: startup: + path: "/health/startup" tags: - name: "HEALTHCHECKS__0__TAGS__1" value: "policyhubdb" + liveness: + path: "/healthz" + readyness: + path: "/ready" swaggerEnabled: false policyhubmigrations: - image: "docker.io/tractusx/policy-hub-migrations:0.1.0" + image: + name: "docker.io/tractusx/policy-hub-migrations" + tag: "" imagePullPolicy: "IfNotPresent" - # -- We recommend not to specify default resource limits and to leave this as a conscious choice for the user. - # If you do want to specify resource limits, uncomment the following lines and adjust them as necessary. + # -- We recommend to review the default resource limits as this should a conscious choice. resources: requests: cpu: 15m memory: 105M - # limits: - # cpu: 45m - # memory: 105M + limits: + cpu: 45m + memory: 105M seeding: testDataEnvironments: "" testDataPaths: "Seeder/Data" logging: default: "Information" +dotnetEnvironment: "Production" + +dbConnection: + schema: "hub" + sslMode: "Disable" + postgresql: # -- PostgreSQL chart configuration; # default configurations: @@ -118,6 +77,11 @@ postgresql: # port: 5432; # Switch to enable or disable the PostgreSQL helm chart. enabled: true + # -- Setting image tag to major to get latest minor updates + image: + tag: "15-debian-11" + commonLabels: + app.kubernetes.io/version: "15" auth: # -- Non-root username. username: hub @@ -126,6 +90,12 @@ postgresql: # -- Secret containing the passwords for root usernames postgres and non-root username hub. # Should not be changed without changing the "phub-postgresSecretName" template as well. existingSecret: "{{ .Release.Name }}-phub-postgres" + # -- Password for the root username 'postgres'. Secret-key 'postgres-password'. + postgrespassword: "" + # -- Password for the non-root username 'hub'. Secret-key 'password'. + password: "" + # -- Password for the non-root username 'repl_user'. Secret-key 'replication-password'. + replicationPassword: "" architecture: replication audit: pgAuditLog: "write, ddl" @@ -149,26 +119,54 @@ externalDatabase: # -- Database port number. port: 5432 # -- Non-root username for policy-hub. - user: "hub" + username: "hub" # -- Database name. database: "policy-hub" # -- Password for the non-root username (default 'hub'). Secret-key 'password'. password: "" # -- Secret containing the password non-root username, (default 'hub'). existingSecret: "policy-hub-external-db" - # -- Name of an existing secret key containing the database credentials. - existingSecretPasswordKey: "password" - -secrets: - postgresql: - auth: - existingSecret: - # -- Password for the root username 'postgres'. Secret-key 'postgres-password'. - postgrespassword: "" - # -- Password for the non-root username 'hub'. Secret-key 'password'. - password: "" - # -- Password for the non-root username 'repl_user'. Secret-key 'replication-password'. - replicationPassword: "" + +# -- Provide details about centralidp (CX IAM) Keycloak instance. +centralidp: + # -- Provide centralidp base address (CX IAM), without trailing '/auth'. + address: "https://centralidp.example.org" + authRealm: "CX-Central" + jwtBearerOptions: + requireHttpsMetadata: "true" + metadataPath: "/auth/realms/CX-Central/.well-known/openid-configuration" + tokenValidationParameters: + validIssuerPath: "/auth/realms/CX-Central" + validAudience: "Cl23-CX-Policy-Hub" + refreshInterval: "00:00:30" + tokenPath: "/auth/realms/CX-Central/protocol/openid-connect/token" + # -- Flag if the api should be used with an leading /auth path + useAuthTrail: true + +ingress: + # -- Policy Hub ingress parameters, + # enable ingress record generation for policy-hub. + enabled: false + # className: "nginx" + ## Optional annotations when using the nginx ingress class + # annotations: + # nginx.ingress.kubernetes.io/use-regex: "true" + # nginx.ingress.kubernetes.io/enable-cors: "true" + # nginx.ingress.kubernetes.io/proxy-body-size: "8m" + # # -- Provide CORS allowed origin. + # nginx.ingress.kubernetes.io/cors-allow-origin: "https://*.example.org" + tls: + # -- Provide tls secret. + - secretName: "" + # -- Provide host for tls secret. + hosts: + - "" + hosts: + # -- Provide default path for the ingress record. + - host: "" + paths: + - path: "/api/policy-hub" + pathType: "Prefix" portContainer: 8080 diff --git a/consortia/argocd-app-templates/appsetup-beta.yaml b/consortia/argocd-app-templates/appsetup-beta.yaml index 3f56806..04846ec 100644 --- a/consortia/argocd-app-templates/appsetup-beta.yaml +++ b/consortia/argocd-app-templates/appsetup-beta.yaml @@ -28,7 +28,7 @@ spec: source: path: charts/policy-hub repoURL: 'https://github.com/eclipse-tractusx/policy-hub.git' - targetRevision: policy-hub-1.0.0 + targetRevision: policy-hub-1.0.0-rc.1 plugin: env: - name: AVP_SECRET diff --git a/consortia/argocd-app-templates/appsetup-int.yaml b/consortia/argocd-app-templates/appsetup-int.yaml index b097ad9..625dc10 100644 --- a/consortia/argocd-app-templates/appsetup-int.yaml +++ b/consortia/argocd-app-templates/appsetup-int.yaml @@ -28,7 +28,7 @@ spec: source: path: charts/policy-hub repoURL: 'https://github.com/eclipse-tractusx/policy-hub.git' - targetRevision: policy-hub-0.1.0 + targetRevision: policy-hub-1.0.0-rc.1 plugin: env: - name: AVP_SECRET diff --git a/consortia/argocd-app-templates/appsetup-pen.yaml b/consortia/argocd-app-templates/appsetup-pen.yaml index 7807743..41abe6f 100644 --- a/consortia/argocd-app-templates/appsetup-pen.yaml +++ b/consortia/argocd-app-templates/appsetup-pen.yaml @@ -28,7 +28,7 @@ spec: source: path: charts/policy-hub repoURL: 'https://github.com/eclipse-tractusx/policy-hub.git' - targetRevision: policy-hub-0.1.0 + targetRevision: policy-hub-1.0.0-rc.1 plugin: env: - name: AVP_SECRET diff --git a/consortia/argocd-app-templates/appsetup-stable.yaml b/consortia/argocd-app-templates/appsetup-stable.yaml index 3d908c0..e95c581 100644 --- a/consortia/argocd-app-templates/appsetup-stable.yaml +++ b/consortia/argocd-app-templates/appsetup-stable.yaml @@ -29,7 +29,7 @@ spec: source: path: '' repoURL: 'https://eclipse-tractusx.github.io/charts/dev' - targetRevision: policy-hub-0.1.0 + targetRevision: policy-hub-1.0.0-rc.1 plugin: env: - name: HELM_VALUES diff --git a/consortia/environments/values-beta.yaml b/consortia/environments/values-beta.yaml index 01ddbef..2fa43d2 100644 --- a/consortia/environments/values-beta.yaml +++ b/consortia/environments/values-beta.yaml @@ -18,7 +18,8 @@ ############################################################### policyHubBackendAddress: "https://policy-hub.beta.demo.catena-x.net" -centralidpAddress: "https://centralidp.beta.demo.catena-x.net" +centralidp: + address: "https://centralidp.beta.demo.catena-x.net" ingress: enabled: true @@ -45,10 +46,8 @@ policyhubmigrations: logging: default: "Debug" -secrets: - postgresql: - auth: - existingSecret: - postgrespassword: "" - password: "" - replicationPassword: "" +postgresql: + auth: + postgrespassword: "" + password: "" + replicationPassword: "" diff --git a/consortia/environments/values-dev.yaml b/consortia/environments/values-dev.yaml index 9ac129b..30828de 100644 --- a/consortia/environments/values-dev.yaml +++ b/consortia/environments/values-dev.yaml @@ -18,7 +18,8 @@ ############################################################### policyHubAddress: "https://policy-hub.dev.demo.catena-x.net" -centralidpAddress: "https://centralidp.dev.demo.catena-x.net" +centralidp: + address: "https://centralidp.dev.demo.catena-x.net" ingress: enabled: true @@ -45,20 +46,20 @@ keycloak: validAudience: "Cl23-CX-Policy-Hub" policyhub: - image: "docker.io/tractusx/policy-hub-service:dev" + image: + tag: "dev" imagePullPolicy: "Always" swaggerEnabled: true policyhubmigrations: - image: "docker.io/tractusx/policy-hub-migrations:dev" + image: + tag: "dev" imagePullPolicy: "Always" logging: default: "Debug" -secrets: - postgresql: - auth: - existingSecret: - postgrespassword: "" - password: "" - replicationPassword: "" +postgresql: + auth: + postgrespassword: "" + password: "" + replicationPassword: "" diff --git a/consortia/environments/values-int.yaml b/consortia/environments/values-int.yaml index 2c8ce65..f19857a 100644 --- a/consortia/environments/values-int.yaml +++ b/consortia/environments/values-int.yaml @@ -18,7 +18,8 @@ ############################################################### policyHubAddress: "https://policy-hub.int.demo.catena-x.net" -centralidpAddress: "https://centralidp.int.demo.catena-x.net" +centralidp: + address: "https://centralidp.int.demo.catena-x.net" ingress: enabled: true @@ -51,10 +52,8 @@ policyhubmigrations: logging: default: "Debug" -secrets: - postgresql: - auth: - existingSecret: - postgrespassword: "" - password: "" - replicationPassword: "" +postgresql: + auth: + postgrespassword: "" + password: "" + replicationPassword: "" diff --git a/consortia/environments/values-pen.yaml b/consortia/environments/values-pen.yaml index b80707e..7d06373 100644 --- a/consortia/environments/values-pen.yaml +++ b/consortia/environments/values-pen.yaml @@ -18,7 +18,8 @@ ############################################################### policyHubAddress: "https://policy-hub-pen.dev.demo.catena-x.net" -centralidpAddress: "https://centralidp-pen.dev.demo.catena-x.net" +centralidp: + address: "https://centralidp-pen.dev.demo.catena-x.net" ingress: enabled: true @@ -45,10 +46,8 @@ policyhubmigrations: logging: default: "Debug" -secrets: - postgresql: - auth: - existingSecret: - postgrespassword: "" - password: "" - replicationPassword: "" +postgresql: + auth: + postgrespassword: "" + password: "" + replicationPassword: "" diff --git a/consortia/environments/values-rc.yaml b/consortia/environments/values-rc.yaml index 5f909cf..f8adcd3 100644 --- a/consortia/environments/values-rc.yaml +++ b/consortia/environments/values-rc.yaml @@ -18,7 +18,8 @@ ############################################################### policyHubAddress: "https://policy-hub-rc.dev.demo.catena-x.net" -centralidpAddress: "https://centralidp-rc.dev.demo.catena-x.net" +centralidp: + address: "https://centralidp-rc.dev.demo.catena-x.net" ingress: enabled: true @@ -39,20 +40,20 @@ ingress: pathType: "Prefix" policyhub: - image: "docker.io/tractusx/policy-hub-service:rc" + image: + tag: "rc" imagePullPolicy: "Always" swaggerEnabled: true policyhubmigrations: - image: "docker.io/tractusx/policy-hub-migrations:rc" + image: + tag: "rc" imagePullPolicy: "Always" logging: default: "Debug" -secrets: - postgresql: - auth: - existingSecret: - postgrespassword: "" - password: "" - replicationPassword: "" +postgresql: + auth: + postgrespassword: "" + password: "" + replicationPassword: "" diff --git a/consortia/environments/values-upgrade.yaml b/consortia/environments/values-upgrade.yaml deleted file mode 100644 index f613d45..0000000 --- a/consortia/environments/values-upgrade.yaml +++ /dev/null @@ -1,28 +0,0 @@ -############################################################### -# 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 -############################################################### - -replicaCount: 0 - -secrets: - postgresql: - auth: - existingSecret: - postgrespassword: "" - password: "" - replicationPassword: "" diff --git a/docker/Dockerfile-policy-hub-migrations b/docker/Dockerfile-policy-hub-migrations index edcb02e..b25cd2e 100644 --- a/docker/Dockerfile-policy-hub-migrations +++ b/docker/Dockerfile-policy-hub-migrations @@ -17,9 +17,9 @@ # SPDX-License-Identifier: Apache-2.0 ############################################################### -FROM mcr.microsoft.com/dotnet/runtime:7.0-alpine AS base +FROM mcr.microsoft.com/dotnet/runtime:8.0-alpine AS base -FROM mcr.microsoft.com/dotnet/sdk:7.0-alpine-amd64 AS publish +FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine-amd64 AS publish WORKDIR / COPY LICENSE NOTICE.md DEPENDENCIES / COPY /src/database /src/database diff --git a/docker/Dockerfile-policy-hub-service b/docker/Dockerfile-policy-hub-service index 1652752..5f574f0 100644 --- a/docker/Dockerfile-policy-hub-service +++ b/docker/Dockerfile-policy-hub-service @@ -17,9 +17,9 @@ # SPDX-License-Identifier: Apache-2.0 ############################################################### -FROM mcr.microsoft.com/dotnet/aspnet:7.0-alpine AS base +FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine AS base -FROM mcr.microsoft.com/dotnet/sdk:7.0-alpine-amd64 AS publish +FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine-amd64 AS publish WORKDIR / COPY LICENSE NOTICE.md DEPENDENCIES / COPY src/ src/ diff --git a/docker/notice-policy-hub-migrations.md b/docker/notice-policy-hub-migrations.md index e549341..51d8550 100644 --- a/docker/notice-policy-hub-migrations.md +++ b/docker/notice-policy-hub-migrations.md @@ -13,7 +13,7 @@ __Policy Hub Migrations__ __Used base images__ -- Dockerfile: [mcr.microsoft.com/dotnet/runtime:7.0-alpine](https://github.com/dotnet/dotnet-docker/blob/main/src/runtime/7.0/alpine3.19/amd64/Dockerfile) +- Dockerfile: [mcr.microsoft.com/dotnet/runtime:8.0-alpine](https://github.com/dotnet/dotnet-docker/blob/main/src/runtime/8.0/alpine3.19/amd64/Dockerfile) - GitHub project: [https://github.com/dotnet/dotnet-docker](https://github.com/dotnet/dotnet-docker) - DockerHub: [https://hub.docker.com/_/microsoft-dotnet-runtime](https://hub.docker.com/_/microsoft-dotnet-runtime) diff --git a/docker/notice-policy-hub-service.md b/docker/notice-policy-hub-service.md index 6d10d9e..c98f4b1 100644 --- a/docker/notice-policy-hub-service.md +++ b/docker/notice-policy-hub-service.md @@ -13,7 +13,7 @@ __Policy Hub Service__ __Used base images__ -- Dockerfile: [mcr.microsoft.com/dotnet/aspnet:7.0-alpine](https://github.com/dotnet/dotnet-docker/blob/main/src/aspnet/7.0/alpine3.19/amd64/Dockerfile) +- Dockerfile: [mcr.microsoft.com/dotnet/aspnet:8.0-alpine](https://github.com/dotnet/dotnet-docker/blob/main/src/aspnet/8.0/alpine3.19/amd64/Dockerfile) - GitHub project: [https://github.com/dotnet/dotnet-docker](https://github.com/dotnet/dotnet-docker) - DockerHub: [https://hub.docker.com/_/microsoft-dotnet-aspnet](https://hub.docker.com/_/microsoft-dotnet-aspnet) diff --git a/scripts/check-dependencies.md b/scripts/check-dependencies.md index e8bda8d..8b9f8c1 100644 --- a/scripts/check-dependencies.md +++ b/scripts/check-dependencies.md @@ -6,7 +6,7 @@ This workflow uses the executable jar in the download directory. In order to update the executable jar run the following command from the root directory: - curl -L --output ./scripts/download/org.eclipse.dash.licenses-1.1.1.jar 'https://repo.eclipse.org/service/local/artifact/maven/redirect?r=dash-licenses&g=org.eclipse.dash&a=org.eclipse.dash.licenses&v=1.1.1' + curl -L --output ./scripts/download/org.eclipse.dash.licenses-1.1.1.jar 'https://repo.eclipse.org/service/local/artifact/maven/redirect?r=dash-licenses&g=org.eclipse.dash&a=org.eclipse.dash.licenses&v=LATEST' ## NOTICE diff --git a/scripts/download/org.eclipse.dash.licenses-1.1.1-20240213.065029-71.jar b/scripts/download/org.eclipse.dash.licenses-1.1.1.jar similarity index 100% rename from scripts/download/org.eclipse.dash.licenses-1.1.1-20240213.065029-71.jar rename to scripts/download/org.eclipse.dash.licenses-1.1.1.jar diff --git a/src/Directory.Build.props b/src/Directory.Build.props index ad4631c..34d1a3b 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -19,7 +19,7 @@ - 0.1.0 - + 1.0.0 + rc.1 diff --git a/src/database/PolicyHub.DbAccess/PolicyHub.DbAccess.csproj b/src/database/PolicyHub.DbAccess/PolicyHub.DbAccess.csproj index a81179f..724f775 100644 --- a/src/database/PolicyHub.DbAccess/PolicyHub.DbAccess.csproj +++ b/src/database/PolicyHub.DbAccess/PolicyHub.DbAccess.csproj @@ -22,7 +22,7 @@ Org.Eclipse.TractusX.PolicyHub.DbAccess Org.Eclipse.TractusX.PolicyHub.DbAccess - net7.0 + net8.0 enable enable @@ -32,9 +32,9 @@ - - - + + + diff --git a/src/database/PolicyHub.DbAccess/Repositories/IPolicyRepository.cs b/src/database/PolicyHub.DbAccess/Repositories/IPolicyRepository.cs index 641287e..e86260a 100644 --- a/src/database/PolicyHub.DbAccess/Repositories/IPolicyRepository.cs +++ b/src/database/PolicyHub.DbAccess/Repositories/IPolicyRepository.cs @@ -28,4 +28,5 @@ public interface IPolicyRepository IAsyncEnumerable GetPolicyTypes(PolicyTypeId? type, UseCaseId? useCase); Task<(bool Exists, string LeftOperand, (AttributeKeyId? Key, IEnumerable Values) Attributes, string? RightOperandValue)> GetPolicyContentAsync(UseCaseId? useCase, PolicyTypeId type, string credential); IAsyncEnumerable<(string TechnicalKey, string LeftOperand, (AttributeKeyId? Key, IEnumerable Values) Attributes, string? RightOperandValue)> GetPolicyForOperandContent(PolicyTypeId type, IEnumerable technicalKeys); + Task Values)>> GetAttributeValuesForTechnicalKeys(PolicyTypeId type, IEnumerable technicalKeys); } diff --git a/src/database/PolicyHub.DbAccess/Repositories/PolicyRepository.cs b/src/database/PolicyHub.DbAccess/Repositories/PolicyRepository.cs index 60ca3b9..6957b04 100644 --- a/src/database/PolicyHub.DbAccess/Repositories/PolicyRepository.cs +++ b/src/database/PolicyHub.DbAccess/Repositories/PolicyRepository.cs @@ -24,25 +24,20 @@ namespace Org.Eclipse.TractusX.PolicyHub.DbAccess.Repositories; -public class PolicyRepository : IPolicyRepository +public class PolicyRepository(PolicyHubContext dbContext) + : IPolicyRepository { - private readonly PolicyHubContext _dbContext; - - public PolicyRepository(PolicyHubContext dbContext) - { - _dbContext = dbContext; - } - public IAsyncEnumerable GetAttributeKeys() => - _dbContext.AttributeKeys + dbContext.AttributeKeys .Select(x => x.Label) .AsAsyncEnumerable(); public IAsyncEnumerable GetPolicyTypes(PolicyTypeId? type, UseCaseId? useCase) => - _dbContext.Policies + dbContext.Policies .Where(p => - (type == null || p.Types.Any(x => x.Id == type)) && - (useCase == null || p.UseCases.Any(x => x.Id == useCase))) + p.IsActive && + (type == null || p.Types.Any(x => x.Id == type && x.IsActive)) && + (useCase == null || p.UseCases.Any(x => x.Id == useCase && x.IsActive))) .Select(p => new PolicyTypeResponse( p.TechnicalKey, p.Types.Where(t => t.IsActive).Select(t => t.Id), @@ -54,22 +49,31 @@ public IAsyncEnumerable GetPolicyTypes(PolicyTypeId? type, U .AsAsyncEnumerable(); public Task<(bool Exists, string LeftOperand, (AttributeKeyId? Key, IEnumerable Values) Attributes, string? RightOperandValue)> GetPolicyContentAsync(UseCaseId? useCase, PolicyTypeId type, string credential) => - _dbContext.Policies + dbContext.Policies .Where(p => + p.IsActive && p.Types.Any(t => t.IsActive && t.Id == type) && - (useCase == null || p.UseCases.Any(x => x.Id == useCase)) && + (useCase == null || p.UseCases.Any(x => x.Id == useCase && x.IsActive)) && p.TechnicalKey == credential) .Select(p => new ValueTuple>, string?>( true, p.LeftOperandValue ?? p.TechnicalKey, - new ValueTuple>(p.AttributeKeyId, p.AttributeKey!.PolicyAttributes.Where(pa => pa.IsActive && pa.PolicyId == p.Id).Select(a => a.AttributeValue)), + new ValueTuple>( + p.AttributeKeyId, + p.AttributeKey!.PolicyAttributes.Where(pa => + pa.IsActive && + pa.PolicyId == p.Id && + pa.IsActive && + (useCase == null || pa.PolicyAttributeAssignedUseCases.Any(x => x.UseCaseId == useCase && x.IsActive)) + ).Select(a => a.AttributeValue)), p.PolicyKind!.Configuration!.RightOperandValue )) .FirstOrDefaultAsync(); public IAsyncEnumerable<(string TechnicalKey, string LeftOperand, (AttributeKeyId? Key, IEnumerable Values) Attributes, string? RightOperandValue)> GetPolicyForOperandContent(PolicyTypeId type, IEnumerable technicalKeys) => - _dbContext.Policies + dbContext.Policies .Where(p => + p.IsActive && p.Types.Any(t => t.IsActive && t.Id == type) && technicalKeys.Contains(p.TechnicalKey)) .Select(p => new ValueTuple>, string?>( @@ -79,4 +83,16 @@ public IAsyncEnumerable GetPolicyTypes(PolicyTypeId? type, U p.PolicyKind!.Configuration!.RightOperandValue )) .AsAsyncEnumerable(); + + public Task Values)>> GetAttributeValuesForTechnicalKeys(PolicyTypeId type, IEnumerable technicalKeys) => + dbContext.Policies + .Where(p => + p.IsActive && + p.Types.Any(t => t.IsActive && t.Id == type) && + technicalKeys.Contains(p.TechnicalKey)) + .Select(x => new ValueTuple>( + x.TechnicalKey, + x.AttributeKeyId, + x.Attributes.Select(a => a.AttributeValue))) + .ToListAsync(); } diff --git a/src/database/PolicyHub.Entities/Entities/IActiveEntity.cs b/src/database/PolicyHub.Entities/Entities/IActiveEntity.cs new file mode 100644 index 0000000..f95f029 --- /dev/null +++ b/src/database/PolicyHub.Entities/Entities/IActiveEntity.cs @@ -0,0 +1,6 @@ +namespace Org.Eclipse.TractusX.PolicyHub.Entities.Entities; + +public interface IActiveEntity +{ + bool IsActive { get; set; } +} diff --git a/src/database/PolicyHub.Entities/Entities/Policy.cs b/src/database/PolicyHub.Entities/Entities/Policy.cs index 98f410d..356a325 100644 --- a/src/database/PolicyHub.Entities/Entities/Policy.cs +++ b/src/database/PolicyHub.Entities/Entities/Policy.cs @@ -21,7 +21,7 @@ namespace Org.Eclipse.TractusX.PolicyHub.Entities.Entities; -public class Policy +public class Policy : IActiveEntity { private Policy() { diff --git a/src/database/PolicyHub.Entities/Entities/PolicyAttribute.cs b/src/database/PolicyHub.Entities/Entities/PolicyAttribute.cs index 2cfbffb..07830c7 100644 --- a/src/database/PolicyHub.Entities/Entities/PolicyAttribute.cs +++ b/src/database/PolicyHub.Entities/Entities/PolicyAttribute.cs @@ -21,30 +21,35 @@ namespace Org.Eclipse.TractusX.PolicyHub.Entities.Entities; -public class PolicyAttribute +public class PolicyAttribute : IActiveEntity { private PolicyAttribute() { AttributeValue = null!; + PolicyAttributeAssignedUseCases = new HashSet(); } - public PolicyAttribute(Guid policyId, AttributeKeyId key, string attributeValue) + public PolicyAttribute(Guid id, Guid policyId, AttributeKeyId key, string attributeValue) : this() { + Id = id; PolicyId = policyId; Key = key; AttributeValue = attributeValue; } - public Guid PolicyId { get; private set; } + public Guid Id { get; set; } + public Guid PolicyId { get; set; } - public AttributeKeyId Key { get; private set; } + public AttributeKeyId Key { get; set; } - public string AttributeValue { get; private set; } + public string AttributeValue { get; set; } public bool IsActive { get; set; } public virtual Policy? Policy { get; private set; } public virtual AttributeKey? AttributeKey { get; private set; } + + public virtual ICollection PolicyAttributeAssignedUseCases { get; private set; } } diff --git a/src/database/PolicyHub.Entities/Entities/PolicyAttributeAssignedUseCases.cs b/src/database/PolicyHub.Entities/Entities/PolicyAttributeAssignedUseCases.cs new file mode 100644 index 0000000..d32d1f2 --- /dev/null +++ b/src/database/PolicyHub.Entities/Entities/PolicyAttributeAssignedUseCases.cs @@ -0,0 +1,47 @@ +/******************************************************************************** + * Copyright (c) 2024 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 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +namespace Org.Eclipse.TractusX.PolicyHub.Entities.Entities; + +public class PolicyAttributeAssignedUseCases +{ + private PolicyAttributeAssignedUseCases() + { + PolicyAttribute = null!; + UseCase = null!; + } + + public PolicyAttributeAssignedUseCases(Guid attributeId, UseCaseId useCaseId) + : this() + { + AttributeId = attributeId; + UseCaseId = useCaseId; + } + + public Guid AttributeId { get; set; } + + public UseCaseId UseCaseId { get; set; } + + public bool IsActive { get; set; } + + public virtual PolicyAttribute? PolicyAttribute { get; private set; } + public virtual UseCase? UseCase { get; private set; } +} diff --git a/src/database/PolicyHub.Entities/Entities/PolicyType.cs b/src/database/PolicyHub.Entities/Entities/PolicyType.cs index c33f9eb..171011d 100644 --- a/src/database/PolicyHub.Entities/Entities/PolicyType.cs +++ b/src/database/PolicyHub.Entities/Entities/PolicyType.cs @@ -21,7 +21,7 @@ namespace Org.Eclipse.TractusX.PolicyHub.Entities.Entities; -public class PolicyType +public class PolicyType : IActiveEntity { private PolicyType() { diff --git a/src/database/PolicyHub.Entities/Entities/UseCase.cs b/src/database/PolicyHub.Entities/Entities/UseCase.cs index 5849811..166a5a4 100644 --- a/src/database/PolicyHub.Entities/Entities/UseCase.cs +++ b/src/database/PolicyHub.Entities/Entities/UseCase.cs @@ -21,15 +21,17 @@ namespace Org.Eclipse.TractusX.PolicyHub.Entities.Entities; -public class UseCase +public class UseCase : IActiveEntity { private UseCase() { Label = null!; Policies = new HashSet(); + PolicyAttributeAssignedUseCases = new HashSet(); } - public UseCase(UseCaseId useCaseId, bool isActive) : this() + public UseCase(UseCaseId useCaseId, bool isActive) + : this() { Id = useCaseId; Label = useCaseId.ToString(); @@ -43,4 +45,6 @@ public UseCase(UseCaseId useCaseId, bool isActive) : this() // Navigation properties public virtual ICollection Policies { get; private set; } + + public virtual ICollection PolicyAttributeAssignedUseCases { get; private set; } } diff --git a/src/database/PolicyHub.Entities/PolicyHub.Entities.csproj b/src/database/PolicyHub.Entities/PolicyHub.Entities.csproj index f6ac785..014ebdd 100644 --- a/src/database/PolicyHub.Entities/PolicyHub.Entities.csproj +++ b/src/database/PolicyHub.Entities/PolicyHub.Entities.csproj @@ -21,17 +21,17 @@ Org.Eclipse.TractusX.PolicyHub.Entities Org.Eclipse.TractusX.PolicyHub.Entities - net7.0 + net8.0 enable enable - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + diff --git a/src/database/PolicyHub.Entities/PolicyHubContext.cs b/src/database/PolicyHub.Entities/PolicyHubContext.cs index d8ea154..540fe1a 100644 --- a/src/database/PolicyHub.Entities/PolicyHubContext.cs +++ b/src/database/PolicyHub.Entities/PolicyHubContext.cs @@ -111,10 +111,10 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity(entity => { - entity.Property(x => x.IsActive).HasDefaultValue(true); - entity - .HasKey(x => new { x.PolicyId, x.Key, x.AttributeValue }); + .HasKey(x => new { x.Id }); + + entity.Property(x => x.IsActive).HasDefaultValue(true); entity .HasOne(pa => pa.AttributeKey) @@ -127,6 +127,24 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasForeignKey(x => x.PolicyId); }); + modelBuilder.Entity(entity => + { + entity.Property(x => x.IsActive).HasDefaultValue(true); + + entity + .HasKey(x => new { x.AttributeId, x.UseCaseId }); + + entity + .HasOne(pa => pa.PolicyAttribute) + .WithMany(p => p.PolicyAttributeAssignedUseCases) + .HasForeignKey(x => x.AttributeId); + + entity + .HasOne(pa => pa.UseCase) + .WithMany(p => p.PolicyAttributeAssignedUseCases) + .HasForeignKey(x => x.UseCaseId); + }); + modelBuilder.Entity(entity => { entity.Property(x => x.IsActive).HasDefaultValue(true); diff --git a/src/database/PolicyHub.Migrations/Migrations/20240430122950_1.0.0-rc.1.Designer.cs b/src/database/PolicyHub.Migrations/Migrations/20240430122950_1.0.0-rc.1.Designer.cs new file mode 100644 index 0000000..815c2a4 --- /dev/null +++ b/src/database/PolicyHub.Migrations/Migrations/20240430122950_1.0.0-rc.1.Designer.cs @@ -0,0 +1,543 @@ +/******************************************************************************** + * 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 + ********************************************************************************/ + +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Org.Eclipse.TractusX.PolicyHub.Entities; + +#nullable disable + +namespace Org.Eclipse.TractusX.PolicyHub.Migrations.Migrations +{ + [DbContext(typeof(PolicyHubContext))] + [Migration("20240430122950_1.0.0-rc.1")] + partial class _100rc1 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("policy-hub") + .UseCollation("en_US.utf8") + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.AttributeKey", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_attribute_keys"); + + b.ToTable("attribute_keys", "policy-hub"); + + b.HasData( + new + { + Id = 1, + Label = "Regex" + }, + new + { + Id = 2, + Label = "Static" + }, + new + { + Id = 3, + Label = "DynamicValue" + }, + new + { + Id = 4, + Label = "Brands" + }, + new + { + Id = 5, + Label = "Version" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.Policy", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AttributeKeyId") + .HasColumnType("integer") + .HasColumnName("attribute_key_id"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("IsActive") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("is_active"); + + b.Property("KindId") + .HasColumnType("integer") + .HasColumnName("kind_id"); + + b.Property("LeftOperandValue") + .HasColumnType("text") + .HasColumnName("left_operand_value"); + + b.Property("TechnicalKey") + .IsRequired() + .HasColumnType("text") + .HasColumnName("technical_key"); + + b.HasKey("Id") + .HasName("pk_policies"); + + b.HasIndex("AttributeKeyId") + .HasDatabaseName("ix_policies_attribute_key_id"); + + b.HasIndex("KindId") + .HasDatabaseName("ix_policies_kind_id"); + + b.ToTable("policies", "policy-hub"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyAssignedTypes", b => + { + b.Property("PolicyId") + .HasColumnType("uuid") + .HasColumnName("policy_id"); + + b.Property("PolicyTypeId") + .HasColumnType("integer") + .HasColumnName("policy_type_id"); + + b.HasKey("PolicyId", "PolicyTypeId") + .HasName("pk_policy_assigned_types"); + + b.HasIndex("PolicyTypeId") + .HasDatabaseName("ix_policy_assigned_types_policy_type_id"); + + b.ToTable("policy_assigned_types", "policy-hub"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyAssignedUseCases", b => + { + b.Property("PolicyId") + .HasColumnType("uuid") + .HasColumnName("policy_id"); + + b.Property("UseCaseId") + .HasColumnType("integer") + .HasColumnName("use_case_id"); + + b.HasKey("PolicyId", "UseCaseId") + .HasName("pk_policy_assigned_use_cases"); + + b.HasIndex("UseCaseId") + .HasDatabaseName("ix_policy_assigned_use_cases_use_case_id"); + + b.ToTable("policy_assigned_use_cases", "policy-hub"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyAttribute", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AttributeValue") + .IsRequired() + .HasColumnType("text") + .HasColumnName("attribute_value"); + + b.Property("IsActive") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("is_active"); + + b.Property("Key") + .HasColumnType("integer") + .HasColumnName("key"); + + b.Property("PolicyId") + .HasColumnType("uuid") + .HasColumnName("policy_id"); + + b.HasKey("Id") + .HasName("pk_policy_attributes"); + + b.HasIndex("Key") + .HasDatabaseName("ix_policy_attributes_key"); + + b.HasIndex("PolicyId") + .HasDatabaseName("ix_policy_attributes_policy_id"); + + b.ToTable("policy_attributes", "policy-hub"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyAttributeAssignedUseCases", b => + { + b.Property("AttributeId") + .HasColumnType("uuid") + .HasColumnName("attribute_id"); + + b.Property("UseCaseId") + .HasColumnType("integer") + .HasColumnName("use_case_id"); + + b.Property("IsActive") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("is_active"); + + b.HasKey("AttributeId", "UseCaseId") + .HasName("pk_policy_attribute_assigned_use_cases"); + + b.HasIndex("UseCaseId") + .HasDatabaseName("ix_policy_attribute_assigned_use_cases_use_case_id"); + + b.ToTable("policy_attribute_assigned_use_cases", "policy-hub"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyKind", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text") + .HasColumnName("label"); + + b.Property("TechnicalEnforced") + .HasColumnType("boolean") + .HasColumnName("technical_enforced"); + + b.HasKey("Id") + .HasName("pk_policy_kinds"); + + b.ToTable("policy_kinds", "policy-hub"); + + b.HasData( + new + { + Id = 1, + Label = "BusinessPartnerNumber", + TechnicalEnforced = true + }, + new + { + Id = 2, + Label = "Membership", + TechnicalEnforced = true + }, + new + { + Id = 3, + Label = "Framework", + TechnicalEnforced = true + }, + new + { + Id = 4, + Label = "Purpose", + TechnicalEnforced = false + }, + new + { + Id = 5, + Label = "Dismantler", + TechnicalEnforced = true + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyKindConfiguration", b => + { + b.Property("PolicyKindId") + .HasColumnType("integer") + .HasColumnName("policy_kind_id"); + + b.Property("RightOperandValue") + .IsRequired() + .HasColumnType("text") + .HasColumnName("right_operand_value"); + + b.HasKey("PolicyKindId") + .HasName("pk_policy_kind_configurations"); + + b.ToTable("policy_kind_configurations", "policy-hub"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyType", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("IsActive") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("is_active"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_policy_types"); + + b.ToTable("policy_types", "policy-hub"); + + b.HasData( + new + { + Id = 1, + IsActive = true, + Label = "Access" + }, + new + { + Id = 2, + IsActive = true, + Label = "Usage" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.UseCase", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("IsActive") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("is_active"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text") + .HasColumnName("label"); + + b.HasKey("Id") + .HasName("pk_use_cases"); + + b.ToTable("use_cases", "policy-hub"); + + b.HasData( + new + { + Id = 1, + IsActive = true, + Label = "Traceability" + }, + new + { + Id = 2, + IsActive = true, + Label = "Quality" + }, + new + { + Id = 3, + IsActive = true, + Label = "PCF" + }, + new + { + Id = 4, + IsActive = true, + Label = "Behavioraltwin" + }, + new + { + Id = 5, + IsActive = true, + Label = "Sustainability" + }); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.Policy", b => + { + b.HasOne("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.AttributeKey", "AttributeKey") + .WithMany("Policies") + .HasForeignKey("AttributeKeyId") + .HasConstraintName("fk_policies_attribute_keys_attribute_key_id"); + + b.HasOne("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyKind", "PolicyKind") + .WithMany("Policies") + .HasForeignKey("KindId") + .IsRequired() + .HasConstraintName("fk_policies_policy_kinds_kind_id"); + + b.Navigation("AttributeKey"); + + b.Navigation("PolicyKind"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyAssignedTypes", b => + { + b.HasOne("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.Policy", "Policy") + .WithMany() + .HasForeignKey("PolicyId") + .IsRequired() + .HasConstraintName("fk_policy_assigned_types_policies_policy_id"); + + b.HasOne("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyType", "PolicyType") + .WithMany() + .HasForeignKey("PolicyTypeId") + .IsRequired() + .HasConstraintName("fk_policy_assigned_types_policy_types_policy_type_id"); + + b.Navigation("Policy"); + + b.Navigation("PolicyType"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyAssignedUseCases", b => + { + b.HasOne("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.Policy", "Policy") + .WithMany() + .HasForeignKey("PolicyId") + .IsRequired() + .HasConstraintName("fk_policy_assigned_use_cases_policies_policy_id"); + + b.HasOne("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.UseCase", "UseCase") + .WithMany() + .HasForeignKey("UseCaseId") + .IsRequired() + .HasConstraintName("fk_policy_assigned_use_cases_use_cases_use_case_id"); + + b.Navigation("Policy"); + + b.Navigation("UseCase"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyAttribute", b => + { + b.HasOne("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.AttributeKey", "AttributeKey") + .WithMany("PolicyAttributes") + .HasForeignKey("Key") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_policy_attributes_attribute_keys_key"); + + b.HasOne("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.Policy", "Policy") + .WithMany("Attributes") + .HasForeignKey("PolicyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_policy_attributes_policies_policy_id"); + + b.Navigation("AttributeKey"); + + b.Navigation("Policy"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyAttributeAssignedUseCases", b => + { + b.HasOne("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyAttribute", "PolicyAttribute") + .WithMany("PolicyAttributeAssignedUseCases") + .HasForeignKey("AttributeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_policy_attribute_assigned_use_cases_policy_attributes_attri"); + + b.HasOne("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.UseCase", "UseCase") + .WithMany("PolicyAttributeAssignedUseCases") + .HasForeignKey("UseCaseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_policy_attribute_assigned_use_cases_use_cases_use_case_id"); + + b.Navigation("PolicyAttribute"); + + b.Navigation("UseCase"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyKindConfiguration", b => + { + b.HasOne("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyKind", "PolicyKind") + .WithOne("Configuration") + .HasForeignKey("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyKindConfiguration", "PolicyKindId") + .IsRequired() + .HasConstraintName("fk_policy_kind_configurations_policy_kinds_policy_kind_id"); + + b.Navigation("PolicyKind"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.AttributeKey", b => + { + b.Navigation("Policies"); + + b.Navigation("PolicyAttributes"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.Policy", b => + { + b.Navigation("Attributes"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyAttribute", b => + { + b.Navigation("PolicyAttributeAssignedUseCases"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyKind", b => + { + b.Navigation("Configuration"); + + b.Navigation("Policies"); + }); + + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.UseCase", b => + { + b.Navigation("PolicyAttributeAssignedUseCases"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/database/PolicyHub.Migrations/Migrations/20240430122950_1.0.0-rc.1.cs b/src/database/PolicyHub.Migrations/Migrations/20240430122950_1.0.0-rc.1.cs new file mode 100644 index 0000000..da65020 --- /dev/null +++ b/src/database/PolicyHub.Migrations/Migrations/20240430122950_1.0.0-rc.1.cs @@ -0,0 +1,180 @@ +/******************************************************************************** + * 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 + ********************************************************************************/ + +using Microsoft.EntityFrameworkCore.Migrations; +using System; + +#nullable disable + +namespace Org.Eclipse.TractusX.PolicyHub.Migrations.Migrations +{ + /// + public partial class _100rc1 : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "fk_policies_policy_kinds_policy_kind_id", + schema: "policy-hub", + table: "policies"); + + migrationBuilder.DropForeignKey( + name: "fk_policy_attributes_attribute_keys_attribute_key_id", + schema: "policy-hub", + table: "policy_attributes"); + + migrationBuilder.DropPrimaryKey( + name: "pk_policy_attributes", + schema: "policy-hub", + table: "policy_attributes"); + + migrationBuilder.AddColumn( + name: "id", + schema: "policy-hub", + table: "policy_attributes", + type: "uuid", + nullable: false, + defaultValueSql: "gen_random_uuid()"); + + migrationBuilder.AddPrimaryKey( + name: "pk_policy_attributes", + schema: "policy-hub", + table: "policy_attributes", + column: "id"); + + migrationBuilder.CreateTable( + name: "policy_attribute_assigned_use_cases", + schema: "policy-hub", + columns: table => new + { + attribute_id = table.Column(type: "uuid", nullable: false), + use_case_id = table.Column(type: "integer", nullable: false), + is_active = table.Column(type: "boolean", nullable: false, defaultValue: true) + }, + constraints: table => + { + table.PrimaryKey("pk_policy_attribute_assigned_use_cases", x => new { x.attribute_id, x.use_case_id }); + table.ForeignKey( + name: "fk_policy_attribute_assigned_use_cases_policy_attributes_attri", + column: x => x.attribute_id, + principalSchema: "policy-hub", + principalTable: "policy_attributes", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "fk_policy_attribute_assigned_use_cases_use_cases_use_case_id", + column: x => x.use_case_id, + principalSchema: "policy-hub", + principalTable: "use_cases", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "ix_policy_attributes_policy_id", + schema: "policy-hub", + table: "policy_attributes", + column: "policy_id"); + + migrationBuilder.CreateIndex( + name: "ix_policy_attribute_assigned_use_cases_use_case_id", + schema: "policy-hub", + table: "policy_attribute_assigned_use_cases", + column: "use_case_id"); + + migrationBuilder.AddForeignKey( + name: "fk_policies_policy_kinds_kind_id", + schema: "policy-hub", + table: "policies", + column: "kind_id", + principalSchema: "policy-hub", + principalTable: "policy_kinds", + principalColumn: "id"); + + migrationBuilder.AddForeignKey( + name: "fk_policy_attributes_attribute_keys_key", + schema: "policy-hub", + table: "policy_attributes", + column: "key", + principalSchema: "policy-hub", + principalTable: "attribute_keys", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "fk_policies_policy_kinds_kind_id", + schema: "policy-hub", + table: "policies"); + + migrationBuilder.DropForeignKey( + name: "fk_policy_attributes_attribute_keys_key", + schema: "policy-hub", + table: "policy_attributes"); + + migrationBuilder.DropTable( + name: "policy_attribute_assigned_use_cases", + schema: "policy-hub"); + + migrationBuilder.DropPrimaryKey( + name: "pk_policy_attributes", + schema: "policy-hub", + table: "policy_attributes"); + + migrationBuilder.DropIndex( + name: "ix_policy_attributes_policy_id", + schema: "policy-hub", + table: "policy_attributes"); + + migrationBuilder.DropColumn( + name: "id", + schema: "policy-hub", + table: "policy_attributes"); + + migrationBuilder.AddPrimaryKey( + name: "pk_policy_attributes", + schema: "policy-hub", + table: "policy_attributes", + columns: new[] { "policy_id", "key", "attribute_value" }); + + migrationBuilder.AddForeignKey( + name: "fk_policies_policy_kinds_policy_kind_id", + schema: "policy-hub", + table: "policies", + column: "kind_id", + principalSchema: "policy-hub", + principalTable: "policy_kinds", + principalColumn: "id"); + + migrationBuilder.AddForeignKey( + name: "fk_policy_attributes_attribute_keys_attribute_key_id", + schema: "policy-hub", + table: "policy_attributes", + column: "key", + principalSchema: "policy-hub", + principalTable: "attribute_keys", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/src/database/PolicyHub.Migrations/Migrations/PolicyHubContextModelSnapshot.cs b/src/database/PolicyHub.Migrations/Migrations/PolicyHubContextModelSnapshot.cs index ec552b8..a98c95b 100644 --- a/src/database/PolicyHub.Migrations/Migrations/PolicyHubContextModelSnapshot.cs +++ b/src/database/PolicyHub.Migrations/Migrations/PolicyHubContextModelSnapshot.cs @@ -34,7 +34,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder .HasDefaultSchema("policy-hub") .UseCollation("en_US.utf8") - .HasAnnotation("ProductVersion", "7.0.12") + .HasAnnotation("ProductVersion", "8.0.3") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); @@ -170,15 +170,13 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyAttribute", b => { - b.Property("PolicyId") + b.Property("Id") + .ValueGeneratedOnAdd() .HasColumnType("uuid") - .HasColumnName("policy_id"); - - b.Property("Key") - .HasColumnType("integer") - .HasColumnName("key"); + .HasColumnName("id"); b.Property("AttributeValue") + .IsRequired() .HasColumnType("text") .HasColumnName("attribute_value"); @@ -188,15 +186,51 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasDefaultValue(true) .HasColumnName("is_active"); - b.HasKey("PolicyId", "Key", "AttributeValue") + b.Property("Key") + .HasColumnType("integer") + .HasColumnName("key"); + + b.Property("PolicyId") + .HasColumnType("uuid") + .HasColumnName("policy_id"); + + b.HasKey("Id") .HasName("pk_policy_attributes"); b.HasIndex("Key") .HasDatabaseName("ix_policy_attributes_key"); + b.HasIndex("PolicyId") + .HasDatabaseName("ix_policy_attributes_policy_id"); + b.ToTable("policy_attributes", "policy-hub"); }); + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyAttributeAssignedUseCases", b => + { + b.Property("AttributeId") + .HasColumnType("uuid") + .HasColumnName("attribute_id"); + + b.Property("UseCaseId") + .HasColumnType("integer") + .HasColumnName("use_case_id"); + + b.Property("IsActive") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("is_active"); + + b.HasKey("AttributeId", "UseCaseId") + .HasName("pk_policy_attribute_assigned_use_cases"); + + b.HasIndex("UseCaseId") + .HasDatabaseName("ix_policy_attribute_assigned_use_cases_use_case_id"); + + b.ToTable("policy_attribute_assigned_use_cases", "policy-hub"); + }); + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyKind", b => { b.Property("Id") @@ -370,7 +404,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .WithMany("Policies") .HasForeignKey("KindId") .IsRequired() - .HasConstraintName("fk_policies_policy_kinds_policy_kind_id"); + .HasConstraintName("fk_policies_policy_kinds_kind_id"); b.Navigation("AttributeKey"); @@ -422,7 +456,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasForeignKey("Key") .OnDelete(DeleteBehavior.Cascade) .IsRequired() - .HasConstraintName("fk_policy_attributes_attribute_keys_attribute_key_id"); + .HasConstraintName("fk_policy_attributes_attribute_keys_key"); b.HasOne("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.Policy", "Policy") .WithMany("Attributes") @@ -436,6 +470,27 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Policy"); }); + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyAttributeAssignedUseCases", b => + { + b.HasOne("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyAttribute", "PolicyAttribute") + .WithMany("PolicyAttributeAssignedUseCases") + .HasForeignKey("AttributeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_policy_attribute_assigned_use_cases_policy_attributes_attri"); + + b.HasOne("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.UseCase", "UseCase") + .WithMany("PolicyAttributeAssignedUseCases") + .HasForeignKey("UseCaseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_policy_attribute_assigned_use_cases_use_cases_use_case_id"); + + b.Navigation("PolicyAttribute"); + + b.Navigation("UseCase"); + }); + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyKindConfiguration", b => { b.HasOne("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyKind", "PolicyKind") @@ -459,12 +514,22 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Attributes"); }); + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyAttribute", b => + { + b.Navigation("PolicyAttributeAssignedUseCases"); + }); + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.PolicyKind", b => { b.Navigation("Configuration"); b.Navigation("Policies"); }); + + modelBuilder.Entity("Org.Eclipse.TractusX.PolicyHub.Entities.Entities.UseCase", b => + { + b.Navigation("PolicyAttributeAssignedUseCases"); + }); #pragma warning restore 612, 618 } } diff --git a/src/database/PolicyHub.Migrations/PolicyHub.Migrations.csproj b/src/database/PolicyHub.Migrations/PolicyHub.Migrations.csproj index c12b89a..91e8046 100644 --- a/src/database/PolicyHub.Migrations/PolicyHub.Migrations.csproj +++ b/src/database/PolicyHub.Migrations/PolicyHub.Migrations.csproj @@ -21,7 +21,7 @@ Org.Eclipse.TractusX.PolicyHub.Migrations Org.Eclipse.TractusX.PolicyHub.Migrations - net7.0 + net8.0 enable enable Linux @@ -33,21 +33,21 @@ true - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - + + + + + + + + + + + diff --git a/src/database/PolicyHub.Migrations/Seeder/BatchDeleteSeeder.cs b/src/database/PolicyHub.Migrations/Seeder/BatchDeleteSeeder.cs new file mode 100644 index 0000000..acc9ff2 --- /dev/null +++ b/src/database/PolicyHub.Migrations/Seeder/BatchDeleteSeeder.cs @@ -0,0 +1,97 @@ +/******************************************************************************** + * 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 + ********************************************************************************/ + +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Org.Eclipse.TractusX.PolicyHub.Entities; +using Org.Eclipse.TractusX.PolicyHub.Entities.Entities; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Seeding; + +namespace Org.Eclipse.TractusX.PolicyHub.Migrations.Seeder; + +/// +/// Seeder to seed the all configured entities +/// +public class BatchDeleteSeeder : ICustomSeeder +{ + private readonly PolicyHubContext _context; + private readonly ILogger _logger; + private readonly SeederSettings _settings; + + /// + /// Constructor + /// + /// The database context + /// The logger + /// The options + public BatchDeleteSeeder(PolicyHubContext context, ILogger logger, IOptions options) + { + _context = context; + _logger = logger; + _settings = options.Value; + } + + /// + public int Order => 3; + + /// + public async Task ExecuteAsync(CancellationToken cancellationToken) + { + if (!_settings.DataPaths.Any()) + { + _logger.LogInformation("There a no data paths configured, therefore the {SeederName} will be skipped", nameof(BatchInsertSeeder)); + return; + } + + await SeedTable("policies", x => x.Id, cancellationToken).ConfigureAwait(false); + await SeedTable("policy_attributes", x => x.Id, cancellationToken).ConfigureAwait(false); + await SeedTable("policy_kind_configurations", x => x.PolicyKindId, cancellationToken).ConfigureAwait(false); + await SeedTable("policy_assigned_types", x => new { x.PolicyId, x.PolicyTypeId }, cancellationToken).ConfigureAwait(false); + await SeedTable("policy_assigned_use_cases", x => new { x.PolicyId, x.UseCaseId }, cancellationToken).ConfigureAwait(false); + await SeedTable("policy_attribute_assigned_use_cases", x => new { x.AttributeId, x.UseCaseId }, cancellationToken).ConfigureAwait(false); + + await _context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); + } + + private async Task SeedTable(string fileName, Func keySelector, CancellationToken cancellationToken) where T : class + { + _logger.LogDebug("Start seeding {Filename}", fileName); + var additionalEnvironments = _settings.TestDataEnvironments ?? Enumerable.Empty(); + var data = await SeederHelper.GetSeedData(_logger, fileName, _settings.DataPaths, cancellationToken, additionalEnvironments.ToArray()).ConfigureAwait(false); + _logger.LogDebug("Found {ElementCount} data", data.Count); + var isActiveEntity = typeof(T).IsAssignableTo(typeof(IActiveEntity)); + + // Identify entities in the database that are not present in the JSON data + var existingEntities = await _context.Set().ToListAsync(cancellationToken).ConfigureAwait(false); + var entitiesToRemove = existingEntities.Where(dbEntity => data.All(jsonEntity => !keySelector(dbEntity).Equals(keySelector(jsonEntity)))).ToList(); + if (isActiveEntity) + { + foreach (var entity in entitiesToRemove) + { + _context.Set().Attach(entity); + (entity as IActiveEntity)!.IsActive = false; + } + } + else + { + _context.Set().RemoveRange(entitiesToRemove); + } + } +} diff --git a/src/database/PolicyHub.Migrations/Seeder/BatchInsertSeeder.cs b/src/database/PolicyHub.Migrations/Seeder/BatchInsertSeeder.cs index cfed58d..a8b714d 100644 --- a/src/database/PolicyHub.Migrations/Seeder/BatchInsertSeeder.cs +++ b/src/database/PolicyHub.Migrations/Seeder/BatchInsertSeeder.cs @@ -60,10 +60,11 @@ public async Task ExecuteAsync(CancellationToken cancellationToken) } await SeedTable("policies", x => x.Id, cancellationToken).ConfigureAwait(false); - await SeedTable("policy_attributes", x => new { x.PolicyId, x.Key, x.AttributeValue }, cancellationToken).ConfigureAwait(false); + await SeedTable("policy_attributes", x => x.Id, cancellationToken).ConfigureAwait(false); await SeedTable("policy_kind_configurations", x => x.PolicyKindId, cancellationToken).ConfigureAwait(false); await SeedTable("policy_assigned_types", x => new { x.PolicyId, x.PolicyTypeId }, cancellationToken).ConfigureAwait(false); await SeedTable("policy_assigned_use_cases", x => new { x.PolicyId, x.UseCaseId }, cancellationToken).ConfigureAwait(false); + await SeedTable("policy_attribute_assigned_use_cases", x => new { x.AttributeId, x.UseCaseId }, cancellationToken).ConfigureAwait(false); await _context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); } diff --git a/src/database/PolicyHub.Migrations/Seeder/BatchUpdateSeeder.cs b/src/database/PolicyHub.Migrations/Seeder/BatchUpdateSeeder.cs index ff172d4..c8a74b6 100644 --- a/src/database/PolicyHub.Migrations/Seeder/BatchUpdateSeeder.cs +++ b/src/database/PolicyHub.Migrations/Seeder/BatchUpdateSeeder.cs @@ -44,19 +44,24 @@ public async Task ExecuteAsync(CancellationToken cancellationToken) await SeedTable( "policies", x => new { x.Id }, - x => x.dbEntity.IsActive != x.dataEntity.IsActive, + x => x.dbEntity.IsActive != x.dataEntity.IsActive || x.dbEntity.TechnicalKey != x.dataEntity.TechnicalKey || x.dbEntity.LeftOperandValue != x.dataEntity.LeftOperandValue, (dbEntity, entity) => { dbEntity.IsActive = entity.IsActive; + dbEntity.TechnicalKey = entity.TechnicalKey; + dbEntity.LeftOperandValue = entity.LeftOperandValue; }, cancellationToken).ConfigureAwait(false); await SeedTable( "policy_attributes", - x => new { x.PolicyId, x.Key, x.AttributeValue }, - x => x.dbEntity.IsActive != x.dataEntity.IsActive, + x => new { x.Id }, + x => x.dbEntity.IsActive != x.dataEntity.IsActive || x.dbEntity.AttributeValue != x.dataEntity.AttributeValue || x.dbEntity.Key != x.dataEntity.Key || x.dbEntity.PolicyId != x.dataEntity.PolicyId, (dbEntry, entry) => { dbEntry.IsActive = entry.IsActive; + dbEntry.AttributeValue = entry.AttributeValue; + dbEntry.Key = entry.Key; + dbEntry.PolicyId = entry.PolicyId; }, cancellationToken).ConfigureAwait(false); await _context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); diff --git a/src/database/PolicyHub.Migrations/Seeder/Data/policies.json b/src/database/PolicyHub.Migrations/Seeder/Data/policies.json index cdfdb02..872809b 100644 --- a/src/database/PolicyHub.Migrations/Seeder/Data/policies.json +++ b/src/database/PolicyHub.Migrations/Seeder/Data/policies.json @@ -12,80 +12,40 @@ "kind_id": 2, "technical_key": "Membership", "description": "The membership credential can get used to ensure that only CX members are allowed to view or negotiate the respective data offer.", + "left_operand_value": null, "is_active": true, "attribute_key_id": 2 }, { - "id": "01a0fba3-9b6e-435a-b045-e0e890c300b3", - "kind_id": 3, - "technical_key": "FrameworkAgreement.traceability", - "description": "With the Framework Credential, only those participants which have signed the respective framework agreement (general or via a specific version) are allowed to view or negotiate the respective data offer. Generic: \"rightOperand\": \"active\"; specific \"rightOperand\": \"active:{version}\"", - "is_active": true, - "attribute_key_id": 5 - }, - { - "id": "01a0fba3-9b6e-435a-b045-e0e890c300b4", - "kind_id": 3, - "technical_key": "FrameworkAgreement.quality", - "description": "With the Framework Credential, only those participants which have signed the respective framework agreement (general or via a specific version) are allowed to view or negotiate the respective data offer. Generic: \"rightOperand\": \"active\"; specific \"rightOperand\": \"active:{version}\"", + "id": "01a0fba3-9b6e-435a-b045-e0e890c300c1", + "kind_id": 5, + "technical_key": "Dismantler.allowedBrands", + "description": "Company role defining a dismantler. Companies holding the credential are dismantler certified companies.", "is_active": true, - "attribute_key_id": 5 + "attribute_key_id": 4 }, { - "id": "01a0fba3-9b6e-435a-b045-e0e890c300b5", - "kind_id": 3, - "technical_key": "FrameworkAgreement.pcf", - "description": "With the Framework Credential, only those participants which have signed the respective framework agreement (general or via a specific version) are allowed to view or negotiate the respective data offer. Generic: \"rightOperand\": \"active\"; specific \"rightOperand\": \"active:{version}\"", + "id": "01a0fba3-9b6e-435a-b045-e0e890c300c2", + "kind_id": 4, + "technical_key": "UsagePurpose", + "description": "", "is_active": true, - "attribute_key_id": 5 + "attribute_key_id": 3 }, { - "id": "01a0fba3-9b6e-435a-b045-e0e890c300b6", + "id": "01a0fba3-9b6e-435a-b045-e0e890c300c9", "kind_id": 3, - "technical_key": "FrameworkAgreement.behavioraltwin", + "technical_key": "FrameworkAgreement", "description": "With the Framework Credential, only those participants which have signed the respective framework agreement (general or via a specific version) are allowed to view or negotiate the respective data offer. Generic: \"rightOperand\": \"active\"; specific \"rightOperand\": \"active:{version}\"", "is_active": true, "attribute_key_id": 5 }, { - "id": "01a0fba3-9b6e-435a-b045-e0e890c300b7", - "kind_id": 4, - "technical_key": "purpose.trace.v1.TraceBattery", - "description": "Facilitating compliance with mandatory regulatory requirements for tracking and reporting battery cells, modules & high-voltage batteries.", - "is_active": true, - "attribute_key_id": 2 - }, - { - "id": "01a0fba3-9b6e-435a-b045-e0e890c300b8", - "kind_id": 4, - "technical_key": "purpose.trace.v1.aspects", - "description": "Establishing a digital representation of the automotive supply chain to enable a component specific data exchange.", - "is_active": true, - "attribute_key_id": 2 - }, - { - "id": "01a0fba3-9b6e-435a-b045-e0e890c300b9", - "kind_id": 4, - "technical_key": "purpose.trace.v1.qualityanalysis", - "description": " The data can be used for quality analysis to identify and select affected components and to send quality notifications to affected customers or suppliers.", - "is_active": true, - "attribute_key_id": 2 - }, - { - "id": "01a0fba3-9b6e-435a-b045-e0e890c300c1", + "id": "01a0fba3-9b6e-435a-b045-e0e890c300d1", "kind_id": 5, - "technical_key": "companyRole.dismantler", - "left_operand_value": "Dismantler.activityType", - "description": "Company role defining a dismantler. Companies holding the credential are dismantler certified companies.", + "technical_key": "Dismantler", + "description": "Companies holding the credential are dismantler certified companies.", "is_active": true, "attribute_key_id": 4 - }, - { - "id": "01a0fba3-9b6e-435a-b045-e0e890c300c2", - "kind_id": 4, - "technical_key": "purpose", - "description": "", - "is_active": true, - "attribute_key_id": 3 } ] diff --git a/src/database/PolicyHub.Migrations/Seeder/Data/policy_assigned_types.json b/src/database/PolicyHub.Migrations/Seeder/Data/policy_assigned_types.json index acd5385..05b6fbc 100644 --- a/src/database/PolicyHub.Migrations/Seeder/Data/policy_assigned_types.json +++ b/src/database/PolicyHub.Migrations/Seeder/Data/policy_assigned_types.json @@ -2,15 +2,11 @@ { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b1", "policy_type_id": 1, "is_active": true }, { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b1", "policy_type_id": 2, "is_active": true }, { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b2", "policy_type_id": 1, "is_active": true }, - { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b2", "policy_type_id": 2, "is_active": true }, - { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b3", "policy_type_id": 2, "is_active": true }, - { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b4", "policy_type_id": 2, "is_active": true }, - { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b5", "policy_type_id": 2, "is_active": true }, - { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b6", "policy_type_id": 2, "is_active": true }, - { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b7", "policy_type_id": 2, "is_active": true }, - { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b8", "policy_type_id": 2, "is_active": true }, - { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b9", "policy_type_id": 2, "is_active": true }, + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b2", "policy_type_id": 2, "is_active": true }, { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c1", "policy_type_id": 1, "is_active": true }, { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c1", "policy_type_id": 2, "is_active": true }, - { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c2", "policy_type_id": 2, "is_active": true } + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c2", "policy_type_id": 2, "is_active": true }, + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c9", "policy_type_id": 2, "is_active": true }, + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300d1", "policy_type_id": 1, "is_active": true }, + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300d1", "policy_type_id": 2, "is_active": true } ] diff --git a/src/database/PolicyHub.Migrations/Seeder/Data/policy_assigned_use_cases.json b/src/database/PolicyHub.Migrations/Seeder/Data/policy_assigned_use_cases.json index dd48519..ccfb878 100644 --- a/src/database/PolicyHub.Migrations/Seeder/Data/policy_assigned_use_cases.json +++ b/src/database/PolicyHub.Migrations/Seeder/Data/policy_assigned_use_cases.json @@ -8,18 +8,21 @@ { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b2", "use_case_id": 2, "is_active": true }, { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b2", "use_case_id": 3, "is_active": true }, { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b2", "use_case_id": 4, "is_active": true }, - { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b2", "use_case_id": 5, "is_active": true }, - { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b3", "use_case_id": 1, "is_active": true }, - { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b4", "use_case_id": 2, "is_active": true }, - { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b5", "use_case_id": 3, "is_active": true }, - { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b6", "use_case_id": 4, "is_active": true }, - { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b7", "use_case_id": 1, "is_active": true }, - { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b8", "use_case_id": 1, "is_active": true }, - { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b9", "use_case_id": 1, "is_active": true }, + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b2", "use_case_id": 5, "is_active": true }, { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c1", "use_case_id": 1, "is_active": true }, { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c1", "use_case_id": 2, "is_active": true }, { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c1", "use_case_id": 3, "is_active": true }, { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c1", "use_case_id": 4, "is_active": true }, { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c1", "use_case_id": 5, "is_active": true }, - { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c2", "use_case_id": 1, "is_active": true } + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c2", "use_case_id": 1, "is_active": true }, + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c9", "use_case_id": 1, "is_active": true }, + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c9", "use_case_id": 2, "is_active": true }, + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c9", "use_case_id": 3, "is_active": true }, + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c9", "use_case_id": 4, "is_active": true }, + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c9", "use_case_id": 5, "is_active": true }, + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300d1", "use_case_id": 1, "is_active": true }, + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300d1", "use_case_id": 2, "is_active": true }, + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300d1", "use_case_id": 3, "is_active": true }, + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300d1", "use_case_id": 4, "is_active": true }, + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300d1", "use_case_id": 5, "is_active": true } ] diff --git a/src/database/PolicyHub.Migrations/Seeder/Data/policy_attribute_assigned_use_cases.json b/src/database/PolicyHub.Migrations/Seeder/Data/policy_attribute_assigned_use_cases.json new file mode 100644 index 0000000..b969a73 --- /dev/null +++ b/src/database/PolicyHub.Migrations/Seeder/Data/policy_attribute_assigned_use_cases.json @@ -0,0 +1,62 @@ +[ + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d1", "use_case_id": 1, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d1", "use_case_id": 2, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d1", "use_case_id": 3, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d1", "use_case_id": 4, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d1", "use_case_id": 5, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d2", "use_case_id": 1, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d2", "use_case_id": 2, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d2", "use_case_id": 3, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d2", "use_case_id": 4, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d2", "use_case_id": 5, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d6", "use_case_id": 1, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d6", "use_case_id": 2, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d6", "use_case_id": 3, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d6", "use_case_id": 4, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d6", "use_case_id": 5, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d7", "use_case_id": 1, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d7", "use_case_id": 2, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d7", "use_case_id": 3, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d7", "use_case_id": 4, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d7", "use_case_id": 5, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d8", "use_case_id": 1, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d8", "use_case_id": 2, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d8", "use_case_id": 3, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d8", "use_case_id": 4, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d8", "use_case_id": 5, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300d9", "use_case_id": 1, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e1", "use_case_id": 1, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e2", "use_case_id": 1, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e3", "use_case_id": 2, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e3", "use_case_id": 3, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e3", "use_case_id": 4, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e3", "use_case_id": 5, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e4", "use_case_id": 2, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e4", "use_case_id": 3, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e4", "use_case_id": 4, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e4", "use_case_id": 5, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e6", "use_case_id": 2, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e6", "use_case_id": 3, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e6", "use_case_id": 4, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e6", "use_case_id": 5, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e7", "use_case_id": 2, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e7", "use_case_id": 3, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e7", "use_case_id": 4, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e7", "use_case_id": 5, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e8", "use_case_id": 2, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e8", "use_case_id": 3, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e8", "use_case_id": 4, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e8", "use_case_id": 5, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e9", "use_case_id": 2, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e9", "use_case_id": 3, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e9", "use_case_id": 4, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300e9", "use_case_id": 5, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300f1", "use_case_id": 2, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300f1", "use_case_id": 3, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300f1", "use_case_id": 4, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300f2", "use_case_id": 1, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300f2", "use_case_id": 2, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300f2", "use_case_id": 3, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300f2", "use_case_id": 4, "is_active": true }, + { "attribute_id": "01a0fba3-9b6e-435a-b045-e0e890c300f2", "use_case_id": 5, "is_active": true } +] \ No newline at end of file diff --git a/src/database/PolicyHub.Migrations/Seeder/Data/policy_attributes.json b/src/database/PolicyHub.Migrations/Seeder/Data/policy_attributes.json index 8afec65..e0d787c 100644 --- a/src/database/PolicyHub.Migrations/Seeder/Data/policy_attributes.json +++ b/src/database/PolicyHub.Migrations/Seeder/Data/policy_attributes.json @@ -1,92 +1,135 @@ [ { + "id": "01a0fba3-9b6e-435a-b045-e0e890c300d1", "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b1", "key": 1, "attribute_value": "^BPNL[\\w|\\d]{12}$", "is_active": true }, { + "id": "01a0fba3-9b6e-435a-b045-e0e890c300d2", "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b2", "key": 2, "attribute_value": "active", "is_active": true }, { - "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b3", - "key": 5, - "attribute_value": "1.0", + "id": "01a0fba3-9b6e-435a-b045-e0e890c300d3", + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c2", + "key": 2, + "attribute_value": "purpose.trace.v1.TraceBattery", "is_active": true }, { - "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b3", - "key": 5, - "attribute_value": "1.1", + "id": "01a0fba3-9b6e-435a-b045-e0e890c300d4", + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c2", + "key": 2, + "attribute_value": "purpose.trace.v1.aspects", "is_active": true }, { - "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b3", + "id": "01a0fba3-9b6e-435a-b045-e0e890c300d5", + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c2", + "key": 2, + "attribute_value": "purpose.trace.v1.qualityanalysis", + "is_active": true + }, + { + "id": "01a0fba3-9b6e-435a-b045-e0e890c300d6", + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c1", + "key": 4, + "attribute_value": "BMW", + "is_active": true + }, + { + "id": "01a0fba3-9b6e-435a-b045-e0e890c300d7", + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c1", + "key": 4, + "attribute_value": "Audi", + "is_active": true + }, + { + "id": "01a0fba3-9b6e-435a-b045-e0e890c300d8", + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c1", + "key": 4, + "attribute_value": "VW", + "is_active": true + }, + { + "id": "01a0fba3-9b6e-435a-b045-e0e890c300d9", + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c9", "key": 5, - "attribute_value": "1.2", + "attribute_value": "Traceability:1.0", "is_active": true }, { - "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b4", + "id": "01a0fba3-9b6e-435a-b045-e0e890c300e1", + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c9", "key": 5, - "attribute_value": "1.0", + "attribute_value": "Traceability:1.1", "is_active": true }, { - "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b5", + "id": "01a0fba3-9b6e-435a-b045-e0e890c300e2", + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c9", "key": 5, - "attribute_value": "1.0", + "attribute_value": "Traceability:1.2", "is_active": true }, { - "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b6", + "id": "01a0fba3-9b6e-435a-b045-e0e890c300e3", + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c9", "key": 5, - "attribute_value": "1.0", + "attribute_value": "Quality:1.0", "is_active": true }, { - "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b7", - "key": 2, - "attribute_value": "purpose.trace.v1.TraceBattery", + "id": "01a0fba3-9b6e-435a-b045-e0e890c300e4", + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c9", + "key": 5, + "attribute_value": "PCF:1.0", "is_active": true }, { - "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b8", - "key": 2, - "attribute_value": "purpose.trace.v1.aspects", + "id": "01a0fba3-9b6e-435a-b045-e0e890c300e6", + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c9", + "key": 5, + "attribute_value": "Behavioraltwin:1.0", "is_active": true }, { - "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b9", - "key": 2, - "attribute_value": "purpose.trace.v1.qualityanalysis", + "id": "01a0fba3-9b6e-435a-b045-e0e890c300e7", + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c9", + "key": 5, + "attribute_value": "Circulareconomy:1.0", "is_active": true }, { - "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c1", - "key": 4, - "attribute_value": "BMW", + "id": "01a0fba3-9b6e-435a-b045-e0e890c300e8", + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c9", + "key": 5, + "attribute_value": "Demandcapacity:1.0", "is_active": true }, { - "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c1", - "key": 4, - "attribute_value": "Audi", + "id": "01a0fba3-9b6e-435a-b045-e0e890c300e9", + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c9", + "key": 5, + "attribute_value": "Puris:1.0", "is_active": true }, { - "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c1", - "key": 4, - "attribute_value": "VW", + "id": "01a0fba3-9b6e-435a-b045-e0e890c300f1", + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c9", + "key": 5, + "attribute_value": "Businesspartner:1.0", "is_active": true }, { - "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c2", - "key": 2, - "attribute_value": "ID Trace 3.1", + "id": "01a0fba3-9b6e-435a-b045-e0e890c300f2", + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300d1", + "key": 4, + "attribute_value": "active", "is_active": true } -] +] \ No newline at end of file diff --git a/src/database/PolicyHub.Migrations/Seeder/Data/policy_kind_configurations.json b/src/database/PolicyHub.Migrations/Seeder/Data/policy_kind_configurations.json index f47fb46..0d4f101 100644 --- a/src/database/PolicyHub.Migrations/Seeder/Data/policy_kind_configurations.json +++ b/src/database/PolicyHub.Migrations/Seeder/Data/policy_kind_configurations.json @@ -1,3 +1,2 @@ [ - { "policy_kind_id": 3, "right_operand_value": "active:{0}" } ] diff --git a/src/hub/PolicyHub.Service/BusinessLogic/PolicyHubBusinessLogic.cs b/src/hub/PolicyHub.Service/BusinessLogic/PolicyHubBusinessLogic.cs index 3b0ef5c..9c4093c 100644 --- a/src/hub/PolicyHub.Service/BusinessLogic/PolicyHubBusinessLogic.cs +++ b/src/hub/PolicyHub.Service/BusinessLogic/PolicyHubBusinessLogic.cs @@ -20,32 +20,28 @@ using Org.Eclipse.TractusX.PolicyHub.DbAccess; using Org.Eclipse.TractusX.PolicyHub.DbAccess.Models; using Org.Eclipse.TractusX.PolicyHub.DbAccess.Repositories; +using Org.Eclipse.TractusX.PolicyHub.Entities.Entities; using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; using Org.Eclipse.TractusX.PolicyHub.Service.Extensions; using Org.Eclipse.TractusX.PolicyHub.Service.Models; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Linq; using System.Text.RegularExpressions; namespace Org.Eclipse.TractusX.PolicyHub.Service.BusinessLogic; -public class PolicyHubBusinessLogic : IPolicyHubBusinessLogic +public class PolicyHubBusinessLogic(IHubRepositories hubRepositories) + : IPolicyHubBusinessLogic { - private readonly IHubRepositories _hubRepositories; - - public PolicyHubBusinessLogic(IHubRepositories hubRepositories) - { - _hubRepositories = hubRepositories; - } - public IAsyncEnumerable GetAttributeKeys() => - _hubRepositories.GetInstance().GetAttributeKeys(); + hubRepositories.GetInstance().GetAttributeKeys(); public IAsyncEnumerable GetPolicyTypes(PolicyTypeId? type, UseCaseId? useCase) => - _hubRepositories.GetInstance().GetPolicyTypes(type, useCase); + hubRepositories.GetInstance().GetPolicyTypes(type, useCase); public async Task GetPolicyContentWithFiltersAsync(UseCaseId? useCase, PolicyTypeId type, string credential, OperatorId operatorId, string? value) { - var (exists, leftOperand, attributes, rightOperandValue) = await _hubRepositories.GetInstance().GetPolicyContentAsync(useCase, type, credential).ConfigureAwait(false); + var (exists, leftOperand, attributes, rightOperandValue) = await hubRepositories.GetInstance().GetPolicyContentAsync(useCase, type, credential).ConfigureAwait(false); if (!exists) { throw new NotFoundException($"Policy for type {type} and technicalKey {credential} does not exists"); @@ -58,19 +54,26 @@ public async Task GetPolicyContentWithFiltersAsync(UseCaseId? us } var (rightOperand, additionalAttribute) = attributes.Key != null ? - GetRightOperand(operatorId, attributes, rightOperands, value, leftOperand) : + GetRightOperand(operatorId, attributes, rightOperands, value, leftOperand, useCase) : (rightOperandValue!, null); - return new PolicyResponse(CreateFileContent(type, operatorId, leftOperand, rightOperand), additionalAttribute == null ? null : Enumerable.Repeat(additionalAttribute, 1)); + return new PolicyResponse(CreateFileContent(type, operatorId, "cx-policy:" + leftOperand, rightOperand), additionalAttribute == null ? null : Enumerable.Repeat(additionalAttribute, 1)); } - private static (object rightOperand, AdditionalAttributes? additionalAttribute) GetRightOperand(OperatorId operatorId, (AttributeKeyId? Key, IEnumerable Values) attributes, IEnumerable rightOperands, string? value, string leftOperand) => + private static (object rightOperand, AdditionalAttributes? additionalAttribute) GetRightOperand(OperatorId operatorId, (AttributeKeyId? Key, IEnumerable Values) attributes, IEnumerable rightOperands, string? value, string leftOperand, UseCaseId? useCase) => attributes.Key switch { AttributeKeyId.DynamicValue => (value ?? "{dynamicValue}", null), AttributeKeyId.Regex => (GetRegexValue(attributes, value), null), _ => operatorId == OperatorId.Equals - ? rightOperands.Count() > 1 ? ($"@{leftOperand}-{attributes.Key}", new AdditionalAttributes($"@{leftOperand}-{attributes.Key}", rightOperands)) : (rightOperands.Single(), null) + ? rightOperands.Count() > 1 ? + ($"@{leftOperand}{(useCase != null ? + useCase.ToString().Insert(0, ".") : + string.Empty)}-{attributes.Key}", + new AdditionalAttributes($"@{leftOperand}{(useCase != null ? + useCase.ToString().Insert(0, ".") : + string.Empty)}-{attributes.Key}", rightOperands)) : + (rightOperands.Single(), null) : (rightOperands, null) }; @@ -112,6 +115,26 @@ private static PolicyFileContent CreateFileContent(PolicyTypeId type, OperatorId public async Task GetPolicyContentAsync(PolicyContentRequest requestData) { + if (requestData.PolicyType == PolicyTypeId.Usage && requestData.ConstraintOperand == ConstraintOperandId.Or) + { + throw new ControllerArgumentException($"The support of OR constraintOperand for Usage constraints are not supported for now"); + } + + if (requestData.PolicyType == PolicyTypeId.Access && requestData.ConstraintOperand == ConstraintOperandId.And && requestData.Constraints.Any(x => x.Key == "BusinessPartnerNumber" && (x.Value!.Split(",").Count() > 1))) + { + throw new ControllerArgumentException($"Only a single value BPNL is allowed with an AND constraint"); + } + + if (requestData.Constraints.Any(x => x.Key == "BusinessPartnerNumber") && !requestData.Constraints.Any(x => x.Operator == OperatorId.Equals)) + { + throw new ControllerArgumentException($"The operator for BPNLs should always be Equals"); + } + + if (requestData.PolicyType == PolicyTypeId.Usage && requestData.Constraints.Any(x => x.Key == "BusinessPartnerNumber" && (x.Value!.Split(",").Count() > 1))) + { + throw new ControllerArgumentException($"For usage policies only a single BPNL is allowed"); + } + var keyCounts = requestData.Constraints .GroupBy(pair => pair.Key) .ToDictionary(group => group.Key, group => group.Count()); @@ -121,10 +144,35 @@ public async Task GetPolicyContentAsync(PolicyContentRequest req throw new ControllerArgumentException($"Keys {string.Join(",", multipleDefinedKey.Select(x => x.Key).Distinct())} have been defined multiple times"); } - var policies = await _hubRepositories.GetInstance().GetPolicyForOperandContent(requestData.PolicyType, requestData.Constraints.Select(x => x.Key)).ToListAsync().ConfigureAwait(false); + var technicalKeys = requestData.Constraints.Select(x => x.Key); + var attributeValuesForTechnicalKeys = await hubRepositories.GetInstance().GetAttributeValuesForTechnicalKeys(requestData.PolicyType, technicalKeys).ConfigureAwait(false); + if (technicalKeys.Except(attributeValuesForTechnicalKeys.Select(a => a.TechnicalKey)).Any()) + { + throw new ControllerArgumentException($"Policy for type {requestData.PolicyType} and requested technicalKeys does not exists. TechnicalKeys {string.Join(",", attributeValuesForTechnicalKeys.Select(x => x.TechnicalKey))} are allowed"); + } + + IEnumerable<(string TechnicalKey, IEnumerable Values)> keyValues = requestData.Constraints.GroupBy(x => x.Key).Select(x => new ValueTuple>(x.Key, x.Where(y => y.Value != null).SelectMany(y => y.Value!.Split(",")))); + IEnumerable<(string TechnicalKey, IEnumerable Values)> missingValues = keyValues + .Join(attributeValuesForTechnicalKeys, secondItem => secondItem.TechnicalKey, firstItem => firstItem.TechnicalKey, + (secondItem, firstItem) => new { secondItem, firstItem }) + .Select(t => new { t, missing = t.secondItem.Values.Except(t.firstItem.Values) }) + .Where(t => t.missing.Any()) + .Select(t => (Key: t.t.secondItem.TechnicalKey, MissingValues: t.missing)); + + var attributesToIgnore = new[] { AttributeKeyId.Regex, AttributeKeyId.DynamicValue }; + var technicalKeysToIgnore = attributeValuesForTechnicalKeys.Where(x => x.AttributeKey != null && attributesToIgnore.Any(y => y == x.AttributeKey)).Select(x => x.TechnicalKey); + var invalidValues = missingValues.Select(x => x.TechnicalKey).Except(technicalKeysToIgnore); + if (invalidValues.Any()) + { + var x = missingValues.Where(x => invalidValues.Contains(x.TechnicalKey)).Select(x => + $"Key: {x.TechnicalKey}, invalid values: {string.Join(',', x.Values)}"); + throw new ControllerArgumentException($"Invalid values set for {string.Join(',', x)}"); + } + + var policies = await hubRepositories.GetInstance().GetPolicyForOperandContent(requestData.PolicyType, technicalKeys).ToListAsync().ConfigureAwait(false); if (policies.Count != requestData.Constraints.Count()) { - throw new NotFoundException($"Policy for type {requestData.PolicyType} and technicalKeys {string.Join(",", requestData.Constraints.Select(x => x.Key).Except(policies.Select(x => x.TechnicalKey)))} does not exists"); + throw new NotFoundException($"Policy for type {requestData.PolicyType} and technicalKeys {string.Join(",", technicalKeys.Except(policies.Select(x => x.TechnicalKey)))} does not exists"); } var constraints = new List(); @@ -138,21 +186,46 @@ public async Task GetPolicyContentAsync(PolicyContentRequest req throw new UnexpectedConditionException("There must be one configured rightOperand value"); } - var (rightOperand, additionalAttribute) = policy.Attributes.Key != null ? - GetRightOperand(constraint.Operator, policy.Attributes, rightOperands, constraint.Value, policy.LeftOperand) : - (policy.RightOperandValue!, null); - if (additionalAttribute != null) + if (constraint.Value != null) { - additionalAttributes ??= new List(); - additionalAttributes.Add(additionalAttribute); + foreach (var keyValue in constraint.Value.Split(",")) + { + var (rightOperand, additionalAttribute) = policy.Attributes.Key != null ? + GetRightOperand(constraint.Operator, policy.Attributes, rightOperands, keyValue.Trim(), policy.LeftOperand, null) : + (policy.RightOperandValue!, null); + if (additionalAttribute != null) + { + additionalAttributes ??= new List(); + additionalAttributes.Add(additionalAttribute); + } + + constraints.Add(new Constraint(null, + null, + "cx-policy:" + policy.LeftOperand, + constraint.Operator.OperatorToJsonString(), + rightOperand + )); + + } + } + else + { + var (rightOperand, additionalAttribute) = policy.Attributes.Key != null ? + GetRightOperand(constraint.Operator, policy.Attributes, rightOperands, null, policy.LeftOperand, null) : + (policy.RightOperandValue!, null); + if (additionalAttribute != null) + { + additionalAttributes ??= new List(); + additionalAttributes.Add(additionalAttribute); + } + + constraints.Add(new Constraint(null, + null, + "cx-policy:" + policy.LeftOperand, + constraint.Operator.OperatorToJsonString(), + rightOperand + )); } - - constraints.Add(new Constraint(null, - null, - policy.LeftOperand, - constraint.Operator.OperatorToJsonString(), - rightOperand - )); } var permission = new Permission( diff --git a/src/hub/PolicyHub.Service/Controllers/PolicyHubController.cs b/src/hub/PolicyHub.Service/Controllers/PolicyHubController.cs index dfc157f..cf67bb3 100644 --- a/src/hub/PolicyHub.Service/Controllers/PolicyHubController.cs +++ b/src/hub/PolicyHub.Service/Controllers/PolicyHubController.cs @@ -23,7 +23,7 @@ using Org.Eclipse.TractusX.PolicyHub.Service.BusinessLogic; using Org.Eclipse.TractusX.PolicyHub.Service.Extensions; using Org.Eclipse.TractusX.PolicyHub.Service.Models; -using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Service; +using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Web; using System.Diagnostics.CodeAnalysis; namespace Org.Eclipse.TractusX.PolicyHub.Service.Controllers; @@ -46,7 +46,7 @@ public static RouteGroupBuilder MapPolicyHubApi(this RouteGroupBuilder group) .Produces(StatusCodes.Status200OK, typeof(string), Constants.JsonContentType); policyHub.MapGet("policy-types", (PolicyTypeId? type, UseCaseId? useCase, IPolicyHubBusinessLogic logic) => logic.GetPolicyTypes(type, useCase)) - .WithSwaggerDescription("Gets the policy types", + .WithSwaggerDescription("Provides all current supported policy types incl. a policy description and useCase link.", "Example: GET: api/policy-hub/policy-types", "OPTIONAL: Type to filter the response", "OPTIONAL: UseCase to filter the response") @@ -57,24 +57,24 @@ public static RouteGroupBuilder MapPolicyHubApi(this RouteGroupBuilder group) policyHub.MapGet("policy-content", (UseCaseId? useCase, PolicyTypeId type, - string credential, - OperatorId operatorId, + string policyName, + OperatorId operatorType, string? value, - IPolicyHubBusinessLogic logic) => logic.GetPolicyContentWithFiltersAsync(useCase, type, credential, operatorId, value)) - .WithSwaggerDescription("Gets the content for a specific policy type", + IPolicyHubBusinessLogic logic) => logic.GetPolicyContentWithFiltersAsync(useCase, type, policyName, operatorType, value)) + .WithSwaggerDescription("Receive the policy template 'access' or 'usage' for a single policy rule based on the request parameters submitted by the user.", "Example: GET: api/policy-hub/policy-content", "OPTIONAL: The use case", - "Type of the policy to get the content for", + "Policy type for which the policy is supposed to get created. Possible values: 'Access' or 'Usage'", "The technical key of the policy", - "The operator of the left and right operand", - "OPTIONAL: Value for dynamic or regex operands") + "Policy Rule operator. Possible values: 'Equals' or 'In'", + "OPTIONAL: Value to be used for the rightOperand") .RequireAuthorization() .WithDefaultResponses() .Produces(StatusCodes.Status200OK, typeof(PolicyResponse), Constants.JsonContentType) .Produces(StatusCodes.Status404NotFound, typeof(ErrorResponse), Constants.JsonContentType); policyHub.MapPost("policy-content", ([FromBody] PolicyContentRequest requestData, IPolicyHubBusinessLogic logic) => logic.GetPolicyContentAsync(requestData)) - .WithSwaggerDescription("Gets the content for a specific policy type", + .WithSwaggerDescription("Receive the policy template 'access' or 'usage' for multiple policy rule template based on the input request body.", "Example: POST: api/policy-hub/policy-content", "Request data with the configuration of the constraints") .RequireAuthorization() diff --git a/src/hub/PolicyHub.Service/Extensions/RouteHandlerBuilderExtensions.cs b/src/hub/PolicyHub.Service/Extensions/RouteHandlerBuilderExtensions.cs index b444bfb..280e032 100644 --- a/src/hub/PolicyHub.Service/Extensions/RouteHandlerBuilderExtensions.cs +++ b/src/hub/PolicyHub.Service/Extensions/RouteHandlerBuilderExtensions.cs @@ -17,7 +17,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Service; +using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Web; using System.Diagnostics.CodeAnalysis; namespace Org.Eclipse.TractusX.PolicyHub.Service.Extensions; diff --git a/src/hub/PolicyHub.Service/PolicyHub.Service.csproj b/src/hub/PolicyHub.Service/PolicyHub.Service.csproj index 42b261d..e96ff48 100644 --- a/src/hub/PolicyHub.Service/PolicyHub.Service.csproj +++ b/src/hub/PolicyHub.Service/PolicyHub.Service.csproj @@ -22,7 +22,7 @@ Org.Eclipse.TractusX.PolicyHub.Service Org.Eclipse.TractusX.PolicyHub.Service - net7.0 + net8.0 enable enable Linux @@ -34,9 +34,9 @@ - - - + + + diff --git a/tests/database/PolicyHub.DbAccess.Tests/HubRepositoriesTests.cs b/tests/database/PolicyHub.DbAccess.Tests/HubRepositoriesTests.cs index c0280b9..2e01a2c 100644 --- a/tests/database/PolicyHub.DbAccess.Tests/HubRepositoriesTests.cs +++ b/tests/database/PolicyHub.DbAccess.Tests/HubRepositoriesTests.cs @@ -8,7 +8,9 @@ public class HubRepositoriesTests : IAssemblyFixture { private readonly TestDbFixture _dbTestDbFixture; +#pragma warning disable xUnit1041 // Fixture arguments to test classes must have fixture sources public HubRepositoriesTests(TestDbFixture testDbFixture) +#pragma warning restore xUnit1041 // Fixture arguments to test classes must have fixture sources { _dbTestDbFixture = testDbFixture; } @@ -18,7 +20,7 @@ public HubRepositoriesTests(TestDbFixture testDbFixture) [Fact] public async Task GetInstance_WithValid_ReturnsExpected() { - var sut = await CreateSut().ConfigureAwait(false); + var sut = await CreateSut(); var repo = sut.GetInstance(); diff --git a/tests/database/PolicyHub.DbAccess.Tests/PolicyHub.DbAccess.Tests.csproj b/tests/database/PolicyHub.DbAccess.Tests/PolicyHub.DbAccess.Tests.csproj index 134f1f6..4f8a1be 100644 --- a/tests/database/PolicyHub.DbAccess.Tests/PolicyHub.DbAccess.Tests.csproj +++ b/tests/database/PolicyHub.DbAccess.Tests/PolicyHub.DbAccess.Tests.csproj @@ -21,7 +21,7 @@ Org.Eclipse.TractusX.PolicyHub.DbAccess.Tests Org.Eclipse.TractusX.PolicyHub.DbAccess.Tests - net7.0 + net8.0 enable enable false @@ -32,23 +32,23 @@ - - - - - - - + + + + + + + - - - + + + - + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/tests/database/PolicyHub.DbAccess.Tests/PolicyRepositoryTests.cs b/tests/database/PolicyHub.DbAccess.Tests/PolicyRepositoryTests.cs index b88fc2b..389b85e 100644 --- a/tests/database/PolicyHub.DbAccess.Tests/PolicyRepositoryTests.cs +++ b/tests/database/PolicyHub.DbAccess.Tests/PolicyRepositoryTests.cs @@ -31,7 +31,9 @@ public class PolicyRepositoryTests : IAssemblyFixture { private readonly TestDbFixture _dbTestDbFixture; +#pragma warning disable xUnit1041 // Fixture arguments to test classes must have fixture sources public PolicyRepositoryTests(TestDbFixture testDbFixture) +#pragma warning restore xUnit1041 // Fixture arguments to test classes must have fixture sources { _dbTestDbFixture = testDbFixture; } @@ -42,10 +44,10 @@ public PolicyRepositoryTests(TestDbFixture testDbFixture) public async Task GetAttributeKeys_ReturnsExpectedResult() { // Arrange - var sut = await CreateSut().ConfigureAwait(false); + var sut = await CreateSut(); // Act - var result = await sut.GetAttributeKeys().ToListAsync().ConfigureAwait(false); + var result = await sut.GetAttributeKeys().ToListAsync(); // Assert result.Should().NotBeEmpty().And.HaveCount(5).And.Satisfy( @@ -64,24 +66,19 @@ public async Task GetAttributeKeys_ReturnsExpectedResult() public async Task GetPolicyTypes_ReturnsExpectedResult() { // Arrange - var sut = await CreateSut().ConfigureAwait(false); + var sut = await CreateSut(); // Act - var result = await sut.GetPolicyTypes(null, null).ToListAsync().ConfigureAwait(false); + var result = await sut.GetPolicyTypes(null, null).ToListAsync(); // Assert - result.Should().NotBeEmpty().And.HaveCount(11).And.Satisfy( + result.Should().NotBeEmpty().And.HaveCount(6).And.Satisfy( x => x.TechnicalKey == "BusinessPartnerNumber", x => x.TechnicalKey == "Membership", - x => x.TechnicalKey == "FrameworkAgreement.traceability", - x => x.TechnicalKey == "FrameworkAgreement.quality", - x => x.TechnicalKey == "FrameworkAgreement.pcf", - x => x.TechnicalKey == "FrameworkAgreement.behavioraltwin", - x => x.TechnicalKey == "purpose.trace.v1.TraceBattery", - x => x.TechnicalKey == "purpose.trace.v1.aspects", - x => x.TechnicalKey == "companyRole.dismantler", - x => x.TechnicalKey == "purpose.trace.v1.qualityanalysis", - x => x.TechnicalKey == "purpose" + x => x.TechnicalKey == "FrameworkAgreement", + x => x.TechnicalKey == "Dismantler.allowedBrands", + x => x.TechnicalKey == "UsagePurpose", + x => x.TechnicalKey == "Dismantler" ); } @@ -89,16 +86,17 @@ public async Task GetPolicyTypes_ReturnsExpectedResult() public async Task GetPolicyTypes_WithTypeFilter_ReturnsExpectedResult() { // Arrange - var sut = await CreateSut().ConfigureAwait(false); + var sut = await CreateSut(); // Act - var result = await sut.GetPolicyTypes(PolicyTypeId.Access, null).ToListAsync().ConfigureAwait(false); + var result = await sut.GetPolicyTypes(PolicyTypeId.Access, null).ToListAsync(); // Assert - result.Should().NotBeEmpty().And.HaveCount(3).And.Satisfy( + result.Should().NotBeEmpty().And.HaveCount(4).And.Satisfy( x => x.TechnicalKey == "BusinessPartnerNumber" && x.Attribute.Count() == 1 && x.Type.Count() == 2 && x.UseCase.Count() == 5, x => x.TechnicalKey == "Membership" && x.Attribute.Count() == 1 && x.Type.Count() == 2 && x.UseCase.Count() == 5, - x => x.TechnicalKey == "companyRole.dismantler" && x.Attribute.Count() == 3 && x.Type.Count() == 2 && x.UseCase.Count() == 5 + x => x.TechnicalKey == "Dismantler.allowedBrands" && x.Attribute.Count() == 3 && x.Type.Count() == 2 && x.UseCase.Count() == 5, + x => x.TechnicalKey == "Dismantler" && x.Attribute.Count() == 1 && x.Type.Count() == 2 && x.UseCase.Count() == 5 ); } @@ -106,16 +104,18 @@ public async Task GetPolicyTypes_WithTypeFilter_ReturnsExpectedResult() public async Task GetPolicyTypes_WithUseCase_ReturnsExpectedResult() { // Arrange - var sut = await CreateSut().ConfigureAwait(false); + var sut = await CreateSut(); // Act - var result = await sut.GetPolicyTypes(null, UseCaseId.Sustainability).ToListAsync().ConfigureAwait(false); + var result = await sut.GetPolicyTypes(null, UseCaseId.Quality).ToListAsync(); // Assert - result.Should().NotBeEmpty().And.HaveCount(3).And.Satisfy( + result.Should().NotBeEmpty().And.HaveCount(5).And.Satisfy( x => x.TechnicalKey == "BusinessPartnerNumber" && x.Attribute.Count() == 1 && x.Type.Count() == 2 && x.UseCase.Count() == 5, x => x.TechnicalKey == "Membership" && x.Attribute.Count() == 1 && x.Type.Count() == 2 && x.UseCase.Count() == 5, - x => x.TechnicalKey == "companyRole.dismantler" && x.Attribute.Count() == 3 && x.Type.Count() == 2 && x.UseCase.Count() == 5 + x => x.TechnicalKey == "Dismantler.allowedBrands" && x.Attribute.Count() == 3 && x.Type.Count() == 2 && x.UseCase.Count() == 5, + x => x.TechnicalKey == "FrameworkAgreement" && x.Attribute.Count() == 10 && x.Type.Count() == 1 && x.UseCase.Count() == 5, + x => x.TechnicalKey == "Dismantler" && x.Attribute.Count() == 1 && x.Type.Count() == 2 && x.UseCase.Count() == 5 ); } @@ -127,17 +127,17 @@ public async Task GetPolicyTypes_WithUseCase_ReturnsExpectedResult() public async Task GetPolicyContentAsync_WithoutRightOperand_ReturnsExpectedResult() { // Arrange - var sut = await CreateSut().ConfigureAwait(false); + var sut = await CreateSut(); // Act - var result = await sut.GetPolicyContentAsync(null, PolicyTypeId.Usage, "purpose.trace.v1.TraceBattery").ConfigureAwait(false); + var result = await sut.GetPolicyContentAsync(null, PolicyTypeId.Usage, "Membership"); // Assert result.Exists.Should().BeTrue(); result.Attributes.Key.Should().Be(AttributeKeyId.Static); result.Attributes.Values.Should().ContainSingle() - .And.Satisfy(x => x == "purpose.trace.v1.TraceBattery"); - result.LeftOperand.Should().Be("purpose.trace.v1.TraceBattery"); + .And.Satisfy(x => x == "active"); + result.LeftOperand.Should().Be("Membership"); result.RightOperandValue.Should().BeNull(); } @@ -145,18 +145,28 @@ public async Task GetPolicyContentAsync_WithoutRightOperand_ReturnsExpectedResul public async Task GetPolicyContentAsync_WithRightOperand_ReturnsExpectedResult() { // Arrange - var sut = await CreateSut().ConfigureAwait(false); + var sut = await CreateSut(); // Act - var result = await sut.GetPolicyContentAsync(null, PolicyTypeId.Usage, "FrameworkAgreement.behavioraltwin").ConfigureAwait(false); + var result = await sut.GetPolicyContentAsync(null, PolicyTypeId.Usage, "FrameworkAgreement"); // Assert result.Exists.Should().BeTrue(); result.Attributes.Key.Should().Be(AttributeKeyId.Version); - result.Attributes.Values.Should().ContainSingle() - .And.Satisfy(x => x == "1.0"); - result.LeftOperand.Should().Be("FrameworkAgreement.behavioraltwin"); - result.RightOperandValue.Should().Be("active:{0}"); + result.Attributes.Values.Should().Satisfy( + x => x == "Traceability:1.0", + x => x == "Traceability:1.1", + x => x == "Traceability:1.2", + x => x == "Quality:1.0", + x => x == "PCF:1.0", + x => x == "Behavioraltwin:1.0", + x => x == "Circulareconomy:1.0", + x => x == "Demandcapacity:1.0", + x => x == "Puris:1.0", + x => x == "Businesspartner:1.0" + ); + result.LeftOperand.Should().Be("FrameworkAgreement"); + result.RightOperandValue.Should().BeNull(); } #endregion @@ -167,18 +177,18 @@ public async Task GetPolicyContentAsync_WithRightOperand_ReturnsExpectedResult() public async Task GetPolicyForOperandContent__ReturnsExpectedResult() { // Arrange - var sut = await CreateSut().ConfigureAwait(false); + var sut = await CreateSut(); // Act - var result = await sut.GetPolicyForOperandContent(PolicyTypeId.Usage, Enumerable.Repeat("purpose.trace.v1.TraceBattery", 1)).ToListAsync().ConfigureAwait(false); + var result = await sut.GetPolicyForOperandContent(PolicyTypeId.Usage, Enumerable.Repeat("Membership", 1)).ToListAsync(); // Assert result.Should().ContainSingle() .And.Satisfy( - x => x.TechnicalKey == "purpose.trace.v1.TraceBattery" && + x => x.TechnicalKey == "Membership" && x.Attributes.Key == AttributeKeyId.Static && - x.Attributes.Values.Single() == "purpose.trace.v1.TraceBattery" && - x.LeftOperand == "purpose.trace.v1.TraceBattery" && + x.Attributes.Values.Single() == "active" && + x.LeftOperand == "Membership" && x.RightOperandValue == null); } diff --git a/tests/database/PolicyHub.Entities.Tests/PolicyHub.Entities.Tests.csproj b/tests/database/PolicyHub.Entities.Tests/PolicyHub.Entities.Tests.csproj index 447ffe5..bb42047 100644 --- a/tests/database/PolicyHub.Entities.Tests/PolicyHub.Entities.Tests.csproj +++ b/tests/database/PolicyHub.Entities.Tests/PolicyHub.Entities.Tests.csproj @@ -21,7 +21,7 @@ Org.Eclipse.TractusX.PolicyHub.Entities.Tests Org.Eclipse.TractusX.PolicyHub.Entities.Tests - net7.0 + net8.0 enable enable false @@ -34,17 +34,17 @@ - + - + - + - + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/tests/hub/PolicyHub.Service.Tests/Authentication/KeycloakClaimsTransformationTests.cs b/tests/hub/PolicyHub.Service.Tests/Authentication/KeycloakClaimsTransformationTests.cs index bb6cdf1..4771c58 100644 --- a/tests/hub/PolicyHub.Service.Tests/Authentication/KeycloakClaimsTransformationTests.cs +++ b/tests/hub/PolicyHub.Service.Tests/Authentication/KeycloakClaimsTransformationTests.cs @@ -50,7 +50,7 @@ public async Task TransformAsync_WithoutRoles_ReturnsExpected() var principal = new ClaimsPrincipal(identity); // Act - var result = await _sut.TransformAsync(principal).ConfigureAwait(false); + var result = await _sut.TransformAsync(principal); // Assert result.Claims.Should().ContainSingle() @@ -66,7 +66,7 @@ public async Task TransformAsync_WithRoles_ReturnsExpected() var principal = new ClaimsPrincipal(identity); // Act - var result = await _sut.TransformAsync(principal).ConfigureAwait(false); + var result = await _sut.TransformAsync(principal); // Assert result.Claims.Should().HaveCount(2).And.Satisfy( @@ -83,7 +83,7 @@ public async Task TransformAsync_WithIntRole_ReturnsExpected() var principal = new ClaimsPrincipal(identity); // Act - var result = await _sut.TransformAsync(principal).ConfigureAwait(false); + var result = await _sut.TransformAsync(principal); // Assert result.Claims.Should().ContainSingle() diff --git a/tests/hub/PolicyHub.Service.Tests/BusinessLogic/PolicyHubBusinessLogicTests.cs b/tests/hub/PolicyHub.Service.Tests/BusinessLogic/PolicyHubBusinessLogicTests.cs index 2e49723..f42afbe 100644 --- a/tests/hub/PolicyHub.Service.Tests/BusinessLogic/PolicyHubBusinessLogicTests.cs +++ b/tests/hub/PolicyHub.Service.Tests/BusinessLogic/PolicyHubBusinessLogicTests.cs @@ -58,7 +58,7 @@ public async Task GetAttributeKeys_ReturnsExpected() Setup_GetAttributeKeys(); // Act - var result = await _sut.GetAttributeKeys().ToListAsync().ConfigureAwait(false); + var result = await _sut.GetAttributeKeys().ToListAsync(); // Assert result.Should().HaveCount(5); @@ -75,7 +75,7 @@ public async Task GetPolicyTypes_WithoutFilter_ReturnsExpected() Setup_GetPolicyTypes(); // Act - var result = await _sut.GetPolicyTypes(null, null).ToListAsync().ConfigureAwait(false); + var result = await _sut.GetPolicyTypes(null, null).ToListAsync(); // Assert result.Should().HaveCount(2); @@ -88,7 +88,7 @@ public async Task GetPolicyTypes_WithUseCaseFilter_ReturnsExpected() Setup_GetPolicyTypes(); // Act - var result = await _sut.GetPolicyTypes(null, UseCaseId.Sustainability).ToListAsync().ConfigureAwait(false); + var result = await _sut.GetPolicyTypes(null, UseCaseId.Sustainability).ToListAsync(); // Assert result.Should().ContainSingle(); @@ -105,7 +105,7 @@ public async Task GetPolicyContentWithFiltersAsync_WithNotExistingInDatabase_Thr const PolicyTypeId policyTypeId = PolicyTypeId.Access; A.CallTo(() => _policyRepository.GetPolicyContentAsync(null, policyTypeId, "membership")) .Returns(new ValueTuple), string?>(false, null!, default, null!)); - async Task Act() => await _sut.GetPolicyContentWithFiltersAsync(null, policyTypeId, "membership", OperatorId.Equals, null); + Task Act() => _sut.GetPolicyContentWithFiltersAsync(null, policyTypeId, "membership", OperatorId.Equals, null); // Act var ex = await Assert.ThrowsAsync(Act); @@ -121,7 +121,7 @@ public async Task GetPolicyContentWithFiltersAsync_AttributeAndRightOperandNull_ const PolicyTypeId policyTypeId = PolicyTypeId.Access; A.CallTo(() => _policyRepository.GetPolicyContentAsync(null, policyTypeId, "membership")) .Returns(new ValueTuple), string?>(true, "test", (null, Enumerable.Empty()), null!)); - async Task Act() => await _sut.GetPolicyContentWithFiltersAsync(null, policyTypeId, "membership", OperatorId.Equals, null); + Task Act() => _sut.GetPolicyContentWithFiltersAsync(null, policyTypeId, "membership", OperatorId.Equals, null); // Act var ex = await Assert.ThrowsAsync(Act); @@ -152,10 +152,10 @@ public async Task GetPolicyContentWithFiltersAsync_WithMultipleRegexValues_Throw const PolicyTypeId policyTypeId = PolicyTypeId.Access; A.CallTo(() => _policyRepository.GetPolicyContentAsync(null, policyTypeId, "membership")) .Returns(new ValueTuple), string?>(true, "test", (AttributeKeyId.Regex, new[] { "test1", "test2" }), null)); - async Task Act() => await _sut.GetPolicyContentWithFiltersAsync(null, policyTypeId, "membership", OperatorId.Equals, "test"); + Task Act() => _sut.GetPolicyContentWithFiltersAsync(null, policyTypeId, "membership", OperatorId.Equals, "test"); // Act - var ex = await Assert.ThrowsAsync(Act).ConfigureAwait(false); + var ex = await Assert.ThrowsAsync(Act); // Assert ex.Message.Should().Be("There should only be one regex pattern defined"); @@ -169,7 +169,7 @@ public async Task GetPolicyContentWithFiltersAsync_WithMultipleValues_ReturnsExp .Returns(new ValueTuple>, string?>(true, "multipleAdditionalValues", new ValueTuple>(AttributeKeyId.Static, new[] { "value1", "value2", "value3" }), null)); // Act - var result = await _sut.GetPolicyContentWithFiltersAsync(UseCaseId.Traceability, PolicyTypeId.Usage, "multipleAdditionalValues", OperatorId.Equals, "test").ConfigureAwait(false); + var result = await _sut.GetPolicyContentWithFiltersAsync(UseCaseId.Traceability, PolicyTypeId.Usage, "multipleAdditionalValues", OperatorId.Equals, "test"); // Assert result.Content.Id.Should().Be("...."); @@ -181,8 +181,8 @@ public async Task GetPolicyContentWithFiltersAsync_WithMultipleValues_ReturnsExp x => x == "value2", x => x == "value3" ); - result.Content.Permission.Constraint.RightOperandValue.Should().Be("@multipleAdditionalValues-Static"); - result.Content.Permission.Constraint.LeftOperand.Should().Be("multipleAdditionalValues"); + result.Content.Permission.Constraint.RightOperandValue.Should().Be("@multipleAdditionalValues.Traceability-Static"); + result.Content.Permission.Constraint.LeftOperand.Should().Be("cx-policy:multipleAdditionalValues"); result.Content.Permission.Constraint.Operator.Should().Be("eq"); result.Content.Permission.Constraint.AndOperands.Should().BeNull(); result.Content.Permission.Constraint.OrOperands.Should().BeNull(); @@ -202,32 +202,88 @@ public async Task GetPolicyContentAsync_WithUnmatchingPoliciesAndConstraints_Thr new Constraints("test", OperatorId.In, null), new Constraints("abc", OperatorId.Equals, null) }); + A.CallTo(() => _policyRepository.GetAttributeValuesForTechnicalKeys(data.PolicyType, A>._)) + .Returns([ + ("test", AttributeKeyId.Version, []), + ("abc", AttributeKeyId.Version, []), + ]); A.CallTo(() => _policyRepository.GetPolicyForOperandContent(data.PolicyType, A>._)) .Returns(Enumerable.Repeat(new ValueTuple>, string?>("test", "active", default, null), 1).ToAsyncEnumerable()); - async Task Act() => await _sut.GetPolicyContentAsync(data); + Task Act() => _sut.GetPolicyContentAsync(data); // Act - var ex = await Assert.ThrowsAsync(Act).ConfigureAwait(false); + var ex = await Assert.ThrowsAsync(Act); // Assert ex.Message.Should().Be($"Policy for type {data.PolicyType} and technicalKeys abc does not exists"); } [Fact] - public async Task GetPolicyContentAsync_WithAttributeAndRightOperandNull_ThrowsUnexpectedConditionException() + public async Task GetPolicyContentAsync_WithUnmatchingTechnicalKeys_ThrowsControllerArgumentException() { // Arrange var data = new PolicyContentRequest(PolicyTypeId.Access, ConstraintOperandId.Or, new[] { new Constraints("test", OperatorId.In, null), + new Constraints("abc", OperatorId.Equals, null) }); + A.CallTo(() => _policyRepository.GetAttributeValuesForTechnicalKeys(data.PolicyType, A>._)) + .Returns([("test", AttributeKeyId.Version, [])]); A.CallTo(() => _policyRepository.GetPolicyForOperandContent(data.PolicyType, A>._)) - .Returns(Enumerable.Repeat(new ValueTuple>, string?>("test", "active", (null, Enumerable.Empty()), null), 1).ToAsyncEnumerable()); + .Returns(Enumerable.Repeat(new ValueTuple>, string?>("test", "active", default, null), 1).ToAsyncEnumerable()); + async Task Act() => await _sut.GetPolicyContentAsync(data); + + // Act + var ex = await Assert.ThrowsAsync(Act); + + // Assert + ex.Message.Should().Be($"Policy for type {data.PolicyType} and requested technicalKeys does not exists. TechnicalKeys test are allowed"); + } + + [Fact] + public async Task GetPolicyContentAsync_WithUnmatchingAttributeValues_ThrowsControllerArgumentException() + { + // Arrange + var data = new PolicyContentRequest(PolicyTypeId.Access, ConstraintOperandId.Or, + new[] + { + new Constraints("test", OperatorId.In, "abc"), + new Constraints("abc", OperatorId.Equals, null) + }); + A.CallTo(() => _policyRepository.GetAttributeValuesForTechnicalKeys(data.PolicyType, A>._)) + .Returns([ + ("test", AttributeKeyId.Version, ["test"]), + ("abc", AttributeKeyId.Version, []) + ]); + A.CallTo(() => _policyRepository.GetPolicyForOperandContent(data.PolicyType, A>._)) + .Returns(Enumerable.Repeat(new ValueTuple>, string?>("test", "active", default, null), 1).ToAsyncEnumerable()); async Task Act() => await _sut.GetPolicyContentAsync(data); // Act - var ex = await Assert.ThrowsAsync(Act).ConfigureAwait(false); + var ex = await Assert.ThrowsAsync(Act); + + // Assert + ex.Message.Should().Be("Invalid values set for Key: test, invalid values: abc"); + } + + [Fact] + public async Task GetPolicyContentAsync_WithAttributeAndRightOperandNull_ThrowsUnexpectedConditionException() + { + // Arrange + var data = new PolicyContentRequest(PolicyTypeId.Access, ConstraintOperandId.Or, + new[] + { + new Constraints("test", OperatorId.In, "test1"), + }); + A.CallTo(() => _policyRepository.GetAttributeValuesForTechnicalKeys(data.PolicyType, A>._)) + .Returns([("test", AttributeKeyId.Version, new List { "test1" })]); + A.CallTo(() => _policyRepository.GetPolicyForOperandContent(data.PolicyType, A>._)) + .Returns(Enumerable.Repeat(new ValueTuple>, string?>("test", "active", (null, Enumerable.Empty()), null), 1).ToAsyncEnumerable()); + Task Act() => _sut.GetPolicyContentAsync(data); + + // Act + var ex = await Assert.ThrowsAsync(Act); // Assert ex.Message.Should().Be("There must be one configured rightOperand value"); @@ -242,12 +298,14 @@ public async Task GetPolicyContentAsync_WithRegexWithoutValue_ThrowsControllerAr { new Constraints("test", OperatorId.Equals, null), }); + A.CallTo(() => _policyRepository.GetAttributeValuesForTechnicalKeys(data.PolicyType, A>._)) + .Returns([("test", AttributeKeyId.Regex, new List { "test1" })]); A.CallTo(() => _policyRepository.GetPolicyForOperandContent(data.PolicyType, A>._)) .Returns(Enumerable.Repeat(new ValueTuple>, string?>("test", "active", (AttributeKeyId.Regex, Enumerable.Repeat(@"^BPNL[\w|\d]{12}$", 1)), null), 1).ToAsyncEnumerable()); - async Task Act() => await _sut.GetPolicyContentAsync(data); + Task Act() => _sut.GetPolicyContentAsync(data); // Act - var ex = await Assert.ThrowsAsync(Act).ConfigureAwait(false); + var ex = await Assert.ThrowsAsync(Act); // Assert ex.ParamName.Should().Be("value"); @@ -263,18 +321,104 @@ public async Task GetPolicyContentAsync_WithRegexWithoutMatchingRegexPattern_Thr { new Constraints("test", OperatorId.Equals, "testRegValue"), }); + A.CallTo(() => _policyRepository.GetAttributeValuesForTechnicalKeys(data.PolicyType, A>._)) + .Returns([("test", AttributeKeyId.Version, new List { "testRegValue" })]); A.CallTo(() => _policyRepository.GetPolicyForOperandContent(data.PolicyType, A>._)) .Returns(Enumerable.Repeat(new ValueTuple>, string?>("test", "active", (AttributeKeyId.Regex, Enumerable.Repeat(@"^BPNL[\w|\d]{12}$", 1)), null), 1).ToAsyncEnumerable()); - async Task Act() => await _sut.GetPolicyContentAsync(data); + Task Act() => _sut.GetPolicyContentAsync(data); // Act - var ex = await Assert.ThrowsAsync(Act).ConfigureAwait(false); + var ex = await Assert.ThrowsAsync(Act); // Assert ex.ParamName.Should().Be("value"); ex.Message.Should().Be(@"The provided value testRegValue does not match the regex pattern ^BPNL[\w|\d]{12}$ (Parameter 'value')"); } + [Fact] + public async Task GetPolicyContentAsync_WithUsageConstraintNotAllowedWithOR_ThrowsControllerArgumentException() + { + // Arrange + var data = new PolicyContentRequest(PolicyTypeId.Usage, ConstraintOperandId.Or, + new[] + { + new Constraints("test", OperatorId.Equals, "testRegValue"), + }); + A.CallTo(() => _policyRepository.GetAttributeValuesForTechnicalKeys(data.PolicyType, A>._)) + .Returns([("test", AttributeKeyId.Version, new List { "testRegValue" })]); + + async Task Act() => await _sut.GetPolicyContentAsync(data); + + // Act + var ex = await Assert.ThrowsAsync(Act); + + // Assert + ex.Message.Should().Be("The support of OR constraintOperand for Usage constraints are not supported for now"); + } + + [Fact] + public async Task GetPolicyContentAsync_WithBPNLAllowingANDOperandWithSingleBPNL_ThrowsControllerArgumentException() + { + // Arrange + var data = new PolicyContentRequest(PolicyTypeId.Access, ConstraintOperandId.And, + new[] + { + new Constraints("BusinessPartnerNumber", OperatorId.Equals, "BPNL00000003CRHK,BPNL00000004CRHK"), + }); + A.CallTo(() => _policyRepository.GetAttributeValuesForTechnicalKeys(data.PolicyType, A>._)) + .Returns([("test", AttributeKeyId.Version, new List { "testRegValue" })]); + + async Task Act() => await _sut.GetPolicyContentAsync(data); + + // Act + var ex = await Assert.ThrowsAsync(Act); + + // Assert + ex.Message.Should().Be("Only a single value BPNL is allowed with an AND constraint"); + } + + [Fact] + public async Task GetPolicyContentAsync_WithBPNLOperatorShouldEquals_ThrowsControllerArgumentException() + { + // Arrange + var data = new PolicyContentRequest(PolicyTypeId.Access, ConstraintOperandId.And, + new[] + { + new Constraints("BusinessPartnerNumber", OperatorId.In, "BPNL00000003CRHK"), + }); + A.CallTo(() => _policyRepository.GetAttributeValuesForTechnicalKeys(data.PolicyType, A>._)) + .Returns([("test", AttributeKeyId.Version, new List { "testRegValue" })]); + + async Task Act() => await _sut.GetPolicyContentAsync(data); + + // Act + var ex = await Assert.ThrowsAsync(Act); + + // Assert + ex.Message.Should().Be("The operator for BPNLs should always be Equals"); + } + + [Fact] + public async Task GetPolicyContentAsync_WithUsagePolicyOnlySingleBPNLAllowed_ThrowsControllerArgumentException() + { + // Arrange + var data = new PolicyContentRequest(PolicyTypeId.Usage, ConstraintOperandId.And, + new[] + { + new Constraints("BusinessPartnerNumber", OperatorId.Equals, "BPNL00000003CRHK,BPNL00000003CRHK"), + }); + A.CallTo(() => _policyRepository.GetAttributeValuesForTechnicalKeys(data.PolicyType, A>._)) + .Returns([("test", AttributeKeyId.Version, new List { "testRegValue" })]); + + async Task Act() => await _sut.GetPolicyContentAsync(data); + + // Act + var ex = await Assert.ThrowsAsync(Act); + + // Assert + ex.Message.Should().Be("For usage policies only a single BPNL is allowed"); + } + [Fact] public async Task GetPolicyContentAsync_WithMultipleDefinedKeys_ThrowsNotFoundException() { @@ -285,15 +429,17 @@ public async Task GetPolicyContentAsync_WithMultipleDefinedKeys_ThrowsNotFoundEx new Constraints("test", OperatorId.In, null), new Constraints("test", OperatorId.Equals, null) }); + A.CallTo(() => _policyRepository.GetAttributeValuesForTechnicalKeys(data.PolicyType, A>._)) + .Returns([]); A.CallTo(() => _policyRepository.GetPolicyForOperandContent(data.PolicyType, A>._)) .Returns(new[] { new ValueTuple>, string?>("test", "active", default, null) }.ToAsyncEnumerable()); - async Task Act() => await _sut.GetPolicyContentAsync(data); + Task Act() => _sut.GetPolicyContentAsync(data); // Act - var ex = await Assert.ThrowsAsync(Act).ConfigureAwait(false); + var ex = await Assert.ThrowsAsync(Act); // Assert ex.Message.Should().Be("Keys test have been defined multiple times"); @@ -311,6 +457,13 @@ public async Task GetPolicyContentAsync_WithValid_ReturnsExpected() new Constraints("dynamicWithoutValue", OperatorId.Equals, null), new Constraints("dynamicWithValue", OperatorId.Equals, "test") }); + A.CallTo(() => _policyRepository.GetAttributeValuesForTechnicalKeys(data.PolicyType, A>._)) + .Returns([ + ("inValues", AttributeKeyId.Version, []), + ("regValue", AttributeKeyId.Regex, ["BPNL..."]), + ("dynamicWithoutValue", AttributeKeyId.DynamicValue, []), + ("dynamicWithValue", AttributeKeyId.DynamicValue, []), + ]); A.CallTo(() => _policyRepository.GetPolicyForOperandContent(data.PolicyType, A>._)) .Returns(new[] { @@ -321,7 +474,7 @@ public async Task GetPolicyContentAsync_WithValid_ReturnsExpected() }.ToAsyncEnumerable()); // Act - var result = await _sut.GetPolicyContentAsync(data).ConfigureAwait(false); + var result = await _sut.GetPolicyContentAsync(data); // Assert result.Content.Id.Should().Be("...."); @@ -332,10 +485,10 @@ public async Task GetPolicyContentAsync_WithValid_ReturnsExpected() result.Content.Permission.Constraint.AndOperands.Should().BeNull(); result.Content.Permission.Constraint.OrOperands.Should().HaveCount(4) .And.Satisfy( - x => x.LeftOperand == "active" && x.Operator == "in" && ((x.RightOperandValue as IEnumerable)!).Count() == 2, - x => x.LeftOperand == "active" && x.Operator == "eq" && x.RightOperandValue as string == "BPNL00000001TEST", - x => x.LeftOperand == "active" && x.Operator == "eq" && x.RightOperandValue as string == "{dynamicValue}", - x => x.LeftOperand == "active" && x.Operator == "eq" && x.RightOperandValue as string == "test"); + x => x.LeftOperand == "cx-policy:active" && x.Operator == "in" && ((x.RightOperandValue as IEnumerable)!).Count() == 2, + x => x.LeftOperand == "cx-policy:active" && x.Operator == "eq" && x.RightOperandValue as string == "BPNL00000001TEST", + x => x.LeftOperand == "cx-policy:active" && x.Operator == "eq" && x.RightOperandValue as string == "{dynamicValue}", + x => x.LeftOperand == "cx-policy:active" && x.Operator == "eq" && x.RightOperandValue as string == "test"); } [Fact] @@ -347,6 +500,11 @@ public async Task GetPolicyContentAsync_WithMultipleValues_ReturnsExpected() new Constraints("multipleAdditionalValues", OperatorId.Equals, null), new Constraints("test", OperatorId.In, null) }); + A.CallTo(() => _policyRepository.GetAttributeValuesForTechnicalKeys(data.PolicyType, A>._)) + .Returns([ + ("multipleAdditionalValues", AttributeKeyId.Version, ["test"]), + ("test", AttributeKeyId.Version, []) + ]); A.CallTo(() => _policyRepository.GetPolicyForOperandContent(data.PolicyType, A>._)) .Returns(new[] { @@ -355,7 +513,7 @@ public async Task GetPolicyContentAsync_WithMultipleValues_ReturnsExpected() }.ToAsyncEnumerable()); // Act - var result = await _sut.GetPolicyContentAsync(data).ConfigureAwait(false); + var result = await _sut.GetPolicyContentAsync(data); // Assert result.Content.Id.Should().Be("...."); @@ -366,8 +524,8 @@ public async Task GetPolicyContentAsync_WithMultipleValues_ReturnsExpected() result.Content.Permission.Constraint.OrOperands.Should().BeNull(); result.Content.Permission.Constraint.AndOperands.Should().HaveCount(2) .And.Satisfy( - x => x.LeftOperand == "multipleAdditionalValues" && x.Operator == "eq" && x.RightOperandValue as string == "@multipleAdditionalValues-Static", - x => x.LeftOperand == "test" && x.Operator == "in" && (x.RightOperandValue as IEnumerable)!.Count() == 2); + x => x.LeftOperand == "cx-policy:multipleAdditionalValues" && x.Operator == "eq" && x.RightOperandValue as string == "@multipleAdditionalValues-Static", + x => x.LeftOperand == "cx-policy:test" && x.Operator == "in" && (x.RightOperandValue as IEnumerable)!.Count() == 2); result.AdditionalAttributes.Should().ContainSingle() .And.Satisfy(x => x.Key == "@multipleAdditionalValues-Static"); result.AdditionalAttributes!.Single().PossibleValues.Should().HaveCount(3) diff --git a/tests/hub/PolicyHub.Service.Tests/Controllers/PolicyHubControllerTests.cs b/tests/hub/PolicyHub.Service.Tests/Controllers/PolicyHubControllerTests.cs index 463d827..805abcd 100644 --- a/tests/hub/PolicyHub.Service.Tests/Controllers/PolicyHubControllerTests.cs +++ b/tests/hub/PolicyHub.Service.Tests/Controllers/PolicyHubControllerTests.cs @@ -21,7 +21,7 @@ using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; using Org.Eclipse.TractusX.PolicyHub.Service.Models; using Org.Eclipse.TractusX.PolicyHub.Service.Tests.Setup; -using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Service; +using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Web; using System.Net; using System.Net.Http.Json; using System.Text.Json; @@ -54,7 +54,7 @@ public PolicyHubControllerTests(IntegrationTestFactory factory) public async Task GetAttributes() { // Act - var attributes = await _client.GetFromJsonAsync>($"{BaseUrl}/policy-attributes").ConfigureAwait(false); + var attributes = await _client.GetFromJsonAsync>($"{BaseUrl}/policy-attributes"); // Assert attributes.Should().NotBeNull().And.HaveCount(5).And.Satisfy( @@ -74,22 +74,17 @@ public async Task GetAttributes() public async Task GetPolicyTypes_WithoutFilter_ReturnsExpected() { // Act - var policies = await _client.GetFromJsonAsync>($"{BaseUrl}/policy-types", JsonOptions).ConfigureAwait(false); + var policies = await _client.GetFromJsonAsync>($"{BaseUrl}/policy-types", JsonOptions); // Assert policies.Should().NotBeNull() - .And.HaveCount(11).And.Satisfy( + .And.HaveCount(6).And.Satisfy( x => x.TechnicalKey == "BusinessPartnerNumber", x => x.TechnicalKey == "Membership", - x => x.TechnicalKey == "FrameworkAgreement.traceability", - x => x.TechnicalKey == "FrameworkAgreement.quality", - x => x.TechnicalKey == "FrameworkAgreement.pcf", - x => x.TechnicalKey == "FrameworkAgreement.behavioraltwin", - x => x.TechnicalKey == "purpose.trace.v1.TraceBattery", - x => x.TechnicalKey == "purpose.trace.v1.aspects", - x => x.TechnicalKey == "companyRole.dismantler", - x => x.TechnicalKey == "purpose.trace.v1.qualityanalysis", - x => x.TechnicalKey == "purpose" + x => x.TechnicalKey == "FrameworkAgreement", + x => x.TechnicalKey == "Dismantler.allowedBrands", + x => x.TechnicalKey == "UsagePurpose", + x => x.TechnicalKey == "Dismantler" ); } @@ -97,14 +92,15 @@ public async Task GetPolicyTypes_WithoutFilter_ReturnsExpected() public async Task GetPolicyTypes_WithTypeFilter_ReturnsExpected() { // Act - var policies = await _client.GetFromJsonAsync>($"{BaseUrl}/policy-types?type={PolicyTypeId.Access.ToString()}", JsonOptions).ConfigureAwait(false); + var policies = await _client.GetFromJsonAsync>($"{BaseUrl}/policy-types?type={PolicyTypeId.Access}", JsonOptions); // Assert policies.Should().NotBeNull() - .And.HaveCount(3).And.Satisfy( + .And.HaveCount(4).And.Satisfy( x => x.TechnicalKey == "BusinessPartnerNumber", x => x.TechnicalKey == "Membership", - x => x.TechnicalKey == "companyRole.dismantler" + x => x.TechnicalKey == "Dismantler.allowedBrands", + x => x.TechnicalKey == "Dismantler" ); } @@ -112,19 +108,17 @@ public async Task GetPolicyTypes_WithTypeFilter_ReturnsExpected() public async Task GetPolicyTypes_WithUseCaseFilter_ReturnsExpected() { // Act - var policies = await _client.GetFromJsonAsync>($"{BaseUrl}/policy-types?useCase={UseCaseId.Traceability.ToString()}", JsonOptions).ConfigureAwait(false); + var policies = await _client.GetFromJsonAsync>($"{BaseUrl}/policy-types?useCase={UseCaseId.Traceability}", JsonOptions); // Assert policies.Should().NotBeNull() - .And.HaveCount(8).And.Satisfy( + .And.HaveCount(6).And.Satisfy( x => x.TechnicalKey == "BusinessPartnerNumber", x => x.TechnicalKey == "Membership", - x => x.TechnicalKey == "FrameworkAgreement.traceability", - x => x.TechnicalKey == "purpose.trace.v1.TraceBattery", - x => x.TechnicalKey == "purpose.trace.v1.aspects", - x => x.TechnicalKey == "companyRole.dismantler", - x => x.TechnicalKey == "purpose.trace.v1.qualityanalysis", - x => x.TechnicalKey == "purpose" + x => x.TechnicalKey == "FrameworkAgreement", + x => x.TechnicalKey == "Dismantler.allowedBrands", + x => x.TechnicalKey == "UsagePurpose", + x => x.TechnicalKey == "Dismantler" ); } @@ -136,12 +130,12 @@ public async Task GetPolicyTypes_WithUseCaseFilter_ReturnsExpected() public async Task GetPolicyContent_WithRegexWithIncorrectValue_ReturnsExpected() { // Act - var response = await _client.GetAsync($"{BaseUrl}/policy-content?type={PolicyTypeId.Access}&credential=BusinessPartnerNumber&operatorId={OperatorId.Equals}&value=notmatching").ConfigureAwait(false); + var response = await _client.GetAsync($"{BaseUrl}/policy-content?type={PolicyTypeId.Access}&policyName=BusinessPartnerNumber&operatorType={OperatorId.Equals}&value=notmatching"); // Assert response.Should().NotBeNull(); response.StatusCode.Should().Be(HttpStatusCode.BadRequest); - var error = await response.Content.ReadFromJsonAsync(JsonOptions).ConfigureAwait(false); + var error = await response.Content.ReadFromJsonAsync(JsonOptions); error!.Errors.Should().ContainSingle().And.Satisfy( x => x.Value.Single() == @"The provided value notmatching does not match the regex pattern ^BPNL[\w|\d]{12}$ (Parameter 'value')"); } @@ -150,12 +144,12 @@ public async Task GetPolicyContent_WithRegexWithIncorrectValue_ReturnsExpected() public async Task GetPolicyContent_WithRegexWithoutValue_ReturnsExpected() { // Act - var response = await _client.GetAsync($"{BaseUrl}/policy-content?type={PolicyTypeId.Access}&credential=BusinessPartnerNumber&operatorId={OperatorId.Equals}").ConfigureAwait(false); + var response = await _client.GetAsync($"{BaseUrl}/policy-content?type={PolicyTypeId.Access}&policyName=BusinessPartnerNumber&operatorType={OperatorId.Equals}"); // Assert response.Should().NotBeNull(); response.StatusCode.Should().Be(HttpStatusCode.BadRequest); - var error = await response.Content.ReadFromJsonAsync(JsonOptions).ConfigureAwait(false); + var error = await response.Content.ReadFromJsonAsync(JsonOptions); error!.Errors.Should().ContainSingle().And.Satisfy( x => x.Value.Single() == "you must provide a value for the regex (Parameter 'value')"); } @@ -164,56 +158,56 @@ public async Task GetPolicyContent_WithRegexWithoutValue_ReturnsExpected() public async Task GetPolicyContent_BpnWithValue_ReturnsExpected() { // Act - var response = await _client.GetAsync($"{BaseUrl}/policy-content?type={PolicyTypeId.Usage}&credential=BusinessPartnerNumber&operatorId={OperatorId.Equals}&value=BPNL00000003CRHK").ConfigureAwait(false); + var response = await _client.GetAsync($"{BaseUrl}/policy-content?type={PolicyTypeId.Usage}&policyName=BusinessPartnerNumber&operatorType={OperatorId.Equals}&value=BPNL00000003CRHK"); // Assert response.Should().NotBeNull(); response.StatusCode.Should().Be(HttpStatusCode.OK); - (await response.Content.ReadAsStringAsync().ConfigureAwait(false)) + (await response.Content.ReadAsStringAsync()) .Should() - .Be("{\"content\":{\"@context\":[\"https://www.w3.org/ns/odrl.jsonld\",{\"cx\":\"https://w3id.org/catenax/v0.0.1/ns/\"}],\"@type\":\"Offer\",\"@id\":\"....\",\"permission\":{\"action\":\"use\",\"constraint\":{\"leftOperand\":\"BusinessPartnerNumber\",\"operator\":\"eq\",\"rightOperand\":\"BPNL00000003CRHK\"}}}}"); + .Be("{\"content\":{\"@context\":[\"https://www.w3.org/ns/odrl.jsonld\",{\"cx\":\"https://w3id.org/catenax/v0.0.1/ns/\"}],\"@type\":\"Offer\",\"@id\":\"....\",\"permission\":{\"action\":\"use\",\"constraint\":{\"leftOperand\":\"cx-policy:BusinessPartnerNumber\",\"operator\":\"eq\",\"rightOperand\":\"BPNL00000003CRHK\"}}}}"); } [Fact] public async Task GetPolicyContent_UsageFrameworkEquals_ReturnsExpected() { // Act - var response = await _client.GetAsync($"{BaseUrl}/policy-content?type={PolicyTypeId.Usage}&credential=FrameworkAgreement.traceability&operatorId={OperatorId.Equals}").ConfigureAwait(false); + var response = await _client.GetAsync($"{BaseUrl}/policy-content?useCase=Traceability&type={PolicyTypeId.Usage}&policyName=FrameworkAgreement&operatorType={OperatorId.Equals}"); // Assert response.Should().NotBeNull(); response.StatusCode.Should().Be(HttpStatusCode.OK); - (await response.Content.ReadAsStringAsync().ConfigureAwait(false)) + (await response.Content.ReadAsStringAsync()) .Should() - .Be("{\"content\":{\"@context\":[\"https://www.w3.org/ns/odrl.jsonld\",{\"cx\":\"https://w3id.org/catenax/v0.0.1/ns/\"}],\"@type\":\"Offer\",\"@id\":\"....\",\"permission\":{\"action\":\"use\",\"constraint\":{\"leftOperand\":\"FrameworkAgreement.traceability\",\"operator\":\"eq\",\"rightOperand\":\"@FrameworkAgreement.traceability-Version\"}}},\"attributes\":[{\"key\":\"@FrameworkAgreement.traceability-Version\",\"possibleValues\":[\"active:1.0\",\"active:1.1\",\"active:1.2\"]}]}"); + .Be("{\"content\":{\"@context\":[\"https://www.w3.org/ns/odrl.jsonld\",{\"cx\":\"https://w3id.org/catenax/v0.0.1/ns/\"}],\"@type\":\"Offer\",\"@id\":\"....\",\"permission\":{\"action\":\"use\",\"constraint\":{\"leftOperand\":\"cx-policy:FrameworkAgreement\",\"operator\":\"eq\",\"rightOperand\":\"@FrameworkAgreement.Traceability-Version\"}}},\"attributes\":[{\"key\":\"@FrameworkAgreement.Traceability-Version\",\"possibleValues\":[\"Traceability:1.0\",\"Traceability:1.1\",\"Traceability:1.2\"]}]}"); } [Fact] public async Task GetPolicyContent_UsageDismantlerIn_ReturnsExpected() { // Act - var response = await _client.GetAsync($"{BaseUrl}/policy-content?type={PolicyTypeId.Usage}&credential=companyRole.dismantler&operatorId={OperatorId.In}").ConfigureAwait(false); + var response = await _client.GetAsync($"{BaseUrl}/policy-content?type={PolicyTypeId.Usage}&policyName=Dismantler.allowedBrands&operatorType={OperatorId.In}"); // Assert response.Should().NotBeNull(); response.StatusCode.Should().Be(HttpStatusCode.OK); - (await response.Content.ReadAsStringAsync().ConfigureAwait(false)) + (await response.Content.ReadAsStringAsync()) .Should() - .Be("{\"content\":{\"@context\":[\"https://www.w3.org/ns/odrl.jsonld\",{\"cx\":\"https://w3id.org/catenax/v0.0.1/ns/\"}],\"@type\":\"Offer\",\"@id\":\"....\",\"permission\":{\"action\":\"use\",\"constraint\":{\"leftOperand\":\"Dismantler.activityType\",\"operator\":\"in\",\"rightOperand\":[\"Audi\",\"BMW\",\"VW\"]}}}}"); + .Be("{\"content\":{\"@context\":[\"https://www.w3.org/ns/odrl.jsonld\",{\"cx\":\"https://w3id.org/catenax/v0.0.1/ns/\"}],\"@type\":\"Offer\",\"@id\":\"....\",\"permission\":{\"action\":\"use\",\"constraint\":{\"leftOperand\":\"cx-policy:Dismantler.allowedBrands\",\"operator\":\"in\",\"rightOperand\":[\"BMW\",\"Audi\",\"VW\"]}}}}"); } [Fact] public async Task GetPolicyContent_TraceabilityUsagePurposeEquals_ReturnsExpected() { // Act - var response = await _client.GetAsync($"{BaseUrl}/policy-content?useCase={UseCaseId.Traceability}&type={PolicyTypeId.Usage}&credential=purpose.trace.v1.TraceBattery&operatorId={OperatorId.Equals}").ConfigureAwait(false); + var response = await _client.GetAsync($"{BaseUrl}/policy-content?useCase={UseCaseId.Traceability}&type={PolicyTypeId.Usage}&policyName=Membership&operatorType={OperatorId.Equals}"); // Assert response.Should().NotBeNull(); response.StatusCode.Should().Be(HttpStatusCode.OK); - (await response.Content.ReadAsStringAsync().ConfigureAwait(false)) + (await response.Content.ReadAsStringAsync()) .Should() - .Be("{\"content\":{\"@context\":[\"https://www.w3.org/ns/odrl.jsonld\",{\"cx\":\"https://w3id.org/catenax/v0.0.1/ns/\"}],\"@type\":\"Offer\",\"@id\":\"....\",\"permission\":{\"action\":\"use\",\"constraint\":{\"leftOperand\":\"purpose.trace.v1.TraceBattery\",\"operator\":\"eq\",\"rightOperand\":\"purpose.trace.v1.TraceBattery\"}}}}"); + .Be("{\"content\":{\"@context\":[\"https://www.w3.org/ns/odrl.jsonld\",{\"cx\":\"https://w3id.org/catenax/v0.0.1/ns/\"}],\"@type\":\"Offer\",\"@id\":\"....\",\"permission\":{\"action\":\"use\",\"constraint\":{\"leftOperand\":\"cx-policy:Membership\",\"operator\":\"eq\",\"rightOperand\":\"active\"}}}}"); } #endregion @@ -229,23 +223,23 @@ public async Task GetPolicyContentWithFiltersAsync_TwoEqualsConstraintsAndOperan ConstraintOperandId.And, new[] { - new Constraints("FrameworkAgreement.traceability", OperatorId.Equals, null), - new Constraints("companyRole.dismantler", OperatorId.In, null) + new Constraints("FrameworkAgreement", OperatorId.Equals, "Traceability:1.0"), + new Constraints("Dismantler.allowedBrands", OperatorId.In, "Audi") }); // Act - var response = await _client.PostAsJsonAsync($"{BaseUrl}/policy-content", data, JsonOptions).ConfigureAwait(false); + var response = await _client.PostAsJsonAsync($"{BaseUrl}/policy-content", data, JsonOptions); // Assert response.Should().NotBeNull(); response.StatusCode.Should().Be(HttpStatusCode.OK); - (await response.Content.ReadAsStringAsync().ConfigureAwait(false)) + (await response.Content.ReadAsStringAsync()) .Should() - .Be("{\"content\":{\"@context\":[\"https://www.w3.org/ns/odrl.jsonld\",{\"cx\":\"https://w3id.org/catenax/v0.0.1/ns/\"}],\"@type\":\"Offer\",\"@id\":\"....\",\"permission\":{\"action\":\"use\",\"constraint\":{\"odrl:and\":[{\"leftOperand\":\"FrameworkAgreement.traceability\",\"operator\":\"eq\",\"rightOperand\":\"@FrameworkAgreement.traceability-Version\"},{\"leftOperand\":\"Dismantler.activityType\",\"operator\":\"in\",\"rightOperand\":[\"Audi\",\"BMW\",\"VW\"]}]}}},\"attributes\":[{\"key\":\"@FrameworkAgreement.traceability-Version\",\"possibleValues\":[\"active:1.0\",\"active:1.1\",\"active:1.2\"]}]}"); + .Be("{\"content\":{\"@context\":[\"https://www.w3.org/ns/odrl.jsonld\",{\"cx\":\"https://w3id.org/catenax/v0.0.1/ns/\"}],\"@type\":\"Offer\",\"@id\":\"....\",\"permission\":{\"action\":\"use\",\"constraint\":{\"odrl:and\":[{\"leftOperand\":\"cx-policy:Dismantler.allowedBrands\",\"operator\":\"in\",\"rightOperand\":[\"BMW\",\"Audi\",\"VW\"]},{\"leftOperand\":\"cx-policy:FrameworkAgreement\",\"operator\":\"eq\",\"rightOperand\":\"@FrameworkAgreement-Version\"}]}}},\"attributes\":[{\"key\":\"@FrameworkAgreement-Version\",\"possibleValues\":[\"Traceability:1.0\",\"Traceability:1.1\",\"Traceability:1.2\",\"Quality:1.0\",\"PCF:1.0\",\"Behavioraltwin:1.0\",\"Circulareconomy:1.0\",\"Demandcapacity:1.0\",\"Puris:1.0\",\"Businesspartner:1.0\"]}]}"); } [Fact] - public async Task GetPolicyContentWithFiltersAsync_MultipleConstraintsEqualsAndOperand_ReturnsExpected() + public async Task GetPolicyContentWithFiltersAsync_WithWrongValue_ReturnsBadRequest() { // Arrange var data = new PolicyContentRequest( @@ -253,68 +247,41 @@ public async Task GetPolicyContentWithFiltersAsync_MultipleConstraintsEqualsAndO ConstraintOperandId.And, new[] { - new Constraints("FrameworkAgreement.traceability", OperatorId.Equals, null), - new Constraints("companyRole.dismantler", OperatorId.In, null), - new Constraints("BusinessPartnerNumber", OperatorId.Equals, "BPNL00000003CRHK") + new Constraints("FrameworkAgreement.traceability", OperatorId.Equals, "1.0"), + new Constraints("purpose", OperatorId.In, "By accepting this policy you have to pay 1K BC") }); // Act - var response = await _client.PostAsJsonAsync($"{BaseUrl}/policy-content", data, JsonOptions).ConfigureAwait(false); + var response = await _client.PostAsJsonAsync($"{BaseUrl}/policy-content", data, JsonOptions); // Assert response.Should().NotBeNull(); - response.StatusCode.Should().Be(HttpStatusCode.OK); - (await response.Content.ReadAsStringAsync().ConfigureAwait(false)) - .Should() - .Be("{\"content\":{\"@context\":[\"https://www.w3.org/ns/odrl.jsonld\",{\"cx\":\"https://w3id.org/catenax/v0.0.1/ns/\"}],\"@type\":\"Offer\",\"@id\":\"....\",\"permission\":{\"action\":\"use\",\"constraint\":{\"odrl:and\":[{\"leftOperand\":\"BusinessPartnerNumber\",\"operator\":\"eq\",\"rightOperand\":\"BPNL00000003CRHK\"},{\"leftOperand\":\"FrameworkAgreement.traceability\",\"operator\":\"eq\",\"rightOperand\":\"@FrameworkAgreement.traceability-Version\"},{\"leftOperand\":\"Dismantler.activityType\",\"operator\":\"in\",\"rightOperand\":[\"Audi\",\"BMW\",\"VW\"]}]}}},\"attributes\":[{\"key\":\"@FrameworkAgreement.traceability-Version\",\"possibleValues\":[\"active:1.0\",\"active:1.1\",\"active:1.2\"]}]}"); + response.StatusCode.Should().Be(HttpStatusCode.BadRequest); } [Fact] - public async Task GetPolicyContentWithFiltersAsync_MultipleConstraintsEqualsOrOperand_ReturnsExpected() + public async Task GetPolicyContentWithFiltersAsync_MultipleConstraintsEqualsAndOperand_ReturnsExpected() { // Arrange var data = new PolicyContentRequest( PolicyTypeId.Usage, - ConstraintOperandId.Or, + ConstraintOperandId.And, new[] { - new Constraints("FrameworkAgreement.traceability", OperatorId.Equals, null), - new Constraints("companyRole.dismantler", OperatorId.In, null), + new Constraints("FrameworkAgreement", OperatorId.Equals, "Traceability:1.0"), + new Constraints("Dismantler.allowedBrands", OperatorId.In, "Audi"), + new Constraints("BusinessPartnerNumber", OperatorId.Equals, "BPNL00000003CRHK") }); // Act - var response = await _client.PostAsJsonAsync($"{BaseUrl}/policy-content", data, JsonOptions).ConfigureAwait(false); + var response = await _client.PostAsJsonAsync($"{BaseUrl}/policy-content", data, JsonOptions); // Assert response.Should().NotBeNull(); response.StatusCode.Should().Be(HttpStatusCode.OK); - (await response.Content.ReadAsStringAsync().ConfigureAwait(false)) + (await response.Content.ReadAsStringAsync()) .Should() - .Be("{\"content\":{\"@context\":[\"https://www.w3.org/ns/odrl.jsonld\",{\"cx\":\"https://w3id.org/catenax/v0.0.1/ns/\"}],\"@type\":\"Offer\",\"@id\":\"....\",\"permission\":{\"action\":\"use\",\"constraint\":{\"odrl:or\":[{\"leftOperand\":\"FrameworkAgreement.traceability\",\"operator\":\"eq\",\"rightOperand\":\"@FrameworkAgreement.traceability-Version\"},{\"leftOperand\":\"Dismantler.activityType\",\"operator\":\"in\",\"rightOperand\":[\"Audi\",\"BMW\",\"VW\"]}]}}},\"attributes\":[{\"key\":\"@FrameworkAgreement.traceability-Version\",\"possibleValues\":[\"active:1.0\",\"active:1.1\",\"active:1.2\"]}]}"); - } - - [Fact] - public async Task GetPolicyContentWithFiltersAsync_WithSameConstraintKeys_ReturnsError() - { - // Arrange - var data = new PolicyContentRequest( - PolicyTypeId.Usage, - ConstraintOperandId.Or, - new[] - { - new Constraints("FrameworkAgreement.traceability", OperatorId.Equals, null), - new Constraints("FrameworkAgreement.traceability", OperatorId.Equals, null), - }); - - // Act - var response = await _client.PostAsJsonAsync($"{BaseUrl}/policy-content", data, JsonOptions).ConfigureAwait(false); - - // Assert - response.Should().NotBeNull(); - response.StatusCode.Should().Be(HttpStatusCode.BadRequest); - var error = await response.Content.ReadFromJsonAsync(JsonOptions).ConfigureAwait(false); - error!.Errors.Should().ContainSingle().And.Satisfy( - x => x.Value.Single() == "Keys FrameworkAgreement.traceability have been defined multiple times"); + .Be("{\"content\":{\"@context\":[\"https://www.w3.org/ns/odrl.jsonld\",{\"cx\":\"https://w3id.org/catenax/v0.0.1/ns/\"}],\"@type\":\"Offer\",\"@id\":\"....\",\"permission\":{\"action\":\"use\",\"constraint\":{\"odrl:and\":[{\"leftOperand\":\"cx-policy:BusinessPartnerNumber\",\"operator\":\"eq\",\"rightOperand\":\"BPNL00000003CRHK\"},{\"leftOperand\":\"cx-policy:Dismantler.allowedBrands\",\"operator\":\"in\",\"rightOperand\":[\"BMW\",\"Audi\",\"VW\"]},{\"leftOperand\":\"cx-policy:FrameworkAgreement\",\"operator\":\"eq\",\"rightOperand\":\"@FrameworkAgreement-Version\"}]}}},\"attributes\":[{\"key\":\"@FrameworkAgreement-Version\",\"possibleValues\":[\"Traceability:1.0\",\"Traceability:1.1\",\"Traceability:1.2\",\"Quality:1.0\",\"PCF:1.0\",\"Behavioraltwin:1.0\",\"Circulareconomy:1.0\",\"Demandcapacity:1.0\",\"Puris:1.0\",\"Businesspartner:1.0\"]}]}"); } #endregion @@ -325,7 +292,7 @@ public async Task GetPolicyContentWithFiltersAsync_WithSameConstraintKeys_Return public async Task CheckSwagger_ReturnsExpected() { // Act - var response = await _client.GetAsync($"{BaseUrl}/swagger/v2/swagger.json").ConfigureAwait(false); + var response = await _client.GetAsync($"{BaseUrl}/swagger/v2/swagger.json"); // Assert response.Should().NotBeNull(); diff --git a/tests/hub/PolicyHub.Service.Tests/PolicyHub.Service.Tests.csproj b/tests/hub/PolicyHub.Service.Tests/PolicyHub.Service.Tests.csproj index da72574..8ec3ec9 100644 --- a/tests/hub/PolicyHub.Service.Tests/PolicyHub.Service.Tests.csproj +++ b/tests/hub/PolicyHub.Service.Tests/PolicyHub.Service.Tests.csproj @@ -21,7 +21,7 @@ Org.Eclipse.TractusX.PolicyHub.Service.Tests Org.Eclipse.TractusX.PolicyHub.Service.Tests - net7.0 + net8.0 enable enable false @@ -35,18 +35,18 @@ - - - - - - - - + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all