From e6f7a0ca11592852ab94c02026e8399083162d5b Mon Sep 17 00:00:00 2001 From: akovylyaeva Date: Wed, 17 Sep 2025 14:46:48 +0500 Subject: [PATCH 01/13] chore: fix readme --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 94b4732..73ec553 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,6 @@ Note: If you already has this network, skip this step. - MockForPullRequest - used in PR pipeline to run the service in isolation (no external deps) and run its Karate tests against it - MockForDevelopment - used locally when you run the service in Visual Studio e.g. in Debug and don't want to spin up any external deps -- LocalEnvForDevelopment - used locally when you run the service in Visual Studio and you want to connect to its external deps from Local Env -- ProdForDevelopment - used locally when you run the service in Visual Studio and want to connect to its external deps from Prod specially dedicated Local Development Tenant -- ProdForDeployment - used when we run the service in Prod, it shouldn't contain any secrets, it should be a Release build, using real Prod external deps ## Database scheme From 7ab7b6e1946f393873bdc85dd5c9885acca4d95b Mon Sep 17 00:00:00 2001 From: akovylyaeva Date: Wed, 17 Sep 2025 15:15:09 +0500 Subject: [PATCH 02/13] chore: update auth-api using new code style --- .devcontainer/devcontainer.json | 33 ++++++ .github/workflows/docker-build-and-push.yml | 57 ++++++++++ .../karate-tests-on-pull-request.yml | 97 ++++++++++++++++ .github/workflows/prod-docker-publish.yml | 74 ++++++------ .../workflows/unit-tests-on-pull-request.yml | 23 ++++ Api/Dockerfile | 15 ++- Api/Properties/launchSettings.json | 13 ++- Api/appsettings.LocalEnvForDevelopment.json | 23 ---- Api/appsettings.MockForDevelopment.json | 12 +- Api/appsettings.MockForPullRequest.json | 18 +-- Api/appsettings.ProdForDeployment.json | 23 ---- Api/appsettings.ProdForDevelopment.json | 23 ---- Api/appsettings.json | 3 +- Api/ci/helmfile.yaml | 25 +++++ Api/ci/values-local-env.yaml | 2 +- Api/ci/{values-custom.yaml => values.yaml} | 2 +- docker-compose-tests.yml | 28 ----- docker-compose.yml | 105 ++++++++++++++---- e2e/KarateDockerfile | 11 ++ e2e/item-types-happy-path.feature | 71 ++++++++++++ e2e/js-utils.js | 31 ++++++ e2e/mock-server-initialization.json | 3 + 22 files changed, 494 insertions(+), 198 deletions(-) create mode 100644 .devcontainer/devcontainer.json create mode 100644 .github/workflows/docker-build-and-push.yml create mode 100644 .github/workflows/karate-tests-on-pull-request.yml create mode 100644 .github/workflows/unit-tests-on-pull-request.yml delete mode 100644 Api/appsettings.LocalEnvForDevelopment.json delete mode 100644 Api/appsettings.ProdForDeployment.json delete mode 100644 Api/appsettings.ProdForDevelopment.json create mode 100644 Api/ci/helmfile.yaml rename Api/ci/{values-custom.yaml => values.yaml} (99%) delete mode 100644 docker-compose-tests.yml create mode 100644 e2e/KarateDockerfile create mode 100644 e2e/item-types-happy-path.feature create mode 100644 e2e/js-utils.js create mode 100644 e2e/mock-server-initialization.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..f12b233 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,33 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-dockerfile +{ + "name": "Existing Dockerfile", + "build": { + // Sets the run context to one level up instead of the .devcontainer folder. + "context": "..", + // Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename. + "dockerfile": "../e2e/KarateDockerfile" + }, + "runArgs": [ + "--network=host" + ], + "customizations": { + "vscode": { + "extensions": [ + "karatelabs.karate", + "bierner.markdown-mermaid" + ] + } + }, + "containerEnv": { + "AUTH_FIRST_TENANT_LOGIN_WITH_ALL_PERMISSIONS": "first-tenant-login-with-all-permissions", + "AUTH_FIRST_TENANT_PASSWORD_WITH_ALL_PERMISSIONS": "first-tenant-password-with-all-permissions", + "AUTH_SECOND_TENANT_LOGIN_WITH_ALL_PERMISSIONS": "second-tenant-login-with-all-permissions", + "AUTH_SECOND_TENANT_PASSWORD_WITH_ALL_PERMISSIONS": "second-tenant-password-with-all-permissions", + "AUTH_LOGIN_WITHOUT_PERMISSIONS": "first-tenant-login-without-permissions", + "AUTH_PASSWORD_WITHOUT_PERMISSIONS": "first-tenant-password-without-permissions", + "AUTH_API_ROOT_URL": "http://localhost:8503", + "API_ROOT_URL": "http://localhost:6503", + "SHOULD_USE_FAKE_EXTERNAL_DEPENDENCIES": "true" + } +} \ No newline at end of file diff --git a/.github/workflows/docker-build-and-push.yml b/.github/workflows/docker-build-and-push.yml new file mode 100644 index 0000000..e39b85d --- /dev/null +++ b/.github/workflows/docker-build-and-push.yml @@ -0,0 +1,57 @@ +name: Publish Docker image + +on: + push: + branches: + - master + - feature/* + # to allow to wait for a docker image to be published to proceed in another workflow + workflow_call: + +jobs: + push_to_registry: + name: Push Docker image to Git Registry + runs-on: ubuntu-22.04 + permissions: + packages: write + contents: read + attestations: write + steps: + - name: Check out the repo + uses: actions/checkout@v4 + # multi-platform build configured using this https://docs.docker.com/build/ci/github-actions/multi-platform/ + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Log in to GitHub Container Registry + uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + with: + images: ghcr.io/tourmalinecore/${{ github.event.repository.name }} + tags: | + # minimal (short sha) + type=sha + # full length sha + type=sha,format=long + # set latest tag for default branch + # https://github.com/docker/metadata-action/issues/171 explains how to tag latest only on default branch + type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }} + + - name: Build and push Docker image + id: push + uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671 + with: + context: . + file: ./Api/Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + platforms: linux/amd64,linux/arm64 \ No newline at end of file diff --git a/.github/workflows/karate-tests-on-pull-request.yml b/.github/workflows/karate-tests-on-pull-request.yml new file mode 100644 index 0000000..8d080bc --- /dev/null +++ b/.github/workflows/karate-tests-on-pull-request.yml @@ -0,0 +1,97 @@ +name: E2E Tests + +on: + push: + branches: + - feature/* + +jobs: + # this is needed to wait for the new docker image to be build and published to the registry + # so that we can use the image to run ui of the needed commit related version as part of local-env + # the idea is taken from here https://stackoverflow.com/a/71489231 + push_to_registry: + uses: ./.github/workflows/docker-build-and-push.yml + # without this it cannot login to the registry + secrets: inherit + + e2e-test-without-local-env: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - name: Run service via docker-compose and run Karate-tests + # Hide credentials and token from logs, get the number of failed and passed tests + # Find text with 'failed' and 'passed' in logs from karate-testing container + run: | + LOGS=$(docker compose --profile MockForPullRequest up --abort-on-container-exit) + FILTERED_LOGS=$(echo "$LOGS" | sed -E 's/"login":"[^"]*"/"login":"****"/g' \ + | sed -E 's/"password":"[^"]*"/"password":"****"/g' \ + | sed -E 's/"accessToken":[^,}]*"[^"]*"/"accessToken":"****"/g' \ + | sed -E 's/"Authorization":"[^"]*"/"Authorization":"****"/g' \ + | sed -E 's/"X-DEBUG-TOKEN":[^,}]*"[^"]*"/"X-DEBUG-TOKEN":"****"/g' \ + | sed -E 's/accessToken":\{[^}]*\}/accessToken":{"value":"****"}/g' \ + | sed -E 's/X-DEBUG-TOKEN: [^ ]*/X-DEBUG-TOKEN: ****/g') + echo "$FILTERED_LOGS" + FAILED=$(echo "$FILTERED_LOGS" | grep -oP 'failed: *\K\d+') + PASSED=$(echo "$FILTERED_LOGS" | grep -oP 'passed: *\K\d+') + echo "Failed tests: $FAILED" + echo "Passed tests: $PASSED" + if [ "$FAILED" -gt 0 ]; then + echo "Failed tests found! Failing the pipeline..." + exit 1 + fi + if [ "$PASSED" -eq 0 ]; then + echo "No tests passed! Failing the pipeline..." + exit 1 + fi + + e2e-test-with-local-env: + name: Run karate tests in local env + runs-on: ubuntu-22.04 + needs: [push_to_registry] + steps: + - name: Checkout local-env + uses: actions/checkout@v4 + with: + repository: TourmalineCore/inner-circle-local-env + + - name: Deploy Local Env to Kind k8s + uses: devcontainers/ci@v0.3 + with: + runCmd: | + # we need to override "latest" image tag of ui inside local-env to run e2e against the current commit ui version and not against latest from master + yq -i '.image.tag = "sha-${{ github.sha }}"' deploy/values-auth-api.yaml.gotmpl + + kind create cluster --name inner-circle --config kind-local-config.yaml --kubeconfig ./.inner-circle-cluster-kubeconfig + # we need to properly expose KUBECONFIG as an absolute path, pwd prints current working directory path + export KUBECONFIG=$(pwd)/.inner-circle-cluster-kubeconfig + + helmfile --environment local --namespace local -f deploy/helmfile.yaml apply + push: never + # this variable is used by local-env helmfile to use current feature branch helm chart values.yaml file + # this is needed for a case when as part of the feature the chart was changed and is different from master branch + # this should properly fill the feature branch name in spite of the pipeline trigger source (PR, commit, etc.) + # https://stackoverflow.com/a/71158878 + env: | + AUTH_API_BRANCH=${{ github.head_ref || github.ref_name }} + + - name: Checkout api + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + + - name: Download Karate JAR + run: | + curl -L https://github.com/karatelabs/karate/releases/download/v1.5.1/karate-1.5.1.jar -o karate.jar + + - name: Run Karate Tests + run: | + java -jar karate.jar . + env: + AUTH_API_ROOT_URL: "http://localhost:30090/api" + API_ROOT_URL: "http://localhost:30090" + AUTH_LOGIN: "ceo@tourmalinecore.com" + AUTH_PASSWORD: "cEoPa$$wo1d" \ No newline at end of file diff --git a/.github/workflows/prod-docker-publish.yml b/.github/workflows/prod-docker-publish.yml index 6133884..834c506 100644 --- a/.github/workflows/prod-docker-publish.yml +++ b/.github/workflows/prod-docker-publish.yml @@ -1,54 +1,48 @@ -name: deploy service to prod k8s +name: Deploy to Prod on: push: branches: - master - pull_request: - -env: - GITHUB_REGISTRY: ghcr.io jobs: + # this is needed to wait for the new docker image to be build and published to the registry + # so that we can use the image to run ui of the needed commit related version as part of local-env + # the idea is taken from here https://stackoverflow.com/a/71489231 + push_to_registry: + uses: ./.github/workflows/docker-build-and-push.yml + # without this it cannot login to the registry + secrets: inherit - build-image: - name: Build and push service image + deploy-to-prod: + name: Deploy service to k8s for prod environment + needs: [push_to_registry] runs-on: ubuntu-22.04 steps: - - name: checkout - uses: actions/checkout@v1 - - name: Build and push image + - name: Check out the repo + uses: actions/checkout@v4 + + - name: Create default global .kube/config file run: | - echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin - docker build -t $GITHUB_REGISTRY/tourmalinecore/inner-circle/auth-api:latest -t $GITHUB_REGISTRY/tourmalinecore/inner-circle/auth-api:${{ github.sha }} -f Api/Dockerfile . - docker push $GITHUB_REGISTRY/tourmalinecore/inner-circle/auth-api:latest - docker push $GITHUB_REGISTRY/tourmalinecore/inner-circle/auth-api:${{ github.sha }} + cd $HOME + mkdir .kube + echo "${{ secrets.DEV_KUBECONFIG }}" > .kube/config - deploy-to-prod-k8s: - needs: build-image - name: Deploy service to k8s for prod environment - if: github.event_name == 'push' - runs-on: ubuntu-22.04 - steps: - - name: checkout - uses: actions/checkout@v1 - name: Deploy - uses: WyriHaximus/github-action-helm3@v3 + uses: helmfile/helmfile-action@v1.9.0 with: - exec: | - RELEASE_NAME=auth-api - helm repo add bitnami https://charts.bitnami.com/bitnami - helm upgrade --install --namespace dev-inner-circle --create-namespace --values ./Api/ci/values-custom.yaml \ - --set "image.tag=${{ github.sha }}" \ - --set "ingress.enabled=true" \ - --set "ingress.hostname=${{ secrets.DEV_HOST }}" \ - --set "extraSecretEnvVars.ConnectionStrings__DefaultConnection=${{ secrets.DEV_POSTGRESQL_CONNECTION_STRING }}" \ - --set "extraSecretEnvVars.AuthenticationOptions__PublicSigningKey=${{ secrets.DEV_AUTH_PUBLIC_SIGNING_KEY }}" \ - --set "extraSecretEnvVars.AuthenticationOptions__PrivateSigningKey=${{ secrets.DEV_AUTH_PRIVATE_SIGNING_KEY }}" \ - --set "extraSecretEnvVars.InnerCircleServiceUrls__MailServiceUrl=${{ secrets.DEV_MAIL_SERVICE_URL }}" \ - --set "extraSecretEnvVars.InnerCircleServiceUrls__AuthUIServiceUrl=${{ secrets.DEV_AUTH_UI_SERVICE_URL }}" \ - --set "extraSecretEnvVars.InnerCircleServiceUrls__AccountsServiceUrl=${{ secrets.DEV_ACCOUNTS_SERVICE_URL }}" \ - --set "extraSecretEnvVars.InnerCircleServiceUrls__EmployeesServiceUrl=${{ secrets.DEV_EMPLOYEES_SERVICE_URL }}" \ - "${RELEASE_NAME}" \ - bitnami/aspnet-core --version 4.4.7 - kubeconfig: "${{ secrets.DEV_KUBECONFIG }}" + helmfile-version: 'v0.164.0' + helm-version: 'v3.14.4' + helmfile-args: > + apply --namespace dev-inner-circle -f Api/ci/helmfile.yaml + --state-values-set image.tag=sha-${{ github.sha }} + --state-values-set ingress.enabled=true + --state-values-set ingress.hostname=${{ secrets.DEV_HOST }} + --state-values-set extraSecretEnvVars.ConnectionStrings__DefaultConnection=${{ secrets.DEV_POSTGRESQL_CONNECTION_STRING }} + --state-values-set extraSecretEnvVars.AuthenticationOptions__PublicSigningKey=${{ secrets.DEV_AUTH_PUBLIC_SIGNING_KEY }} + --state-values-set extraSecretEnvVars.AuthenticationOptions__PrivateSigningKey=${{ secrets.DEV_AUTH_PRIVATE_SIGNING_KEY }} + --state-values-set extraSecretEnvVars.InnerCircleServiceUrls__MailServiceUrl=${{ secrets.DEV_MAIL_SERVICE_URL }} + --state-values-set extraSecretEnvVars.InnerCircleServiceUrls__AuthUIServiceUrl=${{ secrets.DEV_AUTH_UI_SERVICE_URL }} + --state-values-set extraSecretEnvVars.InnerCircleServiceUrls__AccountsServiceUrl=${{ secrets.DEV_ACCOUNTS_SERVICE_URL }} + --state-values-set extraSecretEnvVars.InnerCircleServiceUrls__EmployeesServiceUrl=${{ secrets.DEV_EMPLOYEES_SERVICE_URL }} + helmfile-auto-init: "false" diff --git a/.github/workflows/unit-tests-on-pull-request.yml b/.github/workflows/unit-tests-on-pull-request.yml new file mode 100644 index 0000000..ffd5d31 --- /dev/null +++ b/.github/workflows/unit-tests-on-pull-request.yml @@ -0,0 +1,23 @@ +name: Unit Tests + +on: + push: + branches: + - feature/* + +jobs: + unit-tests: + name: Run unit tests + runs-on: ubuntu-24.04 + steps: + - name: Check out the repo + uses: actions/checkout@v4 + + - name: Restore application dependencies + run: dotnet restore + + - name: Build application + run: dotnet build + + - name: Run unit-tests + run: dotnet test diff --git a/Api/Dockerfile b/Api/Dockerfile index 39de24c..5ab8fbc 100644 --- a/Api/Dockerfile +++ b/Api/Dockerfile @@ -1,23 +1,30 @@ #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. +# This stage is used when running from VS in fast mode (Default for Debug configuration) FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +USER $APP_UID WORKDIR /app EXPOSE 80 -EXPOSE 443 +# This stage is used to build the service project FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG BUILD_CONFIGURATION=Release +ARG EXCLUDE_UNIT_TESTS_FROM_BUILD=${EXCLUDE_UNIT_TESTS_FROM_BUILD} WORKDIR /src COPY ["Api/Api.csproj", "Api/"] -COPY ["DataAccess/DataAccess.csproj", "DataAccess/"] RUN dotnet restore "Api/Api.csproj" COPY . . WORKDIR "/src/Api" -RUN dotnet build "Api.csproj" -c Release -o /app/build +RUN dotnet build "./Api.csproj" -c $BUILD_CONFIGURATION -o /app/build /p:EXCLUDE_UNIT_TESTS_FROM_BUILD=$EXCLUDE_UNIT_TESTS_FROM_BUILD +# This stage is used to publish the service project to be copied to the final stage FROM build AS publish -RUN dotnet publish "Api.csproj" -c Release -o /app/publish /p:UseAppHost=false +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "./Api.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false /p:EXCLUDE_UNIT_TESTS_FROM_BUILD=$EXCLUDE_UNIT_TESTS_FROM_BUILD +# This stage is used in production or when running from VS in regular mode (Default when not using the Debug configuration) FROM base AS final WORKDIR /app COPY --from=publish /app/publish . +ENV ASPNETCORE_HTTP_PORTS=80 ENTRYPOINT ["dotnet", "Api.dll"] \ No newline at end of file diff --git a/Api/Properties/launchSettings.json b/Api/Properties/launchSettings.json index c13b203..204fdcf 100644 --- a/Api/Properties/launchSettings.json +++ b/Api/Properties/launchSettings.json @@ -1,14 +1,15 @@ { "profiles": { - "Api": { + "MockForDevelopment": { "commandName": "Project", - "launchBrowser": true, - "launchUrl": "swagger", "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Debug" + "ASPNETCORE_URLS": "http://*:5503", + "ASPNETCORE_ENVIRONMENT": "MockForDevelopment" }, - "applicationUrl": "http://localhost:5002", + "publishAllPorts": true, + "useSSL": false, "dotnetRunMessages": true } - } + }, + "$schema": "https://json.schemastore.org/launchsettings.json" } \ No newline at end of file diff --git a/Api/appsettings.LocalEnvForDevelopment.json b/Api/appsettings.LocalEnvForDevelopment.json deleted file mode 100644 index df391c1..0000000 --- a/Api/appsettings.LocalEnvForDevelopment.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "ConnectionStrings": { - "DefaultConnection": "Host=localhost;Port=30100;Database=auth-db;Username=postgres;Password=password" - }, - "AuthenticationOptions": { - "PublicSigningKey": "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAz+luHwhsNo4aQxYNCkaxcqL/HUcqWG1zz3pCpbyW5nbgxoo+Xw0jwAqVeRlrWHZf0WszbPObyCpmGVifyj6n0PSp5Np7431zjUhRUkxwyNSyVE5BWw5aJLyLB5EF9HH39CqtxdtWmYuLzhBS5fZT4tyR4xlQffNTxylg7xZgLfunUDRuLxdqR0JO3sjebgogrDVvHj3sif46uitipeTfUyCtqBG/JngPkMbDMNRkTH6QXnXfLgpX5Lr21O4PZPIBwCXzPCTCDMgbXHLvAzdlqgVYJcLf9xXPtVkPGOv8y+hbSTAyCNLViOLKKm2a2W4bPiElDIDwbtbHesj8zHPlpP5Q7QMtT168UxetgUeKsr5kfpxtLpE/QO4GkkqTA6rV7PQKrCTY0B5V8ZD8Ir/hlOKk8jxGe9NLui+8rLnnwJUZErT7Swp9yQL1eed2YtdrcR3q5eOE8+2pkzwjbEoFuIQidDKOghrZOwf6j217fme/xE+aEP0OPv5z07kJr2torh7tUefrVerT4Krj5LVl4DgdlkHAuILWOaYdSoLnRrsrfFa9Y1alM2D/juH9+YtaR/YjNWOhdZNMNyoDT08SbgE81ZbKmVgLGaWFLcMn/LBD6DBeRb5dRx12QZnv0jGJLVVgjTe9EqrjVF92ahGRljDIGjNzEI2f2syc0/qKS4sCAwEAAQ==", - "PrivateSigningKey": "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" - }, - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "AllowedHosts": "*", - "InnerCircleServiceUrls": { - "MailServiceUrl": "http://inner-circle.local.tourmalinecore.internal/api", - "AuthUIServiceUrl": "http://inner-circle.local.tourmalinecore.internal", - "AccountsServiceUrl": "http://inner-circle.local.tourmalinecore.internal", - "EmployeesServiceUrl": "http://inner-circle.local.tourmalinecore.internal" - } -} \ No newline at end of file diff --git a/Api/appsettings.MockForDevelopment.json b/Api/appsettings.MockForDevelopment.json index 61b9914..54a798a 100644 --- a/Api/appsettings.MockForDevelopment.json +++ b/Api/appsettings.MockForDevelopment.json @@ -1,19 +1,11 @@ { "ConnectionStrings": { - "DefaultConnection": "Host=localhost;Port=10003;Database=auth-db;Username=postgres;Password=postgres" + "DefaultConnection": "Host=localhost;Port=7503;Database=auth-api-db;Username=postgres;Password=postgres" }, "AuthenticationOptions": { "PublicSigningKey": "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAz+luHwhsNo4aQxYNCkaxcqL/HUcqWG1zz3pCpbyW5nbgxoo+Xw0jwAqVeRlrWHZf0WszbPObyCpmGVifyj6n0PSp5Np7431zjUhRUkxwyNSyVE5BWw5aJLyLB5EF9HH39CqtxdtWmYuLzhBS5fZT4tyR4xlQffNTxylg7xZgLfunUDRuLxdqR0JO3sjebgogrDVvHj3sif46uitipeTfUyCtqBG/JngPkMbDMNRkTH6QXnXfLgpX5Lr21O4PZPIBwCXzPCTCDMgbXHLvAzdlqgVYJcLf9xXPtVkPGOv8y+hbSTAyCNLViOLKKm2a2W4bPiElDIDwbtbHesj8zHPlpP5Q7QMtT168UxetgUeKsr5kfpxtLpE/QO4GkkqTA6rV7PQKrCTY0B5V8ZD8Ir/hlOKk8jxGe9NLui+8rLnnwJUZErT7Swp9yQL1eed2YtdrcR3q5eOE8+2pkzwjbEoFuIQidDKOghrZOwf6j217fme/xE+aEP0OPv5z07kJr2torh7tUefrVerT4Krj5LVl4DgdlkHAuILWOaYdSoLnRrsrfFa9Y1alM2D/juH9+YtaR/YjNWOhdZNMNyoDT08SbgE81ZbKmVgLGaWFLcMn/LBD6DBeRb5dRx12QZnv0jGJLVVgjTe9EqrjVF92ahGRljDIGjNzEI2f2syc0/qKS4sCAwEAAQ==", - "PrivateSigningKey": "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" + "IsDebugTokenEnabled": true }, - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "AllowedHosts": "*", "InnerCircleServiceUrls": { "MailServiceUrl": "http://localhost:5005/api", "AuthUIServiceUrl": "https://localhost:3000", diff --git a/Api/appsettings.MockForPullRequest.json b/Api/appsettings.MockForPullRequest.json index f1a2c01..333cd17 100644 --- a/Api/appsettings.MockForPullRequest.json +++ b/Api/appsettings.MockForPullRequest.json @@ -1,23 +1,15 @@ { "ConnectionStrings": { - "DefaultConnection": "Host=localhost;Port=5432;Database=auth-db;Username=postgres;Password=postgres" + "DefaultConnection": "Host=auth-api-db;Port=5432;Database=auth-api-db;Username=postgres;Password=postgres" }, "AuthenticationOptions": { "PublicSigningKey": "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAz+luHwhsNo4aQxYNCkaxcqL/HUcqWG1zz3pCpbyW5nbgxoo+Xw0jwAqVeRlrWHZf0WszbPObyCpmGVifyj6n0PSp5Np7431zjUhRUkxwyNSyVE5BWw5aJLyLB5EF9HH39CqtxdtWmYuLzhBS5fZT4tyR4xlQffNTxylg7xZgLfunUDRuLxdqR0JO3sjebgogrDVvHj3sif46uitipeTfUyCtqBG/JngPkMbDMNRkTH6QXnXfLgpX5Lr21O4PZPIBwCXzPCTCDMgbXHLvAzdlqgVYJcLf9xXPtVkPGOv8y+hbSTAyCNLViOLKKm2a2W4bPiElDIDwbtbHesj8zHPlpP5Q7QMtT168UxetgUeKsr5kfpxtLpE/QO4GkkqTA6rV7PQKrCTY0B5V8ZD8Ir/hlOKk8jxGe9NLui+8rLnnwJUZErT7Swp9yQL1eed2YtdrcR3q5eOE8+2pkzwjbEoFuIQidDKOghrZOwf6j217fme/xE+aEP0OPv5z07kJr2torh7tUefrVerT4Krj5LVl4DgdlkHAuILWOaYdSoLnRrsrfFa9Y1alM2D/juH9+YtaR/YjNWOhdZNMNyoDT08SbgE81ZbKmVgLGaWFLcMn/LBD6DBeRb5dRx12QZnv0jGJLVVgjTe9EqrjVF92ahGRljDIGjNzEI2f2syc0/qKS4sCAwEAAQ==", - "PrivateSigningKey": "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" + "IsDebugTokenEnabled": true }, - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "AllowedHosts": "*", "InnerCircleServiceUrls": { - "MailServiceUrl": "http://mockServer:1080/api", + "MailServiceUrl": "http://auth-api-mock-server:1080/api", "AuthUIServiceUrl": "https://localhost:3000", - "AccountsServiceUrl": "http://mockServer:1080", - "EmployeesServiceUrl": "http://mockServer:1080" + "AccountsServiceUrl": "http://auth-api-mock-server:1080", + "EmployeesServiceUrl": "http://auth-api-mock-server:1080" } } \ No newline at end of file diff --git a/Api/appsettings.ProdForDeployment.json b/Api/appsettings.ProdForDeployment.json deleted file mode 100644 index 1539840..0000000 --- a/Api/appsettings.ProdForDeployment.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "ConnectionStrings": { - "DefaultConnection": "**secret**" - }, - "AuthenticationOptions": { - "PublicSigningKey": "**secret**", - "PrivateSigningKey": "**secret**" - }, - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "AllowedHosts": "*", - "InnerCircleServiceUrls": { - "MailServiceUrl": "**secret**", - "AuthUIServiceUrl": "**secret**", - "AccountsServiceUrl": "**secret**", - "EmployeesServiceUrl": "**secret**" - } -} \ No newline at end of file diff --git a/Api/appsettings.ProdForDevelopment.json b/Api/appsettings.ProdForDevelopment.json deleted file mode 100644 index ecb0178..0000000 --- a/Api/appsettings.ProdForDevelopment.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "ConnectionStrings": { - "DefaultConnection": "not_completed_yet" - }, - "AuthenticationOptions": { - "PublicSigningKey": "not_completed_yet", - "PrivateSigningKey": "not_completed_yet" - }, - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "AllowedHosts": "*", - "InnerCircleServiceUrls": { - "MailServiceUrl": "not_completed_yet", - "AuthUIServiceUrl": "not_completed_yet", - "AccountsServiceUrl": "not_completed_yet", - "EmployeesServiceUrl": "not_completed_yet" - } -} \ No newline at end of file diff --git a/Api/appsettings.json b/Api/appsettings.json index 222224e..ec04bc1 100644 --- a/Api/appsettings.json +++ b/Api/appsettings.json @@ -2,8 +2,7 @@ "Logging": { "LogLevel": { "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" + "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" diff --git a/Api/ci/helmfile.yaml b/Api/ci/helmfile.yaml new file mode 100644 index 0000000..a9fbff2 --- /dev/null +++ b/Api/ci/helmfile.yaml @@ -0,0 +1,25 @@ +repositories: + - name: bitnami + url: https://charts.bitnami.com/bitnami + +releases: + - name: auth-api + labels: + app: auth-api + wait: true + chart: bitnami/aspnet-core + version: 4.4.7 + values: + - values.yaml + - image: + tag: "{{ .StateValues.image.tag }}" + - ingress: + hostname: "{{ .StateValues.ingress.hostname }}" + - extraSecretEnvVars: + ConnectionStrings__DefaultConnection: "{{ .StateValues.extraSecretEnvVars.ConnectionStrings__DefaultConnection }}" + AuthenticationOptions__PublicSigningKey: "{{ .StateValues.extraSecretEnvVars.AuthenticationOptions__PublicSigningKey }}" + AuthenticationOptions__PrivateSigningKey: "{{ .StateValues.extraSecretEnvVars.AuthenticationOptions__PrivateSigningKey }}" + InnerCircleServiceUrls__MailServiceUrl: "{{ .StateValues.extraSecretEnvVars.InnerCircleServiceUrls__MailServiceUrl }}" + InnerCircleServiceUrls__AuthUIServiceUrl: "{{ .StateValues.extraSecretEnvVars.InnerCircleServiceUrls__AuthUIServiceUrl }}" + InnerCircleServiceUrls__AccountsServiceUrl: "{{ .StateValues.extraSecretEnvVars.InnerCircleServiceUrls__AccountsServiceUrl }}" + InnerCircleServiceUrls__EmployeesServiceUrl: "{{ .StateValues.extraSecretEnvVars.InnerCircleServiceUrls__EmployeesServiceUrl }}" \ No newline at end of file diff --git a/Api/ci/values-local-env.yaml b/Api/ci/values-local-env.yaml index ac00a76..2ba5085 100644 --- a/Api/ci/values-local-env.yaml +++ b/Api/ci/values-local-env.yaml @@ -13,7 +13,7 @@ ## image: registry: ghcr.io - repository: tourmalinecore/inner-circle/auth-api + repository: tourmalinecore/inner-circle-auth-api tag: latest ## Optionally specify an array of imagePullSecrets. ## Secrets must be manually created in the namespace. diff --git a/Api/ci/values-custom.yaml b/Api/ci/values.yaml similarity index 99% rename from Api/ci/values-custom.yaml rename to Api/ci/values.yaml index 7f2b51d..4a1806a 100644 --- a/Api/ci/values-custom.yaml +++ b/Api/ci/values.yaml @@ -13,7 +13,7 @@ ## image: registry: ghcr.io - repository: tourmalinecore/inner-circle/auth-api + repository: tourmalinecore/inner-circle-auth-api tag: latest ## Optionally specify an array of imagePullSecrets. ## Secrets must be manually created in the namespace. diff --git a/docker-compose-tests.yml b/docker-compose-tests.yml deleted file mode 100644 index 7b4891d..0000000 --- a/docker-compose-tests.yml +++ /dev/null @@ -1,28 +0,0 @@ -services: - auth-db-test: - image: postgres:14.2-alpine - restart: always - container_name: 'auth-db-test' - networks: - - tests - environment: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: postgres-password - POSTGRES_DB: TCAuthTest - ports: - - 11001:5432 - - auth-tests: - container_name: 'auth-tests' - build: - dockerfile: Tests/Dockerfile - context: . - depends_on: - - auth-db-test - networks: - - tests - volumes: - - ./logs/tc-auth-tests:/var/log/tc-auth-tests - -networks: - tests: {} diff --git a/docker-compose.yml b/docker-compose.yml index e880f3d..72c36f3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,41 +1,98 @@ services: - auth-db: - container_name: 'auth-db' - profiles: ['MockForDevelopment', 'db-only'] - image: postgres:14.2-alpine - restart: always + + auth-api-db: + image: postgres:14 + container_name: 'auth-api-db' + profiles: + - DbOnly + - MockForDevelopment + - MockForTests + - MockForPullRequest environment: + POSTGRES_DB: auth-api-db POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres - POSTGRES_DB: auth-db ports: - - 10003:5432 + - 7503:5432 + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 10s + timeout: 5s + retries: 5 networks: - - auth-network + - auth-api-network auth-api: container_name: 'auth-api' - profiles: ['MockForDevelopment'] + profiles: + - MockForTests + - MockForPullRequest depends_on: - - 'auth-db' + auth-api-db: + condition: service_healthy + auth-api-mock-server: + condition: service_started build: - dockerfile: Api/Dockerfile + dockerfile: ./Api/Dockerfile context: . + args: + EXCLUDE_UNIT_TESTS_FROM_BUILD: "true" + environment: + - ASPNETCORE_ENVIRONMENT=MockForPullRequest ports: - - 10004:80 + - 6503:80 + networks: + - auth-api-network + + auth-api-mock-server: + container_name: 'auth-api-mock-server' + profiles: + - MockForDevelopment + - MockForTests + - MockForPullRequest + image: mockserver/mockserver:5.15.0 + command: -logLevel INFO + ports: + - 8503:1080 + volumes: + - ./e2e/mock-server-initialization.json:/config/mock-server-initialization.json + environment: + SERVER_PORT: 1080 + MOCKSERVER_INITIALIZATION_JSON_PATH: /config/mock-server-initialization.json + networks: + - auth-api-network + + auth-api-karate-tests: + container_name: 'auth-api-karate-tests' + profiles: + - MockForPullRequest + build: + dockerfile: ./e2e/KarateDockerfile + context: . + # service_started is not what we need, we need deps to be healthy and ready, this needs to be implemented in api and mock-server first + depends_on: + auth-api: + condition: service_started + auth-api-mock-server: + condition: service_started + # restart twice in case of not ready db or network failures + restart: on-failure:2 + command: ["karate", "/karate"] + volumes: + - .:/karate environment: - - ASPNETCORE_ENVIRONMENT=MockForDevelopment - - LOGS_PATH=/var/log/dev-auth-api - - ConnectionStrings__DefaultConnection=User ID=postgres;Password=postgres;Host=auth-db;port=5432;Database=auth-db - - AuthenticationOptions__PublicSigningKey=MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAz+luHwhsNo4aQxYNCkaxcqL/HUcqWG1zz3pCpbyW5nbgxoo+Xw0jwAqVeRlrWHZf0WszbPObyCpmGVifyj6n0PSp5Np7431zjUhRUkxwyNSyVE5BWw5aJLyLB5EF9HH39CqtxdtWmYuLzhBS5fZT4tyR4xlQffNTxylg7xZgLfunUDRuLxdqR0JO3sjebgogrDVvHj3sif46uitipeTfUyCtqBG/JngPkMbDMNRkTH6QXnXfLgpX5Lr21O4PZPIBwCXzPCTCDMgbXHLvAzdlqgVYJcLf9xXPtVkPGOv8y+hbSTAyCNLViOLKKm2a2W4bPiElDIDwbtbHesj8zHPlpP5Q7QMtT168UxetgUeKsr5kfpxtLpE/QO4GkkqTA6rV7PQKrCTY0B5V8ZD8Ir/hlOKk8jxGe9NLui+8rLnnwJUZErT7Swp9yQL1eed2YtdrcR3q5eOE8+2pkzwjbEoFuIQidDKOghrZOwf6j217fme/xE+aEP0OPv5z07kJr2torh7tUefrVerT4Krj5LVl4DgdlkHAuILWOaYdSoLnRrsrfFa9Y1alM2D/juH9+YtaR/YjNWOhdZNMNyoDT08SbgE81ZbKmVgLGaWFLcMn/LBD6DBeRb5dRx12QZnv0jGJLVVgjTe9EqrjVF92ahGRljDIGjNzEI2f2syc0/qKS4sCAwEAAQ== - - AuthenticationOptions__PrivateSigningKey=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 - - InnerCircleServiceUrls__MailServiceUrl=http://email-sender-api:80 - - InnerCircleServiceUrls__AccountsServiceUrl=http://accounts-api:80 + AUTH_FIRST_TENANT_LOGIN_WITH_ALL_PERMISSIONS: "first-tenant-login-with-all-permissions" + AUTH_FIRST_TENANT_PASSWORD_WITH_ALL_PERMISSIONS: "first-tenant-password-with-all-permissions" + AUTH_SECOND_TENANT_LOGIN_WITH_ALL_PERMISSIONS: "second-tenant-login-with-all-permissions" + AUTH_SECOND_TENANT_PASSWORD_WITH_ALL_PERMISSIONS: "second-tenant-password-with-all-permissions" + AUTH_LOGIN_WITHOUT_PERMISSIONS: "first-tenant-login-without-permissions" + AUTH_PASSWORD_WITHOUT_PERMISSIONS: "first-tenant-password-without-permissions" + # here the port is 1080 because it needs to be an internal port, not an external which is 8501 in this case + AUTH_API_ROOT_URL: "http://auth-api-mock-server:1080" + API_ROOT_URL: "http://auth-api" + SHOULD_USE_FAKE_EXTERNAL_DEPENDENCIES: "true" networks: - - auth-network - - ic-backend-deb + - auth-api-network networks: - auth-network: {} - ic-backend-deb: - external: true + auth-api-network: diff --git a/e2e/KarateDockerfile b/e2e/KarateDockerfile new file mode 100644 index 0000000..748b5d5 --- /dev/null +++ b/e2e/KarateDockerfile @@ -0,0 +1,11 @@ +FROM eclipse-temurin:17-jre-noble + +RUN apt-get update && apt-get install -y curl + +RUN apt-get install -y unzip + +RUN curl -o /karate.jar -L 'https://github.com/intuit/karate/releases/download/v1.5.1/karate-1.5.1.jar' + +COPY ./e2e/js-utils.js . + +ENTRYPOINT ["java", "-jar", "karate.jar"] diff --git a/e2e/item-types-happy-path.feature b/e2e/item-types-happy-path.feature new file mode 100644 index 0000000..3d5c583 --- /dev/null +++ b/e2e/item-types-happy-path.feature @@ -0,0 +1,71 @@ +Feature: Item Types +# https://github.com/karatelabs/karate/issues/1191 +# https://github.com/karatelabs/karate?tab=readme-ov-file#karate-fork + +Background: +* header Content-Type = 'application/json' + +Scenario: Happy Path + + * def jsUtils = read('./js-utils.js') + * def authApiRootUrl = jsUtils().getEnvVariable('AUTH_API_ROOT_URL') + * def apiRootUrl = jsUtils().getEnvVariable('API_ROOT_URL') + * def authLogin = jsUtils().getEnvVariable('AUTH_FIRST_TENANT_LOGIN_WITH_ALL_PERMISSIONS') + * def authPassword = jsUtils().getEnvVariable('AUTH_FIRST_TENANT_PASSWORD_WITH_ALL_PERMISSIONS') + + # Authentication + Given url authApiRootUrl + And path '/auth/login' + And request + """ + { + "login": "#(authLogin)", + "password": "#(authPassword)" + } + """ + And method POST + Then status 200 + + * def accessToken = karate.toMap(response.accessToken.value) + + * configure headers = jsUtils().getAuthHeaders(accessToken) + + # Step 1: Create a new item type + * def randomName = '[API-E2E]-Test-item-type-' + Math.random() + + Given url apiRootUrl + Given path 'item-types' + And request + """ + { + "name": "#(randomName)" + } + """ + When method POST + Then status 200 + + * def newItemTypeId = response.newItemTypeId + + # Step 2: Verify that item type is in the list with the id and generated name + Given url apiRootUrl + Given path 'item-types' + When method GET + And match response.itemTypes contains + """ + { + "id": "#(newItemTypeId)", + "name": "#(randomName)" + } + """ + + # Cleanup: Delete the item type (hard delete) + Given path 'item-types', newItemTypeId, 'hard-delete' + When method DELETE + Then status 200 + And match response == { isDeleted: true } + + # Cleanup Verification: Verify that item type was deleted + Given url apiRootUrl + Given path 'item-types' + When method GET + And assert response.itemTypes.filter(x => x.id == newItemTypeId).length == 0 diff --git a/e2e/js-utils.js b/e2e/js-utils.js new file mode 100644 index 0000000..d0dc43d --- /dev/null +++ b/e2e/js-utils.js @@ -0,0 +1,31 @@ +function fn() { + return { + getAuthHeaders: function (tokenValue) { + return { + [this.getAuthHeaderKey()]: this.getAuthHeaderValue(tokenValue) + } + }, + + getAuthHeaderKey: function () { + return this.shouldUseFakeExternalDependencies() + ? 'X-DEBUG-TOKEN' + : 'Authorization'; + }, + + getAuthHeaderValue: function (tokenValue) { + return this.shouldUseFakeExternalDependencies() + ? tokenValue + : 'Bearer ' + tokenValue; + }, + + shouldUseFakeExternalDependencies: function () { + return this.getEnvVariable('SHOULD_USE_FAKE_EXTERNAL_DEPENDENCIES') === 'true'; + }, + + getEnvVariable: function (variable) { + var System = Java.type('java.lang.System'); + + return System.getenv(variable); + }, + } +} \ No newline at end of file diff --git a/e2e/mock-server-initialization.json b/e2e/mock-server-initialization.json new file mode 100644 index 0000000..c9c513b --- /dev/null +++ b/e2e/mock-server-initialization.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file From f00a47d38c15d1c49ae3262f1da93f8bcf6838a5 Mon Sep 17 00:00:00 2001 From: Anastasia Saraeva Date: Thu, 18 Sep 2025 13:46:46 +0500 Subject: [PATCH 03/13] test: add test for check employeeId in token --- .../workflows/unit-tests-on-pull-request.yml | 23 ------ docker-compose.yml | 11 +-- e2e/check-employeeId-in-token.feature | 31 ++++++++ e2e/item-types-happy-path.feature | 71 ------------------- e2e/js-utils.js | 43 +++++------ e2e/mock-server-initialization.json | 45 +++++++++++- 6 files changed, 97 insertions(+), 127 deletions(-) delete mode 100644 .github/workflows/unit-tests-on-pull-request.yml create mode 100644 e2e/check-employeeId-in-token.feature delete mode 100644 e2e/item-types-happy-path.feature diff --git a/.github/workflows/unit-tests-on-pull-request.yml b/.github/workflows/unit-tests-on-pull-request.yml deleted file mode 100644 index ffd5d31..0000000 --- a/.github/workflows/unit-tests-on-pull-request.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Unit Tests - -on: - push: - branches: - - feature/* - -jobs: - unit-tests: - name: Run unit tests - runs-on: ubuntu-24.04 - steps: - - name: Check out the repo - uses: actions/checkout@v4 - - - name: Restore application dependencies - run: dotnet restore - - - name: Build application - run: dotnet build - - - name: Run unit-tests - run: dotnet test diff --git a/docker-compose.yml b/docker-compose.yml index 72c36f3..b06d310 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -81,16 +81,7 @@ services: volumes: - .:/karate environment: - AUTH_FIRST_TENANT_LOGIN_WITH_ALL_PERMISSIONS: "first-tenant-login-with-all-permissions" - AUTH_FIRST_TENANT_PASSWORD_WITH_ALL_PERMISSIONS: "first-tenant-password-with-all-permissions" - AUTH_SECOND_TENANT_LOGIN_WITH_ALL_PERMISSIONS: "second-tenant-login-with-all-permissions" - AUTH_SECOND_TENANT_PASSWORD_WITH_ALL_PERMISSIONS: "second-tenant-password-with-all-permissions" - AUTH_LOGIN_WITHOUT_PERMISSIONS: "first-tenant-login-without-permissions" - AUTH_PASSWORD_WITHOUT_PERMISSIONS: "first-tenant-password-without-permissions" - # here the port is 1080 because it needs to be an internal port, not an external which is 8501 in this case - AUTH_API_ROOT_URL: "http://auth-api-mock-server:1080" - API_ROOT_URL: "http://auth-api" - SHOULD_USE_FAKE_EXTERNAL_DEPENDENCIES: "true" + API_ROOT_URL: "http://auth-api/api" networks: - auth-api-network diff --git a/e2e/check-employeeId-in-token.feature b/e2e/check-employeeId-in-token.feature new file mode 100644 index 0000000..5b2ab26 --- /dev/null +++ b/e2e/check-employeeId-in-token.feature @@ -0,0 +1,31 @@ +Feature: Auth API +# https://github.com/karatelabs/karate/issues/1191 +# https://github.com/karatelabs/karate?tab=readme-ov-file#karate-fork + +Background: +* header Content-Type = 'application/json' + +Scenario: Check employeeId in token + + * def jsUtils = read('./js-utils.js') + * def apiRootUrl = jsUtils().getEnvVariable('API_ROOT_URL') + * def authLogin = jsUtils().getEnvVariable('AUTH_LOGIN') + * def authPassword = jsUtils().getEnvVariable('AUTH_PASSWORD') + + # Authentication + Given url apiRootUrl + And path '/auth/login' + And request + """ + { + "login": "#(authLogin)", + "password": "#(authPassword)" + } + """ + And method POST + Then status 200 + + * def accessToken = karate.toMap(response.accessToken.value) + * def employeeId = jsUtils().getEmployeeIdFromToken(accessToken) + * match employeeId == '#notnull' + diff --git a/e2e/item-types-happy-path.feature b/e2e/item-types-happy-path.feature deleted file mode 100644 index 3d5c583..0000000 --- a/e2e/item-types-happy-path.feature +++ /dev/null @@ -1,71 +0,0 @@ -Feature: Item Types -# https://github.com/karatelabs/karate/issues/1191 -# https://github.com/karatelabs/karate?tab=readme-ov-file#karate-fork - -Background: -* header Content-Type = 'application/json' - -Scenario: Happy Path - - * def jsUtils = read('./js-utils.js') - * def authApiRootUrl = jsUtils().getEnvVariable('AUTH_API_ROOT_URL') - * def apiRootUrl = jsUtils().getEnvVariable('API_ROOT_URL') - * def authLogin = jsUtils().getEnvVariable('AUTH_FIRST_TENANT_LOGIN_WITH_ALL_PERMISSIONS') - * def authPassword = jsUtils().getEnvVariable('AUTH_FIRST_TENANT_PASSWORD_WITH_ALL_PERMISSIONS') - - # Authentication - Given url authApiRootUrl - And path '/auth/login' - And request - """ - { - "login": "#(authLogin)", - "password": "#(authPassword)" - } - """ - And method POST - Then status 200 - - * def accessToken = karate.toMap(response.accessToken.value) - - * configure headers = jsUtils().getAuthHeaders(accessToken) - - # Step 1: Create a new item type - * def randomName = '[API-E2E]-Test-item-type-' + Math.random() - - Given url apiRootUrl - Given path 'item-types' - And request - """ - { - "name": "#(randomName)" - } - """ - When method POST - Then status 200 - - * def newItemTypeId = response.newItemTypeId - - # Step 2: Verify that item type is in the list with the id and generated name - Given url apiRootUrl - Given path 'item-types' - When method GET - And match response.itemTypes contains - """ - { - "id": "#(newItemTypeId)", - "name": "#(randomName)" - } - """ - - # Cleanup: Delete the item type (hard delete) - Given path 'item-types', newItemTypeId, 'hard-delete' - When method DELETE - Then status 200 - And match response == { isDeleted: true } - - # Cleanup Verification: Verify that item type was deleted - Given url apiRootUrl - Given path 'item-types' - When method GET - And assert response.itemTypes.filter(x => x.id == newItemTypeId).length == 0 diff --git a/e2e/js-utils.js b/e2e/js-utils.js index d0dc43d..0ddb33a 100644 --- a/e2e/js-utils.js +++ b/e2e/js-utils.js @@ -1,31 +1,32 @@ function fn() { + function decodeString(string) { + var Bytes = Java.type('java.util.Base64'); + var decodedBytes = Bytes.getDecoder().decode(string); + + return new java.lang.String(decodedBytes); + } + return { - getAuthHeaders: function (tokenValue) { - return { - [this.getAuthHeaderKey()]: this.getAuthHeaderValue(tokenValue) - } - }, + getEnvVariable: function (variable) { + var System = Java.type('java.lang.System'); - getAuthHeaderKey: function () { - return this.shouldUseFakeExternalDependencies() - ? 'X-DEBUG-TOKEN' - : 'Authorization'; + return System.getenv(variable); }, - getAuthHeaderValue: function (tokenValue) { - return this.shouldUseFakeExternalDependencies() - ? tokenValue - : 'Bearer ' + tokenValue; - }, + getEmployeeIdFromToken: function (tokenValue) { + var decodedString; - shouldUseFakeExternalDependencies: function () { - return this.getEnvVariable('SHOULD_USE_FAKE_EXTERNAL_DEPENDENCIES') === 'true'; - }, + if (tokenValue.includes('.')) { + var payload = tokenValue.split('.')[1]; - getEnvVariable: function (variable) { - var System = Java.type('java.lang.System'); + decodedString = decodeString(payload); + } else { + decodedString = decodeString(tokenValue); + } - return System.getenv(variable); - }, + var tokenData = JSON.parse(decodedString); + + return tokenData.employeeId; + } } } \ No newline at end of file diff --git a/e2e/mock-server-initialization.json b/e2e/mock-server-initialization.json index c9c513b..2e77c79 100644 --- a/e2e/mock-server-initialization.json +++ b/e2e/mock-server-initialization.json @@ -1,3 +1,44 @@ [ - -] \ No newline at end of file + { + "httpRequest": { + "method": "GET", + "path": "/internal/get-employee", + "queryStringParameters": { + "corporateEmail": ["trial@tourmalinecore.com"] + } + }, + "httpResponse": { + "statusCode": 200, + "body": "{ \"id\": 3, \"fullName\": \"Trial Trial Trial\", \"corporateEmail\": \"trial@tourmalinecore.com\", \"tenantId\": 3}", + "headers": { + "Content-Type": ["application/json"] + } + } + }, + { + "httpRequest": { + "method": "GET", + "path": "/internal/get-tenantId-by-accountId/3" + }, + "httpResponse": { + "statusCode": 200, + "body": "1", + "headers": { + "Content-Type": ["text/plain; charset=utf-8"] + } + } + }, + { + "httpRequest": { + "method": "GET", + "path": "/internal/account-permissions/3" + }, + "httpResponse": { + "statusCode": 200, + "body": "[\"CanViewBooks\", \"CanTakeBooks\"]", + "headers": { + "Content-Type": ["application/json"] + } + } + } +] From 5a9398524d7507101a45ac16ae177f08313b5624 Mon Sep 17 00:00:00 2001 From: Anastasia Saraeva Date: Thu, 18 Sep 2025 15:13:37 +0500 Subject: [PATCH 04/13] chore: update PrivateSigningKey --- Api/appsettings.MockForDevelopment.json | 1 + Api/appsettings.MockForPullRequest.json | 1 + 2 files changed, 2 insertions(+) diff --git a/Api/appsettings.MockForDevelopment.json b/Api/appsettings.MockForDevelopment.json index 54a798a..75c0622 100644 --- a/Api/appsettings.MockForDevelopment.json +++ b/Api/appsettings.MockForDevelopment.json @@ -4,6 +4,7 @@ }, "AuthenticationOptions": { "PublicSigningKey": "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAz+luHwhsNo4aQxYNCkaxcqL/HUcqWG1zz3pCpbyW5nbgxoo+Xw0jwAqVeRlrWHZf0WszbPObyCpmGVifyj6n0PSp5Np7431zjUhRUkxwyNSyVE5BWw5aJLyLB5EF9HH39CqtxdtWmYuLzhBS5fZT4tyR4xlQffNTxylg7xZgLfunUDRuLxdqR0JO3sjebgogrDVvHj3sif46uitipeTfUyCtqBG/JngPkMbDMNRkTH6QXnXfLgpX5Lr21O4PZPIBwCXzPCTCDMgbXHLvAzdlqgVYJcLf9xXPtVkPGOv8y+hbSTAyCNLViOLKKm2a2W4bPiElDIDwbtbHesj8zHPlpP5Q7QMtT168UxetgUeKsr5kfpxtLpE/QO4GkkqTA6rV7PQKrCTY0B5V8ZD8Ir/hlOKk8jxGe9NLui+8rLnnwJUZErT7Swp9yQL1eed2YtdrcR3q5eOE8+2pkzwjbEoFuIQidDKOghrZOwf6j217fme/xE+aEP0OPv5z07kJr2torh7tUefrVerT4Krj5LVl4DgdlkHAuILWOaYdSoLnRrsrfFa9Y1alM2D/juH9+YtaR/YjNWOhdZNMNyoDT08SbgE81ZbKmVgLGaWFLcMn/LBD6DBeRb5dRx12QZnv0jGJLVVgjTe9EqrjVF92ahGRljDIGjNzEI2f2syc0/qKS4sCAwEAAQ==", + "PrivateSigningKey": "MIIEogIBAAKCAQEArYPimgsy6jR66moJgO96DjvnWQ0kM3kd2x+EOC5NB9P2zxLzSSMZalqDlaVhEkhsic3lXwHcHjgs+ZBeE7mh1epQ27J6NwycUCD7abFHrORn2DHY0JC2f7ol8Bjv7lmx18cgOsq1vlF0IpeDgc6Us+Bfa4XNMbgT4wDTn68231S38Ny/fMptk/8H/Wv30wFdrnMM/BTr9bzHm0crync4Lgnrosz+87JpP0X8cwCAeLElX8OOI32EZNZUhxkBTv2Hmnq//lqP7XgwiRVU5Ue0ZHisP8XZT5ep+3ovUZWCYDCxa693zWSBlDxqZN14HA8aA59WdintywvXdqkOtrfRbwIDAQABAoIBADzipN6B5H1LKgBccfZE0fLxsTXNxzCqpL/RmM8v7Aa9qYKy9xxoTRBFL5wQmnXUZQWb8or6d5dBBgMSVfic8D1ESdg1ke4EJkt1r1LAitKPmSLDJv3Ucb1y/8H2tiZQYffB3zzSCaD9Kv/CY7pmV0ahCkqL+lsiaRQEI74KOPp3R13kljbkCCEEw3hZT9renUxpVxPDo1cb5x9SIzS1kjWhekrSVzocDx6bZnPt/mNVoxoScuQt+XVhxRlwkalBBv7nBzK6/2xX2ojJKiI5yUPB8u/sevRg8QhI9myyZCVBTQkBzA+qTFYUkJsy9biO231b+QO7AwFIIsF2KBp6mM0CgYEA1txpfK45G93A5cGx0hRcOaqvQO/osSjJXCisLS33PRbs3DgibE0R1rMC4aA0brj68fd4wvZlcVU8g5xPdX9iy9bh4t6p3GG1fubiKNiLawYf2DRrVpHOyRXMw1u2oRcxYsmR+qiug+3EdNJfF8NmQ7fbeHpY1k+/RgvFyWivBt0CgYEAzrzf0f6BY45eXe8En+r09MfiMYbhPKgq572wUsy86Gn07JePibZb/B+HYg3jF7TbjMBkKggWNr8fx8OiO13ZQoTttMcwCNS5FSippB3V2JgR/KDA0meIuwjG7yl0Eanrdf43/mHceup4ZZvOEQvhXv7/lM3pw3KPDePtqtstJrsCgYB50/BcKc1n540AuZtCKxk/+W/1uhKOoTnLb6Rw2adelCkplQqvreN3gXkYxeX1Ah4IJPHsWhma8WGmnnLPhLNYMTdTlD1sIFrw4alKz739qTNVPCPAqlw92IaKHu6m2KfAA9sp7YtGcwL52m7g4oKR0yY2YekNW5pw9Svoz9quYQKBgCL2J/ewTZtTeTvzbtnIdzJqFyN/BtomKlNUbdwiyZOYT5YvL1P/peCmSFPZu1zH9hUAeC/vfCo3+hzjRa06esJYDoby5Hmp177vSHj7nq1pUilh2hn67lGK83GAliNik/I5UqjPTeTvf/rW9WtGkg9pmjlE9VJbLjwQHqI1PJZ/AoGASnF/RSTN0OoW0Tgjj4Zt4kX34lYDU1rwfoK65w8R98Yr06GlPG2aI4tWtWnN7hdNmxs6Ib58rxrWryXgkHV5wJZgwCI+bkq3ad7H1leq/ROXbBhX/OYhHAs/tlDl8RK8V4jzBaS3WTIemPmb268huBjIVlnK+FAwP4lQsVuQeCo=", "IsDebugTokenEnabled": true }, "InnerCircleServiceUrls": { diff --git a/Api/appsettings.MockForPullRequest.json b/Api/appsettings.MockForPullRequest.json index 333cd17..ce12678 100644 --- a/Api/appsettings.MockForPullRequest.json +++ b/Api/appsettings.MockForPullRequest.json @@ -4,6 +4,7 @@ }, "AuthenticationOptions": { "PublicSigningKey": "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAz+luHwhsNo4aQxYNCkaxcqL/HUcqWG1zz3pCpbyW5nbgxoo+Xw0jwAqVeRlrWHZf0WszbPObyCpmGVifyj6n0PSp5Np7431zjUhRUkxwyNSyVE5BWw5aJLyLB5EF9HH39CqtxdtWmYuLzhBS5fZT4tyR4xlQffNTxylg7xZgLfunUDRuLxdqR0JO3sjebgogrDVvHj3sif46uitipeTfUyCtqBG/JngPkMbDMNRkTH6QXnXfLgpX5Lr21O4PZPIBwCXzPCTCDMgbXHLvAzdlqgVYJcLf9xXPtVkPGOv8y+hbSTAyCNLViOLKKm2a2W4bPiElDIDwbtbHesj8zHPlpP5Q7QMtT168UxetgUeKsr5kfpxtLpE/QO4GkkqTA6rV7PQKrCTY0B5V8ZD8Ir/hlOKk8jxGe9NLui+8rLnnwJUZErT7Swp9yQL1eed2YtdrcR3q5eOE8+2pkzwjbEoFuIQidDKOghrZOwf6j217fme/xE+aEP0OPv5z07kJr2torh7tUefrVerT4Krj5LVl4DgdlkHAuILWOaYdSoLnRrsrfFa9Y1alM2D/juH9+YtaR/YjNWOhdZNMNyoDT08SbgE81ZbKmVgLGaWFLcMn/LBD6DBeRb5dRx12QZnv0jGJLVVgjTe9EqrjVF92ahGRljDIGjNzEI2f2syc0/qKS4sCAwEAAQ==", + "PrivateSigningKey": "MIIEogIBAAKCAQEArYPimgsy6jR66moJgO96DjvnWQ0kM3kd2x+EOC5NB9P2zxLzSSMZalqDlaVhEkhsic3lXwHcHjgs+ZBeE7mh1epQ27J6NwycUCD7abFHrORn2DHY0JC2f7ol8Bjv7lmx18cgOsq1vlF0IpeDgc6Us+Bfa4XNMbgT4wDTn68231S38Ny/fMptk/8H/Wv30wFdrnMM/BTr9bzHm0crync4Lgnrosz+87JpP0X8cwCAeLElX8OOI32EZNZUhxkBTv2Hmnq//lqP7XgwiRVU5Ue0ZHisP8XZT5ep+3ovUZWCYDCxa693zWSBlDxqZN14HA8aA59WdintywvXdqkOtrfRbwIDAQABAoIBADzipN6B5H1LKgBccfZE0fLxsTXNxzCqpL/RmM8v7Aa9qYKy9xxoTRBFL5wQmnXUZQWb8or6d5dBBgMSVfic8D1ESdg1ke4EJkt1r1LAitKPmSLDJv3Ucb1y/8H2tiZQYffB3zzSCaD9Kv/CY7pmV0ahCkqL+lsiaRQEI74KOPp3R13kljbkCCEEw3hZT9renUxpVxPDo1cb5x9SIzS1kjWhekrSVzocDx6bZnPt/mNVoxoScuQt+XVhxRlwkalBBv7nBzK6/2xX2ojJKiI5yUPB8u/sevRg8QhI9myyZCVBTQkBzA+qTFYUkJsy9biO231b+QO7AwFIIsF2KBp6mM0CgYEA1txpfK45G93A5cGx0hRcOaqvQO/osSjJXCisLS33PRbs3DgibE0R1rMC4aA0brj68fd4wvZlcVU8g5xPdX9iy9bh4t6p3GG1fubiKNiLawYf2DRrVpHOyRXMw1u2oRcxYsmR+qiug+3EdNJfF8NmQ7fbeHpY1k+/RgvFyWivBt0CgYEAzrzf0f6BY45eXe8En+r09MfiMYbhPKgq572wUsy86Gn07JePibZb/B+HYg3jF7TbjMBkKggWNr8fx8OiO13ZQoTttMcwCNS5FSippB3V2JgR/KDA0meIuwjG7yl0Eanrdf43/mHceup4ZZvOEQvhXv7/lM3pw3KPDePtqtstJrsCgYB50/BcKc1n540AuZtCKxk/+W/1uhKOoTnLb6Rw2adelCkplQqvreN3gXkYxeX1Ah4IJPHsWhma8WGmnnLPhLNYMTdTlD1sIFrw4alKz739qTNVPCPAqlw92IaKHu6m2KfAA9sp7YtGcwL52m7g4oKR0yY2YekNW5pw9Svoz9quYQKBgCL2J/ewTZtTeTvzbtnIdzJqFyN/BtomKlNUbdwiyZOYT5YvL1P/peCmSFPZu1zH9hUAeC/vfCo3+hzjRa06esJYDoby5Hmp177vSHj7nq1pUilh2hn67lGK83GAliNik/I5UqjPTeTvf/rW9WtGkg9pmjlE9VJbLjwQHqI1PJZ/AoGASnF/RSTN0OoW0Tgjj4Zt4kX34lYDU1rwfoK65w8R98Yr06GlPG2aI4tWtWnN7hdNmxs6Ib58rxrWryXgkHV5wJZgwCI+bkq3ad7H1leq/ROXbBhX/OYhHAs/tlDl8RK8V4jzBaS3WTIemPmb268huBjIVlnK+FAwP4lQsVuQeCo=", "IsDebugTokenEnabled": true }, "InnerCircleServiceUrls": { From 7d4043c9691e9e3aff0d19f22fe5ab6eec20c8b6 Mon Sep 17 00:00:00 2001 From: akovylyaeva Date: Thu, 18 Sep 2025 15:15:18 +0500 Subject: [PATCH 05/13] chore: update KarateDockerfile, update README.md, and remove unnecessary containerEnvs --- .devcontainer/devcontainer.json | 8 ----- README.md | 55 ++++++++++++++++++++++++++++----- e2e/KarateDockerfile | 4 +-- 3 files changed, 49 insertions(+), 18 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index f12b233..7150551 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -20,14 +20,6 @@ } }, "containerEnv": { - "AUTH_FIRST_TENANT_LOGIN_WITH_ALL_PERMISSIONS": "first-tenant-login-with-all-permissions", - "AUTH_FIRST_TENANT_PASSWORD_WITH_ALL_PERMISSIONS": "first-tenant-password-with-all-permissions", - "AUTH_SECOND_TENANT_LOGIN_WITH_ALL_PERMISSIONS": "second-tenant-login-with-all-permissions", - "AUTH_SECOND_TENANT_PASSWORD_WITH_ALL_PERMISSIONS": "second-tenant-password-with-all-permissions", - "AUTH_LOGIN_WITHOUT_PERMISSIONS": "first-tenant-login-without-permissions", - "AUTH_PASSWORD_WITHOUT_PERMISSIONS": "first-tenant-password-without-permissions", - "AUTH_API_ROOT_URL": "http://localhost:8503", "API_ROOT_URL": "http://localhost:6503", - "SHOULD_USE_FAKE_EXTERNAL_DEPENDENCIES": "true" } } \ No newline at end of file diff --git a/README.md b/README.md index 73ec553..8f75f5c 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,56 @@ # inner-circle-auth-api -## Launch docker containers +## Run in Visual Studio -1. You need to create an internal network for configuring interaction between different back-end services. -You can do it using the following command in your terminal: `docker network create ic-backend-deb`. -Note: If you already has this network, skip this step. +First run this script to run a db and mocked external deps: -2. Execute the command `docker-compose up -d` from source folder +```bash +docker compose --profile MockForDevelopment up --build +``` + +## Karate Tests + +### Run Karate Tests Against Api Running in IDE (not Docker Compose) + +Run Db and MockServer executing the following command (don't close the terminal unless you want to stop the containers) + +```bash +docker compose --profile MockForDevelopment up --build +``` -## Configurations +Then execute following command inside of the dev-container -- MockForPullRequest - used in PR pipeline to run the service in isolation (no external deps) and run its Karate tests against it -- MockForDevelopment - used locally when you run the service in Visual Studio e.g. in Debug and don't want to spin up any external deps +```bash +API_ROOT_URL=http://host.docker.internal:5503 java -jar /karate.jar . +``` + +### Run Karate against Api, Db, and MockServer in Docker Compose + +Run Api, Db, and MockServer executing the following command (don't close the terminal unless you want to stop the containers) + +```bash +docker compose --profile MockForTests up --build +``` + +Then execute following command inside of the dev-container + +```bash +java -jar /karate.jar . +``` + +### Running Karate Tests, Api, Db, and MockServer in Docker Compose + +Run the docker compose with MockForPullRequest profile executing the following command (don't close the terminal unless you want to stop the containers) + +```bash +docker compose --profile MockForPullRequest up --build +``` + +>Note: this also includes Karate Tests run by default. However, if you want to run the test again from Dev Container execute: + +```bash +java -jar /karate.jar . +``` ## Database scheme diff --git a/e2e/KarateDockerfile b/e2e/KarateDockerfile index 748b5d5..e3f5cfa 100644 --- a/e2e/KarateDockerfile +++ b/e2e/KarateDockerfile @@ -1,10 +1,10 @@ -FROM eclipse-temurin:17-jre-noble +FROM openjdk:11-jre-slim RUN apt-get update && apt-get install -y curl RUN apt-get install -y unzip -RUN curl -o /karate.jar -L 'https://github.com/intuit/karate/releases/download/v1.5.1/karate-1.5.1.jar' +RUN curl -o /karate.jar -L 'https://github.com/intuit/karate/releases/download/v1.4.1/karate-1.4.1.jar' COPY ./e2e/js-utils.js . From 69dc3bd426abf356147b9d7b05e62f166cdf9711 Mon Sep 17 00:00:00 2001 From: akovylyaeva Date: Thu, 18 Sep 2025 16:25:55 +0500 Subject: [PATCH 06/13] chore: fix repository name in values.yaml --- Api/ci/values-local-env.yaml | 2 +- Api/ci/values.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Api/ci/values-local-env.yaml b/Api/ci/values-local-env.yaml index 2ba5085..9403589 100644 --- a/Api/ci/values-local-env.yaml +++ b/Api/ci/values-local-env.yaml @@ -13,7 +13,7 @@ ## image: registry: ghcr.io - repository: tourmalinecore/inner-circle-auth-api + repository: tourmalinecore/auth-api tag: latest ## Optionally specify an array of imagePullSecrets. ## Secrets must be manually created in the namespace. diff --git a/Api/ci/values.yaml b/Api/ci/values.yaml index 4a1806a..b8a2811 100644 --- a/Api/ci/values.yaml +++ b/Api/ci/values.yaml @@ -13,7 +13,7 @@ ## image: registry: ghcr.io - repository: tourmalinecore/inner-circle-auth-api + repository: tourmalinecore/auth-api tag: latest ## Optionally specify an array of imagePullSecrets. ## Secrets must be manually created in the namespace. From 9d13a393d12049507892aaff3c0c188bce2ee320 Mon Sep 17 00:00:00 2001 From: akovylyaeva Date: Mon, 22 Sep 2025 13:49:55 +0500 Subject: [PATCH 07/13] ci: update karate-tests-on-pull-request.yml --- .../workflows/karate-tests-on-pull-request.yml | 16 +++++++++------- README.md | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.github/workflows/karate-tests-on-pull-request.yml b/.github/workflows/karate-tests-on-pull-request.yml index 8d080bc..8ca24a6 100644 --- a/.github/workflows/karate-tests-on-pull-request.yml +++ b/.github/workflows/karate-tests-on-pull-request.yml @@ -59,7 +59,15 @@ jobs: with: runCmd: | # we need to override "latest" image tag of ui inside local-env to run e2e against the current commit ui version and not against latest from master - yq -i '.image.tag = "sha-${{ github.sha }}"' deploy/values-auth-api.yaml.gotmpl + # We tried to use yq to change the image tag, but in the values files for helmfile we have non-yaml code that yq can`t parse or ignore + # so for that reason we use Stream EDitor which can find needed string using regular expressions and change it to a new value + # The -i flag is needed to write new image tag directly to values file + sed -i "0,/tag:.*/s//tag: \"sha-${{ github.sha }}\"/" deploy/values-auth-api.yaml.gotmpl + + # we need to override "latest" ref of service chart inside local-env to run tests against the current commit service chart version and not against latest from master + sed -i "0,/git+https:\/\/github.com\/TourmalineCore\/${{ github.event.repository.name }}.git?ref=.*/s//git+https:\/\/github.com\/TourmalineCore\/${{ github.event.repository.name }}.git?ref=${{ github.sha }}/" deploy/helmfile.yaml + + sed -i "0,/git::https:\/\/github.com\/TourmalineCore\/${{ github.event.repository.name }}.git@\/ci\/values-local-env.yaml?ref=.*/s//git::https:\/\/github.com\/TourmalineCore\/${{ github.event.repository.name }}.git@\/ci\/values-local-env.yaml?ref=${{ github.sha }}/" deploy/helmfile.yaml kind create cluster --name inner-circle --config kind-local-config.yaml --kubeconfig ./.inner-circle-cluster-kubeconfig # we need to properly expose KUBECONFIG as an absolute path, pwd prints current working directory path @@ -67,12 +75,6 @@ jobs: helmfile --environment local --namespace local -f deploy/helmfile.yaml apply push: never - # this variable is used by local-env helmfile to use current feature branch helm chart values.yaml file - # this is needed for a case when as part of the feature the chart was changed and is different from master branch - # this should properly fill the feature branch name in spite of the pipeline trigger source (PR, commit, etc.) - # https://stackoverflow.com/a/71158878 - env: | - AUTH_API_BRANCH=${{ github.head_ref || github.ref_name }} - name: Checkout api uses: actions/checkout@v4 diff --git a/README.md b/README.md index 8f75f5c..4cf521f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# inner-circle-auth-api +# auth-api ## Run in Visual Studio From ee426ee50c972ef5971315d3b5fab62ea21dead4 Mon Sep 17 00:00:00 2001 From: akovylyaeva Date: Mon, 22 Sep 2025 14:02:54 +0500 Subject: [PATCH 08/13] fix: change envs for karate local env test --- .github/workflows/karate-tests-on-pull-request.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/karate-tests-on-pull-request.yml b/.github/workflows/karate-tests-on-pull-request.yml index 8ca24a6..19fa76d 100644 --- a/.github/workflows/karate-tests-on-pull-request.yml +++ b/.github/workflows/karate-tests-on-pull-request.yml @@ -93,7 +93,6 @@ jobs: run: | java -jar karate.jar . env: - AUTH_API_ROOT_URL: "http://localhost:30090/api" - API_ROOT_URL: "http://localhost:30090" + API_ROOT_URL: "http://localhost:30090/api" AUTH_LOGIN: "ceo@tourmalinecore.com" AUTH_PASSWORD: "cEoPa$$wo1d" \ No newline at end of file From a682b0782354eee2844f3569ea181b6e8b945053 Mon Sep 17 00:00:00 2001 From: akovylyaeva Date: Mon, 22 Sep 2025 14:26:26 +0500 Subject: [PATCH 09/13] chore: test login password to local karate test --- docker-compose.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index b06d310..4817aa7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -82,6 +82,8 @@ services: - .:/karate environment: API_ROOT_URL: "http://auth-api/api" + AUTH_LOGIN: "aaa" + AUTH_PASSWORD: "aaa" networks: - auth-api-network From 029743e1ddddec59d78f4861abf34b44946a045d Mon Sep 17 00:00:00 2001 From: akovylyaeva Date: Mon, 22 Sep 2025 14:34:47 +0500 Subject: [PATCH 10/13] chore: add secrets for local karate test --- .github/workflows/karate-tests-on-pull-request.yml | 5 +++++ docker-compose.yml | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/karate-tests-on-pull-request.yml b/.github/workflows/karate-tests-on-pull-request.yml index 19fa76d..5e42a52 100644 --- a/.github/workflows/karate-tests-on-pull-request.yml +++ b/.github/workflows/karate-tests-on-pull-request.yml @@ -18,6 +18,11 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 + # Get secrets to sign in + - name: Set up Docker Compose environment variables + run: | + echo TEST_AUTH_LOGIN=${{ secrets.TEST_AUTH_LOGIN }} >> .env + echo TEST_AUTH_PASSWORD=${{ secrets.TEST_AUTH_PASSWORD }} >> .env - name: Run service via docker-compose and run Karate-tests # Hide credentials and token from logs, get the number of failed and passed tests # Find text with 'failed' and 'passed' in logs from karate-testing container diff --git a/docker-compose.yml b/docker-compose.yml index 4817aa7..e069a70 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -82,8 +82,8 @@ services: - .:/karate environment: API_ROOT_URL: "http://auth-api/api" - AUTH_LOGIN: "aaa" - AUTH_PASSWORD: "aaa" + AUTH_LOGIN: ${TEST_AUTH_LOGIN} + AUTH_PASSWORD: ${TEST_AUTH_PASSWORD} networks: - auth-api-network From 06c4f23cfa1f5e9c563a77f66af9303b54b6a52f Mon Sep 17 00:00:00 2001 From: akovylyaeva Date: Mon, 22 Sep 2025 14:41:21 +0500 Subject: [PATCH 11/13] chore: test change env addition --- .github/workflows/karate-tests-on-pull-request.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/karate-tests-on-pull-request.yml b/.github/workflows/karate-tests-on-pull-request.yml index 5e42a52..b04e3bc 100644 --- a/.github/workflows/karate-tests-on-pull-request.yml +++ b/.github/workflows/karate-tests-on-pull-request.yml @@ -18,11 +18,6 @@ jobs: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - # Get secrets to sign in - - name: Set up Docker Compose environment variables - run: | - echo TEST_AUTH_LOGIN=${{ secrets.TEST_AUTH_LOGIN }} >> .env - echo TEST_AUTH_PASSWORD=${{ secrets.TEST_AUTH_PASSWORD }} >> .env - name: Run service via docker-compose and run Karate-tests # Hide credentials and token from logs, get the number of failed and passed tests # Find text with 'failed' and 'passed' in logs from karate-testing container @@ -47,7 +42,10 @@ jobs: if [ "$PASSED" -eq 0 ]; then echo "No tests passed! Failing the pipeline..." exit 1 - fi + fi + env: + TEST_AUTH_LOGIN: ${{ secrets.TEST_AUTH_LOGIN }} + TEST_AUTH_PASSWORD: ${{ secrets.TEST_AUTH_PASSWORD }} e2e-test-with-local-env: name: Run karate tests in local env From 3f7b057eddd05fa292996a6d9117a38fa4adae97 Mon Sep 17 00:00:00 2001 From: akovylyaeva Date: Mon, 22 Sep 2025 16:52:20 +0500 Subject: [PATCH 12/13] chore: fix devcontainer.json and README.md --- .devcontainer/devcontainer.json | 5 ++++- README.md | 22 ++-------------------- 2 files changed, 6 insertions(+), 21 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 7150551..b87231c 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -8,6 +8,9 @@ // Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename. "dockerfile": "../e2e/KarateDockerfile" }, + "features": { + "ghcr.io/devcontainers/features/docker-outside-of-docker:1.6.0": {} + }, "runArgs": [ "--network=host" ], @@ -20,6 +23,6 @@ } }, "containerEnv": { - "API_ROOT_URL": "http://localhost:6503", + "API_ROOT_URL": "http://localhost:6503/api", } } \ No newline at end of file diff --git a/README.md b/README.md index 4cf521f..175615e 100644 --- a/README.md +++ b/README.md @@ -10,20 +10,6 @@ docker compose --profile MockForDevelopment up --build ## Karate Tests -### Run Karate Tests Against Api Running in IDE (not Docker Compose) - -Run Db and MockServer executing the following command (don't close the terminal unless you want to stop the containers) - -```bash -docker compose --profile MockForDevelopment up --build -``` - -Then execute following command inside of the dev-container - -```bash -API_ROOT_URL=http://host.docker.internal:5503 java -jar /karate.jar . -``` - ### Run Karate against Api, Db, and MockServer in Docker Compose Run Api, Db, and MockServer executing the following command (don't close the terminal unless you want to stop the containers) @@ -34,6 +20,8 @@ docker compose --profile MockForTests up --build Then execute following command inside of the dev-container +Note: for now you need to ask AUTH_LOGIN and AUTH_PASSWORD and add them to devcontainer.json file + ```bash java -jar /karate.jar . ``` @@ -46,12 +34,6 @@ Run the docker compose with MockForPullRequest profile executing the following c docker compose --profile MockForPullRequest up --build ``` ->Note: this also includes Karate Tests run by default. However, if you want to run the test again from Dev Container execute: - -```bash -java -jar /karate.jar . -``` - ## Database scheme This project is based on the [TourmalineCore.AspNetCore.JwtAuthentication](https://github.com/TourmalineCore/TourmalineCore.AspNetCore.JwtAuthentication/tree/master/JwtAuthentication.Identity) library which contains [Microsoft Identity Platform](https://learn.microsoft.com/en-us/entra/identity-platform/), so the database schema is inherited from them. From 22cfa9f5b7545ec071c72327c98b9585487c6f48 Mon Sep 17 00:00:00 2001 From: Anastasia Saraeva Date: Mon, 27 Oct 2025 17:55:20 +0500 Subject: [PATCH 13/13] chore: update gitignore --- .gitignore | 1 + e2e/check-employeeId-in-token.feature | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 8646bab..7062f60 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ obj/ .vs *.sln.DotSettings.user *.csproj.user +target # storage for pgadmin */pgadmin/sessions/ diff --git a/e2e/check-employeeId-in-token.feature b/e2e/check-employeeId-in-token.feature index 5b2ab26..4d3cffe 100644 --- a/e2e/check-employeeId-in-token.feature +++ b/e2e/check-employeeId-in-token.feature @@ -28,4 +28,3 @@ Scenario: Check employeeId in token * def accessToken = karate.toMap(response.accessToken.value) * def employeeId = jsUtils().getEmployeeIdFromToken(accessToken) * match employeeId == '#notnull' -