diff --git a/.editorconfig b/.editorconfig index b651108..5945d4a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -148,7 +148,7 @@ dotnet_diagnostic.RS2008.severity = none # IDE0073: File header dotnet_diagnostic.IDE0073.severity = warning -#file_header_template = /********************************************************************************\n * Copyright (c) 2021,2022 BMW Group AG\n * Copyright (c) 2021,2022 Contributors to the CatenaX (ng) GitHub Organisation.\n *\n * \nSee the NOTICE file(s) distributed with this work for additional\n * information regarding copyright ownership.\n *\n * This program and the accompanying materials are made available under the\n * terms of the \nApache License, Version 2.0 which is available at\n * https://www.apache.org/licenses/LICENSE-2.0.\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License \nis distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the \nLicense. *\n * SPDX-License-Identifier: Apache-2.0\n ********************************************************************************/\n +#file_header_template = /********************************************************************************\n * Copyright (c) 2021,2022 Contributors to the CatenaX (ng) GitHub Organisation.\n *\n * \nSee the NOTICE file(s) distributed with this work for additional\n * information regarding copyright ownership.\n *\n * This program and the accompanying materials are made available under the\n * terms of the \nApache License, Version 2.0 which is available at\n * https://www.apache.org/licenses/LICENSE-2.0.\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License \nis distributed on an "AS IS" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations\n * under the \nLicense. *\n * SPDX-License-Identifier: Apache-2.0\n ********************************************************************************/\n # IDE0035: Remove unreachable code dotnet_diagnostic.IDE0035.severity = warning diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index ed72626..4c562a4 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -22,3 +22,4 @@ Please delete options that are not relevant. - [ ] I have added tests that prove my changes work - [ ] I have checked that new and existing tests pass locally with my changes - [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] I have added copyright and license headers, footers (for .md files) or files (for images) \ No newline at end of file diff --git a/.github/workflows/chart-release.yaml b/.github/workflows/chart-release.yaml new file mode 100644 index 0000000..35bca98 --- /dev/null +++ b/.github/workflows/chart-release.yaml @@ -0,0 +1,63 @@ +############################################################### +# 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" diff --git a/.github/workflows/dependencies.yaml b/.github/workflows/dependencies.yml similarity index 100% rename from .github/workflows/dependencies.yaml rename to .github/workflows/dependencies.yml diff --git a/.github/workflows/kics.yml b/.github/workflows/kics.yml index 440cd01..e02e801 100644 --- a/.github/workflows/kics.yml +++ b/.github/workflows/kics.yml @@ -20,16 +20,16 @@ name: "KICS" on: - # push: - # branches: [main, dev] + push: + branches: [main, dev] # pull_request: # The branches below must be a subset of the branches above # branches: [main, dev] # paths-ignore: # - "**/*.md" # - "**/*.txt" - # schedule: - # - cron: "0 0 * * *" + schedule: + - cron: "0 0 * * *" workflow_dispatch: jobs: diff --git a/.github/workflows/lint-pull-request.yml b/.github/workflows/lint-pull-request.yml new file mode 100644 index 0000000..705ef8d --- /dev/null +++ b/.github/workflows/lint-pull-request.yml @@ -0,0 +1,61 @@ +# ############################################################################# +# Copyright (c) 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################# + +name: "Lint PullRequest" + +on: + pull_request_target: + types: + - opened + - edited + - synchronize + +jobs: + main: + name: Validate PR title + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@v5 + id: lint_pr_title + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - uses: marocchino/sticky-pull-request-comment@v2 + # 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) + with: + header: pr-title-lint-error + message: | + Hey there and thank you for opening this pull request! 👋🏼 + + We require pull request titles to follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/) and it looks like your proposed title needs to be adjusted. + + Details: + + ``` + ${{ steps.lint_pr_title.outputs.error_message }} + ``` + + # 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 + with: + header: pr-title-lint-error + delete: true \ No newline at end of file diff --git a/.github/workflows/policy-hub-chart-test.yml b/.github/workflows/policy-hub-chart-test.yml new file mode 100644 index 0000000..dcaa3fd --- /dev/null +++ b/.github/workflows/policy-hub-chart-test.yml @@ -0,0 +1,119 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +name: PolicyHub Lint and Test Chart + +on: + push: + paths: + - 'charts/policy-hub/**' + branches: [main, dev, release-candidate] + pull_request: + paths: + - 'charts/policy-hub/**' + workflow_dispatch: + inputs: + node_image: + description: 'kindest/node image for k8s kind cluster' + # k8s version from 3.1 release as default + default: 'kindest/node:v1.27.3' + required: false + type: string + upgrade_from: + description: 'policyhub chart version to upgrade from' + # tbd + default: '0.1.0-rc.1' + required: false + type: string + +jobs: + + lint-test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Kubernetes KinD Cluster + uses: container-tools/kind-action@v1 + 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 + # default value for event_name != workflow_dispatch + node_image: ${{ github.event.inputs.node_image || 'kindest/node:v1.27.3' }} + + - name: Build migration image + id: build-migration-image + uses: docker/build-push-action@v3 + with: + context: . + 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 + with: + context: . + 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 + with: + version: v3.9.3 + + - uses: actions/setup-python@v4 + with: + python-version: '3.9' + check-latest: true + + - name: Set up chart-testing + uses: helm/chart-testing-action@v2.3.1 + + - name: Run chart-testing (list-changed) + id: list-changed + run: | + changed=$(ct list-changed --target-branch ${{ github.event.repository.default_branch }}) + if [[ -n "$changed" ]]; then + echo "changed=true" >> $GITHUB_OUTPUT + fi + + - name: Run chart-testing (lint) + run: ct lint --validate-maintainers=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" + if: github.event_name != 'pull_request' || steps.list-changed.outputs.changed == 'true' + + # currently the update is commented out, at the moment we're working for the initial version, after that the update will be enabled + # Upgrade the released chart version with the locally available chart + # default value for event_name != workflow_dispatch + # - name: Run helm upgrade + # 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-service tractusx-dev/policy-hub-service --version ${{ github.event.inputs.upgrade_from || '1.0.0' }} + # helm dependency update charts/policy-hub-service + # helm upgrade policy-hub-service charts/policy-hub-service + # if: github.event_name != 'pull_request' || steps.list-changed.outputs.changed == 'true' \ No newline at end of file diff --git a/.github/workflows/policy-hub-migrations.yml b/.github/workflows/policy-hub-migrations.yml index 3be9347..e7fc618 100644 --- a/.github/workflows/policy-hub-migrations.yml +++ b/.github/workflows/policy-hub-migrations.yml @@ -17,21 +17,21 @@ # SPDX-License-Identifier: Apache-2.0 ############################################################### -name: Portal-Migrations +name: PolicyHub-Migrations on: - # push: - # paths: - # # service and transitive paths - # - 'src/database/PolicyHub.Migrations/**' - # - 'src/database/PolicyHub.PortalEntities/**' - # # workflow file - # - '.github/workflows/policy-hub-migrations.yml' - # # dockerfile - # - 'docker/Dockerfile-policy-hub-migrations' + push: + paths: + # service and transitive paths + - 'src/database/PolicyHub.Migrations/**' + - 'src/database/PolicyHub.Entities/**' + # workflow file + - '.github/workflows/policy-hub-migrations.yml' + # dockerfile + - 'docker/Dockerfile-policy-hub-migrations' - # branches: - # - 'dev' + branches: + - 'dev' workflow_dispatch: env: @@ -90,5 +90,3 @@ jobs: password: ${{ secrets.DOCKER_HUB_TOKEN }} repository: ${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME }} readme-filepath: "./docker/notice-policy-hub-migrations.md" - - # build chart \ No newline at end of file diff --git a/.github/workflows/policy-hub-service.yml b/.github/workflows/policy-hub-service.yml index dbb3047..e2bf484 100644 --- a/.github/workflows/policy-hub-service.yml +++ b/.github/workflows/policy-hub-service.yml @@ -17,20 +17,20 @@ # SPDX-License-Identifier: Apache-2.0 ############################################################### -name: Administration-Service +name: PolicyHub-Service on: - # push: - # paths: - # # service and transitive paths - # - 'src/**' - # # workflow file - # - '.github/workflows/policy_hub-service.yml' - # # dockerfile - # - 'docker/Dockerfile-policy-hub-service' + push: + paths: + # service and transitive paths + - 'src/**' + # workflow file + - '.github/workflows/policy-hub-service.yml' + # dockerfile + - 'docker/Dockerfile-policy-hub-service' - # branches: - # - 'dev' + branches: + - 'dev' workflow_dispatch: env: @@ -89,5 +89,3 @@ jobs: password: ${{ secrets.DOCKER_HUB_TOKEN }} repository: ${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME }} readme-filepath: "./docker/notice-policy-hub-service.md" - - # build chart \ No newline at end of file diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml new file mode 100644 index 0000000..1d3d67c --- /dev/null +++ b/.github/workflows/release-please.yml @@ -0,0 +1,40 @@ +############################################################### +# 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 Please + +on: + push: + branches: + - 'v*.*.*' + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +jobs: + prepare-release: + runs-on: ubuntu-latest + steps: + - uses: google-github-actions/release-please-action@v4 + name: Prepare release + with: + target-branch: ${{ github.ref_name }} + release-type: simple diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..78ead14 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,152 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +name: Release + +on: + push: + tags: + - 'v*.*.*' + workflow_dispatch: + +env: + IMAGE_NAMESPACE: "tractusx" + IMAGE_NAME_SERVICE: "policy-hub-service" + IMAGE_NAME_MIGRATIONS: "policy-hub-migrations" + +jobs: + policy-hub-service-release: + runs-on: ubuntu-latest + permissions: + packages: write + + 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 + with: + images: | + ${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME_SERVICE }} + # 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-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 + + - 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 + 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 }} + + # 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" diff --git a/.github/workflows/release_candidate.yml b/.github/workflows/release_candidate.yml new file mode 100644 index 0000000..e8ed839 --- /dev/null +++ b/.github/workflows/release_candidate.yml @@ -0,0 +1,136 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +name: Release Candidate (RC) + +on: + push: + branches: + - '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: + runs-on: ubuntu-latest + permissions: + contents: read + + 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 + 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 + + - 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_MIGRATIONS }} + tags: | + type=raw,value=rc + type=raw,value=${{ github.sha }} + + - 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 }} + + # 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" diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml new file mode 100644 index 0000000..fd09881 --- /dev/null +++ b/.github/workflows/sonarcloud.yml @@ -0,0 +1,75 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +name: Sonarcloud +on: + push: + branches: [main, dev] + pull_request: + types: [opened, synchronize, reopened] + workflow_dispatch: + +jobs: + build: + name: Build + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository + runs-on: ubuntu-latest + strategy: + matrix: + dotnet-version: ['7.0'] + + steps: + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '17' + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + - name: Cache SonarCloud packages + uses: actions/cache@v3 + 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 + with: + path: ./.sonar/scanner + key: ${{ runner.os }}-sonar-scanner + restore-keys: ${{ runner.os }}-sonar-scanner + - name: Install SonarCloud scanner + if: steps.cache-sonar-scanner.outputs.cache-hit != 'true' + run: | + mkdir -p ./.sonar/scanner + dotnet tool update dotnet-sonarscanner --tool-path ./.sonar/scanner + - name: Build and analyze + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: | + dotnet tool install --global dotnet-coverage + ./.sonar/scanner/dotnet-sonarscanner begin /k:"${{ vars.SONAR_PROJECT_KEY }}" /o:"${{ vars.SONAR_ORGANIZATION }}" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.vscoveragexml.reportsPaths=src/coverage.xml + dotnet build src + cd src + dotnet-coverage collect 'dotnet test --no-restore --verbosity normal' -s 'settings-coverage.xml' -f xml -o 'coverage.xml' + cd .. + ./.sonar/scanner/dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}" diff --git a/.github/workflows/test-automation.yml b/.github/workflows/test-automation.yml new file mode 100644 index 0000000..46d1ac9 --- /dev/null +++ b/.github/workflows/test-automation.yml @@ -0,0 +1,75 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +name: TestAutomation E2E-Tests + +on: + workflow_dispatch: + +jobs: + build: + + runs-on: ubuntu-latest + environment: ${{ github.event.inputs.environment }} + strategy: + matrix: + dotnet-version: [ '7.0' ] + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup JQ + run: + sudo apt-get install jq + + - name: Update JSON file + env: + project: ${{ secrets.REPORTPORTAL_PROJECT }} + apiKey: ${{ secrets.REPORTPORTAL_AUTHENTICATION_UUID }} + url: ${{ vars.REPORTPORTAL_URL }} + run: | + cd tests/endToEnd + jq --arg project "$project" \ + --arg apiKey "$apiKey" \ + --arg url "$url" \ + '.server |= ( .project = $project | .apiKey = $apiKey | .url = $url )' \ + ReportPortal.config.json > temp.json + mv temp.json ReportPortal.config.json + - name: Setup .NET Core SDK ${{ matrix.dotnet-version }} + uses: actions/setup-dotnet@v2 + with: + dotnet-version: ${{ matrix.dotnet-version }} + - name: Install dependencies + run: dotnet restore src + - name: Build + run: dotnet build src --configuration Release --no-restore + - name: Tests - PolicyHub E2E Tests + env: + ENVIRONMENT: ${{ github.event.inputs.environment }} + AUTH_CLIENT_ID: ${{ secrets.AUTH_CLIENT_ID }} + AUTH_CLIENT_SECRET: ${{ secrets.AUTH_CLIENT_SECRET }} + AUTH_URL: ${{ secrets.AUTH_URL }} + run: dotnet test tests/endToEnd --no-restore --verbosity minimal --logger "html;logfilename=e2ePolicyHub.html" + - name: 'Upload Artifact' + if: always() + uses: actions/upload-artifact@v3 + 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 2b8654b..e6be35d 100644 --- a/.github/workflows/trivy-dev.yml +++ b/.github/workflows/trivy-dev.yml @@ -23,8 +23,8 @@ name: "Trivy Dev" on: - # push: - # branches: [ dev ] + push: + branches: [ dev ] # pull_request: # The branches below must be a subset of the branches above # branches: [ main, master ] @@ -54,15 +54,13 @@ jobs: uses: actions/checkout@v3 - name: Run Trivy vulnerability scanner in repo mode - uses: aquasecurity/trivy-action@master + uses: aquasecurity/trivy-action@0.14.0 with: scan-type: "config" - # ignore-unfixed: true - exit-code: "1" hide-progress: false format: "sarif" output: "trivy-results1.sarif" - severity: "CRITICAL,HIGH" + vuln-type: "os,library" timeout: "3600s" - name: Upload Trivy scan results to GitHub Security tab @@ -89,14 +87,13 @@ jobs: # For public images, no ENV vars must be set. - name: Run Trivy vulnerability scanner if: always() - uses: aquasecurity/trivy-action@master + uses: aquasecurity/trivy-action@0.14.0 with: # Path to Docker image image-ref: "${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME }}-service:dev" format: "sarif" output: "trivy-results3.sarif" - exit-code: "1" - severity: "CRITICAL,HIGH" + vuln-type: "os,library" - name: Upload Trivy scan results to GitHub Security tab if: always() @@ -122,14 +119,14 @@ jobs: # For public images, no ENV vars must be set. - name: Run Trivy vulnerability scanner if: always() - uses: aquasecurity/trivy-action@master + uses: aquasecurity/trivy-action@0.14.0 with: # Path to Docker image image-ref: "${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME }}-migrations:dev" format: "sarif" output: "trivy-results9.sarif" - exit-code: "1" - severity: "CRITICAL,HIGH" + vuln-type: "os,library" + skip-dirs: "docs/" - name: Upload Trivy scan results to GitHub Security tab if: always() diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index 18fc88c..0219a5f 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -23,17 +23,17 @@ name: "Trivy Stable" on: - # push: - # branches: [ main ] + push: + branches: [ main ] # pull_request: # The branches below must be a subset of the branches above # branches: [ main, master ] # paths-ignore: # - "**/*.md" # - "**/*.txt" - # schedule: + schedule: # Once a day - # - cron: "0 0 * * *" + - cron: "0 0 * * *" workflow_dispatch: # Trigger manually @@ -54,15 +54,14 @@ jobs: uses: actions/checkout@v3 - name: Run Trivy vulnerability scanner in repo mode - uses: aquasecurity/trivy-action@master + uses: aquasecurity/trivy-action@0.14.0 with: scan-type: "config" - # ignore-unfixed: true - exit-code: "1" hide-progress: false format: "sarif" output: "trivy-results1.sarif" - severity: "CRITICAL,HIGH" + vuln-type: "os,library" + skip-dirs: "docs/" timeout: "3600s" - name: Upload Trivy scan results to GitHub Security tab @@ -89,14 +88,13 @@ jobs: # For public images, no ENV vars must be set. - name: Run Trivy vulnerability scanner if: always() - uses: aquasecurity/trivy-action@master + uses: aquasecurity/trivy-action@0.14.0 with: # Path to Docker image image-ref: "${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME }}-service:latest" format: "sarif" output: "trivy-results3.sarif" - exit-code: "1" - severity: "CRITICAL,HIGH" + vuln-type: "os,library" - name: Upload Trivy scan results to GitHub Security tab if: always() @@ -122,17 +120,16 @@ jobs: # For public images, no ENV vars must be set. - name: Run Trivy vulnerability scanner if: always() - uses: aquasecurity/trivy-action@master + uses: aquasecurity/trivy-action@0.14.0 with: # Path to Docker image image-ref: "${{ env.IMAGE_NAMESPACE }}/${{ env.IMAGE_NAME }}-migrations:latest" format: "sarif" - output: "trivy-results10.sarif" - exit-code: "1" - severity: "CRITICAL,HIGH" + output: "trivy-results9.sarif" + vuln-type: "os,library" - name: Upload Trivy scan results to GitHub Security tab if: always() uses: github/codeql-action/upload-sarif@v2 with: - sarif_file: "trivy-results10.sarif" + sarif_file: "trivy-results9.sarif" diff --git a/.github/workflows/veracode.yaml b/.github/workflows/veracode.yaml index 03af264..409cd01 100644 --- a/.github/workflows/veracode.yaml +++ b/.github/workflows/veracode.yaml @@ -31,15 +31,15 @@ on: # Trigger manually workflow_dispatch: # Triggered once a week - # schedule: - # - cron: "0 0 * * 0" + schedule: + - cron: "0 0 * * 0" env: DOTNET_VERSION: '7.0' # The .NET SDK version to use jobs: - analyze-administration-service: + analyze-policy-hub-service: runs-on: ubuntu-latest permissions: actions: read diff --git a/.gitignore b/.gitignore index c9ddcb6..28bd2c7 100644 --- a/.gitignore +++ b/.gitignore @@ -43,5 +43,11 @@ msbuild.wrn # Visual Studio 2015 .vs/ +### Helm ### +# Chart dependencies and local install +**/charts/*.tgz +Chart.lock +**/values-local.yaml + # local dev configuration appsettings.Development.json diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..700b32e --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,21 @@ +# Changelog + +## 0.1.0-rc.1 (2024-01-23) + + +### Features + +* add initial implementation for policy hub ([0b5433a](https://github.com/eclipse-tractusx/policy-hub/commit/0b5433a989e34a4fce9b12ac0f7ef3a09b2a86d4)) +* add purpose trace 3.1 id ([243488a](https://github.com/eclipse-tractusx/policy-hub/commit/243488aece1731481a5aebd67f2b8de961987cbd)) +* **helm-chart:** ensure unique resource names ([#11](https://github.com/eclipse-tractusx/policy-hub/issues/11)) ([cd56676](https://github.com/eclipse-tractusx/policy-hub/commit/cd56676f49073a032d0905d5dcb637898d983ec2)) +* **helm-chart:** use templates for unique resource names ([#14](https://github.com/eclipse-tractusx/policy-hub/issues/14)) ([d412b38](https://github.com/eclipse-tractusx/policy-hub/commit/d412b389fd45e2aec2e8db20dc64d70f41a2d563)) + + +### Bug Fixes + +* set product name in .tractusx ([#3](https://github.com/eclipse-tractusx/policy-hub/issues/3)) ([04b6689](https://github.com/eclipse-tractusx/policy-hub/commit/04b668933812737a691d118662ccdd349a14909b)), closes [#4](https://github.com/eclipse-tractusx/policy-hub/issues/4) + + +### Miscellaneous Chores + +* release 0.1.0-rc.1 ([d24b8a4](https://github.com/eclipse-tractusx/policy-hub/commit/d24b8a426a151addc31b52806e4e4c8a0270741a)) diff --git a/DEPENDENCIES b/DEPENDENCIES index 3600e12..aa9dbca 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -1,8 +1,49 @@ +nuget/nuget/-/AutoFixture.AutoFakeItEasy/4.18.0, MIT, approved, #10064 +nuget/nuget/-/AutoFixture.Xunit/4.18.0, 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/-/Fare/2.1.1, MIT, approved, clearlydefined +nuget/nuget/-/FluentAssertions/6.11.0, Apache-2.0 AND MIT, approved, #10061 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/-/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.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/2.12.0, Apache-2.0, approved, #8435 +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.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/-/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/-/Xunit.Extensions.AssemblyFixture/2.4.1, MIT, approved, #3502 +nuget/nuget/-/coverlet.collector/6.0.0, 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 diff --git a/PACKAGES b/PACKAGES new file mode 100644 index 0000000..f603629 --- /dev/null +++ b/PACKAGES @@ -0,0 +1,49 @@ +nuget/nuget/-/Flurl.Signed/3.0.6 +nuget/nuget/-/EFCore.NamingConventions/7.0.2 +nuget/nuget/-/Newtonsoft.Json/13.0.3 +nuget/nuget/-/Npgsql/7.0.6 +nuget/nuget/-/Npgsql.EntityFrameworkCore.PostgreSQL/7.0.11 +nuget/nuget/-/Serilog/3.0.1 +nuget/nuget/-/Serilog.AspNetCore/7.0.0 +nuget/nuget/-/Serilog.Enrichers.CorrelationId/3.0.1 +nuget/nuget/-/Serilog.Enrichers.Environment/2.3.0 +nuget/nuget/-/Serilog.Enrichers.Process/2.0.2 +nuget/nuget/-/Serilog.Enrichers.Sensitive/1.7.3 +nuget/nuget/-/Serilog.Enrichers.Thread/3.1.0 +nuget/nuget/-/Serilog.Extensions.Hosting/7.0.0 +nuget/nuget/-/Serilog.Extensions.Logging/7.0.0 +nuget/nuget/-/Serilog.Formatting.Compact/1.1.0 +nuget/nuget/-/Serilog.Settings.Configuration/7.0.1 +nuget/nuget/-/Serilog.Sinks.Console/4.1.0 +nuget/nuget/-/Serilog.Sinks.Debug/2.0.0 +nuget/nuget/-/Serilog.Sinks.File/5.0.0 +nuget/nuget/-/Swashbuckle.AspNetCore/6.5.0 +nuget/nuget/-/Swashbuckle.AspNetCore.Swagger/6.5.0 +nuget/nuget/-/Swashbuckle.AspNetCore.SwaggerGen/6.5.0 +nuget/nuget/-/Swashbuckle.AspNetCore.SwaggerUI/6.5.0 +nuget/nuget/-/SwashBuckle.AspNetCore/6.5.0 +nuget/nuget/-/Humanizer.Core/2.14.1 +nuget/nuget/-/Mono.TextTemplating/2.2.1 +nuget/nuget/-/AutoFixture/4.18.0 +nuget/nuget/-/AutoFixture.AutoFakeItEasy/4.18.0 +nuget/nuget/-/AutoFixture.Xunit/4.18.0 +nuget/nuget/-/coverlet.collector/6.0.0 +nuget/nuget/-/FakeItEasy/7.4.0 +nuget/nuget/-/FluentAssertions/6.11.0 +nuget/nuget/-/Testcontainers/3.4.0 +nuget/nuget/-/Testcontainers.PostgreSql/3.4.0 +nuget/nuget/-/xunit/2.5.0 +nuget/nuget/-/Xunit.Extensions.AssemblyFixture/2.4.1 +nuget/nuget/-/xunit.runner.visualstudio/2.5.0 +nuget/nuget/-/Castle.Core/4.3.1 +nuget/nuget/-/Fare/2.1.1 +nuget/nuget/-/Portable.BouncyCastle/1.9.0 +nuget/nuget/-/SharpZipLib/1.4.2 +nuget/nuget/-/SSH.NET/2020.0.2 +nuget/nuget/-/SshNet.Security.Cryptography/1.3.0 +nuget/nuget/-/xunit.abstractions/2.0.3 +nuget/nuget/-/xunit.analyzers/1.2.0 +nuget/nuget/-/xunit.assert/2.5.0 +nuget/nuget/-/xunit.core/2.5.0 +nuget/nuget/-/xunit.extensibility.core/2.5.0 +nuget/nuget/-/xunit.extensibility.execution/2.5.0 diff --git a/README.md b/README.md index ab968d7..e63733c 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,11 @@ dotnet run This application provides container images for demonstration purposes. +### DockerHub + +* [https://hub.docker.com/r/tractusx/policy-hub-service](https://hub.docker.com/r/tractusx/policy-hub-service) +* [https://hub.docker.com/r/tractusx/policy-hub-migrations](https://hub.docker.com/r/tractusx/policy-hub-migrations) + ### Base images mcr.microsoft.com/dotnet/aspnet:7.0-alpine: diff --git a/charts/chart-testing-config.yaml b/charts/chart-testing-config.yaml new file mode 100644 index 0000000..fc9a54d --- /dev/null +++ b/charts/chart-testing-config.yaml @@ -0,0 +1,23 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +validate-maintainers: false +chart-repos: + - bitnami=https://charts.bitnami.com/bitnami + - tractusx-dev=https://eclipse-tractusx.github.io/charts/dev diff --git a/charts/policy-hub/.helmignore b/charts/policy-hub/.helmignore new file mode 100644 index 0000000..0bffc69 --- /dev/null +++ b/charts/policy-hub/.helmignore @@ -0,0 +1,27 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ + +# Custom dirs and files +argocd/ +*.gotmpl diff --git a/charts/policy-hub/Chart.yaml b/charts/policy-hub/Chart.yaml new file mode 100644 index 0000000..369ba26 --- /dev/null +++ b/charts/policy-hub/Chart.yaml @@ -0,0 +1,31 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +apiVersion: v2 +name: policy-hub +type: application +version: 0.1.0-rc.1 +appVersion: 0.1.0-rc.1 +description: Helm chart for Catena-X Policy Hub +home: https://github.com/eclipse-tractusx/policy-hub +dependencies: + - condition: postgresql.enabled + name: postgresql + repository: https://charts.bitnami.com/bitnami + version: 12.12.x diff --git a/charts/policy-hub/LICENSE b/charts/policy-hub/LICENSE new file mode 100644 index 0000000..f49a4e1 --- /dev/null +++ b/charts/policy-hub/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://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. \ No newline at end of file diff --git a/charts/policy-hub/README.md b/charts/policy-hub/README.md new file mode 100644 index 0000000..272da99 --- /dev/null +++ b/charts/policy-hub/README.md @@ -0,0 +1,121 @@ +# Helm chart for Catena-X Policy Hub + +This helm chart installs the Catena-X Policy Hub application. + +For further information please refer to [Technical Documentation](./docs/technical-documentation). + +The referenced container images are for demonstration purposes only. + +## Installation + +To install the chart with the release name `policy-hub`: + +```shell +$ helm repo add tractusx-dev https://eclipse-tractusx.github.io/charts/dev +$ helm install policy-hub tractusx-dev/policy-hub +``` + +To install the helm chart into your cluster with your values: + +```shell +$ helm install -f your-values.yaml policy-hub tractusx-dev/policy-hub +``` + +To use the helm chart as a dependency: + +```yaml +dependencies: + - name: policy-hub + repository: https://eclipse-tractusx.github.io/charts/dev + version: 0.1.0-rc.1 +``` + +## Requirements + +| Repository | Name | Version | +|------------|------|---------| +| https://charts.bitnami.com/bitnami | postgresql | 12.12.x | + +## Values + +| 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.name | string | `"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":[{"backend":{"port":8080},"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 | `"tractusx/policy-hub-service:0.1.0-rc.1"` | | +| 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.logging.businessLogic | string | `"Information"` | | +| policyhub.logging.default | string | `"Information"` | | +| policyhub.healthChecks.startup.tags[0].name | string | `"HEALTHCHECKS__0__TAGS__1"` | | +| policyhub.healthChecks.startup.tags[0].value | string | `"policyhubdb"` | | +| policyhub.swaggerEnabled | bool | `false` | | +| policyhubmigrations.image | string | `"tractusx/policy-hub-migrations:0.1.0-rc.1"` | | +| 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.seeding.testDataEnvironments | string | `""` | | +| policyhubmigrations.seeding.testDataPaths | string | `"Seeder/Data"` | | +| policyhubmigrations.logging.default | string | `"Information"` | | +| 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.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. | +| postgresql.architecture | string | `"replication"` | | +| postgresql.audit.pgAuditLog | string | `"write, ddl"` | | +| postgresql.audit.logLinePrefix | string | `"%m %u %d "` | | +| postgresql.primary.extendedConfiguration | string | `""` | Extended PostgreSQL Primary configuration (increase of max_connections recommended - default is 100) | +| postgresql.primary.initdb.scriptsConfigMap | string | `"{{ .Release.Name }}-phub-cm-postgres"` | | +| 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.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'. | +| portContainer | int | `8080` | | +| portService | int | `8080` | | +| replicaCount | int | `3` | | +| nodeSelector | object | `{}` | Node labels for pod assignment | +| tolerations | list | `[]` | Tolerations for pod assignment | +| affinity.podAntiAffinity | object | `{"preferredDuringSchedulingIgnoredDuringExecution":[{"podAffinityTerm":{"labelSelector":{"matchExpressions":[{"key":"app.kubernetes.io/name","operator":"DoesNotExist"}]},"topologyKey":"kubernetes.io/hostname"},"weight":100}]}` | Following Catena-X Helm Best Practices, [reference](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity). | +| updateStrategy.type | string | `"RollingUpdate"` | Update strategy type, rolling update configuration parameters, [reference](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies). | +| updateStrategy.rollingUpdate.maxSurge | int | `1` | | +| updateStrategy.rollingUpdate.maxUnavailable | int | `0` | | +| startupProbe | object | `{"failureThreshold":30,"initialDelaySeconds":10,"periodSeconds":10,"successThreshold":1,"timeoutSeconds":1}` | Following Catena-X Helm Best Practices, [reference](https://github.com/helm/charts/blob/master/stable/nginx-ingress/values.yaml#L210). | +| livenessProbe.failureThreshold | int | `3` | | +| livenessProbe.initialDelaySeconds | int | `10` | | +| livenessProbe.periodSeconds | int | `10` | | +| livenessProbe.successThreshold | int | `1` | | +| livenessProbe.timeoutSeconds | int | `10` | | +| readinessProbe.failureThreshold | int | `3` | | +| readinessProbe.initialDelaySeconds | int | `10` | | +| readinessProbe.periodSeconds | int | `10` | | +| readinessProbe.successThreshold | int | `1` | | +| readinessProbe.timeoutSeconds | int | `1` | | + +Autogenerated with [helm docs](https://github.com/norwoodj/helm-docs) diff --git a/charts/policy-hub/README.md.gotmpl b/charts/policy-hub/README.md.gotmpl new file mode 100644 index 0000000..499eb7a --- /dev/null +++ b/charts/policy-hub/README.md.gotmpl @@ -0,0 +1,37 @@ +# {{ template "chart.description" . }} + +This helm chart installs the Catena-X Policy Hub application. + +For further information please refer to [Technical Documentation](./docs/technical-documentation). + +The referenced container images are for demonstration purposes only. + +## Installation + +To install the chart with the release name `{{ template "chart.name" . }}`: + +```shell +$ helm repo add tractusx-dev https://eclipse-tractusx.github.io/charts/dev +$ helm install {{ template "chart.name" . }} tractusx-dev/{{ template "chart.name" . }} +``` + +To install the helm chart into your cluster with your values: + +```shell +$ helm install -f your-values.yaml {{ template "chart.name" . }} tractusx-dev/{{ template "chart.name" . }} +``` + +To use the helm chart as a dependency: + +```yaml +dependencies: + - name: {{ template "chart.name" . }} + repository: https://eclipse-tractusx.github.io/charts/dev + version: {{ template "chart.version" . }} +``` + +{{ template "chart.requirementsSection" . }} + +{{ template "chart.valuesSection" . }} + +Autogenerated with [helm docs](https://github.com/norwoodj/helm-docs) diff --git a/charts/policy-hub/templates/_helpers.tpl b/charts/policy-hub/templates/_helpers.tpl new file mode 100644 index 0000000..06b1c87 --- /dev/null +++ b/charts/policy-hub/templates/_helpers.tpl @@ -0,0 +1,91 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "phub.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "phub.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "phub.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "phub.labels" -}} +helm.sh/chart: {{ include "phub.chart" . }} +{{ include "phub.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "phub.selectorLabels" -}} +app.kubernetes.io/name: {{ include "phub.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "phub.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "phub.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Determine database hostname for subchart +*/}} + +{{- define "postgresql.primary.fullname" -}} +{{- if eq .Values.postgresql.architecture "replication" }} +{{- printf "%s-primary" (include "chart-name-postgresql-dependency" .) | trunc 63 | trimSuffix "-" -}} +{{- else -}} + {{- include "chart-name-postgresql-dependency" . -}} +{{- end -}} +{{- end -}} + +{{- define "postgresql.readReplica.fullname" -}} +{{- printf "%s-read" (include "chart-name-postgresql-dependency" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define "chart-name-postgresql-dependency" -}} +{{- if .Values.postgresql.fullnameOverride -}} +{{- .Values.postgresql.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default "postgresql" .Values.postgresql.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/policy-hub/templates/configmap-postgres-init.yaml b/charts/policy-hub/templates/configmap-postgres-init.yaml new file mode 100644 index 0000000..6ac456b --- /dev/null +++ b/charts/policy-hub/templates/configmap-postgres-init.yaml @@ -0,0 +1,35 @@ +{{- /* +* Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +* +* See the NOTICE file(s) distributed with this work for additional +* information regarding copyright ownership. +* +* This program and the accompanying materials are made available under the +* terms of the Apache License, Version 2.0 which is available at +* https://www.apache.org/licenses/LICENSE-2.0. +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +* License for the specific language governing permissions and limitations +* under the License. +* +* SPDX-License-Identifier: Apache-2.0 +*/}} + +{{- if .Values.postgresql.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Release.Name }}-phub-cm-postgres + namespace: {{ .Release.Namespace }} +data: + 02-init-db.sql: | + CREATE SCHEMA hub; + ALTER SCHEMA hub OWNER TO hub; + CREATE TABLE public.__efmigrations_history_hub ( + migration_id character varying(150) NOT NULL, + product_version character varying(32) NOT NULL + ); + ALTER TABLE public.__efmigrations_history_hub OWNER TO hub; +{{- end -}} diff --git a/charts/policy-hub/templates/deployment-hub.yaml b/charts/policy-hub/templates/deployment-hub.yaml new file mode 100644 index 0000000..b93a337 --- /dev/null +++ b/charts/policy-hub/templates/deployment-hub.yaml @@ -0,0 +1,142 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "phub.fullname" . }} + namespace: {{ .Values.namespace }} + labels: + {{- include "phub.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + strategy: + {{- toYaml .Values.updateStrategy | nindent 4 }} + selector: + matchLabels: + {{- include "phub.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "phub.selectorLabels" . | nindent 8 }} + spec: + containers: + - name: {{ .Chart.Name }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + runAsNonRoot: true + image: "{{ .Values.policyhub.image }}" + imagePullPolicy: "Always" + env: + - name: DOTNET_ENVIRONMENT + value: "{{ .Values.dotnetEnvironment }}" + {{- if .Values.postgresql.enabled }} + - name: "POLICY_HUB_PASSWORD" + valueFrom: + secretKeyRef: + name: "{{ .Release.Name }}-phub-postgres" + key: "password" + - name: "CONNECTIONSTRINGS__POLICYHUBDB" + value: "Server={{ template "postgresql.primary.fullname" . }};Database={{ .Values.postgresql.auth.database }};Port={{ .Values.postgresql.auth.port }};User Id={{ .Values.postgresql.auth.username }};Password=$(POLICY_HUB_PASSWORD);Ssl Mode={{ .Values.dbConnection.sslMode }};" + {{- end }} + {{- if not .Values.postgresql.enabled }} + - name: "POLICY_HUB_PASSWORD" + valueFrom: + secretKeyRef: + name: "{{ .Values.externalDatabase.existingSecret }}" + key: "password" + - name: "CONNECTIONSTRINGS__POLICYHUBDB" + 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}}" + {{- if .Values.policyhub.healthChecks.startup.tags }} + {{- toYaml .Values.policyhub.healthChecks.startup.tags | nindent 8 }} + {{- end }} + - name: "HEALTHCHECKS__1__PATH" + value: "{{ .Values.healthChecks.readyness.path}}" + - name: "HEALTHCHECKS__2__PATH" + value: "{{ .Values.healthChecks.liveness.path}}" + - name: "JWTBEAREROPTIONS__METADATAADDRESS" + value: "{{ .Values.centralidpAddress }}{{ .Values.keycloak.central.jwtBearerOptions.metadataPath }}" + - name: "JWTBEAREROPTIONS__REQUIREHTTPSMETADATA" + value: "{{ .Values.keycloak.central.jwtBearerOptions.requireHttpsMetadata }}" + - name: "JWTBEAREROPTIONS__TOKENVALIDATIONPARAMETERS__VALIDAUDIENCE" + value: "{{ .Values.keycloak.central.jwtBearerOptions.tokenValidationParameters.validAudience }}" + - name: "JWTBEAREROPTIONS__TOKENVALIDATIONPARAMETERS__VALIDISSUER" + value: "{{ .Values.centralidpAddress }}{{ .Values.keycloak.central.jwtBearerOptions.tokenValidationParameters.validIssuerPath }}" + - name: "JWTBEAREROPTIONS__REFRESHINTERVAL" + value: "{{ .Values.keycloak.central.jwtBearerOptions.refreshInterval }}" + - name: "SERILOG__MINIMUMLEVEL__Default" + value: "{{ .Values.policyhub.logging.default }}" + - name: "SERILOG__MINIMUMLEVEL__OVERRIDE__Org.Eclipse.TractusX.PolicyHub.Service" + value: "{{ .Values.policyhub.logging.businessLogic }}" + - name: "SWAGGERENABLED" + value: "{{ .Values.policyhub.swaggerEnabled }}" + ports: + - name: http + containerPort: {{ .Values.portContainer }} + protocol: TCP + startupProbe: + httpGet: + path: {{ .Values.healthChecks.startup.path }} + port: {{ .Values.portContainer }} + scheme: HTTP + initialDelaySeconds: {{ .Values.startupProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.startupProbe.periodSeconds }} + timeoutSeconds: {{ .Values.startupProbe.timeoutSeconds }} + successThreshold: {{ .Values.startupProbe.successThreshold }} + failureThreshold: {{ .Values.startupProbe.failureThreshold }} + livenessProbe: + httpGet: + path: {{ .Values.healthChecks.liveness.path }} + port: {{ .Values.portContainer }} + scheme: HTTP + initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.livenessProbe.failureThreshold }} + readinessProbe: + httpGet: + path: {{ .Values.healthChecks.readyness.path }} + port: {{ .Values.portContainer }} + scheme: HTTP + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + resources: + {{- toYaml .Values.policyhub.resources | nindent 10 }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/charts/policy-hub/templates/ingress.yaml b/charts/policy-hub/templates/ingress.yaml new file mode 100644 index 0000000..225956e --- /dev/null +++ b/charts/policy-hub/templates/ingress.yaml @@ -0,0 +1,80 @@ +{{- /* +* Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +* +* See the NOTICE file(s) distributed with this work for additional +* information regarding copyright ownership. +* +* This program and the accompanying materials are made available under the +* terms of the Apache License, Version 2.0 which is available at +* https://www.apache.org/licenses/LICENSE-2.0. +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +* License for the specific language governing permissions and limitations +* under the License. +* +* SPDX-License-Identifier: Apache-2.0 +*/}} + +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "phub.fullname" . -}} +{{- $svcPort := .Values.portService -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "phub.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ .backend.port }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/policy-hub/templates/job-policy-hub-migrations.yaml b/charts/policy-hub/templates/job-policy-hub-migrations.yaml new file mode 100644 index 0000000..241148e --- /dev/null +++ b/charts/policy-hub/templates/job-policy-hub-migrations.yaml @@ -0,0 +1,77 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "phub.fullname" . }}-migrations + annotations: + "batch.kubernetes.io/job-tracking": "true" + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-weight": "-5" +spec: + template: + metadata: + labels: + {{- include "phub.selectorLabels" . | nindent 8 }} + spec: + restartPolicy: Never + containers: + - name: {{ include "phub.fullname" . }}-migrations + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + runAsNonRoot: true + image: "{{ .Values.policyhubmigrations.image }}" + imagePullPolicy: "Always" + env: + - name: DOTNET_ENVIRONMENT + value: "{{ .Values.dotnetEnvironment }}" + {{- if .Values.postgresql.enabled }} + - name: "POLICY_HUB_PASSWORD" + valueFrom: + secretKeyRef: + name: "{{ .Release.Name }}-phub-postgres" + key: "password" + - name: "CONNECTIONSTRINGS__POLICYHUBDB" + value: "Server={{ template "postgresql.primary.fullname" . }};Database={{ .Values.postgresql.auth.database }};Port={{ .Values.postgresql.auth.port }};User Id={{ .Values.postgresql.auth.username }};Password=$(POLICY_HUB_PASSWORD);Ssl Mode={{ .Values.dbConnection.sslMode }};" + {{- end }} + {{- if not .Values.postgresql.enabled }} + - name: "POLICY_HUB_PASSWORD" + valueFrom: + secretKeyRef: + name: "{{ .Values.externalDatabase.existingSecret }}" + key: "password" + - name: "CONNECTIONSTRINGS__POLICYHUBDB" + 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: "SEEDING__TESTDATAENVIRONMENTS__0" + value: "{{ .Values.policyhubmigrations.seeding.testDataEnvironments }}" + - name: "SEEDING__DATAPATHS__0" + value: "{{ .Values.policyhubmigrations.seeding.testDataPaths }}" + - name: "SERILOG__MINIMUMLEVEL__Default" + value: "{{ .Values.policyhubmigrations.logging.default }}" + ports: + - name: http + containerPort: {{ .Values.portContainer }} + protocol: TCP + resources: + {{- toYaml .Values.policyhubmigrations.resources | nindent 10 }} diff --git a/charts/policy-hub/templates/secret-external-db.yaml b/charts/policy-hub/templates/secret-external-db.yaml new file mode 100644 index 0000000..78c60e5 --- /dev/null +++ b/charts/policy-hub/templates/secret-external-db.yaml @@ -0,0 +1,39 @@ +{{- /* +* Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +* +* See the NOTICE file(s) distributed with this work for additional +* information regarding copyright ownership. +* +* This program and the accompanying materials are made available under the +* terms of the Apache License, Version 2.0 which is available at +* https://www.apache.org/licenses/LICENSE-2.0. +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +* License for the specific language governing permissions and limitations +* under the License. +* +* SPDX-License-Identifier: Apache-2.0 +*/}} + +{{- if not .Values.postgresql.enabled -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Values.externalDatabase.existingSecret }} + namespace: {{ .Release.Namespace }} +type: Opaque +# use lookup function to check if secret exists +{{- $secret := (lookup "v1" "Secret" .Release.Namespace .Values.externalDatabase.existingSecret) }} +{{ if $secret -}} +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 + password: {{ ( .Values.externalDatabase.password | b64enc ) | default $secret.data.password | quote }} +{{ else -}} +stringData: + # if secret doesn't exist, use provided value from values file or generate a random one + password: {{ .Values.externalDatabase.password | default ( randAlphaNum 32 ) | quote }} +{{ end }} +{{- end -}} diff --git a/charts/policy-hub/templates/secret-postgres.yaml b/charts/policy-hub/templates/secret-postgres.yaml new file mode 100644 index 0000000..b07b1c3 --- /dev/null +++ b/charts/policy-hub/templates/secret-postgres.yaml @@ -0,0 +1,26 @@ + +{{- if .Values.postgresql.enabled -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-phub-postgres + namespace: {{ .Release.Namespace }} +type: Opaque +# use lookup function to check if secret exists +{{- $secret := (lookup "v1" "Secret" .Release.Namespace .Values.postgresql.auth.existingSecret) }} +{{ if $secret -}} +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}} +{{ 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 }} +{{ end }} +{{- end -}} diff --git a/charts/policy-hub/templates/service-hub.yaml b/charts/policy-hub/templates/service-hub.yaml new file mode 100644 index 0000000..678cfad --- /dev/null +++ b/charts/policy-hub/templates/service-hub.yaml @@ -0,0 +1,33 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +apiVersion: v1 +kind: Service +metadata: + name: {{ include "phub.fullname" . }} + namespace: {{ .Values.namespace }} + labels: + {{- include "phub.labels" . | nindent 4 }} +spec: + type: ClusterIP + ports: + - port: {{ .Values.portService }} + targetPort: {{ .Values.portContainer }} + selector: + {{- include "phub.selectorLabels" . | nindent 4 }} diff --git a/charts/policy-hub/values.yaml b/charts/policy-hub/values.yaml new file mode 100644 index 0000000..a7857a1 --- /dev/null +++ b/charts/policy-hub/values.yaml @@ -0,0 +1,224 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +# -- 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 + name: "policy-hub" + 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" + backend: + port: 8080 +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: "tractusx/policy-hub-service:0.1.0-rc.1" + # -- 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. + resources: + requests: + cpu: 15m + memory: 300M + # limits: + # cpu: 45m + # memory: 400M + logging: + businessLogic: "Information" + default: "Information" + healthChecks: + startup: + tags: + - name: "HEALTHCHECKS__0__TAGS__1" + value: "policyhubdb" + swaggerEnabled: false + +policyhubmigrations: + image: "tractusx/policy-hub-migrations:0.1.0-rc.1" + # -- 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. + resources: + requests: + cpu: 15m + memory: 105M + # limits: + # cpu: 45m + # memory: 105M + seeding: + testDataEnvironments: "" + testDataPaths: "Seeder/Data" + logging: + default: "Information" + +postgresql: + # -- PostgreSQL chart configuration; + # default configurations: + # host: "policy-hub-postgresql-primary", + # port: 5432; + # Switch to enable or disable the PostgreSQL helm chart. + enabled: true + auth: + # -- Non-root username. + username: hub + # -- Database name. + database: policy-hub + # -- Secret containing the passwords for root usernames postgres and non-root username hub. + existingSecret: "{{ .Release.Name }}-phub-postgres" + architecture: replication + audit: + pgAuditLog: "write, ddl" + logLinePrefix: "%m %u %d " + primary: + # -- Extended PostgreSQL Primary configuration (increase of max_connections recommended - default is 100) + extendedConfiguration: "" + initdb: + scriptsConfigMap: "{{ .Release.Name }}-phub-cm-postgres" + readReplicas: + # -- Extended PostgreSQL read only replicas configuration (increase of max_connections recommended - default is 100) + extendedConfiguration: "" + +externalDatabase: + # -- 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). + host: "phub-postgres-ext" + # -- Database port number. + port: 5432 + # -- Non-root username for policy-hub. + user: "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: "" + +portContainer: 8080 + +portService: 8080 + +replicaCount: 3 + +# -- Node labels for pod assignment +nodeSelector: {} + +# -- Tolerations for pod assignment +tolerations: [] + +affinity: +# -- Following Catena-X Helm Best Practices, +# [reference](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity). + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: DoesNotExist + topologyKey: kubernetes.io/hostname + +updateStrategy: +# -- Update strategy type, +# rolling update configuration parameters, +# [reference](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies). + type: RollingUpdate + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + +# -- Following Catena-X Helm Best Practices, +# [reference](https://github.com/helm/charts/blob/master/stable/nginx-ingress/values.yaml#L210). +startupProbe: + failureThreshold: 30 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 +livenessProbe: + failureThreshold: 3 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 10 +readinessProbe: + failureThreshold: 3 + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 diff --git a/consortia/argocd-app-templates/appsetup-beta.yaml b/consortia/argocd-app-templates/appsetup-beta.yaml new file mode 100644 index 0000000..dcdc965 --- /dev/null +++ b/consortia/argocd-app-templates/appsetup-beta.yaml @@ -0,0 +1,38 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: policy-hub +spec: + destination: + namespace: product-portal + server: 'https://kubernetes.default.svc' + source: + path: charts/policy-hub + repoURL: 'https://github.com/eclipse-tractusx/policy-hub.git' + targetRevision: policy-hub-1.0.0 + plugin: + env: + - name: AVP_SECRET + value: vault-secret + - name: helm_args + value: '-f values.yaml -f ../../consortia/environments/values-beta.yaml' + project: project-portal diff --git a/consortia/argocd-app-templates/appsetup-dev.yaml b/consortia/argocd-app-templates/appsetup-dev.yaml new file mode 100644 index 0000000..841b621 --- /dev/null +++ b/consortia/argocd-app-templates/appsetup-dev.yaml @@ -0,0 +1,41 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: policy-hub +spec: + destination: + namespace: product-portal + server: 'https://kubernetes.default.svc' + source: + path: charts/policy-hub + repoURL: 'https://github.com/eclipse-tractusx/policy-hub.git' + targetRevision: dev + plugin: + env: + - name: AVP_SECRET + value: vault-secret + - name: helm_args + value: '-f values.yaml -f ../../consortia/environments/values-dev.yaml' + project: project-portal + syncPolicy: + automated: + prune: true diff --git a/consortia/argocd-app-templates/appsetup-int.yaml b/consortia/argocd-app-templates/appsetup-int.yaml new file mode 100644 index 0000000..4aa6dcf --- /dev/null +++ b/consortia/argocd-app-templates/appsetup-int.yaml @@ -0,0 +1,38 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: policy-hub +spec: + destination: + namespace: product-portal + server: 'https://kubernetes.default.svc' + source: + path: charts/policy-hub + repoURL: 'https://github.com/eclipse-tractusx/policy-hub.git' + targetRevision: policy-hub-0.1.0-rc.1 + plugin: + env: + - name: AVP_SECRET + value: vault-secret + - name: helm_args + value: '-f values.yaml -f ../../consortia/environments/values-int.yaml' + project: project-portal diff --git a/consortia/argocd-app-templates/appsetup-pen.yaml b/consortia/argocd-app-templates/appsetup-pen.yaml new file mode 100644 index 0000000..9e15b9e --- /dev/null +++ b/consortia/argocd-app-templates/appsetup-pen.yaml @@ -0,0 +1,38 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: policy-hub-pen +spec: + destination: + namespace: product-portal-pen + server: 'https://kubernetes.default.svc' + source: + path: charts/policy-hub + repoURL: 'https://github.com/eclipse-tractusx/policy-hub.git' + targetRevision: policy-hub-0.1.0-rc.1 + plugin: + env: + - name: AVP_SECRET + value: vault-secret + - name: helm_args + value: '-f values.yaml -f ../../consortia/environments/values-pen.yaml' + project: project-portal diff --git a/consortia/argocd-app-templates/appsetup-rc.yaml b/consortia/argocd-app-templates/appsetup-rc.yaml new file mode 100644 index 0000000..3297d1a --- /dev/null +++ b/consortia/argocd-app-templates/appsetup-rc.yaml @@ -0,0 +1,38 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: policy-hub-rc +spec: + destination: + namespace: product-iam + server: 'https://kubernetes.default.svc' + source: + path: charts/policy-hub + repoURL: 'https://github.com/eclipse-tractusx/policy-hub.git' + targetRevision: release-candidate + plugin: + env: + - name: AVP_SECRET + value: vault-secret + - name: helm_args + value: '-f values.yaml -f ../../consortia/environments/values-rc.yaml' + project: project-portal diff --git a/consortia/argocd-app-templates/appsetup-stable.yaml b/consortia/argocd-app-templates/appsetup-stable.yaml new file mode 100644 index 0000000..9ca2e49 --- /dev/null +++ b/consortia/argocd-app-templates/appsetup-stable.yaml @@ -0,0 +1,77 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: policy-hub +spec: + destination: + name: '' + namespace: product-portal + server: 'https://kubernetes.default.svc' + source: + path: '' + repoURL: 'https://eclipse-tractusx.github.io/charts/dev' + targetRevision: policy-hub-0.1.0-rc.1 + plugin: + env: + - name: HELM_VALUES + value: | + policyHubBackendAddress: "https://policy-hub.stable.demo.catena-x.net" + ingress: + enabled: true + 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" + nginx.ingress.kubernetes.io/cors-allow-origin: "http://localhost:3000, https://*.stable.demo.catena-x.net" + tls: + - secretName: "tls-secret" + hosts: + - "policy-hub.stable.demo.catena-x.net" + hosts: + - host: "policy-hub.stable.demo.catena-x.net" + paths: + - path: "/api/policy-hub" + pathType: "Prefix" + backend: + service: "policy-hub-service" + port: 8080 + policyhubmigrations: + logging: + default: "Debug" + postgresql: + primary: + extendedConfiguration: | + max_connections = 200 + readReplicas: + extendedConfiguration: | + max_connections = 200 + secrets: + postgresql: + auth: + existingSecret: + postgrespassword: "" + password: "" + replicationPassword: "" + chart: policy-hub + sources: [] + project: project-portal diff --git a/consortia/argocd-app-templates/appsetup-upgrade.yaml b/consortia/argocd-app-templates/appsetup-upgrade.yaml new file mode 100644 index 0000000..d207e26 --- /dev/null +++ b/consortia/argocd-app-templates/appsetup-upgrade.yaml @@ -0,0 +1,38 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: policy-hub +spec: + destination: + namespace: product-portal + server: 'https://kubernetes.default.svc' + source: + path: charts/policy-hub + repoURL: 'https://github.com/eclipse-tractusx/policy-hub.git' + targetRevision: policy-hub-1.0.0 + plugin: + env: + - name: AVP_SECRET + value: vault-secret + - name: helm_args + value: '-f values.yaml -f ../../consortia/environments/values-upgrade.yaml' + project: project-portal diff --git a/consortia/environments/values-beta.yaml b/consortia/environments/values-beta.yaml new file mode 100644 index 0000000..f674c43 --- /dev/null +++ b/consortia/environments/values-beta.yaml @@ -0,0 +1,56 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +policyHubBackendAddress: "https://policy-hub.beta.demo.catena-x.net" +centralidpAddress: "https://centralidp.beta.demo.catena-x.net" + +ingress: + enabled: true + 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" + nginx.ingress.kubernetes.io/cors-allow-origin: "http://localhost:3000, https://*.beta.demo.catena-x.net" + tls: + - secretName: "tls-secret" + hosts: + - "policy-hub.beta.demo.catena-x.net" + hosts: + - host: "policy-hub.beta.demo.catena-x.net" + paths: + - path: "/api/policy-hub" + pathType: "Prefix" + backend: + port: 8080 + +policyhub: + swaggerEnabled: true + +policyhubmigrations: + logging: + default: "Debug" + +secrets: + postgresql: + auth: + existingSecret: + postgrespassword: "" + password: "" + replicationPassword: "" diff --git a/consortia/environments/values-dev.yaml b/consortia/environments/values-dev.yaml new file mode 100644 index 0000000..860b213 --- /dev/null +++ b/consortia/environments/values-dev.yaml @@ -0,0 +1,64 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +policyHubAddress: "https://policy-hub.dev.demo.catena-x.net" +centralidpAddress: "https://centralidp.dev.demo.catena-x.net" + +ingress: + enabled: true + 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" + nginx.ingress.kubernetes.io/cors-allow-origin: "http://localhost:3000, https://*.dev.demo.catena-x.net" + tls: + - secretName: "tls-secret" + hosts: + - "policy-hub.dev.demo.catena-x.net" + hosts: + - host: "policy-hub.dev.demo.catena-x.net" + paths: + - path: "/api/policy-hub" + pathType: "Prefix" + backend: + port: 8080 + +keycloak: + central: + jwtBearerOptions: + tokenValidationParameters: + validAudience: "Cl23-CX-Policy-Hub" + +policyhub: + image: "tractusx/policy-hub-service:dev" + swaggerEnabled: true + +policyhubmigrations: + image: "tractusx/policy-hub-migrations:dev" + logging: + default: "Debug" + +secrets: + postgresql: + auth: + existingSecret: + postgrespassword: "" + password: "" + replicationPassword: "" diff --git a/consortia/environments/values-int.yaml b/consortia/environments/values-int.yaml new file mode 100644 index 0000000..7303746 --- /dev/null +++ b/consortia/environments/values-int.yaml @@ -0,0 +1,62 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +policyHubAddress: "https://policy-hub.int.demo.catena-x.net" +centralidpAddress: "https://centralidp.int.demo.catena-x.net" + +ingress: + enabled: true + 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" + nginx.ingress.kubernetes.io/cors-allow-origin: "http://localhost:3000, https://*.int.demo.catena-x.net" + tls: + - secretName: "tls-secret" + hosts: + - "policy-hub.int.demo.catena-x.net" + hosts: + - host: "policy-hub.int.demo.catena-x.net" + paths: + - path: "/api/policy-hub" + pathType: "Prefix" + backend: + port: 8080 + +keycloak: + central: + jwtBearerOptions: + tokenValidationParameters: + validAudience: "Cl23-CX-Policy-Hub" + +policyhub: + swaggerEnabled: true + +policyhubmigrations: + logging: + default: "Debug" + +secrets: + postgresql: + auth: + existingSecret: + postgrespassword: "" + password: "" + replicationPassword: "" diff --git a/consortia/environments/values-pen.yaml b/consortia/environments/values-pen.yaml new file mode 100644 index 0000000..6fdbc5d --- /dev/null +++ b/consortia/environments/values-pen.yaml @@ -0,0 +1,56 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +policyHubAddress: "https://policy-hub-pen.dev.demo.catena-x.net" +centralidpAddress: "https://centralidp-pen.dev.demo.catena-x.net" + +ingress: + enabled: true + 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" + nginx.ingress.kubernetes.io/cors-allow-origin: "http://localhost:3000, https://*.dev.demo.catena-x.net" + tls: + - secretName: "tls-secret" + hosts: + - "policy-hub-backend-pen.dev.demo.catena-x.net" + hosts: + - host: "policy-hub-backend-pen.dev.demo.catena-x.net" + paths: + - path: "/api/policy-hub" + pathType: "Prefix" + backend: + port: 8080 + +policyhub: + swaggerEnabled: true + +policyhubmigrations: + logging: + default: "Debug" + +secrets: + postgresql: + auth: + existingSecret: + postgrespassword: "" + password: "" + replicationPassword: "" diff --git a/consortia/environments/values-rc.yaml b/consortia/environments/values-rc.yaml new file mode 100644 index 0000000..d76032b --- /dev/null +++ b/consortia/environments/values-rc.yaml @@ -0,0 +1,56 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +policyHubAddress: "https://policy-hub-rc.dev.demo.catena-x.net" +centralidpAddress: "https://centralidp-rc.dev.demo.catena-x.net" + +ingress: + enabled: true + 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" + nginx.ingress.kubernetes.io/cors-allow-origin: "http://localhost:3000, https://*.dev.demo.catena-x.net" + tls: + - secretName: "tls-secret" + hosts: + - "policy-hub-backend-rc.dev.demo.catena-x.net" + hosts: + - host: "policy-hub-backend-rc.dev.demo.catena-x.net" + paths: + - path: "/api/policy-hub" + pathType: "Prefix" + backend: + port: 8080 + +policyhub: + swaggerEnabled: true + +policyhubmigrations: + logging: + default: "Debug" + +secrets: + postgresql: + auth: + existingSecret: + postgrespassword: "" + password: "" + replicationPassword: "" diff --git a/consortia/environments/values-upgrade.yaml b/consortia/environments/values-upgrade.yaml new file mode 100644 index 0000000..aa58620 --- /dev/null +++ b/consortia/environments/values-upgrade.yaml @@ -0,0 +1,28 @@ +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +replicaCount: 0 + +secrets: + postgresql: + auth: + existingSecret: + postgrespassword: "" + password: "" + replicationPassword: "" diff --git a/docs/technical-documentation/architecture/Architecture Constraints.md b/docs/technical-documentation/architecture/Architecture Constraints.md new file mode 100644 index 0000000..3d19338 --- /dev/null +++ b/docs/technical-documentation/architecture/Architecture Constraints.md @@ -0,0 +1,30 @@ +# Architecture Constraints + +## General + +- This project is an readonly API project, there is no plan to implement an UI yet. + +- Run anywhere: can be deployed as a docker image, e. g. on Kubernetes (platform-independent, cloud, on prem or local). + +## Developer + +- OpenSource software first - FOSS licenses approved by the eclipse foundation has to be used. It could represent the initial set that the CX community agrees on to regulate the content contribution under FOSS licenses. + +- Coding guidelines for BE are defined and are to be followed for all policy hub related developments. + +- Apache License 2.0 - Apache License 2.0 is one of the approved licenses which should be used to respect and guarantee Intellectual property (IP). + +- Code Analysis, Linting and Code Coverage - Consistent style increases readability and maintainability of the code base. Hence, we use analyzers to enforce consistency and style rules. We enforce the code style and rules in the CI to avoid merging code that does not comply with standards. + +## Code analysis, linting and code coverage + +--comming soon--- +(Veracode; Eslinter, Sonarcloud, etc.) + +## NOTICE + +This work is licensed under the [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0). + +- SPDX-License-Identifier: Apache-2.0 +- SPDX-FileCopyrightText: 2021-2023 Contributors to the Eclipse Foundation +- Source URL: https://github.com/eclipse-tractusx/policy-hub diff --git a/docs/technical-documentation/architecture/Context and scope.md b/docs/technical-documentation/architecture/Context and scope.md new file mode 100644 index 0000000..28b675c --- /dev/null +++ b/docs/technical-documentation/architecture/Context and scope.md @@ -0,0 +1,17 @@ +# Content and Scope + +## Business Context + +TODO (PS): add description + +## Technical Context + +The policy hub comprise the technical foundation for interaction, monitoring, auditing and further functionalities. They are state of the art in terms of technology portfolio, consist of open-source components whenever possible and are open-sourced themselves 100%. + +## NOTICE + +This work is licensed under the [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0). + +- SPDX-License-Identifier: Apache-2.0 +- SPDX-FileCopyrightText: 2021-2023 Contributors to the Eclipse Foundation +- Source URL: https://github.com/eclipse-tractusx/policy-hub diff --git a/docs/technical-documentation/architecture/Development Concept.md b/docs/technical-documentation/architecture/Development Concept.md new file mode 100644 index 0000000..e30eed4 --- /dev/null +++ b/docs/technical-documentation/architecture/Development Concept.md @@ -0,0 +1,143 @@ +# Development Concept + +## Build, test, deploy + +Details to the build, test and deploy process can get found under the following md file: [Release Process](/docs/Release%20Process.md) + +## Development Guidelines + +The policy hub is using following key frameworks: + +- .Net +- Entity Framework + +### Swagger + +The API uses OpenAPI annotations to describe the endpoints with all necessary information. The annotations are then used to automatically generate the OpenAPI specification file, which can be viewed in the Swagger UI that is deployed with the application. + +#### API Dev Guidelines + +##### Implement authorization + +API's need to ensure that they only grant access to the authorized requester. For example, a user might be approved to access the API, but if they’re not allowed to add information to the application’s database via the POST method, any request to do so should be rejected. Authorization information can also be contained within a request as a token. + +Unlike some other API types, REST APIs must authenticate and authorize each request made to the server, even if multiple requests come from the same user. This is because REST communications are stateless — that is, each request can be understood by the API in isolation, without information from previous requests. + +Authorization can be governed by user roles, where each role comes with different permissions. Generally, API developers should adhere to the principle of least privilege, which states that users should only have access to the resources and methods necessary for their role, and nothing more. Predefined roles make it easier to oversee and change user permissions, reducing the chance that a bad actor can access sensitive data. + +In terms of implementation all endpoints should be secured with the highest restrictions as default. Restrictions should only be lessened through explicit exemptions. This ensures that in case of oversights an endpoint can be more secured than intended but never less secured. + +##### Validate all requests + +As mentioned, sometimes requests from perfectly valid sources may be hacking attempts. Therefore, APIs need rules to determine whether a request is friendly, friendly but invalid, or harmful, like an attempt to inject harmful code. + +An API request is only processed once its contents pass a thorough validation check — otherwise, the request should never reach the application data layer. + +Validation also includes sanity checks: Define sensible value ranges for the parameters a user provides. This especially is valid for the size of the request and the response. APIs should limit the possible number of records to process in order to prevent intentional or unintentional overloads of the system. + +##### Encrypt all requests and responses + +To prevent MITM attacks, any data transfer from the user to the API server or vice versa must be properly encrypted. This way, any intercepted requests or responses are useless to the intruder without the right decryption method. + +Since REST APIs use HTTP, encryption can be achieved by using the Transport Layer Security (TLS) protocol or Secure Sockets Layer (SSL) protocol. These protocols supply the S in “HTTPS” (“S” meaning “secure'') and are the standard for encrypting web pages and REST API communications. + +TLS/SSL only encrypts data when that data is being transferred. It doesn’t encrypt data sitting behind your API, which is why sensitive data should also be encrypted in the database layer as well. + +##### Only include necessary information in responses + +Like you might unintentionally let a secret slip when telling a story to a friend, it’s possible for an API response to expose information hackers can use. To prevent this, all responses sent to the end-user should include only the information to communicate the success or failure of the request, the resource requested (if any), and any other information directly related to these resources. + +In other words, avoid “oversharing” data — the response is a chance for you to inadvertently expose private data, either through the returned resources or verbose status messages. + +=> in the ownership of every API Developer + +##### Throttle API requests and establish quotas + +To prevent brute-force attacks like DDoS, an API can impose rate-limiting, a way to control the number of requests to the API server at any given time. + +There are two main ways to rate-limit API requests, quotas and throttling. Quotas limit the number of requests allowed from a user over a span of time, while throttling slows a user’s connection while still allowing them to use your API. + +Both methods should allow normal API requests but prevent floods of traffic intended to disrupt, as well as unexpected request spikes in general. + +##### Log API activity + +Logging API activities is extremely important when it comes to tracing user activity and in worst case hack activity. + +###### Conduct security tests + +=> see [Test Section](#tests) below + +##### Error Handling + +The simplest way we handle errors is to respond with an appropriate status code. + +Common agreed response codes: + +- 400 Bad Request – client sent an invalid request, such as lacking required request body or parameter. + Example: The same constraint has been configured multiple times in the request +- 401 Unauthorized – user authenticated but doesn't have permission to access the requested resource. + Example: User token doesn't have the access on the resource. +- 403 Forbidden – client failed to authenticate with the server. + Example: token expired oder invalid login. +- 404 Not Found – the requested resource does not exist. + Example: A specific policy was requested which does not exist in the database.. +- 500 Internal Server Error – a generic error occurred in the internal system logic. + Example: Unexpected server-side issue during policy validation. + Additionally to the generic error code, a detailed message/error is needed to ensure that the issue can get validated and resolved quickly. + +##### Repository Pattern + +The repositories are used via the Factory HubRepositories, which ensures that the same database instance is used for all repositories. + +Furthermore, it provides an implicit transaction functionality. + +The repositories themselves must not be registered for dependency injection in the corresponding startup; the method HubRepositories.GetInstance provides the instance of a requested repository. + +In the repository itself, you should not work with SaveChanges, it should only be called via the HubRepositories.SaveChanges to ensure that any transaction dependencies can be rolled back. + +#### Tests + +##### User Authentication Test + +If authentication mechanisms are implemented incorrectly, attackers can compromise authentication tokens or exploit implementation flaws to assume other users’ identities and gain access to your API’s endpoints. + +To test your authentication mechanisms, try sending API requests without proper authentication (either no tokens or credentials, or incorrect ones) and see if your API responds with the correct error and messaging. + +##### Parameter Tampering Test + +To run a parameter tampering test, try various combinations of invalid query parameters in your API requests and see if it responds with the correct error codes. If not, then your API likely has some backend validation errors that need to be resolved. + +##### Injection Test + +To test if your API is vulnerable to injections, try injecting SQL, NoSQL, LDAP, OS, or other commands in API inputs and see if your API executes them. These commands should be harmless, like reboot commands or cat commands. + +##### Unhandled HTTP Methods Test + +Most APIs have various HTTP methods that are used to retrieve, store, or delete data. Sometimes web servers will give access to unsupported HTTP methods by default, which makes your API vulnerable. + +To test for this vulnerability, you should try all the common HTTP methods (POST, GET, PUT, PATCH, and DELETE) as well as a few uncommon ones. TRY sending an API request with the HEAD verb instead of GET, for example, or a request with an arbitrary method like FOO. You should get an error code, but if you get a 200 OK response, then your API has a vulnerability. + +##### Load Test + +Load testing should be one of the last steps of your API security auditing process. This type is pushing the API to its limits in order to discover any functional or security issues that have yet to be revealed. + +To achieve this, send a large number of randomized requests, including SQL queries, system commands, arbitrary numbers, and other non-text characters, and see if your API responds with errors, processes any of these inputs incorrectly, or crashes. This type of testing will mimic Overflow and DDoS attacks. + +An API manager or gateway tool will handle or help address the API security guidelines described above (including testing). + +## Migration + +To run the policy hub, migrations are needed to load the initial data inside the policy hub db to enable the policy hub to work. +The migration will consist of an initial migration as well as delta migration files with future releases. As part of a new release, a migration file (if applicable) will get released and can get loaded via a delta load. + +## Configurability + +Policy Hub configuration is mainly possible via the appsettings files as well as the static data migration files. + +## NOTICE + +This work is licensed under the [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0). + +- SPDX-License-Identifier: Apache-2.0 +- SPDX-FileCopyrightText: 2021-2023 Contributors to the Eclipse Foundation +- Source URL: https://github.com/eclipse-tractusx/policy-hub diff --git a/docs/technical-documentation/architecture/Requirements.md b/docs/technical-documentation/architecture/Requirements.md new file mode 100644 index 0000000..2918aa0 --- /dev/null +++ b/docs/technical-documentation/architecture/Requirements.md @@ -0,0 +1,22 @@ +# Requirements overview + +## What is the Policy Hub Product? + +The Policy Hub is a central readonly API to receive information related policies of the Catena-X network. + +## Requirements + +For Catena-X Member Companies +|ID|Title|Requirement| +|--------|--------|--------| +|REQ-C-004|Identity Integration|Authentication is done vis IdP Federation to minimize administration overhead and to simplify logins. Authorization not included, this must be done Catena-X specific by the Central-IdP| + +TODO (PS): tbd with julia + +## NOTICE + +This work is licensed under the [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0). + +- SPDX-License-Identifier: Apache-2.0 +- SPDX-FileCopyrightText: 2021-2023 Contributors to the Eclipse Foundation +- Source URL: https://github.com/eclipse-tractusx/policy-hub diff --git a/docs/technical-documentation/architecture/Solution strategy.md b/docs/technical-documentation/architecture/Solution strategy.md new file mode 100644 index 0000000..6893ebd --- /dev/null +++ b/docs/technical-documentation/architecture/Solution strategy.md @@ -0,0 +1,14 @@ +# Solution Strategy + +- The technology portfolio and development stack are kept simple, based on commodity and oss components and products. +- APIs are always REST-based with token authentication. +- OIDC is used for authentication and authorization. +- IaC is fully realized via helm charts. + +## NOTICE + +This work is licensed under the [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0). + +- SPDX-License-Identifier: Apache-2.0 +- SPDX-FileCopyrightText: 2021-2023 Contributors to the Eclipse Foundation +- Source URL: https://github.com/eclipse-tractusx/policy-hub diff --git a/docs/technical-documentation/architecture/Whitebox Overall System.md b/docs/technical-documentation/architecture/Whitebox Overall System.md new file mode 100644 index 0000000..43c2054 --- /dev/null +++ b/docs/technical-documentation/architecture/Whitebox Overall System.md @@ -0,0 +1,15 @@ +# Whitebox Overall System + +## Summary + +In the following image you see the overall system overview of the Policy Hub + +TODO (PS): add image for system view + +## NOTICE + +This work is licensed under the [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0). + +- SPDX-License-Identifier: Apache-2.0 +- SPDX-FileCopyrightText: 2021-2023 Contributors to the Eclipse Foundation +- Source URL: https://github.com/eclipse-tractusx/policy-hub diff --git a/docs/technical-documentation/architecture/operational-concept.md b/docs/technical-documentation/architecture/operational-concept.md new file mode 100644 index 0000000..485faae --- /dev/null +++ b/docs/technical-documentation/architecture/operational-concept.md @@ -0,0 +1,47 @@ +# Operational concepts + +## Policy Hub Service + +### Configuration + +The Policy Hub can be configured using two methods: + +### appsettings.json + +If you build the Policy Hub, you can modify the appsettings.json for each backend service, to individually configure to a certain extend. This file contains all possible config entries for the application. + +### Helm Chart + +The most relevant config properties are exposed as environment variables and must be set in the Helm chart so the application can run at all. Check the Policy Hub Helm chart in Git for all available variables. + +### DB Migration File + +Static Data migration files provide a certain configuration possibility by adding or deleting static data records before the deployment. Be aware that touching static data files will always impact the application business process. It is suggested to always test the application with the planned changes carefully in INT before releasing to a productive env. + +## Disaster-Recovery + +Note: will be added soon + +## Scaling + +If the number of consumers raises, the IRS can be scaled up by using more resources for the Deployment Pod. Those resources can be used to utilize more parallel threads to handle Job execution. + +## Clustering + +Note: will be added soon + +## Monitoring + +Currently all backend services write log entries as structural data in json format. These logs can easily be monitored. There are several options to provide a stable monitoring solution, one of them is to setup loki and grafana. In this solution loki is used as a datasource and custom dashboards can be setup in grafana to monitor the services. Some general Properties to query with grafana are: + +- StatusCode - contains the status code of the response +- Elapsed - contains the time a endpoint took to response in milliseconds +- RenderedMessage - contains the log message with possible errors + +## NOTICE + +This work is licensed under the [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0). + +- SPDX-License-Identifier: Apache-2.0 +- SPDX-FileCopyrightText: 2021-2023 Contributors to the Eclipse Foundation +- Source URL: https://github.com/eclipse-tractusx/policy-hub diff --git a/docs/technical-documentation/authentication/authentication.md b/docs/technical-documentation/authentication/authentication.md new file mode 100644 index 0000000..9ed3a9d --- /dev/null +++ b/docs/technical-documentation/authentication/authentication.md @@ -0,0 +1,13 @@ +# Authentication + +The authentication process for the Policy Hub involves interaction with the central IAM (Identity and Access Management). The configuration for IAM can be customized either locally during development through secrets or within the chart for the Docker image. + +Currently, the Policy Hub performs a basic validation by checking for a valid token in the request. However, it's important to note that no permission checks are conducted at this stage. + +## NOTICE + +This work is licensed under the [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0). + +- SPDX-License-Identifier: Apache-2.0 +- SPDX-FileCopyrightText: 2021-2023 Contributors to the Eclipse Foundation +- Source URL: https://github.com/eclipse-tractusx/policy-hub diff --git a/docs/technical-documentation/database/db-view.md b/docs/technical-documentation/database/db-view.md new file mode 100644 index 0000000..b96c247 --- /dev/null +++ b/docs/technical-documentation/database/db-view.md @@ -0,0 +1,105 @@ + +# Database View + +- [Database View](#database-view) + - [Database Overview](#database-overview) + - [Database Structure](#database-structure) + - [Enum Value Tables](#enum-value-tables) + - [Mapping Tables](#mapping-tables) + - [Configuration Table](#configuration-table) + - [Attribute Mapping](#attribute-mapping) + - [Policy Information](#policy-information) + - [NOTICE](#notice) + +## Database Overview + +```mermaid +erDiagram + policies ||..|| policy_assigned_types : policy_id + policies ||..|| policy_assigned_use_case : policy_id + policies ||..|| policy_kinds : kind_id + policies ||..|| attribute_keys : attribute_key_id + policies ||..|| policy_attributes : policy_id + policy_attributes ||..|| attribute_keys : key + policies { + uuid id PK + integer kind_id FK + text left_operand_value + text technical_key + text description + boolean is_active + integer attribute_key FK + } + policy_assigned_types ||..|| policy_types : policy_type_id + policy_assigned_types { + uuid policy_id FK + integer policy_type_id FK + } + policy_types { + integer id PK + text label + bool is_active + } + policy_assigned_use_case ||..|| use_cases : use_case_id + policy_assigned_use_case { + uuid policy_id FK + integer use_case_id FK + } + use_cases{ + integer id PK + text label + bool is_active + } + policy_kinds ||..|| policy_kind_configuration : policy_kind_id + policy_kinds { + integer id PK + text label + boolean technical_enforced + } + policy_kind_configuration{ + integer policy_kind_id PK + text right_operand_value + } + attribute_keys { + uuid id PK + text label + } + policy_attributes{ + integer policy_id PK + integer key PK + text attribute_value PK + bool is_active + } +``` + +## Database Structure + +The database is organized into several key tables, each serving a specific purpose: + +### Enum Value Tables + +`attribute_keys`, `policy_kinds`, `policy_types`, and `use_cases` are tables designed to store enum values. They contain an id and label, derived from the backend enums. + +### Mapping Tables + +`policy_assigned_types` and `policy_assigned_use_cases` are used to map types and use cases to specific policies. + +### Configuration Table + +The `policy_kind_configurations` table is utilized to define specific right operand values for each policy_kind. + +### Attribute Mapping + +In the `policy_attributes` table, specific attributes are mapped to policies. This allows for multiple attributes to be assigned to a single policy. + +### Policy Information + +The `policies` table serves as the repository for comprehensive information about each policy. + +## NOTICE + +This work is licensed under the [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0). + +- SPDX-License-Identifier: Apache-2.0 +- SPDX-FileCopyrightText: 2021-2023 Contributors to the Eclipse Foundation +- Source URL: https://github.com/eclipse-tractusx/policy-hub diff --git a/docs/technical-documentation/database/seeding.md b/docs/technical-documentation/database/seeding.md new file mode 100644 index 0000000..ab92302 --- /dev/null +++ b/docs/technical-documentation/database/seeding.md @@ -0,0 +1,44 @@ +# Seeding Mechanism + +## Database Seeding + +All data for the Policy Hub is stored in the database. Due to the absence of create or update logic in the API, a seeding process has been implemented to populate the database with initial data. + +## Execution + +The seeding process is triggered by the PolicyHub.migration job. During this process, data is sourced from .json files located in a configurable directory. The default directory for the base setup is Seeder -> Data. + +## Configuration + +To specify the data to be seeded, configure the `BatchInsertSeeder`. This configuration includes the following details: + +- Database Table: Identify the target database table +- File Name: Specify the name of the .json file containing the data +- Primary Keys: The primary keys which check for existing entries + +To specify the data which should be modified within the seeding, configure the `BatchUpdateSeeder`. This configuration includes the following details: + +- Database Table: Identify the target database table +- File Name: Specify the name of the .json file containing the data +- Primary Keys: The primary keys which check for existing entries +- Where Clause: Check for the entries in the table that should be modified +- Update Entries: The function that should be executed to modify the entries. + +Currently the update seeder will only modify the is_active flag. + +## Data Integrity + +The seeder includes a check to ensure that only data not yet existing in the database is written. This prevents duplication of records. + +## Limitations + +- While the seeder is designed to add new data, it does not support deletion. Any existing records in the database will not be removed by the seeding process. +- Modifications of the enum values, currently `AttributeKeyId`, `ConstraintOperandId`, `OperatorId`, `PolicyKindId`, `PolicyTypeId` and `UseCaseId` must be made with a migration. + +## NOTICE + +This work is licensed under the [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0). + +- SPDX-License-Identifier: Apache-2.0 +- SPDX-FileCopyrightText: 2021-2023 Contributors to the Eclipse Foundation +- Source URL: https://github.com/eclipse-tractusx/policy-hub diff --git a/docs/technical-documentation/dev-process/Dev-flow_deploy-dev-env.md b/docs/technical-documentation/dev-process/Dev-flow_deploy-dev-env.md new file mode 100644 index 0000000..4db0726 --- /dev/null +++ b/docs/technical-documentation/dev-process/Dev-flow_deploy-dev-env.md @@ -0,0 +1,31 @@ +# Dev flow with deployment to dev environment + +```mermaid +flowchart LR + subgraph local + D(Developer) + end + subgraph eclipse-tractusx + direction LR + D -- PR* to dev*--> PH(policy-hub**) + click PH "https://github.com/eclipse-tractusx/policy-hub" + end + subgraph Argo CD - sync to k8s cluster + PH -- auto-sync --> A(Argo CD dev) + click A "https://argo.dev.demo.catena-x.net" + end +``` + +Note\* Every pull request (PR) requires at least one approving review by a committer + +Note\*\* Unit tests and Sonarcloud runs at pull request, Trivy and KICS scans at merge as well as daily and Veracode scan runs weekly + +Note\*\* Trivy and KICS scans are scheduled to daily + +## NOTICE + +This work is licensed under the [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0). + +- SPDX-License-Identifier: Apache-2.0 +- SPDX-FileCopyrightText: 2021-2023 Contributors to the Eclipse Foundation +- Source URL: https://github.com/eclipse-tractusx/policy-hub diff --git a/docs/technical-documentation/dev-process/Dev-flow_git-diagram.md b/docs/technical-documentation/dev-process/Dev-flow_git-diagram.md new file mode 100644 index 0000000..92be5c1 --- /dev/null +++ b/docs/technical-documentation/dev-process/Dev-flow_git-diagram.md @@ -0,0 +1,133 @@ +# Dev flow (git diagram) + +```mermaid +%%{init: { 'logLevel': 'debug', 'theme': 'base' } }%% +gitGraph + commit id: "release: v1.0.0" tag:"1.0.0" + branch dev order: 1 + checkout dev + branch feature/feature1 order: 2 + commit id:"feat(function): add feature1" + checkout dev + branch bug/bug1 order: 3 + commit id: "fix(function): change bug1" + checkout dev + branch feature/feature2 order: 4 + commit id:"feat(function)!: enable feature2" + checkout bug/bug1 + commit id:"fix(function): refactor bug1" + checkout dev + merge bug/bug1 + checkout dev + branch feature/feature3 order: 5 + commit id:"feat(function): wip - enable feature3" + checkout dev + checkout feature/feature3 + commit id: "feat(function): enable feature3" + checkout dev + merge feature/feature3 + checkout feature/feature1 + commit id:"feat(function): enable feature1" + checkout dev + merge feature/feature1 + branch release/1.1.0 order: 6 + commit id: "release(1.1.0): aggregate migrations (backend)" + commit id: "release(1.1.0): update version, changelog..." tag: "1.1.0" + checkout main + merge release/1.1.0 id: "1. merge into main" + checkout dev + merge main id: "2. merge main into dev" + checkout dev + branch feature/feature4 order: 7 + commit id: "feat(function): add feature4" + checkout feature/feature2 + commit id: "feat(function)!: change feature2" + checkout dev + merge feature/feature2 + checkout feature/feature4 + commit id: "feat(function): change feature4" + checkout dev + merge feature/feature4 + branch release/1.2.0 order: 8 + commit id: "release(1.2.0-RC1): prepare migration (backend)" + commit id: "release(1.2.0-RC1): update version, changelog..." tag: "1.2.0-RC1" + checkout main + merge release/1.2.0 + checkout dev + merge main + checkout release/1.2.0 + branch bug/bug2 order: 9 + commit id:"fix(function): change1 bug2" + checkout release/1.2.0 + branch bug/bug3 order: 10 + commit id:"fix(function): change bug3" + checkout release/1.2.0 + merge bug/bug3 + merge dev + checkout dev + branch feature/feature5 order: 11 + commit id: "feat(function): add feature5" + checkout bug/bug2 + commit id:"fix(function): change2 bug2" + checkout release/1.2.0 + merge bug/bug2 + commit id: "release(1.2.0-RC2): update version, changelog..." tag: "1.2.0-RC2" + checkout main + merge release/1.2.0 + checkout dev + merge main + checkout dev + branch feature/feature6 order: 12 + commit id: "feat(function): add feature for 1.4.0" + checkout feature/feature5 + commit id: "feat(function): change feature5" + checkout dev + merge feature/feature5 + branch release/1.3.0 order: 13 + commit id: "release(1.3.0): aggregate migrations (backend)" + commit id: "release(1.3.0): update version, changelog..." tag: "1.3.0" + checkout main + merge release/1.3.0 + checkout dev + merge main + checkout feature/feature6 + commit id: "feat(function): change feature for 1.4.0" + merge dev + checkout release/1.2.0 + branch bug/bug4 order: 14 + commit id:"fix(function): change1 bug4" + commit id:"fix(function): change2 bug4" + checkout release/1.2.0 + merge bug/bug4 + commit id: "release(1.2.0): update version, changelog..." tag: "1.2.0" + checkout main + merge release/1.2.0 + checkout dev + merge main + checkout release/1.2.0 + branch hotfix/1.2.1 order: 15 + branch bug/bug5 order: 16 + commit id:"fix(function): change1 bug5" + checkout hotfix/1.2.1 + branch bug/bug6 order: 17 + commit id:"fix(function): change bug6" + checkout hotfix/1.2.1 + merge bug/bug6 + checkout bug/bug5 + commit id:"fix(function): change2 bug5" + checkout hotfix/1.2.1 + merge bug/bug5 + commit id: "hotfix(1.2.1): update version, changelog..." tag: "1.2.1" + checkout main + merge hotfix/1.2.1 + checkout dev + merge main +``` + +## NOTICE + +This work is licensed under the [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0). + +- SPDX-License-Identifier: Apache-2.0 +- SPDX-FileCopyrightText: 2021-2023 Contributors to the Eclipse Foundation +- Source URL: https://github.com/eclipse-tractusx/policy-hub diff --git a/docs/technical-documentation/dev-process/Enumeration Handling.md b/docs/technical-documentation/dev-process/Enumeration Handling.md new file mode 100644 index 0000000..e77f773 --- /dev/null +++ b/docs/technical-documentation/dev-process/Enumeration Handling.md @@ -0,0 +1,40 @@ +## Enumeration + +Enum or enumeration are used for data type consisting of named values like elements, status workflow, types, etc., that represent integral constants. Enums are non-transactional (so called static data) which can only get changed in a new application version. Changes in the operation mode of an application are not allowed since this will result into possible system breaks. + +List of used enums in the policy hub application that are stored in the database + +- attribute_key_id +- policy_kinds +- policy_types +- use_cases + +### Add Enums + +New enums can get added easily be enhancing the enumeration table (via the seeding data). With the next deployment; the new enum is getting auto deployed to the respective env. +Since enums have an enhanced impact on the system functionality; it is mandatorily needed to test (FE wise) the impacted screens / flows before releasing new enums. It is likely that the enum has an enhanced impact on the user journey / flow and break the system if not well tested. + +### Change Enums + +Change of enums (labels) is possible but need to be done carefully and only if necessarily needed. +In the case a change is getting executed; the system configuration / appsettings / env. variables need to get checked to ensure that those don't refer to the enum which is getting changed/ updated. +Same applies to backend logic, since it might refer to the enum label and will automatically fail when an enum value is getting changed. + +### Delete Enums + +Deletion of enums have following impacts + +- Seeding data update needed (likely data need to get deleted / changed) +- Data inside the database in the different running environments need to get updated +- User flow process impacted +- Backend business logic impacted + +It is not recommended to delete enums; instead .......... to be updated; we need to define how enums can / should get changed if needed + +## NOTICE + +This work is licensed under the [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0). + +- SPDX-License-Identifier: Apache-2.0 +- SPDX-FileCopyrightText: 2021-2023 Contributors to the Eclipse Foundation +- Source URL: https://github.com/eclipse-tractusx/policy-hub diff --git a/docs/developer/Technical-Documentation/Dev-Process/How-to-contribute.md b/docs/technical-documentation/dev-process/How to contribute.md similarity index 87% rename from docs/developer/Technical-Documentation/Dev-Process/How-to-contribute.md rename to docs/technical-documentation/dev-process/How to contribute.md index f069a52..ed4f051 100644 --- a/docs/developer/Technical-Documentation/Dev-Process/How-to-contribute.md +++ b/docs/technical-documentation/dev-process/How to contribute.md @@ -1,6 +1,6 @@ # Contribution details -To contribute to the portal as part of the open source community, please read the details defined below. +To contribute to the policy hub as part of the open source community, please read the details defined below. Besides a generic "how to", some commit and pull request (PR) guidelines are defined to ensure readability and make newly created PRs easier to review. Additionally, changelogs can get validated as well as written with more ease. Moreover, similar patterns are in use across the contributor community. **Content**: @@ -100,4 +100,12 @@ The suggested naming convention is '{type}{(function)}: {short summary}' ### PR description Add details to the change, fix or feature in the PR description. -What was changed, why was it changed (e.g. which issue was fixed or which requirement was implemented), and how was it changed. \ No newline at end of file +What was changed, why was it changed (e.g. which issue was fixed or which requirement was implemented), and how was it changed. + +## NOTICE + +This work is licensed under the [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0). + +- SPDX-License-Identifier: Apache-2.0 +- SPDX-FileCopyrightText: 2021-2023 Contributors to the Eclipse Foundation +- Source URL: https://github.com/eclipse-tractusx/policy-hub diff --git a/docs/technical-documentation/release-process/Release Process.md b/docs/technical-documentation/release-process/Release Process.md new file mode 100644 index 0000000..a2256d4 --- /dev/null +++ b/docs/technical-documentation/release-process/Release Process.md @@ -0,0 +1,118 @@ +# Release Process + +The release process for a new version can roughly be divided into the following steps: + +- [Preparations on the release branch](#preparations-on-the-release-branch) +- [Update CHANGELOG.md](#update-changelogmd) +- [Tag and build of versioned images](#tag-and-build-of-versioned-images) +- [Create releases from tags](#create-releases-from-tags) +- [Merge release branch](#merge-release-branch) +- [RC: provide successive RC branch and change base of open PRs](#rc-provide-successive-rc-branch-and-change-base-of-open-prs) + +The process builds on the development flow which, usually, takes place within forks and leads to merged pull requests in the repositories of the eclipse-tractusx organization. + +For assigning and incrementing **version** numbers [Semantic Versioning](https://semver.org) is followed. + +## Preparations on the release branch + +Checking out from the dev branch a release branch (release/{to be released version} e.g. release/v1.2.0, or respectively release/v1.2.0-RC1 for a release candidate). +On the release branch the following steps are executed: + +### 1. Aggregate migrations + +Migrations should be **aggregated in the case of releasing a new version**, in order to not release the entire history of migrations which accumulate during the development process. + +Once a version has been released, migrations **mustn't be aggregated** in order to ensure upgradeability this also applies to **release candidates > RC1 and hotfixes**. +Be aware that migrations coming release branches for release candidates or from hotfix branches, will **need to be incorporated into dev and main**. + +### 2. Version bump + +The version needs to be updated in the `src` directory within the 'Directory.Build.props' file. + +Bump helm chart and image version (also for argocd-app-templates, needed for consortia-environments). + +Example for commit message: + +_release: bump version for vx.x.x_ + +### 3. Update README (on chart level) + +Use [helm-docs](https://github.com/norwoodj/helm-docs) (gotemplate driven) for updating the README file. + +```bash +helm-docs --chart-search-root [charts-dir] --sort-values-order file +``` + +Example for commit message: + +_release: update readme for vx.x.x_ + +## Update CHANGELOG.md + +The changelog file tracks all notable changes since the last released version. +Once a new version is ready to be released, the changelog gets automatically created by triggering the [release-please workflow](../../../.github/workflows/release-please.yml). + +Please see: + +- [How release please works](https://github.com/google-github-actions/release-please-action/tree/v4.0.2?tab=readme-ov-file#how-release-please-works) +- [How do I change the version number?](https://github.com/googleapis/release-please/tree/v16.7.0?tab=readme-ov-file#how-do-i-change-the-version-number) +- [How can I fix release notes?](https://github.com/googleapis/release-please/tree/v16.7.0?tab=readme-ov-file#how-can-i-fix-release-notes) + +## Tag and build of versioned images + +It's important to pull the latest state of the release branch locally. +Then create and push a tag for the released version. +The push of the tag triggers the [release workflow](../../../.github/workflows/release.yml) which creates the versioned image/s. + +Example for tag: + +_v0.1.0_ + +Examples for tag messages: + +_Version 0.1.0: Policy-Hub for Catena-X_ + +## Create releases from tags + +Create the release from the tag available in repository. + +Examples for release messages: + +_Version 0.1.0: Policy-Hub for Catena-X_ + +## Merge release branch + +The release branch must be merged into main. +Afterwards, main into dev. +Those merges need to happen via PRs. + +Example for PR titles: + +_release(1.2.0): merge release into main_ + +_release(1.2.0): merge main to dev_ + +Be aware that merge into main trigger the workflow with the [helm-chart releaser](../../../.github/workflows/chart-release.yaml). + +Besides the official chart itself, there is also created a 'policy-hub-x.x.x' tag. +This tag is used to install (with the convenience of the argocd-app-templates) or upgrade the version via AgroCD on the consortia K8s clusters. + +## RC: provide successive RC branch and change base of open PRs + +During a release candidate phase, checkout the successive 'RC' branch and push it to the server, so that it can be used for further bugfixes. + +Example: + +```bash +git checkout tags/v0.1.0-RC2 -b release/v0.1.0-RC3 +``` + +Also make sure to change the base of all open pull requests still pointing to the previous 'RC' branch to the newly pushed 'RC' branch. + +## NOTICE + +This work is licensed under the [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0). + +- SPDX-License-Identifier: Apache-2.0 +- SPDX-FileCopyrightText: 2021-2024 Contributors to the Eclipse Foundation +- Source URL: https://github.com/eclipse-tractusx/policy-hub diff --git a/scripts/add_notice_footer.sh b/scripts/add_notice_footer.sh new file mode 100644 index 0000000..c7b8cc7 --- /dev/null +++ b/scripts/add_notice_footer.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +print-usage() { + cat << EOF +# +# Add license notice to all md files +# +# usage: +# source ./scripts/add_notice_footer.sh +# cd path/to/your/documentation +# add-notice +# +EOF +} + +add-notice() { + notice_text='''## NOTICE + +This work is licensed under the [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0). + +- SPDX-License-Identifier: Apache-2.0 +- SPDX-FileCopyrightText: 2021-2023 Contributors to the Eclipse Foundation +- Source URL: https://github.com/eclipse-tractusx/policy-hub''' + + # Find all .md files in the directory and its subdirectories, excluding directories from the search + find . -type f -name "*.md" -print0 | while IFS= read -r -d '' file; do + last_line=$(tail -n 7 "$file") + + # Check if the last line of the file matches the notice text + if [ "$last_line" != "$notice_text" ]; then + # Append the notice text if it's not already there + echo -e "\n$notice_text" >> "$file" + echo "Notice added to $file" + fi + done +} + +print-usage \ No newline at end of file diff --git a/scripts/license.sh b/scripts/license.sh new file mode 100644 index 0000000..98b9401 --- /dev/null +++ b/scripts/license.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +############################################################### +# Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################### + +print-usage() { + cat << EOF +# +# Generate license files for all images in folder and subfolders +# +# usage: +# source ./scripts/license.sh +# cd path/to/your/images +# license-images +# +EOF +} + +license-images() { + for file in $(find . -type f \( -name '*.png' -o -name '*.jpg' -o -name '*.svg' \)); + do + echo $file + cat << EOF > $file.license +This work is licensed under the [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/legalcode). + +- SPDX-License-Identifier: CC-BY-4.0 +- SPDX-FileCopyrightText: Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation +- Source URL: https://github.com/eclipse-tractusx/policy-hub + +EOF + done +} + +print-usage diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 0000000..9e78a55 --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,25 @@ + + + + + 0.1.0 + rc.1 + + diff --git a/src/PolicyHub.sln b/src/PolicyHub.sln index 898d203..6c0fe51 100644 --- a/src/PolicyHub.sln +++ b/src/PolicyHub.sln @@ -12,6 +12,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PolicyHub.Entities", "datab EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PolicyHub.DbAccess", "database\PolicyHub.DbAccess\PolicyHub.DbAccess.csproj", "{F5BED39D-6419-49AD-A5E0-FAB88723285C}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{9C9DA872-893E-48BA-9DD5-025D477F6EC3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PolicyHub.DbAccess.Tests", "..\tests\database\PolicyHub.DbAccess.Tests\PolicyHub.DbAccess.Tests.csproj", "{F1551715-BECA-45B2-A71B-CAB60F2D35FE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PolicyHub.Service.Tests", "..\tests\hub\PolicyHub.Service.Tests\PolicyHub.Service.Tests.csproj", "{A337EA35-B303-4F1B-9A83-5205E2CBA69D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PolicyHub.Entities.Tests", "..\tests\database\PolicyHub.Entities.Tests\PolicyHub.Entities.Tests.csproj", "{1F4F15B3-C3D6-4030-9822-62D72B6DA1C9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -34,11 +42,26 @@ Global {F5BED39D-6419-49AD-A5E0-FAB88723285C}.Debug|Any CPU.Build.0 = Debug|Any CPU {F5BED39D-6419-49AD-A5E0-FAB88723285C}.Release|Any CPU.ActiveCfg = Release|Any CPU {F5BED39D-6419-49AD-A5E0-FAB88723285C}.Release|Any CPU.Build.0 = Release|Any CPU + {F1551715-BECA-45B2-A71B-CAB60F2D35FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F1551715-BECA-45B2-A71B-CAB60F2D35FE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F1551715-BECA-45B2-A71B-CAB60F2D35FE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F1551715-BECA-45B2-A71B-CAB60F2D35FE}.Release|Any CPU.Build.0 = Release|Any CPU + {A337EA35-B303-4F1B-9A83-5205E2CBA69D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A337EA35-B303-4F1B-9A83-5205E2CBA69D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A337EA35-B303-4F1B-9A83-5205E2CBA69D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A337EA35-B303-4F1B-9A83-5205E2CBA69D}.Release|Any CPU.Build.0 = Release|Any CPU + {1F4F15B3-C3D6-4030-9822-62D72B6DA1C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1F4F15B3-C3D6-4030-9822-62D72B6DA1C9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1F4F15B3-C3D6-4030-9822-62D72B6DA1C9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1F4F15B3-C3D6-4030-9822-62D72B6DA1C9}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {92B16AED-3229-4C46-8498-11D33E5C7F69} = {D30D713C-43E8-488F-BFBB-FD610E77ACA3} {696BC957-EF9C-4092-8F3C-E4899FC53ED8} = {6EB9F0CF-3A57-42AA-BF74-AADCF8815F90} {7C1F94B0-D401-40F1-8FE1-004016DC1E49} = {6EB9F0CF-3A57-42AA-BF74-AADCF8815F90} {F5BED39D-6419-49AD-A5E0-FAB88723285C} = {6EB9F0CF-3A57-42AA-BF74-AADCF8815F90} + {F1551715-BECA-45B2-A71B-CAB60F2D35FE} = {9C9DA872-893E-48BA-9DD5-025D477F6EC3} + {A337EA35-B303-4F1B-9A83-5205E2CBA69D} = {9C9DA872-893E-48BA-9DD5-025D477F6EC3} + {1F4F15B3-C3D6-4030-9822-62D72B6DA1C9} = {9C9DA872-893E-48BA-9DD5-025D477F6EC3} EndGlobalSection EndGlobal diff --git a/src/database/PolicyHub.DbAccess/DependencyInjection/HubRepositoriesServiceExtensions.cs b/src/database/PolicyHub.DbAccess/DependencyInjection/HubRepositoriesServiceExtensions.cs new file mode 100644 index 0000000..5eb6453 --- /dev/null +++ b/src/database/PolicyHub.DbAccess/DependencyInjection/HubRepositoriesServiceExtensions.cs @@ -0,0 +1,41 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Org.Eclipse.TractusX.PolicyHub.Entities; +using System.Diagnostics.CodeAnalysis; + +namespace Org.Eclipse.TractusX.PolicyHub.DbAccess.DependencyInjection; + +public static class HubRepositoriesServiceExtensions +{ + [ExcludeFromCodeCoverage] + public static IServiceCollection AddHubRepositories(this IServiceCollection services, IConfiguration configuration) + { + services + .AddDbContext(o => o + .UseNpgsql(configuration.GetConnectionString("PolicyHubDb"))) + .AddScoped() + .AddHealthChecks() + .AddDbContextCheck("PolicyHubContext", tags: new[] { "policydb" }); + return services; + } +} diff --git a/src/database/PolicyHub.DbAccess/HubRepositories.cs b/src/database/PolicyHub.DbAccess/HubRepositories.cs new file mode 100644 index 0000000..5baa62f --- /dev/null +++ b/src/database/PolicyHub.DbAccess/HubRepositories.cs @@ -0,0 +1,50 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.DbAccess.Repositories; +using Org.Eclipse.TractusX.PolicyHub.Entities; +using System.Collections.Immutable; + +namespace Org.Eclipse.TractusX.PolicyHub.DbAccess; + +public class HubRepositories : IHubRepositories +{ + private readonly PolicyHubContext _dbContext; + + private static readonly IReadOnlyDictionary> Types = new Dictionary> { + { typeof(IPolicyRepository), context => new PolicyRepository(context) } + }.ToImmutableDictionary(); + + public HubRepositories(PolicyHubContext policyHubContext) + { + _dbContext = policyHubContext; + } + + public RepositoryType GetInstance() + { + object? repository = default; + + if (Types.TryGetValue(typeof(RepositoryType), out var createFunc)) + { + repository = createFunc(_dbContext); + } + + return (RepositoryType)(repository ?? throw new ArgumentException($"unexpected type {typeof(RepositoryType).Name}", nameof(RepositoryType))); + } +} diff --git a/src/database/PolicyHub.DbAccess/IHubRepositories.cs b/src/database/PolicyHub.DbAccess/IHubRepositories.cs new file mode 100644 index 0000000..360c798 --- /dev/null +++ b/src/database/PolicyHub.DbAccess/IHubRepositories.cs @@ -0,0 +1,25 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +namespace Org.Eclipse.TractusX.PolicyHub.DbAccess; + +public interface IHubRepositories +{ + public T GetInstance(); +} diff --git a/src/database/PolicyHub.DbAccess/Models/PolicyTypeResponse.cs b/src/database/PolicyHub.DbAccess/Models/PolicyTypeResponse.cs new file mode 100644 index 0000000..5a691c6 --- /dev/null +++ b/src/database/PolicyHub.DbAccess/Models/PolicyTypeResponse.cs @@ -0,0 +1,34 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +namespace Org.Eclipse.TractusX.PolicyHub.DbAccess.Models; + +public record PolicyTypeResponse +( + string TechnicalKey, + IEnumerable Type, + string Description, + IEnumerable UseCase, + IEnumerable Attribute, + bool TechnicalEnforced +); + +public record PolicyAttributeResponse(AttributeKeyId Key, string Value); diff --git a/src/database/PolicyHub.DbAccess/PolicyHub.DbAccess.csproj b/src/database/PolicyHub.DbAccess/PolicyHub.DbAccess.csproj index c02cc4f..c8f8287 100644 --- a/src/database/PolicyHub.DbAccess/PolicyHub.DbAccess.csproj +++ b/src/database/PolicyHub.DbAccess/PolicyHub.DbAccess.csproj @@ -33,6 +33,8 @@ + + diff --git a/src/database/PolicyHub.DbAccess/Repositories/IPolicyRepository.cs b/src/database/PolicyHub.DbAccess/Repositories/IPolicyRepository.cs new file mode 100644 index 0000000..f21788e --- /dev/null +++ b/src/database/PolicyHub.DbAccess/Repositories/IPolicyRepository.cs @@ -0,0 +1,31 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.DbAccess.Models; +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +namespace Org.Eclipse.TractusX.PolicyHub.DbAccess.Repositories; + +public interface IPolicyRepository +{ + IAsyncEnumerable GetAttributeKeys(); + 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); +} diff --git a/src/database/PolicyHub.DbAccess/Repositories/PolicyRepository.cs b/src/database/PolicyHub.DbAccess/Repositories/PolicyRepository.cs new file mode 100644 index 0000000..e641638 --- /dev/null +++ b/src/database/PolicyHub.DbAccess/Repositories/PolicyRepository.cs @@ -0,0 +1,82 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Microsoft.EntityFrameworkCore; +using Org.Eclipse.TractusX.PolicyHub.DbAccess.Models; +using Org.Eclipse.TractusX.PolicyHub.Entities; +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +namespace Org.Eclipse.TractusX.PolicyHub.DbAccess.Repositories; + +public class PolicyRepository : IPolicyRepository +{ + private readonly PolicyHubContext _dbContext; + + public PolicyRepository(PolicyHubContext dbContext) + { + _dbContext = dbContext; + } + + public IAsyncEnumerable GetAttributeKeys() => + _dbContext.AttributeKeys + .Select(x => x.Label) + .AsAsyncEnumerable(); + + public IAsyncEnumerable GetPolicyTypes(PolicyTypeId? type, UseCaseId? useCase) => + _dbContext.Policies + .Where(p => + (type == null || p.Types.Any(x => x.Id == type)) && + (useCase == null || p.UseCases.Any(x => x.Id == useCase))) + .Select(p => new PolicyTypeResponse( + p.TechnicalKey, + p.Types.Where(t => t.IsActive).Select(t => t.Id), + p.Description, + p.UseCases.Where(u => u.IsActive).Select(u => u.Id), + p.Attributes.Where(a => a.IsActive).Select(a => new PolicyAttributeResponse(a.Key, a.AttributeValue)), + p.PolicyKind!.TechnicalEnforced + )) + .AsAsyncEnumerable(); + + public Task<(bool Exists, string LeftOperand, (AttributeKeyId? Key, IEnumerable Values) Attributes, string? RightOperandValue)> GetPolicyContentAsync(UseCaseId? useCase, PolicyTypeId type, string credential) => + _dbContext.Policies + .Where(p => + p.Types.Any(t => t.IsActive && t.Id == type) && + (useCase == null || p.UseCases.Any(x => x.Id == useCase)) && + 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)), + 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 + .Where(p => + p.Types.Any(t => t.IsActive && t.Id == type) && + technicalKeys.Contains(p.TechnicalKey)) + .Select(p => new ValueTuple>, string?>( + p.TechnicalKey, + p.LeftOperandValue ?? p.TechnicalKey, + new ValueTuple>(p.AttributeKeyId, p.AttributeKey!.PolicyAttributes.Where(pa => pa.IsActive && pa.PolicyId == p.Id).Select(a => a.AttributeValue)), + p.PolicyKind!.Configuration!.RightOperandValue + )) + .AsAsyncEnumerable(); +} diff --git a/src/database/PolicyHub.Entities/Entities/AttributeKey.cs b/src/database/PolicyHub.Entities/Entities/AttributeKey.cs new file mode 100644 index 0000000..baea888 --- /dev/null +++ b/src/database/PolicyHub.Entities/Entities/AttributeKey.cs @@ -0,0 +1,45 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +namespace Org.Eclipse.TractusX.PolicyHub.Entities.Entities; + +public class AttributeKey +{ + private AttributeKey() + { + Label = null!; + PolicyAttributes = new HashSet(); + Policies = new HashSet(); + } + + public AttributeKey(AttributeKeyId attributeKeyId) : this() + { + Id = attributeKeyId; + Label = attributeKeyId.ToString(); + } + + public AttributeKeyId Id { get; private set; } + public string Label { get; private set; } + + // Navigation properties + public virtual ICollection PolicyAttributes { get; private set; } + public virtual ICollection Policies { get; private set; } +} diff --git a/src/database/PolicyHub.Entities/Entities/ConstraintOperand.cs b/src/database/PolicyHub.Entities/Entities/ConstraintOperand.cs new file mode 100644 index 0000000..38ddce5 --- /dev/null +++ b/src/database/PolicyHub.Entities/Entities/ConstraintOperand.cs @@ -0,0 +1,39 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +namespace Org.Eclipse.TractusX.PolicyHub.Entities.Entities; + +public class ConstraintOperand +{ + private ConstraintOperand() + { + Label = null!; + } + + public ConstraintOperand(ConstraintOperandId constraintOperandId) : this() + { + Id = constraintOperandId; + Label = constraintOperandId.ToString(); + } + + public ConstraintOperandId Id { get; private set; } + public string Label { get; private set; } +} diff --git a/src/database/PolicyHub.Entities/Entities/Operator.cs b/src/database/PolicyHub.Entities/Entities/Operator.cs new file mode 100644 index 0000000..18ec733 --- /dev/null +++ b/src/database/PolicyHub.Entities/Entities/Operator.cs @@ -0,0 +1,39 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +namespace Org.Eclipse.TractusX.PolicyHub.Entities.Entities; + +public class Operator +{ + private Operator() + { + Label = null!; + } + + public Operator(OperatorId operatorId) : this() + { + Id = operatorId; + Label = operatorId.ToString(); + } + + public OperatorId Id { get; private set; } + public string Label { get; private set; } +} diff --git a/src/database/PolicyHub.Entities/Entities/Policy.cs b/src/database/PolicyHub.Entities/Entities/Policy.cs new file mode 100644 index 0000000..a1ef1d6 --- /dev/null +++ b/src/database/PolicyHub.Entities/Entities/Policy.cs @@ -0,0 +1,68 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +namespace Org.Eclipse.TractusX.PolicyHub.Entities.Entities; + +public class Policy +{ + private Policy() + { + TechnicalKey = null!; + Description = null!; + Types = new HashSet(); + Attributes = new HashSet(); + UseCases = new HashSet(); + } + + public Policy(Guid id, PolicyKindId kindId, string technicalKey, string description, bool isActive) + : this() + { + Id = id; + KindId = kindId; + TechnicalKey = technicalKey; + Description = description; + IsActive = isActive; + } + + public Guid Id { get; set; } + + public PolicyKindId KindId { get; set; } + + public string? LeftOperandValue { get; set; } + + public string TechnicalKey { get; set; } + + public string Description { get; set; } + + public bool IsActive { get; set; } + + public AttributeKeyId? AttributeKeyId { get; set; } + + public virtual PolicyKind? PolicyKind { get; set; } + + public ICollection Types { get; private set; } + + public ICollection UseCases { get; private set; } + + public virtual AttributeKey? AttributeKey { get; private set; } + + public ICollection Attributes { get; private set; } +} diff --git a/src/database/PolicyHub.Entities/Entities/PolicyAssignedTypes.cs b/src/database/PolicyHub.Entities/Entities/PolicyAssignedTypes.cs new file mode 100644 index 0000000..01a8258 --- /dev/null +++ b/src/database/PolicyHub.Entities/Entities/PolicyAssignedTypes.cs @@ -0,0 +1,45 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +namespace Org.Eclipse.TractusX.PolicyHub.Entities.Entities; + +public class PolicyAssignedTypes +{ + private PolicyAssignedTypes() + { + Policy = null!; + PolicyType = null!; + } + + public PolicyAssignedTypes(Guid policyId, PolicyTypeId policyTypeId) + : this() + { + PolicyId = policyId; + PolicyTypeId = policyTypeId; + } + + public Guid PolicyId { get; set; } + + public PolicyTypeId PolicyTypeId { get; set; } + + public virtual Policy? Policy { get; private set; } + public virtual PolicyType? PolicyType { get; private set; } +} diff --git a/src/database/PolicyHub.Entities/Entities/PolicyAssignedUseCases.cs b/src/database/PolicyHub.Entities/Entities/PolicyAssignedUseCases.cs new file mode 100644 index 0000000..932c499 --- /dev/null +++ b/src/database/PolicyHub.Entities/Entities/PolicyAssignedUseCases.cs @@ -0,0 +1,45 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +namespace Org.Eclipse.TractusX.PolicyHub.Entities.Entities; + +public class PolicyAssignedUseCases +{ + private PolicyAssignedUseCases() + { + Policy = null!; + UseCase = null!; + } + + public PolicyAssignedUseCases(Guid policyId, UseCaseId useCaseId) + : this() + { + PolicyId = policyId; + UseCaseId = useCaseId; + } + + public Guid PolicyId { get; set; } + + public UseCaseId UseCaseId { get; set; } + + public virtual Policy? Policy { get; private set; } + public virtual UseCase? UseCase { get; private set; } +} diff --git a/src/database/PolicyHub.Entities/Entities/PolicyAttribute.cs b/src/database/PolicyHub.Entities/Entities/PolicyAttribute.cs new file mode 100644 index 0000000..888114e --- /dev/null +++ b/src/database/PolicyHub.Entities/Entities/PolicyAttribute.cs @@ -0,0 +1,50 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +namespace Org.Eclipse.TractusX.PolicyHub.Entities.Entities; + +public class PolicyAttribute +{ + private PolicyAttribute() + { + AttributeValue = null!; + } + + public PolicyAttribute(Guid policyId, AttributeKeyId key, string attributeValue) + : this() + { + PolicyId = policyId; + Key = key; + AttributeValue = attributeValue; + } + + public Guid PolicyId { get; private set; } + + public AttributeKeyId Key { get; private set; } + + public string AttributeValue { get; private set; } + + public bool IsActive { get; set; } + + public virtual Policy? Policy { get; private set; } + + public virtual AttributeKey? AttributeKey { get; private set; } +} diff --git a/src/database/PolicyHub.Entities/Entities/PolicyKind.cs b/src/database/PolicyHub.Entities/Entities/PolicyKind.cs new file mode 100644 index 0000000..3b4bba8 --- /dev/null +++ b/src/database/PolicyHub.Entities/Entities/PolicyKind.cs @@ -0,0 +1,48 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; +using Org.Eclipse.TractusX.PolicyHub.Entities.Extensions; + +namespace Org.Eclipse.TractusX.PolicyHub.Entities.Entities; + +public class PolicyKind +{ + private PolicyKind() + { + Label = null!; + Policies = new HashSet(); + } + + public PolicyKind(PolicyKindId policyKindId) : this() + { + Id = policyKindId; + Label = policyKindId.ToString(); + TechnicalEnforced = policyKindId.IsTechnicalEnforced(); + } + + public PolicyKindId Id { get; private set; } + public string Label { get; private set; } + + public bool TechnicalEnforced { get; set; } + + // Navigation properties + public virtual PolicyKindConfiguration? Configuration { get; private set; } + public virtual ICollection Policies { get; private set; } +} diff --git a/src/database/PolicyHub.Entities/Entities/PolicyKindConfiguration.cs b/src/database/PolicyHub.Entities/Entities/PolicyKindConfiguration.cs new file mode 100644 index 0000000..b99f16a --- /dev/null +++ b/src/database/PolicyHub.Entities/Entities/PolicyKindConfiguration.cs @@ -0,0 +1,41 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +namespace Org.Eclipse.TractusX.PolicyHub.Entities.Entities; + +public class PolicyKindConfiguration +{ + public PolicyKindConfiguration() + { + RightOperandValue = null!; + } + + public PolicyKindConfiguration(PolicyKindId policyKindId, string rightOperandValue) + { + PolicyKindId = policyKindId; + RightOperandValue = rightOperandValue; + } + + public PolicyKindId PolicyKindId { get; set; } + + public string RightOperandValue { get; set; } + public virtual PolicyKind? PolicyKind { get; private set; } +} diff --git a/src/database/PolicyHub.Entities/Entities/PolicyType.cs b/src/database/PolicyHub.Entities/Entities/PolicyType.cs new file mode 100644 index 0000000..f712fe0 --- /dev/null +++ b/src/database/PolicyHub.Entities/Entities/PolicyType.cs @@ -0,0 +1,46 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +namespace Org.Eclipse.TractusX.PolicyHub.Entities.Entities; + +public class PolicyType +{ + private PolicyType() + { + Label = null!; + Policies = new HashSet(); + } + + public PolicyType(PolicyTypeId policyTypeId, bool isActive) : this() + { + Id = policyTypeId; + Label = policyTypeId.ToString(); + IsActive = isActive; + } + + public PolicyTypeId Id { get; private set; } + public string Label { get; private set; } + + public bool IsActive { get; set; } + + // Navigation properties + public virtual ICollection Policies { get; private set; } +} diff --git a/src/database/PolicyHub.Entities/Entities/UseCase.cs b/src/database/PolicyHub.Entities/Entities/UseCase.cs new file mode 100644 index 0000000..8e46585 --- /dev/null +++ b/src/database/PolicyHub.Entities/Entities/UseCase.cs @@ -0,0 +1,46 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +namespace Org.Eclipse.TractusX.PolicyHub.Entities.Entities; + +public class UseCase +{ + private UseCase() + { + Label = null!; + Policies = new HashSet(); + } + + public UseCase(UseCaseId useCaseId, bool isActive) : this() + { + Id = useCaseId; + Label = useCaseId.ToString(); + IsActive = isActive; + } + + public UseCaseId Id { get; private set; } + public string Label { get; private set; } + + public bool IsActive { get; set; } + + // Navigation properties + public virtual ICollection Policies { get; private set; } +} diff --git a/src/database/PolicyHub.Entities/Enums/AttributeKeyId.cs b/src/database/PolicyHub.Entities/Enums/AttributeKeyId.cs new file mode 100644 index 0000000..4af7ce3 --- /dev/null +++ b/src/database/PolicyHub.Entities/Enums/AttributeKeyId.cs @@ -0,0 +1,29 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +namespace Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +public enum AttributeKeyId +{ + Regex = 1, + Static = 2, + DynamicValue = 3, + Brands = 4, + Version = 5 +} diff --git a/src/database/PolicyHub.Entities/Enums/ConstraintOperandId.cs b/src/database/PolicyHub.Entities/Enums/ConstraintOperandId.cs new file mode 100644 index 0000000..2e87203 --- /dev/null +++ b/src/database/PolicyHub.Entities/Enums/ConstraintOperandId.cs @@ -0,0 +1,26 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +namespace Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +public enum ConstraintOperandId +{ + And = 1, + Or = 2 +} diff --git a/src/database/PolicyHub.Entities/Enums/OperatorId.cs b/src/database/PolicyHub.Entities/Enums/OperatorId.cs new file mode 100644 index 0000000..2c7fe6e --- /dev/null +++ b/src/database/PolicyHub.Entities/Enums/OperatorId.cs @@ -0,0 +1,26 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +namespace Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +public enum OperatorId +{ + Equals = 1, + In = 2 +} diff --git a/src/database/PolicyHub.Entities/Enums/PolicyKindId.cs b/src/database/PolicyHub.Entities/Enums/PolicyKindId.cs new file mode 100644 index 0000000..4dba2c8 --- /dev/null +++ b/src/database/PolicyHub.Entities/Enums/PolicyKindId.cs @@ -0,0 +1,29 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +namespace Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +public enum PolicyKindId +{ + BusinessPartnerNumber = 1, + Membership = 2, + Framework = 3, + Purpose = 4, + Dismantler = 5 +} diff --git a/src/database/PolicyHub.Entities/Enums/PolicyTypeId.cs b/src/database/PolicyHub.Entities/Enums/PolicyTypeId.cs new file mode 100644 index 0000000..8e955e6 --- /dev/null +++ b/src/database/PolicyHub.Entities/Enums/PolicyTypeId.cs @@ -0,0 +1,26 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +namespace Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +public enum PolicyTypeId +{ + Access = 1, + Usage = 2 +} diff --git a/src/database/PolicyHub.Entities/Enums/UseCaseId.cs b/src/database/PolicyHub.Entities/Enums/UseCaseId.cs new file mode 100644 index 0000000..6c89c59 --- /dev/null +++ b/src/database/PolicyHub.Entities/Enums/UseCaseId.cs @@ -0,0 +1,29 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +namespace Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +public enum UseCaseId +{ + Traceability = 1, + Quality = 2, + PCF = 3, + Behavioraltwin = 4, + Sustainability = 5 +} diff --git a/src/database/PolicyHub.Entities/Extensions/PolicyKindExtensions.cs b/src/database/PolicyHub.Entities/Extensions/PolicyKindExtensions.cs new file mode 100644 index 0000000..b03135e --- /dev/null +++ b/src/database/PolicyHub.Entities/Extensions/PolicyKindExtensions.cs @@ -0,0 +1,36 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +namespace Org.Eclipse.TractusX.PolicyHub.Entities.Extensions; + +public static class PolicyKindExtensions +{ + public static bool IsTechnicalEnforced(this PolicyKindId policyKindId) => + policyKindId switch + { + PolicyKindId.BusinessPartnerNumber => true, + PolicyKindId.Membership => true, + PolicyKindId.Framework => true, + PolicyKindId.Purpose => false, + PolicyKindId.Dismantler => true, + _ => throw new ArgumentOutOfRangeException(nameof(policyKindId), policyKindId, $"PolicyKindId {policyKindId} is not supported") + }; +} diff --git a/src/database/PolicyHub.Entities/PolicyHub.Entities.csproj b/src/database/PolicyHub.Entities/PolicyHub.Entities.csproj index 22e7fbb..11d6c43 100644 --- a/src/database/PolicyHub.Entities/PolicyHub.Entities.csproj +++ b/src/database/PolicyHub.Entities/PolicyHub.Entities.csproj @@ -33,4 +33,9 @@ + + + **/PolicyHubDbContext.cs + + diff --git a/src/database/PolicyHub.Entities/PolicyHubContext.cs b/src/database/PolicyHub.Entities/PolicyHubContext.cs new file mode 100644 index 0000000..a9b0b71 --- /dev/null +++ b/src/database/PolicyHub.Entities/PolicyHubContext.cs @@ -0,0 +1,173 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Microsoft.EntityFrameworkCore; +using Org.Eclipse.TractusX.PolicyHub.Entities.Entities; +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +namespace Org.Eclipse.TractusX.PolicyHub.Entities; + +public class PolicyHubContext : DbContext +{ + public PolicyHubContext() + { + } + + public PolicyHubContext(DbContextOptions options) + : base(options) + { + } + + public virtual DbSet AttributeKeys { get; set; } = default!; + public virtual DbSet Policies { get; set; } = default!; + public virtual DbSet PolicyAttributes { get; set; } = default!; + public virtual DbSet PolicyTypes { get; set; } = default!; + public virtual DbSet PolicyAssignedTypes { get; set; } = default!; + public virtual DbSet PolicyKinds { get; set; } = default!; + public virtual DbSet PolicyKindConfigurations { get; set; } = default!; + public virtual DbSet PolicyAssignedUseCases { get; set; } = default!; + public virtual DbSet UseCases { get; set; } = default!; + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseSnakeCaseNamingConvention(); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.HasAnnotation("Relational:Collation", "en_US.utf8"); + modelBuilder.HasDefaultSchema("policy-hub"); + + modelBuilder.Entity().HasData( + Enum.GetValues(typeof(AttributeKeyId)) + .Cast() + .Select(e => new AttributeKey(e)) + ); + + modelBuilder.Entity(entity => + { + entity.Property(x => x.IsActive).HasDefaultValue(true); + + entity.HasMany(p => p.Types) + .WithMany(pt => pt.Policies) + .UsingEntity(p => p + .HasOne(x => x.PolicyType) + .WithMany() + .HasForeignKey(x => x.PolicyTypeId) + .OnDelete(DeleteBehavior.ClientSetNull), + p => p + .HasOne(x => x.Policy) + .WithMany() + .HasForeignKey(x => x.PolicyId) + .OnDelete(DeleteBehavior.ClientSetNull), + x => + { + x.HasKey(e => new { e.PolicyId, e.PolicyTypeId }); + }); + + entity.HasMany(p => p.UseCases) + .WithMany(pt => pt.Policies) + .UsingEntity(p => p + .HasOne(x => x.UseCase) + .WithMany() + .HasForeignKey(x => x.UseCaseId) + .OnDelete(DeleteBehavior.ClientSetNull), + p => p + .HasOne(x => x.Policy) + .WithMany() + .HasForeignKey(x => x.PolicyId) + .OnDelete(DeleteBehavior.ClientSetNull), + x => + { + x.HasKey(e => new { e.PolicyId, e.UseCaseId }); + }); + + entity.HasOne(p => p.AttributeKey) + .WithMany(pt => pt.Policies) + .HasForeignKey(p => p.AttributeKeyId) + .OnDelete(DeleteBehavior.ClientSetNull); + + entity.HasOne(p => p.PolicyKind) + .WithMany(pt => pt.Policies) + .HasForeignKey(x => x.KindId) + .OnDelete(DeleteBehavior.ClientSetNull); + }); + + modelBuilder.Entity(entity => + { + entity.Property(x => x.IsActive).HasDefaultValue(true); + + entity + .HasKey(x => new { x.PolicyId, x.Key, x.AttributeValue }); + + entity + .HasOne(pa => pa.AttributeKey) + .WithMany(p => p.PolicyAttributes) + .HasForeignKey(x => x.Key); + + entity + .HasOne(pa => pa.Policy) + .WithMany(p => p.Attributes) + .HasForeignKey(x => x.PolicyId); + }); + + modelBuilder.Entity(entity => + { + entity.Property(x => x.IsActive).HasDefaultValue(true); + + entity + .HasData( + Enum.GetValues(typeof(PolicyTypeId)) + .Cast() + .Select(e => new PolicyType(e, true)) + ); + }); + + modelBuilder.Entity(entity => + { + entity.Property(x => x.IsActive).HasDefaultValue(true); + + entity + .HasData( + Enum.GetValues(typeof(UseCaseId)) + .Cast() + .Select(e => new UseCase(e, true)) + ); + }); + + modelBuilder.Entity(entity => + { + entity.HasOne(x => x.Configuration) + .WithOne(x => x.PolicyKind) + .HasForeignKey(x => x.PolicyKindId) + .OnDelete(DeleteBehavior.ClientSetNull); + + entity.HasData( + Enum.GetValues(typeof(PolicyKindId)) + .Cast() + .Select(e => new PolicyKind(e)) + ); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(x => x.PolicyKindId); + }); + } +} diff --git a/src/database/PolicyHub.Migrations/Migrations/20240122150103_0.1.0-rc.1.Designer.cs b/src/database/PolicyHub.Migrations/Migrations/20240122150103_0.1.0-rc.1.Designer.cs new file mode 100644 index 0000000..55863ac --- /dev/null +++ b/src/database/PolicyHub.Migrations/Migrations/20240122150103_0.1.0-rc.1.Designer.cs @@ -0,0 +1,484 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +// +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("20240122150103_0.1.0-rc.1")] + partial class _010rc1 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("policy-hub") + .UseCollation("en_US.utf8") + .HasAnnotation("ProductVersion", "7.0.12") + .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("PolicyId") + .HasColumnType("uuid") + .HasColumnName("policy_id"); + + b.Property("Key") + .HasColumnType("integer") + .HasColumnName("key"); + + b.Property("AttributeValue") + .HasColumnType("text") + .HasColumnName("attribute_value"); + + b.Property("IsActive") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("is_active"); + + b.HasKey("PolicyId", "Key", "AttributeValue") + .HasName("pk_policy_attributes"); + + b.HasIndex("Key") + .HasDatabaseName("ix_policy_attributes_key"); + + b.ToTable("policy_attributes", "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" + }, + new + { + Id = 3, + IsActive = true, + Label = "Purpose" + }); + }); + + 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_policy_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_attribute_key_id"); + + 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.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.PolicyKind", b => + { + b.Navigation("Configuration"); + + b.Navigation("Policies"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/database/PolicyHub.Migrations/Migrations/20240122150103_0.1.0-rc.1.cs b/src/database/PolicyHub.Migrations/Migrations/20240122150103_0.1.0-rc.1.cs new file mode 100644 index 0000000..1a5e493 --- /dev/null +++ b/src/database/PolicyHub.Migrations/Migrations/20240122150103_0.1.0-rc.1.cs @@ -0,0 +1,340 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace Org.Eclipse.TractusX.PolicyHub.Migrations.Migrations +{ + /// + public partial class _010rc1 : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.EnsureSchema( + name: "policy-hub"); + + migrationBuilder.CreateTable( + name: "attribute_keys", + schema: "policy-hub", + columns: table => new + { + id = table.Column(type: "integer", nullable: false), + label = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_attribute_keys", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "policy_kinds", + schema: "policy-hub", + columns: table => new + { + id = table.Column(type: "integer", nullable: false), + label = table.Column(type: "text", nullable: false), + technical_enforced = table.Column(type: "boolean", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_policy_kinds", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "policy_types", + schema: "policy-hub", + columns: table => new + { + id = table.Column(type: "integer", nullable: false), + label = table.Column(type: "text", nullable: false), + is_active = table.Column(type: "boolean", nullable: false, defaultValue: true) + }, + constraints: table => + { + table.PrimaryKey("pk_policy_types", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "use_cases", + schema: "policy-hub", + columns: table => new + { + id = table.Column(type: "integer", nullable: false), + label = table.Column(type: "text", nullable: false), + is_active = table.Column(type: "boolean", nullable: false, defaultValue: true) + }, + constraints: table => + { + table.PrimaryKey("pk_use_cases", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "policies", + schema: "policy-hub", + columns: table => new + { + id = table.Column(type: "uuid", nullable: false), + kind_id = table.Column(type: "integer", nullable: false), + left_operand_value = table.Column(type: "text", nullable: true), + technical_key = table.Column(type: "text", nullable: false), + description = table.Column(type: "text", nullable: false), + is_active = table.Column(type: "boolean", nullable: false, defaultValue: true), + attribute_key_id = table.Column(type: "integer", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_policies", x => x.id); + table.ForeignKey( + name: "fk_policies_attribute_keys_attribute_key_id", + column: x => x.attribute_key_id, + principalSchema: "policy-hub", + principalTable: "attribute_keys", + principalColumn: "id"); + table.ForeignKey( + name: "fk_policies_policy_kinds_policy_kind_id", + column: x => x.kind_id, + principalSchema: "policy-hub", + principalTable: "policy_kinds", + principalColumn: "id"); + }); + + migrationBuilder.CreateTable( + name: "policy_kind_configurations", + schema: "policy-hub", + columns: table => new + { + policy_kind_id = table.Column(type: "integer", nullable: false), + right_operand_value = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_policy_kind_configurations", x => x.policy_kind_id); + table.ForeignKey( + name: "fk_policy_kind_configurations_policy_kinds_policy_kind_id", + column: x => x.policy_kind_id, + principalSchema: "policy-hub", + principalTable: "policy_kinds", + principalColumn: "id"); + }); + + migrationBuilder.CreateTable( + name: "policy_assigned_types", + schema: "policy-hub", + columns: table => new + { + policy_id = table.Column(type: "uuid", nullable: false), + policy_type_id = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_policy_assigned_types", x => new { x.policy_id, x.policy_type_id }); + table.ForeignKey( + name: "fk_policy_assigned_types_policies_policy_id", + column: x => x.policy_id, + principalSchema: "policy-hub", + principalTable: "policies", + principalColumn: "id"); + table.ForeignKey( + name: "fk_policy_assigned_types_policy_types_policy_type_id", + column: x => x.policy_type_id, + principalSchema: "policy-hub", + principalTable: "policy_types", + principalColumn: "id"); + }); + + migrationBuilder.CreateTable( + name: "policy_assigned_use_cases", + schema: "policy-hub", + columns: table => new + { + policy_id = table.Column(type: "uuid", nullable: false), + use_case_id = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_policy_assigned_use_cases", x => new { x.policy_id, x.use_case_id }); + table.ForeignKey( + name: "fk_policy_assigned_use_cases_policies_policy_id", + column: x => x.policy_id, + principalSchema: "policy-hub", + principalTable: "policies", + principalColumn: "id"); + table.ForeignKey( + name: "fk_policy_assigned_use_cases_use_cases_use_case_id", + column: x => x.use_case_id, + principalSchema: "policy-hub", + principalTable: "use_cases", + principalColumn: "id"); + }); + + migrationBuilder.CreateTable( + name: "policy_attributes", + schema: "policy-hub", + columns: table => new + { + policy_id = table.Column(type: "uuid", nullable: false), + key = table.Column(type: "integer", nullable: false), + attribute_value = table.Column(type: "text", nullable: false), + is_active = table.Column(type: "boolean", nullable: false, defaultValue: true) + }, + constraints: table => + { + table.PrimaryKey("pk_policy_attributes", x => new { x.policy_id, x.key, x.attribute_value }); + table.ForeignKey( + name: "fk_policy_attributes_attribute_keys_attribute_key_id", + column: x => x.key, + principalSchema: "policy-hub", + principalTable: "attribute_keys", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "fk_policy_attributes_policies_policy_id", + column: x => x.policy_id, + principalSchema: "policy-hub", + principalTable: "policies", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.InsertData( + schema: "policy-hub", + table: "attribute_keys", + columns: new[] { "id", "label" }, + values: new object[,] + { + { 1, "Regex" }, + { 2, "Static" }, + { 3, "DynamicValue" }, + { 4, "Brands" }, + { 5, "Version" } + }); + + migrationBuilder.InsertData( + schema: "policy-hub", + table: "policy_kinds", + columns: new[] { "id", "label", "technical_enforced" }, + values: new object[,] + { + { 1, "BusinessPartnerNumber", true }, + { 2, "Membership", true }, + { 3, "Framework", true }, + { 4, "Purpose", false }, + { 5, "Dismantler", true } + }); + + migrationBuilder.InsertData( + schema: "policy-hub", + table: "policy_types", + columns: new[] { "id", "is_active", "label" }, + values: new object[,] + { + { 1, true, "Access" }, + { 2, true, "Usage" } + }); + + migrationBuilder.InsertData( + schema: "policy-hub", + table: "use_cases", + columns: new[] { "id", "is_active", "label" }, + values: new object[,] + { + { 1, true, "Traceability" }, + { 2, true, "Quality" }, + { 3, true, "PCF" }, + { 4, true, "Behavioraltwin" }, + { 5, true, "Sustainability" } + }); + + migrationBuilder.CreateIndex( + name: "ix_policies_attribute_key_id", + schema: "policy-hub", + table: "policies", + column: "attribute_key_id"); + + migrationBuilder.CreateIndex( + name: "ix_policies_kind_id", + schema: "policy-hub", + table: "policies", + column: "kind_id"); + + migrationBuilder.CreateIndex( + name: "ix_policy_assigned_types_policy_type_id", + schema: "policy-hub", + table: "policy_assigned_types", + column: "policy_type_id"); + + migrationBuilder.CreateIndex( + name: "ix_policy_assigned_use_cases_use_case_id", + schema: "policy-hub", + table: "policy_assigned_use_cases", + column: "use_case_id"); + + migrationBuilder.CreateIndex( + name: "ix_policy_attributes_key", + schema: "policy-hub", + table: "policy_attributes", + column: "key"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "policy_assigned_types", + schema: "policy-hub"); + + migrationBuilder.DropTable( + name: "policy_assigned_use_cases", + schema: "policy-hub"); + + migrationBuilder.DropTable( + name: "policy_attributes", + schema: "policy-hub"); + + migrationBuilder.DropTable( + name: "policy_kind_configurations", + schema: "policy-hub"); + + migrationBuilder.DropTable( + name: "policy_types", + schema: "policy-hub"); + + migrationBuilder.DropTable( + name: "use_cases", + schema: "policy-hub"); + + migrationBuilder.DropTable( + name: "policies", + schema: "policy-hub"); + + migrationBuilder.DropTable( + name: "attribute_keys", + schema: "policy-hub"); + + migrationBuilder.DropTable( + name: "policy_kinds", + schema: "policy-hub"); + } + } +} diff --git a/src/database/PolicyHub.Migrations/Migrations/PolicyHubContextModelSnapshot.cs b/src/database/PolicyHub.Migrations/Migrations/PolicyHubContextModelSnapshot.cs new file mode 100644 index 0000000..a4563f1 --- /dev/null +++ b/src/database/PolicyHub.Migrations/Migrations/PolicyHubContextModelSnapshot.cs @@ -0,0 +1,471 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +// + +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Org.Eclipse.TractusX.PolicyHub.Entities; + +namespace Org.Eclipse.TractusX.PolicyHub.Migrations.Migrations +{ + [DbContext(typeof(PolicyHubContext))] + partial class PolicyHubContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("policy-hub") + .UseCollation("en_US.utf8") + .HasAnnotation("ProductVersion", "7.0.12") + .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("PolicyId") + .HasColumnType("uuid") + .HasColumnName("policy_id"); + + b.Property("Key") + .HasColumnType("integer") + .HasColumnName("key"); + + b.Property("AttributeValue") + .HasColumnType("text") + .HasColumnName("attribute_value"); + + b.Property("IsActive") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("is_active"); + + b.HasKey("PolicyId", "Key", "AttributeValue") + .HasName("pk_policy_attributes"); + + b.HasIndex("Key") + .HasDatabaseName("ix_policy_attributes_key"); + + b.ToTable("policy_attributes", "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_policy_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_attribute_key_id"); + + 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.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.PolicyKind", b => + { + b.Navigation("Configuration"); + + b.Navigation("Policies"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/database/PolicyHub.Migrations/PolicyHub.Migrations.csproj b/src/database/PolicyHub.Migrations/PolicyHub.Migrations.csproj index 5fcc4ba..b9d63fd 100644 --- a/src/database/PolicyHub.Migrations/PolicyHub.Migrations.csproj +++ b/src/database/PolicyHub.Migrations/PolicyHub.Migrations.csproj @@ -45,6 +45,8 @@ + + diff --git a/src/database/PolicyHub.Migrations/Program.cs b/src/database/PolicyHub.Migrations/Program.cs index 7b19d75..a90acc9 100644 --- a/src/database/PolicyHub.Migrations/Program.cs +++ b/src/database/PolicyHub.Migrations/Program.cs @@ -17,6 +17,42 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Org.Eclipse.TractusX.PolicyHub.Entities; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Logging; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Seeding.DependencyInjection; +using Serilog; +using System.Reflection; -Host.CreateDefaultBuilder(args).Build().Run(); +LoggingExtensions.EnsureInitialized(); +Log.Information("Starting process"); +try +{ + var host = Host.CreateDefaultBuilder(args) + .ConfigureServices((hostContext, services) => + { + services + .AddDbContext(o => + o.UseNpgsql(hostContext.Configuration.GetConnectionString("PolicyHubDb"), + x => x.MigrationsAssembly(Assembly.GetExecutingAssembly().GetName().Name) + .MigrationsHistoryTable("__efmigrations_history_hub", "public"))) + .AddDatabaseInitializer(hostContext.Configuration.GetSection("Seeding")); + }) + .AddLogging() + .Build(); + + await host.Services.InitializeDatabasesAsync(); // We don't actually run anything here. The magic happens in InitializeDatabasesAsync +} +catch (Exception ex) when (!ex.GetType().Name.Equals("StopTheHostException", StringComparison.Ordinal)) +{ + Log.Fatal("Unhandled exception {Exception}", ex); + throw; +} +finally +{ + Log.Information("Process Shutting down..."); + Log.CloseAndFlush(); +} diff --git a/src/database/PolicyHub.Migrations/Seeder/BatchInsertSeeder.cs b/src/database/PolicyHub.Migrations/Seeder/BatchInsertSeeder.cs new file mode 100644 index 0000000..ba580a2 --- /dev/null +++ b/src/database/PolicyHub.Migrations/Seeder/BatchInsertSeeder.cs @@ -0,0 +1,90 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +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 BatchInsertSeeder : ICustomSeeder +{ + private readonly PolicyHubContext _context; + private readonly ILogger _logger; + private readonly SeederSettings _settings; + + /// + /// Constructor + /// + /// The database context + /// The logger + /// The options + public BatchInsertSeeder(PolicyHubContext context, ILogger logger, IOptions options) + { + _context = context; + _logger = logger; + _settings = options.Value; + } + + /// + public int Order => 1; + + /// + 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 => new { x.PolicyId, x.Key, x.AttributeValue }, 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 _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); + if (data.Any()) + { + var typeName = typeof(T).Name; + _logger.LogDebug("Started to Seed {TableName}", typeName); + data = data.GroupJoin(_context.Set(), keySelector, keySelector, (d, dbEntry) => new { d, dbEntry }) + .SelectMany(t => t.dbEntry.DefaultIfEmpty(), (t, x) => new { t, x }) + .Where(t => t.x == null) + .Select(t => t.t.d).ToList(); + _logger.LogDebug("Seeding {DataCount} {TableName}", data.Count, typeName); + await _context.Set().AddRangeAsync(data, cancellationToken).ConfigureAwait(false); + _logger.LogDebug("Seeded {TableName}", typeName); + } + } +} diff --git a/src/database/PolicyHub.Migrations/Seeder/BatchUpdateSeeder.cs b/src/database/PolicyHub.Migrations/Seeder/BatchUpdateSeeder.cs new file mode 100644 index 0000000..ff172d4 --- /dev/null +++ b/src/database/PolicyHub.Migrations/Seeder/BatchUpdateSeeder.cs @@ -0,0 +1,91 @@ +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 modify the is_active flag of the configured entities +/// +public class BatchUpdateSeeder : ICustomSeeder +{ + private readonly PolicyHubContext _context; + private readonly ILogger _logger; + private readonly SeederSettings _settings; + + /// + /// Constructor + /// + /// The database context + /// The logger + /// The options + public BatchUpdateSeeder(PolicyHubContext context, ILogger logger, IOptions options) + { + _context = context; + _logger = logger; + _settings = options.Value; + } + + /// + public int Order => 2; + + /// + 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(BatchUpdateSeeder)); + return; + } + + _logger.LogInformation("Start BaseEntityBatch Seeder"); + await SeedTable( + "policies", + x => new { x.Id }, + x => x.dbEntity.IsActive != x.dataEntity.IsActive, + (dbEntity, entity) => + { + dbEntity.IsActive = entity.IsActive; + }, cancellationToken).ConfigureAwait(false); + + await SeedTable( + "policy_attributes", + x => new { x.PolicyId, x.Key, x.AttributeValue }, + x => x.dbEntity.IsActive != x.dataEntity.IsActive, + (dbEntry, entry) => + { + dbEntry.IsActive = entry.IsActive; + }, cancellationToken).ConfigureAwait(false); + + await _context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); + _logger.LogInformation("Finished BaseEntityBatch Seeder"); + } + + private async Task SeedTable(string fileName, Func keySelector, Func<(T dataEntity, T dbEntity), bool> whereClause, Action updateEntries, 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); + if (data.Any()) + { + var typeName = typeof(T).Name; + var entriesForUpdate = data + .Join(_context.Set(), keySelector, keySelector, (dataEntry, dbEntry) => (DataEntry: dataEntry, DbEntry: dbEntry)) + .Where(whereClause.Invoke) + .ToList(); + if (entriesForUpdate.Any()) + { + _logger.LogDebug("Started to Update {EntryCount} entries of {TableName}", entriesForUpdate.Count, typeName); + foreach (var entry in entriesForUpdate) + { + updateEntries.Invoke(entry.DbEntry, entry.DataEntry); + } + + _logger.LogDebug("Updated {TableName}", typeName); + } + } + } +} diff --git a/src/database/PolicyHub.Migrations/Seeder/Data/policies.json b/src/database/PolicyHub.Migrations/Seeder/Data/policies.json new file mode 100644 index 0000000..cdfdb02 --- /dev/null +++ b/src/database/PolicyHub.Migrations/Seeder/Data/policies.json @@ -0,0 +1,91 @@ +[ + { + "id": "01a0fba3-9b6e-435a-b045-e0e890c300b1", + "kind_id": 1, + "technical_key": "BusinessPartnerNumber", + "description": "The business partner number restriction can get used to define which exact business partners (based on BPNL) are allowed to view or negotiate the respective data offer. Please ensure that you add minimum one 16-digit BPNL Number in the rightOperand; wildcards are not supported.", + "is_active": true, + "attribute_key_id": 1 + }, + { + "id": "01a0fba3-9b6e-435a-b045-e0e890c300b2", + "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.", + "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}\"", + "is_active": true, + "attribute_key_id": 5 + }, + { + "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}\"", + "is_active": true, + "attribute_key_id": 5 + }, + { + "id": "01a0fba3-9b6e-435a-b045-e0e890c300b6", + "kind_id": 3, + "technical_key": "FrameworkAgreement.behavioraltwin", + "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", + "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.", + "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 new file mode 100644 index 0000000..acd5385 --- /dev/null +++ b/src/database/PolicyHub.Migrations/Seeder/Data/policy_assigned_types.json @@ -0,0 +1,16 @@ +[ + { "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-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 } +] 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 new file mode 100644 index 0000000..dd48519 --- /dev/null +++ b/src/database/PolicyHub.Migrations/Seeder/Data/policy_assigned_use_cases.json @@ -0,0 +1,25 @@ +[ + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b1", "use_case_id": 1, "is_active": true }, + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b1", "use_case_id": 2, "is_active": true }, + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b1", "use_case_id": 3, "is_active": true }, + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b1", "use_case_id": 4, "is_active": true }, + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b1", "use_case_id": 5, "is_active": true }, + { "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b2", "use_case_id": 1, "is_active": true }, + { "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-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 } +] diff --git a/src/database/PolicyHub.Migrations/Seeder/Data/policy_attributes.json b/src/database/PolicyHub.Migrations/Seeder/Data/policy_attributes.json new file mode 100644 index 0000000..8afec65 --- /dev/null +++ b/src/database/PolicyHub.Migrations/Seeder/Data/policy_attributes.json @@ -0,0 +1,92 @@ +[ + { + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b1", + "key": 1, + "attribute_value": "^BPNL[\\w|\\d]{12}$", + "is_active": true + }, + { + "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", + "is_active": true + }, + { + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b3", + "key": 5, + "attribute_value": "1.1", + "is_active": true + }, + { + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b3", + "key": 5, + "attribute_value": "1.2", + "is_active": true + }, + { + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b4", + "key": 5, + "attribute_value": "1.0", + "is_active": true + }, + { + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b5", + "key": 5, + "attribute_value": "1.0", + "is_active": true + }, + { + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b6", + "key": 5, + "attribute_value": "1.0", + "is_active": true + }, + { + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b7", + "key": 2, + "attribute_value": "purpose.trace.v1.TraceBattery", + "is_active": true + }, + { + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b8", + "key": 2, + "attribute_value": "purpose.trace.v1.aspects", + "is_active": true + }, + { + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300b9", + "key": 2, + "attribute_value": "purpose.trace.v1.qualityanalysis", + "is_active": true + }, + { + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c1", + "key": 4, + "attribute_value": "BMW", + "is_active": true + }, + { + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c1", + "key": 4, + "attribute_value": "Audi", + "is_active": true + }, + { + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c1", + "key": 4, + "attribute_value": "VW", + "is_active": true + }, + { + "policy_id": "01a0fba3-9b6e-435a-b045-e0e890c300c2", + "key": 2, + "attribute_value": "ID Trace 3.1", + "is_active": true + } +] diff --git a/src/database/PolicyHub.Migrations/Seeder/Data/policy_kind_configurations.json b/src/database/PolicyHub.Migrations/Seeder/Data/policy_kind_configurations.json new file mode 100644 index 0000000..f47fb46 --- /dev/null +++ b/src/database/PolicyHub.Migrations/Seeder/Data/policy_kind_configurations.json @@ -0,0 +1,3 @@ +[ + { "policy_kind_id": 3, "right_operand_value": "active:{0}" } +] diff --git a/src/database/PolicyHub.Migrations/appsettings.json b/src/database/PolicyHub.Migrations/appsettings.json index 8eb98c2..4d8c8dc 100644 --- a/src/database/PolicyHub.Migrations/appsettings.json +++ b/src/database/PolicyHub.Migrations/appsettings.json @@ -25,7 +25,7 @@ } }, "ConnectionStrings": { - "PolicyHubDb": "Server=placeholder;Database=placeholder;Port=5432;User Id=placeholder;Password=placeholder;Ssl Mode=Disable;" + "PolicyHubDb": "placeholder" }, "Seeding": { "DataPaths": [ diff --git a/src/hub/PolicyHub.Service/Authentication/KeycloakClaimsTransformation.cs b/src/hub/PolicyHub.Service/Authentication/KeycloakClaimsTransformation.cs new file mode 100644 index 0000000..c81c94a --- /dev/null +++ b/src/hub/PolicyHub.Service/Authentication/KeycloakClaimsTransformation.cs @@ -0,0 +1,77 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.Extensions.Options; +using System.Json; +using System.Security.Claims; + +namespace Org.Eclipse.TractusX.PolicyHub.Service.Authentication; + +public class KeycloakClaimsTransformation : IClaimsTransformation +{ + private readonly JwtBearerOptions _options; + public const string ResourceAccess = "resource_access"; + + public KeycloakClaimsTransformation(IOptions options) + { + _options = options.Value; + } + + public Task TransformAsync(ClaimsPrincipal principal) + { + var claimsIdentity = new ClaimsIdentity(); + if (AddRoles(principal, claimsIdentity)) + { + principal.AddIdentity(claimsIdentity); + } + + return Task.FromResult(principal); + } + + private bool AddRoles(ClaimsPrincipal principal, ClaimsIdentity claimsIdentity) + { + var resourceAccess = principal.Claims + .FirstOrDefault(claim => claim is { Type: ResourceAccess, ValueType: "JSON" })?.Value; + if (resourceAccess == null || + !((JsonValue.Parse(resourceAccess) as JsonObject)?.TryGetValue( + _options.TokenValidationParameters.ValidAudience, + out var audience) ?? false) || + !((audience as JsonObject)?.TryGetValue("roles", out var roles) ?? false) || + roles is not JsonArray) + { + return false; + } + + var rolesAdded = false; + foreach (JsonValue role in roles) + { + if (role.JsonType != JsonType.String) + { + continue; + } + + claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, role)); + rolesAdded = true; + } + + return rolesAdded; + } +} diff --git a/src/hub/PolicyHub.Service/BusinessLogic/IPolicyHubBusinessLogic.cs b/src/hub/PolicyHub.Service/BusinessLogic/IPolicyHubBusinessLogic.cs new file mode 100644 index 0000000..0318b24 --- /dev/null +++ b/src/hub/PolicyHub.Service/BusinessLogic/IPolicyHubBusinessLogic.cs @@ -0,0 +1,33 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.DbAccess.Models; +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; +using Org.Eclipse.TractusX.PolicyHub.Service.Models; +using Org.Eclipse.TractusX.Portal.Backend.Framework.DependencyInjection; + +namespace Org.Eclipse.TractusX.PolicyHub.Service.BusinessLogic; + +public interface IPolicyHubBusinessLogic : ITransient +{ + IAsyncEnumerable GetAttributeKeys(); + IAsyncEnumerable GetPolicyTypes(PolicyTypeId? type, UseCaseId? useCase); + Task GetPolicyContentWithFiltersAsync(UseCaseId? useCase, PolicyTypeId type, string credential, OperatorId operatorId, string? value); + Task GetPolicyContentAsync(PolicyContentRequest requestData); +} diff --git a/src/hub/PolicyHub.Service/BusinessLogic/PolicyHubBusinessLogic.cs b/src/hub/PolicyHub.Service/BusinessLogic/PolicyHubBusinessLogic.cs new file mode 100644 index 0000000..c888798 --- /dev/null +++ b/src/hub/PolicyHub.Service/BusinessLogic/PolicyHubBusinessLogic.cs @@ -0,0 +1,176 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +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.Enums; +using Org.Eclipse.TractusX.PolicyHub.Service.Extensions; +using Org.Eclipse.TractusX.PolicyHub.Service.Models; +using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Library; +using System.Text.RegularExpressions; + +namespace Org.Eclipse.TractusX.PolicyHub.Service.BusinessLogic; + +public class PolicyHubBusinessLogic : IPolicyHubBusinessLogic +{ + private readonly IHubRepositories _hubRepositories; + + public PolicyHubBusinessLogic(IHubRepositories hubRepositories) + { + _hubRepositories = hubRepositories; + } + + public IAsyncEnumerable GetAttributeKeys() => + _hubRepositories.GetInstance().GetAttributeKeys(); + + public IAsyncEnumerable GetPolicyTypes(PolicyTypeId? type, UseCaseId? 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); + if (!exists) + { + throw new NotFoundException($"Policy for type {type} and technicalKey {credential} does not exists"); + } + + var rightOperands = attributes.Values.Select(a => rightOperandValue != null ? string.Format(rightOperandValue, a) : a); + if (attributes.Key == null && rightOperandValue == null) + { + throw new UnexpectedConditionException("There must be one configured rightOperand value"); + } + + var (rightOperand, additionalAttribute) = attributes.Key != null ? + GetRightOperand(operatorId, attributes, rightOperands, value, leftOperand) : + (rightOperandValue!, null); + + return new PolicyResponse(CreateFileContent(type, operatorId, 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) => + 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, null) + }; + + private static object GetRegexValue((AttributeKeyId? Key, IEnumerable Values) attributes, string? value) + { + if (string.IsNullOrWhiteSpace(value)) + { + throw new ControllerArgumentException("you must provide a value for the regex", nameof(value)); + } + + if (attributes.Values.Count() != 1) + { + throw new UnexpectedConditionException("There should only be one regex pattern defined"); + } + + if (!Regex.IsMatch(value, attributes.Values.Single(), RegexOptions.Compiled, TimeSpan.FromSeconds(1))) + { + throw new ControllerArgumentException($"The provided value {value} does not match the regex pattern {attributes.Values.Single()}", nameof(value)); + } + + return value; + } + + private static PolicyFileContent CreateFileContent(PolicyTypeId type, OperatorId operatorId, string leftOperand, object rightOperand) => + new( + GetContext(), + "Offer", + "....", + new Permission( + type.TypeToJsonString(), + new Constraint( + null, + null, + leftOperand, + operatorId.OperatorToJsonString(), + rightOperand + ) + )); + + public async Task GetPolicyContentAsync(PolicyContentRequest requestData) + { + var keyCounts = requestData.Constraints + .GroupBy(pair => pair.Key) + .ToDictionary(group => group.Key, group => group.Count()); + var multipleDefinedKey = keyCounts.Where(x => x.Value != 1); + if (multipleDefinedKey.Any()) + { + 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); + 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"); + } + + var constraints = new List(); + List? additionalAttributes = null; + foreach (var policy in policies) + { + var constraint = requestData.Constraints.Single(x => x.Key == policy.TechnicalKey); + var rightOperands = policy.Attributes.Values.Select(a => policy.RightOperandValue != null ? string.Format(policy.RightOperandValue, a) : a); + if (policy.Attributes.Key == null && policy.RightOperandValue == null) + { + 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) + { + additionalAttributes ??= new List(); + additionalAttributes.Add(additionalAttribute); + } + + constraints.Add(new Constraint(null, + null, + policy.LeftOperand, + constraint.Operator.OperatorToJsonString(), + rightOperand + )); + } + + var permission = new Permission( + requestData.PolicyType.TypeToJsonString(), + new Constraint( + requestData.ConstraintOperand == ConstraintOperandId.And ? constraints : null, + requestData.ConstraintOperand == ConstraintOperandId.Or ? constraints : null, + null, + null, + null)); + var content = new PolicyFileContent( + GetContext(), + "Offer", + "....", + permission); + + return new PolicyResponse(content, additionalAttributes); + } + + private static IEnumerable GetContext() => new object[] { "https://www.w3.org/ns/odrl.jsonld", new { cx = "https://w3id.org/catenax/v0.0.1/ns/" } }; +} diff --git a/src/hub/PolicyHub.Service/Controllers/PolicyHubController.cs b/src/hub/PolicyHub.Service/Controllers/PolicyHubController.cs new file mode 100644 index 0000000..0b6e5ea --- /dev/null +++ b/src/hub/PolicyHub.Service/Controllers/PolicyHubController.cs @@ -0,0 +1,87 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Microsoft.AspNetCore.Mvc; +using Org.Eclipse.TractusX.PolicyHub.DbAccess.Models; +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; +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.Library; +using System.Diagnostics.CodeAnalysis; + +namespace Org.Eclipse.TractusX.PolicyHub.Service.Controllers; + +/// +/// Creates a new instance of +/// +public static class PolicyHubController +{ + [ExcludeFromCodeCoverage] + public static RouteGroupBuilder MapPolicyHubApi(this RouteGroupBuilder group) + { + var policyHub = group.MapGroup("/policy-hub"); + + policyHub.MapGet("policy-attributes", (IPolicyHubBusinessLogic logic) => logic.GetAttributeKeys()) + .WithSwaggerDescription("Gets the keys for the attributes", + "Example: GET: api/policy-hub/policy-attributes") + .RequireAuthorization() + .WithDefaultResponses() + .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", + "Example: GET: api/policy-hub/policy-types", + "OPTIONAL: Type to filter the response", + "OPTIONAL: UseCase to filter the response") + .RequireAuthorization() + .WithDefaultResponses() + .Produces(StatusCodes.Status200OK, typeof(PolicyTypeResponse), Constants.JsonContentType); + + policyHub.MapGet("policy-content", + (UseCaseId? useCase, + PolicyTypeId type, + string credential, + OperatorId operatorId, + string? value, + IPolicyHubBusinessLogic logic) => logic.GetPolicyContentWithFiltersAsync(useCase, type, credential, operatorId, value)) + .WithSwaggerDescription("Gets the content for a specific policy type", + "Example: GET: api/policy-hub/policy-content", + "OPTIONAL: The use case", + "Type of the policy to get the content for", + "The technical key of the policy", + "The operator of the left and right operand", + "OPTIONAL: Value for dynamic or regex operands") + .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", + "Example: POST: api/policy-hub/policy-content", + "Request data with the configuration of the constraints") + .RequireAuthorization() + .WithDefaultResponses() + .Produces(StatusCodes.Status200OK, typeof(PolicyResponse), Constants.JsonContentType) + .Produces(StatusCodes.Status404NotFound, typeof(ErrorResponse), Constants.JsonContentType); + + return group; + } +} diff --git a/src/hub/PolicyHub.Service/Extensions/JsonGenerationExtensions.cs b/src/hub/PolicyHub.Service/Extensions/JsonGenerationExtensions.cs new file mode 100644 index 0000000..1e21746 --- /dev/null +++ b/src/hub/PolicyHub.Service/Extensions/JsonGenerationExtensions.cs @@ -0,0 +1,41 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; + +namespace Org.Eclipse.TractusX.PolicyHub.Service.Extensions; + +public static class JsonGenerationExtensions +{ + public static string TypeToJsonString(this PolicyTypeId type) => + type switch + { + PolicyTypeId.Access => "access", + PolicyTypeId.Usage => "use", + _ => throw new ArgumentOutOfRangeException(nameof(type), type, $"{type} is not a valid value") + }; + + public static string OperatorToJsonString(this OperatorId type) => + type switch + { + OperatorId.Equals => "eq", + OperatorId.In => "in", + _ => throw new ArgumentOutOfRangeException(nameof(type), type, $"{type} is not a valid value") + }; +} diff --git a/src/hub/PolicyHub.Service/Extensions/RouteHandlerBuilderExtensions.cs b/src/hub/PolicyHub.Service/Extensions/RouteHandlerBuilderExtensions.cs new file mode 100644 index 0000000..028f875 --- /dev/null +++ b/src/hub/PolicyHub.Service/Extensions/RouteHandlerBuilderExtensions.cs @@ -0,0 +1,48 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Library; +using System.Diagnostics.CodeAnalysis; + +namespace Org.Eclipse.TractusX.PolicyHub.Service.Extensions; + +[ExcludeFromCodeCoverage] +public static class RouteHandlerBuilderExtensions +{ + public static RouteHandlerBuilder WithSwaggerDescription(this RouteHandlerBuilder builder, string summary, string description, params string[] parameterDescriptions) => + builder.WithOpenApi(op => + { + op.Summary = summary; + op.Description = description; + for (var i = 0; i < parameterDescriptions.Length; i++) + { + if (i < op.Parameters.Count) + { + op.Parameters[i].Description = parameterDescriptions[i]; + } + } + + return op; + }); + + public static RouteHandlerBuilder WithDefaultResponses(this RouteHandlerBuilder builder) => + builder + .Produces(StatusCodes.Status401Unauthorized, typeof(ErrorResponse), contentType: "application/json") + .Produces(StatusCodes.Status500InternalServerError, typeof(ErrorResponse), "application/json"); +} diff --git a/src/hub/PolicyHub.Service/Models/Constants.cs b/src/hub/PolicyHub.Service/Models/Constants.cs new file mode 100644 index 0000000..dd3c055 --- /dev/null +++ b/src/hub/PolicyHub.Service/Models/Constants.cs @@ -0,0 +1,25 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +namespace Org.Eclipse.TractusX.PolicyHub.Service.Models; + +public static class Constants +{ + public const string JsonContentType = "application/json"; +} diff --git a/src/hub/PolicyHub.Service/Models/PolicyContentRequest.cs b/src/hub/PolicyHub.Service/Models/PolicyContentRequest.cs new file mode 100644 index 0000000..a5d473b --- /dev/null +++ b/src/hub/PolicyHub.Service/Models/PolicyContentRequest.cs @@ -0,0 +1,35 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; +using System.Text.Json.Serialization; + +namespace Org.Eclipse.TractusX.PolicyHub.Service.Models; + +public record PolicyContentRequest( + [property: JsonPropertyName("policyType")] PolicyTypeId PolicyType, + [property: JsonPropertyName("constraintOperand")] ConstraintOperandId ConstraintOperand, + [property: JsonPropertyName("constraints")] IEnumerable Constraints +); + +public record Constraints( + [property: JsonPropertyName("key")] string Key, + [property: JsonPropertyName("operator")] OperatorId Operator, + [property: JsonPropertyName("value"), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] string? Value +); diff --git a/src/hub/PolicyHub.Service/Models/PolicyFileContent.cs b/src/hub/PolicyHub.Service/Models/PolicyFileContent.cs new file mode 100644 index 0000000..435e1f4 --- /dev/null +++ b/src/hub/PolicyHub.Service/Models/PolicyFileContent.cs @@ -0,0 +1,55 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using System.Text.Json.Serialization; + +namespace Org.Eclipse.TractusX.PolicyHub.Service.Models; + +public record PolicyResponse( + [property: JsonPropertyName("content")] PolicyFileContent Content, + [property: JsonPropertyName("attributes"), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] IEnumerable? AdditionalAttributes +); + +public record AdditionalAttributes( + [property: JsonPropertyName("key")] string Key, + [property: JsonPropertyName("possibleValues")] IEnumerable PossibleValues +); + +public record PolicyFileContent +( + [property: JsonPropertyName("@context")] IEnumerable Context, + [property: JsonPropertyName("@type")] string Type, + [property: JsonPropertyName("@id")] string Id, + [property: JsonPropertyName("permission")] Permission Permission +); + +public record Permission +( + [property: JsonPropertyName("action")] string Action, + [property: JsonPropertyName("constraint")] Constraint Constraint +); + +public record Constraint +( + [property: JsonPropertyName("odrl:and"), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] IEnumerable? AndOperands, + [property: JsonPropertyName("odrl:or"), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] IEnumerable? OrOperands, + [property: JsonPropertyName("leftOperand"), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] string? LeftOperand, + [property: JsonPropertyName("operator"), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] string? Operator, + [property: JsonPropertyName("rightOperand"), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] object? RightOperandValue +); diff --git a/src/hub/PolicyHub.Service/PolicyHub.Service.csproj b/src/hub/PolicyHub.Service/PolicyHub.Service.csproj index cd76e05..812af2b 100644 --- a/src/hub/PolicyHub.Service/PolicyHub.Service.csproj +++ b/src/hub/PolicyHub.Service/PolicyHub.Service.csproj @@ -36,6 +36,7 @@ + diff --git a/src/hub/PolicyHub.Service/Program.cs b/src/hub/PolicyHub.Service/Program.cs index ee0420e..ef8bc23 100644 --- a/src/hub/PolicyHub.Service/Program.cs +++ b/src/hub/PolicyHub.Service/Program.cs @@ -17,4 +17,33 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -Host.CreateDefaultBuilder(args).Build().Run(); +using Org.Eclipse.TractusX.PolicyHub.DbAccess.DependencyInjection; +using Org.Eclipse.TractusX.PolicyHub.Service.Authentication; +using Org.Eclipse.TractusX.PolicyHub.Service.Controllers; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Web; +using System.Text.Json.Serialization; + +const string Version = "v2"; + +WebApplicationBuildRunner + .BuildAndRunWebApplication(args, "policy-hub", Version, ".Hub", + builder => + { + builder.Services.AddEndpointsApiExplorer(); + builder.Services.AddHubRepositories(builder.Configuration); + builder.Services.ConfigureHttpJsonOptions(options => + { + options.SerializerOptions.Converters.Add(new JsonStringEnumConverter()); + }); + builder.Services.Configure(options => + { + options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); + }); + }, + (app, _) => + { + app.MapGroup("/api") + .WithOpenApi() + .MapPolicyHubApi(); + }, + null); diff --git a/src/hub/PolicyHub.Service/Properties/launchSettings.json b/src/hub/PolicyHub.Service/Properties/launchSettings.json index d636d08..532c085 100644 --- a/src/hub/PolicyHub.Service/Properties/launchSettings.json +++ b/src/hub/PolicyHub.Service/Properties/launchSettings.json @@ -21,11 +21,11 @@ "PolicyHub.Service": { "commandName": "Project", "launchBrowser": false, - "launchUrl": "api/hub/swagger", + "launchUrl": "api/policy-hub/swagger", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development", "Cors__AllowedOrigins__0": "http://localhost:3000", - "Cors__AllowedOrigins__1": "https://portal.example.org" + "Cors__AllowedOrigins__1": "https://policy-hub.example.org" }, "applicationUrl": "https://localhost:5001;http://localhost:5000" }, diff --git a/tests/database/PolicyHub.DbAccess.Tests/HubRepositoriesTests.cs b/tests/database/PolicyHub.DbAccess.Tests/HubRepositoriesTests.cs new file mode 100644 index 0000000..c0280b9 --- /dev/null +++ b/tests/database/PolicyHub.DbAccess.Tests/HubRepositoriesTests.cs @@ -0,0 +1,40 @@ +using Org.Eclipse.TractusX.PolicyHub.DbAccess.Repositories; +using Org.Eclipse.TractusX.PolicyHub.DbAccess.Tests.Setup; +using Xunit.Extensions.AssemblyFixture; + +namespace Org.Eclipse.TractusX.PolicyHub.DbAccess.Tests; + +public class HubRepositoriesTests : IAssemblyFixture +{ + private readonly TestDbFixture _dbTestDbFixture; + + public HubRepositoriesTests(TestDbFixture testDbFixture) + { + _dbTestDbFixture = testDbFixture; + } + + #region GetInstance + + [Fact] + public async Task GetInstance_WithValid_ReturnsExpected() + { + var sut = await CreateSut().ConfigureAwait(false); + + var repo = sut.GetInstance(); + + repo.Should().BeOfType(); + } + + #endregion + + #region Setup + + private async Task CreateSut() + { + var context = await _dbTestDbFixture.GetPolicyHubDbContext().ConfigureAwait(false); + var sut = new HubRepositories(context); + return sut; + } + + #endregion +} diff --git a/tests/database/PolicyHub.DbAccess.Tests/PolicyHub.DbAccess.Tests.csproj b/tests/database/PolicyHub.DbAccess.Tests/PolicyHub.DbAccess.Tests.csproj new file mode 100644 index 0000000..cac108a --- /dev/null +++ b/tests/database/PolicyHub.DbAccess.Tests/PolicyHub.DbAccess.Tests.csproj @@ -0,0 +1,67 @@ + + + + + Org.Eclipse.TractusX.PolicyHub.DbAccess.Tests + Org.Eclipse.TractusX.PolicyHub.DbAccess.Tests + net7.0 + enable + enable + false + + + + + + + + + + + + + + + + + + + + + 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 new file mode 100644 index 0000000..392d5fe --- /dev/null +++ b/tests/database/PolicyHub.DbAccess.Tests/PolicyRepositoryTests.cs @@ -0,0 +1,197 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.DbAccess.Repositories; +using Org.Eclipse.TractusX.PolicyHub.DbAccess.Tests.Setup; +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; +using Xunit.Extensions.AssemblyFixture; + +namespace Org.Eclipse.TractusX.PolicyHub.DbAccess.Tests; + +/// +/// Tests the functionality of the +/// +public class PolicyRepositoryTests : IAssemblyFixture +{ + private readonly TestDbFixture _dbTestDbFixture; + + public PolicyRepositoryTests(TestDbFixture testDbFixture) + { + _dbTestDbFixture = testDbFixture; + } + + #region GetPolicyTypes + + [Fact] + public async Task GetAttributeKeys_ReturnsExpectedResult() + { + // Arrange + var sut = await CreateSut().ConfigureAwait(false); + + // Act + var result = await sut.GetAttributeKeys().ToListAsync().ConfigureAwait(false); + + // Assert + result.Should().NotBeEmpty().And.HaveCount(5).And.Satisfy( + x => x == "Regex", + x => x == "Static", + x => x == "DynamicValue", + x => x == "Brands", + x => x == "Version"); + } + + #endregion + + #region GetPolicyTypes + + [Fact] + public async Task GetPolicyTypes_ReturnsExpectedResult() + { + // Arrange + var sut = await CreateSut().ConfigureAwait(false); + + // Act + var result = await sut.GetPolicyTypes(null, null).ToListAsync().ConfigureAwait(false); + + // Assert + result.Should().NotBeEmpty().And.HaveCount(11).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" + ); + } + + [Fact] + public async Task GetPolicyTypes_WithTypeFilter_ReturnsExpectedResult() + { + // Arrange + var sut = await CreateSut().ConfigureAwait(false); + + // Act + var result = await sut.GetPolicyTypes(PolicyTypeId.Access, null).ToListAsync().ConfigureAwait(false); + + // Assert + result.Should().NotBeEmpty().And.HaveCount(3).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 + ); + } + + [Fact] + public async Task GetPolicyTypes_WithUseCase_ReturnsExpectedResult() + { + // Arrange + var sut = await CreateSut().ConfigureAwait(false); + + // Act + var result = await sut.GetPolicyTypes(null, UseCaseId.Sustainability).ToListAsync().ConfigureAwait(false); + + // Assert + result.Should().NotBeEmpty().And.HaveCount(3).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 + ); + } + + #endregion + + #region GetPolicyContentAsync + + [Fact] + public async Task GetPolicyContentAsync_WithoutRightOperand_ReturnsExpectedResult() + { + // Arrange + var sut = await CreateSut().ConfigureAwait(false); + + // Act + var result = await sut.GetPolicyContentAsync(null, PolicyTypeId.Usage, "purpose.trace.v1.TraceBattery").ConfigureAwait(false); + + // 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"); + result.RightOperandValue.Should().BeNull(); + } + + [Fact] + public async Task GetPolicyContentAsync_WithRightOperand_ReturnsExpectedResult() + { + // Arrange + var sut = await CreateSut().ConfigureAwait(false); + + // Act + var result = await sut.GetPolicyContentAsync(null, PolicyTypeId.Usage, "FrameworkAgreement.behavioraltwin").ConfigureAwait(false); + + // 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}"); + } + + #endregion + + #region GetPolicyForOperandContent + + [Fact] + public async Task GetPolicyForOperandContent__ReturnsExpectedResult() + { + // Arrange + var sut = await CreateSut().ConfigureAwait(false); + + // Act + var result = await sut.GetPolicyForOperandContent(PolicyTypeId.Usage, Enumerable.Repeat("purpose.trace.v1.TraceBattery", 1)).ToListAsync().ConfigureAwait(false); + + // Assert + result.Should().ContainSingle() + .And.Satisfy( + x => x.TechnicalKey == "purpose.trace.v1.TraceBattery" && + x.Attributes.Key == AttributeKeyId.Static && + x.Attributes.Values.Single() == "purpose.trace.v1.TraceBattery" && + x.LeftOperand == "purpose.trace.v1.TraceBattery" && + x.RightOperandValue == null); + } + + #endregion + + #region Setup + + private async Task CreateSut() + { + var context = await _dbTestDbFixture.GetPolicyHubDbContext().ConfigureAwait(false); + var sut = new PolicyRepository(context); + return sut; + } + + #endregion +} diff --git a/tests/database/PolicyHub.DbAccess.Tests/Setup/TestDbFixture.cs b/tests/database/PolicyHub.DbAccess.Tests/Setup/TestDbFixture.cs new file mode 100644 index 0000000..6904923 --- /dev/null +++ b/tests/database/PolicyHub.DbAccess.Tests/Setup/TestDbFixture.cs @@ -0,0 +1,103 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Org.Eclipse.TractusX.PolicyHub.Entities; +using Org.Eclipse.TractusX.PolicyHub.Migrations.Seeder; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Seeding; +using Testcontainers.PostgreSql; +using Xunit.Extensions.AssemblyFixture; + +[assembly: TestFramework(AssemblyFixtureFramework.TypeName, AssemblyFixtureFramework.AssemblyName)] +namespace Org.Eclipse.TractusX.PolicyHub.DbAccess.Tests.Setup; + +public class TestDbFixture : IAsyncLifetime +{ + private readonly PostgreSqlContainer _container = new PostgreSqlBuilder() + .WithDatabase("test_db") + .WithImage("postgres") + .WithCleanUp(true) + .WithName(Guid.NewGuid().ToString()) + .Build(); + + /// + /// Foreach test a new policyHubContext will be created and filled with the custom seeding data. + /// + /// + /// In this method the migrations don't need to get executed since they are already on the testcontainer. + /// Because of that the EnsureCreatedAsync is enough. + /// + /// Returns the created PolicyHubContext + public async Task GetPolicyHubDbContext() + { + var optionsBuilder = new DbContextOptionsBuilder(); + + optionsBuilder.UseNpgsql( + _container.GetConnectionString(), + x => x.MigrationsAssembly(typeof(BatchInsertSeeder).Assembly.GetName().Name) + .MigrationsHistoryTable("__efmigrations_history_hub", "public") + ); + var context = new PolicyHubContext(optionsBuilder.Options); + await context.Database.EnsureCreatedAsync().ConfigureAwait(false); + + return context; + } + + /// + /// This method is used to initially setup the database and run all migrations + /// + public async Task InitializeAsync() + { + await _container.StartAsync() + .ConfigureAwait(false); + + var optionsBuilder = new DbContextOptionsBuilder(); + + optionsBuilder.UseNpgsql( + _container.GetConnectionString(), + x => x.MigrationsAssembly(typeof(BatchInsertSeeder).Assembly.GetName().Name) + .MigrationsHistoryTable("__efmigrations_history_hub", "public") + ); + var context = new PolicyHubContext(optionsBuilder.Options); + await context.Database.MigrateAsync().ConfigureAwait(false); + + var seederOptions = Options.Create(new SeederSettings + { + TestDataEnvironments = new[] { "test" }, + DataPaths = new[] { "Seeder/Data" } + }); + var insertSeeder = new BatchInsertSeeder(context, + LoggerFactory.Create(builder => builder.AddConsole()).CreateLogger(), + seederOptions); + await insertSeeder.ExecuteAsync(CancellationToken.None).ConfigureAwait(false); + var updateSeeder = new BatchUpdateSeeder(context, + LoggerFactory.Create(builder => builder.AddConsole()).CreateLogger(), + seederOptions); + await updateSeeder.ExecuteAsync(CancellationToken.None).ConfigureAwait(false); + } + + /// + public async Task DisposeAsync() + { + await _container.DisposeAsync() + .ConfigureAwait(false); + } +} diff --git a/tests/database/PolicyHub.DbAccess.Tests/Usings.cs b/tests/database/PolicyHub.DbAccess.Tests/Usings.cs new file mode 100644 index 0000000..5f8f40c --- /dev/null +++ b/tests/database/PolicyHub.DbAccess.Tests/Usings.cs @@ -0,0 +1,23 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +global using AutoFixture; +global using AutoFixture.AutoFakeItEasy; +global using FluentAssertions; +global using Xunit; diff --git a/tests/database/PolicyHub.Entities.Tests/PolicyHub.Entities.Tests.csproj b/tests/database/PolicyHub.Entities.Tests/PolicyHub.Entities.Tests.csproj new file mode 100644 index 0000000..da8b058 --- /dev/null +++ b/tests/database/PolicyHub.Entities.Tests/PolicyHub.Entities.Tests.csproj @@ -0,0 +1,56 @@ + + + + + Org.Eclipse.TractusX.PolicyHub.Entities.Tests + Org.Eclipse.TractusX.PolicyHub.Entities.Tests + net7.0 + enable + enable + false + + + + + + + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + diff --git a/tests/database/PolicyHub.Entities.Tests/PolicyKindExtensionsTests.cs b/tests/database/PolicyHub.Entities.Tests/PolicyKindExtensionsTests.cs new file mode 100644 index 0000000..c06c6f0 --- /dev/null +++ b/tests/database/PolicyHub.Entities.Tests/PolicyKindExtensionsTests.cs @@ -0,0 +1,51 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; +using Org.Eclipse.TractusX.PolicyHub.Entities.Extensions; + +namespace Org.Eclipse.TractusX.PolicyHub.Entities.Tests; + +public class PolicyKindExtensionsTests +{ + [Theory] + [InlineData(PolicyKindId.BusinessPartnerNumber, true)] + [InlineData(PolicyKindId.Membership, true)] + [InlineData(PolicyKindId.Framework, true)] + [InlineData(PolicyKindId.Purpose, false)] + [InlineData(PolicyKindId.Dismantler, true)] + public void IsTechnicalEnforced_WithValidData_ReturnsExpected(PolicyKindId policyKindId, bool expectedResult) + { + // Act + var result = policyKindId.IsTechnicalEnforced(); + + // Assert + result.Should().Be(expectedResult); + } + + [Fact] + public void IsTechnicalEnforced_WithInvalidData_ThrowsArgumentOutOfRangeException() + { + // Act + var ex = Assert.Throws(() => ((PolicyKindId)0).IsTechnicalEnforced()); + + // Assert + ex.Message.Should().Be($"PolicyKindId 0 is not supported (Parameter 'policyKindId'){Environment.NewLine}Actual value was 0."); + } +} diff --git a/tests/database/PolicyHub.Entities.Tests/Usings.cs b/tests/database/PolicyHub.Entities.Tests/Usings.cs new file mode 100644 index 0000000..de2be4f --- /dev/null +++ b/tests/database/PolicyHub.Entities.Tests/Usings.cs @@ -0,0 +1,21 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +global using FluentAssertions; +global using Xunit; diff --git a/tests/hub/PolicyHub.Service.Tests/Authentication/KeycloakClaimsTransformationTests.cs b/tests/hub/PolicyHub.Service.Tests/Authentication/KeycloakClaimsTransformationTests.cs new file mode 100644 index 0000000..9c5bb63 --- /dev/null +++ b/tests/hub/PolicyHub.Service.Tests/Authentication/KeycloakClaimsTransformationTests.cs @@ -0,0 +1,92 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.Extensions.Options; +using Microsoft.IdentityModel.Tokens; +using Org.Eclipse.TractusX.PolicyHub.Service.Authentication; +using System.Security.Claims; +using System.Text.Json; + +namespace Org.Eclipse.TractusX.PolicyHub.Service.Tests.Authentication; + +public class KeycloakClaimsTransformationTests +{ + private readonly KeycloakClaimsTransformation _sut; + + public KeycloakClaimsTransformationTests() + { + var options = Options.Create(new JwtBearerOptions + { + TokenValidationParameters = new TokenValidationParameters + { + ValidAudience = "validAudience" + } + }); + _sut = new KeycloakClaimsTransformation(options); + } + + [Fact] + public async Task TransformAsync_WithoutRoles_ReturnsExpected() + { + // Arrange + var identity = new ClaimsIdentity(Enumerable.Repeat(new Claim(ClaimTypes.Email, "test@mail.com"), 1)); + var principal = new ClaimsPrincipal(identity); + + // Act + var result = await _sut.TransformAsync(principal).ConfigureAwait(false); + + // Assert + result.Claims.Should().ContainSingle() + .And.Satisfy(x => x.Type == ClaimTypes.Email && x.Value == "test@mail.com"); + } + + [Fact] + public async Task TransformAsync_WithRoles_ReturnsExpected() + { + // Arrange + var json = JsonSerializer.Serialize(new { validAudience = new { roles = Enumerable.Repeat("testRole", 1) } }); + var identity = new ClaimsIdentity(Enumerable.Repeat(new Claim(KeycloakClaimsTransformation.ResourceAccess, json, "JSON"), 1)); + var principal = new ClaimsPrincipal(identity); + + // Act + var result = await _sut.TransformAsync(principal).ConfigureAwait(false); + + // Assert + result.Claims.Should().HaveCount(2).And.Satisfy( + x => x.Type == KeycloakClaimsTransformation.ResourceAccess && x.Value == json, + x => x.Type == ClaimTypes.Role && x.Value == "testRole"); + } + + [Fact] + public async Task TransformAsync_WithIntRole_ReturnsExpected() + { + // Arrange + var json = JsonSerializer.Serialize(new { validAudience = new { roles = Enumerable.Repeat(1, 1) } }); + var identity = new ClaimsIdentity(Enumerable.Repeat(new Claim(KeycloakClaimsTransformation.ResourceAccess, json, "JSON"), 1)); + var principal = new ClaimsPrincipal(identity); + + // Act + var result = await _sut.TransformAsync(principal).ConfigureAwait(false); + + // Assert + result.Claims.Should().ContainSingle() + .And.Satisfy(x => x.Type == KeycloakClaimsTransformation.ResourceAccess && x.Value == json); + } +} diff --git a/tests/hub/PolicyHub.Service.Tests/BusinessLogic/PolicyHubBusinessLogicTests.cs b/tests/hub/PolicyHub.Service.Tests/BusinessLogic/PolicyHubBusinessLogicTests.cs new file mode 100644 index 0000000..12288fa --- /dev/null +++ b/tests/hub/PolicyHub.Service.Tests/BusinessLogic/PolicyHubBusinessLogicTests.cs @@ -0,0 +1,408 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +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.Enums; +using Org.Eclipse.TractusX.PolicyHub.Service.BusinessLogic; +using Org.Eclipse.TractusX.PolicyHub.Service.Models; +using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Library; + +namespace Org.Eclipse.TractusX.PolicyHub.Service.Tests.BusinessLogic; + +public class PolicyHubBusinessLogicTests +{ + private readonly IFixture _fixture; + private readonly IPolicyRepository _policyRepository; + + private readonly PolicyHubBusinessLogic _sut; + + public PolicyHubBusinessLogicTests() + { + _fixture = new Fixture().Customize(new AutoFakeItEasyCustomization { ConfigureMembers = true }); + _fixture.Behaviors.OfType().ToList() + .ForEach(b => _fixture.Behaviors.Remove(b)); + _fixture.Behaviors.Add(new OmitOnRecursionBehavior()); + + var hubRepositories = A.Fake(); + _policyRepository = A.Fake(); + + A.CallTo(() => hubRepositories.GetInstance()).Returns(_policyRepository); + + _sut = new PolicyHubBusinessLogic(hubRepositories); + } + + #region GetAttributes + + [Fact] + public async Task GetAttributeKeys_ReturnsExpected() + { + // Arrange + Setup_GetAttributeKeys(); + + // Act + var result = await _sut.GetAttributeKeys().ToListAsync().ConfigureAwait(false); + + // Assert + result.Should().HaveCount(5); + } + + #endregion + + #region GetPolicyTypes + + [Fact] + public async Task GetPolicyTypes_WithoutFilter_ReturnsExpected() + { + // Arrange + Setup_GetPolicyTypes(); + + // Act + var result = await _sut.GetPolicyTypes(null, null).ToListAsync().ConfigureAwait(false); + + // Assert + result.Should().HaveCount(2); + } + + [Fact] + public async Task GetPolicyTypes_WithUseCaseFilter_ReturnsExpected() + { + // Arrange + Setup_GetPolicyTypes(); + + // Act + var result = await _sut.GetPolicyTypes(null, UseCaseId.Sustainability).ToListAsync().ConfigureAwait(false); + + // Assert + result.Should().ContainSingle(); + } + + #endregion + + #region GetPolicyContentWithFiltersAsync + + [Fact] + public async Task GetPolicyContentWithFiltersAsync_WithNotExistingInDatabase_ThrowsNotFoundException() + { + // Arrange + 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); + + // Act + var ex = await Assert.ThrowsAsync(Act); + + // Assert + ex.Message.Should().Be($"Policy for type {policyTypeId} and technicalKey membership does not exists"); + } + + [Fact] + public async Task GetPolicyContentWithFiltersAsync_AttributeAndRightOperandNull_ThrowsUnexpectedConditionException() + { + // Arrange + 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); + + // Act + var ex = await Assert.ThrowsAsync(Act); + + // Assert + ex.Message.Should().Be("There must be one configured rightOperand value"); + } + + [Fact] + public async Task GetPolicyContentWithFiltersAsync_WithDynamicValue_ThrowsUnexpectedConditionException() + { + // Arrange + const PolicyTypeId policyTypeId = PolicyTypeId.Access; + A.CallTo(() => _policyRepository.GetPolicyContentAsync(null, policyTypeId, "membership")) + .Returns(new ValueTuple), string?>(true, "test", (AttributeKeyId.DynamicValue, Enumerable.Empty()), "test:{0}")); + + // Act + var result = await _sut.GetPolicyContentWithFiltersAsync(null, policyTypeId, "membership", OperatorId.Equals, "abc"); + + // Assert + result.Content.Permission.Constraint.RightOperandValue.Should().Be("abc"); + } + + [Fact] + public async Task GetPolicyContentWithFiltersAsync_WithMultipleRegexValues_ThrowsUnexpectedConditionException() + { + // Arrange + 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"); + + // Act + var ex = await Assert.ThrowsAsync(Act).ConfigureAwait(false); + + // Assert + ex.Message.Should().Be("There should only be one regex pattern defined"); + } + + [Fact] + public async Task GetPolicyContentWithFiltersAsync_WithMultipleValues_ReturnsExpected() + { + // Arrange + A.CallTo(() => _policyRepository.GetPolicyContentAsync(UseCaseId.Traceability, PolicyTypeId.Usage, "multipleAdditionalValues")) + .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); + + // Assert + result.Content.Id.Should().Be("...."); + result.Content.Permission.Action.Should().Be("use"); + result.AdditionalAttributes.Should().ContainSingle(); + result.AdditionalAttributes!.Single().PossibleValues.Should().HaveCount(3) + .And.Satisfy( + x => x == "value1", + 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.Operator.Should().Be("eq"); + result.Content.Permission.Constraint.AndOperands.Should().BeNull(); + result.Content.Permission.Constraint.OrOperands.Should().BeNull(); + } + + #endregion + + #region GetPolicyContentAsync + + [Fact] + public async Task GetPolicyContentAsync_WithUnmatchingPoliciesAndConstraints_ThrowsNotFoundException() + { + // 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.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); + + // Assert + ex.Message.Should().Be($"Policy for type {data.PolicyType} and technicalKeys abc does not exists"); + } + + [Fact] + public async Task GetPolicyContentAsync_WithAttributeAndRightOperandNull_ThrowsUnexpectedConditionException() + { + // Arrange + var data = new PolicyContentRequest(PolicyTypeId.Access, ConstraintOperandId.Or, + new[] + { + new Constraints("test", OperatorId.In, null), + }); + A.CallTo(() => _policyRepository.GetPolicyForOperandContent(data.PolicyType, A>._)) + .Returns(Enumerable.Repeat(new ValueTuple>, string?>("test", "active", (null, Enumerable.Empty()), null), 1).ToAsyncEnumerable()); + async Task Act() => await _sut.GetPolicyContentAsync(data); + + // Act + var ex = await Assert.ThrowsAsync(Act).ConfigureAwait(false); + + // Assert + ex.Message.Should().Be("There must be one configured rightOperand value"); + } + + [Fact] + public async Task GetPolicyContentAsync_WithRegexWithoutValue_ThrowsControllerArgumentException() + { + // Arrange + var data = new PolicyContentRequest(PolicyTypeId.Access, ConstraintOperandId.Or, + new[] + { + new Constraints("test", OperatorId.Equals, null), + }); + 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); + + // Act + var ex = await Assert.ThrowsAsync(Act).ConfigureAwait(false); + + // Assert + ex.ParamName.Should().Be("value"); + ex.Message.Should().Be("you must provide a value for the regex (Parameter 'value')"); + } + + [Fact] + public async Task GetPolicyContentAsync_WithRegexWithoutMatchingRegexPattern_ThrowsControllerArgumentException() + { + // Arrange + var data = new PolicyContentRequest(PolicyTypeId.Access, ConstraintOperandId.Or, + new[] + { + new Constraints("test", OperatorId.Equals, "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); + + // Act + var ex = await Assert.ThrowsAsync(Act).ConfigureAwait(false); + + // 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_WithMultipleDefinedKeys_ThrowsNotFoundException() + { + // Arrange + var data = new PolicyContentRequest(PolicyTypeId.Access, ConstraintOperandId.Or, + new[] + { + new Constraints("test", OperatorId.In, null), + new Constraints("test", OperatorId.Equals, null) + }); + A.CallTo(() => _policyRepository.GetPolicyForOperandContent(data.PolicyType, A>._)) + .Returns(new[] + { + new ValueTuple>, string?>("test", "active", default, null) + }.ToAsyncEnumerable()); + async Task Act() => await _sut.GetPolicyContentAsync(data); + + // Act + var ex = await Assert.ThrowsAsync(Act).ConfigureAwait(false); + + // Assert + ex.Message.Should().Be("Keys test have been defined multiple times"); + } + + [Fact] + public async Task GetPolicyContentAsync_WithValid_ReturnsExpected() + { + // Arrange + var data = new PolicyContentRequest(PolicyTypeId.Access, ConstraintOperandId.Or, + new[] + { + new Constraints("inValues", OperatorId.In, null), + new Constraints("regValue", OperatorId.Equals, "BPNL00000001TEST"), + new Constraints("dynamicWithoutValue", OperatorId.Equals, null), + new Constraints("dynamicWithValue", OperatorId.Equals, "test") + }); + A.CallTo(() => _policyRepository.GetPolicyForOperandContent(data.PolicyType, A>._)) + .Returns(new[] + { + new ValueTuple>, string?>("inValues", "active", new (AttributeKeyId.Brands, new[] { "BMW", "Mercedes" }), null), + new ValueTuple>, string?>("regValue", "active", new (AttributeKeyId.Regex, Enumerable.Repeat(@"^BPNL[\w|\d]{12}$", 1)), null), + new ValueTuple>, string?>("dynamicWithoutValue", "active", new (AttributeKeyId.DynamicValue, Enumerable.Repeat("active:{0}", 1)), "rightOperandValueTest"), + new ValueTuple>, string?>("dynamicWithValue", "active", new (AttributeKeyId.DynamicValue, Enumerable.Repeat("active:{0}", 1)), "rightOperandValueTest") + }.ToAsyncEnumerable()); + + // Act + var result = await _sut.GetPolicyContentAsync(data).ConfigureAwait(false); + + // Assert + result.Content.Id.Should().Be("...."); + result.Content.Permission.Action.Should().Be("access"); + result.Content.Permission.Constraint.RightOperandValue.Should().BeNull(); + result.Content.Permission.Constraint.LeftOperand.Should().BeNull(); + result.Content.Permission.Constraint.Operator.Should().BeNull(); + 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"); + } + + [Fact] + public async Task GetPolicyContentAsync_WithMultipleValues_ReturnsExpected() + { + var data = new PolicyContentRequest(PolicyTypeId.Usage, ConstraintOperandId.And, + new[] + { + new Constraints("multipleAdditionalValues", OperatorId.Equals, null), + new Constraints("test", OperatorId.In, null) + }); + A.CallTo(() => _policyRepository.GetPolicyForOperandContent(data.PolicyType, A>._)) + .Returns(new[] + { + new ValueTuple>, string?>("multipleAdditionalValues", "multipleAdditionalValues", new(AttributeKeyId.Static, new[] { "value1", "value2", "value3" }), null), + new ValueTuple>, string?>("test", "test", new(AttributeKeyId.Version, new[] { "1.0", "1.1" }), null) + }.ToAsyncEnumerable()); + + // Act + var result = await _sut.GetPolicyContentAsync(data).ConfigureAwait(false); + + // Assert + result.Content.Id.Should().Be("...."); + result.Content.Permission.Action.Should().Be("use"); + result.Content.Permission.Constraint.RightOperandValue.Should().BeNull(); + result.Content.Permission.Constraint.LeftOperand.Should().BeNull(); + result.Content.Permission.Constraint.Operator.Should().BeNull(); + 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); + result.AdditionalAttributes.Should().ContainSingle() + .And.Satisfy(x => x.Key == "@multipleAdditionalValues-Static"); + result.AdditionalAttributes!.Single().PossibleValues.Should().HaveCount(3) + .And.Satisfy( + x => x == "value1", + x => x == "value2", + x => x == "value3"); + } + + #endregion + + #region Setup + + private void Setup_GetAttributeKeys() + { + A.CallTo(() => _policyRepository.GetAttributeKeys()) + .Returns(_fixture.CreateMany(5).ToAsyncEnumerable()); + } + + private void Setup_GetPolicyTypes() + { + var susAccess = _fixture.Build() + .With(x => x.UseCase, Enumerable.Repeat(UseCaseId.Sustainability, 1)) + .With(x => x.Type, Enumerable.Repeat(PolicyTypeId.Access, 1)) + .Create(); + var traceAccess = _fixture.Build() + .With(x => x.UseCase, Enumerable.Repeat(UseCaseId.Traceability, 1)) + .With(x => x.Type, Enumerable.Repeat(PolicyTypeId.Access, 1)) + .Create(); + + A.CallTo(() => _policyRepository.GetPolicyTypes(null, null)) + .Returns(new[] { susAccess, traceAccess }.ToAsyncEnumerable()); + A.CallTo(() => _policyRepository.GetPolicyTypes(null, UseCaseId.Sustainability)) + .Returns(new[] { susAccess }.ToAsyncEnumerable()); + } + + #endregion +} diff --git a/tests/hub/PolicyHub.Service.Tests/Controllers/PolicyHubControllerTests.cs b/tests/hub/PolicyHub.Service.Tests/Controllers/PolicyHubControllerTests.cs new file mode 100644 index 0000000..751b84c --- /dev/null +++ b/tests/hub/PolicyHub.Service.Tests/Controllers/PolicyHubControllerTests.cs @@ -0,0 +1,336 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.DbAccess.Models; +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.Library; +using System.Net; +using System.Net.Http.Json; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Org.Eclipse.TractusX.PolicyHub.Service.Tests.Controllers; + +[Trait("Category", "PolicyHubEndToEnd")] +[Collection("PolicyHub")] +public class PolicyHubControllerTests : IClassFixture +{ + private static readonly JsonSerializerOptions JsonOptions = new() + { + PropertyNameCaseInsensitive = true, + Converters = { new JsonStringEnumConverter() }, + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase + }; + + private const string BaseUrl = "/api/policy-hub"; + private readonly HttpClient _client; + + public PolicyHubControllerTests(IntegrationTestFactory factory) + { + _client = factory.CreateClient(); + } + + #region Policy Attributes + + [Fact] + public async Task GetAttributes() + { + // Act + var attributes = await _client.GetFromJsonAsync>($"{BaseUrl}/policy-attributes").ConfigureAwait(false); + + // Assert + attributes.Should().NotBeNull().And.HaveCount(5).And.Satisfy( + x => x == "Regex", + x => x == "Static", + x => x == "DynamicValue", + x => x == "Brands", + x => x == "Version" + ); + } + + #endregion + + #region Policy Types + + [Fact] + public async Task GetPolicyTypes_WithoutFilter_ReturnsExpected() + { + // Act + var policies = await _client.GetFromJsonAsync>($"{BaseUrl}/policy-types", JsonOptions).ConfigureAwait(false); + + // Assert + policies.Should().NotBeNull() + .And.HaveCount(11).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" + ); + } + + [Fact] + public async Task GetPolicyTypes_WithTypeFilter_ReturnsExpected() + { + // Act + var policies = await _client.GetFromJsonAsync>($"{BaseUrl}/policy-types?type={PolicyTypeId.Access.ToString()}", JsonOptions).ConfigureAwait(false); + + // Assert + policies.Should().NotBeNull() + .And.HaveCount(3).And.Satisfy( + x => x.TechnicalKey == "BusinessPartnerNumber", + x => x.TechnicalKey == "Membership", + x => x.TechnicalKey == "companyRole.dismantler" + ); + } + + [Fact] + public async Task GetPolicyTypes_WithUseCaseFilter_ReturnsExpected() + { + // Act + var policies = await _client.GetFromJsonAsync>($"{BaseUrl}/policy-types?useCase={UseCaseId.Traceability.ToString()}", JsonOptions).ConfigureAwait(false); + + // Assert + policies.Should().NotBeNull() + .And.HaveCount(8).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" + ); + } + + #endregion + + #region Policy Content + + [Fact] + 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); + + // 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() == @"The provided value notmatching does not match the regex pattern ^BPNL[\w|\d]{12}$ (Parameter 'value')"); + } + + [Fact] + 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); + + // 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() == "you must provide a value for the regex (Parameter 'value')"); + } + + [Fact] + 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); + + // 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\":{\"leftOperand\":\"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); + + // 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\":{\"leftOperand\":\"FrameworkAgreement.traceability\",\"operator\":\"eq\",\"rightOperand\":\"@FrameworkAgreement.traceability-Version\"}}},\"attributes\":[{\"key\":\"@FrameworkAgreement.traceability-Version\",\"possibleValues\":[\"active:1.0\",\"active:1.1\",\"active: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); + + // 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\":{\"leftOperand\":\"Dismantler.activityType\",\"operator\":\"in\",\"rightOperand\":[\"Audi\",\"BMW\",\"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); + + // 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\":{\"leftOperand\":\"purpose.trace.v1.TraceBattery\",\"operator\":\"eq\",\"rightOperand\":\"purpose.trace.v1.TraceBattery\"}}}}"); + } + + #endregion + + #region Policy Content with Filters + + [Fact] + public async Task GetPolicyContentWithFiltersAsync_TwoEqualsConstraintsAndOperand_ReturnsExpected() + { + // Arrange + var data = new PolicyContentRequest( + PolicyTypeId.Usage, + ConstraintOperandId.And, + new[] + { + new Constraints("FrameworkAgreement.traceability", OperatorId.Equals, null), + new Constraints("companyRole.dismantler", OperatorId.In, null) + }); + + // Act + var response = await _client.PostAsJsonAsync($"{BaseUrl}/policy-content", data, JsonOptions).ConfigureAwait(false); + + // 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\":\"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_MultipleConstraintsEqualsAndOperand_ReturnsExpected() + { + // Arrange + var data = new PolicyContentRequest( + PolicyTypeId.Usage, + ConstraintOperandId.And, + new[] + { + new Constraints("FrameworkAgreement.traceability", OperatorId.Equals, null), + new Constraints("companyRole.dismantler", OperatorId.In, null), + new Constraints("BusinessPartnerNumber", OperatorId.Equals, "BPNL00000003CRHK") + }); + + // Act + var response = await _client.PostAsJsonAsync($"{BaseUrl}/policy-content", data, JsonOptions).ConfigureAwait(false); + + // 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\"]}]}"); + } + + [Fact] + public async Task GetPolicyContentWithFiltersAsync_MultipleConstraintsEqualsOrOperand_ReturnsExpected() + { + // Arrange + var data = new PolicyContentRequest( + PolicyTypeId.Usage, + ConstraintOperandId.Or, + new[] + { + new Constraints("FrameworkAgreement.traceability", OperatorId.Equals, null), + new Constraints("companyRole.dismantler", OperatorId.In, null), + }); + + // Act + var response = await _client.PostAsJsonAsync($"{BaseUrl}/policy-content", data, JsonOptions).ConfigureAwait(false); + + // 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: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"); + } + + #endregion + + #region Swagger + + [Fact] + public async Task CheckSwagger_ReturnsExpected() + { + // Act + var response = await _client.GetAsync($"{BaseUrl}/swagger/v2/swagger.json").ConfigureAwait(false); + + // Assert + response.Should().NotBeNull(); + response.StatusCode.Should().Be(HttpStatusCode.OK); + } + + #endregion +} diff --git a/tests/hub/PolicyHub.Service.Tests/Extensions/JsonGenerationExtensionsTests.cs b/tests/hub/PolicyHub.Service.Tests/Extensions/JsonGenerationExtensionsTests.cs new file mode 100644 index 0000000..a64db63 --- /dev/null +++ b/tests/hub/PolicyHub.Service.Tests/Extensions/JsonGenerationExtensionsTests.cs @@ -0,0 +1,70 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Org.Eclipse.TractusX.PolicyHub.Entities.Enums; +using Org.Eclipse.TractusX.PolicyHub.Service.Extensions; + +namespace Org.Eclipse.TractusX.PolicyHub.Service.Tests.Extensions; + +public class JsonGenerationExtensionsTests +{ + [Theory] + [InlineData(PolicyTypeId.Access, "access")] + [InlineData(PolicyTypeId.Usage, "use")] + public void TypeToJsonString_WithValidData_ReturnsExpected(PolicyTypeId policyTypeId, string result) + { + // Act + var jsonString = policyTypeId.TypeToJsonString(); + + // Assert + jsonString.Should().Be(result); + } + + [Fact] + public void TypeToJsonString_WithInvalidData_ThrowsArgumentOutOfRangeException() + { + // Act + var ex = Assert.Throws(() => ((PolicyTypeId)0).TypeToJsonString()); + + // Assert + ex.Message.Should().Be($"0 is not a valid value (Parameter 'type'){Environment.NewLine}Actual value was 0."); + } + + [Theory] + [InlineData(OperatorId.Equals, "eq")] + [InlineData(OperatorId.In, "in")] + public void OperatorToJsonString_WithValidData_ReturnsExpected(OperatorId operatorId, string result) + { + // Act + var jsonString = operatorId.OperatorToJsonString(); + + // Assert + jsonString.Should().Be(result); + } + + [Fact] + public void OperatorToJsonString_WithInvalidData_ThrowsArgumentOutOfRangeException() + { + // Act + var ex = Assert.Throws(() => ((OperatorId)0).OperatorToJsonString()); + + // Assert + ex.Message.Should().Be($"0 is not a valid value (Parameter 'type'){Environment.NewLine}Actual value was 0."); + } +} diff --git a/tests/hub/PolicyHub.Service.Tests/PolicyHub.Service.Tests.csproj b/tests/hub/PolicyHub.Service.Tests/PolicyHub.Service.Tests.csproj new file mode 100644 index 0000000..a1d437b --- /dev/null +++ b/tests/hub/PolicyHub.Service.Tests/PolicyHub.Service.Tests.csproj @@ -0,0 +1,65 @@ + + + + + Org.Eclipse.TractusX.PolicyHub.Service.Tests + Org.Eclipse.TractusX.PolicyHub.Service.Tests + net7.0 + enable + enable + false + + + + + + + + + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + Always + + + diff --git a/tests/hub/PolicyHub.Service.Tests/Setup/FakePolicyEvaluator.cs b/tests/hub/PolicyHub.Service.Tests/Setup/FakePolicyEvaluator.cs new file mode 100644 index 0000000..2a2b2dc --- /dev/null +++ b/tests/hub/PolicyHub.Service.Tests/Setup/FakePolicyEvaluator.cs @@ -0,0 +1,36 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 BMW Group AG + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authorization.Policy; +using Microsoft.AspNetCore.Http; +using System.Security.Claims; + +namespace Org.Eclipse.TractusX.PolicyHub.Service.Tests.Setup; + +public class FakePolicyEvaluator : IPolicyEvaluator +{ + public Task AuthenticateAsync(AuthorizationPolicy policy, HttpContext context) => + Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(), new AuthenticationProperties(), "FakeScheme"))); + + public Task AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context, object? resource) => + Task.FromResult(PolicyAuthorizationResult.Success()); +} diff --git a/tests/hub/PolicyHub.Service.Tests/Setup/IntegrationTestFactory.cs b/tests/hub/PolicyHub.Service.Tests/Setup/IntegrationTestFactory.cs new file mode 100644 index 0000000..4cea060 --- /dev/null +++ b/tests/hub/PolicyHub.Service.Tests/Setup/IntegrationTestFactory.cs @@ -0,0 +1,123 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using Microsoft.AspNetCore.Authorization.Policy; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.AspNetCore.TestHost; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Org.Eclipse.TractusX.PolicyHub.Entities; +using Org.Eclipse.TractusX.PolicyHub.Migrations.Seeder; +using Org.Eclipse.TractusX.PolicyHub.Service.BusinessLogic; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Logging; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Seeding; +using System.Reflection; +using System.Text.Json.Serialization; +using Testcontainers.PostgreSql; + +[assembly: CollectionBehavior(DisableTestParallelization = true)] +namespace Org.Eclipse.TractusX.PolicyHub.Service.Tests.Setup; + +public class IntegrationTestFactory : WebApplicationFactory, IAsyncLifetime +{ + private readonly PostgreSqlContainer _container = new PostgreSqlBuilder() + .WithDatabase("test_db") + .WithImage("postgres") + .WithCleanUp(true) + .WithName(Guid.NewGuid().ToString()) + .Build(); + + protected override void ConfigureWebHost(IWebHostBuilder builder) + { + var projectDir = Directory.GetCurrentDirectory(); + var configPath = Path.Combine(projectDir, "appsettings.IntegrationTests.json"); + + builder.ConfigureAppConfiguration((_, conf) => + { + conf.AddJsonFile(configPath, true) + .AddUserSecrets(Assembly.GetExecutingAssembly(), true) + .AddEnvironmentVariables(); + }); + builder.ConfigureTestServices(services => + { + services.ConfigureHttpJsonOptions(options => + { + options.SerializerOptions.Converters.Add(new JsonStringEnumConverter()); + }); + services.Configure(options => + { + options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); + }); + + var descriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions)); + if (descriptor != null) + services.Remove(descriptor); + + services.AddDbContext(options => + { + options.UseNpgsql(_container.GetConnectionString(), + x => x.MigrationsAssembly(typeof(BatchInsertSeeder).Assembly.GetName().Name) + .MigrationsHistoryTable("__efmigrations_history_hub", "public")); + }); + + services.AddSingleton(); + }); + } + + /// + protected override IHost CreateHost(IHostBuilder builder) + { + builder.AddLogging(); + var host = base.CreateHost(builder); + + var optionsBuilder = new DbContextOptionsBuilder(); + + optionsBuilder.UseNpgsql( + _container.GetConnectionString(), + x => x.MigrationsAssembly(typeof(BatchInsertSeeder).Assembly.GetName().Name) + .MigrationsHistoryTable("__efmigrations_history_hub", "public") + ); + var context = new PolicyHubContext(optionsBuilder.Options); + context.Database.Migrate(); + + var seederOptions = Options.Create(new SeederSettings + { + TestDataEnvironments = new[] { "test" }, + DataPaths = new[] { "Seeder/Data" } + }); + var insertSeeder = new BatchInsertSeeder(context, + LoggerFactory.Create(c => c.AddConsole()).CreateLogger(), + seederOptions); + insertSeeder.ExecuteAsync(CancellationToken.None).GetAwaiter().GetResult(); + var updateSeeder = new BatchUpdateSeeder(context, + LoggerFactory.Create(c => c.AddConsole()).CreateLogger(), + seederOptions); + updateSeeder.ExecuteAsync(CancellationToken.None).GetAwaiter().GetResult(); + return host; + } + + public async Task InitializeAsync() => await _container.StartAsync(); + + public new async Task DisposeAsync() => await _container.DisposeAsync(); +} diff --git a/tests/hub/PolicyHub.Service.Tests/Usings.cs b/tests/hub/PolicyHub.Service.Tests/Usings.cs new file mode 100644 index 0000000..65016ae --- /dev/null +++ b/tests/hub/PolicyHub.Service.Tests/Usings.cs @@ -0,0 +1,24 @@ +/******************************************************************************** + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +global using AutoFixture; +global using AutoFixture.AutoFakeItEasy; +global using FakeItEasy; +global using FluentAssertions; +global using Xunit; diff --git a/tests/hub/PolicyHub.Service.Tests/appsettings.IntegrationTests.json b/tests/hub/PolicyHub.Service.Tests/appsettings.IntegrationTests.json new file mode 100644 index 0000000..107e7db --- /dev/null +++ b/tests/hub/PolicyHub.Service.Tests/appsettings.IntegrationTests.json @@ -0,0 +1,39 @@ +{ + "Serilog": { + "Using": [ "Serilog.Sinks.Console" ], + "MinimumLevel": { + "Default": "Debug" + }, + "WriteTo": [ + { "Name": "Console" } + ], + "Enrich": [ + "WithCorrelationId" + ], + "Properties": { + "Application": "PolicyHub" + } + }, + "SwaggerEnabled": true, + "HealthChecks": [], + "Cors": { + "AllowedOrigins": [] + }, + "ConnectionStrings": { + "PolicyHubDb": "Server=placeholder;Database=placeholder;Port=5432;User Id=placeholder;Password=;Ssl Mode=Disable;" + }, + "JwtBearerOptions": { + "RequireHttpsMetadata": true, + "MetadataAddress": "", + "SaveToken": true, + "TokenValidationParameters": { + "ValidateIssuer": true, + "ValidIssuer": "", + "ValidateIssuerSigningKey": true, + "ValidAudience": "", + "ValidateAudience": true, + "ValidateLifetime": true, + "ClockSkew": 600000 + } + } +}