From fd0217b9a829e77477b380ad6c0175b918b05218 Mon Sep 17 00:00:00 2001 From: Ravi Patel <82118011+rpatel-figure@users.noreply.github.com> Date: Thu, 12 Oct 2023 11:29:49 -0500 Subject: [PATCH] Update Spring Boot to v3, Java to v17, and do more cleanup (#122) * Update Java from 11 to 17 * Update Spring Boot from 2.5.6 to 3.1.4 * Update Gradle from 7.4.2 to 8.4 * Update Docker image build to use Jib instead of a Dockerfile * Rename service/docker folder to service/local-docker for clarity of usage * Update minor and patch versions for a few other dependencies to accommodate the major version changes * Remove CHANGELOG.md as it has never been used and is currently superseded by release-drafter * Remove CONTRIBUTING.md as it was copied from another Provenance repository and is too inaccurate to warrant keeping * Address some minor build warnings --- .github/PULL_REQUEST_TEMPLATE.md | 13 +- .github/workflows/build.yml | 20 +-- .github/workflows/release.yml | 36 +--- .gitignore | 10 +- .sdkmanrc | 2 +- CHANGELOG.md | 0 CODE_OF_CONDUCT.md | 2 +- CONTRIBUTING.md | 157 ------------------ build.gradle.kts | 18 +- buildSrc/build.gradle.kts | 5 + gradle/libs.versions.toml | 25 +-- gradle/wrapper/gradle-wrapper.jar | Bin 59821 -> 63721 bytes gradle/wrapper/gradle-wrapper.properties | 4 +- gradlew | 41 +++-- gradlew.bat | 15 +- models/build.gradle.kts | 3 +- service/build.gradle.kts | 118 +++++++++---- service/docker/Dockerfile | 31 ---- .../{docker => local-docker}/bootstrap.env | 0 .../db-init/db-init.sql | 0 .../dependencies.yaml | 0 .../object-store-1.env | 0 .../object-store-2.env | 0 .../prov-init/config/addrbook.json | 0 .../prov-init/config/app.toml | 0 .../prov-init/config/config.toml | 0 .../prov-init/config/genesis.json | 0 ...4c224b016aa26b423aeda4a74e79361ef5c56.json | 0 .../prov-init/config/node_key.json | 0 .../prov-init/config/priv_validator_key.json | 0 .../contracts/asset_definitions.json | 0 .../prov-init/data/priv_validator_state.json | 0 ...66d10381755083c5e4a7eec81da0d49086.address | 0 .../prov-init/keyring-test/validator.info | 0 .../vault/init-and-unseal.sh | 0 .../vault/secrets/local-controller-a.json | 0 .../vault/secrets/local-controller-b.json | 0 .../vault/secrets/local-dart.json | 0 .../vault/secrets/local-investor.json | 0 .../vault/secrets/local-originator.json | 0 .../secrets/local-portfolio-manager.json | 0 .../vault/secrets/local-servicer.json | 0 .../vault/secrets/local-validator.json | 0 .../main/jib}/service-configure | 9 +- .../frameworks/config/ProvenanceProperties.kt | 2 +- .../api/frameworks/config/ServiceProps.kt | 2 - .../api/frameworks/config/VaultProperties.kt | 2 +- .../frameworks/web/config/SecurityConfig.kt | 47 ++++-- .../api/util/MultiPartExtensions.kt | 7 +- 49 files changed, 235 insertions(+), 334 deletions(-) delete mode 100644 CHANGELOG.md delete mode 100644 CONTRIBUTING.md delete mode 100644 service/docker/Dockerfile rename service/{docker => local-docker}/bootstrap.env (100%) rename service/{docker => local-docker}/db-init/db-init.sql (100%) rename service/{docker => local-docker}/dependencies.yaml (100%) rename service/{docker => local-docker}/object-store-1.env (100%) rename service/{docker => local-docker}/object-store-2.env (100%) rename service/{docker => local-docker}/prov-init/config/addrbook.json (100%) rename service/{docker => local-docker}/prov-init/config/app.toml (100%) rename service/{docker => local-docker}/prov-init/config/config.toml (100%) rename service/{docker => local-docker}/prov-init/config/genesis.json (100%) rename service/{docker => local-docker}/prov-init/config/gentx/gentx-e4c4c224b016aa26b423aeda4a74e79361ef5c56.json (100%) rename service/{docker => local-docker}/prov-init/config/node_key.json (100%) rename service/{docker => local-docker}/prov-init/config/priv_validator_key.json (100%) rename service/{docker => local-docker}/prov-init/contracts/asset_definitions.json (100%) rename service/{docker => local-docker}/prov-init/data/priv_validator_state.json (100%) rename service/{docker => local-docker}/prov-init/keyring-test/651a5e66d10381755083c5e4a7eec81da0d49086.address (100%) rename service/{docker => local-docker}/prov-init/keyring-test/validator.info (100%) rename service/{docker => local-docker}/vault/init-and-unseal.sh (100%) rename service/{docker => local-docker}/vault/secrets/local-controller-a.json (100%) rename service/{docker => local-docker}/vault/secrets/local-controller-b.json (100%) rename service/{docker => local-docker}/vault/secrets/local-dart.json (100%) rename service/{docker => local-docker}/vault/secrets/local-investor.json (100%) rename service/{docker => local-docker}/vault/secrets/local-originator.json (100%) rename service/{docker => local-docker}/vault/secrets/local-portfolio-manager.json (100%) rename service/{docker => local-docker}/vault/secrets/local-servicer.json (100%) rename service/{docker => local-docker}/vault/secrets/local-validator.json (100%) rename service/{docker => src/main/jib}/service-configure (74%) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 805a546b..45ab8a59 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -18,8 +18,11 @@ Before we can merge this PR, please make sure that all the following items have checked off. If any of the checklist items are not applicable, please leave them but write a little note why. -- [ ] Targeted PR against correct branch (see [CONTRIBUTING.md](https://github.com/provenance-io/p8e-cee-api/blob/main/CONTRIBUTING.md#pr-targeting)) -- [ ] Linked to Github issue with discussion and accepted design OR link to spec that describes this work. -- [ ] Wrote unit and integration -- [ ] Re-reviewed `Files changed` in the Github PR explorer -- [ ] Review `Unit Test Results` in the comment section below once CI passes +- [ ] Targeted PR against correct branch +- [ ] Tagged PR with **exactly one of** `patch`, `minor`, or `major`, adhering to [semantic versioning](https://semver.org/) +- [ ] Tagged PR with one or more of `feature`, `enhancement`, `fix`/`bugfix`, `chore`, `dependencies`, & `docs`, as applicable to the scope of the PR +- [ ] Acknowledge that by merging my changes to `main`, they are ready to be included in the next release, and otherwise would ask for a prerelease to be created against my branch +- [ ] Linked to GitHub issue with discussion and accepted design OR link to spec that describes this work +- [ ] Wrote unit and integration tests as applicable to the scope of the PR +- [ ] Re-reviewed `Files changed` in the GitHub PR explorer +- [ ] Reviewed `Test Results` in the comment section below once CI passes diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index aba52a63..a9bb1c69 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,15 +25,13 @@ jobs: if: inputs.linting || github.event.pull_request.draft == false steps: - name: Checkout Code - uses: actions/checkout@v3 - with: - fetch-depth: 0 + uses: actions/checkout@v4 - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v3 with: - distribution: 'temurin' - java-version: '11' + distribution: 'zulu' + java-version: '17' - name: Linting run: ./gradlew clean ktlint detekt --parallel --refresh-dependencies @@ -43,13 +41,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v3 with: - java-version: '11' - distribution: 'temurin' + java-version: '17' + distribution: 'zulu' + + # TODO: Figure out how to simplify integration test run below - name: Add Homebrew to PATH run: echo "/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin" >> $GITHUB_PATH diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 42726136..9d4d19cf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,11 +28,11 @@ jobs: - name: Checkout uses: actions/checkout@v3 - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v3 with: - java-version: 11 - distribution: 'temurin' + java-version: 17 + distribution: 'zulu' - name: Add Homebrew to PATH run: echo "/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin" >> $GITHUB_PATH @@ -50,37 +50,19 @@ jobs: - name: Set Image Details id: ci-release-create-outputs run: | - DOCKER_IMAGE=provenanceio/p8e-cee-api VERSION=$( echo ${{ github.event.release.tag_name }} | sed -e 's/^v//' ) if [ "$VERSION" == "" ] ; then VERSION=$( echo ${{ github.event.inputs.versionTag }} | sed -e 's/^v//' ) fi - TAGS="${DOCKER_IMAGE}:${VERSION}" - - if [ ${{ github.event.inputs.tagAsLatest }} == 'true' ] ; then - TAGS="${TAGS},${DOCKER_IMAGE}:latest" - fi - echo "version=${VERSION}" >> $GITHUB_OUTPUT - echo "tags=${TAGS}" >> $GITHUB_OUTPUT - echo "created=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Login to DockerHub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and Push Docker Image - uses: docker/build-push-action@v3 - with: - file: service/docker/Dockerfile - context: . - push: true - tags: ${{ steps.ci-release-create-outputs.outputs.tags }} + env: + JIB_AUTH_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + JIB_AUTH_PASSWORD: ${{ secrets.DOCKERHUB_TOKEN }} + DOCKER_IMAGE_NAME: provenanceio/p8e-cee-api:${{ steps.ci-release-create-outputs.outputs.version }} + TAG_DOCKER_IMAGE_AS_LATEST: ${{ github.event.inputs.tagAsLatest }} + run: ./gradlew :service:jib -Djib.console=plain -Pversion=${VERSION} - name: Install gpg secret key if: inputs.publishToMaven || github.event_name == 'release' diff --git a/.gitignore b/.gitignore index 1f42dc37..32504a2c 100644 --- a/.gitignore +++ b/.gitignore @@ -48,12 +48,12 @@ out/ /.datastore # Vault -service/docker/volumes/ -service/docker/vault/init.output -service/docker/vault/keys.output +service/local-docker/volumes/ +service/local-docker/vault/init.output +service/local-docker/vault/keys.output service/src/test/resources/volumes/ # Object store files -service/docker/object-store-1/ -service/docker/object-store-2/ +service/local-docker/object-store-1/ +service/local-docker/object-store-2/ diff --git a/.sdkmanrc b/.sdkmanrc index 2fe70516..1fc5c141 100644 --- a/.sdkmanrc +++ b/.sdkmanrc @@ -1 +1 @@ -java=11.0.20-tem +java=17.0.8-zulu diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index e69de29b..00000000 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index c9f9cc24..727cc891 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -34,7 +34,7 @@ This Code of Conduct applies both within project spaces and in public spaces whe ## Enforcement -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at community@interchain.io. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at inbound@provenance.io. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index ac97b5b0..00000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,157 +0,0 @@ -# Preface - -The Provenance repository is built on the work of many open source projects including -the [Cosmos SDK]](https://github.com/cosmos/cosmos-sdk). The source code outside of the `/x/` -folder is largely based on a reference implementation of this SDK. The work inside the modules -folder represents the evolution of blockchain applications started at Figure Technologies in 2018. - -This project would not be possible without the dedication and support of the [Cosmos](https://cosmos.network) community. - -# Contributing - -- [Preface](#preface) -- [Contributing](#contributing) - - [Architecture Decision Records (ADR)](#architecture-decision-records-adr) - - [Pull Requests](#pull-requests) - - [Process for reviewing PRs](#process-for-reviewing-prs) - - [Updating Documentation](#updating-documentation) - - [Forking](#forking) - - [Dependencies](#dependencies) - - [Branching Model and Release](#branching-model-and-release) - - [PR Targeting](#pr-targeting) - - [Development Procedure](#development-procedure) - - [Pull Merge Procedure](#pull-merge-procedure) - - [Release Procedure](#release-procedure) - - [Point Release Procedure](#point-release-procedure) - -Thank you for considering making contributions to the Provenance! - -Contributing to this repo can mean many things such as participated in -discussion or proposing code changes. To ensure a smooth workflow for all -contributors, the general procedure for contributing has been established: - -1. Either [open](https://github.com/provenance-io/explorer-service/issues/new/choose) or - [find](https://github.com/provenance-io/explorer-service/issues) an issue you'd like to help with -2. Participate in thoughtful discussion on that issue -3. If you would like to contribute: - 1. If the issue is a proposal, ensure that the proposal has been accepted - 2. Ensure that nobody else has already begun working on this issue. If they have, - make sure to contact them to collaborate - 3. If nobody has been assigned for the issue and you would like to work on it, - make a comment on the issue to inform the community of your intentions - to begin work - 4. Follow standard Github best practices: fork the repo, branch from the - HEAD of `main`, make some commits, and submit a PR to `main` - 5. Be sure to submit the PR in `Draft` mode submit your PR early, even if - it's incomplete as this indicates to the community you're working on - something and allows them to provide comments early in the development process - 6. When the code is complete it can be marked `Ready for Review` - 7. Be sure to include a relevant change log entry in the `Unreleased` section - of `CHANGELOG.md` (see file for log format) - -Note that for very small or blatantly obvious problems (such as typos) it is -not required to an open issue to submit a PR, but be aware that for more complex -problems/features, if a PR is opened before an adequate design discussion has -taken place in a github issue, that PR runs a high likelihood of being rejected. - -Take a peek at our [coding repo](https://github.com/tendermint/coding) for -overall information on repository workflow and standards. Note, we use `make tools` for installing the linting tools. - -## Pull Requests - -To accommodate review process we suggest that PRs are categorically broken up. -Ideally each PR addresses only a single issue. Additionally, as much as possible -code refactoring and cleanup should be submitted as a separate PRs from bugfixes/feature-additions. - -### Process for reviewing PRs - -All PRs require two Reviews before merge (except docs changes, or variable name-changes which only require one). When reviewing PRs please use the following review explanations: - -- `LGTM` without an explicit approval means that the changes look good, but you haven't pulled down the code, run tests locally and thoroughly reviewed it. -- `Approval` through the GH UI means that you understand the code, documentation/spec is updated in the right places, you have pulled down and tested the code locally. In addition: - - You must also think through anything which ought to be included but is not - - You must think through whether any added code could be partially combined (DRYed) with existing code - - You must think through any potential security issues or incentive-compatibility flaws introduced by the changes - - Naming must be consistent with conventions and the rest of the codebase - - Code must live in a reasonable location, considering dependency structures (e.g. not importing testing modules in production code, or including example code modules in production code). - - if you approve of the PR, you are responsible for fixing any of the issues mentioned here and more -- If you sat down with the PR submitter and did a pairing review please note that in the `Approval`, or your PR comments. -- If you are only making "surface level" reviews, submit any notes as `Comments` without adding a review. - -## Branching Model and Release - -User-facing repos should adhere to the trunk based development branching model: https://trunkbaseddevelopment.com/. - -Libraries need not follow the model strictly, but would be wise to. - -### PR Targeting - -Ensure that you base and target your PR on the `main` branch. - -All feature additions should be targeted against `main`. Bug fixes for an outstanding release candidate -should be targeted against the release candidate branch. Release candidate branches themselves should be the -only pull requests targeted directly against main. - -### Development Procedure - -- the latest state of development is on `main` - -### Pull Merge Procedure - -- ensure pull branch is rebased on `main` -- merge pull request - -### Release Procedure - -If new commits are API breaking, a new major version will be released. Everything else can be considered the next -minor version to be released. - -- All new commits are merged into `main` -- The `CHANGELOG` will be updated as needed - -To create a new release: - -- Start on `main` -- Create the release version branch `release/vx.x.x` (aka `release`) -- On the `release` branch, prepare a new version section in the `CHANGELOG.md` - - At the top of latest changes add `## [vx.x.x](https://github.com/provenance-io/explorer-service/releases/tag/vx.x.x) - YYYY-MM-DD` - - Beneath that add `### Release Name: xxxxxx` and choose a unique name from [this list](https://en.wikipedia.org/wiki/List_of_explorers) - - All links must be link-ified: `python ./scripts/linkify.py CHANGELOG.md` - - Copy the latest release entries into a `RELEASE_CHANGELOG.md`, this is needed so the bot knows which entries to add to the release page on github. - - Commit changes to the `release` branch - - Push `release` branch up to github -- Tag the release (use `git tag -a vx.x.x -m "vx.x.x"`) -- Push the tag up (use `git push origin vx.x.x`) - - The release will happen automatically in github -- Create a PR from branch `release` to `main` to incorporate ONLY the `CHANGELOG.md` updates - - Do not push `RELEASE_CHANGELOG.md` to `main` -- Delete the `release` branch - -### Hotfix Procedure - -If a hotfix is needed against the current release, a hotfix branch will be created from the current version tag per the -follow procedure: - -- Start from tag `vx.x.x` -- Create a branch `hotfix/vx.x.(x+1)` (aka `hotfix`) -- The hotfix commit should be PR'd against both `main` and `hotfix` - - The `CHANGELOG` should be updated accordingly for both - -It is the PR's author's responsibility to fix merge conflicts, update changelog entries, and -ensure CI passes. If a PR originates from an external contributor, it may be a core team member's -responsibility to perform this process instead of the original author. -Lastly, it is core team's responsibility to ensure that the PR meets all the Hotfix criteria. - -When the hotfix is ready to be released: - -- Start on `hotfix/vx.x.(x+1)` (aka `hotfix`) -- On the `hotfix` branch, prepare a new version section in the `CHANGELOG.md` - - At the top of latest changes add `## [vx.x.x](https://github.com/provenance-io/explorer-service/releases/tag/vx.x.x) - YYYY-MM-DD` - - All links must be link-ified: `$ python ./scripts/linkify_changelog.py CHANGELOG.md` -- Copy the latest release entries into a `RELEASE_CHANGELOG.md` -- Tag the release (use `git tag -a vx.x.x -m "vx.x.x"`) -- Push the tag up (use `git push origin vx.x.x`) - - The release will happen automatically in github -- Create a PR into `main` containing ONLY `CHANGELOG.md` updates - -Do not push `RELEASE_CHANGELOG.md` to `main` -- Delete the `hotfix` branch diff --git a/build.gradle.kts b/build.gradle.kts index fa6a7b19..78a3daca 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,5 @@ -@Suppress("DSL_SCOPE_VIOLATION") plugins { - kotlin("jvm") version "1.8.10" + kotlin("jvm") version "1.8.22" id("java") id("maven-publish") id("java-library") @@ -24,8 +23,8 @@ subprojects { allprojects { java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } tasks.withType { @@ -33,11 +32,10 @@ allprojects { freeCompilerArgs = listOf( "-Xjsr305=strict", "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", - "-Xskip-prerelease-check", // To support loan package contracts dependency using context receivers ) - jvmTarget = "11" - apiVersion = "1.6" - languageVersion = "1.6" + jvmTarget = "17" + apiVersion = "1.8" + languageVersion = "1.8" allWarningsAsErrors = true } } @@ -56,8 +54,8 @@ nexusPublishing { } java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } allprojects { diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 3604cdf8..1821bb40 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -11,6 +11,11 @@ plugins { `kotlin-dsl` } +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + // For everything else repositories { mavenCentral() diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 847ba590..41c04dac 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,15 +1,15 @@ [versions] -kotlin = "1.8.10" +kotlin = "1.8.22" kotlin_coroutines = "1.6.4" assetClassification = "3.7.0" bouncyCastle = "1.70" detekt = "1.18.1" grpc = "1.51.3" hamkrest = "1.8.0.1" -jackson_databind = "2.12.6.1" -jackson_jsr310 = "2.12.+" -jackson_kotlinModule = "2.12.5" -jackson_protobuf = "0.9.9-jackson2.9-proto3" +jackson = "2.15.2" +jackson_protobuf = "0.9.14" +jakarta_servlet = "5.0.0" +jib = "3.4.0" kong_unirest = "3.13.6" kotest = "5.5.5" kotest_extensions_arrow = "1.2.+" @@ -29,11 +29,11 @@ provenance_client = "1.3.0" provenance_hdWallet = "0.1.15" provenance_kmsConnector = "0.3.6" provenance_proto = "1.13.1" -reactor = "3.4.9" +reactor = "3.5.10" redisson = "3.16.0" reflections = "0.9.10" -spring_boot = "2.5.6" -spring_dependencyManagement = "1.0.11.RELEASE" +spring_boot = "3.1.4" +spring_dependencyManagement = "1.1.3" spring_mockk = "3.0.1" springdoc = "1.5.13" springfox = "3.0.0" @@ -44,6 +44,7 @@ testContainers = "1.3.3" kotlin = { id = "kotlin", version.ref = "kotlin" } detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } idea = { id = "idea" } +jib = { id = "com.google.cloud.tools.jib", version.ref = "jib" } nexus_publishing = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "nexus_publishing" } protobuf = { id = "com.google.protobuf", version.ref = "protobuf_plugin" } spring_boot = { id = "org.springframework.boot", version.ref = "spring_boot" } @@ -87,10 +88,9 @@ assetClassification_client = { module = "tech.figure.classification.asset:ac-cli assetClassification_verifier = { module = "tech.figure.classification.asset:ac-verifier", version.ref = "assetClassification" } objectStore_gateway = { module = "tech.figure.objectstore.gateway:client", version.ref = "objectStore_gateway" } # Jackson -## TODO: Clean up Jackson versions -jackson_databind = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref = "jackson_databind" } -jackson_datatype = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jsr310", version.ref = "jackson_jsr310" } -jackson_kotlinModule = { module = "com.fasterxml.jackson.module:jackson-module-kotlin", version.ref = "jackson_kotlinModule" } +jackson_databind = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref = "jackson" } +jackson_datatype = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jsr310", version.ref = "jackson" } +jackson_kotlinModule = { module = "com.fasterxml.jackson.module:jackson-module-kotlin", version.ref = "jackson" } jackson_protobuf = { module = "com.hubspot.jackson:jackson-datatype-protobuf", version.ref = "jackson_protobuf" } # Google grpc_protobuf = { module = "io.grpc:grpc-protobuf", version.ref = "grpc" } @@ -100,6 +100,7 @@ protobuf_java_util = { module = "com.google.protobuf:protobuf-java-util", versio # Other bouncyCastle = { module = "org.bouncycastle:bcpkix-jdk15on", version.ref = "bouncyCastle" } bouncyCastle_provider = { module = "org.bouncycastle:bcprov-jdk15on", version.ref = "bouncyCastle" } +jakarta_servlet = { module = "jakarta.servlet:jakarta.servlet-api", version.ref = "jakarta_servlet" } kong_unirest = { module = "com.konghq:unirest-java", version.ref = "kong_unirest" } kotlin_logging = { module = "io.github.microutils:kotlin-logging-jvm", version.ref = "kotlin_logging" } ktlint = { module = "com.pinterest:ktlint", version.ref = "ktlint" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 41d9927a4d4fb3f96a785543079b8df6723c946b..7f93135c49b765f8051ef9d0a6055ff8e46073d8 100644 GIT binary patch delta 44451 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 W0}GkPe@wIjfE;Yd41Mt9+y4Mm#rGos delta 40585 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�Kz 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index aa991fce..3fa8f862 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1b6c7873..1aa94a42 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +80,11 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,22 +131,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ @@ -205,6 +214,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index ac1b06f9..6689b85b 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/models/build.gradle.kts b/models/build.gradle.kts index 3cf8699d..95542a14 100644 --- a/models/build.gradle.kts +++ b/models/build.gradle.kts @@ -1,13 +1,12 @@ val ktlint: Configuration by configurations.creating -@Suppress("DSL_SCOPE_VIOLATION") plugins { alias(libs.plugins.detekt) `java-library` `maven-publish` } -java.sourceCompatibility = JavaVersion.VERSION_11 +java.sourceCompatibility = JavaVersion.VERSION_17 dependencies { ktlint(libs.ktlint) diff --git a/service/build.gradle.kts b/service/build.gradle.kts index 7d8e1fd9..93b78867 100644 --- a/service/build.gradle.kts +++ b/service/build.gradle.kts @@ -1,14 +1,14 @@ val ktlint: Configuration by configurations.creating -@Suppress("DSL_SCOPE_VIOLATION") plugins { alias(libs.plugins.detekt) + alias(libs.plugins.jib) alias(libs.plugins.spring.boot) alias(libs.plugins.spring.dependencyManagement) - kotlin("plugin.spring") version "1.8.10" + kotlin("plugin.spring") version "1.8.22" } -java.sourceCompatibility = JavaVersion.VERSION_11 +java.sourceCompatibility = JavaVersion.VERSION_17 dependencyManagement { applyMavenExclusions(false) @@ -30,40 +30,41 @@ dependencies { libs.kotlin.coroutines.reactor, libs.springBoot.starter, libs.springBoot.starter.actuator, - libs.springBoot.starter.jetty, libs.springBoot.starter.devTools, + libs.springBoot.starter.jetty, libs.springBoot.starter.security, libs.springBoot.starter.validation, - libs.reactor.core, // Needed to play nice with WebFlux Coroutines stuff + libs.assetClassification.client, + libs.assetClassification.verifier, + libs.bouncyCastle, + libs.bouncyCastle.provider, + libs.grpc.protobuf, + libs.grpc.stub, + libs.jackson.databind, + libs.jackson.datatype, + libs.jackson.kotlinModule, + libs.jackson.protobuf, + libs.jakarta.servlet, + libs.kong.unirest, libs.kotlin.logging, - libs.springfox.swagger, - libs.springfox.swagger.ui, - libs.swagger.annotations, + libs.objectStore.gateway, libs.p8eScope.encryption, libs.p8eScope.objectStore.client, libs.p8eScope.sdk, - libs.provenance.keyAccessLib, + libs.protobuf.java.util, + libs.provenance.client, libs.provenance.hdWallet, libs.provenance.hdWallet.bip39, - libs.provenance.client, - libs.provenance.protoKotlin, + libs.provenance.keyAccessLib, libs.provenance.loanPackage, - libs.jackson.databind, - libs.jackson.datatype, - libs.jackson.protobuf, - libs.jackson.kotlinModule, - libs.protobuf.java.util, - libs.kong.unirest, - libs.grpc.protobuf, - libs.grpc.stub, + libs.provenance.protoKotlin, + libs.reactor.core, // Needed to play nice with WebFlux Coroutines stuff libs.reflections, - libs.bouncyCastle, - libs.bouncyCastle.provider, - libs.springdoc.openApi.webFluxSupport, libs.springdoc.openApi.kotlinSupport, - libs.assetClassification.client, - libs.assetClassification.verifier, - libs.objectStore.gateway, + libs.springdoc.openApi.webFluxSupport, + libs.springfox.swagger, + libs.springfox.swagger.ui, + libs.swagger.annotations, ).forEach { dependency -> implementation(dependency) } @@ -82,15 +83,15 @@ dependencies { listOf( libs.hamkrest, - libs.mockk, - libs.kotlin.faker, - libs.kotlin.coroutines.test, - libs.spring.mockk, libs.kotest, libs.kotest.assertions, libs.kotest.assertions.arrow, libs.kotest.property, libs.kotest.spring, + libs.kotlin.coroutines.test, + libs.kotlin.faker, + libs.mockk, + libs.spring.mockk, libs.testContainers.core, ).forEach { testDependency -> testImplementation(testDependency) @@ -143,3 +144,62 @@ detekt { config = files("${rootDir.path}/detekt.yml") source = files("src/main/kotlin", "src/test/kotlin") } + +val latestTag: String? = "latest".takeIf { + System.getenv("TAG_DOCKER_IMAGE_AS_LATEST") == "true" || + System.getenv("GITHUB_REF_NAME") + ?.takeIf { it.isNotBlank() } + ?.let { githubRefName -> setOf("main").any { githubRefName.endsWith(it) } } + ?: false +} + +tasks.named("jib") { + dependsOn(tasks.named("bootJar")) +} + +tasks.named("jibDockerBuild") { + dependsOn(tasks.named("bootJar")) +} + +val jarFileName = "service.jar" +val mainClassName = "io.provenance.api.ApplicationKt" + +jib { + from { + auth { + username = System.getenv("JIB_AUTH_USERNAME") ?: "_json_key" + password = System.getenv("JIB_AUTH_PASSWORD") ?: "nopass" + } + image = "azul/zulu-openjdk:17.0.8.1" + } + to { + auth { + username = System.getenv("JIB_AUTH_USERNAME") ?: "_json_key" + password = System.getenv("JIB_AUTH_PASSWORD") ?: "nopass" + } + // The base tag should be specified with `image`, and additional tags with `tags, to control setting of `latest` + image = System.getenv("DOCKER_IMAGE_NAME") ?: "provenanceio/${rootProject.name}:${rootProject.version}" + tags = setOfNotNull(latestTag) + } + extraDirectories { + paths { + path { + setFrom(file("src/main/jib/")) + into = "/" + includes.set(listOf("service-configure")) + } + path { + setFrom(file("build/libs")) + into = "/" + includes.set(listOf(jarFileName)) + } + } + permissions = mapOf("/service-configure" to "755", jarFileName to "755") + } + container { + mainClass = mainClassName + ports = listOf("8080") + entrypoint = listOf("/bin/bash", "-c", "--", "/service-configure /$jarFileName") + creationTime = "USE_CURRENT_TIMESTAMP" + } +} diff --git a/service/docker/Dockerfile b/service/docker/Dockerfile deleted file mode 100644 index e716bb90..00000000 --- a/service/docker/Dockerfile +++ /dev/null @@ -1,31 +0,0 @@ -FROM gradle:7.3.3-jdk11 AS build -RUN gradle --version && java -version -WORKDIR /app - -# Only copy dependency-related files -COPY build.gradle.kts gradle.properties settings.gradle.kts buildSrc/build.gradle.kts /app/ - -# Only download dependencies -# Eat the expected build failure since no source code has been copied yet -RUN gradle clean build --no-daemon > /dev/null 2>&1 || true - -# Copy all files -COPY service /app/service/ -COPY models /app/models/ -COPY buildSrc /app/buildSrc/ -COPY .git /app/.git/ -COPY detekt.yml /app/ -COPY build.gradle.kts gradle.properties settings.gradle.kts /app/ -COPY CHANGELOG.md CODE_OF_CONDUCT.md CONTRIBUTING.md LICENSE README.md /app/ - -# Do the actual build -RUN gradle clean build --no-daemon - -FROM openjdk:11-jre - -ADD service/build/libs/*.jar /p8e-cee-api.jar -ADD service/docker/service-configure /configure - -EXPOSE 8080/tcp - -ENTRYPOINT /configure /p8e-cee-api.jar diff --git a/service/docker/bootstrap.env b/service/local-docker/bootstrap.env similarity index 100% rename from service/docker/bootstrap.env rename to service/local-docker/bootstrap.env diff --git a/service/docker/db-init/db-init.sql b/service/local-docker/db-init/db-init.sql similarity index 100% rename from service/docker/db-init/db-init.sql rename to service/local-docker/db-init/db-init.sql diff --git a/service/docker/dependencies.yaml b/service/local-docker/dependencies.yaml similarity index 100% rename from service/docker/dependencies.yaml rename to service/local-docker/dependencies.yaml diff --git a/service/docker/object-store-1.env b/service/local-docker/object-store-1.env similarity index 100% rename from service/docker/object-store-1.env rename to service/local-docker/object-store-1.env diff --git a/service/docker/object-store-2.env b/service/local-docker/object-store-2.env similarity index 100% rename from service/docker/object-store-2.env rename to service/local-docker/object-store-2.env diff --git a/service/docker/prov-init/config/addrbook.json b/service/local-docker/prov-init/config/addrbook.json similarity index 100% rename from service/docker/prov-init/config/addrbook.json rename to service/local-docker/prov-init/config/addrbook.json diff --git a/service/docker/prov-init/config/app.toml b/service/local-docker/prov-init/config/app.toml similarity index 100% rename from service/docker/prov-init/config/app.toml rename to service/local-docker/prov-init/config/app.toml diff --git a/service/docker/prov-init/config/config.toml b/service/local-docker/prov-init/config/config.toml similarity index 100% rename from service/docker/prov-init/config/config.toml rename to service/local-docker/prov-init/config/config.toml diff --git a/service/docker/prov-init/config/genesis.json b/service/local-docker/prov-init/config/genesis.json similarity index 100% rename from service/docker/prov-init/config/genesis.json rename to service/local-docker/prov-init/config/genesis.json diff --git a/service/docker/prov-init/config/gentx/gentx-e4c4c224b016aa26b423aeda4a74e79361ef5c56.json b/service/local-docker/prov-init/config/gentx/gentx-e4c4c224b016aa26b423aeda4a74e79361ef5c56.json similarity index 100% rename from service/docker/prov-init/config/gentx/gentx-e4c4c224b016aa26b423aeda4a74e79361ef5c56.json rename to service/local-docker/prov-init/config/gentx/gentx-e4c4c224b016aa26b423aeda4a74e79361ef5c56.json diff --git a/service/docker/prov-init/config/node_key.json b/service/local-docker/prov-init/config/node_key.json similarity index 100% rename from service/docker/prov-init/config/node_key.json rename to service/local-docker/prov-init/config/node_key.json diff --git a/service/docker/prov-init/config/priv_validator_key.json b/service/local-docker/prov-init/config/priv_validator_key.json similarity index 100% rename from service/docker/prov-init/config/priv_validator_key.json rename to service/local-docker/prov-init/config/priv_validator_key.json diff --git a/service/docker/prov-init/contracts/asset_definitions.json b/service/local-docker/prov-init/contracts/asset_definitions.json similarity index 100% rename from service/docker/prov-init/contracts/asset_definitions.json rename to service/local-docker/prov-init/contracts/asset_definitions.json diff --git a/service/docker/prov-init/data/priv_validator_state.json b/service/local-docker/prov-init/data/priv_validator_state.json similarity index 100% rename from service/docker/prov-init/data/priv_validator_state.json rename to service/local-docker/prov-init/data/priv_validator_state.json diff --git a/service/docker/prov-init/keyring-test/651a5e66d10381755083c5e4a7eec81da0d49086.address b/service/local-docker/prov-init/keyring-test/651a5e66d10381755083c5e4a7eec81da0d49086.address similarity index 100% rename from service/docker/prov-init/keyring-test/651a5e66d10381755083c5e4a7eec81da0d49086.address rename to service/local-docker/prov-init/keyring-test/651a5e66d10381755083c5e4a7eec81da0d49086.address diff --git a/service/docker/prov-init/keyring-test/validator.info b/service/local-docker/prov-init/keyring-test/validator.info similarity index 100% rename from service/docker/prov-init/keyring-test/validator.info rename to service/local-docker/prov-init/keyring-test/validator.info diff --git a/service/docker/vault/init-and-unseal.sh b/service/local-docker/vault/init-and-unseal.sh similarity index 100% rename from service/docker/vault/init-and-unseal.sh rename to service/local-docker/vault/init-and-unseal.sh diff --git a/service/docker/vault/secrets/local-controller-a.json b/service/local-docker/vault/secrets/local-controller-a.json similarity index 100% rename from service/docker/vault/secrets/local-controller-a.json rename to service/local-docker/vault/secrets/local-controller-a.json diff --git a/service/docker/vault/secrets/local-controller-b.json b/service/local-docker/vault/secrets/local-controller-b.json similarity index 100% rename from service/docker/vault/secrets/local-controller-b.json rename to service/local-docker/vault/secrets/local-controller-b.json diff --git a/service/docker/vault/secrets/local-dart.json b/service/local-docker/vault/secrets/local-dart.json similarity index 100% rename from service/docker/vault/secrets/local-dart.json rename to service/local-docker/vault/secrets/local-dart.json diff --git a/service/docker/vault/secrets/local-investor.json b/service/local-docker/vault/secrets/local-investor.json similarity index 100% rename from service/docker/vault/secrets/local-investor.json rename to service/local-docker/vault/secrets/local-investor.json diff --git a/service/docker/vault/secrets/local-originator.json b/service/local-docker/vault/secrets/local-originator.json similarity index 100% rename from service/docker/vault/secrets/local-originator.json rename to service/local-docker/vault/secrets/local-originator.json diff --git a/service/docker/vault/secrets/local-portfolio-manager.json b/service/local-docker/vault/secrets/local-portfolio-manager.json similarity index 100% rename from service/docker/vault/secrets/local-portfolio-manager.json rename to service/local-docker/vault/secrets/local-portfolio-manager.json diff --git a/service/docker/vault/secrets/local-servicer.json b/service/local-docker/vault/secrets/local-servicer.json similarity index 100% rename from service/docker/vault/secrets/local-servicer.json rename to service/local-docker/vault/secrets/local-servicer.json diff --git a/service/docker/vault/secrets/local-validator.json b/service/local-docker/vault/secrets/local-validator.json similarity index 100% rename from service/docker/vault/secrets/local-validator.json rename to service/local-docker/vault/secrets/local-validator.json diff --git a/service/docker/service-configure b/service/src/main/jib/service-configure similarity index 74% rename from service/docker/service-configure rename to service/src/main/jib/service-configure index dbd8aa75..cf1937b4 100755 --- a/service/docker/service-configure +++ b/service/src/main/jib/service-configure @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash set -e if [ -d "/vault/secrets" ]; then @@ -9,12 +9,13 @@ fi # Create the trust store and key store for java if [ "$KAFKA_SECURITY_PROTOCOL" != "" ]; then - echo -n ${KAFKA_TRUSTSTORE} | base64 -d > ${KAFKA_TRUSTSTORE_PATH} - echo -n ${KAFKA_KEYSTORE} | base64 -d > ${KAFKA_KEYSTORE_PATH} + echo -n "${KAFKA_TRUSTSTORE}" | base64 -d > "${KAFKA_TRUSTSTORE_PATH}" + echo -n "${KAFKA_KEYSTORE}" | base64 -d > "${KAFKA_KEYSTORE_PATH}" fi if [ "$JMX_ENABLED" = true ]; then JAVA_OPTS="$JAVA_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/dumps/dump.bin -Dcom.sun.management.jmxremote.port=7199 -Dcom.sun.management.jmxremote.rmi.port=7199 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=$POD_IP -Dcom.sun.management.jmxremote.local.only=false" fi -java $JAVA_OPTS -jar $1 +# shellcheck disable=SC2086 +exec java $JAVA_OPTS -jar $1 diff --git a/service/src/main/kotlin/io/provenance/api/frameworks/config/ProvenanceProperties.kt b/service/src/main/kotlin/io/provenance/api/frameworks/config/ProvenanceProperties.kt index f0113b36..ebe0932a 100644 --- a/service/src/main/kotlin/io/provenance/api/frameworks/config/ProvenanceProperties.kt +++ b/service/src/main/kotlin/io/provenance/api/frameworks/config/ProvenanceProperties.kt @@ -1,7 +1,7 @@ package io.provenance.api.frameworks.config import io.provenance.api.domain.usecase.common.originator.DefaultAudience -import javax.validation.constraints.NotNull +import jakarta.validation.constraints.NotNull import org.springframework.boot.context.properties.ConfigurationProperties import org.springframework.validation.annotation.Validated diff --git a/service/src/main/kotlin/io/provenance/api/frameworks/config/ServiceProps.kt b/service/src/main/kotlin/io/provenance/api/frameworks/config/ServiceProps.kt index 611b8c48..32a422e5 100644 --- a/service/src/main/kotlin/io/provenance/api/frameworks/config/ServiceProps.kt +++ b/service/src/main/kotlin/io/provenance/api/frameworks/config/ServiceProps.kt @@ -1,10 +1,8 @@ package io.provenance.api.frameworks.config import org.springframework.boot.context.properties.ConfigurationProperties -import org.springframework.boot.context.properties.ConstructorBinding import org.springframework.validation.annotation.Validated -@ConstructorBinding @ConfigurationProperties(prefix = "service") @Validated data class ServiceProps( diff --git a/service/src/main/kotlin/io/provenance/api/frameworks/config/VaultProperties.kt b/service/src/main/kotlin/io/provenance/api/frameworks/config/VaultProperties.kt index ba4d7445..bb2cc10f 100644 --- a/service/src/main/kotlin/io/provenance/api/frameworks/config/VaultProperties.kt +++ b/service/src/main/kotlin/io/provenance/api/frameworks/config/VaultProperties.kt @@ -1,7 +1,7 @@ package io.provenance.api.frameworks.config +import jakarta.validation.constraints.NotNull import org.springframework.boot.context.properties.ConfigurationProperties -import javax.validation.constraints.NotNull @ConfigurationProperties(prefix = "vault") class VaultProperties : LoggableProperties() { diff --git a/service/src/main/kotlin/io/provenance/api/frameworks/web/config/SecurityConfig.kt b/service/src/main/kotlin/io/provenance/api/frameworks/web/config/SecurityConfig.kt index 88aab600..a443737d 100644 --- a/service/src/main/kotlin/io/provenance/api/frameworks/web/config/SecurityConfig.kt +++ b/service/src/main/kotlin/io/provenance/api/frameworks/web/config/SecurityConfig.kt @@ -16,20 +16,37 @@ import org.springframework.security.web.server.SecurityWebFilterChain @EnableConfigurationProperties(value = [ServiceProps::class]) class SecurityConfig { @Bean - fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain { - http.authorizeExchange { - it.pathMatchers("${Routes.MANAGE_BASE}/**", "${Routes.EXTERNAL_BASE}/**", "${Routes.INTERNAL_BASE}/**", "${Routes.DOCS_BASE}/**").permitAll() + fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain = http.apply { + authorizeExchange { spec -> + spec.pathMatchers( + "${Routes.MANAGE_BASE}/**", + "${Routes.EXTERNAL_BASE}/**", + "${Routes.INTERNAL_BASE}/**", + "${Routes.DOCS_BASE}/**" + ).permitAll() } - - return http.httpBasic().disable() - .formLogin().disable() - .logout().disable() - .csrf().disable() - .headers().frameOptions().disable() - .cache().disable() - .and() - .authorizeExchange() - .pathMatchers("/").permitAll() - .and().build() - } + httpBasic { spec -> + spec.disable() + } + formLogin { spec -> + spec.disable() + } + logout { spec -> + spec.disable() + } + csrf { spec -> + spec.disable() + } + headers { spec -> + spec.frameOptions { frameOptionsSpec -> + frameOptionsSpec.disable() + } + spec.cache { cacheSpec -> + cacheSpec.disable() + } + } + http.authorizeExchange { authorize -> + authorize.pathMatchers("/").permitAll() + } + }.build() } diff --git a/service/src/main/kotlin/io/provenance/api/util/MultiPartExtensions.kt b/service/src/main/kotlin/io/provenance/api/util/MultiPartExtensions.kt index 68a77d3f..2f640b45 100644 --- a/service/src/main/kotlin/io/provenance/api/util/MultiPartExtensions.kt +++ b/service/src/main/kotlin/io/provenance/api/util/MultiPartExtensions.kt @@ -3,6 +3,11 @@ package io.provenance.api.util import org.springframework.core.io.buffer.DataBufferUtils import org.springframework.http.codec.multipart.FilePart import reactor.core.publisher.Mono +import java.nio.ByteBuffer fun FilePart.awaitAllBytes(): Mono = - DataBufferUtils.join(this.content()).map { it.asByteBuffer().array() } + DataBufferUtils.join(this.content()).map { dataBuffer -> + ByteBuffer.allocate(dataBuffer.capacity()).also { byteBuffer -> + dataBuffer.toByteBuffer(byteBuffer) + }.array() + }