diff --git a/.github/workflows/aws-bootstrap-template.yml b/.github/workflows/aws-bootstrap-template.yml deleted file mode 100644 index 3f634a3d..00000000 --- a/.github/workflows/aws-bootstrap-template.yml +++ /dev/null @@ -1,134 +0,0 @@ -name: AWS Bootstrap Workflow - -on: - workflow_call: - inputs: - CONTEXT_FOLDER: - required: true - type: string - ENVIRONMENT_NAME: - required: true - type: string - TOOLKIT_STACK_NAME: - required: true - type: string - QUALIFIER: - required: true - type: string - -permissions: - id-token: write - contents: read - -jobs: - check_changes: - name: Check Changes - runs-on: ubuntu-20.04 - outputs: - infra_changed: ${{ steps.check_changes.outputs.infra_changed }} - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 2 - - name: Check modified folders - id: check_changes - env: - CONTEXT_FOLDER: ${{ inputs.CONTEXT_FOLDER }} - CHANGE_FOLDER_NAME: ${{ inputs.CHANGE_FOLDER_NAME }} - run: | - echo "=============== list modified files ===============" - git diff --name-only HEAD^ HEAD - - echo "========== check paths of modified files ==========" - git diff --name-only HEAD^ HEAD >> files.txt - infra_changed=false - while IFS= read -r file - do - echo $file - if [[ $file == $CHANGE_FOLDER_NAME/* ]]; then - infra_changed=true - break - fi - done < files.txt - echo "infra_changed=$infra_changed" >> "$GITHUB_OUTPUT" - - - - synth_deploy_state_components: - name: Synth and Deploy Terraform State Components - runs-on: ubuntu-20.04 - environment: ${{ inputs.ENVIRONMENT_NAME }} - needs: [check_changes, build_push_api_auth_lambda, build_push_cdc_events_lambda, build_push_cdc_auth_lambda] - # if: needs.check_changes.outputs.infra_changed == 'true' - steps: - - uses: actions/checkout@v4 - - - name: Get AWS Account ID - run: echo "CDK_DEFAULT_ACCOUNT=${{ vars.AWS_ACCOUNT }}" >> $GITHUB_ENV - - - name: Get AWS Region - run: echo "CDK_DEFAULT_REGION=${{ vars.AWS_REGION }}" >> $GITHUB_ENV - - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 - with: - role-skip-session-tagging: true - aws-region: ${{ vars.AWS_REGION }} - role-to-assume: ${{ vars.AWS_ROLE_ARN }} - role-duration-seconds: 1800 - role-session-name: ci-deployment - - - - - name: Install Node.js - uses: actions/setup-node@v4 - with: - node-version: '20.12.2' - - - name: Install NPM Modules - run: "npm config set engine-strict true && npm ci" - working-directory: ${{ inputs.CONTEXT_FOLDER }} - - - name: Build - run: "npm run build" - working-directory: ${{ inputs.CONTEXT_FOLDER }} - - - name: Install AWS CDK - run: "npm install -g aws-cdk@2.85.0" - - - name: CDK Bootstrap - env: - TOOLKIT_STACK_NAME: ${{ inputs.TOOLKIT_STACK_NAME }} - QUALIFIER: ${{ inputs.QUALIFIER }} - BRANCH_NAME: ${{ inputs.BRANCH_NAME }} - ENV_NAME: ${{ inputs.ENVIRONMENT_NAME }} - run: | - echo "Running CDK Bootstrap" - npx cdk bootstrap --toolkit-stack-name $TOOLKIT_STACK_NAME --qualifier $QUALIFIER --context branch-name=$BRANCH_NAME - working-directory: ${{ inputs.CONTEXT_FOLDER }} - - - name: CDK Synth - env: - TOOLKIT_STACK_NAME: ${{ inputs.TOOLKIT_STACK_NAME }} - QUALIFIER: ${{ inputs.QUALIFIER }} - BRANCH_NAME: ${{ inputs.BRANCH_NAME }} - ENV_NAME: ${{ inputs.BRANCH_NAME }} - run: | - echo "Running CDK Synth" - npx cdk synth --toolkit-stack-name $TOOLKIT_STACK_NAME --qualifier $QUALIFIER --context branch-name=$BRANCH_NAME - working-directory: ${{ inputs.CONTEXT_FOLDER }} - - - - - name: CDK Deploy - id: cdk_deploy - env: - TOOLKIT_STACK_NAME: ${{ inputs.TOOLKIT_STACK_NAME }} - QUALIFIER: ${{ inputs.QUALIFIER }} - BRANCH_NAME: ${{ inputs.BRANCH_NAME }} - ENV_NAME: ${{ inputs.BRANCH_NAME }} - run: | - npx cdk deploy --toolkit-stack-name $TOOLKIT_STACK_NAME --qualifier $QUALIFIER --require-approval never --all - working-directory: ${{ inputs.CONTEXT_FOLDER }} - - \ No newline at end of file diff --git a/.github/workflows/aws-template-terraform.yml b/.github/workflows/aws-template-terraform.yml deleted file mode 100644 index 0f293295..00000000 --- a/.github/workflows/aws-template-terraform.yml +++ /dev/null @@ -1,134 +0,0 @@ -name: AWS Template Workflow - -on: - workflow_call: - inputs: - CONTEXT_FOLDER: - required: true - type: string - TF_VARS_CONFIG_FOLDER: - required: true - type: string - ENVIRONMENT_NAME: - required: true - type: string - CHANGE_FOLDER_NAME: - required: true - type: string - APPLY_TF_CODE: - required: true - default: false - type: boolean - -permissions: - id-token: write - contents: read - -jobs: - check_changes: - name: Check Changes - runs-on: ubuntu-20.04 - outputs: - infra_changed: ${{ steps.check_changes.outputs.infra_changed }} - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 2 - - name: Check modified folders - id: check_changes - env: - CONTEXT_FOLDER: ${{ inputs.CONTEXT_FOLDER }} - CHANGE_FOLDER_NAME: ${{ inputs.CHANGE_FOLDER_NAME }} - run: | - echo "=============== list modified files ===============" - git diff --name-only HEAD^ HEAD - - echo "========== check paths of modified files ==========" - git diff --name-only HEAD^ HEAD >> files.txt - infra_changed=false - while IFS= read -r file - do - echo $file - if [[ $file == $CHANGE_FOLDER_NAME/* ]]; then - infra_changed=true - break - fi - done < files.txt - echo "infra_changed=$infra_changed" >> "$GITHUB_OUTPUT" - - scan: - name: Scan TF Code - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - name: tfsec - uses: aquasecurity/tfsec-sarif-action@v0.1.4 - with: - sarif_file: tfsec.sarif - working_directory: ${{ inputs.CONTEXT_FOLDER }} - tfsec_args: "--tfvars-file=${{ inputs.CONTEXT_FOLDER }}/${{ inputs.TF_VARS_CONFIG_FOLDER }}/${{ inputs.ENVIRONMENT_NAME }}.tfvars" - - name: Upload SARIF file - uses: github/codeql-action/upload-sarif@v3 - with: - sarif_file: tfsec.sarif - needs: [check_changes] - - deploy_infra: - name: Deploy Infra - runs-on: ubuntu-latest - environment: - name: ${{ inputs.ENVIRONMENT_NAME }} - env: - TF_VAR_app_name: ${{ vars.APP_NAME }} - TF_VAR_environment: ${{ vars.ENVIRONMENT_NAME }} - TF_VAR_kms_key_name: ${{ vars.KMS_KEY_NAME }} - TF_VAR_vpc_id: ${{ vars.VPC_ID }} - TF_VAR_lambda_memory_size: ${{ vars.LAMBDA_MEMORY_SIZE }} - needs: [check_changes, scan] - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 - with: - role-skip-session-tagging: true - aws-region: ${{ vars.AWS_REGION }} - role-to-assume: ${{ vars.AWS_ROLE_ARN }} - role-duration-seconds: 1800 - role-session-name: ci-deployment - - - name: Setup Terraform - uses: hashicorp/setup-terraform@v3 - with: - terraform_version: 1.9.0 - - name: Terraform Init - id: init - env: - CONTEXT_FOLDER: ${{ inputs.CONTEXT_FOLDER }} - run: | - terraform init -input=false -backend-config=${{ inputs.TF_VARS_CONFIG_FOLDER }}/backend.tfvars -var-file=${{ inputs.TF_VARS_CONFIG_FOLDER }}/${{ inputs.ENVIRONMENT_NAME }}.tfvars - working-directory: ${{ inputs.CONTEXT_FOLDER }} - - name: Terraform Plan - id: plan - env: - CONTEXT_FOLDER: ${{ inputs.CONTEXT_FOLDER }} - run: | - terraform plan -no-color -input=false -var-file=${{ inputs.TF_VARS_CONFIG_FOLDER }}/${{ inputs.ENVIRONMENT_NAME }}.tfvars - continue-on-error: true - working-directory: ${{ inputs.CONTEXT_FOLDER }} - - name: Terraform Plan Status - if: steps.plan.outcome == 'failure' - run: exit 1 - - name: Terraform Apply - if: inputs.APPLY_TF_CODE == true - env: - CONTEXT_FOLDER: ${{ inputs.CONTEXT_FOLDER }} - run: | - terraform apply --auto-approve -input=false -var-file=${{ inputs.TF_VARS_CONFIG_FOLDER }}/${{ inputs.ENVIRONMENT_NAME }}.tfvars - working-directory: ${{ inputs.CONTEXT_FOLDER }} diff --git a/.github/workflows/build-and-test-api.yml b/.github/workflows/build-and-test-api.yml index e5a76c5e..81821df5 100644 --- a/.github/workflows/build-and-test-api.yml +++ b/.github/workflows/build-and-test-api.yml @@ -19,7 +19,7 @@ jobs: strategy: matrix: - dotnet-major-version: [8] + dotnet-major-version: [9] dotnet-minor-version: [0] steps: diff --git a/.github/workflows/build-and-test-web.yml b/.github/workflows/build-and-test-web.yml index 944ab51a..b499633b 100644 --- a/.github/workflows/build-and-test-web.yml +++ b/.github/workflows/build-and-test-web.yml @@ -18,7 +18,7 @@ jobs: strategy: matrix: - node-version: [12.x] + node-version: [18.x] steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/.github/workflows/build-infra.yml b/.github/workflows/build-infra.yml index c4835284..42d8af01 100644 --- a/.github/workflows/build-infra.yml +++ b/.github/workflows/build-infra.yml @@ -21,24 +21,79 @@ on: - test - prod -jobs: - build-initial: - uses: ./.github/workflows/aws-template-terraform.yml - with: - CONTEXT_FOLDER: "./infrastructure/cloud/environments/initial" - TF_VARS_CONFIG_FOLDER: "../${{ inputs.environment || 'dev' }}" - CHANGE_FOLDER_NAME: environments/${{ inputs.environment || 'dev' }} - ENVIRONMENT_NAME: ${{ inputs.environment || 'dev' }} - APPLY_TF_CODE: false - secrets: inherit +env: + WORKING_DIRECTORY: "./infrastructure/cloud/environments/${{ inputs.environment }}" +jobs: build: - needs: [build-initial] - uses: ./.github/workflows/aws-template-terraform.yml - with: - CONTEXT_FOLDER: "./infrastructure/cloud/environments/${{ inputs.environment || 'dev' }}" - TF_VARS_CONFIG_FOLDER: "." - CHANGE_FOLDER_NAME: environments/${{ inputs.environment || 'dev' }} - ENVIRONMENT_NAME: ${{ inputs.environment || 'dev' }} - APPLY_TF_CODE: false - secrets: inherit + runs-on: ubuntu-latest + environment: + name: ${{ inputs.environment }} + env: + TF_VAR_app_name: ${{ vars.APP_NAME }} + TF_VAR_environment: ${{ vars.ENVIRONMENT_NAME }} + TF_VAR_kms_key_name: ${{ vars.KMS_KEY_NAME }} + TF_VAR_vpc_id: ${{ vars.VPC_ID }} + TF_VAR_lambda_memory_size: ${{ vars.LAMBDA_MEMORY_SIZE }} + permissions: + id-token: write + actions: read + contents: read + security-events: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: tfsec + uses: aquasecurity/tfsec-sarif-action@v0.1.4 + with: + sarif_file: tfsec.sarif + working_directory: ${{ env.WORKING_DIRECTORY }} + tfsec_args: "--tfvars-file=${{ env.WORKING_DIRECTORY }}/${{ inputs.environment }}.tfvars" + + - name: Upload SARIF file + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: tfsec.sarif + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-skip-session-tagging: true + aws-region: ${{ vars.AWS_REGION }} + role-to-assume: ${{ vars.AWS_ROLE_ARN }} + role-duration-seconds: 1800 + role-session-name: ci-deployment + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v3 + with: + terraform_version: 1.9.0 + + - name: Terraform Init + id: init + run: | + terraform init -input=false -backend-config=backend.tfvars -var-file=${{ inputs.environment }}.tfvars + working-directory: ${{ env.WORKING_DIRECTORY }} + + - name: Terraform Plan (Initial Stack) + id: plan-initial + run: | + terraform plan -target=module.initial -no-color -input=false -var-file=${{ inputs.environment }}.tfvars + continue-on-error: true + working-directory: ${{ env.WORKING_DIRECTORY }} + + - name: Terraform Plan (Initial) Status + if: steps.plan-initial.outcome == 'failure' + run: exit 1 + + - name: Terraform Plan (Main Stack) + id: plan-main + run: | + terraform plan -no-color -input=false -var-file=${{ inputs.environment }}.tfvars + continue-on-error: true + working-directory: ${{ env.WORKING_DIRECTORY }} + + - name: Terraform Plan (Main) Status + if: steps.plan-main.outcome == 'failure' + run: exit 1 \ No newline at end of file diff --git a/.github/workflows/deploy-infra-sandbox.yml b/.github/workflows/deploy-infra-sandbox.yml deleted file mode 100644 index d1992e21..00000000 --- a/.github/workflows/deploy-infra-sandbox.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: Deploy AWS Infra to Sandbox - -on: - workflow_dispatch: - -jobs: - infrastructure_deploy_snd: - uses: ./.github/workflows/aws-template-terraform.yml - with: - CONTEXT_FOLDER: ./infrastructure/cloud/environments/sandbox - CHANGE_FOLDER_NAME: environments/sandbox - ENVIRONMENT_NAME: sandbox - TEST_BUCKET_NAME: jasper-test-bucket - secrets: inherit - - \ No newline at end of file diff --git a/.github/workflows/publish-api.yml b/.github/workflows/publish-api.yml index 07b3ab14..eb7465aa 100644 --- a/.github/workflows/publish-api.yml +++ b/.github/workflows/publish-api.yml @@ -24,7 +24,7 @@ jobs: strategy: matrix: - dotnet-major-version: [8] + dotnet-major-version: [9] dotnet-minor-version: [0] steps: @@ -118,20 +118,19 @@ jobs: - name: Checkout uses: actions/checkout@v4 - # Uncomment when infra in AWS in TEST environment has been configured - # - name: Deploy to ${{ env.ENVIRONMENT }} - # uses: ./.github/workflows/actions/deploy-app - # with: - # environment: ${{ env.ENVIRONMENT }} - # aws_account: ${{ vars.AWS_ACCOUNT }} - # region: ${{ vars.AWS_REGION }} - # app_name: ${{ vars.APP_NAME }} - # aws_role_arn: ${{ vars.AWS_ROLE_ARN }} - # ghcr_token: ${{ secrets.GITHUB_TOKEN }} - # github_image_repo: ${{ env.GITHUB_IMAGE_REPO }} - # image_name: ${{ env.IMAGE_NAME }} - # tier_name: api - # short_sha: ${{ needs.build.outputs.short_sha }} + - name: Deploy to ${{ env.ENVIRONMENT }} + uses: ./.github/workflows/actions/deploy-app + with: + environment: ${{ env.ENVIRONMENT }} + aws_account: ${{ vars.AWS_ACCOUNT }} + region: ${{ vars.AWS_REGION }} + app_name: ${{ vars.APP_NAME }} + aws_role_arn: ${{ vars.AWS_ROLE_ARN }} + ghcr_token: ${{ secrets.GITHUB_TOKEN }} + github_image_repo: ${{ env.GITHUB_IMAGE_REPO }} + image_name: ${{ env.IMAGE_NAME }} + tier_name: api + short_sha: ${{ needs.build.outputs.short_sha }} deploy2prod: name: Deploy to PROD diff --git a/.github/workflows/publish-infra.yml b/.github/workflows/publish-infra.yml index aec18547..39c6f787 100644 --- a/.github/workflows/publish-infra.yml +++ b/.github/workflows/publish-infra.yml @@ -20,44 +20,83 @@ on: - dev - test - prod - run_initial: - description: "Run initial Terraform setup?" - required: false - default: "No" - type: choice - options: - - "No" - - "Yes" + +env: + WORKING_DIRECTORY: "./infrastructure/cloud/environments/${{ inputs.environment }}" + DUMMY_IMAGE_NAME: dummy-image + GITHUB_IMAGE_REPO: ghcr.io/bcgov/jasper + APP_ECR_REPO_URL: ${{ vars.AWS_ACCOUNT }}.dkr.ecr.${{ vars.AWS_REGION }}.amazonaws.com/${{ vars.APP_NAME }}-app-repo-${{ inputs.environment }} + LAMBDA_ECR_REPO_URL: ${{ vars.AWS_ACCOUNT }}.dkr.ecr.${{ vars.AWS_REGION }}.amazonaws.com/${{ vars.APP_NAME }}-lambda-repo-${{ inputs.environment }} jobs: - initial: - if: ${{ inputs.run_initial == 'Yes' }} - uses: ./.github/workflows/aws-template-terraform.yml - with: - CONTEXT_FOLDER: "./infrastructure/cloud/environments/initial" - TF_VARS_CONFIG_FOLDER: "../${{ inputs.environment || 'dev' }}" - CHANGE_FOLDER_NAME: environments/${{ inputs.environment }} - ENVIRONMENT_NAME: ${{ inputs.environment || 'dev' }} - APPLY_TF_CODE: true - secrets: inherit - - post-initial: + deploy: runs-on: ubuntu-latest - needs: initial - if: ${{ inputs.run_initial == 'Yes' }} - environment: ${{ inputs.environment }} + environment: + name: ${{ inputs.environment }} + env: + TF_VAR_app_name: ${{ vars.APP_NAME }} + TF_VAR_environment: ${{ vars.ENVIRONMENT_NAME }} + TF_VAR_kms_key_name: ${{ vars.KMS_KEY_NAME }} + TF_VAR_vpc_id: ${{ vars.VPC_ID }} + TF_VAR_lambda_memory_size: ${{ vars.LAMBDA_MEMORY_SIZE }} permissions: id-token: write + actions: read + contents: read + security-events: write packages: write - env: - DUMMY_IMAGE_NAME: dummy-image - GITHUB_IMAGE_REPO: ghcr.io/bcgov/jasper - APP_ECR_REPO_URL: ${{ vars.AWS_ACCOUNT }}.dkr.ecr.${{ vars.AWS_REGION }}.amazonaws.com/${{ vars.APP_NAME }}-app-repo-${{ inputs.environment }} - LAMBDA_ECR_REPO_URL: ${{ vars.AWS_ACCOUNT }}.dkr.ecr.${{ vars.AWS_REGION }}.amazonaws.com/${{ vars.APP_NAME }}-lambda-repo-${{ inputs.environment }} steps: - name: Checkout repository uses: actions/checkout@v4 + + - name: tfsec + uses: aquasecurity/tfsec-sarif-action@v0.1.4 + with: + sarif_file: tfsec.sarif + working_directory: ${{ env.WORKING_DIRECTORY }} + tfsec_args: "--tfvars-file=${{ env.WORKING_DIRECTORY }}/${{ inputs.environment }}.tfvars" + + - name: Upload SARIF file + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: tfsec.sarif + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-skip-session-tagging: true + aws-region: ${{ vars.AWS_REGION }} + role-to-assume: ${{ vars.AWS_ROLE_ARN }} + role-duration-seconds: 1800 + role-session-name: ci-deployment + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v3 + with: + terraform_version: 1.9.0 + + - name: Terraform Init + id: init + run: | + terraform init -input=false -backend-config=backend.tfvars -var-file=${{ inputs.environment }}.tfvars + working-directory: ${{ env.WORKING_DIRECTORY }} + + - name: Terraform Plan (Initial Stack) + id: plan-initial + run: | + terraform plan -target=module.initial -no-color -input=false -var-file=${{ inputs.environment }}.tfvars + continue-on-error: true + working-directory: ${{ env.WORKING_DIRECTORY }} + + - name: Terraform Plan (Initial) Status + if: steps.plan-initial.outcome == 'failure' + run: exit 1 + - name: Terraform Apply (Initial Stack) + run: | + terraform apply -target=module.initial --auto-approve -input=false -var-file=${{ inputs.environment }}.tfvars + working-directory: ${{ env.WORKING_DIRECTORY }} + - name: Log in to the GHCR uses: docker/login-action@v3 with: @@ -88,40 +127,71 @@ jobs: tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 - with: - role-skip-session-tagging: true - aws-region: ${{ vars.AWS_REGION }} - role-to-assume: ${{ vars.AWS_ROLE_ARN }} - role-duration-seconds: 1800 - role-session-name: ci-deployment - - name: Login to Amazon ECR uses: aws-actions/amazon-ecr-login@v2 - - name: Push dummy images to App ECR + - name: Check dummy-image in App ECR exists + id: app-ecr-check + shell: bash + run: | + IMAGE_TAG=${{ env.DUMMY_IMAGE_NAME }} + REPOSITORY_NAME=${{ vars.APP_NAME }}-app-repo-${{ inputs.environment }} + + IMAGE_EXISTS=$(aws ecr describe-images --repository-name $REPOSITORY_NAME --query "imageDetails[?contains(imageTags, '$IMAGE_TAG')]" --output text) + + if [ -z "$IMAGE_EXISTS" ]; then + echo "Image with tag $IMAGE_TAG does not exist." + echo "exists=false" >> $GITHUB_OUTPUT + else + echo "Image with tag $IMAGE_TAG already exists." + echo "exists=true" >> $GITHUB_OUTPUT + fi + + - name: Push dummy image to App ECR + if: steps.app-ecr-check.outputs.exists == 'false' shell: bash run: | echo 'Deploying ${{ env.DUMMY_IMAGE_NAME }} to App ECR' docker tag ${{ env.GITHUB_IMAGE_REPO }}/${{ env.DUMMY_IMAGE_NAME }}:latest ${{ env.APP_ECR_REPO_URL }}:${{ env.DUMMY_IMAGE_NAME }} docker push ${{ env.APP_ECR_REPO_URL }}:${{ env.DUMMY_IMAGE_NAME }} + - name: Check dummy-image in Lambda ECR exists + id: lambda-ecr-check + shell: bash + run: | + IMAGE_TAG=${{ env.DUMMY_IMAGE_NAME }} + REPOSITORY_NAME=${{ vars.APP_NAME }}-lambda-repo-${{ inputs.environment }} + + IMAGE_EXISTS=$(aws ecr describe-images --repository-name $REPOSITORY_NAME --query "imageDetails[?contains(imageTags, '$IMAGE_TAG')]" --output text) + + if [ -z "$IMAGE_EXISTS" ]; then + echo "Image with tag $IMAGE_TAG does not exist." + echo "exists=false" >> $GITHUB_OUTPUT + else + echo "Image with tag $IMAGE_TAG already exists." + echo "exists=true" >> $GITHUB_OUTPUT + fi + - name: Push dummy images to Lambda ECR + if: steps.lambda-ecr-check.outputs.exists == 'false' shell: bash run: | echo 'Deploying ${{ env.env.DUMMY_IMAGE_NAME }} to Lambda ECR' docker tag ${{ env.GITHUB_IMAGE_REPO }}/${{ env.DUMMY_IMAGE_NAME }}:latest ${{ env.LAMBDA_ECR_REPO_URL }}:${{ env.DUMMY_IMAGE_NAME }} docker push ${{ env.LAMBDA_ECR_REPO_URL }}:${{ env.DUMMY_IMAGE_NAME }} - deploy: - needs: [initial, post-initial] - if: always() - uses: ./.github/workflows/aws-template-terraform.yml - with: - CONTEXT_FOLDER: "./infrastructure/cloud/environments/${{ inputs.environment || 'dev' }}" - TF_VARS_CONFIG_FOLDER: "." - CHANGE_FOLDER_NAME: environments/${{ inputs.environment || 'dev' }} - ENVIRONMENT_NAME: ${{ inputs.environment || 'dev' }} - APPLY_TF_CODE: true - secrets: inherit + - name: Terraform Plan (Main Stack) + id: plan-main + run: | + terraform plan -no-color -input=false -var-file=${{ inputs.environment }}.tfvars + continue-on-error: true + working-directory: ${{ env.WORKING_DIRECTORY }} + + - name: Terraform Plan (Main) Status + if: steps.plan-main.outcome == 'failure' + run: exit 1 + + - name: Terraform Apply (Main Stack) + run: | + terraform apply --auto-approve -input=false -var-file=${{ inputs.environment }}.tfvars + working-directory: ${{ env.WORKING_DIRECTORY }} \ No newline at end of file diff --git a/.github/workflows/publish-web.yml b/.github/workflows/publish-web.yml index 5a1c8fbc..176813c7 100644 --- a/.github/workflows/publish-web.yml +++ b/.github/workflows/publish-web.yml @@ -26,7 +26,7 @@ jobs: strategy: matrix: - node-major-version: [12] + node-major-version: [18] node-minor-version: [x] steps: @@ -79,7 +79,6 @@ jobs: NGINX_RUNTIME_SRC=../../docker/nginx-runtime VUE_ON_NGINX_SRC=../../docker/vue-on-nginx WEB_SRC=../../web - NPM_INSTALL_ARGS=--unsafe-perm deploy2dev: name: Deploy to DEV @@ -125,20 +124,19 @@ jobs: - name: Checkout uses: actions/checkout@v4 - # Uncomment when infra in AWS in TEST environment has been configured - # - name: Deploy to ${{ env.ENVIRONMENT }} - # uses: ./.github/workflows/actions/deploy-app - # with: - # environment: ${{ env.ENVIRONMENT }} - # aws_account: ${{ vars.AWS_ACCOUNT }} - # region: ${{ vars.AWS_REGION }} - # app_name: ${{ vars.APP_NAME }} - # aws_role_arn: ${{ vars.AWS_ROLE_ARN }} - # ghcr_token: ${{ secrets.GITHUB_TOKEN }} - # github_image_repo: ${{ env.GITHUB_IMAGE_REPO }} - # image_name: ${{ env.WEB_IMAGE_NAME }} - # tier_name: web - # short_sha: ${{ needs.build.outputs.short_sha }} + - name: Deploy to ${{ env.ENVIRONMENT }} + uses: ./.github/workflows/actions/deploy-app + with: + environment: ${{ env.ENVIRONMENT }} + aws_account: ${{ vars.AWS_ACCOUNT }} + region: ${{ vars.AWS_REGION }} + app_name: ${{ vars.APP_NAME }} + aws_role_arn: ${{ vars.AWS_ROLE_ARN }} + ghcr_token: ${{ secrets.GITHUB_TOKEN }} + github_image_repo: ${{ env.GITHUB_IMAGE_REPO }} + image_name: ${{ env.WEB_IMAGE_NAME }} + tier_name: web + short_sha: ${{ needs.build.outputs.short_sha }} deploy2prod: name: Deploy to PROD @@ -168,4 +166,4 @@ jobs: # github_image_repo: ${{ env.GITHUB_IMAGE_REPO }} # image_name: ${{ env.WEB_IMAGE_NAME }} # tier_name: web - # short_sha: ${{ needs.build.outputs.short_sha }} + # short_sha: ${{ needs.build.outputs.short_sha }} \ No newline at end of file diff --git a/api/api.csproj b/api/api.csproj index 5505cd4b..9c065420 100644 --- a/api/api.csproj +++ b/api/api.csproj @@ -1,34 +1,34 @@  - net8.0 + net9.0 Scv.Api de959767-ede6-4f8a-b6b9-d36aed703396 - bin\$(Configuration)\net8.0\api.xml + bin\$(Configuration)\net9.0\api.xml 1701;1702;1591 1701;1702;1591 - bin\$(Configuration)\net8.0\api.xml + bin\$(Configuration)\net9.0\api.xml - - - + + + - + - + @@ -40,4 +40,4 @@ - \ No newline at end of file + diff --git a/db/db.csproj b/db/db.csproj index 3653e81f..020b245a 100644 --- a/db/db.csproj +++ b/db/db.csproj @@ -1,18 +1,18 @@ - net8.0 + net9.0 Scv.Db - + - + - \ No newline at end of file + diff --git a/docker/api/Dockerfile.dev b/docker/api/Dockerfile.dev index 0d4f88c3..5a76caf2 100644 --- a/docker/api/Dockerfile.dev +++ b/docker/api/Dockerfile.dev @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/sdk:8.0 +FROM mcr.microsoft.com/dotnet/sdk:9.0 ENV ASPNETCORE_ENVIRONMENT='Production' ENV ASPNETCORE_URLS='http://+:5000' diff --git a/docker/api/Dockerfile.release b/docker/api/Dockerfile.release index 0089b4f8..becb051b 100644 --- a/docker/api/Dockerfile.release +++ b/docker/api/Dockerfile.release @@ -1,5 +1,5 @@ # Dockerfile used by Github Action -ARG dotnet_version=8.0 +ARG dotnet_version=9.0 FROM mcr.microsoft.com/dotnet/aspnet:${dotnet_version} AS base WORKDIR /app EXPOSE 8080 @@ -32,4 +32,4 @@ FROM base AS final # copy app WORKDIR /app COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "api.dll"] \ No newline at end of file +ENTRYPOINT ["dotnet", "api.dll"] diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 353c0a3f..0703d42d 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -1,7 +1,7 @@ -version: "3.4" +version: '3.4' services: web: - image: "${COMPOSE_PROJECT_NAME}-web" + image: '${COMPOSE_PROJECT_NAME}-web' environment: - API_URL=${API_URL} - USE_SELF_SIGNED_SSL=${USE_SELF_SIGNED_SSL} @@ -15,7 +15,7 @@ services: - api web-dev: - image: "${COMPOSE_PROJECT_NAME}-web-dev" + image: '${COMPOSE_PROJECT_NAME}-web-dev' environment: - API_URL=${API_URL} - WEB_BASE_HREF=${WEB_BASE_HREF} @@ -25,15 +25,15 @@ services: - VITE_PORT=1339 - CHOKIDAR_USEPOLLING=true ports: - - "8080:1339" + - '8080:1339' volumes: - - "${LOCAL_WORKSPACE_FOLDER-..}/web/src:/opt/app-root/src/src" - - "${LOCAL_WORKSPACE_FOLDER-..}/web/package.json:/opt/app-root/src/package.json" + - '${LOCAL_WORKSPACE_FOLDER-..}/web/src:/opt/app-root/src/src' + - '${LOCAL_WORKSPACE_FOLDER-..}/web/package.json:/opt/app-root/src/package.json' depends_on: - api api: - image: "${COMPOSE_PROJECT_NAME}-api" + image: '${COMPOSE_PROJECT_NAME}-api' environment: - ASPNETCORE_URLS=${ASPNETCORE_URLS} - FileServicesClient__Username=${FileServicesClientUsername} diff --git a/docker/manage b/docker/manage index 94818965..e96f3c3b 100755 --- a/docker/manage +++ b/docker/manage @@ -80,7 +80,7 @@ build-api() { echo -e "----------------------------------------------------------------------------------------------------" docker build \ -t "${COMPOSE_PROJECT_NAME}-api" \ - -f './api//Dockerfile.dev' '..' + -f './api/Dockerfile.dev' '..' echo -e "====================================================================================================" } diff --git a/docker/openshift/update-aws-creds.sh b/docker/openshift/update-aws-creds.sh index bd32aea4..44fac4c2 100644 --- a/docker/openshift/update-aws-creds.sh +++ b/docker/openshift/update-aws-creds.sh @@ -13,9 +13,9 @@ if [ $? -eq 0 ]; then currentSecretAccessKey=$(echo "$param_value" | jq -r '.current.SecretAccessKey') if [ "$AWS_ACCESS_KEY_ID" = "$pendingAccessKeyId" ] || [ "$AWS_SECRET_ACCESS_KEY" = "$pendingSecretAccessKey" ]; then - echo "Updating AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY..." + echo "Updating AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY for aws-secret-${ENVIRONMENT} secret..." - oc create secret generic aws-secret \ + oc create secret generic aws-secret-${ENVIRONMENT} \ --from-literal=AWS_ACCESS_KEY_ID=$currentAccessKeyId \ --from-literal=AWS_SECRET_ACCESS_KEY=$currentSecretAccessKey \ --dry-run=client -o yaml | oc apply -f - diff --git a/infrastructure/cloud/environments/dev/webapp.tf b/infrastructure/cloud/environments/dev/webapp.tf index efd37bcd..0f7afcdf 100644 --- a/infrastructure/cloud/environments/dev/webapp.tf +++ b/infrastructure/cloud/environments/dev/webapp.tf @@ -1,16 +1,22 @@ -# This the rest of JASPER's infra resources. -# Make sure that the "initial" stack has been deployed first. +# +# "initial" stack containing resources that main stack depends on (e.g. ECR, KMS, openshiftuser) +# +module "initial" { + source = "../../modules/initial" + openshift_iam_user = var.openshift_iam_user + iam_user_table_name = var.iam_user_table_name + test_s3_bucket_name = var.test_s3_bucket_name + region = var.region + kms_key_name = var.kms_key_name + app_name = var.app_name + environment = var.environment +} # -# Existing Resources +# The "main" stack # data "aws_caller_identity" "current" {} -# KMS Key -data "aws_kms_key" "kms_key" { - key_id = "alias/${var.kms_key_name}-${var.environment}" -} - # VPC data "aws_vpc" "vpc" { id = var.vpc_id @@ -29,16 +35,6 @@ data "aws_security_group" "data_sg" { name = "Data_sg" } -# App ECR Repo -data "aws_ecr_repository" "app_ecr_repo" { - name = "${var.app_name}-app-repo-${var.environment}" -} - -# Lambda ECR Repo -data "aws_ecr_repository" "lambda_ecr_repo" { - name = "${var.app_name}-lambda-repo-${var.environment}" -} - # # Modules # @@ -49,7 +45,7 @@ module "secrets_manager" { environment = var.environment app_name = var.app_name region = var.region - kms_key_arn = data.aws_kms_key.kms_key.arn + kms_key_arn = module.initial.kms_key_arn rotate_key_lambda_arn = module.lambda.lambda_functions["rotate-key"].arn } @@ -62,8 +58,9 @@ module "rds" { db_password = module.secrets_manager.db_password data_sg_id = data.aws_security_group.data_sg.id vpc_id = data.aws_vpc.vpc.id - kms_key_arn = data.aws_kms_key.kms_key.arn + kms_key_arn = module.initial.kms_key_arn rds_db_ca_cert = var.rds_db_ca_cert + all_subnet_ids = module.subnets.all_subnet_ids } # Create IAM Roles/Policies @@ -71,11 +68,13 @@ module "iam" { source = "../../modules/IAM" environment = var.environment app_name = var.app_name - kms_key_arn = data.aws_kms_key.kms_key.arn - app_ecr_repo_arn = data.aws_ecr_repository.app_ecr_repo.arn + kms_key_arn = module.initial.kms_key_arn + app_ecr_repo_arn = module.initial.app_ecr.ecr_repo_arn openshift_iam_user = var.openshift_iam_user iam_user_table_name = var.iam_user_table_name secrets_arn_list = module.secrets_manager.secrets_arn_list + account_id = data.aws_caller_identity.current.account_id + kms_key_id = module.initial.kms_key_arn } # Parse Subnets @@ -128,7 +127,7 @@ module "lambda" { app_name = var.app_name lambda_role_arn = module.iam.lambda_role_arn apigw_execution_arn = module.apigw.apigw_execution_arn - lambda_ecr_repo_url = data.aws_ecr_repository.lambda_ecr_repo.repository_url + lambda_ecr_repo_url = module.initial.lambda_ecr.ecr_repo_url mtls_secret_name = module.secrets_manager.mtls_secret_name lambda_memory_size = var.lambda_memory_size functions = { @@ -158,7 +157,7 @@ module "ecs_api_td_log_group" { source = "../../modules/Cloudwatch/LogGroup" environment = var.environment app_name = var.app_name - kms_key_arn = data.aws_kms_key.kms_key.arn + kms_key_arn = module.initial.kms_key_arn resource_name = "ecs" name = "api-td" } @@ -167,7 +166,7 @@ module "ecs_web_td_log_group" { source = "../../modules/Cloudwatch/LogGroup" environment = var.environment app_name = var.app_name - kms_key_arn = data.aws_kms_key.kms_key.arn + kms_key_arn = module.initial.kms_key_arn resource_name = "ecs" name = "web-td" } @@ -176,7 +175,7 @@ module "apigw_api_log_group" { source = "../../modules/Cloudwatch/LogGroup" environment = var.environment app_name = var.app_name - kms_key_arn = data.aws_kms_key.kms_key.arn + kms_key_arn = module.initial.kms_key_arn resource_name = "apigateway" name = "api" } @@ -210,10 +209,10 @@ module "ecs_web_td" { name = "web" region = var.region ecs_execution_role_arn = module.iam.ecs_execution_role_arn - ecr_repository_url = data.aws_ecr_repository.app_ecr_repo.repository_url + ecr_repository_url = module.initial.app_ecr.ecr_repo_url port = 8080 secret_env_variables = module.secrets_manager.web_secrets - kms_key_arn = data.aws_kms_key.kms_key.arn + kms_key_arn = module.initial.kms_key_arn log_group_name = module.ecs_web_td_log_group.log_group.name } @@ -225,7 +224,7 @@ module "ecs_api_td" { name = "api" region = var.region ecs_execution_role_arn = module.iam.ecs_execution_role_arn - ecr_repository_url = data.aws_ecr_repository.app_ecr_repo.repository_url + ecr_repository_url = module.initial.app_ecr.ecr_repo_url port = 5000 env_variables = [ { @@ -238,7 +237,7 @@ module "ecs_api_td" { } ] secret_env_variables = module.secrets_manager.api_secrets - kms_key_arn = data.aws_kms_key.kms_key.arn + kms_key_arn = module.initial.kms_key_arn log_group_name = module.ecs_api_td_log_group.log_group.name } diff --git a/infrastructure/cloud/environments/initial/backend.tfvars b/infrastructure/cloud/environments/initial/backend.tfvars deleted file mode 100644 index 1c0b5d64..00000000 --- a/infrastructure/cloud/environments/initial/backend.tfvars +++ /dev/null @@ -1,4 +0,0 @@ -bucket = "terraform-remote-state-b5e4f5-dev" -dynamodb_table = "terraform-remote-state-lock-b5e4f5" -key = "initial.terraform.tfstate" -region = "ca-central-1" diff --git a/infrastructure/cloud/environments/initial/dev.tfvars b/infrastructure/cloud/environments/initial/dev.tfvars deleted file mode 100644 index 1a02c1a4..00000000 --- a/infrastructure/cloud/environments/initial/dev.tfvars +++ /dev/null @@ -1,10 +0,0 @@ -region = "ca-central-1" -test_s3_bucket_name = "jasper-test-s3-bucket-dev" -web_subnet_names = ["Web_Dev_aza_net", "Web_Dev_azb_net"] -app_subnet_names = ["App_Dev_aza_net", "App_Dev_azb_net"] -data_subnet_names = ["Data_Dev_aza_net", "Data_Dev_azb_net"] -openshift_iam_user = "openshiftuserdev" -iam_user_table_name = "BCGOV_IAM_USER_TABLE" -lb_name = "default" -rds_db_ca_cert = "rds-ca-rsa2048-g1" -cert_domain_name = "*.example.ca" diff --git a/infrastructure/cloud/environments/initial/providers.tf b/infrastructure/cloud/environments/initial/providers.tf deleted file mode 100644 index 4cafa436..00000000 --- a/infrastructure/cloud/environments/initial/providers.tf +++ /dev/null @@ -1,21 +0,0 @@ -terraform { - required_version = "~> 1.9.0" - required_providers { - aws = { - source = "hashicorp/aws" - version = "~> 5.0" - } - - tls = { - source = "hashicorp/tls" - version = "4.0.5" - } - } - - backend "s3" { - } -} - -provider "aws" { - region = var.region -} diff --git a/infrastructure/cloud/environments/initial/variables.tf b/infrastructure/cloud/environments/initial/variables.tf deleted file mode 100644 index 5acbe981..00000000 --- a/infrastructure/cloud/environments/initial/variables.tf +++ /dev/null @@ -1,74 +0,0 @@ -variable "test_s3_bucket_name" { - description = "The name of the S3 bucket to create for testing" - type = string -} - -variable "region" { - description = "The AWS region" - type = string -} - -variable "kms_key_name" { - description = "Name of KMS key" - type = string -} - -variable "app_name" { - description = "The name of the application" - type = string -} - -variable "environment" { - description = "The AWS environment to deploy to" - type = string -} - -variable "vpc_id" { - description = "The provisioned VPC ID" - type = string -} - -variable "web_subnet_names" { - description = "List of Subnets for Web" - type = list(string) -} - -variable "app_subnet_names" { - description = "List of Subnets for App" - type = list(string) -} - -variable "data_subnet_names" { - description = "List of Subnets for Data" - type = list(string) -} - -variable "openshift_iam_user" { - description = "Openshift IAM Username" - type = string -} - -variable "iam_user_table_name" { - description = "The BCGOV DynamoDb IAM user table" - type = string -} - -variable "lb_name" { - description = "The BCGOV provisioned Load Balancer name" - type = string -} - -variable "rds_db_ca_cert" { - description = "The Certifiate Authority identifier used in RDS" - type = string -} - -variable "cert_domain_name" { - description = "The BCGov provisioned certificate domain name" - type = string -} - -variable "lambda_memory_size" { - description = "The Lambda Function default Memory Size" - type = number -} diff --git a/infrastructure/cloud/environments/test/.gitkeep b/infrastructure/cloud/environments/test/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/infrastructure/cloud/environments/test/webapp.tf b/infrastructure/cloud/environments/test/main.tf similarity index 84% rename from infrastructure/cloud/environments/test/webapp.tf rename to infrastructure/cloud/environments/test/main.tf index efd37bcd..0f7afcdf 100644 --- a/infrastructure/cloud/environments/test/webapp.tf +++ b/infrastructure/cloud/environments/test/main.tf @@ -1,16 +1,22 @@ -# This the rest of JASPER's infra resources. -# Make sure that the "initial" stack has been deployed first. +# +# "initial" stack containing resources that main stack depends on (e.g. ECR, KMS, openshiftuser) +# +module "initial" { + source = "../../modules/initial" + openshift_iam_user = var.openshift_iam_user + iam_user_table_name = var.iam_user_table_name + test_s3_bucket_name = var.test_s3_bucket_name + region = var.region + kms_key_name = var.kms_key_name + app_name = var.app_name + environment = var.environment +} # -# Existing Resources +# The "main" stack # data "aws_caller_identity" "current" {} -# KMS Key -data "aws_kms_key" "kms_key" { - key_id = "alias/${var.kms_key_name}-${var.environment}" -} - # VPC data "aws_vpc" "vpc" { id = var.vpc_id @@ -29,16 +35,6 @@ data "aws_security_group" "data_sg" { name = "Data_sg" } -# App ECR Repo -data "aws_ecr_repository" "app_ecr_repo" { - name = "${var.app_name}-app-repo-${var.environment}" -} - -# Lambda ECR Repo -data "aws_ecr_repository" "lambda_ecr_repo" { - name = "${var.app_name}-lambda-repo-${var.environment}" -} - # # Modules # @@ -49,7 +45,7 @@ module "secrets_manager" { environment = var.environment app_name = var.app_name region = var.region - kms_key_arn = data.aws_kms_key.kms_key.arn + kms_key_arn = module.initial.kms_key_arn rotate_key_lambda_arn = module.lambda.lambda_functions["rotate-key"].arn } @@ -62,8 +58,9 @@ module "rds" { db_password = module.secrets_manager.db_password data_sg_id = data.aws_security_group.data_sg.id vpc_id = data.aws_vpc.vpc.id - kms_key_arn = data.aws_kms_key.kms_key.arn + kms_key_arn = module.initial.kms_key_arn rds_db_ca_cert = var.rds_db_ca_cert + all_subnet_ids = module.subnets.all_subnet_ids } # Create IAM Roles/Policies @@ -71,11 +68,13 @@ module "iam" { source = "../../modules/IAM" environment = var.environment app_name = var.app_name - kms_key_arn = data.aws_kms_key.kms_key.arn - app_ecr_repo_arn = data.aws_ecr_repository.app_ecr_repo.arn + kms_key_arn = module.initial.kms_key_arn + app_ecr_repo_arn = module.initial.app_ecr.ecr_repo_arn openshift_iam_user = var.openshift_iam_user iam_user_table_name = var.iam_user_table_name secrets_arn_list = module.secrets_manager.secrets_arn_list + account_id = data.aws_caller_identity.current.account_id + kms_key_id = module.initial.kms_key_arn } # Parse Subnets @@ -128,7 +127,7 @@ module "lambda" { app_name = var.app_name lambda_role_arn = module.iam.lambda_role_arn apigw_execution_arn = module.apigw.apigw_execution_arn - lambda_ecr_repo_url = data.aws_ecr_repository.lambda_ecr_repo.repository_url + lambda_ecr_repo_url = module.initial.lambda_ecr.ecr_repo_url mtls_secret_name = module.secrets_manager.mtls_secret_name lambda_memory_size = var.lambda_memory_size functions = { @@ -158,7 +157,7 @@ module "ecs_api_td_log_group" { source = "../../modules/Cloudwatch/LogGroup" environment = var.environment app_name = var.app_name - kms_key_arn = data.aws_kms_key.kms_key.arn + kms_key_arn = module.initial.kms_key_arn resource_name = "ecs" name = "api-td" } @@ -167,7 +166,7 @@ module "ecs_web_td_log_group" { source = "../../modules/Cloudwatch/LogGroup" environment = var.environment app_name = var.app_name - kms_key_arn = data.aws_kms_key.kms_key.arn + kms_key_arn = module.initial.kms_key_arn resource_name = "ecs" name = "web-td" } @@ -176,7 +175,7 @@ module "apigw_api_log_group" { source = "../../modules/Cloudwatch/LogGroup" environment = var.environment app_name = var.app_name - kms_key_arn = data.aws_kms_key.kms_key.arn + kms_key_arn = module.initial.kms_key_arn resource_name = "apigateway" name = "api" } @@ -210,10 +209,10 @@ module "ecs_web_td" { name = "web" region = var.region ecs_execution_role_arn = module.iam.ecs_execution_role_arn - ecr_repository_url = data.aws_ecr_repository.app_ecr_repo.repository_url + ecr_repository_url = module.initial.app_ecr.ecr_repo_url port = 8080 secret_env_variables = module.secrets_manager.web_secrets - kms_key_arn = data.aws_kms_key.kms_key.arn + kms_key_arn = module.initial.kms_key_arn log_group_name = module.ecs_web_td_log_group.log_group.name } @@ -225,7 +224,7 @@ module "ecs_api_td" { name = "api" region = var.region ecs_execution_role_arn = module.iam.ecs_execution_role_arn - ecr_repository_url = data.aws_ecr_repository.app_ecr_repo.repository_url + ecr_repository_url = module.initial.app_ecr.ecr_repo_url port = 5000 env_variables = [ { @@ -238,7 +237,7 @@ module "ecs_api_td" { } ] secret_env_variables = module.secrets_manager.api_secrets - kms_key_arn = data.aws_kms_key.kms_key.arn + kms_key_arn = module.initial.kms_key_arn log_group_name = module.ecs_api_td_log_group.log_group.name } diff --git a/infrastructure/cloud/modules/APIGateway/main.tf b/infrastructure/cloud/modules/APIGateway/main.tf index 358815ea..d5f65afe 100644 --- a/infrastructure/cloud/modules/APIGateway/main.tf +++ b/infrastructure/cloud/modules/APIGateway/main.tf @@ -77,8 +77,6 @@ resource "aws_api_gateway_rest_api_policy" "apigw_rest_api_policy" { resource "aws_api_gateway_account" "apigateway_account" { cloudwatch_role_arn = var.apigw_logging_role_arn - - depends_on = [aws_api_gateway_stage.apigw_stage] } resource "aws_api_gateway_usage_plan" "apigw_usage_plan" { diff --git a/infrastructure/cloud/modules/DynamoDb/main.tf b/infrastructure/cloud/modules/DynamoDb/main.tf new file mode 100644 index 00000000..581c056c --- /dev/null +++ b/infrastructure/cloud/modules/DynamoDb/main.tf @@ -0,0 +1,48 @@ +# +# Openshift +# +# https://developer.gov.bc.ca/docs/default/component/public-cloud-techdocs/design-build-and-deploy-an-application/iam-user-service/ +# Step 1: Add opeshiftuser if not exist +data "aws_dynamodb_table" "iam_user_table" { + name = var.iam_user_table_name +} + +resource "null_resource" "check_and_insert_openshiftuser_record" { + triggers = { + always_run = timestamp() + } + + provisioner "local-exec" { + command = </test'], - testMatch: ['**/*.test.ts'], - transform: { - '^.+\\.tsx?$': 'ts-jest' - } -}; diff --git a/infrastructure/jasper-aws-bootstrap/lib/jasper-aws-bootstrap-stack.ts b/infrastructure/jasper-aws-bootstrap/lib/jasper-aws-bootstrap-stack.ts deleted file mode 100644 index 5f900276..00000000 --- a/infrastructure/jasper-aws-bootstrap/lib/jasper-aws-bootstrap-stack.ts +++ /dev/null @@ -1,59 +0,0 @@ -import * as cdk from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -// import * as sqs from 'aws-cdk-lib/aws-sqs'; -import * as s3 from 'aws-cdk-lib/aws-s3'; -import * as ddb from 'aws-cdk-lib/aws-dynamodb'; - -export class JasperAwsBootstrapStack extends cdk.Stack { - stateBucket: s3.Bucket; - stateLockTable: ddb.Table; - constructor(scope: Construct, id: string, props?: cdk.StackProps) { - super(scope, id, props); - - const namespace = this.stackName; - const env = process.env.ENV_NAME || 'dev'; - - let removalPolicy = cdk.RemovalPolicy.DESTROY; - let s3BucketAutoDel: boolean = true; - if (env == 'prod') { - removalPolicy = cdk.RemovalPolicy.RETAIN; - s3BucketAutoDel = false; - } - - const kmsCmkey = new cdk.aws_kms.Key(this, `${namespace}-state-KMSKey`, { - description: `KMS CMK for ${namespace} state`, - enableKeyRotation: true, - alias: `${namespace}-cmk-state-key`, - removalPolicy: removalPolicy, - }); - cdk.Tags.of(kmsCmkey).add('Name', `${namespace}-state-KMSKey`); - const kmsCmkState = kmsCmkey.addAlias(namespace + "-state-alias-key") - - - // create s3 bucket for state - const s3BucketName = `${namespace}-state`; - this.stateBucket = new s3.Bucket(this, s3BucketName, { - versioned: true, - removalPolicy: removalPolicy, - bucketName: s3BucketName, - autoDeleteObjects: s3BucketAutoDel, - encryption: s3.BucketEncryption.KMS, - encryptionKey: kmsCmkState, - objectOwnership: s3.ObjectOwnership.BUCKET_OWNER_ENFORCED, - blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL, - }); - - // create dynamodb table for state lock - const stateLockTableName = `${namespace}-state-table`; - this.stateLockTable = new ddb.Table(this, stateLockTableName, { - tableName: stateLockTableName, - partitionKey: { name: 'LockID', type: ddb.AttributeType.STRING }, - removalPolicy: cdk.RemovalPolicy.RETAIN_ON_UPDATE_OR_DELETE, - billingMode: ddb.BillingMode.PAY_PER_REQUEST, - encryption: ddb.TableEncryption.CUSTOMER_MANAGED, - encryptionKey:kmsCmkey, - }); - - cdk.Tags.of(this.stateLockTable).add('Name', stateLockTableName); - } -} diff --git a/infrastructure/jasper-aws-bootstrap/package.json b/infrastructure/jasper-aws-bootstrap/package.json deleted file mode 100644 index b6aa41f4..00000000 --- a/infrastructure/jasper-aws-bootstrap/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "jasper-aws-bootstrap", - "version": "0.1.0", - "bin": { - "jasper-aws-bootstrap": "bin/jasper-aws-bootstrap.js" - }, - "scripts": { - "build": "tsc", - "watch": "tsc -w", - "test": "jest", - "cdk": "cdk" - }, - "devDependencies": { - "@types/jest": "^29.5.12", - "@types/node": "20.14.2", - "jest": "^29.7.0", - "ts-jest": "^29.1.4", - "aws-cdk": "2.146.0", - "ts-node": "^10.9.2", - "typescript": "~5.4.5" - }, - "dependencies": { - "aws-cdk-lib": "2.146.0", - "constructs": "^10.0.0", - "source-map-support": "^0.5.21" - } -} \ No newline at end of file diff --git a/infrastructure/jasper-aws-bootstrap/test/jasper-aws-bootstrap.test.ts b/infrastructure/jasper-aws-bootstrap/test/jasper-aws-bootstrap.test.ts deleted file mode 100644 index 1a8c7312..00000000 --- a/infrastructure/jasper-aws-bootstrap/test/jasper-aws-bootstrap.test.ts +++ /dev/null @@ -1,43 +0,0 @@ -import * as cdk from 'aws-cdk-lib'; -import { Template,Match } from 'aws-cdk-lib/assertions'; -import * as JasperAwsBootstrap from '../lib/jasper-aws-bootstrap-stack'; - -// example test. To run these tests, uncomment this file along with the -// example resource in lib/jasper-aws-bootstrap-stack.ts -test('State S3 bucket created', () => { - const app = new cdk.App(); - // WHEN - const stack = new JasperAwsBootstrap.JasperAwsBootstrapStack(app, 'jasper-bootstrap-dev', { - env: { - account: '123456789012', - region: 'ca-central-1' - } - - }); - // THEN - - const template = Template.fromStack(stack); - - template.resourceCountIs('AWS::S3::Bucket', 1); - - -}); - -// test dynamodb table created -test('State Lock Table Created', () => { - const app = new cdk.App(); - // WHEN - const stack = new JasperAwsBootstrap.JasperAwsBootstrapStack(app, 'jasper-bootstrap-dev', { - env: { - account: '123456789012', - region: 'ca-central-1' - } - - }); - // THEN - - const template = Template.fromStack(stack); - - template.resourceCountIs('AWS::DynamoDB::Table', 1); - -}); diff --git a/infrastructure/jasper-aws-bootstrap/tsconfig.json b/infrastructure/jasper-aws-bootstrap/tsconfig.json deleted file mode 100644 index aaa7dc51..00000000 --- a/infrastructure/jasper-aws-bootstrap/tsconfig.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "module": "commonjs", - "lib": [ - "es2020", - "dom" - ], - "declaration": true, - "strict": true, - "noImplicitAny": true, - "strictNullChecks": true, - "noImplicitThis": true, - "alwaysStrict": true, - "noUnusedLocals": false, - "noUnusedParameters": false, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": false, - "inlineSourceMap": true, - "inlineSources": true, - "experimentalDecorators": true, - "strictPropertyInitialization": false, - "typeRoots": [ - "./node_modules/@types" - ] - }, - "exclude": [ - "node_modules", - "cdk.out" - ] -} diff --git a/jc-interface-client/jc-interface-client.csproj b/jc-interface-client/jc-interface-client.csproj index 0c6cacb8..6535dd39 100644 --- a/jc-interface-client/jc-interface-client.csproj +++ b/jc-interface-client/jc-interface-client.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + net9.0 JCCommon @@ -17,7 +17,7 @@ - + diff --git a/openshift/sync-secrets.dc.yaml b/openshift/sync-secrets.dc.yaml index 254058c4..67be3936 100644 --- a/openshift/sync-secrets.dc.yaml +++ b/openshift/sync-secrets.dc.yaml @@ -2,7 +2,7 @@ # Team is investigating the integration of ArgoCD as a long term solution. # e.g. # # Removes existing components to start from a clean slate -# oc delete cronjob,pvc,rolebinding,sa,roles -n $NAMESPACE -l app=sync-secrets +# oc delete cronjob,pvc,rolebinding,sa,roles -n $NAMESPACE -l app=sync-secrets # # # Dry Run # oc process -f sync_secrets.dc.yaml --param-file=.env @@ -13,21 +13,25 @@ # # Manually create and trigger a job based from the cronjob template # oc create job -n $NAMESPACE "sync-secrets-manual-$(date +%s)" --from=cronjob/sync-secrets # -# The code in "vault.hashicorp.com/agent-inject-template-values" iterates on each secret and -# save it json format to make it easier for the shell script to manipulate the secrets. +# The code in "vault.hashicorp.com/agent-inject-template-values" iterates on each secret and +# save it json format to make it easier for the shell script to manipulate the secrets. apiVersion: template.openshift.io/v1 kind: Template labels: app: sync-secrets template: sync-secrets-template metadata: - name: sync-secrets + # Append the target environment: + # - sync-secrets-dev + # - sync-secrets-test + # - sync-secrets-prod + name: sync-secrets-dev objects: - apiVersion: batch/v1 kind: CronJob metadata: - name: sync-secrets + name: sync-secrets-${ENVIRONMENT} spec: concurrencyPolicy: Forbid failedJobsHistoryLimit: 3 @@ -53,9 +57,9 @@ objects: vault.hashicorp.com/auth-path: auth/k8s-emerald vault.hashicorp.com/namespace: platform-services vault.hashicorp.com/role: ${LICENSE_PLATE}-${VAULT_ROLE} - vault.hashicorp.com/agent-inject-secret-values: jasper-secret-${VAULT_SECRET_ENV} + vault.hashicorp.com/agent-inject-secret-values: jasper-secret-${ENVIRONMENT} vault.hashicorp.com/agent-inject-template-values: | - {{- with secret "${LICENSE_PLATE}-${VAULT_ROLE}/jasper-secret-${VAULT_SECRET_ENV}" -}} + {{- with secret "${LICENSE_PLATE}-${VAULT_ROLE}/jasper-secret-${ENVIRONMENT}" -}} { {{ $length := (len .Data.data) }} {{ $index := 0 }} @@ -81,23 +85,23 @@ objects: imagePullPolicy: Always env: - name: VAULT_SECRET_ENV - value: "${VAULT_SECRET_ENV}" + value: "${ENVIRONMENT}" - name: LOCAL_SECRET_PATH value: "${LOCAL_SECRET_PATH}" - name: AWS_ACCESS_KEY_ID valueFrom: secretKeyRef: - name: aws-secret + name: aws-secret-${ENVIRONMENT} key: AWS_ACCESS_KEY_ID - name: AWS_SECRET_ACCESS_KEY valueFrom: secretKeyRef: - name: aws-secret + name: aws-secret-${ENVIRONMENT} key: AWS_SECRET_ACCESS_KEY - name: AWS_REGION valueFrom: secretKeyRef: - name: aws-secret + name: aws-secret-${ENVIRONMENT} key: AWS_REGION - name: HTTP_PROXY valueFrom: @@ -134,8 +138,8 @@ parameters: required: true value: "nonprod" - - name: VAULT_SECRET_ENV - description: Vault's Environment (dev, test, prod) + - name: ENVIRONMENT + description: Target environment (dev, test, prod) required: true value: "dev" @@ -167,4 +171,4 @@ parameters: - name: IMAGE_TAG description: Image tag required: true - value: "latest" \ No newline at end of file + value: "latest" diff --git a/openshift/update-aws-creds.dc.yaml b/openshift/update-aws-creds.dc.yaml index 40b15de2..e4d6dff9 100644 --- a/openshift/update-aws-creds.dc.yaml +++ b/openshift/update-aws-creds.dc.yaml @@ -2,7 +2,7 @@ # Team is investigating the integration of ArgoCD as a long term solution. # e.g. # # Removes existing components to start from a clean slate -# oc delete cronjob,pvc,rolebinding,sa,roles -n $NAMESPACE -l app=update-aws-creds +# oc delete cronjob,pvc,rolebinding,sa,roles -n $NAMESPACE -l app=update-aws-creds # # # Dry Run # oc process -f update-aws-creds.dc.yaml --param-file=.env @@ -19,20 +19,24 @@ labels: app: update-aws-creds template: update-aws-creds-template metadata: - name: update-aws-creds + # Append the target environment: + # - update-aws-creds-dev + # - update-aws-creds-test + # - update-aws-creds-prod + name: update-aws-creds-dev objects: - apiVersion: v1 kind: ServiceAccount metadata: - name: update-aws-creds + name: update-aws-creds-${ENVIRONMENT} - apiVersion: authorization.openshift.io/v1 kind: Role metadata: annotations: openshift.io/description: Least-priviledge role for the update-aws-creds job - name: update-aws-creds + name: update-aws-creds-${ENVIRONMENT} rules: - apiGroups: - "" @@ -46,18 +50,18 @@ objects: - apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: update-aws-creds + name: update-aws-creds-${ENVIRONMENT} subjects: - - kind: ServiceAccount - name: update-aws-creds + - kind: ServiceAccount + name: update-aws-creds-${ENVIRONMENT} roleRef: kind: Role - name: update-aws-creds + name: update-aws-creds-${ENVIRONMENT} - apiVersion: batch/v1 kind: CronJob metadata: - name: update-aws-creds + name: update-aws-creds-${ENVIRONMENT} spec: concurrencyPolicy: Forbid failedJobsHistoryLimit: 3 @@ -78,7 +82,7 @@ objects: DataClass: Medium role: update-aws-creds spec: - serviceAccountName: update-aws-creds + serviceAccountName: update-aws-creds-${ENVIRONMENT} containers: - name: update-aws-creds image: "${IMAGE_REGISTRY}/${IMAGE_NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG}" @@ -89,17 +93,17 @@ objects: - name: AWS_ACCESS_KEY_ID valueFrom: secretKeyRef: - name: aws-secret + name: aws-secret-${ENVIRONMENT} key: AWS_ACCESS_KEY_ID - name: AWS_SECRET_ACCESS_KEY valueFrom: secretKeyRef: - name: aws-secret + name: aws-secret-${ENVIRONMENT} key: AWS_SECRET_ACCESS_KEY - name: AWS_REGION valueFrom: secretKeyRef: - name: aws-secret + name: aws-secret-${ENVIRONMENT} key: AWS_REGION - name: HTTP_PROXY valueFrom: @@ -127,14 +131,14 @@ objects: parameters: - name: ENVIRONMENT - description: Current environment (dev, test, prod) + description: Target environment (dev, test, prod) required: true value: "dev" - name: CRON_SCHEDULE description: Cronjob Schedule required: true - value: "0 0 * * *" # This runs the job daily at midnight; adjust as needed + value: "0 0 * * *" # This runs the job daily at midnight; adjust as needed - name: IMAGE_REGISTRY description: Image Registry @@ -154,4 +158,4 @@ parameters: - name: IMAGE_TAG description: Image tag required: true - value: "latest" \ No newline at end of file + value: "latest" diff --git a/pcss-client/pcss-client.csproj b/pcss-client/pcss-client.csproj index fee4f5ff..7bfba1c7 100644 --- a/pcss-client/pcss-client.csproj +++ b/pcss-client/pcss-client.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 pcss_client enable enable @@ -9,7 +9,7 @@ - + true diff --git a/tests/tests.csproj b/tests/tests.csproj index d69adb9d..e19ffa07 100644 --- a/tests/tests.csproj +++ b/tests/tests.csproj @@ -1,6 +1,6 @@ - net8.0 + net9.0 de959767-ede6-4f8a-b6b9-d36aed703396 @@ -13,7 +13,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -25,4 +25,4 @@ - \ No newline at end of file + diff --git a/web/package-lock.json b/web/package-lock.json index fb5e096c..397d80e0 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -8,33 +8,32 @@ "name": "scv-web", "version": "0.1.0", "dependencies": { - "@bcgov/bootstrap-theme": "https://github.com/bcgov/bootstrap-theme/releases/download/v1.1.3/bcgov-bootstrap-theme-1.1.3.tgz", "@fullcalendar/core": "^6.1.15", "@fullcalendar/daygrid": "^6.1.15", "@fullcalendar/interaction": "^6.1.15", "@fullcalendar/timegrid": "^6.1.15", "@fullcalendar/vue3": "^6.1.15", + "@mdi/font": "^7.4.47", "@types/underscore": "^1.13.0", "@vitejs/plugin-basic-ssl": "^1.2.0", - "@vue/compat": "^3.5.13", "axios": "^1.7.9", "base64url": "^3.0.1", "bootstrap": "^4.3.1", - "bootstrap-vue": "^2.23.0", + "bootstrap-vue-next": "^0.26.8", "cross-env": "^7.0.3", "intersection-observer": "^0.12.2", "jquery": "^3.7.1", "lodash": "^4.17.21", "pinia": "^2.3.0", "regenerator-runtime": "^0.14.1", - "sass": "^1.82.0", "splunk-logging": "^0.11.1", "style-loader": "^4.0.0", "underscore": "^1.13.7", "uuid": "^11.0.3", "vue": "^3.5.13", "vue-month-picker": "^1.7.2", - "vue-router": "^4.5.0" + "vue-router": "^4.5.0", + "vuetify": "^3.7.5" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^8.17.0", @@ -50,9 +49,20 @@ "ts-loader": "^9.5.1", "tslib": "^2.8.1", "typescript": "^5.7.2", + "unplugin-vue-components": "^0.27.5", "vite": "^6.0.2" } }, + "node_modules/@antfu/utils": { + "version": "0.7.10", + "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.10.tgz", + "integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/@babel/helper-string-parser": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", @@ -99,15 +109,6 @@ "node": ">=6.9.0" } }, - "node_modules/@bcgov/bootstrap-theme": { - "version": "1.1.3", - "resolved": "https://github.com/bcgov/bootstrap-theme/releases/download/v1.1.3/bcgov-bootstrap-theme-1.1.3.tgz", - "integrity": "sha512-D37u71R8TWdGlhM7KY0ENLqgB2M+A8GLBPGi7FZ/ovR2WipRcSTeLGgm8x4KkXiYs+XY0LiLbbYCi/YLpVzCGA==", - "license": "Apache-2.0", - "peerDependencies": { - "bootstrap": "~4.3.1" - } - }, "node_modules/@esbuild/aix-ppc64": { "version": "0.24.0", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz", @@ -832,6 +833,12 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@mdi/font": { + "version": "7.4.47", + "resolved": "https://registry.npmjs.org/@mdi/font/-/font-7.4.47.tgz", + "integrity": "sha512-43MtGpd585SNzHZPcYowu/84Vz2a2g31TvPMTm9uTiCSWzaheQySUcSyUH/46fPnuPQWof2yd0pGBtzee/IQWw==", + "license": "Apache-2.0" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -870,24 +877,6 @@ "node": ">= 8" } }, - "node_modules/@nuxt/opencollective": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@nuxt/opencollective/-/opencollective-0.3.3.tgz", - "integrity": "sha512-6IKCd+gP0HliixqZT/p8nW3tucD6Sv/u/eR2A9X4rxT/6hXlMzA4GZQzq4d2qnBAwSwGpmKyzkyTjNjrhaA25A==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "consola": "^2.15.0", - "node-fetch": "^2.6.7" - }, - "bin": { - "opencollective": "bin/opencollective.js" - }, - "engines": { - "node": ">=8.0.0", - "npm": ">=5.0.0" - } - }, "node_modules/@parcel/watcher": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.0.tgz", @@ -895,6 +884,7 @@ "hasInstallScript": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", @@ -936,6 +926,7 @@ "os": [ "android" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -956,6 +947,7 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -976,6 +968,7 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -996,6 +989,7 @@ "os": [ "freebsd" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1016,6 +1010,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1036,6 +1031,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1056,6 +1052,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1076,6 +1073,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1096,6 +1094,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1116,6 +1115,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1136,6 +1136,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1156,6 +1157,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1176,6 +1178,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -1184,6 +1187,42 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/@rollup/pluginutils": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.3.tgz", + "integrity": "sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.28.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.28.0.tgz", @@ -1705,20 +1744,6 @@ "vue": "^3.2.25" } }, - "node_modules/@vue/compat": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compat/-/compat-3.5.13.tgz", - "integrity": "sha512-Q3xRdTPN4l+kddxU98REyUBgvc0meAo9CefCWE2lW8Fg3dyPn3vSCce52b338ihrJAx1RQQhO5wMWhJ/PAKUpA==", - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.25.3", - "estree-walker": "^2.0.2", - "source-map-js": "^1.2.0" - }, - "peerDependencies": { - "vue": "3.5.13" - } - }, "node_modules/@vue/compiler-core": { "version": "3.5.13", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.13.tgz", @@ -2078,6 +2103,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -2089,6 +2115,20 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -2150,6 +2190,19 @@ "node": ">=6.0.0" } }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -2158,47 +2211,6 @@ "license": "ISC" }, "node_modules/bootstrap": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.3.1.tgz", - "integrity": "sha512-rXqOmH1VilAt2DyPzluTi2blhk17bO7ef+zLLPlWvG494pDxcM234pJ8wTc/6R40UWizAIIMgxjvxZg5kmsbag==", - "license": "MIT", - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jquery": "1.9.1 - 3", - "popper.js": "^1.14.7" - } - }, - "node_modules/bootstrap-vue": { - "version": "2.23.1", - "resolved": "https://registry.npmjs.org/bootstrap-vue/-/bootstrap-vue-2.23.1.tgz", - "integrity": "sha512-SEWkG4LzmMuWjQdSYmAQk1G/oOKm37dtNfjB5kxq0YafnL2W6qUAmeDTcIZVbPiQd2OQlIkWOMPBRGySk/zGsg==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@nuxt/opencollective": "^0.3.2", - "bootstrap": "^4.6.1", - "popper.js": "^1.16.1", - "portal-vue": "^2.1.7", - "vue-functional-data-merge": "^3.1.0" - } - }, - "node_modules/bootstrap-vue/node_modules/@vue/compiler-sfc": { - "version": "2.7.16", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.16.tgz", - "integrity": "sha512-KWhJ9k5nXuNtygPU7+t1rX6baZeqOYLEforUPjgNDBnLicfHCoi48H87Q8XyLZOrNNsmhuwKqtpDQWjEFe6Ekg==", - "peer": true, - "dependencies": { - "@babel/parser": "^7.23.5", - "postcss": "^8.4.14", - "source-map": "^0.6.1" - }, - "optionalDependencies": { - "prettier": "^1.18.2 || ^2.0.0" - } - }, - "node_modules/bootstrap-vue/node_modules/bootstrap": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.2.tgz", "integrity": "sha512-51Bbp/Uxr9aTuy6ca/8FbFloBUJZLHwnhTcnjIeRn2suQWsWzcuJhGjKDB5eppVte/8oCdOL3VuwxvZDUggwGQ==", @@ -2218,52 +2230,17 @@ "popper.js": "^1.16.1" } }, - "node_modules/bootstrap-vue/node_modules/portal-vue": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/portal-vue/-/portal-vue-2.1.7.tgz", - "integrity": "sha512-+yCno2oB3xA7irTt0EU5Ezw22L2J51uKAacE/6hMPMoO/mx3h4rXFkkBkT4GFsMDv/vEe8TNKC3ujJJ0PTwb6g==", + "node_modules/bootstrap-vue-next": { + "version": "0.26.10", + "resolved": "https://registry.npmjs.org/bootstrap-vue-next/-/bootstrap-vue-next-0.26.10.tgz", + "integrity": "sha512-OP6mTwvpmZ12kFvSfpzU9puxqALctCW8uQdLPFDAPDzW++1g9dIVfSOzJ8mLnu4x/tGfcJugi/JW0uF3TZoZzw==", "license": "MIT", - "peerDependencies": { - "vue": "^2.5.18" - } - }, - "node_modules/bootstrap-vue/node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "license": "MIT", - "optional": true, - "peer": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/bootstrap-vue/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "license": "BSD-3-Clause", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/bootstrap-vue/node_modules/vue": { - "version": "2.7.16", - "resolved": "https://registry.npmjs.org/vue/-/vue-2.7.16.tgz", - "integrity": "sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw==", - "deprecated": "Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details.", - "license": "MIT", - "peer": true, - "dependencies": { - "@vue/compiler-sfc": "2.7.16", - "csstype": "^3.1.0" + "type": "opencollective", + "url": "https://opencollective.com/bootstrap-vue-next" + }, + "peerDependencies": { + "vue": "^3.5.13" } }, "node_modules/brace-expansion": { @@ -2389,6 +2366,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -2406,6 +2384,8 @@ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "readdirp": "^4.0.1" }, @@ -2430,6 +2410,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -2442,6 +2423,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, "license": "MIT" }, "node_modules/combined-stream": { @@ -2470,10 +2452,11 @@ "dev": true, "license": "MIT" }, - "node_modules/consola": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", - "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==", + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true, "license": "MIT" }, "node_modules/cross-env": { @@ -2567,6 +2550,7 @@ "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", "license": "Apache-2.0", "optional": true, + "peer": true, "bin": { "detect-libc": "bin/detect-libc.js" }, @@ -3205,7 +3189,9 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz", "integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/import-fresh": { "version": "3.3.0", @@ -3240,6 +3226,19 @@ "integrity": "sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==", "license": "Apache-2.0" }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -3390,6 +3389,23 @@ "node": ">=6.11.5" } }, + "node_modules/local-pkg": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.1.tgz", + "integrity": "sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mlly": "^1.7.3", + "pkg-types": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -3496,6 +3512,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/mlly": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.3.tgz", + "integrity": "sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.14.0", + "pathe": "^1.1.2", + "pkg-types": "^1.2.1", + "ufo": "^1.5.4" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -3565,27 +3594,8 @@ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", "license": "MIT", - "optional": true - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } + "optional": true, + "peer": true }, "node_modules/node-releases": { "version": "2.0.18", @@ -3594,6 +3604,16 @@ "license": "MIT", "peer": true }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -3689,6 +3709,13 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true, + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -3730,12 +3757,25 @@ } } }, + "node_modules/pkg-types": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.2.1.tgz", + "integrity": "sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.2", + "pathe": "^1.1.2" + } + }, "node_modules/popper.js": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1", "license": "MIT", + "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" @@ -3880,6 +3920,8 @@ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 14.16.0" }, @@ -4008,6 +4050,8 @@ "resolved": "https://registry.npmjs.org/sass/-/sass-1.82.0.tgz", "integrity": "sha512-j4GMCTa8elGyN9A7x7bEglx0VgSpNUG4W4wNedQ33wSMdnkqQCT8HTwOaVSV4e6yQovcu/3Oc4coJP/l0xhL2Q==", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", @@ -4174,6 +4218,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -4258,12 +4303,6 @@ "node": ">=8.0" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, "node_modules/ts-api-utils": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", @@ -4372,6 +4411,13 @@ } } }, + "node_modules/ufo": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", + "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", + "dev": true, + "license": "MIT" + }, "node_modules/underscore": { "version": "1.13.7", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", @@ -4385,6 +4431,109 @@ "license": "MIT", "peer": true }, + "node_modules/unplugin": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.16.0.tgz", + "integrity": "sha512-5liCNPuJW8dqh3+DM6uNM2EI3MLLpCKp/KY+9pB5M2S2SR2qvvDHhKgBOaTWEbZTAws3CXfB0rKTIolWKL05VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.14.0", + "webpack-virtual-modules": "^0.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/unplugin-vue-components": { + "version": "0.27.5", + "resolved": "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-0.27.5.tgz", + "integrity": "sha512-m9j4goBeNwXyNN8oZHHxvIIYiG8FQ9UfmKWeNllpDvhU7btKNNELGPt+o3mckQKuPwrE7e0PvCsx+IWuDSD9Vg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@antfu/utils": "^0.7.10", + "@rollup/pluginutils": "^5.1.3", + "chokidar": "^3.6.0", + "debug": "^4.3.7", + "fast-glob": "^3.3.2", + "local-pkg": "^0.5.1", + "magic-string": "^0.30.14", + "minimatch": "^9.0.5", + "mlly": "^1.7.3", + "unplugin": "^1.16.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@babel/parser": "^7.15.8", + "@nuxt/kit": "^3.2.2", + "vue": "2 || 3" + }, + "peerDependenciesMeta": { + "@babel/parser": { + "optional": true + }, + "@nuxt/kit": { + "optional": true + } + } + }, + "node_modules/unplugin-vue-components/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/unplugin-vue-components/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/unplugin-vue-components/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/update-browserslist-db": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", @@ -4623,12 +4772,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/vue-functional-data-merge": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/vue-functional-data-merge/-/vue-functional-data-merge-3.1.0.tgz", - "integrity": "sha512-leT4kdJVQyeZNY1kmnS1xiUlQ9z1B/kdBFCILIjYYQDqZgLqCLa0UhjSSeRX6c3mUe6U5qYeM8LrEqkHJ1B4LA==", - "license": "MIT" - }, "node_modules/vue-month-picker": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/vue-month-picker/-/vue-month-picker-1.7.2.tgz", @@ -4650,6 +4793,36 @@ "vue": "^3.2.0" } }, + "node_modules/vuetify": { + "version": "3.7.5", + "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.7.5.tgz", + "integrity": "sha512-5aiSz8WJyGzYe3yfgDbzxsFATwHvKtdvFAaUJEDTx7xRv55s3YiOho/MFhs5iTbmh2VT4ToRgP0imBUP660UOw==", + "license": "MIT", + "engines": { + "node": "^12.20 || >=14.13" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/johnleider" + }, + "peerDependencies": { + "typescript": ">=4.7", + "vite-plugin-vuetify": ">=1.0.0", + "vue": "^3.3.0", + "webpack-plugin-vuetify": ">=2.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vite-plugin-vuetify": { + "optional": true + }, + "webpack-plugin-vuetify": { + "optional": true + } + } + }, "node_modules/watchpack": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", @@ -4664,12 +4837,6 @@ "node": ">=10.13.0" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, "node_modules/webpack": { "version": "5.97.1", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz", @@ -4727,6 +4894,13 @@ "node": ">=10.13.0" } }, + "node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", + "dev": true, + "license": "MIT" + }, "node_modules/webpack/node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -4751,16 +4925,6 @@ "node": ">=4.0" } }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/web/package.json b/web/package.json index fbe83ba8..3c179b38 100644 --- a/web/package.json +++ b/web/package.json @@ -20,33 +20,32 @@ "json-schema": ">=0.4.0" }, "dependencies": { - "@bcgov/bootstrap-theme": "https://github.com/bcgov/bootstrap-theme/releases/download/v1.1.3/bcgov-bootstrap-theme-1.1.3.tgz", "@fullcalendar/core": "^6.1.15", "@fullcalendar/daygrid": "^6.1.15", "@fullcalendar/interaction": "^6.1.15", "@fullcalendar/timegrid": "^6.1.15", "@fullcalendar/vue3": "^6.1.15", + "@mdi/font": "^7.4.47", "@types/underscore": "^1.13.0", "@vitejs/plugin-basic-ssl": "^1.2.0", - "@vue/compat": "^3.5.13", "axios": "^1.7.9", "base64url": "^3.0.1", "bootstrap": "^4.3.1", - "bootstrap-vue": "^2.23.0", + "bootstrap-vue-next": "^0.26.8", "cross-env": "^7.0.3", "intersection-observer": "^0.12.2", "jquery": "^3.7.1", "lodash": "^4.17.21", "pinia": "^2.3.0", "regenerator-runtime": "^0.14.1", - "sass": "^1.82.0", "splunk-logging": "^0.11.1", "style-loader": "^4.0.0", "underscore": "^1.13.7", "uuid": "^11.0.3", "vue": "^3.5.13", "vue-month-picker": "^1.7.2", - "vue-router": "^4.5.0" + "vue-router": "^4.5.0", + "vuetify": "^3.7.5" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^8.17.0", @@ -62,6 +61,7 @@ "ts-loader": "^9.5.1", "tslib": "^2.8.1", "typescript": "^5.7.2", + "unplugin-vue-components": "^0.27.5", "vite": "^6.0.2" }, "eslintConfig": { diff --git a/web/src/App.vue b/web/src/App.vue index eef3abed..aa4d95da 100644 --- a/web/src/App.vue +++ b/web/src/App.vue @@ -19,3 +19,12 @@ }, }); + + diff --git a/web/src/components/NavigationTopbar.vue b/web/src/components/NavigationTopbar.vue index 0370c0ca..9fbb74ba 100644 --- a/web/src/components/NavigationTopbar.vue +++ b/web/src/components/NavigationTopbar.vue @@ -78,7 +78,29 @@ }, }); + diff --git a/web/src/components/civil/CivilDocumentsView.vue b/web/src/components/civil/CivilDocumentsView.vue index 7ffd4c8d..18b7f407 100644 --- a/web/src/components/civil/CivilDocumentsView.vue +++ b/web/src/components/civil/CivilDocumentsView.vue @@ -53,9 +53,9 @@ ([]); const commonStyles = { cellStyle: 'font-size: 14px;', @@ -736,13 +738,13 @@ } }); - const sortBy = computed(() => { - if (activetab.value == 'COURT SUMMARY') { - return 'appearanceDate'; - } else if (activetab.value == 'ORDERS') { - return 'seq'; + watch(activetab, (newValue) => { + if (newValue == 'COURT SUMMARY') { + sortBy.value.push({ key: 'appearanceDate', order: 'asc' }); + } else if (newValue == 'ORDERS') { + sortBy.value.push({ key: 'seq', order: 'asc' }); } else { - return 'dateFiled'; + sortBy.value.push({ key: 'dateFiled', order: 'asc' }); } }); diff --git a/web/src/components/courtfilesearch/CourtFileSearchResult.vue b/web/src/components/courtfilesearch/CourtFileSearchResult.vue index 43e3b512..2712eb63 100644 --- a/web/src/components/courtfilesearch/CourtFileSearchResult.vue +++ b/web/src/components/courtfilesearch/CourtFileSearchResult.vue @@ -386,26 +386,24 @@ diff --git a/web/src/components/courtfilesearch/CourtFileSearchView.vue b/web/src/components/courtfilesearch/CourtFileSearchView.vue index 24cd32a2..af484deb 100644 --- a/web/src/components/courtfilesearch/CourtFileSearchView.vue +++ b/web/src/components/courtfilesearch/CourtFileSearchView.vue @@ -588,14 +588,12 @@