From db3475fe359ede8fbf5bcbe6e9dc40c40cd2378d Mon Sep 17 00:00:00 2001 From: eduv09 Date: Mon, 22 Jul 2024 19:25:22 +0000 Subject: [PATCH 1/8] feat(consortium-static): new consortium plugin * New plugin consortium-static, based on consortium-manual. Long story short, the plugin allows for the addition of Cacti Nodes to consortium at runtime. New node entities must belong to one of the consortium entities (organizations) that were specified on consortium creation. So it allows to add new nodes 'CactusNode', but not new 'ConsortiumMember' entities. * New feature: add CactusNode to consortium at runtime The code is based on the plugin-consortium-manual, with the new features built on top of it. The process of adding a new node is conducted as follows: 1. The new node forges a request with information about itself and sends it to any Node in the consortium 2. The receiver verifies the request, and if it is approved, broadcasts it to the rest of the consortium Nodes. 3. Each node verifies the same request, and adds the new node to the consortium database. At the same time, the receiver node from point 2 sends the consortium data to the new node, who updates it's database. * Includes a new policy model The package includes a policy model, which was developed based on the ideas of the Policy Core Information Model [RFC3060](https://www.rfc-editor.org/rfc/rfc3060) . The idea was to introduce the idea of a multi-purpose policy framework that can be leveraged by other packages in cacti. Signed-off-by: eduv09 --- .github/workflows/ci.yaml | 34 +- .../cacti-plugin-consortium-static/.gitignore | 2 + .../cacti-plugin-consortium-static/README.md | 56 ++ .../openapitools.json | 7 + .../package.json | 98 +++ .../src/main/json/openapi.json | 505 ++++++++++++ .../src/main/json/openapi.tpl.json | 505 ++++++++++++ .../kotlin-client/.openapi-generator/FILES | 38 + .../kotlin-client/.openapi-generator/VERSION | 1 + .../generated/openapi/kotlin-client/README.md | 78 ++ .../openapi/kotlin-client/build.gradle | 38 + .../generated/openapi/kotlin-client/gradlew | 245 ++++++ .../openapi/kotlin-client/gradlew.bat | 92 +++ .../openapi/kotlin-client/settings.gradle | 2 + .../openapitools/client/apis/DefaultApi.kt | 410 ++++++++++ .../client/infrastructure/ApiAbstractions.kt | 23 + .../client/infrastructure/ApiClient.kt | 245 ++++++ .../client/infrastructure/ApiResponse.kt | 43 + .../infrastructure/BigDecimalAdapter.kt | 17 + .../infrastructure/BigIntegerAdapter.kt | 17 + .../client/infrastructure/ByteArrayAdapter.kt | 12 + .../client/infrastructure/Errors.kt | 18 + .../client/infrastructure/LocalDateAdapter.kt | 19 + .../infrastructure/LocalDateTimeAdapter.kt | 19 + .../infrastructure/OffsetDateTimeAdapter.kt | 19 + .../client/infrastructure/PartConfig.kt | 11 + .../client/infrastructure/RequestConfig.kt | 18 + .../client/infrastructure/RequestMethod.kt | 8 + .../infrastructure/ResponseExtensions.kt | 24 + .../client/infrastructure/Serializer.kt | 23 + .../client/infrastructure/URIAdapter.kt | 13 + .../client/infrastructure/UUIDAdapter.kt | 13 + .../client/models/BroadcastRequestV1.kt | 40 + .../models/BroadcastRequestV1Message.kt | 40 + .../client/models/BroadcastResponseV1.kt | 35 + .../openapitools/client/models/CactusNode.kt | 61 ++ .../client/models/CactusNodeAllOf.kt | 52 ++ .../client/models/CactusNodeMeta.kt | 40 + .../client/models/GetConsortiumJwsResponse.kt | 36 + .../client/models/GetNodeJwsResponse.kt | 36 + .../openapitools/client/models/Identity.kt | 46 ++ .../openapitools/client/models/JWSGeneral.kt | 40 + .../client/models/JWSRecipient.kt | 43 + .../org/openapitools/client/models/Ledger.kt | 44 + .../openapitools/client/models/LedgerType.kt | 75 ++ .../client/models/NewNodeRequestV1.kt | 63 ++ .../client/models/PluginInstance.kt | 39 + .../consortium/add-new-node-endpoint-v1.ts | 121 +++ .../get-consortium-jws-endpoint-v1.ts | 122 +++ .../consortium/get-node-jws-endpoint-v1.ts | 118 +++ ...prometheus-exporter-metrics-endpoint-v1.ts | 109 +++ .../process-broadcast-endpoint-v1.ts | 132 +++ .../typescript-axios/.openapi-generator/FILES | 5 + .../.openapi-generator/VERSION | 1 + .../generated/openapi/typescript-axios/api.ts | 750 ++++++++++++++++++ .../openapi/typescript-axios/base.ts | 72 ++ .../openapi/typescript-axios/common.ts | 150 ++++ .../openapi/typescript-axios/configuration.ts | 101 +++ .../openapi/typescript-axios/index.ts | 18 + .../src/main/typescript/index.ts | 1 + .../src/main/typescript/index.web.ts | 1 + .../typescript/plugin-consortium-static.ts | 515 ++++++++++++ .../plugin-factory-consortium-static.ts | 20 + .../main/typescript/policy-model/i-policy.ts | 10 + .../typescript/policy-model/policy-action.ts | 4 + .../policy-model/policy-condition.ts | 5 + .../typescript/policy-model/policy-group.ts | 153 ++++ .../typescript/policy-model/policy-rule.ts | 31 + .../typescript/policy-model/polity-item.ts | 47 ++ .../prometheus-exporter/data-fetcher.ts | 12 + .../typescript/prometheus-exporter/metrics.ts | 11 + .../prometheus-exporter.ts | 43 + .../prometheus-exporter/response.type.ts | 3 + .../src/main/typescript/public-api.ts | 31 + .../repository/static-consortium-provider.ts | 72 ++ .../static-consortium-repository.ts | 199 +++++ .../src/main/typescript/utils.ts | 91 +++ .../api-routing-node-to-node.test.ts | 396 +++++++++ .../integration/api-surface.test.ts | 6 + ...est-new-node-broadcast-with-proofs.test.ts | 510 ++++++++++++ .../api-test-new-node-broadcast.test.ts | 452 +++++++++++ .../test/typescript/unit/api-surface.test.ts | 6 + .../tsconfig.json | 25 + .../src/main/typescript/api-client.ts | 1 + tsconfig.json | 3 + yarn.lock | 41 + 86 files changed, 7730 insertions(+), 1 deletion(-) create mode 100644 packages/cacti-plugin-consortium-static/.gitignore create mode 100644 packages/cacti-plugin-consortium-static/README.md create mode 100644 packages/cacti-plugin-consortium-static/openapitools.json create mode 100644 packages/cacti-plugin-consortium-static/package.json create mode 100644 packages/cacti-plugin-consortium-static/src/main/json/openapi.json create mode 100644 packages/cacti-plugin-consortium-static/src/main/json/openapi.tpl.json create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/.openapi-generator/FILES create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/.openapi-generator/VERSION create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/README.md create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/build.gradle create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/gradlew create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/gradlew.bat create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/settings.gradle create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/apis/DefaultApi.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/ApiAbstractions.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/ApiResponse.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/Errors.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/PartConfig.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/RequestConfig.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/RequestMethod.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/ResponseExtensions.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/BroadcastRequestV1.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/BroadcastRequestV1Message.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/BroadcastResponseV1.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactusNode.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactusNodeAllOf.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactusNodeMeta.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetConsortiumJwsResponse.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetNodeJwsResponse.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/Identity.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/JWSGeneral.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/JWSRecipient.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/Ledger.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/LedgerType.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/NewNodeRequestV1.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/PluginInstance.kt create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/consortium/add-new-node-endpoint-v1.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/consortium/get-consortium-jws-endpoint-v1.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/consortium/get-node-jws-endpoint-v1.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/consortium/get-prometheus-exporter-metrics-endpoint-v1.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/consortium/process-broadcast-endpoint-v1.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/FILES create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/VERSION create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/api.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/base.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/common.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/configuration.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/index.ts create mode 100755 packages/cacti-plugin-consortium-static/src/main/typescript/index.ts create mode 100755 packages/cacti-plugin-consortium-static/src/main/typescript/index.web.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/plugin-consortium-static.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/plugin-factory-consortium-static.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/i-policy.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/policy-action.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/policy-condition.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/policy-group.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/policy-rule.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/polity-item.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/prometheus-exporter/data-fetcher.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/prometheus-exporter/metrics.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/prometheus-exporter/prometheus-exporter.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/prometheus-exporter/response.type.ts create mode 100755 packages/cacti-plugin-consortium-static/src/main/typescript/public-api.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/repository/static-consortium-provider.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/repository/static-consortium-repository.ts create mode 100644 packages/cacti-plugin-consortium-static/src/main/typescript/utils.ts create mode 100644 packages/cacti-plugin-consortium-static/src/test/typescript/integration/api-routing-node-to-node.test.ts create mode 100644 packages/cacti-plugin-consortium-static/src/test/typescript/integration/api-surface.test.ts create mode 100644 packages/cacti-plugin-consortium-static/src/test/typescript/integration/api-test-new-node-broadcast-with-proofs.test.ts create mode 100644 packages/cacti-plugin-consortium-static/src/test/typescript/integration/api-test-new-node-broadcast.test.ts create mode 100644 packages/cacti-plugin-consortium-static/src/test/typescript/unit/api-surface.test.ts create mode 100644 packages/cacti-plugin-consortium-static/tsconfig.json diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 460ca6e5f33..4ce1f2261cc 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -2205,7 +2205,6 @@ jobs: with: name: coverage-reports-37 path: ./code-coverage-ts/**/ - ct-cmd-api-server: continue-on-error: false needs: @@ -2528,6 +2527,39 @@ jobs: with: name: coverage-reports-46 path: ./code-coverage-ts/**/ + cp-consortium-static: + continue-on-error: false + env: + FULL_BUILD_DISABLED: true + JEST_TEST_RUNNER_DISABLED: false + JEST_TEST_PATTERN: packages/cacti-plugin-consortium-static/src/test/typescript/(unit|integration|benchmark)/.*/*.test.ts + JEST_TEST_COVERAGE_PATH: ./code-coverage-ts/cp-consortium-static + JEST_TEST_CODE_COVERAGE_ENABLED: true + TAPE_TEST_RUNNER_DISABLED: true + needs: build-dev + runs-on: ubuntu-22.04 + steps: + - name: Use Node.js ${{ env.NODEJS_VERSION }} + uses: actions/setup-node@v4.0.3 + with: + node-version: ${{ env.NODEJS_VERSION }} + - uses: actions/checkout@v4.1.7 + + - id: yarn-cache + name: Restore Yarn Cache + uses: actions/cache@v4.0.2 + with: + key: ${{ runner.os }}-yarn-${{ hashFiles('./yarn.lock') }} + path: ./.yarn/ + restore-keys: | + ${{ runner.os }}-yarn-${{ hashFiles('./yarn.lock') }} + - run: ./tools/ci.sh + if: ${{ env.RUN_CODE_COVERAGE == 'true' }} + - name: Upload coverage reports as artifacts + uses: actions/upload-artifact@v4.3.3 + with: + name: coverage-reports-47 + path: ./code-coverage-ts/**/ ghcr-besu-all-in-one: runs-on: ubuntu-22.04 steps: diff --git a/packages/cacti-plugin-consortium-static/.gitignore b/packages/cacti-plugin-consortium-static/.gitignore new file mode 100644 index 00000000000..ce4bacc38a3 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/.gitignore @@ -0,0 +1,2 @@ +cactus-openapi-spec-plugin-consortium-manual.json +src/main/typescript/generated/openapi/typescript-axios/.npmignore \ No newline at end of file diff --git a/packages/cacti-plugin-consortium-static/README.md b/packages/cacti-plugin-consortium-static/README.md new file mode 100644 index 00000000000..f879b40501f --- /dev/null +++ b/packages/cacti-plugin-consortium-static/README.md @@ -0,0 +1,56 @@ +# `@hyperledger/cacti-plugin-consortium-static` + +## Cacti Consortium Static + +This plugin is an improvement of the package /cactus-plugin-consortium-manual ,bringing some new features to the table while conserving the possibility to be used as the old one (not allowing runtime changes) + +### Add Nodes to Consortium + +It is possible to add a new node to the consortium using the api of the plugin. + +New nodes need to belong/be certified by one of the organizations that are part of the consortium. On creating the consortium, it is required to specify the public keys of the organizations that are part of the consortium. When a new node requests to join, the request carries a jwt token signed by the organization it is tied to, which serves as proof that the organization reccognises the new node identity. + +When a new node submits a request to join, the receiving node verifies the request and broadcasts it (or not, depending on the verification) to the remaining nodes in the consortium. There is no consensus or reliable broadcast implemented. All the other nodes submit the request to the same verification process. If, for some reason, there are disparities in the consortiumDatabases of each node, either it is due to a network issue (broadcast did not reach destination) or due to malfunction of some node. + + +### Consortium Repository + +In addition to the default consortium repository (in cactus-core), the new repository includes data about the Node the repository belongs to: +```typescript +//data about self + private readonly node: CactusNode; + private readonly ledgers: Ledger[]; + private readonly pluginInstances: PluginInstance[]; + private readonly memberId: string; +``` +It also includes the root PolicyGroup of the consortium (explained in next section), and the common configurations of the packages deployed by nodes within the consortium. + +We do not verify if the nodes actually apply these configurations and policies, the information so far is used just to check that nodes have knowledge of this settings. Compliance or not is at the responsibility of each node, and to be verified if necessary by other means. + +To verify new nodes have the same policies and package configs as the others already in the consortium, we deterministically build two merkle trees (one with each info), concat both roots, and each node verifies the result against their own policies and package common configs. + +As a result of this proccess, nodes with divergent policies and configs are not accepted in the consortium (we assume all nodes are correctly configured when the network is created). + +### Policy Model + +We introduce in this package a proposal of a general-purpose policy model based in work done by the IETF: Core Policy Framework [RFC3060](https://www.rfc-editor.org/rfc/rfc3060). + +The model (simplified version) can be viewed in the policy-model directory. + +As a brief description, we group PolicyRules in PolicyGroups. PolicyGroups contain PolicyRules and possibly other PolicyGroups. A PolicyRule is composed by a PolicyCondition (constraint to be verified prior to applying the policy) and a PolicyAction (action to be applied). + +Below a simplified UML with the relationships between the classes: + +![policy model uml](https://github.com/eduv09/images/blob/main/policy-model-uml.jpg) + +The consortium information needs to hold only the root policyGroup (others are reached going down in the hierarchy). Each PolicyGroup has a Role. Roles identify the scope of the policy, so a PolicyRule has a set of Roles (role of the group it belongs to, and groups higher in the hierarchy). + +The model is in an early stage, and serves only as a POC for now. The goal is to refine it, and possibly move it to cactus-core once if it is accepted by the community as a advantageous feature. It is possible to create consortium without any policy rule or group defined. + + + +## Notes + +Please reffer to package "@hyperledger/cactus-plugin-consortium-manual" as the documentation there applies to this one, namely information about the Prometheus Exporter. + +For usage, check the tests in the /integration folder \ No newline at end of file diff --git a/packages/cacti-plugin-consortium-static/openapitools.json b/packages/cacti-plugin-consortium-static/openapitools.json new file mode 100644 index 00000000000..225ff1aaaee --- /dev/null +++ b/packages/cacti-plugin-consortium-static/openapitools.json @@ -0,0 +1,7 @@ +{ + "$schema": "node_modules/@openapitools/openapi-generator-cli/config.schema.json", + "spaces": 2, + "generator-cli": { + "version": "6.6.0" + } +} diff --git a/packages/cacti-plugin-consortium-static/package.json b/packages/cacti-plugin-consortium-static/package.json new file mode 100644 index 00000000000..34969fc645e --- /dev/null +++ b/packages/cacti-plugin-consortium-static/package.json @@ -0,0 +1,98 @@ +{ + "name": "@hyperledger/cacti-plugin-consortium-static", + "version": "2.0.0-rc.3", + "description": "A web service plugin that provides management capabilities on a Cactus consortium as a whole for administrative purposes.", + "keywords": [ + "Hyperledger", + "Cactus", + "Integration", + "Blockchain", + "Distributed Ledger Technology" + ], + "homepage": "https://github.com/hyperledger/cacti#readme", + "bugs": { + "url": "https://github.com/hyperledger/cacti/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/hyperledger/cacti.git" + }, + "license": "Apache-2.0", + "author": { + "name": "Hyperledger Cactus Contributors", + "email": "cactus@lists.hyperledger.org", + "url": "https://www.hyperledger.org/use/cacti" + }, + "contributors": [ + { + "name": "Eduardo Vasques", + "email": "eduardovasques10@tecnico.ulisboa.pt", + "url": "https://example.com" + }, + { + "name": "Peter Somogyvari", + "email": "peter.somogyvari@accenture.com", + "url": "https://accenture.com" + } + ], + "main": "dist/lib/main/typescript/index.js", + "module": "dist/lib/main/typescript/index.js", + "browser": "dist/cacti-plugin-consortium-static.web.umd.js", + "types": "dist/lib/main/typescript/index.d.ts", + "files": [ + "dist/*" + ], + "scripts": { + "codegen": "run-p 'codegen:*'", + "codegen:openapi": "npm run generate-sdk", + "generate-sdk": "run-p 'generate-sdk:*'", + "generate-sdk:kotlin": "openapi-generator-cli generate -i ./src/main/json/openapi.json -g kotlin -o ./src/main/kotlin/generated/openapi/kotlin-client/ --reserved-words-mappings protected=protected --ignore-file-override ../../openapi-generator-ignore", + "generate-sdk:typescript-axios": "openapi-generator-cli generate -i ./src/main/json/openapi.json -g typescript-axios -o ./src/main/typescript/generated/openapi/typescript-axios/ --reserved-words-mappings protected=protected --ignore-file-override ../../openapi-generator-ignore", + "watch": "npm-watch", + "webpack": "npm-run-all webpack:dev", + "webpack:dev": "npm-run-all webpack:dev:node webpack:dev:web", + "webpack:dev:node": "webpack --env=dev --target=node --config ../../webpack.config.js", + "webpack:dev:web": "webpack --env=dev --target=web --config ../../webpack.config.js" + }, + "dependencies": { + "@hyperledger/cactus-common": "2.0.0-rc.3", + "@hyperledger/cactus-core": "2.0.0-rc.3", + "@hyperledger/cactus-core-api": "2.0.0-rc.3", + "axios": "1.6.0", + "body-parser": "1.20.2", + "express": "4.19.2", + "http-errors-enhanced-cjs": "2.0.1", + "jose": "4.15.5", + "merkletreejs": "0.4.0", + "prom-client": "15.1.3", + "safe-stable-stringify": "2.4.3", + "typescript-optional": "2.0.1", + "uuid": "10.0.0" + }, + "devDependencies": { + "@hyperledger/cactus-api-client": "2.0.0-rc.3", + "@hyperledger/cactus-cmd-api-server": "2.0.0-rc.3", + "@hyperledger/cactus-plugin-ledger-connector-besu": "2.0.0-rc.3", + "@hyperledger/cactus-test-tooling": "2.0.0-rc.3", + "@types/express": "4.17.21", + "@types/json-stable-stringify": "1.0.33", + "@types/uuid": "10.0.0", + "web3": "1.6.1" + }, + "engines": { + "node": ">=18", + "npm": ">=8" + }, + "publishConfig": { + "access": "public" + }, + "browserMinified": "dist/cacti-plugin-consortium-static.web.umd.min.js", + "mainMinified": "dist/cacti-plugin-consortium-static.node.umd.min.js", + "watch": { + "codegen:openapi": { + "patterns": [ + "./src/main/json/openapi.json" + ] + } + } +} diff --git a/packages/cacti-plugin-consortium-static/src/main/json/openapi.json b/packages/cacti-plugin-consortium-static/src/main/json/openapi.json new file mode 100644 index 00000000000..1e698575cd0 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/json/openapi.json @@ -0,0 +1,505 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Hyperledger Cactus Plugin - Consortium Web Service", + "description": "Manage a Cactus consortium through the APIs. Needs administrative privileges.", + "version": "2.0.0-rc.2", + "license": { + "name": "Apache-2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + } + }, + "components": { + "schemas": { + "Identity": { + "type": "object", + "description": "Identity object of a Cacti Node", + "required": ["pubKey", "memberId", "proof"], + "properties": { + "pubKey": { + "description": "Public key of the Node", + "type": "string", + "nullable": false + }, + "memberId": { + "description": "memberId of the organization the node belongs to", + "type": "string", + "nullable": false + }, + "proof": { + "description": "JWT generated by the organization the node belongs to", + "type": "string", + "nullable": false + } + } + }, + "NewNodeRequestV1": { + "type": "object", + "required": [ + "identity", + "treeHash", + "node", + "ledger", + "pluginInstance", + "signature" + ], + "properties": { + "identity": { + "$ref": "#/components/schemas/Identity", + "nullable": false + }, + "treeHash": { + "description": "proof of common configs and policies defined by the consortium", + "type": "string", + "nullable": false + }, + "node": { + "description": "A Cacti Node", + "$ref": "#/components/schemas/CactusNode", + "nullable": false + }, + "ledger": { + "description": "Ledger metadata", + "type": "array", + "items": { + "$ref": "#/components/schemas/Ledger", + "nullable": false + }, + "default": [] + }, + "pluginInstance": { + "description": "Plugin Instance metadata", + "items": { + "$ref": "#/components/schemas/PluginInstance", + "nullable": false + }, + "default": [] + }, + "signature": { + "description": "signature of the message", + "type": "string", + "nullable": false + } + } + }, + "PrimaryKey": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "nullable": false + }, + "ConsortiumMemberId": { + "$ref": "#/components/schemas/PrimaryKey", + "description": "ID of Consortium member who operates the ledger (if any). Defined as an optional property in case the ledger is a permissionless and/or public one such as the Bitcoin or Ethereum mainnets." + }, + "CactusNodeId": { + "$ref": "#/components/schemas/PrimaryKey", + "description": "ID of a Cactus node that must uniquely distinguish it from all other Cactus nodes within a Consortium. Note that API server instances do not have their own identity the way a node does." + }, + "ConsortiumId": { + "$ref": "#/components/schemas/PrimaryKey" + }, + "LedgerId": { + "description": "String that uniquely identifies a ledger within a Cactus consortium so that transactions can be routed to the correct ledger.", + "$ref": "#/components/schemas/PrimaryKey" + }, + "PluginInstanceId": { + "description": "String that uniquely identifies a plugin instance within a Cactus consortium so that requests can be addressed/routed directly to individual plugins when necessary.", + "$ref": "#/components/schemas/PrimaryKey" + }, + "Ledger": { + "type": "object", + "required": ["id", "ledgerType"], + "properties": { + "id": { + "$ref": "#/components/schemas/LedgerId" + }, + "ledgerType": { + "$ref": "#/components/schemas/LedgerType", + "nullable": false + }, + "consortiumMemberId": { + "$ref": "#/components/schemas/ConsortiumMemberId" + } + } + }, + "LedgerType": { + "description": "Enumerates the different ledger vendors and their major versions encoded within the name of the LedgerType. For example \"BESU_1X\" involves all of the [1.0.0;2.0.0) where 1.0.0 is included and anything up until, but not 2.0.0. See: https://stackoverflow.com/a/4396303/698470 for further explanation.", + "type": "string", + "enum": [ + "BESU_1X", + "BESU_2X", + "BURROW_0X", + "CORDA_4X", + "FABRIC_2", + "SAWTOOTH_1X" + ] + }, + "CactusNodeMeta": { + "description": "A Cactus node meta information", + "type": "object", + "required": ["nodeApiHost", "publicKeyPem"], + "properties": { + "nodeApiHost": { + "type": "string", + "minLength": 1, + "maxLength": 1024, + "nullable": false + }, + "publicKeyPem": { + "description": "The PEM encoded public key that was used to generate the JWS included in the response (the jws property)", + "type": "string", + "minLength": 1, + "maxLength": 65535, + "nullable": false, + "format": "Must only contain the public key, never include here the PEM that also contains a private key. See PEM format: https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail" + } + } + }, + "CactusNode": { + "description": "A Cactus node can be a single server, or a set of servers behind a load balancer acting as one.", + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/CactusNodeMeta" + }, + { + "type": "object", + "required": [ + "id", + "consortiumId", + "nodeApiHost", + "memberId", + "publicKeyPem", + "pluginInstanceIds", + "ledgerIds" + ], + "properties": { + "id": { + "$ref": "#/components/schemas/CactusNodeId", + "example": "809a76ba-cfb8-4045-a5c6-ed70a7314c25" + }, + "consortiumId": { + "$ref": "#/components/schemas/ConsortiumId", + "description": "ID of the Cactus Consortium this node is in.", + "example": "3e2670d9-2d14-45bd-96f5-33e2c4b4e3fb" + }, + "memberId": { + "$ref": "#/components/schemas/ConsortiumMemberId", + "example": "b3674a28-e442-4feb-b1f3-8cbe46c20e5e" + }, + "ledgerIds": { + "description": "Stores an array of Ledger entity IDs that are reachable (routable) via this Cactus Node. This information is used by the client side SDK API client to figure out at runtime where to send API requests that are specific to a certain ledger such as requests to execute transactions.", + "type": "array", + "nullable": false, + "minItems": 0, + "maxItems": 2048, + "default": [], + "items": { + "$ref": "#/components/schemas/LedgerId" + } + }, + "pluginInstanceIds": { + "type": "array", + "nullable": false, + "minItems": 0, + "maxItems": 2048, + "default": [], + "items": { + "$ref": "#/components/schemas/PluginInstanceId" + } + } + } + } + ] + }, + "PluginInstance": { + "type": "object", + "required": ["id", "packageName"], + "properties": { + "id": { + "$ref": "#/components/schemas/PluginInstanceId" + }, + "packageName": { + "type": "string", + "minLength": 1, + "maxLength": 4096, + "nullable": false + } + } + }, + "BroadcastRequestV1": { + "type": "object", + "required": ["message", "signature"], + "properties": { + "message": { + "type": "object", + "nullable": false, + "required": ["message", "pubKey"], + "properties": { + "message": { + "$ref": "#/components/schemas/NewNodeRequestV1" + }, + "pubKey": { + "type": "string", + "nullable": false + } + } + }, + "signature": { + "type": "string", + "nullable": false + } + } + }, + "BroadcastResponseV1": { + "type": "object", + "nullable": false, + "required": ["result"], + "properties": { + "result": { + "type": "boolean", + "nullable": false + } + } + }, + "GetNodeJwsResponse": { + "type": "object", + "required": ["jws"], + "properties": { + "jws": { + "description": "The JSON Web Signature of the Cactus node.", + "$ref": "#/components/schemas/JWSGeneral", + "nullable": false + } + } + }, + "GetConsortiumJwsResponse": { + "type": "object", + "required": ["jws"], + "properties": { + "jws": { + "description": "The JSON Web Signature of the Cactus consortium.", + "$ref": "#/components/schemas/JWSGeneral", + "nullable": false, + "format": "The general format which is a JSON object, not a string." + } + } + }, + "PrometheusExporterMetricsResponse": { + "type": "string", + "nullable": false + }, + "GetNodeJwsRequest": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "GetConsortiumJwsRequest": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "JWSRecipient": { + "description": "A JSON Web Signature. See: https://tools.ietf.org/html/rfc7515 for info about standard.", + "type": "object", + "required": ["signature"], + "properties": { + "signature": { + "type": "string" + }, + "protected": { + "type": "string" + }, + "header": { + "type": "object", + "additionalProperties": true + } + } + }, + "JWSGeneral": { + "type": "object", + "required": ["payload", "signatures"], + "properties": { + "payload": { + "type": "string", + "minLength": 1, + "maxLength": 65535 + }, + "signatures": { + "type": "array", + "items": { + "$ref": "#/components/schemas/JWSRecipient" + } + } + } + } + } + }, + "paths": { + "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/consortium/jws": { + "post": { + "x-hyperledger-cacti": { + "http": { + "verbLowerCase": "post", + "path": "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/consortium/jws" + } + }, + "operationId": "getConsortiumJwsV1", + "summary": "Retrieves a consortium JWS", + "description": "The JWS asserting the consortium metadata (pub keys and hosts of nodes)", + "parameters": [], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetConsortiumJwsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetConsortiumJwsResponse" + } + } + } + } + } + } + }, + "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/node/jws": { + "post": { + "x-hyperledger-cacti": { + "http": { + "verbLowerCase": "post", + "path": "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/node/jws" + } + }, + "operationId": "getNodeJwsV1", + "summary": "Retrieves the JWT of a Cactus Node", + "parameters": [], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetNodeJwsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetNodeJwsResponse" + } + } + } + } + } + } + }, + "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/get-prometheus-exporter-metrics": { + "get": { + "x-hyperledger-cacti": { + "http": { + "verbLowerCase": "get", + "path": "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/get-prometheus-exporter-metrics" + } + }, + "operationId": "getPrometheusMetricsV1", + "summary": "Get the Prometheus Metrics", + "parameters": [], + "responses": { + "200": { + "description": "OK", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/PrometheusExporterMetricsResponse" + } + } + } + } + } + } + }, + "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/add-node": { + "post": { + "x-hyperledger-cacti": { + "http": { + "verbLowerCase": "post", + "path": "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/add-node" + } + }, + "operationId": "addNodeToConsortiumV1", + "summary": "Adds a node to consortium JWS", + "description": "", + "parameters": [], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewNodeRequestV1" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetConsortiumJwsResponse" + } + } + } + } + } + } + }, + "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/receive-broadcast": { + "post": { + "x-hyperledger-cacti": { + "http": { + "verbLowerCase": "post", + "path": "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/receive-broadcast" + } + }, + "operationId": "receiveBroadcastV1", + "summary": "Adds a node to consortium JWS", + "description": "", + "parameters": [], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BroadcastRequestV1" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BroadcastResponseV1" + } + } + } + } + } + } + } + } +} diff --git a/packages/cacti-plugin-consortium-static/src/main/json/openapi.tpl.json b/packages/cacti-plugin-consortium-static/src/main/json/openapi.tpl.json new file mode 100644 index 00000000000..1e698575cd0 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/json/openapi.tpl.json @@ -0,0 +1,505 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Hyperledger Cactus Plugin - Consortium Web Service", + "description": "Manage a Cactus consortium through the APIs. Needs administrative privileges.", + "version": "2.0.0-rc.2", + "license": { + "name": "Apache-2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + } + }, + "components": { + "schemas": { + "Identity": { + "type": "object", + "description": "Identity object of a Cacti Node", + "required": ["pubKey", "memberId", "proof"], + "properties": { + "pubKey": { + "description": "Public key of the Node", + "type": "string", + "nullable": false + }, + "memberId": { + "description": "memberId of the organization the node belongs to", + "type": "string", + "nullable": false + }, + "proof": { + "description": "JWT generated by the organization the node belongs to", + "type": "string", + "nullable": false + } + } + }, + "NewNodeRequestV1": { + "type": "object", + "required": [ + "identity", + "treeHash", + "node", + "ledger", + "pluginInstance", + "signature" + ], + "properties": { + "identity": { + "$ref": "#/components/schemas/Identity", + "nullable": false + }, + "treeHash": { + "description": "proof of common configs and policies defined by the consortium", + "type": "string", + "nullable": false + }, + "node": { + "description": "A Cacti Node", + "$ref": "#/components/schemas/CactusNode", + "nullable": false + }, + "ledger": { + "description": "Ledger metadata", + "type": "array", + "items": { + "$ref": "#/components/schemas/Ledger", + "nullable": false + }, + "default": [] + }, + "pluginInstance": { + "description": "Plugin Instance metadata", + "items": { + "$ref": "#/components/schemas/PluginInstance", + "nullable": false + }, + "default": [] + }, + "signature": { + "description": "signature of the message", + "type": "string", + "nullable": false + } + } + }, + "PrimaryKey": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "nullable": false + }, + "ConsortiumMemberId": { + "$ref": "#/components/schemas/PrimaryKey", + "description": "ID of Consortium member who operates the ledger (if any). Defined as an optional property in case the ledger is a permissionless and/or public one such as the Bitcoin or Ethereum mainnets." + }, + "CactusNodeId": { + "$ref": "#/components/schemas/PrimaryKey", + "description": "ID of a Cactus node that must uniquely distinguish it from all other Cactus nodes within a Consortium. Note that API server instances do not have their own identity the way a node does." + }, + "ConsortiumId": { + "$ref": "#/components/schemas/PrimaryKey" + }, + "LedgerId": { + "description": "String that uniquely identifies a ledger within a Cactus consortium so that transactions can be routed to the correct ledger.", + "$ref": "#/components/schemas/PrimaryKey" + }, + "PluginInstanceId": { + "description": "String that uniquely identifies a plugin instance within a Cactus consortium so that requests can be addressed/routed directly to individual plugins when necessary.", + "$ref": "#/components/schemas/PrimaryKey" + }, + "Ledger": { + "type": "object", + "required": ["id", "ledgerType"], + "properties": { + "id": { + "$ref": "#/components/schemas/LedgerId" + }, + "ledgerType": { + "$ref": "#/components/schemas/LedgerType", + "nullable": false + }, + "consortiumMemberId": { + "$ref": "#/components/schemas/ConsortiumMemberId" + } + } + }, + "LedgerType": { + "description": "Enumerates the different ledger vendors and their major versions encoded within the name of the LedgerType. For example \"BESU_1X\" involves all of the [1.0.0;2.0.0) where 1.0.0 is included and anything up until, but not 2.0.0. See: https://stackoverflow.com/a/4396303/698470 for further explanation.", + "type": "string", + "enum": [ + "BESU_1X", + "BESU_2X", + "BURROW_0X", + "CORDA_4X", + "FABRIC_2", + "SAWTOOTH_1X" + ] + }, + "CactusNodeMeta": { + "description": "A Cactus node meta information", + "type": "object", + "required": ["nodeApiHost", "publicKeyPem"], + "properties": { + "nodeApiHost": { + "type": "string", + "minLength": 1, + "maxLength": 1024, + "nullable": false + }, + "publicKeyPem": { + "description": "The PEM encoded public key that was used to generate the JWS included in the response (the jws property)", + "type": "string", + "minLength": 1, + "maxLength": 65535, + "nullable": false, + "format": "Must only contain the public key, never include here the PEM that also contains a private key. See PEM format: https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail" + } + } + }, + "CactusNode": { + "description": "A Cactus node can be a single server, or a set of servers behind a load balancer acting as one.", + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/CactusNodeMeta" + }, + { + "type": "object", + "required": [ + "id", + "consortiumId", + "nodeApiHost", + "memberId", + "publicKeyPem", + "pluginInstanceIds", + "ledgerIds" + ], + "properties": { + "id": { + "$ref": "#/components/schemas/CactusNodeId", + "example": "809a76ba-cfb8-4045-a5c6-ed70a7314c25" + }, + "consortiumId": { + "$ref": "#/components/schemas/ConsortiumId", + "description": "ID of the Cactus Consortium this node is in.", + "example": "3e2670d9-2d14-45bd-96f5-33e2c4b4e3fb" + }, + "memberId": { + "$ref": "#/components/schemas/ConsortiumMemberId", + "example": "b3674a28-e442-4feb-b1f3-8cbe46c20e5e" + }, + "ledgerIds": { + "description": "Stores an array of Ledger entity IDs that are reachable (routable) via this Cactus Node. This information is used by the client side SDK API client to figure out at runtime where to send API requests that are specific to a certain ledger such as requests to execute transactions.", + "type": "array", + "nullable": false, + "minItems": 0, + "maxItems": 2048, + "default": [], + "items": { + "$ref": "#/components/schemas/LedgerId" + } + }, + "pluginInstanceIds": { + "type": "array", + "nullable": false, + "minItems": 0, + "maxItems": 2048, + "default": [], + "items": { + "$ref": "#/components/schemas/PluginInstanceId" + } + } + } + } + ] + }, + "PluginInstance": { + "type": "object", + "required": ["id", "packageName"], + "properties": { + "id": { + "$ref": "#/components/schemas/PluginInstanceId" + }, + "packageName": { + "type": "string", + "minLength": 1, + "maxLength": 4096, + "nullable": false + } + } + }, + "BroadcastRequestV1": { + "type": "object", + "required": ["message", "signature"], + "properties": { + "message": { + "type": "object", + "nullable": false, + "required": ["message", "pubKey"], + "properties": { + "message": { + "$ref": "#/components/schemas/NewNodeRequestV1" + }, + "pubKey": { + "type": "string", + "nullable": false + } + } + }, + "signature": { + "type": "string", + "nullable": false + } + } + }, + "BroadcastResponseV1": { + "type": "object", + "nullable": false, + "required": ["result"], + "properties": { + "result": { + "type": "boolean", + "nullable": false + } + } + }, + "GetNodeJwsResponse": { + "type": "object", + "required": ["jws"], + "properties": { + "jws": { + "description": "The JSON Web Signature of the Cactus node.", + "$ref": "#/components/schemas/JWSGeneral", + "nullable": false + } + } + }, + "GetConsortiumJwsResponse": { + "type": "object", + "required": ["jws"], + "properties": { + "jws": { + "description": "The JSON Web Signature of the Cactus consortium.", + "$ref": "#/components/schemas/JWSGeneral", + "nullable": false, + "format": "The general format which is a JSON object, not a string." + } + } + }, + "PrometheusExporterMetricsResponse": { + "type": "string", + "nullable": false + }, + "GetNodeJwsRequest": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "GetConsortiumJwsRequest": { + "type": "object", + "additionalProperties": false, + "properties": {} + }, + "JWSRecipient": { + "description": "A JSON Web Signature. See: https://tools.ietf.org/html/rfc7515 for info about standard.", + "type": "object", + "required": ["signature"], + "properties": { + "signature": { + "type": "string" + }, + "protected": { + "type": "string" + }, + "header": { + "type": "object", + "additionalProperties": true + } + } + }, + "JWSGeneral": { + "type": "object", + "required": ["payload", "signatures"], + "properties": { + "payload": { + "type": "string", + "minLength": 1, + "maxLength": 65535 + }, + "signatures": { + "type": "array", + "items": { + "$ref": "#/components/schemas/JWSRecipient" + } + } + } + } + } + }, + "paths": { + "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/consortium/jws": { + "post": { + "x-hyperledger-cacti": { + "http": { + "verbLowerCase": "post", + "path": "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/consortium/jws" + } + }, + "operationId": "getConsortiumJwsV1", + "summary": "Retrieves a consortium JWS", + "description": "The JWS asserting the consortium metadata (pub keys and hosts of nodes)", + "parameters": [], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetConsortiumJwsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetConsortiumJwsResponse" + } + } + } + } + } + } + }, + "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/node/jws": { + "post": { + "x-hyperledger-cacti": { + "http": { + "verbLowerCase": "post", + "path": "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/node/jws" + } + }, + "operationId": "getNodeJwsV1", + "summary": "Retrieves the JWT of a Cactus Node", + "parameters": [], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetNodeJwsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetNodeJwsResponse" + } + } + } + } + } + } + }, + "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/get-prometheus-exporter-metrics": { + "get": { + "x-hyperledger-cacti": { + "http": { + "verbLowerCase": "get", + "path": "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/get-prometheus-exporter-metrics" + } + }, + "operationId": "getPrometheusMetricsV1", + "summary": "Get the Prometheus Metrics", + "parameters": [], + "responses": { + "200": { + "description": "OK", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/PrometheusExporterMetricsResponse" + } + } + } + } + } + } + }, + "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/add-node": { + "post": { + "x-hyperledger-cacti": { + "http": { + "verbLowerCase": "post", + "path": "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/add-node" + } + }, + "operationId": "addNodeToConsortiumV1", + "summary": "Adds a node to consortium JWS", + "description": "", + "parameters": [], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewNodeRequestV1" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetConsortiumJwsResponse" + } + } + } + } + } + } + }, + "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/receive-broadcast": { + "post": { + "x-hyperledger-cacti": { + "http": { + "verbLowerCase": "post", + "path": "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/receive-broadcast" + } + }, + "operationId": "receiveBroadcastV1", + "summary": "Adds a node to consortium JWS", + "description": "", + "parameters": [], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BroadcastRequestV1" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BroadcastResponseV1" + } + } + } + } + } + } + } + } +} diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/.openapi-generator/FILES b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/.openapi-generator/FILES new file mode 100644 index 00000000000..e009b9122d2 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/.openapi-generator/FILES @@ -0,0 +1,38 @@ +README.md +build.gradle +gradlew +gradlew.bat +settings.gradle +src/main/kotlin/org/openapitools/client/apis/DefaultApi.kt +src/main/kotlin/org/openapitools/client/infrastructure/ApiAbstractions.kt +src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt +src/main/kotlin/org/openapitools/client/infrastructure/ApiResponse.kt +src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/Errors.kt +src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/PartConfig.kt +src/main/kotlin/org/openapitools/client/infrastructure/RequestConfig.kt +src/main/kotlin/org/openapitools/client/infrastructure/RequestMethod.kt +src/main/kotlin/org/openapitools/client/infrastructure/ResponseExtensions.kt +src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt +src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt +src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt +src/main/kotlin/org/openapitools/client/models/BroadcastRequestV1.kt +src/main/kotlin/org/openapitools/client/models/BroadcastRequestV1Message.kt +src/main/kotlin/org/openapitools/client/models/BroadcastResponseV1.kt +src/main/kotlin/org/openapitools/client/models/CactusNode.kt +src/main/kotlin/org/openapitools/client/models/CactusNodeAllOf.kt +src/main/kotlin/org/openapitools/client/models/CactusNodeMeta.kt +src/main/kotlin/org/openapitools/client/models/GetConsortiumJwsResponse.kt +src/main/kotlin/org/openapitools/client/models/GetNodeJwsResponse.kt +src/main/kotlin/org/openapitools/client/models/Identity.kt +src/main/kotlin/org/openapitools/client/models/JWSGeneral.kt +src/main/kotlin/org/openapitools/client/models/JWSRecipient.kt +src/main/kotlin/org/openapitools/client/models/Ledger.kt +src/main/kotlin/org/openapitools/client/models/LedgerType.kt +src/main/kotlin/org/openapitools/client/models/NewNodeRequestV1.kt +src/main/kotlin/org/openapitools/client/models/PluginInstance.kt diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/.openapi-generator/VERSION b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/.openapi-generator/VERSION new file mode 100644 index 00000000000..cd802a1ec4e --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/.openapi-generator/VERSION @@ -0,0 +1 @@ +6.6.0 \ No newline at end of file diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/README.md b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/README.md new file mode 100644 index 00000000000..3dc25042e1e --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/README.md @@ -0,0 +1,78 @@ +# org.openapitools.client - Kotlin client library for Hyperledger Cactus Plugin - Consortium Web Service + +Manage a Cactus consortium through the APIs. Needs administrative privileges. + +## Overview +This API client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. By using the [openapi-spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate an API client. + +- API version: 2.0.0-rc.2 +- Package version: +- Build package: org.openapitools.codegen.languages.KotlinClientCodegen + +## Requires + +* Kotlin 1.7.21 +* Gradle 7.5 + +## Build + +First, create the gradle wrapper script: + +``` +gradle wrapper +``` + +Then, run: + +``` +./gradlew check assemble +``` + +This runs all tests and packages the library. + +## Features/Implementation Notes + +* Supports JSON inputs/outputs, File inputs, and Form inputs. +* Supports collection formats for query parameters: csv, tsv, ssv, pipes. +* Some Kotlin and Java types are fully qualified to avoid conflicts with types defined in OpenAPI definitions. +* Implementation of ApiClient is intended to reduce method counts, specifically to benefit Android targets. + + +## Documentation for API Endpoints + +All URIs are relative to *http://localhost* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +*DefaultApi* | [**addNodeToConsortiumV1**](docs/DefaultApi.md#addnodetoconsortiumv1) | **POST** /api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/add-node | Adds a node to consortium JWS +*DefaultApi* | [**getConsortiumJwsV1**](docs/DefaultApi.md#getconsortiumjwsv1) | **POST** /api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/consortium/jws | Retrieves a consortium JWS +*DefaultApi* | [**getNodeJwsV1**](docs/DefaultApi.md#getnodejwsv1) | **POST** /api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/node/jws | Retrieves the JWT of a Cactus Node +*DefaultApi* | [**getPrometheusMetricsV1**](docs/DefaultApi.md#getprometheusmetricsv1) | **GET** /api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/get-prometheus-exporter-metrics | Get the Prometheus Metrics +*DefaultApi* | [**receiveBroadcastV1**](docs/DefaultApi.md#receivebroadcastv1) | **POST** /api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/receive-broadcast | Adds a node to consortium JWS + + + +## Documentation for Models + + - [org.openapitools.client.models.BroadcastRequestV1](docs/BroadcastRequestV1.md) + - [org.openapitools.client.models.BroadcastRequestV1Message](docs/BroadcastRequestV1Message.md) + - [org.openapitools.client.models.BroadcastResponseV1](docs/BroadcastResponseV1.md) + - [org.openapitools.client.models.CactusNode](docs/CactusNode.md) + - [org.openapitools.client.models.CactusNodeAllOf](docs/CactusNodeAllOf.md) + - [org.openapitools.client.models.CactusNodeMeta](docs/CactusNodeMeta.md) + - [org.openapitools.client.models.GetConsortiumJwsResponse](docs/GetConsortiumJwsResponse.md) + - [org.openapitools.client.models.GetNodeJwsResponse](docs/GetNodeJwsResponse.md) + - [org.openapitools.client.models.Identity](docs/Identity.md) + - [org.openapitools.client.models.JWSGeneral](docs/JWSGeneral.md) + - [org.openapitools.client.models.JWSRecipient](docs/JWSRecipient.md) + - [org.openapitools.client.models.Ledger](docs/Ledger.md) + - [org.openapitools.client.models.LedgerType](docs/LedgerType.md) + - [org.openapitools.client.models.NewNodeRequestV1](docs/NewNodeRequestV1.md) + - [org.openapitools.client.models.PluginInstance](docs/PluginInstance.md) + + + +## Documentation for Authorization + +Endpoints do not require authorization. + diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/build.gradle b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/build.gradle new file mode 100644 index 00000000000..66a3c68b890 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/build.gradle @@ -0,0 +1,38 @@ +group 'org.openapitools' +version '1.0.0' + +wrapper { + gradleVersion = '7.5' + distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip" +} + +buildscript { + ext.kotlin_version = '1.7.21' + + repositories { + maven { url "https://repo1.maven.org/maven2" } + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +apply plugin: 'kotlin' +apply plugin: 'maven-publish' + +repositories { + maven { url "https://repo1.maven.org/maven2" } +} + +test { + useJUnitPlatform() +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" + implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" + implementation "com.squareup.moshi:moshi-kotlin:1.13.0" + implementation "com.squareup.moshi:moshi-adapters:1.13.0" + implementation "com.squareup.okhttp3:okhttp:4.10.0" + testImplementation "io.kotlintest:kotlintest-runner-junit5:3.4.2" +} diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/gradlew b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/gradlew new file mode 100644 index 00000000000..aeb74cbb43e --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/gradlew @@ -0,0 +1,245 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# 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/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +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. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +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=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=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# 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, 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. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + 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. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/gradlew.bat b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/gradlew.bat new file mode 100644 index 00000000000..93e3f59f135 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +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! +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 + +:omega diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/settings.gradle b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/settings.gradle new file mode 100644 index 00000000000..391dcea81db --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/settings.gradle @@ -0,0 +1,2 @@ + +rootProject.name = 'kotlin-client' \ No newline at end of file diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/apis/DefaultApi.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/apis/DefaultApi.kt new file mode 100644 index 00000000000..5117aa63107 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/apis/DefaultApi.kt @@ -0,0 +1,410 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.apis + +import java.io.IOException +import okhttp3.OkHttpClient +import okhttp3.HttpUrl + +import org.openapitools.client.models.BroadcastRequestV1 +import org.openapitools.client.models.BroadcastResponseV1 +import org.openapitools.client.models.GetConsortiumJwsResponse +import org.openapitools.client.models.GetNodeJwsResponse +import org.openapitools.client.models.NewNodeRequestV1 + +import com.squareup.moshi.Json + +import org.openapitools.client.infrastructure.ApiClient +import org.openapitools.client.infrastructure.ApiResponse +import org.openapitools.client.infrastructure.ClientException +import org.openapitools.client.infrastructure.ClientError +import org.openapitools.client.infrastructure.ServerException +import org.openapitools.client.infrastructure.ServerError +import org.openapitools.client.infrastructure.MultiValueMap +import org.openapitools.client.infrastructure.PartConfig +import org.openapitools.client.infrastructure.RequestConfig +import org.openapitools.client.infrastructure.RequestMethod +import org.openapitools.client.infrastructure.ResponseType +import org.openapitools.client.infrastructure.Success +import org.openapitools.client.infrastructure.toMultiValue + +class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient = ApiClient.defaultClient) : ApiClient(basePath, client) { + companion object { + @JvmStatic + val defaultBasePath: String by lazy { + System.getProperties().getProperty(ApiClient.baseUrlKey, "http://localhost") + } + } + + /** + * Adds a node to consortium JWS + * + * @param newNodeRequestV1 (optional) + * @return GetConsortiumJwsResponse + * @throws IllegalStateException If the request is not correctly configured + * @throws IOException Rethrows the OkHttp execute method exception + * @throws UnsupportedOperationException If the API returns an informational or redirection response + * @throws ClientException If the API returns a client error response + * @throws ServerException If the API returns a server error response + */ + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun addNodeToConsortiumV1(newNodeRequestV1: NewNodeRequestV1? = null) : GetConsortiumJwsResponse { + val localVarResponse = addNodeToConsortiumV1WithHttpInfo(newNodeRequestV1 = newNodeRequestV1) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as GetConsortiumJwsResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + } + } + + /** + * Adds a node to consortium JWS + * + * @param newNodeRequestV1 (optional) + * @return ApiResponse + * @throws IllegalStateException If the request is not correctly configured + * @throws IOException Rethrows the OkHttp execute method exception + */ + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun addNodeToConsortiumV1WithHttpInfo(newNodeRequestV1: NewNodeRequestV1?) : ApiResponse { + val localVariableConfig = addNodeToConsortiumV1RequestConfig(newNodeRequestV1 = newNodeRequestV1) + + return request( + localVariableConfig + ) + } + + /** + * To obtain the request config of the operation addNodeToConsortiumV1 + * + * @param newNodeRequestV1 (optional) + * @return RequestConfig + */ + fun addNodeToConsortiumV1RequestConfig(newNodeRequestV1: NewNodeRequestV1?) : RequestConfig { + val localVariableBody = newNodeRequestV1 + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json" + + return RequestConfig( + method = RequestMethod.POST, + path = "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/add-node", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = false, + body = localVariableBody + ) + } + + /** + * Retrieves a consortium JWS + * The JWS asserting the consortium metadata (pub keys and hosts of nodes) + * @param body (optional) + * @return GetConsortiumJwsResponse + * @throws IllegalStateException If the request is not correctly configured + * @throws IOException Rethrows the OkHttp execute method exception + * @throws UnsupportedOperationException If the API returns an informational or redirection response + * @throws ClientException If the API returns a client error response + * @throws ServerException If the API returns a server error response + */ + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun getConsortiumJwsV1(body: kotlin.Any? = null) : GetConsortiumJwsResponse { + val localVarResponse = getConsortiumJwsV1WithHttpInfo(body = body) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as GetConsortiumJwsResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + } + } + + /** + * Retrieves a consortium JWS + * The JWS asserting the consortium metadata (pub keys and hosts of nodes) + * @param body (optional) + * @return ApiResponse + * @throws IllegalStateException If the request is not correctly configured + * @throws IOException Rethrows the OkHttp execute method exception + */ + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun getConsortiumJwsV1WithHttpInfo(body: kotlin.Any?) : ApiResponse { + val localVariableConfig = getConsortiumJwsV1RequestConfig(body = body) + + return request( + localVariableConfig + ) + } + + /** + * To obtain the request config of the operation getConsortiumJwsV1 + * + * @param body (optional) + * @return RequestConfig + */ + fun getConsortiumJwsV1RequestConfig(body: kotlin.Any?) : RequestConfig { + val localVariableBody = body + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json" + + return RequestConfig( + method = RequestMethod.POST, + path = "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/consortium/jws", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = false, + body = localVariableBody + ) + } + + /** + * Retrieves the JWT of a Cactus Node + * + * @param body (optional) + * @return GetNodeJwsResponse + * @throws IllegalStateException If the request is not correctly configured + * @throws IOException Rethrows the OkHttp execute method exception + * @throws UnsupportedOperationException If the API returns an informational or redirection response + * @throws ClientException If the API returns a client error response + * @throws ServerException If the API returns a server error response + */ + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun getNodeJwsV1(body: kotlin.Any? = null) : GetNodeJwsResponse { + val localVarResponse = getNodeJwsV1WithHttpInfo(body = body) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as GetNodeJwsResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + } + } + + /** + * Retrieves the JWT of a Cactus Node + * + * @param body (optional) + * @return ApiResponse + * @throws IllegalStateException If the request is not correctly configured + * @throws IOException Rethrows the OkHttp execute method exception + */ + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun getNodeJwsV1WithHttpInfo(body: kotlin.Any?) : ApiResponse { + val localVariableConfig = getNodeJwsV1RequestConfig(body = body) + + return request( + localVariableConfig + ) + } + + /** + * To obtain the request config of the operation getNodeJwsV1 + * + * @param body (optional) + * @return RequestConfig + */ + fun getNodeJwsV1RequestConfig(body: kotlin.Any?) : RequestConfig { + val localVariableBody = body + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json" + + return RequestConfig( + method = RequestMethod.POST, + path = "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/node/jws", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = false, + body = localVariableBody + ) + } + + /** + * Get the Prometheus Metrics + * + * @return kotlin.String + * @throws IllegalStateException If the request is not correctly configured + * @throws IOException Rethrows the OkHttp execute method exception + * @throws UnsupportedOperationException If the API returns an informational or redirection response + * @throws ClientException If the API returns a client error response + * @throws ServerException If the API returns a server error response + */ + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun getPrometheusMetricsV1() : kotlin.String { + val localVarResponse = getPrometheusMetricsV1WithHttpInfo() + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as kotlin.String + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + } + } + + /** + * Get the Prometheus Metrics + * + * @return ApiResponse + * @throws IllegalStateException If the request is not correctly configured + * @throws IOException Rethrows the OkHttp execute method exception + */ + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun getPrometheusMetricsV1WithHttpInfo() : ApiResponse { + val localVariableConfig = getPrometheusMetricsV1RequestConfig() + + return request( + localVariableConfig + ) + } + + /** + * To obtain the request config of the operation getPrometheusMetricsV1 + * + * @return RequestConfig + */ + fun getPrometheusMetricsV1RequestConfig() : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + + return RequestConfig( + method = RequestMethod.GET, + path = "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/get-prometheus-exporter-metrics", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = false, + body = localVariableBody + ) + } + + /** + * Adds a node to consortium JWS + * + * @param broadcastRequestV1 (optional) + * @return BroadcastResponseV1 + * @throws IllegalStateException If the request is not correctly configured + * @throws IOException Rethrows the OkHttp execute method exception + * @throws UnsupportedOperationException If the API returns an informational or redirection response + * @throws ClientException If the API returns a client error response + * @throws ServerException If the API returns a server error response + */ + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun receiveBroadcastV1(broadcastRequestV1: BroadcastRequestV1? = null) : BroadcastResponseV1 { + val localVarResponse = receiveBroadcastV1WithHttpInfo(broadcastRequestV1 = broadcastRequestV1) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as BroadcastResponseV1 + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + } + } + + /** + * Adds a node to consortium JWS + * + * @param broadcastRequestV1 (optional) + * @return ApiResponse + * @throws IllegalStateException If the request is not correctly configured + * @throws IOException Rethrows the OkHttp execute method exception + */ + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun receiveBroadcastV1WithHttpInfo(broadcastRequestV1: BroadcastRequestV1?) : ApiResponse { + val localVariableConfig = receiveBroadcastV1RequestConfig(broadcastRequestV1 = broadcastRequestV1) + + return request( + localVariableConfig + ) + } + + /** + * To obtain the request config of the operation receiveBroadcastV1 + * + * @param broadcastRequestV1 (optional) + * @return RequestConfig + */ + fun receiveBroadcastV1RequestConfig(broadcastRequestV1: BroadcastRequestV1?) : RequestConfig { + val localVariableBody = broadcastRequestV1 + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json" + + return RequestConfig( + method = RequestMethod.POST, + path = "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/receive-broadcast", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = false, + body = localVariableBody + ) + } + + + private fun encodeURIComponent(uriComponent: kotlin.String): kotlin.String = + HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0] +} diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/ApiAbstractions.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/ApiAbstractions.kt new file mode 100644 index 00000000000..ef7a8f1e1a6 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/ApiAbstractions.kt @@ -0,0 +1,23 @@ +package org.openapitools.client.infrastructure + +typealias MultiValueMap = MutableMap> + +fun collectionDelimiter(collectionFormat: String) = when(collectionFormat) { + "csv" -> "," + "tsv" -> "\t" + "pipe" -> "|" + "space" -> " " + else -> "" +} + +val defaultMultiValueConverter: (item: Any?) -> String = { item -> "$item" } + +fun toMultiValue(items: Array, collectionFormat: String, map: (item: T) -> String = defaultMultiValueConverter) + = toMultiValue(items.asIterable(), collectionFormat, map) + +fun toMultiValue(items: Iterable, collectionFormat: String, map: (item: T) -> String = defaultMultiValueConverter): List { + return when(collectionFormat) { + "multi" -> items.map(map) + else -> listOf(items.joinToString(separator = collectionDelimiter(collectionFormat), transform = map)) + } +} \ No newline at end of file diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt new file mode 100644 index 00000000000..ea4b7b65935 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/ApiClient.kt @@ -0,0 +1,245 @@ +package org.openapitools.client.infrastructure + +import okhttp3.OkHttpClient +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.asRequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.FormBody +import okhttp3.HttpUrl.Companion.toHttpUrlOrNull +import okhttp3.ResponseBody +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.Request +import okhttp3.Headers +import okhttp3.Headers.Companion.toHeaders +import okhttp3.MultipartBody +import okhttp3.Call +import okhttp3.Callback +import okhttp3.Response +import okhttp3.internal.EMPTY_REQUEST +import java.io.BufferedWriter +import java.io.File +import java.io.FileWriter +import java.io.IOException +import java.net.URLConnection +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime +import java.time.OffsetDateTime +import java.time.OffsetTime +import java.util.Locale +import com.squareup.moshi.adapter + +open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClient) { + companion object { + protected const val ContentType = "Content-Type" + protected const val Accept = "Accept" + protected const val Authorization = "Authorization" + protected const val JsonMediaType = "application/json" + protected const val FormDataMediaType = "multipart/form-data" + protected const val FormUrlEncMediaType = "application/x-www-form-urlencoded" + protected const val XmlMediaType = "application/xml" + + val apiKey: MutableMap = mutableMapOf() + val apiKeyPrefix: MutableMap = mutableMapOf() + var username: String? = null + var password: String? = null + var accessToken: String? = null + const val baseUrlKey = "org.openapitools.client.baseUrl" + + @JvmStatic + val defaultClient: OkHttpClient by lazy { + builder.build() + } + + @JvmStatic + val builder: OkHttpClient.Builder = OkHttpClient.Builder() + } + + /** + * Guess Content-Type header from the given file (defaults to "application/octet-stream"). + * + * @param file The given file + * @return The guessed Content-Type + */ + protected fun guessContentTypeFromFile(file: File): String { + val contentType = URLConnection.guessContentTypeFromName(file.name) + return contentType ?: "application/octet-stream" + } + + protected inline fun requestBody(content: T, mediaType: String?): RequestBody = + when { + content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull()) + mediaType == FormDataMediaType -> + MultipartBody.Builder() + .setType(MultipartBody.FORM) + .apply { + // content's type *must* be Map> + @Suppress("UNCHECKED_CAST") + (content as Map>).forEach { (name, part) -> + if (part.body is File) { + val partHeaders = part.headers.toMutableMap() + + ("Content-Disposition" to "form-data; name=\"$name\"; filename=\"${part.body.name}\"") + val fileMediaType = guessContentTypeFromFile(part.body).toMediaTypeOrNull() + addPart( + partHeaders.toHeaders(), + part.body.asRequestBody(fileMediaType) + ) + } else { + val partHeaders = part.headers.toMutableMap() + + ("Content-Disposition" to "form-data; name=\"$name\"") + addPart( + partHeaders.toHeaders(), + parameterToString(part.body).toRequestBody(null) + ) + } + } + }.build() + mediaType == FormUrlEncMediaType -> { + FormBody.Builder().apply { + // content's type *must* be Map> + @Suppress("UNCHECKED_CAST") + (content as Map>).forEach { (name, part) -> + add(name, parameterToString(part.body)) + } + }.build() + } + mediaType == null || mediaType.startsWith("application/") && mediaType.endsWith("json") -> + if (content == null) { + EMPTY_REQUEST + } else { + Serializer.moshi.adapter(T::class.java).toJson(content) + .toRequestBody((mediaType ?: JsonMediaType).toMediaTypeOrNull()) + } + mediaType == XmlMediaType -> throw UnsupportedOperationException("xml not currently supported.") + // TODO: this should be extended with other serializers + else -> throw UnsupportedOperationException("requestBody currently only supports JSON body and File body.") + } + + @OptIn(ExperimentalStdlibApi::class) + protected inline fun responseBody(body: ResponseBody?, mediaType: String? = JsonMediaType): T? { + if(body == null) { + return null + } + if (T::class.java == File::class.java) { + // return tempFile + // Attention: if you are developing an android app that supports API Level 25 and bellow, please check flag supportAndroidApiLevel25AndBelow in https://openapi-generator.tech/docs/generators/kotlin#config-options + val tempFile = java.nio.file.Files.createTempFile("tmp.org.openapitools.client", null).toFile() + tempFile.deleteOnExit() + body.byteStream().use { inputStream -> + tempFile.outputStream().use { tempFileOutputStream -> + inputStream.copyTo(tempFileOutputStream) + } + } + return tempFile as T + } + val bodyContent = body.string() + if (bodyContent.isEmpty()) { + return null + } + return when { + mediaType==null || (mediaType.startsWith("application/") && mediaType.endsWith("json")) -> + Serializer.moshi.adapter().fromJson(bodyContent) + else -> throw UnsupportedOperationException("responseBody currently only supports JSON body.") + } + } + + + protected inline fun request(requestConfig: RequestConfig): ApiResponse { + val httpUrl = baseUrl.toHttpUrlOrNull() ?: throw IllegalStateException("baseUrl is invalid.") + + val url = httpUrl.newBuilder() + .addEncodedPathSegments(requestConfig.path.trimStart('/')) + .apply { + requestConfig.query.forEach { query -> + query.value.forEach { queryValue -> + addQueryParameter(query.key, queryValue) + } + } + }.build() + + // take content-type/accept from spec or set to default (application/json) if not defined + if (requestConfig.body != null && requestConfig.headers[ContentType].isNullOrEmpty()) { + requestConfig.headers[ContentType] = JsonMediaType + } + if (requestConfig.headers[Accept].isNullOrEmpty()) { + requestConfig.headers[Accept] = JsonMediaType + } + val headers = requestConfig.headers + + if (headers[Accept].isNullOrEmpty()) { + throw kotlin.IllegalStateException("Missing Accept header. This is required.") + } + + val contentType = if (headers[ContentType] != null) { + // TODO: support multiple contentType options here. + (headers[ContentType] as String).substringBefore(";").lowercase(Locale.US) + } else { + null + } + + val request = when (requestConfig.method) { + RequestMethod.DELETE -> Request.Builder().url(url).delete(requestBody(requestConfig.body, contentType)) + RequestMethod.GET -> Request.Builder().url(url) + RequestMethod.HEAD -> Request.Builder().url(url).head() + RequestMethod.PATCH -> Request.Builder().url(url).patch(requestBody(requestConfig.body, contentType)) + RequestMethod.PUT -> Request.Builder().url(url).put(requestBody(requestConfig.body, contentType)) + RequestMethod.POST -> Request.Builder().url(url).post(requestBody(requestConfig.body, contentType)) + RequestMethod.OPTIONS -> Request.Builder().url(url).method("OPTIONS", null) + }.apply { + headers.forEach { header -> addHeader(header.key, header.value) } + }.build() + + val response = client.newCall(request).execute() + + val accept = response.header(ContentType)?.substringBefore(";")?.lowercase(Locale.US) + + // TODO: handle specific mapping types. e.g. Map> + return when { + response.isRedirect -> Redirection( + response.code, + response.headers.toMultimap() + ) + response.isInformational -> Informational( + response.message, + response.code, + response.headers.toMultimap() + ) + response.isSuccessful -> Success( + responseBody(response.body, accept), + response.code, + response.headers.toMultimap() + ) + response.isClientError -> ClientError( + response.message, + response.body?.string(), + response.code, + response.headers.toMultimap() + ) + else -> ServerError( + response.message, + response.body?.string(), + response.code, + response.headers.toMultimap() + ) + } + } + + protected fun parameterToString(value: Any?): String = when (value) { + null -> "" + is Array<*> -> toMultiValue(value, "csv").toString() + is Iterable<*> -> toMultiValue(value, "csv").toString() + is OffsetDateTime, is OffsetTime, is LocalDateTime, is LocalDate, is LocalTime -> + parseDateToQueryString(value) + else -> value.toString() + } + + protected inline fun parseDateToQueryString(value : T): String { + /* + .replace("\"", "") converts the json object string to an actual string for the query parameter. + The moshi or gson adapter allows a more generic solution instead of trying to use a native + formatter. It also easily allows to provide a simple way to define a custom date format pattern + inside a gson/moshi adapter. + */ + return Serializer.moshi.adapter(T::class.java).toJson(value).replace("\"", "") + } +} diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/ApiResponse.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/ApiResponse.kt new file mode 100644 index 00000000000..cf2cfaa95d9 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/ApiResponse.kt @@ -0,0 +1,43 @@ +package org.openapitools.client.infrastructure + +enum class ResponseType { + Success, Informational, Redirection, ClientError, ServerError +} + +interface Response + +abstract class ApiResponse(val responseType: ResponseType): Response { + abstract val statusCode: Int + abstract val headers: Map> +} + +class Success( + val data: T, + override val statusCode: Int = -1, + override val headers: Map> = mapOf() +): ApiResponse(ResponseType.Success) + +class Informational( + val statusText: String, + override val statusCode: Int = -1, + override val headers: Map> = mapOf() +) : ApiResponse(ResponseType.Informational) + +class Redirection( + override val statusCode: Int = -1, + override val headers: Map> = mapOf() +) : ApiResponse(ResponseType.Redirection) + +class ClientError( + val message: String? = null, + val body: Any? = null, + override val statusCode: Int = -1, + override val headers: Map> = mapOf() +) : ApiResponse(ResponseType.ClientError) + +class ServerError( + val message: String? = null, + val body: Any? = null, + override val statusCode: Int = -1, + override val headers: Map> +): ApiResponse(ResponseType.ServerError) diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt new file mode 100644 index 00000000000..064b57fc6b8 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/BigDecimalAdapter.kt @@ -0,0 +1,17 @@ +package org.openapitools.client.infrastructure + +import com.squareup.moshi.FromJson +import com.squareup.moshi.ToJson +import java.math.BigDecimal + +class BigDecimalAdapter { + @ToJson + fun toJson(value: BigDecimal): String { + return value.toPlainString() + } + + @FromJson + fun fromJson(value: String): BigDecimal { + return BigDecimal(value) + } +} diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt new file mode 100644 index 00000000000..7df6057b450 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/BigIntegerAdapter.kt @@ -0,0 +1,17 @@ +package org.openapitools.client.infrastructure + +import com.squareup.moshi.FromJson +import com.squareup.moshi.ToJson +import java.math.BigInteger + +class BigIntegerAdapter { + @ToJson + fun toJson(value: BigInteger): String { + return value.toString() + } + + @FromJson + fun fromJson(value: String): BigInteger { + return BigInteger(value) + } +} diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt new file mode 100644 index 00000000000..ff5e2a81ee8 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/ByteArrayAdapter.kt @@ -0,0 +1,12 @@ +package org.openapitools.client.infrastructure + +import com.squareup.moshi.FromJson +import com.squareup.moshi.ToJson + +class ByteArrayAdapter { + @ToJson + fun toJson(data: ByteArray): String = String(data) + + @FromJson + fun fromJson(data: String): ByteArray = data.toByteArray() +} diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/Errors.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/Errors.kt new file mode 100644 index 00000000000..b5310e71f13 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/Errors.kt @@ -0,0 +1,18 @@ +@file:Suppress("unused") +package org.openapitools.client.infrastructure + +import java.lang.RuntimeException + +open class ClientException(message: kotlin.String? = null, val statusCode: Int = -1, val response: Response? = null) : RuntimeException(message) { + + companion object { + private const val serialVersionUID: Long = 123L + } +} + +open class ServerException(message: kotlin.String? = null, val statusCode: Int = -1, val response: Response? = null) : RuntimeException(message) { + + companion object { + private const val serialVersionUID: Long = 456L + } +} \ No newline at end of file diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt new file mode 100644 index 00000000000..b2e1654479a --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateAdapter.kt @@ -0,0 +1,19 @@ +package org.openapitools.client.infrastructure + +import com.squareup.moshi.FromJson +import com.squareup.moshi.ToJson +import java.time.LocalDate +import java.time.format.DateTimeFormatter + +class LocalDateAdapter { + @ToJson + fun toJson(value: LocalDate): String { + return DateTimeFormatter.ISO_LOCAL_DATE.format(value) + } + + @FromJson + fun fromJson(value: String): LocalDate { + return LocalDate.parse(value, DateTimeFormatter.ISO_LOCAL_DATE) + } + +} diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt new file mode 100644 index 00000000000..e082db94811 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/LocalDateTimeAdapter.kt @@ -0,0 +1,19 @@ +package org.openapitools.client.infrastructure + +import com.squareup.moshi.FromJson +import com.squareup.moshi.ToJson +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter + +class LocalDateTimeAdapter { + @ToJson + fun toJson(value: LocalDateTime): String { + return DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(value) + } + + @FromJson + fun fromJson(value: String): LocalDateTime { + return LocalDateTime.parse(value, DateTimeFormatter.ISO_LOCAL_DATE_TIME) + } + +} diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt new file mode 100644 index 00000000000..87437871a31 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/OffsetDateTimeAdapter.kt @@ -0,0 +1,19 @@ +package org.openapitools.client.infrastructure + +import com.squareup.moshi.FromJson +import com.squareup.moshi.ToJson +import java.time.OffsetDateTime +import java.time.format.DateTimeFormatter + +class OffsetDateTimeAdapter { + @ToJson + fun toJson(value: OffsetDateTime): String { + return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(value) + } + + @FromJson + fun fromJson(value: String): OffsetDateTime { + return OffsetDateTime.parse(value, DateTimeFormatter.ISO_OFFSET_DATE_TIME) + } + +} diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/PartConfig.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/PartConfig.kt new file mode 100644 index 00000000000..be00e38fbae --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/PartConfig.kt @@ -0,0 +1,11 @@ +package org.openapitools.client.infrastructure + +/** + * Defines a config object for a given part of a multi-part request. + * NOTE: Headers is a Map because rfc2616 defines + * multi-valued headers as csv-only. + */ +data class PartConfig( + val headers: MutableMap = mutableMapOf(), + val body: T? = null +) diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/RequestConfig.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/RequestConfig.kt new file mode 100644 index 00000000000..625a19002b5 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/RequestConfig.kt @@ -0,0 +1,18 @@ +package org.openapitools.client.infrastructure + +/** + * Defines a config object for a given request. + * NOTE: This object doesn't include 'body' because it + * allows for caching of the constructed object + * for many request definitions. + * NOTE: Headers is a Map because rfc2616 defines + * multi-valued headers as csv-only. + */ +data class RequestConfig( + val method: RequestMethod, + val path: String, + val headers: MutableMap = mutableMapOf(), + val query: MutableMap> = mutableMapOf(), + val requiresAuthentication: Boolean, + val body: T? = null +) \ No newline at end of file diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/RequestMethod.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/RequestMethod.kt new file mode 100644 index 00000000000..931b12b8bd7 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/RequestMethod.kt @@ -0,0 +1,8 @@ +package org.openapitools.client.infrastructure + +/** + * Provides enumerated HTTP verbs + */ +enum class RequestMethod { + GET, DELETE, HEAD, OPTIONS, PATCH, POST, PUT +} \ No newline at end of file diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/ResponseExtensions.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/ResponseExtensions.kt new file mode 100644 index 00000000000..9bd2790dc14 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/ResponseExtensions.kt @@ -0,0 +1,24 @@ +package org.openapitools.client.infrastructure + +import okhttp3.Response + +/** + * Provides an extension to evaluation whether the response is a 1xx code + */ +val Response.isInformational : Boolean get() = this.code in 100..199 + +/** + * Provides an extension to evaluation whether the response is a 3xx code + */ +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +val Response.isRedirect : Boolean get() = this.code in 300..399 + +/** + * Provides an extension to evaluation whether the response is a 4xx code + */ +val Response.isClientError : Boolean get() = this.code in 400..499 + +/** + * Provides an extension to evaluation whether the response is a 5xx (Standard) through 999 (non-standard) code + */ +val Response.isServerError : Boolean get() = this.code in 500..999 diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt new file mode 100644 index 00000000000..e22592e47d7 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt @@ -0,0 +1,23 @@ +package org.openapitools.client.infrastructure + +import com.squareup.moshi.Moshi +import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory + +object Serializer { + @JvmStatic + val moshiBuilder: Moshi.Builder = Moshi.Builder() + .add(OffsetDateTimeAdapter()) + .add(LocalDateTimeAdapter()) + .add(LocalDateAdapter()) + .add(UUIDAdapter()) + .add(ByteArrayAdapter()) + .add(URIAdapter()) + .add(KotlinJsonAdapterFactory()) + .add(BigDecimalAdapter()) + .add(BigIntegerAdapter()) + + @JvmStatic + val moshi: Moshi by lazy { + moshiBuilder.build() + } +} diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt new file mode 100644 index 00000000000..927522757da --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt @@ -0,0 +1,13 @@ +package org.openapitools.client.infrastructure + +import com.squareup.moshi.FromJson +import com.squareup.moshi.ToJson +import java.net.URI + +class URIAdapter { + @ToJson + fun toJson(uri: URI) = uri.toString() + + @FromJson + fun fromJson(s: String): URI = URI.create(s) +} diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt new file mode 100644 index 00000000000..7ccf7dc25d2 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt @@ -0,0 +1,13 @@ +package org.openapitools.client.infrastructure + +import com.squareup.moshi.FromJson +import com.squareup.moshi.ToJson +import java.util.UUID + +class UUIDAdapter { + @ToJson + fun toJson(uuid: UUID) = uuid.toString() + + @FromJson + fun fromJson(s: String): UUID = UUID.fromString(s) +} diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/BroadcastRequestV1.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/BroadcastRequestV1.kt new file mode 100644 index 00000000000..255240614de --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/BroadcastRequestV1.kt @@ -0,0 +1,40 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + +import org.openapitools.client.models.BroadcastRequestV1Message + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * + * + * @param message + * @param signature + */ + + +data class BroadcastRequestV1 ( + + @Json(name = "message") + val message: BroadcastRequestV1Message, + + @Json(name = "signature") + val signature: kotlin.String + +) + diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/BroadcastRequestV1Message.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/BroadcastRequestV1Message.kt new file mode 100644 index 00000000000..2eab7e0e9da --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/BroadcastRequestV1Message.kt @@ -0,0 +1,40 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + +import org.openapitools.client.models.NewNodeRequestV1 + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * + * + * @param message + * @param pubKey + */ + + +data class BroadcastRequestV1Message ( + + @Json(name = "message") + val message: NewNodeRequestV1, + + @Json(name = "pubKey") + val pubKey: kotlin.String + +) + diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/BroadcastResponseV1.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/BroadcastResponseV1.kt new file mode 100644 index 00000000000..7a32207857a --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/BroadcastResponseV1.kt @@ -0,0 +1,35 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * + * + * @param result + */ + + +data class BroadcastResponseV1 ( + + @Json(name = "result") + val result: kotlin.Boolean + +) + diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactusNode.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactusNode.kt new file mode 100644 index 00000000000..020128ccb68 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactusNode.kt @@ -0,0 +1,61 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * A Cactus node can be a single server, or a set of servers behind a load balancer acting as one. + * + * @param nodeApiHost + * @param publicKeyPem The PEM encoded public key that was used to generate the JWS included in the response (the jws property) + * @param id + * @param consortiumId + * @param memberId + * @param ledgerIds Stores an array of Ledger entity IDs that are reachable (routable) via this Cactus Node. This information is used by the client side SDK API client to figure out at runtime where to send API requests that are specific to a certain ledger such as requests to execute transactions. + * @param pluginInstanceIds + */ + + +data class CactusNode ( + + @Json(name = "nodeApiHost") + val nodeApiHost: kotlin.String, + + /* The PEM encoded public key that was used to generate the JWS included in the response (the jws property) */ + @Json(name = "publicKeyPem") + val publicKeyPem: kotlin.String, + + @Json(name = "id") + val id: kotlin.String, + + @Json(name = "consortiumId") + val consortiumId: kotlin.String, + + @Json(name = "memberId") + val memberId: kotlin.String, + + /* Stores an array of Ledger entity IDs that are reachable (routable) via this Cactus Node. This information is used by the client side SDK API client to figure out at runtime where to send API requests that are specific to a certain ledger such as requests to execute transactions. */ + @Json(name = "ledgerIds") + val ledgerIds: kotlin.collections.List = arrayListOf(), + + @Json(name = "pluginInstanceIds") + val pluginInstanceIds: kotlin.collections.List = arrayListOf() + +) + diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactusNodeAllOf.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactusNodeAllOf.kt new file mode 100644 index 00000000000..895eb1c8a63 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactusNodeAllOf.kt @@ -0,0 +1,52 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * + * + * @param id + * @param consortiumId + * @param memberId + * @param ledgerIds Stores an array of Ledger entity IDs that are reachable (routable) via this Cactus Node. This information is used by the client side SDK API client to figure out at runtime where to send API requests that are specific to a certain ledger such as requests to execute transactions. + * @param pluginInstanceIds + */ + + +data class CactusNodeAllOf ( + + @Json(name = "id") + val id: kotlin.String, + + @Json(name = "consortiumId") + val consortiumId: kotlin.String, + + @Json(name = "memberId") + val memberId: kotlin.String, + + /* Stores an array of Ledger entity IDs that are reachable (routable) via this Cactus Node. This information is used by the client side SDK API client to figure out at runtime where to send API requests that are specific to a certain ledger such as requests to execute transactions. */ + @Json(name = "ledgerIds") + val ledgerIds: kotlin.collections.List = arrayListOf(), + + @Json(name = "pluginInstanceIds") + val pluginInstanceIds: kotlin.collections.List = arrayListOf() + +) + diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactusNodeMeta.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactusNodeMeta.kt new file mode 100644 index 00000000000..ec9d921ad1a --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactusNodeMeta.kt @@ -0,0 +1,40 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * A Cactus node meta information + * + * @param nodeApiHost + * @param publicKeyPem The PEM encoded public key that was used to generate the JWS included in the response (the jws property) + */ + + +data class CactusNodeMeta ( + + @Json(name = "nodeApiHost") + val nodeApiHost: kotlin.String, + + /* The PEM encoded public key that was used to generate the JWS included in the response (the jws property) */ + @Json(name = "publicKeyPem") + val publicKeyPem: kotlin.String + +) + diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetConsortiumJwsResponse.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetConsortiumJwsResponse.kt new file mode 100644 index 00000000000..eb880bcea16 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetConsortiumJwsResponse.kt @@ -0,0 +1,36 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + +import org.openapitools.client.models.JWSGeneral + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * + * + * @param jws + */ + + +data class GetConsortiumJwsResponse ( + + @Json(name = "jws") + val jws: JWSGeneral + +) + diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetNodeJwsResponse.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetNodeJwsResponse.kt new file mode 100644 index 00000000000..c1d327a7d79 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetNodeJwsResponse.kt @@ -0,0 +1,36 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + +import org.openapitools.client.models.JWSGeneral + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * + * + * @param jws + */ + + +data class GetNodeJwsResponse ( + + @Json(name = "jws") + val jws: JWSGeneral + +) + diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/Identity.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/Identity.kt new file mode 100644 index 00000000000..561a85c83f5 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/Identity.kt @@ -0,0 +1,46 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * Identity object of a Cacti Node + * + * @param pubKey Public key of the Node + * @param memberId memberId of the organization the node belongs to + * @param proof JWT generated by the organization the node belongs to + */ + + +data class Identity ( + + /* Public key of the Node */ + @Json(name = "pubKey") + val pubKey: kotlin.String, + + /* memberId of the organization the node belongs to */ + @Json(name = "memberId") + val memberId: kotlin.String, + + /* JWT generated by the organization the node belongs to */ + @Json(name = "proof") + val proof: kotlin.String + +) + diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/JWSGeneral.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/JWSGeneral.kt new file mode 100644 index 00000000000..f32650672e8 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/JWSGeneral.kt @@ -0,0 +1,40 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + +import org.openapitools.client.models.JWSRecipient + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * + * + * @param payload + * @param signatures + */ + + +data class JWSGeneral ( + + @Json(name = "payload") + val payload: kotlin.String, + + @Json(name = "signatures") + val signatures: kotlin.collections.List + +) + diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/JWSRecipient.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/JWSRecipient.kt new file mode 100644 index 00000000000..7bf5dd698ed --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/JWSRecipient.kt @@ -0,0 +1,43 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * A JSON Web Signature. See: https://tools.ietf.org/html/rfc7515 for info about standard. + * + * @param signature + * @param `protected` + * @param header + */ + + +data class JWSRecipient ( + + @Json(name = "signature") + val signature: kotlin.String, + + @Json(name = "protected") + val `protected`: kotlin.String? = null, + + @Json(name = "header") + val header: kotlin.collections.Map? = null + +) + diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/Ledger.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/Ledger.kt new file mode 100644 index 00000000000..55c44b1d914 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/Ledger.kt @@ -0,0 +1,44 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + +import org.openapitools.client.models.LedgerType + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * + * + * @param id + * @param ledgerType + * @param consortiumMemberId + */ + + +data class Ledger ( + + @Json(name = "id") + val id: kotlin.String, + + @Json(name = "ledgerType") + val ledgerType: LedgerType, + + @Json(name = "consortiumMemberId") + val consortiumMemberId: kotlin.String? = null + +) + diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/LedgerType.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/LedgerType.kt new file mode 100644 index 00000000000..60fe48e4ae1 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/LedgerType.kt @@ -0,0 +1,75 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * Enumerates the different ledger vendors and their major versions encoded within the name of the LedgerType. For example \"BESU_1X\" involves all of the [1.0.0;2.0.0) where 1.0.0 is included and anything up until, but not 2.0.0. See: https://stackoverflow.com/a/4396303/698470 for further explanation. + * + * Values: bESU1X,bESU2X,bURROW0X,cORDA4X,fABRIC2,sAWTOOTH1X + */ + +@JsonClass(generateAdapter = false) +enum class LedgerType(val value: kotlin.String) { + + @Json(name = "BESU_1X") + bESU1X("BESU_1X"), + + @Json(name = "BESU_2X") + bESU2X("BESU_2X"), + + @Json(name = "BURROW_0X") + bURROW0X("BURROW_0X"), + + @Json(name = "CORDA_4X") + cORDA4X("CORDA_4X"), + + @Json(name = "FABRIC_2") + fABRIC2("FABRIC_2"), + + @Json(name = "SAWTOOTH_1X") + sAWTOOTH1X("SAWTOOTH_1X"); + + /** + * Override [toString()] to avoid using the enum variable name as the value, and instead use + * the actual value defined in the API spec file. + * + * This solves a problem when the variable name and its value are different, and ensures that + * the client sends the correct enum values to the server always. + */ + override fun toString(): String = value + + companion object { + /** + * Converts the provided [data] to a [String] on success, null otherwise. + */ + fun encode(data: kotlin.Any?): kotlin.String? = if (data is LedgerType) "$data" else null + + /** + * Returns a valid [LedgerType] for [data], null otherwise. + */ + fun decode(data: kotlin.Any?): LedgerType? = data?.let { + val normalizedData = "$it".lowercase() + values().firstOrNull { value -> + it == value || normalizedData == "$value".lowercase() + } + } + } +} + diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/NewNodeRequestV1.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/NewNodeRequestV1.kt new file mode 100644 index 00000000000..747458dc899 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/NewNodeRequestV1.kt @@ -0,0 +1,63 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + +import org.openapitools.client.models.CactusNode +import org.openapitools.client.models.Identity +import org.openapitools.client.models.Ledger +import org.openapitools.client.models.PluginInstance + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * + * + * @param identity + * @param treeHash proof of common configs and policies defined by the consortium + * @param node + * @param ledger Ledger metadata + * @param pluginInstance Plugin Instance metadata + * @param signature signature of the message + */ + + +data class NewNodeRequestV1 ( + + @Json(name = "identity") + val identity: Identity, + + /* proof of common configs and policies defined by the consortium */ + @Json(name = "treeHash") + val treeHash: kotlin.String, + + @Json(name = "node") + val node: CactusNode, + + /* Ledger metadata */ + @Json(name = "ledger") + val ledger: kotlin.collections.List = arrayListOf(), + + /* Plugin Instance metadata */ + @Json(name = "pluginInstance") + val pluginInstance: kotlin.collections.List = arrayListOf(), + + /* signature of the message */ + @Json(name = "signature") + val signature: kotlin.String + +) + diff --git a/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/PluginInstance.kt b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/PluginInstance.kt new file mode 100644 index 00000000000..5b40ac29bc5 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/PluginInstance.kt @@ -0,0 +1,39 @@ +/** + * + * Please note: + * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * Do not edit this file manually. + * + */ + +@file:Suppress( + "ArrayInDataClass", + "EnumEntryName", + "RemoveRedundantQualifierName", + "UnusedImport" +) + +package org.openapitools.client.models + + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * + * + * @param id + * @param packageName + */ + + +data class PluginInstance ( + + @Json(name = "id") + val id: kotlin.String, + + @Json(name = "packageName") + val packageName: kotlin.String + +) + diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/consortium/add-new-node-endpoint-v1.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/consortium/add-new-node-endpoint-v1.ts new file mode 100644 index 00000000000..1bcbcba600b --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/consortium/add-new-node-endpoint-v1.ts @@ -0,0 +1,121 @@ +import { Express, Request, Response } from "express"; + +import { + IWebServiceEndpoint, + IExpressRequestHandler, + IEndpointAuthzOptions, +} from "@hyperledger/cactus-core-api"; + +import { GetConsortiumJwsResponse } from "../generated/openapi/typescript-axios"; + +import { + Logger, + LogLevelDesc, + LoggerProvider, + Checks, + IAsyncProvider, +} from "@hyperledger/cactus-common"; + +import { + handleRestEndpointException, + registerWebServiceEndpoint, +} from "@hyperledger/cactus-core"; + +import OAS from "../../json/openapi.json"; +import { PluginConsortiumStatic } from "../plugin-consortium-static"; +import { StaticConsortiumRepository } from "../repository/static-consortium-repository"; + +export interface IAddNewNodeEndpointOptions { + plugin: PluginConsortiumStatic; + keyPairPem: string; + consortiumRepo: StaticConsortiumRepository; + logLevel?: LogLevelDesc; +} + +export class AddNewNodeEndpoint implements IWebServiceEndpoint { + public static readonly CLASS_NAME = "AddNewNodeEndpoint"; + + private readonly log: Logger; + private readonly plugin: PluginConsortiumStatic; + + constructor(public readonly options: IAddNewNodeEndpointOptions) { + const fnTag = `${this.className}#constructor()`; + if (!options) { + throw new Error(`${fnTag} options falsy.`); + } + if (!options.keyPairPem) { + throw new Error(`${fnTag} options.keyPairPem falsy.`); + } + Checks.truthy(options.consortiumRepo, `${fnTag} options.consortiumRepo`); + Checks.truthy(options.plugin, `${fnTag} options.plugin`); + Checks.truthy( + options.plugin instanceof PluginConsortiumStatic, + `${fnTag} options.plugin instanceof PluginConsortiumStatic`, + ); + this.plugin = options.plugin; + + const level = options.logLevel || "INFO"; + const label = "add-node-endpoint-v1"; + this.log = LoggerProvider.getOrCreate({ level, label }); + } + + public get className(): string { + return AddNewNodeEndpoint.CLASS_NAME; + } + + getAuthorizationOptionsProvider(): IAsyncProvider { + // TODO: make this an injectable dependency in the constructor + return { + get: async () => ({ + isProtected: true, + requiredRoles: [], + }), + }; + } + + public getExpressRequestHandler(): IExpressRequestHandler { + return this.handleRequest.bind(this); + } + + public get oasPath(): (typeof OAS.paths)["/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/add-node"] { + return OAS.paths[ + "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/add-node" + ]; + } + + public getOperationId(): string { + return this.oasPath.post.operationId; + } + + public getPath(): string { + return this.oasPath.post["x-hyperledger-cacti"].http.path; + } + + public getVerbLowerCase(): string { + return this.oasPath.post["x-hyperledger-cacti"].http.verbLowerCase; + } + + public async registerExpress( + expressApp: Express, + ): Promise { + await registerWebServiceEndpoint(expressApp, this); + return this; + } + + async handleRequest(req: Request, res: Response): Promise { + const fnTag = `${this.className}#handleRequest()`; + const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; + this.log.debug(reqTag); + try { + await this.options.plugin.processNewNodeRequest(req.body); + this.options.plugin.broadcastJoinRequest(req.body); + const jws = await this.options.plugin.getConsortiumJws(); + const body: GetConsortiumJwsResponse = { jws }; + res.status(200); + res.json(body); + } catch (ex: unknown) { + const errorMsg = `${fnTag} request handler fn crashed for: ${reqTag}`; + handleRestEndpointException({ errorMsg, log: this.log, error: ex, res }); + } + } +} diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/consortium/get-consortium-jws-endpoint-v1.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/consortium/get-consortium-jws-endpoint-v1.ts new file mode 100644 index 00000000000..6f1eb04b772 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/consortium/get-consortium-jws-endpoint-v1.ts @@ -0,0 +1,122 @@ +import { Express, Request, Response } from "express"; + +import { + IWebServiceEndpoint, + IExpressRequestHandler, + IEndpointAuthzOptions, +} from "@hyperledger/cactus-core-api"; + +import { GetConsortiumJwsResponse } from "../generated/openapi/typescript-axios"; + +import { + LogLevelDesc, + Logger, + LoggerProvider, + IAsyncProvider, + Checks, +} from "@hyperledger/cactus-common"; + +import { + handleRestEndpointException, + registerWebServiceEndpoint, +} from "@hyperledger/cactus-core"; + +import OAS from "../../json/openapi.json"; +import { PluginConsortiumStatic } from "../plugin-consortium-static"; +import { StaticConsortiumRepository } from "../repository/static-consortium-repository"; + +export interface IGetConsortiumJwsEndpointOptions { + plugin: PluginConsortiumStatic; + keyPairPem: string; + consortiumRepo: StaticConsortiumRepository; + logLevel?: LogLevelDesc; +} + +export class GetConsortiumEndpointV1 implements IWebServiceEndpoint { + public static readonly CLASS_NAME = "GetConsortiumEndpointV1"; + + private readonly log: Logger; + private readonly plugin: PluginConsortiumStatic; + + constructor(public readonly options: IGetConsortiumJwsEndpointOptions) { + const fnTag = `${this.className}#constructor()`; + if (!options) { + throw new Error(`${fnTag} options falsy.`); + } + if (!options.keyPairPem) { + throw new Error(`${fnTag} options.keyPairPem falsy.`); + } + if (!options.consortiumRepo) { + throw new Error(`${fnTag} options.consortium falsy.`); + } + Checks.truthy(options.plugin, `${fnTag} options.plugin`); + Checks.truthy( + options.plugin instanceof PluginConsortiumStatic, + `${fnTag} options.plugin instanceof PluginConsortiumStatic`, + ); + this.plugin = options.plugin; + + const label = "get-consortium-jws-endpoint"; + const level = options.logLevel || "INFO"; + this.log = LoggerProvider.getOrCreate({ label, level }); + } + + public get className(): string { + return GetConsortiumEndpointV1.CLASS_NAME; + } + + getAuthorizationOptionsProvider(): IAsyncProvider { + // TODO: make this an injectable dependency in the constructor + return { + get: async () => ({ + isProtected: true, + requiredRoles: [], + }), + }; + } + + public getExpressRequestHandler(): IExpressRequestHandler { + return this.handleRequest.bind(this); + } + + public get oasPath(): (typeof OAS.paths)["/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/consortium/jws"] { + return OAS.paths[ + "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/consortium/jws" + ]; + } + + public getOperationId(): string { + return this.oasPath.post.operationId; + } + + public getPath(): string { + return this.oasPath.post["x-hyperledger-cacti"].http.path; + } + + public getVerbLowerCase(): string { + return this.oasPath.post["x-hyperledger-cacti"].http.verbLowerCase; + } + + public async registerExpress( + expressApp: Express, + ): Promise { + await registerWebServiceEndpoint(expressApp, this); + return this; + } + + async handleRequest(req: Request, res: Response): Promise { + const fnTag = `${this.className}#handleRequest()`; + const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; + this.log.debug(reqTag); + try { + const jws = await this.options.plugin.getConsortiumJws(); + + const body: GetConsortiumJwsResponse = { jws }; + res.status(200); + res.json(body); + } catch (ex: unknown) { + const errorMsg = `${fnTag} request handler fn crashed for: ${reqTag}`; + handleRestEndpointException({ errorMsg, log: this.log, error: ex, res }); + } + } +} diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/consortium/get-node-jws-endpoint-v1.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/consortium/get-node-jws-endpoint-v1.ts new file mode 100644 index 00000000000..f91fe8060fc --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/consortium/get-node-jws-endpoint-v1.ts @@ -0,0 +1,118 @@ +import { Express, Request, Response } from "express"; + +import { + IWebServiceEndpoint, + IExpressRequestHandler, + IEndpointAuthzOptions, +} from "@hyperledger/cactus-core-api"; + +import { GetNodeJwsResponse } from "../generated/openapi/typescript-axios"; + +import { + Logger, + LogLevelDesc, + LoggerProvider, + Checks, + IAsyncProvider, +} from "@hyperledger/cactus-common"; + +import { + handleRestEndpointException, + registerWebServiceEndpoint, +} from "@hyperledger/cactus-core"; + +import OAS from "../../json/openapi.json"; +import { PluginConsortiumStatic } from "../plugin-consortium-static"; +import { StaticConsortiumRepository } from "../repository/static-consortium-repository"; + +export interface IGetNodeJwsEndpointOptions { + plugin: PluginConsortiumStatic; + keyPairPem: string; + consortiumRepo: StaticConsortiumRepository; + logLevel?: LogLevelDesc; +} + +export class GetNodeJwsEndpoint implements IWebServiceEndpoint { + public static readonly CLASS_NAME = "GetNodeJwsEndpoint"; + + private readonly log: Logger; + private readonly plugin: PluginConsortiumStatic; + + constructor(public readonly options: IGetNodeJwsEndpointOptions) { + const fnTag = `${this.className}#constructor()`; + if (!options) { + throw new Error(`${fnTag} options falsy.`); + } + if (!options.keyPairPem) { + throw new Error(`${fnTag} options.keyPairPem falsy.`); + } + Checks.truthy(options.consortiumRepo, `${fnTag} options.consortiumRepo`); + Checks.truthy(options.plugin, `${fnTag} options.plugin`); + Checks.truthy( + options.plugin instanceof PluginConsortiumStatic, + `${fnTag} options.plugin instanceof PluginConsortiumStatic`, + ); + this.plugin = options.plugin; + + const level = options.logLevel || "INFO"; + const label = "get-node-jws-endpoint-v1"; + this.log = LoggerProvider.getOrCreate({ level, label }); + } + + public get className(): string { + return GetNodeJwsEndpoint.CLASS_NAME; + } + getAuthorizationOptionsProvider(): IAsyncProvider { + // TODO: make this an injectable dependency in the constructor + return { + get: async () => ({ + isProtected: true, + requiredRoles: [], + }), + }; + } + + public getExpressRequestHandler(): IExpressRequestHandler { + return this.handleRequest.bind(this); + } + + public get oasPath(): (typeof OAS.paths)["/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/node/jws"] { + return OAS.paths[ + "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/node/jws" + ]; + } + + public getOperationId(): string { + return this.oasPath.post.operationId; + } + + public getPath(): string { + return this.oasPath.post["x-hyperledger-cacti"].http.path; + } + + public getVerbLowerCase(): string { + return this.oasPath.post["x-hyperledger-cacti"].http.verbLowerCase; + } + + public async registerExpress( + expressApp: Express, + ): Promise { + await registerWebServiceEndpoint(expressApp, this); + return this; + } + + async handleRequest(req: Request, res: Response): Promise { + const fnTag = `${this.className}#handleRequest()`; + const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; + this.log.debug(reqTag); + try { + const jws = await this.options.plugin.getNodeJws(); + const body: GetNodeJwsResponse = { jws }; + res.status(200); + res.json(body); + } catch (ex: unknown) { + const errorMsg = `${fnTag} request handler fn crashed for: ${reqTag}`; + handleRestEndpointException({ errorMsg, log: this.log, error: ex, res }); + } + } +} diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/consortium/get-prometheus-exporter-metrics-endpoint-v1.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/consortium/get-prometheus-exporter-metrics-endpoint-v1.ts new file mode 100644 index 00000000000..eb64650e63a --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/consortium/get-prometheus-exporter-metrics-endpoint-v1.ts @@ -0,0 +1,109 @@ +import { Express, Request, Response } from "express"; + +import { + Logger, + LoggerProvider, + LogLevelDesc, + Checks, + IAsyncProvider, +} from "@hyperledger/cactus-common"; + +import { + IWebServiceEndpoint, + IExpressRequestHandler, + IEndpointAuthzOptions, +} from "@hyperledger/cactus-core-api"; + +import OAS from "../../json/openapi.json"; + +import { + handleRestEndpointException, + registerWebServiceEndpoint, +} from "@hyperledger/cactus-core"; + +import { PluginConsortiumStatic } from "../plugin-consortium-static"; + +export interface IGetPrometheusExporterMetricsEndpointV1Options { + logLevel?: LogLevelDesc; + plugin: PluginConsortiumStatic; +} + +export class GetPrometheusExporterMetricsEndpointV1 + implements IWebServiceEndpoint +{ + public static readonly CLASS_NAME = "GetPrometheusExporterMetricsEndpointV1"; + private readonly log: Logger; + + constructor( + public readonly opts: IGetPrometheusExporterMetricsEndpointV1Options, + ) { + const fnTag = `${this.className}#constructor()`; + + Checks.truthy(opts, `${fnTag} options`); + Checks.truthy(opts.plugin, `${fnTag} options.plugin`); + + this.log = LoggerProvider.getOrCreate({ + label: "get-prometheus-exporter-metrics-v1", + level: opts.logLevel || "INFO", + }); + } + + public get className(): string { + return GetPrometheusExporterMetricsEndpointV1.CLASS_NAME; + } + + getAuthorizationOptionsProvider(): IAsyncProvider { + // TODO: make this an injectable dependency in the constructor + return { + get: async () => ({ + isProtected: true, + requiredRoles: [], + }), + }; + } + + public getExpressRequestHandler(): IExpressRequestHandler { + return this.handleRequest.bind(this); + } + + public get oasPath(): (typeof OAS.paths)["/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/get-prometheus-exporter-metrics"] { + return OAS.paths[ + "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/get-prometheus-exporter-metrics" + ]; + } + + public getPath(): string { + return this.oasPath.get["x-hyperledger-cacti"].http.path; + } + + public getVerbLowerCase(): string { + return this.oasPath.get["x-hyperledger-cacti"].http.verbLowerCase; + } + + public getOperationId(): string { + return this.oasPath.get.operationId; + } + + public async registerExpress( + expressApp: Express, + ): Promise { + await registerWebServiceEndpoint(expressApp, this); + return this; + } + + async handleRequest(req: Request, res: Response): Promise { + const fnTag = `${this.className}#handleRequest()`; + const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; + const verbUpper = this.getVerbLowerCase().toUpperCase(); + this.log.debug(`${verbUpper} ${this.getPath()}`); + + try { + const resBody = await this.opts.plugin.getPrometheusExporterMetrics(); + res.status(200); + res.send(resBody); + } catch (ex: unknown) { + const errorMsg = `${fnTag} request handler fn crashed for: ${reqTag}`; + handleRestEndpointException({ errorMsg, log: this.log, error: ex, res }); + } + } +} diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/consortium/process-broadcast-endpoint-v1.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/consortium/process-broadcast-endpoint-v1.ts new file mode 100644 index 00000000000..f21ccd2a9fe --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/consortium/process-broadcast-endpoint-v1.ts @@ -0,0 +1,132 @@ +import { Express, Request, Response } from "express"; +import { stringify as safeStableStringify } from "safe-stable-stringify"; +import { + IWebServiceEndpoint, + IExpressRequestHandler, + IEndpointAuthzOptions, +} from "@hyperledger/cactus-core-api"; + +import { BroadcastResponseV1 } from "../generated/openapi/typescript-axios"; + +import { + Logger, + LogLevelDesc, + LoggerProvider, + Checks, + IAsyncProvider, +} from "@hyperledger/cactus-common"; + +import { + handleRestEndpointException, + registerWebServiceEndpoint, +} from "@hyperledger/cactus-core"; + +import OAS from "../../json/openapi.json"; +import { PluginConsortiumStatic } from "../plugin-consortium-static"; +import { StaticConsortiumRepository } from "../repository/static-consortium-repository"; +import { InternalServerError } from "http-errors-enhanced-cjs"; + +export interface IProcessBroadcastEndpointOptions { + plugin: PluginConsortiumStatic; + keyPairPem: string; + consortiumRepo: StaticConsortiumRepository; + logLevel?: LogLevelDesc; +} + +export class ProcessBroadcastEndpoint implements IWebServiceEndpoint { + public static readonly CLASS_NAME = "ProcessBroadcastEndpoint"; + + private readonly log: Logger; + private readonly plugin: PluginConsortiumStatic; + + constructor(public readonly options: IProcessBroadcastEndpointOptions) { + const fnTag = `${this.className}#constructor()`; + if (!options) { + throw new Error(`${fnTag} options falsy.`); + } + if (!options.keyPairPem) { + throw new Error(`${fnTag} options.keyPairPem falsy.`); + } + Checks.truthy(options.consortiumRepo, `${fnTag} options.consortiumRepo`); + Checks.truthy(options.plugin, `${fnTag} options.plugin`); + Checks.truthy( + options.plugin instanceof PluginConsortiumStatic, + `${fnTag} options.plugin instanceof PluginConsortiumStatic`, + ); + this.plugin = options.plugin; + + const level = options.logLevel || "INFO"; + const label = "add-node-endpoint-v1"; + this.log = LoggerProvider.getOrCreate({ level, label }); + } + + public get className(): string { + return ProcessBroadcastEndpoint.CLASS_NAME; + } + + getAuthorizationOptionsProvider(): IAsyncProvider { + // TODO: make this an injectable dependency in the constructor + return { + get: async () => ({ + isProtected: true, + requiredRoles: [], + }), + }; + } + + public getExpressRequestHandler(): IExpressRequestHandler { + return this.handleRequest.bind(this); + } + + public get oasPath(): (typeof OAS.paths)["/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/receive-broadcast"] { + return OAS.paths[ + "/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/receive-broadcast" + ]; + } + + public getOperationId(): string { + return this.oasPath.post.operationId; + } + + public getPath(): string { + return this.oasPath.post["x-hyperledger-cacti"].http.path; + } + + public getVerbLowerCase(): string { + return this.oasPath.post["x-hyperledger-cacti"].http.verbLowerCase; + } + + public async registerExpress( + expressApp: Express, + ): Promise { + await registerWebServiceEndpoint(expressApp, this); + return this; + } + + async handleRequest(req: Request, res: Response): Promise { + const fnTag = `${this.className}#handleRequest()`; + const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; + + this.log.debug(reqTag); + try { + const msgStringified = safeStableStringify(req.body.message); + if (typeof msgStringified !== "string") { + throw new InternalServerError( + fnTag + "#safeStableStringify() returned with non-string value.", + ); + } + await this.plugin.verifySignature( + req.body.signature, + msgStringified, + req.body.message.pubKey, + ); + await this.options.plugin.processNewNodeRequest(req.body.message.message); + const body: BroadcastResponseV1 = { result: true }; + res.status(200); + res.json(body); + } catch (ex: unknown) { + const errorMsg = `${fnTag} request handler fn crashed for: ${reqTag}`; + handleRestEndpointException({ errorMsg, log: this.log, error: ex, res }); + } + } +} diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/FILES b/packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/FILES new file mode 100644 index 00000000000..53250c02696 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/FILES @@ -0,0 +1,5 @@ +api.ts +base.ts +common.ts +configuration.ts +index.ts diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/VERSION b/packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/VERSION new file mode 100644 index 00000000000..cd802a1ec4e --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/VERSION @@ -0,0 +1 @@ +6.6.0 \ No newline at end of file diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/api.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/api.ts new file mode 100644 index 00000000000..7bbf9b1c147 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/api.ts @@ -0,0 +1,750 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Consortium Web Service + * Manage a Cactus consortium through the APIs. Needs administrative privileges. + * + * The version of the OpenAPI document: 2.0.0-rc.2 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import type { Configuration } from './configuration'; +import type { AxiosPromise, AxiosInstance, AxiosRequestConfig } from 'axios'; +import globalAxios from 'axios'; +// Some imports not used depending on template conditions +// @ts-ignore +import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObject, setBearerAuthToObject, setOAuthToObject, setSearchParams, serializeDataIfNeeded, toPathString, createRequestFunction } from './common'; +import type { RequestArgs } from './base'; +// @ts-ignore +import { BASE_PATH, COLLECTION_FORMATS, BaseAPI, RequiredError } from './base'; + +/** + * + * @export + * @interface BroadcastRequestV1 + */ +export interface BroadcastRequestV1 { + /** + * + * @type {BroadcastRequestV1Message} + * @memberof BroadcastRequestV1 + */ + 'message': BroadcastRequestV1Message; + /** + * + * @type {string} + * @memberof BroadcastRequestV1 + */ + 'signature': string; +} +/** + * + * @export + * @interface BroadcastRequestV1Message + */ +export interface BroadcastRequestV1Message { + /** + * + * @type {NewNodeRequestV1} + * @memberof BroadcastRequestV1Message + */ + 'message': NewNodeRequestV1; + /** + * + * @type {string} + * @memberof BroadcastRequestV1Message + */ + 'pubKey': string; +} +/** + * + * @export + * @interface BroadcastResponseV1 + */ +export interface BroadcastResponseV1 { + /** + * + * @type {boolean} + * @memberof BroadcastResponseV1 + */ + 'result': boolean; +} +/** + * A Cactus node can be a single server, or a set of servers behind a load balancer acting as one. + * @export + * @interface CactusNode + */ +export interface CactusNode { + /** + * + * @type {string} + * @memberof CactusNode + */ + 'nodeApiHost': string; + /** + * The PEM encoded public key that was used to generate the JWS included in the response (the jws property) + * @type {string} + * @memberof CactusNode + */ + 'publicKeyPem': string; + /** + * + * @type {string} + * @memberof CactusNode + */ + 'id': string; + /** + * + * @type {string} + * @memberof CactusNode + */ + 'consortiumId': string; + /** + * + * @type {string} + * @memberof CactusNode + */ + 'memberId': string; + /** + * Stores an array of Ledger entity IDs that are reachable (routable) via this Cactus Node. This information is used by the client side SDK API client to figure out at runtime where to send API requests that are specific to a certain ledger such as requests to execute transactions. + * @type {Array} + * @memberof CactusNode + */ + 'ledgerIds': Array; + /** + * + * @type {Array} + * @memberof CactusNode + */ + 'pluginInstanceIds': Array; +} +/** + * + * @export + * @interface CactusNodeAllOf + */ +export interface CactusNodeAllOf { + /** + * + * @type {string} + * @memberof CactusNodeAllOf + */ + 'id': string; + /** + * + * @type {string} + * @memberof CactusNodeAllOf + */ + 'consortiumId': string; + /** + * + * @type {string} + * @memberof CactusNodeAllOf + */ + 'memberId': string; + /** + * Stores an array of Ledger entity IDs that are reachable (routable) via this Cactus Node. This information is used by the client side SDK API client to figure out at runtime where to send API requests that are specific to a certain ledger such as requests to execute transactions. + * @type {Array} + * @memberof CactusNodeAllOf + */ + 'ledgerIds': Array; + /** + * + * @type {Array} + * @memberof CactusNodeAllOf + */ + 'pluginInstanceIds': Array; +} +/** + * A Cactus node meta information + * @export + * @interface CactusNodeMeta + */ +export interface CactusNodeMeta { + /** + * + * @type {string} + * @memberof CactusNodeMeta + */ + 'nodeApiHost': string; + /** + * The PEM encoded public key that was used to generate the JWS included in the response (the jws property) + * @type {string} + * @memberof CactusNodeMeta + */ + 'publicKeyPem': string; +} +/** + * + * @export + * @interface GetConsortiumJwsResponse + */ +export interface GetConsortiumJwsResponse { + /** + * + * @type {JWSGeneral} + * @memberof GetConsortiumJwsResponse + */ + 'jws': JWSGeneral; +} +/** + * + * @export + * @interface GetNodeJwsResponse + */ +export interface GetNodeJwsResponse { + /** + * + * @type {JWSGeneral} + * @memberof GetNodeJwsResponse + */ + 'jws': JWSGeneral; +} +/** + * Identity object of a Cacti Node + * @export + * @interface Identity + */ +export interface Identity { + /** + * Public key of the Node + * @type {string} + * @memberof Identity + */ + 'pubKey': string; + /** + * memberId of the organization the node belongs to + * @type {string} + * @memberof Identity + */ + 'memberId': string; + /** + * JWT generated by the organization the node belongs to + * @type {string} + * @memberof Identity + */ + 'proof': string; +} +/** + * + * @export + * @interface JWSGeneral + */ +export interface JWSGeneral { + /** + * + * @type {string} + * @memberof JWSGeneral + */ + 'payload': string; + /** + * + * @type {Array} + * @memberof JWSGeneral + */ + 'signatures': Array; +} +/** + * A JSON Web Signature. See: https://tools.ietf.org/html/rfc7515 for info about standard. + * @export + * @interface JWSRecipient + */ +export interface JWSRecipient { + /** + * + * @type {string} + * @memberof JWSRecipient + */ + 'signature': string; + /** + * + * @type {string} + * @memberof JWSRecipient + */ + 'protected'?: string; + /** + * + * @type {{ [key: string]: any; }} + * @memberof JWSRecipient + */ + 'header'?: { [key: string]: any; }; +} +/** + * + * @export + * @interface Ledger + */ +export interface Ledger { + /** + * + * @type {string} + * @memberof Ledger + */ + 'id': string; + /** + * + * @type {LedgerType} + * @memberof Ledger + */ + 'ledgerType': LedgerType; + /** + * + * @type {string} + * @memberof Ledger + */ + 'consortiumMemberId'?: string; +} + + +/** + * Enumerates the different ledger vendors and their major versions encoded within the name of the LedgerType. For example \"BESU_1X\" involves all of the [1.0.0;2.0.0) where 1.0.0 is included and anything up until, but not 2.0.0. See: https://stackoverflow.com/a/4396303/698470 for further explanation. + * @export + * @enum {string} + */ + +export const LedgerType = { + Besu1X: 'BESU_1X', + Besu2X: 'BESU_2X', + Burrow0X: 'BURROW_0X', + Corda4X: 'CORDA_4X', + Fabric2: 'FABRIC_2', + Sawtooth1X: 'SAWTOOTH_1X' +} as const; + +export type LedgerType = typeof LedgerType[keyof typeof LedgerType]; + + +/** + * + * @export + * @interface NewNodeRequestV1 + */ +export interface NewNodeRequestV1 { + /** + * + * @type {Identity} + * @memberof NewNodeRequestV1 + */ + 'identity': Identity; + /** + * proof of common configs and policies defined by the consortium + * @type {string} + * @memberof NewNodeRequestV1 + */ + 'treeHash': string; + /** + * + * @type {CactusNode} + * @memberof NewNodeRequestV1 + */ + 'node': CactusNode; + /** + * Ledger metadata + * @type {Array} + * @memberof NewNodeRequestV1 + */ + 'ledger': Array; + /** + * Plugin Instance metadata + * @type {Array} + * @memberof NewNodeRequestV1 + */ + 'pluginInstance': Array; + /** + * signature of the message + * @type {string} + * @memberof NewNodeRequestV1 + */ + 'signature': string; +} +/** + * + * @export + * @interface PluginInstance + */ +export interface PluginInstance { + /** + * + * @type {string} + * @memberof PluginInstance + */ + 'id': string; + /** + * + * @type {string} + * @memberof PluginInstance + */ + 'packageName': string; +} + +/** + * DefaultApi - axios parameter creator + * @export + */ +export const DefaultApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * + * @summary Adds a node to consortium JWS + * @param {NewNodeRequestV1} [newNodeRequestV1] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + addNodeToConsortiumV1: async (newNodeRequestV1?: NewNodeRequestV1, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/add-node`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(newNodeRequestV1, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * The JWS asserting the consortium metadata (pub keys and hosts of nodes) + * @summary Retrieves a consortium JWS + * @param {object} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getConsortiumJwsV1: async (body?: object, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/consortium/jws`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(body, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary Retrieves the JWT of a Cactus Node + * @param {object} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getNodeJwsV1: async (body?: object, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/node/jws`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(body, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary Get the Prometheus Metrics + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getPrometheusMetricsV1: async (options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/get-prometheus-exporter-metrics`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary Adds a node to consortium JWS + * @param {BroadcastRequestV1} [broadcastRequestV1] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + receiveBroadcastV1: async (broadcastRequestV1?: BroadcastRequestV1, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/v1/plugins/@hyperledger/cacti-plugin-consortium-static/receive-broadcast`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(broadcastRequestV1, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * DefaultApi - functional programming interface + * @export + */ +export const DefaultApiFp = function(configuration?: Configuration) { + const localVarAxiosParamCreator = DefaultApiAxiosParamCreator(configuration) + return { + /** + * + * @summary Adds a node to consortium JWS + * @param {NewNodeRequestV1} [newNodeRequestV1] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async addNodeToConsortiumV1(newNodeRequestV1?: NewNodeRequestV1, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.addNodeToConsortiumV1(newNodeRequestV1, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, + /** + * The JWS asserting the consortium metadata (pub keys and hosts of nodes) + * @summary Retrieves a consortium JWS + * @param {object} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getConsortiumJwsV1(body?: object, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getConsortiumJwsV1(body, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, + /** + * + * @summary Retrieves the JWT of a Cactus Node + * @param {object} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getNodeJwsV1(body?: object, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getNodeJwsV1(body, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, + /** + * + * @summary Get the Prometheus Metrics + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getPrometheusMetricsV1(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getPrometheusMetricsV1(options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, + /** + * + * @summary Adds a node to consortium JWS + * @param {BroadcastRequestV1} [broadcastRequestV1] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async receiveBroadcastV1(broadcastRequestV1?: BroadcastRequestV1, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.receiveBroadcastV1(broadcastRequestV1, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, + } +}; + +/** + * DefaultApi - factory interface + * @export + */ +export const DefaultApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + const localVarFp = DefaultApiFp(configuration) + return { + /** + * + * @summary Adds a node to consortium JWS + * @param {NewNodeRequestV1} [newNodeRequestV1] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + addNodeToConsortiumV1(newNodeRequestV1?: NewNodeRequestV1, options?: any): AxiosPromise { + return localVarFp.addNodeToConsortiumV1(newNodeRequestV1, options).then((request) => request(axios, basePath)); + }, + /** + * The JWS asserting the consortium metadata (pub keys and hosts of nodes) + * @summary Retrieves a consortium JWS + * @param {object} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getConsortiumJwsV1(body?: object, options?: any): AxiosPromise { + return localVarFp.getConsortiumJwsV1(body, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary Retrieves the JWT of a Cactus Node + * @param {object} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getNodeJwsV1(body?: object, options?: any): AxiosPromise { + return localVarFp.getNodeJwsV1(body, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary Get the Prometheus Metrics + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getPrometheusMetricsV1(options?: any): AxiosPromise { + return localVarFp.getPrometheusMetricsV1(options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary Adds a node to consortium JWS + * @param {BroadcastRequestV1} [broadcastRequestV1] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + receiveBroadcastV1(broadcastRequestV1?: BroadcastRequestV1, options?: any): AxiosPromise { + return localVarFp.receiveBroadcastV1(broadcastRequestV1, options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * DefaultApi - object-oriented interface + * @export + * @class DefaultApi + * @extends {BaseAPI} + */ +export class DefaultApi extends BaseAPI { + /** + * + * @summary Adds a node to consortium JWS + * @param {NewNodeRequestV1} [newNodeRequestV1] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public addNodeToConsortiumV1(newNodeRequestV1?: NewNodeRequestV1, options?: AxiosRequestConfig) { + return DefaultApiFp(this.configuration).addNodeToConsortiumV1(newNodeRequestV1, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * The JWS asserting the consortium metadata (pub keys and hosts of nodes) + * @summary Retrieves a consortium JWS + * @param {object} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public getConsortiumJwsV1(body?: object, options?: AxiosRequestConfig) { + return DefaultApiFp(this.configuration).getConsortiumJwsV1(body, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary Retrieves the JWT of a Cactus Node + * @param {object} [body] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public getNodeJwsV1(body?: object, options?: AxiosRequestConfig) { + return DefaultApiFp(this.configuration).getNodeJwsV1(body, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary Get the Prometheus Metrics + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public getPrometheusMetricsV1(options?: AxiosRequestConfig) { + return DefaultApiFp(this.configuration).getPrometheusMetricsV1(options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary Adds a node to consortium JWS + * @param {BroadcastRequestV1} [broadcastRequestV1] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public receiveBroadcastV1(broadcastRequestV1?: BroadcastRequestV1, options?: AxiosRequestConfig) { + return DefaultApiFp(this.configuration).receiveBroadcastV1(broadcastRequestV1, options).then((request) => request(this.axios, this.basePath)); + } +} + + diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/base.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/base.ts new file mode 100644 index 00000000000..dcb038e0b6d --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/base.ts @@ -0,0 +1,72 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Consortium Web Service + * Manage a Cactus consortium through the APIs. Needs administrative privileges. + * + * The version of the OpenAPI document: 2.0.0-rc.2 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import type { Configuration } from './configuration'; +// Some imports not used depending on template conditions +// @ts-ignore +import type { AxiosPromise, AxiosInstance, AxiosRequestConfig } from 'axios'; +import globalAxios from 'axios'; + +export const BASE_PATH = "http://localhost".replace(/\/+$/, ""); + +/** + * + * @export + */ +export const COLLECTION_FORMATS = { + csv: ",", + ssv: " ", + tsv: "\t", + pipes: "|", +}; + +/** + * + * @export + * @interface RequestArgs + */ +export interface RequestArgs { + url: string; + options: AxiosRequestConfig; +} + +/** + * + * @export + * @class BaseAPI + */ +export class BaseAPI { + protected configuration: Configuration | undefined; + + constructor(configuration?: Configuration, protected basePath: string = BASE_PATH, protected axios: AxiosInstance = globalAxios) { + if (configuration) { + this.configuration = configuration; + this.basePath = configuration.basePath || this.basePath; + } + } +}; + +/** + * + * @export + * @class RequiredError + * @extends {Error} + */ +export class RequiredError extends Error { + constructor(public field: string, msg?: string) { + super(msg); + this.name = "RequiredError" + } +} diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/common.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/common.ts new file mode 100644 index 00000000000..66442d8c0e7 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/common.ts @@ -0,0 +1,150 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Consortium Web Service + * Manage a Cactus consortium through the APIs. Needs administrative privileges. + * + * The version of the OpenAPI document: 2.0.0-rc.2 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import type { Configuration } from "./configuration"; +import type { RequestArgs } from "./base"; +import type { AxiosInstance, AxiosResponse } from 'axios'; +import { RequiredError } from "./base"; + +/** + * + * @export + */ +export const DUMMY_BASE_URL = 'https://example.com' + +/** + * + * @throws {RequiredError} + * @export + */ +export const assertParamExists = function (functionName: string, paramName: string, paramValue: unknown) { + if (paramValue === null || paramValue === undefined) { + throw new RequiredError(paramName, `Required parameter ${paramName} was null or undefined when calling ${functionName}.`); + } +} + +/** + * + * @export + */ +export const setApiKeyToObject = async function (object: any, keyParamName: string, configuration?: Configuration) { + if (configuration && configuration.apiKey) { + const localVarApiKeyValue = typeof configuration.apiKey === 'function' + ? await configuration.apiKey(keyParamName) + : await configuration.apiKey; + object[keyParamName] = localVarApiKeyValue; + } +} + +/** + * + * @export + */ +export const setBasicAuthToObject = function (object: any, configuration?: Configuration) { + if (configuration && (configuration.username || configuration.password)) { + object["auth"] = { username: configuration.username, password: configuration.password }; + } +} + +/** + * + * @export + */ +export const setBearerAuthToObject = async function (object: any, configuration?: Configuration) { + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + object["Authorization"] = "Bearer " + accessToken; + } +} + +/** + * + * @export + */ +export const setOAuthToObject = async function (object: any, name: string, scopes: string[], configuration?: Configuration) { + if (configuration && configuration.accessToken) { + const localVarAccessTokenValue = typeof configuration.accessToken === 'function' + ? await configuration.accessToken(name, scopes) + : await configuration.accessToken; + object["Authorization"] = "Bearer " + localVarAccessTokenValue; + } +} + +function setFlattenedQueryParams(urlSearchParams: URLSearchParams, parameter: any, key: string = ""): void { + if (parameter == null) return; + if (typeof parameter === "object") { + if (Array.isArray(parameter)) { + (parameter as any[]).forEach(item => setFlattenedQueryParams(urlSearchParams, item, key)); + } + else { + Object.keys(parameter).forEach(currentKey => + setFlattenedQueryParams(urlSearchParams, parameter[currentKey], `${key}${key !== '' ? '.' : ''}${currentKey}`) + ); + } + } + else { + if (urlSearchParams.has(key)) { + urlSearchParams.append(key, parameter); + } + else { + urlSearchParams.set(key, parameter); + } + } +} + +/** + * + * @export + */ +export const setSearchParams = function (url: URL, ...objects: any[]) { + const searchParams = new URLSearchParams(url.search); + setFlattenedQueryParams(searchParams, objects); + url.search = searchParams.toString(); +} + +/** + * + * @export + */ +export const serializeDataIfNeeded = function (value: any, requestOptions: any, configuration?: Configuration) { + const nonString = typeof value !== 'string'; + const needsSerialization = nonString && configuration && configuration.isJsonMime + ? configuration.isJsonMime(requestOptions.headers['Content-Type']) + : nonString; + return needsSerialization + ? JSON.stringify(value !== undefined ? value : {}) + : (value || ""); +} + +/** + * + * @export + */ +export const toPathString = function (url: URL) { + return url.pathname + url.search + url.hash +} + +/** + * + * @export + */ +export const createRequestFunction = function (axiosArgs: RequestArgs, globalAxios: AxiosInstance, BASE_PATH: string, configuration?: Configuration) { + return >(axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs = {...axiosArgs.options, url: (configuration?.basePath || basePath) + axiosArgs.url}; + return axios.request(axiosRequestArgs); + }; +} diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/configuration.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/configuration.ts new file mode 100644 index 00000000000..fb9374a9584 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/configuration.ts @@ -0,0 +1,101 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Consortium Web Service + * Manage a Cactus consortium through the APIs. Needs administrative privileges. + * + * The version of the OpenAPI document: 2.0.0-rc.2 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export interface ConfigurationParameters { + apiKey?: string | Promise | ((name: string) => string) | ((name: string) => Promise); + username?: string; + password?: string; + accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise); + basePath?: string; + baseOptions?: any; + formDataCtor?: new () => any; +} + +export class Configuration { + /** + * parameter for apiKey security + * @param name security name + * @memberof Configuration + */ + apiKey?: string | Promise | ((name: string) => string) | ((name: string) => Promise); + /** + * parameter for basic security + * + * @type {string} + * @memberof Configuration + */ + username?: string; + /** + * parameter for basic security + * + * @type {string} + * @memberof Configuration + */ + password?: string; + /** + * parameter for oauth2 security + * @param name security name + * @param scopes oauth2 scope + * @memberof Configuration + */ + accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise); + /** + * override base path + * + * @type {string} + * @memberof Configuration + */ + basePath?: string; + /** + * base options for axios calls + * + * @type {any} + * @memberof Configuration + */ + baseOptions?: any; + /** + * The FormData constructor that will be used to create multipart form data + * requests. You can inject this here so that execution environments that + * do not support the FormData class can still run the generated client. + * + * @type {new () => FormData} + */ + formDataCtor?: new () => any; + + constructor(param: ConfigurationParameters = {}) { + this.apiKey = param.apiKey; + this.username = param.username; + this.password = param.password; + this.accessToken = param.accessToken; + this.basePath = param.basePath; + this.baseOptions = param.baseOptions; + this.formDataCtor = param.formDataCtor; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * @param mime - MIME (Multipurpose Internet Mail Extensions) + * @return True if the given MIME is JSON, false otherwise. + */ + public isJsonMime(mime: string): boolean { + const jsonMime: RegExp = new RegExp('^(application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(;.*)?$', 'i'); + return mime !== null && (jsonMime.test(mime) || mime.toLowerCase() === 'application/json-patch+json'); + } +} diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/index.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/index.ts new file mode 100644 index 00000000000..a346bc2fdb6 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/generated/openapi/typescript-axios/index.ts @@ -0,0 +1,18 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Consortium Web Service + * Manage a Cactus consortium through the APIs. Needs administrative privileges. + * + * The version of the OpenAPI document: 2.0.0-rc.2 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export * from "./api"; +export * from "./configuration"; + diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/index.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/index.ts new file mode 100755 index 00000000000..87cb558397c --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/index.ts @@ -0,0 +1 @@ +export * from "./public-api"; diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/index.web.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/index.web.ts new file mode 100755 index 00000000000..bdf54028d23 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/index.web.ts @@ -0,0 +1 @@ +export * from "./generated/openapi/typescript-axios/index"; diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/plugin-consortium-static.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/plugin-consortium-static.ts new file mode 100644 index 00000000000..402d37e6017 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/plugin-consortium-static.ts @@ -0,0 +1,515 @@ +import { Express } from "express"; +import { + importPKCS8, + GeneralSign, + SignJWT, + compactVerify, + importSPKI, + JWK, +} from "jose"; +import { v4 as uuidv4 } from "uuid"; + +import OAS from "../json/openapi.json"; + +import { + BroadcastRequestV1, + DefaultApi as ConsortiumManagerApi, +} from "./generated/openapi/typescript-axios"; + +import { + ConsortiumDatabase, + IPluginWebService, + IWebServiceEndpoint, + ICactusPlugin, + ICactusPluginOptions, + JWSGeneral, + JWSRecipient, + CactusNode, + Ledger, + PluginInstance, +} from "@hyperledger/cactus-core-api"; + +import { PluginRegistry } from "@hyperledger/cactus-core"; +import { stringify as safeStableStringify } from "safe-stable-stringify"; +import { + Checks, + Logger, + LoggerProvider, + LogLevelDesc, +} from "@hyperledger/cactus-common"; +import { GetConsortiumEndpointV1 } from "./consortium/get-consortium-jws-endpoint-v1"; +import { GetNodeJwsEndpoint } from "./consortium/get-node-jws-endpoint-v1"; + +import { PrometheusExporter } from "./prometheus-exporter/prometheus-exporter"; + +import { + IGetPrometheusExporterMetricsEndpointV1Options, + GetPrometheusExporterMetricsEndpointV1, +} from "./consortium/get-prometheus-exporter-metrics-endpoint-v1"; + +import { + Configuration, + DefaultApi, + NewNodeRequestV1, +} from "./generated/openapi/typescript-axios"; +import { StaticConsortiumRepository } from "./repository/static-consortium-repository"; +import { AddNewNodeEndpoint } from "./consortium/add-new-node-endpoint-v1"; +import { BadRequestError, InternalServerError } from "http-errors-enhanced-cjs"; +import { ProcessBroadcastEndpoint } from "./consortium/process-broadcast-endpoint-v1"; +import { PolicyGroup } from "./policy-model/policy-group"; +export interface IWebAppOptions { + port: number; + hostname: string; +} + +export interface IKeyPair { + publicKey: Uint8Array; + privateKey: Uint8Array; +} + +export interface IPluginConsortiumStaticOptions extends ICactusPluginOptions { + keyPairPem: string; + keyPairPub: string; + consortiumDatabase: ConsortiumDatabase; + node: CactusNode; + ledgers: Ledger[]; + pluginInstances: PluginInstance[]; + memberId: string; + entitiesJWK: { [key: string]: JWK }; + rootPolicyGroup?: PolicyGroup; + packageConfigs?: { [key: string]: unknown }; + prometheusExporter?: PrometheusExporter; + pluginRegistry?: PluginRegistry; + logLevel?: LogLevelDesc; + ctorArgs?: Record; +} + +export class PluginConsortiumStatic + implements ICactusPlugin, IPluginWebService +{ + public static readonly CLASS_NAME = "PluginConsortiumStatic"; + public prometheusExporter: PrometheusExporter; + private readonly log: Logger; + private readonly instanceId: string; + private readonly repo: StaticConsortiumRepository; + private endpoints: IWebServiceEndpoint[] | undefined; + + public get className(): string { + return PluginConsortiumStatic.CLASS_NAME; + } + + constructor(public readonly options: IPluginConsortiumStaticOptions) { + const fnTag = `PluginConsortiumStatic#constructor()`; + if (!options) { + throw new Error(`${fnTag} options falsy.`); + } + Checks.truthy(options.instanceId, `${fnTag} options.instanceId`); + Checks.truthy( + options.consortiumDatabase, + `${fnTag} options.consortiumDatabase`, + ); + + this.log = LoggerProvider.getOrCreate({ + label: "plugin-consortium-static", + level: options.logLevel ? options.logLevel : "INFO", + }); + + this.instanceId = this.options.instanceId; + this.repo = new StaticConsortiumRepository({ + db: options.consortiumDatabase, + node: options.node, + ledgers: options.ledgers, + pluginInstances: options.pluginInstances, + memberId: options.memberId, + rootPolicyGroup: options.rootPolicyGroup, + packageConfigs: options.packageConfigs, + entitiesJWK: options.entitiesJWK, + }); + + this.prometheusExporter = + options.prometheusExporter || + new PrometheusExporter({ pollingIntervalInMin: 1 }); + + Checks.truthy( + this.prometheusExporter, + `${fnTag} options.prometheusExporter`, + ); + this.prometheusExporter.startMetricsCollection(); + this.prometheusExporter.setNodeCount(this.getNodeCount()); + } + + public getOpenApiSpec(): unknown { + return OAS; + } + + public getInstanceId(): string { + return this.instanceId; + } + + public async onPluginInit(): Promise { + return; + } + + public getPrometheusExporter(): PrometheusExporter { + return this.prometheusExporter; + } + + public async shutdown(): Promise { + return; + } + + public async getPrometheusExporterMetrics(): Promise { + const res: string = await this.prometheusExporter.getPrometheusMetrics(); + this.log.debug(`getPrometheusExporterMetrics() response: %o`, res); + return res; + } + + public getNodeCount(): number { + Checks.truthy(this.repo, `${this.className}.this.repo`); + return this.repo.allNodes.length; + } + /** + * Updates the Node count Prometheus metric of the plugin. + * Note: This does not change the underlying consortium database at all, + * only affects **the metrics**. + */ + public updateMetricNodeCount(): void { + const nodeCount = this.getNodeCount(); + this.prometheusExporter.setNodeCount(nodeCount); + } + + public async registerWebServices( + app: Express, + ): Promise { + const webServices = await this.getOrCreateWebServices(); + webServices.forEach((ws) => ws.registerExpress(app)); + return webServices; + } + + public async getOrCreateWebServices(): Promise { + const { log } = this; + const pkgName = this.getPackageName(); + + if (this.endpoints) { + return this.endpoints; + } + log.info(`Creating web services for plugin ${pkgName}...`); + // presence of webAppOptions implies that caller wants the plugin to configure it's own express instance on a custom + // host/port to listen on + + const { keyPairPem } = this.options; + const consortiumRepo = this.repo; + + const endpoints: IWebServiceEndpoint[] = []; + { + const options = { keyPairPem, consortiumRepo, plugin: this }; + const endpoint = new AddNewNodeEndpoint(options); + endpoints.push(endpoint); + const path = endpoint.getPath(); + this.log.info(`Instantiated AddNodeEndpoint at ${path}`); + } + { + const options = { keyPairPem, consortiumRepo, plugin: this }; + const endpoint = new ProcessBroadcastEndpoint(options); + endpoints.push(endpoint); + const path = endpoint.getPath(); + this.log.info(`Instantiated AddNodeEndpoint at ${path}`); + } + { + const options = { keyPairPem, consortiumRepo, plugin: this }; + const endpoint = new GetConsortiumEndpointV1(options); + endpoints.push(endpoint); + const path = endpoint.getPath(); + this.log.info(`Instantiated GetConsortiumEndpointV1 at ${path}`); + } + { + const options = { keyPairPem, consortiumRepo, plugin: this }; + const endpoint = new GetNodeJwsEndpoint(options); + const path = endpoint.getPath(); + endpoints.push(endpoint); + this.log.info(`Instantiated GetNodeJwsEndpoint at ${path}`); + } + { + const opts: IGetPrometheusExporterMetricsEndpointV1Options = { + plugin: this, + logLevel: this.options.logLevel, + }; + const endpoint = new GetPrometheusExporterMetricsEndpointV1(opts); + const path = endpoint.getPath(); + endpoints.push(endpoint); + this.log.info(`Instantiated GetNodeJwsEndpoint at ${path}`); + } + this.endpoints = endpoints; + + log.info(`Instantiated web svcs for plugin ${pkgName} OK`, { endpoints }); + return endpoints; + } + + public getPackageName(): string { + return `@hyperledger/cacti-plugin-consortium-static`; + } + + public async getNodeJws(): Promise { + Checks.truthy(this.repo, `${this.className}.this.repo`); + const { keyPairPem } = this.options; + + this.updateMetricNodeCount(); + const keyPair = await importPKCS8(keyPairPem, "ES256K"); + const payloadObject = { consortiumDatabase: this.repo.consortiumDatabase }; + const payloadJson = safeStableStringify(payloadObject); + const _protected = { + iat: Date.now(), + jti: uuidv4(), + iss: "Hyperledger Cactus", + }; + // TODO: double check if this casting is safe (it is supposed to be) + const encoder = new TextEncoder(); + const sign = new GeneralSign(encoder.encode(payloadJson)); + sign + .addSignature(keyPair) + .setProtectedHeader({ alg: "ES256K", _protected }); + const jwsGeneral = await sign.sign(); + return jwsGeneral as JWSGeneral; + } + + public broadcastJoinRequest(req: NewNodeRequestV1) { + const nodes = this.repo.allNodes.filter((node) => { + return ( + node.id !== this.repo.getSelfData().node.id && node.id !== req.node.id + ); + }); + this.log.info( + "Will broadcast to nodes: ", + nodes.map((node) => { + return node.id; + }), + ); + nodes.forEach(async (node) => { + const api = new ConsortiumManagerApi( + new Configuration({ basePath: node.nodeApiHost }), + ); + const message = { + message: req, + pubKey: this.options.keyPairPub, + }; + const msgStringified = safeStableStringify(message); + if (typeof msgStringified !== "string") { + throw new InternalServerError( + "getNodeJws#safeStableStringify() returned with non-string value.", + ); + } + const sig = await this.sign(msgStringified); + + const broadcast: BroadcastRequestV1 = { + message, + signature: sig, + }; + api.receiveBroadcastV1(broadcast); + }); + } + + public async getConsortiumJws(): Promise { + const nodes = this.repo.allNodes; + + const ctorArgs = this.options.ctorArgs || {}; + + const requests = nodes + .map((cnm) => cnm.nodeApiHost) + .map(function (host) { + // overwrite basePath with node api host + ctorArgs.basePath = host; + // return the ApiClient configuration object + return new Configuration(ctorArgs); + }) + .map((configuration) => new DefaultApi(configuration)) + .map((apiClient) => apiClient.getNodeJwsV1()); + + const responses = await Promise.all(requests); + + const signatures: JWSRecipient[] = []; + + responses + .map((apiResponse) => apiResponse.data) + .map((getNodeJwsResponse) => getNodeJwsResponse.jws) + .forEach((aJws: JWSGeneral) => + aJws.signatures.forEach((signature) => signatures.push(signature)), + ); + + const [response] = responses; + const jws = response.data.jws; + jws.signatures = signatures; + return jws; + } + + public async processNewNodeRequest(req: NewNodeRequestV1) { + const fn = `${PluginConsortiumStatic.CLASS_NAME}#processNewNodeRequest()`; + const identity = req.identity; + + Checks.nonBlankString(identity.pubKey); + const msg = { + identity, + treeHash: req.treeHash, + node: req.node, + ledger: req.ledger, + pluginInstance: req.pluginInstance, + }; + + const msgStringified = safeStableStringify(msg); + if (typeof msgStringified !== "string") { + throw new InternalServerError( + "processNodeRequest#safeStableStringify() returned with non-string value.", + ); + } + if ( + !(await this.verifySignature( + req.signature, + msgStringified, + identity.pubKey, + )) + ) { + throw new BadRequestError(fn + ": Signature is invalid."); + } + + // TODO: make verification of publicKey process configurable! + // Ideally, we want to allow for entities to customize their identification process + // It would allow for integrations with different methods, serving different requirements + + // What is done is: the request to join consortium includes a JWT token that must be signed by one of the + // organizations that already belongs to the consortium. + // Basically we support adding new nodes, but not new organizations + if (!(await this.repo.verifyJWT(identity.proof, req.node.memberId))) { + throw new BadRequestError( + fn + + ": Your token from organization " + + req.node.memberId + + " is invalid.", + ); + } + + const policyAssertion = req.treeHash; + try { + if (!this.verifySettings(policyAssertion)) { + throw new BadRequestError( + fn + + ": Your policy & configuration settings do not match the ones used in this consortium.", + ); + } + } catch (err) { + throw new BadRequestError(fn + err.message); + } + + this.repo.addNode(req.node, req.pluginInstance, req.ledger); + this.updateMetricNodeCount(); + } + + private verifySettings(assert: string): boolean { + const self = this.repo.getPolicyTreeProof() + this.repo.getConfigsProof(); + this.log.info(self); + this.log.info(assert); + return self === assert; + } + + async sign(msg: string): Promise { + const encoder = new TextEncoder(); + const data = encoder.encode(msg); + const privateKey = await importPKCS8(this.options.keyPairPem, "ES256K"); + const _protected = { + iat: Date.now(), + jti: uuidv4(), + iss: "Hyperledger Cactus", + }; + const signature = await new SignJWT({ data: Array.from(data) }) + .setProtectedHeader({ alg: "ES256K", _protected }) + .sign(privateKey); + return signature; + } + + async verifySignature( + signature: string, + msg: string, + pubKey: string, + ): Promise { + const publicKey = await importSPKI(pubKey, "ES256K"); + const { payload } = await compactVerify(signature, publicKey); + + // Extract the original message + const parsedPayload = JSON.parse(payload.toString()); + const signedData = new Uint8Array(parsedPayload.data); + const decodedMessage = new TextDecoder().decode(signedData); + return decodedMessage === msg; + } + + public async joinConsortium(managerApi: ConsortiumManagerApi, jwt: string) { + const fn = `${PluginConsortiumStatic.CLASS_NAME}#joinConsortium()`; + const nodeInfo = this.repo.getSelfData(); + const treeHash = + this.repo.getPolicyTreeProof() + this.repo.getConfigsProof(); + + this.log.info(treeHash); + const msg = safeStableStringify({ + identity: { + pubKey: this.options.keyPairPub, + memberId: nodeInfo.memberId, + proof: jwt, //token signed by the organization identified by nodeInfo.memberId + }, + treeHash, + node: nodeInfo.node, + ledger: nodeInfo.ledgers, + pluginInstance: nodeInfo.pluginInstances, + }) as string; + + const request: NewNodeRequestV1 = { + identity: { + pubKey: this.options.keyPairPub, + memberId: nodeInfo.memberId, + proof: jwt, + }, + treeHash, + node: nodeInfo.node, + ledger: nodeInfo.ledgers, + pluginInstance: nodeInfo.pluginInstances, + signature: await this.sign(msg), + }; + + const response = await managerApi.addNodeToConsortiumV1(request); + + if (!response) { + throw new InternalServerError(`${fn} response is falsy`); + } + if (!response.status) { + throw new InternalServerError(`${fn} response.status is falsy`); + } + const { status, data, statusText, config } = response; + if (response.status < 200 || response.status > 300) { + // We log the error here on the debug level so that later on we can inspect the contents + // of it in the logs if we need to. The reason that this is important is because we do not + // want to dump the full response onto our own error response that is going back to the caller + // due to that potentially being a security issue that we are exposing internal data via the + // error responses. + // With that said, we still need to make sure that we can determine the root cause of any + // issues after the fact and therefore we must save the error response details somewhere (the logs) + this.log.debug( + "ConsortiumApi non-2xx HTTP response:", + data, + status, + config, + ); + + // For the caller/client we just send back a generic error admitting that we somehow messed up: + const errorMessage = `${fn} ConsortiumStaticApi error status: ${status}: ${statusText}`; + throw new InternalServerError(errorMessage); + } + if (!data) { + throw new InternalServerError(`${fn} response.data is falsy`); + } + Checks.truthy(response.data.jws, `${fn}::response.jws`); + Checks.truthy(response.data.jws.payload, `${fn}::response.jws.payload`); + const json = Buffer.from(response.data.jws.payload, "base64").toString(); + const body = JSON.parse(json); + const { consortiumDatabase }: { consortiumDatabase: ConsortiumDatabase } = + body; + + this.repo.populateDb(consortiumDatabase); + this.updateMetricNodeCount(); + } +} diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/plugin-factory-consortium-static.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/plugin-factory-consortium-static.ts new file mode 100644 index 00000000000..1382b31839b --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/plugin-factory-consortium-static.ts @@ -0,0 +1,20 @@ +import { + IPluginFactoryOptions, + PluginFactory, +} from "@hyperledger/cactus-core-api"; +import { + IPluginConsortiumStaticOptions, + PluginConsortiumStatic, +} from "./plugin-consortium-static"; + +export class PluginFactoryWebService extends PluginFactory< + PluginConsortiumStatic, + IPluginConsortiumStaticOptions, + IPluginFactoryOptions +> { + async create( + pluginOptions: IPluginConsortiumStaticOptions, + ): Promise { + return new PluginConsortiumStatic(pluginOptions); + } +} diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/i-policy.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/i-policy.ts new file mode 100644 index 00000000000..2fd8a3f6281 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/i-policy.ts @@ -0,0 +1,10 @@ +/* +This is an interface to represent the base components of a policy +*/ + +export interface IPolicy { + name: string; + caption: string; + description: string; + id: string; +} diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/policy-action.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/policy-action.ts new file mode 100644 index 00000000000..4e9a83c5450 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/policy-action.ts @@ -0,0 +1,4 @@ +import { IPolicy } from "./i-policy"; +export interface PolicyAction extends IPolicy { + execute(...args: unknown[]): Promise; +} diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/policy-condition.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/policy-condition.ts new file mode 100644 index 00000000000..4170c30e035 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/policy-condition.ts @@ -0,0 +1,5 @@ +import { IPolicy } from "./i-policy"; + +export interface PolicyCondition extends IPolicy { + evaluate(...args: unknown[]): Promise; +} diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/policy-group.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/policy-group.ts new file mode 100644 index 00000000000..adff1ad9f82 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/policy-group.ts @@ -0,0 +1,153 @@ +import { Checks } from "@hyperledger/cactus-common"; +import { PolicyRule } from "./policy-rule"; +import { IPolicyItemOptions, PolicyItem } from "./polity-item"; +import MerkleTree from "merkletreejs"; +import { stringify as safeStableStringify } from "safe-stable-stringify"; + +export interface IPolicyGroupOptions extends IPolicyItemOptions { + role: string; +} + +export class PolicyGroup extends PolicyItem { + private policyGroups: Map; + private policyRules: Map; + private role: string; + private inheritedRoles: string[]; + + constructor(options: IPolicyGroupOptions) { + Checks.nonBlankString(options.role); + super(options); + this.role = options.role; + this.policyGroups = new Map(); + this.policyRules = new Map(); + this.inheritedRoles = []; + } + + public setInheritedRoles(roles: string[]) { + this.inheritedRoles = roles; + } + public getRoles(): string[] { + return Array.prototype.concat(this.inheritedRoles, [this.role]); + } + + public addGroup(group: PolicyGroup) { + if (group.getId() === this.getId()) { + throw Error( + "Can't add subgroup" + group.getId() + " to group " + this.getId(), + ); + } + if (this.policyGroups.get(group.getId())) { + throw Error( + "Group " + group.getId() + " already exists in " + this.getId(), + ); + } + + //TODO: verify role (must be unique) + + group.setInheritedRoles(this.getRoles()); + this.policyGroups.set(group.getId(), group); + } + + public addRule(rule: PolicyRule) { + if (!rule.getRoles().includes(this.role)) { + throw Error( + "PolicyRule" + + rule.getId() + + " is not targeted to policy group with role " + + this.role, + ); + } + if (this.policyRules.get(rule.getId())) { + throw Error( + "PolicyRule " + + rule.getId() + + " already exists in Group " + + this.getId(), + ); + } + + this.policyRules.set(rule.getId(), rule); + } + + public getPolicySubGroupById(id: string): PolicyGroup | undefined { + if (this.policyGroups.get(id)) { + return this.policyGroups.get(id); + } + + for (const group of this.policyGroups.values()) { + const g = group.getPolicySubGroupById(id); + if (g) { + return g; + } + } + + return undefined; + } + + public getPolicySubGroupByRole(role: string): PolicyGroup | undefined { + for (const group of this.policyGroups.values()) { + if (group.getRoles()[group.getRoles().length - 1] === role) { + return group; + } + } + } + public getPolicySubGroupByRoles(roles: string[]): PolicyGroup | undefined { + if (roles.length < 1) return undefined; + let group = this.getPolicySubGroupByRole(roles[0]); + if (!group) { + return undefined; + } + for (const role of roles) { + group = group?.getPolicySubGroupByRole(role); + if (!group) { + return undefined; + } + } + return group; + } + + public buildTreeProof(tree?: { rules: string[]; groups: string[] }): string { + if (!tree) { + tree = this.buildTree(); + } + return new MerkleTree( + Array.prototype.concat(tree.rules, tree.groups), + undefined, + { + sort: true, + hashLeaves: true, + }, + ) + .getRoot() + .toString("hex"); + } + + public buildTree(): { + rules: string[]; + groups: string[]; + } { + const tree: { + rules: string[]; + groups: string[]; + } = { + rules: [], + groups: [], + }; + for (const group of this.policyGroups.values()) { + const tr = group.buildTree(); + tree.rules = Array.prototype.concat(tree.rules, tr.rules); + tree.groups = Array.prototype.concat(tree.groups, tr.groups); + } + const rules = Array.from(this.policyRules.values()).map((rule) => { + return safeStableStringify(rule.asIPolicy()); + }); + const groups = Array.from(this.policyRules.values()).map((rule) => { + return safeStableStringify(rule.asIPolicy()); + }); + + tree.rules = Array.prototype.concat(tree.rules, rules); + tree.groups = Array.prototype.concat(tree.groups, groups); + + return tree; + } +} diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/policy-rule.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/policy-rule.ts new file mode 100644 index 00000000000..114cd08d7cd --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/policy-rule.ts @@ -0,0 +1,31 @@ +import { PolicyAction } from "./policy-action"; +import { PolicyCondition } from "./policy-condition"; +import { IPolicyItemOptions, PolicyItem } from "./polity-item"; +export interface IPolicyRuleOptions extends IPolicyItemOptions { + policyAction: PolicyAction; + policyCondition: PolicyCondition; + roles: string[]; +} +export class PolicyRule extends PolicyItem { + private policyCondition: PolicyCondition; + private policyAction: PolicyAction; + private roles: string[]; + constructor(options: IPolicyRuleOptions) { + super(options); + this.policyAction = options.policyAction; + this.policyCondition = options.policyCondition; + this.roles = options.roles; + } + + public async evaluateCondition(): Promise { + return this.policyCondition.evaluate(); + } + + public async executePolicyAction(): Promise { + return this.policyAction.execute(); + } + + public getRoles(): string[] { + return this.roles; + } +} diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/polity-item.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/polity-item.ts new file mode 100644 index 00000000000..59b97c08c46 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/policy-model/polity-item.ts @@ -0,0 +1,47 @@ +import { IPolicy } from "./i-policy"; +import { Checks } from "@hyperledger/cactus-common"; +export interface IPolicyItemOptions { + name: string; + caption: string; + description: string; + id: string; +} +export class PolicyItem implements IPolicy { + name: string; + caption: string; + description: string; + id: string; + + constructor(options: IPolicyItemOptions) { + Checks.nonBlankString(options.name); + Checks.nonBlankString(options.caption); + Checks.nonBlankString(options.description); + Checks.nonBlankString(options.id); + this.name = options.name; + this.caption = options.caption; + this.description = options.description; + this.id = options.id; + } + + public getName(): string { + return this.name; + } + public getCaption(): string { + return this.caption; + } + public getDescription(): string { + return this.description; + } + public getId(): string { + return this.id; + } + + public asIPolicy(): IPolicy { + return { + name: this.getName(), + caption: this.getCaption(), + description: this.getDescription(), + id: this.getId(), + }; + } +} diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/prometheus-exporter/data-fetcher.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/prometheus-exporter/data-fetcher.ts new file mode 100644 index 00000000000..55869bf1cfe --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/prometheus-exporter/data-fetcher.ts @@ -0,0 +1,12 @@ +import { NodeCount } from "./response.type"; + +import { + totalTxCount, + K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT, +} from "./metrics"; + +export async function collectMetrics(nodeCount: NodeCount): Promise { + totalTxCount + .labels(K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT) + .set(nodeCount.counter); +} diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/prometheus-exporter/metrics.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/prometheus-exporter/metrics.ts new file mode 100644 index 00000000000..b965dd39f41 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/prometheus-exporter/metrics.ts @@ -0,0 +1,11 @@ +import { Gauge } from "prom-client"; + +export const K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT = + "cactus_consortium_manual_total_node_count"; + +export const totalTxCount = new Gauge({ + registers: [], + name: K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT, + help: "Total cactus node count", + labelNames: ["type"], +}); diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/prometheus-exporter/prometheus-exporter.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/prometheus-exporter/prometheus-exporter.ts new file mode 100644 index 00000000000..6c07c56008e --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/prometheus-exporter/prometheus-exporter.ts @@ -0,0 +1,43 @@ +import promClient, { Registry } from "prom-client"; +import { NodeCount } from "./response.type"; +import { + totalTxCount, + K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT, +} from "./metrics"; + +export interface IPrometheusExporterOptions { + pollingIntervalInMin?: number; +} + +export class PrometheusExporter { + public readonly metricsPollingIntervalInMin: number; + public readonly nodeCount: NodeCount = { counter: 0 }; + public readonly registry: Registry; + + constructor( + public readonly prometheusExporterOptions: IPrometheusExporterOptions, + ) { + this.metricsPollingIntervalInMin = + prometheusExporterOptions.pollingIntervalInMin || 1; + this.registry = new Registry(); + } + + public setNodeCount(nodeCount: number): void { + this.nodeCount.counter = nodeCount; + totalTxCount + .labels(K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT) + .set(this.nodeCount.counter); + } + + public async getPrometheusMetrics(): Promise { + const result = await this.registry.getSingleMetricAsString( + K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT, + ); + return result; + } + + public startMetricsCollection(): void { + this.registry.registerMetric(totalTxCount); + promClient.collectDefaultMetrics({ register: this.registry }); + } +} diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/prometheus-exporter/response.type.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/prometheus-exporter/response.type.ts new file mode 100644 index 00000000000..4f2cf2ac0c9 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/prometheus-exporter/response.type.ts @@ -0,0 +1,3 @@ +export type NodeCount = { + counter: number; +}; diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/public-api.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/public-api.ts new file mode 100755 index 00000000000..a0c7e6ca2cf --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/public-api.ts @@ -0,0 +1,31 @@ +import * as OpenApiJson from "../json/openapi.json"; +export { OpenApiJson }; + +export { + GetConsortiumEndpointV1, + IGetConsortiumJwsEndpointOptions, +} from "./consortium/get-consortium-jws-endpoint-v1"; + +export { + GetNodeJwsEndpoint, + IGetNodeJwsEndpointOptions, +} from "./consortium/get-node-jws-endpoint-v1"; + +export { + PluginConsortiumStatic, + IPluginConsortiumStaticOptions, + IWebAppOptions, +} from "./plugin-consortium-static"; + +export * from "./generated/openapi/typescript-axios/index"; + +export { PluginFactoryWebService } from "./plugin-factory-consortium-static"; + +import { IPluginFactoryOptions } from "@hyperledger/cactus-core-api"; +import { PluginFactoryWebService } from "./plugin-factory-consortium-static"; + +export async function createPluginFactory( + pluginFactoryOptions: IPluginFactoryOptions, +): Promise { + return new PluginFactoryWebService(pluginFactoryOptions); +} diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/repository/static-consortium-provider.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/repository/static-consortium-provider.ts new file mode 100644 index 00000000000..9775ad5c424 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/repository/static-consortium-provider.ts @@ -0,0 +1,72 @@ +import { + Logger, + LogLevelDesc, + LoggerProvider, +} from "@hyperledger/cactus-common"; + +import { Checks, IAsyncProvider } from "@hyperledger/cactus-common"; +import { ConsortiumDatabase } from "@hyperledger/cactus-core-api"; + +import { + DefaultApi as ConsortiumStaticApi, + GetConsortiumJwsResponse, +} from "../generated/openapi/typescript-axios/api"; + +export interface IStaticConsortiumProviderOptions { + logLevel?: LogLevelDesc; + apiClient: ConsortiumStaticApi; +} + +export class StaticConsortiumProvider + implements IAsyncProvider +{ + public static readonly CLASS_NAME = "StaticConsortiumProvider"; + + private readonly log: Logger; + + public get className(): string { + return StaticConsortiumProvider.CLASS_NAME; + } + + constructor(public readonly options: IStaticConsortiumProviderOptions) { + const fnTag = `${this.className}#constructor()`; + Checks.truthy(options, `${fnTag} arg options`); + + const level = this.options.logLevel || "INFO"; + const label = this.className; + this.log = LoggerProvider.getOrCreate({ level, label }); + } + + parseConsortiumJws(response: GetConsortiumJwsResponse): ConsortiumDatabase { + const fnTag = `StaticConsortiumProvider#parseConsortiumJws()`; + + Checks.truthy(response, `${fnTag}::response`); + Checks.truthy(response.jws, `${fnTag}::response.jws`); + Checks.truthy(response.jws.payload, `${fnTag}::response.jws.payload`); + + const json = Buffer.from(response.jws.payload, "base64").toString(); + const body = JSON.parse(json); + const { consortiumDatabase }: { consortiumDatabase: ConsortiumDatabase } = + body; + + Checks.truthy(consortiumDatabase, `${fnTag}::consortiumDatabase`); + + // FIXME Ideally there would be an option here to validate the JWS based on + // all the signatures and the corresponding public keys (which the caller + // would have to be able to supply). + // We do not yet have this crypto functions available in a cross platform + // manner so it is omitted for now but much needed prior to any GA release. + return consortiumDatabase; + } + + public async get(): Promise { + try { + const res = await this.options.apiClient.getConsortiumJwsV1(); + return this.parseConsortiumJws(res.data); + } catch (ex) { + const innerException = (ex.toJSON && ex.toJSON()) || ex; + this.log.error(`Request for Consortium JWS failed: `, innerException); + throw ex; + } + } +} diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/repository/static-consortium-repository.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/repository/static-consortium-repository.ts new file mode 100644 index 00000000000..b75925af74b --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/repository/static-consortium-repository.ts @@ -0,0 +1,199 @@ +import { + Logger, + Checks, + LogLevelDesc, + LoggerProvider, +} from "@hyperledger/cactus-common"; + +import { + CactusNode, + ConsortiumDatabase, + ICactusPluginOptions, + Ledger, + PluginInstance, +} from "@hyperledger/cactus-core-api"; +import { PolicyGroup } from "../policy-model/policy-group"; +import MerkleTree from "merkletreejs"; +import { JWK } from "jose"; +import { verifyOrganization } from "../utils"; + +export interface IStaticConsortiumRepositoryOptions { + logLevel?: LogLevelDesc; + db: ConsortiumDatabase; + entitiesJWK: { [key: string]: JWK }; + rootPolicyGroup?: PolicyGroup; + packageConfigs?: { [key: string]: unknown }; + + //data about self + node: CactusNode; + ledgers: Ledger[]; + pluginInstances: PluginInstance[]; + memberId: string; +} + +/** + * Class responsible for making it convenient for developers to query the + * `ConsortiumDatabase` model type which is a flat data structure storing + * all the different types of entities for Consortium representation such as + * `CactusNode`, `ConsortiumMember`, `Ledger` etc.. + */ +export class StaticConsortiumRepository { + public static readonly CLASS_NAME = "StaticConsortiumRepository"; + + private readonly log: Logger; + private readonly db: ConsortiumDatabase; + + //data about self + private readonly node: CactusNode; + private readonly ledgers: Ledger[]; + private readonly pluginInstances: PluginInstance[]; + private readonly memberId: string; + + private readonly rootPolicyGroup: PolicyGroup | undefined; + + // map of package names to configs + // The idea is that we can assert configurations (security, etc) of some essential packages + // Possibly in the future we may want to share them (?) + private readonly packageConfigs: Map; + + private readonly entitiesJWK: Map; + + public get className(): string { + return StaticConsortiumRepository.CLASS_NAME; + } + + constructor(public readonly options: IStaticConsortiumRepositoryOptions) { + const fnTag = `${this.className}#constructor()`; + Checks.truthy(options, `${fnTag} arg options`); + Checks.truthy(options.db, `${fnTag} arg options.db`); + Checks.truthy(options.db.cactusNode, `${fnTag} arg options.db.cactusNode`); + this.db = options.db; + + const level = this.options.logLevel || "INFO"; + const label = this.className; + this.log = LoggerProvider.getOrCreate({ level, label }); + + this.node = options.node; + this.ledgers = options.ledgers; + this.pluginInstances = options.pluginInstances; + this.memberId = options.memberId; + + this.rootPolicyGroup = options.rootPolicyGroup; + + this.packageConfigs = new Map(); + if (options.packageConfigs) { + for (const config in options.packageConfigs) { + if (!this.packageConfigs.get(config)) { + //unique configs for each package name + this.packageConfigs.set(config, options.packageConfigs[config]); + } + } + } + + //this map stores the JWK of each entity that belongs to the consortium + //the map cannot be updated (we do not add organizations) + this.entitiesJWK = new Map(); + for (const entity in options.entitiesJWK) { + if (!this.entitiesJWK.get(entity)) { + //unique jwk for each entity + this.entitiesJWK.set(entity, options.entitiesJWK[entity]); + } + } + } + + public get consortiumDatabase(): ConsortiumDatabase { + return this.options.db; + } + + public get allNodes(): CactusNode[] { + return this.options.db.cactusNode; + } + + public getPolicyTreeProof(): string { + if (!this.rootPolicyGroup) { + return ""; + } + return this.rootPolicyGroup.buildTreeProof(); + } + public getConfigsProof(): string { + if (this.packageConfigs.size === 0) { + return ""; + } + return new MerkleTree( + Array.from(this.packageConfigs.entries()), + undefined, + { + sort: true, + hashLeaves: true, + }, + ) + .getRoot() + .toString("hex"); + } + + /** + * Queries the complete list of nodes within the consortium to obtain a sub- + * set of `CactusNode`s which are connected to a `Ledger` with the given + * `ledgerId`. + * @param ledgerId The ID of the ledger to filter nodes based on. + * @throws {Error} If `ledgerId` is falsy or blank. + */ + public nodesWithLedger(ledgerId: string): CactusNode[] { + const fnTag = `${this.className}#nodesWithLedger()`; + Checks.nonBlankString(ledgerId, `${fnTag}:ledgerId`); + + return this.allNodes.filter((cn) => cn.ledgerIds.includes(ledgerId)); + } + public addNode( + node: CactusNode, + pluginInstance: PluginInstance[], + ledger: Ledger[], + ) { + const member = this.db.consortiumMember.find((m) => m.id === node.memberId); + if (!member) { + throw new Error( + "New node does not belong to an organization of this consortium", + ); + } + this.db.cactusNode.push(node); + this.db.pluginInstance.push(...pluginInstance); + this.db.ledger.push(...ledger); + member.nodeIds.push(node.id); + } + + public populateDb(newDb: ConsortiumDatabase) { + this.db.cactusNode = newDb.cactusNode; + this.db.consortium = newDb.consortium; + this.db.consortiumMember = newDb.consortiumMember; + this.db.ledger = newDb.ledger; + this.db.pluginInstance = newDb.pluginInstance; + } + + public getSelfData() { + return { + node: this.node, + ledgers: this.ledgers, + pluginInstances: this.pluginInstances, + memberId: this.memberId, + }; + } + + public async verifyJWT(jwt: string, memberId: string): Promise { + const fn = this.className + "#verifyJWT"; + const jwk = this.entitiesJWK.get(memberId); + const member = this.db.consortiumMember.find((member) => { + return member.id === memberId; + }); + if (!jwk || !member) { + this.log.debug( + fn + ": memberID:" + memberId + "is not part of this consortium.", + ); + return false; + } + const result = await verifyOrganization(jwt, jwk, member.name); + if (typeof result === "string") { + throw new Error(fn + result); + } + return result; + } +} diff --git a/packages/cacti-plugin-consortium-static/src/main/typescript/utils.ts b/packages/cacti-plugin-consortium-static/src/main/typescript/utils.ts new file mode 100644 index 00000000000..fae90251b03 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/main/typescript/utils.ts @@ -0,0 +1,91 @@ +import { + generateKeyPair, + exportJWK, + jwtVerify, + importJWK, + JWK, + SignJWT, + KeyLike, +} from "jose"; +import { stringify as safeStableStringify } from "safe-stable-stringify"; + +import { v4 as uuidv4 } from "uuid"; + +export async function generateES256JWK(): Promise<{ pub: JWK; priv: JWK }> { + // Generate an ES256 (Elliptic Curve using P-256) key pair + const { publicKey, privateKey } = await generateKeyPair("ES256K"); + + // Export the public key as a JWK + const publicJWK: JWK = await exportJWK(publicKey); + + // Export the private key as a JWK + const privateJWK: JWK = await exportJWK(privateKey); + + return { pub: publicJWK, priv: privateJWK }; +} + +export async function verifyOrganization( + token: string, + jwk: JWK, + expectedOrganization: string, +): Promise { + try { + // Import the JWK as a public key + const publicKey: Uint8Array | KeyLike = await importJWK(jwk, "ES256K"); + + // Verify the JWT using the public key + const { payload } = await jwtVerify(token, publicKey); + + // Check if the organization name matches + if (payload.iss !== expectedOrganization) { + return false; + } + + //TODO: verify payload.jti against remote log of the organization. + if (!payload.exp) { + return "Your token does not have an expiration date."; + } + if (payload.exp < Date.now()) { + return "The token has expired"; + } + + return true; + } catch (err) { + console.error(err); + return false; + } +} + +interface TokenPayload { + iss: string; // Issuer (e.g., the issuing authority) + exp: number; // Expiration time (UNIX timestamp) + jti?: string; // id of token +} +export async function issueOrgToken( + jwk: JWK, + parameters: TokenPayload, + memberId: string, + pubKey: string, +): Promise { + // Import the JWK to get the key object + const key = await importJWK(jwk, "ES256K"); + const payloadObject = { pubKey, memberId }; + const payload = safeStableStringify(payloadObject); + const encoder = new TextEncoder(); + const data = encoder.encode(payload); + const _protected = { + iat: Date.now(), + jti: parameters.jti ? parameters.jti : uuidv4(), + iss: parameters.iss, + exp: parameters.exp, + }; + // Create and sign the JWT + const jwt = await new SignJWT({ data: Array.from(data) }) + .setProtectedHeader({ alg: "ES256K", typ: "JWT" }) // Set the algorithm and token type + .setExpirationTime(_protected.exp) + .setIssuer(_protected.iss) + .setJti(_protected.jti) + .setIssuedAt(_protected.iat) + .sign(key); // Sign the JWT with the JWK + return jwt; +} diff --git a/packages/cacti-plugin-consortium-static/src/test/typescript/integration/api-routing-node-to-node.test.ts b/packages/cacti-plugin-consortium-static/src/test/typescript/integration/api-routing-node-to-node.test.ts new file mode 100644 index 00000000000..909f17ef101 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/test/typescript/integration/api-routing-node-to-node.test.ts @@ -0,0 +1,396 @@ +import { AddressInfo } from "net"; + +import "jest-extended"; +import { v4 as uuidV4 } from "uuid"; +import { generateKeyPair, exportSPKI, exportPKCS8 } from "jose"; +import Web3 from "web3"; + +import { ApiClient } from "@hyperledger/cactus-api-client"; +import { + ApiServer, + AuthorizationProtocol, + ConfigService, +} from "@hyperledger/cactus-cmd-api-server"; +import { + CactusNode, + Configuration, + Consortium, + ConsortiumDatabase, + ConsortiumMember, + Ledger, + LedgerType, +} from "@hyperledger/cactus-core-api"; +import { PluginRegistry } from "@hyperledger/cactus-core"; +import { DefaultApi as ConsortiumStaticApi } from "../../../main/typescript"; +import { + DefaultApi as BesuApi, + PluginLedgerConnectorBesu, + ReceiptType, + Web3SigningCredentialType, +} from "@hyperledger/cactus-plugin-ledger-connector-besu"; +import { + pruneDockerAllIfGithubAction, + BesuTestLedger, +} from "@hyperledger/cactus-test-tooling"; +import { LogLevelDesc, Servers } from "@hyperledger/cactus-common"; + +import { Account } from "web3-core"; +import { + IPluginConsortiumStaticOptions, + PluginConsortiumStatic, +} from "../../../main/typescript"; +import { StaticConsortiumProvider } from "../../../main/typescript/repository/static-consortium-provider"; +import { + generateES256JWK, + issueOrgToken, +} from "../../../main/typescript/utils"; + +const logLevel: LogLevelDesc = "TRACE"; +const testCase = "Routes to correct node based on ledger ID"; +const testCase1 = "Set Up Test ledgers, Consortium, Cactus Nodes"; +const testCase2 = "ApiClient #1 Routes based on Ledger ID #1"; +const testCase3 = "ApiClient #1 Routes based on Ledger ID #2"; + +describe(testCase, () => { + const besuTestLedger1 = new BesuTestLedger(); + const besuTestLedger2 = new BesuTestLedger(); + let consortiumDatabase: ConsortiumDatabase; + let mainApiClient: ApiClient; + + let initialFundsAccount1: string; + let initialFundsAccount2: string; + let keyPair1: any; + let keyPair2: any; + let addressInfo1: AddressInfo; + let addressInfo2: AddressInfo; + let httpServer1: any; + let httpServer2: any; + + let node1: CactusNode; + let node2: CactusNode; + let consortium: Consortium; + let member1: ConsortiumMember; + let member2: ConsortiumMember; + + let apiServer1: ApiServer; + let apiServer2: ApiServer; + let testEthAccount1: Account; + + let entitiesJWK: any; + let entity1JWK: any; + let entity2JWK: any; + + const ledger1: Ledger = { + id: "my_cool_ledger_that_i_want_to_transact_on", + ledgerType: LedgerType.Besu2X, + }; + const ledger2: Ledger = { + id: "other_ledger_that_is_just_taking_up_space", + ledgerType: LedgerType.Besu2X, + }; + + beforeAll(async () => { + const pruning = pruneDockerAllIfGithubAction({ logLevel }); + await expect(pruning).resolves.toBeTruthy; + }); + + beforeAll(async () => { + await besuTestLedger1.start(); + await besuTestLedger2.start(); + + testEthAccount1 = await besuTestLedger1.createEthTestAccount(); + + httpServer1 = await Servers.startOnPreferredPort(4050); + addressInfo1 = httpServer1.address() as AddressInfo; + const node1Host = `http://${addressInfo1.address}:${addressInfo1.port}`; + + httpServer2 = await Servers.startOnPreferredPort(4100); + addressInfo2 = httpServer2.address() as AddressInfo; + const node2Host = `http://${addressInfo2.address}:${addressInfo2.port}`; + + keyPair1 = await generateKeyPair("ES256K"); + const pubKeyPem1 = await exportSPKI(keyPair1.publicKey); + + keyPair2 = await generateKeyPair("ES256K"); + const pubKeyPem2 = await exportSPKI(keyPair2.publicKey); + + const consortiumId = uuidV4(); + const consortiumName = "Example Corp. & Friends Crypto Consortium"; + const memberId1 = uuidV4(); + const memberId2 = uuidV4(); + + node1 = { + nodeApiHost: node1Host, + publicKeyPem: pubKeyPem1, + consortiumId, + id: uuidV4(), + ledgerIds: [ledger1.id], + memberId: memberId1, + pluginInstanceIds: [], + }; + + member1 = { + id: memberId1, + name: "Example Corp 1", + nodeIds: [node1.id], + }; + entity1JWK = await generateES256JWK(); + + node2 = { + nodeApiHost: node2Host, + publicKeyPem: pubKeyPem2, + consortiumId, + id: uuidV4(), + ledgerIds: [ledger2.id], + memberId: memberId2, + pluginInstanceIds: [], + }; + + member2 = { + id: memberId2, + name: "Example Corp 2", + nodeIds: [], + }; + + entity2JWK = await generateES256JWK(); + entitiesJWK = { [memberId1]: entity1JWK.pub, [memberId2]: entity2JWK.pub }; + consortium = { + id: consortiumId, + mainApiHost: node1Host, + name: consortiumName, + memberIds: [member1.id, member2.id], + }; + + consortiumDatabase = { + cactusNode: [node1], + consortium: [consortium], + consortiumMember: [member1, member2], + ledger: [ledger1], + pluginInstance: [], + }; + + const config = new Configuration({ basePath: consortium.mainApiHost }); + mainApiClient = new ApiClient(config); + }); + + afterAll(async () => { + await besuTestLedger1.stop(); + await besuTestLedger1.destroy(); + await besuTestLedger2.stop(); + await besuTestLedger2.destroy(); + await apiServer1.shutdown(); + await apiServer2.shutdown(); + await pruneDockerAllIfGithubAction({ logLevel }); + }); + + test(testCase1, async () => { + const rpcApiHttpHost1 = await besuTestLedger1.getRpcApiHttpHost(); + const rpcApiWsHost1 = await besuTestLedger1.getRpcApiWsHost(); + + initialFundsAccount1 = besuTestLedger1.getGenesisAccountPubKey(); + + const rpcApiHttpHost2 = await besuTestLedger2.getRpcApiHttpHost(); + const rpcApiWsHost2 = await besuTestLedger2.getRpcApiWsHost(); + + initialFundsAccount2 = besuTestLedger2.getGenesisAccountPubKey(); + + { + const pluginRegistry = new PluginRegistry({ plugins: [] }); + + const pluginBesuConnector = new PluginLedgerConnectorBesu({ + instanceId: uuidV4(), + rpcApiHttpHost: rpcApiHttpHost1, + rpcApiWsHost: rpcApiWsHost1, + logLevel, + pluginRegistry: new PluginRegistry(), + }); + + const keyPairPem = await exportPKCS8(keyPair1.privateKey); + const pub = await exportSPKI(keyPair2.publicKey); + console.log(pub); + + const options: IPluginConsortiumStaticOptions = { + instanceId: uuidV4(), + pluginRegistry, + keyPairPem: keyPairPem, + keyPairPub: pub, + consortiumDatabase: consortiumDatabase, + node: node1, + ledgers: [ledger1], + pluginInstances: [], + memberId: member1.id, + logLevel, + entitiesJWK, + }; + const pluginConsortiumStatic = new PluginConsortiumStatic(options); + + const configService = new ConfigService(); + const apiServerOptions = await configService.newExampleConfig(); + apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE; + apiServerOptions.configFile = ""; + apiServerOptions.apiCorsDomainCsv = "*"; + apiServerOptions.apiPort = addressInfo1.port; + apiServerOptions.cockpitPort = 0; + apiServerOptions.grpcPort = 0; + apiServerOptions.crpcPort = 0; + apiServerOptions.apiTlsEnabled = false; + apiServerOptions.crpcPort = 0; + const config = + await configService.newExampleConfigConvict(apiServerOptions); + + pluginRegistry.add(pluginConsortiumStatic); + pluginRegistry.add(pluginBesuConnector); + + apiServer1 = new ApiServer({ + httpServerApi: httpServer1, + config: config.getProperties(), + pluginRegistry, + }); + + await apiServer1.start(); + } + + { + const pluginRegistry = new PluginRegistry({ plugins: [] }); + + const pluginBesuConnector = new PluginLedgerConnectorBesu({ + instanceId: uuidV4(), + rpcApiHttpHost: rpcApiHttpHost2, + rpcApiWsHost: rpcApiWsHost2, + logLevel, + pluginRegistry: new PluginRegistry(), + }); + + const consortiumDatabase1 = { + cactusNode: [], + consortium: [], + consortiumMember: [], + ledger: [], + pluginInstance: [], + }; + + const keyPairPem = await exportPKCS8(keyPair2.privateKey); + const pub = await exportSPKI(keyPair2.publicKey); + console.log(pub); + const options: IPluginConsortiumStaticOptions = { + instanceId: uuidV4(), + pluginRegistry, + keyPairPem: keyPairPem, + keyPairPub: pub, + consortiumDatabase: consortiumDatabase1, + node: node2, + ledgers: [ledger2], + pluginInstances: [], + memberId: member2.id, + logLevel, + entitiesJWK, + }; + const pluginConsortiumStatic = new PluginConsortiumStatic(options); + + const configService = new ConfigService(); + const apiServerOptions = await configService.newExampleConfig(); + apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE; + apiServerOptions.configFile = ""; + apiServerOptions.apiCorsDomainCsv = "*"; + apiServerOptions.apiPort = addressInfo2.port; + apiServerOptions.cockpitPort = 0; + apiServerOptions.grpcPort = 0; + apiServerOptions.crpcPort = 0; + apiServerOptions.apiTlsEnabled = false; + apiServerOptions.plugins = []; + apiServerOptions.crpcPort = 0; + const config = + await configService.newExampleConfigConvict(apiServerOptions); + + pluginRegistry.add(pluginConsortiumStatic); + pluginRegistry.add(pluginBesuConnector); + + apiServer2 = new ApiServer({ + httpServerApi: httpServer2, + config: config.getProperties(), + pluginRegistry, + }); + + await apiServer2.start(); + + const consortApi = mainApiClient.extendWith(ConsortiumStaticApi); + //node asks to join consortium, not manual anymore + const jwt = await issueOrgToken( + entity2JWK.priv, + { + iss: member2.name, + exp: Date.now() + 5 * 60 * 1000, //expires in 5min + }, + member2.id, + pub, + ); + await pluginConsortiumStatic.joinConsortium(consortApi, jwt); + // test.onFinish(() => apiServer.shutdown()); + // afterAll(async () => await apiServer.shutdown()); + } + }); + test(testCase2, async () => { + const apiClient1 = await mainApiClient.ofLedger( + ledger1.id, + BesuApi, + {}, + new StaticConsortiumProvider({ + apiClient: mainApiClient.extendWith(ConsortiumStaticApi), + }), + ); + const testAccount1 = new Web3().eth.accounts.create(uuidV4()); + const res = await apiClient1.runTransactionV1({ + transactionConfig: { + from: initialFundsAccount1, + to: testAccount1.address, + value: 10e6, + gas: 1000000, + }, + consistencyStrategy: { + blockConfirmations: 0, + receiptType: ReceiptType.NodeTxPoolAck, + }, + web3SigningCredential: { + ethAccount: testEthAccount1.address, + secret: testEthAccount1.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + }); + + expect(res).toBeTruthy(); + expect(res.status).toBeGreaterThan(199); + expect(res.status).toBeLessThan(300); + }); + + test(testCase3, async () => { + const apiClient2 = await mainApiClient.ofLedger( + ledger2.id, + BesuApi, + {}, + new StaticConsortiumProvider({ + apiClient: mainApiClient.extendWith(ConsortiumStaticApi), + }), + ); + const testAccount2 = new Web3().eth.accounts.create(uuidV4()); + const res = await apiClient2.runTransactionV1({ + transactionConfig: { + from: initialFundsAccount2, + to: testAccount2.address, + value: 10e6, + gas: 1000000, + }, + consistencyStrategy: { + blockConfirmations: 0, + receiptType: ReceiptType.NodeTxPoolAck, + }, + web3SigningCredential: { + ethAccount: initialFundsAccount2, + secret: besuTestLedger2.getGenesisAccountPrivKey(), + type: Web3SigningCredentialType.PrivateKeyHex, + }, + }); + expect(res).toBeTruthy(); + expect(res.status).toBeGreaterThan(199); + expect(res.status).toBeLessThan(300); + }); +}); diff --git a/packages/cacti-plugin-consortium-static/src/test/typescript/integration/api-surface.test.ts b/packages/cacti-plugin-consortium-static/src/test/typescript/integration/api-surface.test.ts new file mode 100644 index 00000000000..34aba3a0aea --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/test/typescript/integration/api-surface.test.ts @@ -0,0 +1,6 @@ +import * as apiSurface from "../../../main/typescript/public-api"; +import "jest-extended"; + +test("Library can be loaded", async () => { + expect(apiSurface).toBeTruthy(); +}); diff --git a/packages/cacti-plugin-consortium-static/src/test/typescript/integration/api-test-new-node-broadcast-with-proofs.test.ts b/packages/cacti-plugin-consortium-static/src/test/typescript/integration/api-test-new-node-broadcast-with-proofs.test.ts new file mode 100644 index 00000000000..545e68aebe5 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/test/typescript/integration/api-test-new-node-broadcast-with-proofs.test.ts @@ -0,0 +1,510 @@ +import { AddressInfo } from "net"; + +import "jest-extended"; +import { v4 as uuidV4 } from "uuid"; +import { generateKeyPair, exportSPKI, exportPKCS8 } from "jose"; + +import { ApiClient } from "@hyperledger/cactus-api-client"; +import { + ApiServer, + AuthorizationProtocol, + ConfigService, +} from "@hyperledger/cactus-cmd-api-server"; +import { + CactusNode, + Configuration, + Consortium, + ConsortiumDatabase, + ConsortiumMember, + Ledger, + LedgerType, +} from "@hyperledger/cactus-core-api"; +import { PluginRegistry } from "@hyperledger/cactus-core"; +import { DefaultApi as ConsortiumStaticApi } from "../../../main/typescript"; +import { PluginLedgerConnectorBesu } from "@hyperledger/cactus-plugin-ledger-connector-besu"; +import { + pruneDockerAllIfGithubAction, + BesuTestLedger, +} from "@hyperledger/cactus-test-tooling"; +import { LogLevelDesc, Servers } from "@hyperledger/cactus-common"; + +import { + IPluginConsortiumStaticOptions, + PluginConsortiumStatic, +} from "../../../main/typescript"; +import { K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT } from "../../../main/typescript/prometheus-exporter/metrics"; +import { + IPolicyGroupOptions, + PolicyGroup, +} from "../../../main/typescript/policy-model/policy-group"; +import { + generateES256JWK, + issueOrgToken, +} from "../../../main/typescript/utils"; + +const logLevel: LogLevelDesc = "TRACE"; +const testCase = "Broadcasts new node request to all consortium"; +const testCase1 = "Set Up Test ledgers, Consortium, Cactus Nodes"; + +describe(testCase, () => { + const besuTestLedger1 = new BesuTestLedger(); + const besuTestLedger2 = new BesuTestLedger(); + let consortiumDatabase: ConsortiumDatabase; + let mainApiClient: ApiClient; + + let keyPair1: any; + let keyPair2: any; + let keyPair3: any; + let addressInfo1: AddressInfo; + let addressInfo2: AddressInfo; + let addressInfo3: AddressInfo; + let httpServer1: any; + let httpServer2: any; + let httpServer3: any; + + let node1: CactusNode; + let node2: CactusNode; + let node3: CactusNode; + let consortium: Consortium; + let member1: ConsortiumMember; + let member2: ConsortiumMember; + + let apiServer1: ApiServer; + let apiServer2: ApiServer; + let apiServer3: ApiServer; + + let pluginConsortiumStatic1: PluginConsortiumStatic; + let pluginConsortiumStatic2: PluginConsortiumStatic; + let pluginConsortiumStatic3: PluginConsortiumStatic; + + let entitiesJWK: any; + let entity1JWK: any; + let entity2JWK: any; + + const sourcePolicyOptions: IPolicyGroupOptions = { + role: "Base", + name: "Root Policy group", + caption: "P Root", + description: "This is a mock policy group with no use", + id: "someId", + }; + const secondPolicyOptions: IPolicyGroupOptions = { + role: "second", + name: "second Policy group", + caption: "lvl 2", + description: "This is a mock policy group with no use", + id: "someId2", + }; + const thirdPolicyOptions: IPolicyGroupOptions = { + role: "third", + name: "third Policy group", + caption: "lvl 3", + description: "This is a mock policy group with no use", + id: "someId3", + }; + const sourcePolicy1: PolicyGroup = new PolicyGroup(sourcePolicyOptions); + const sourcePolicy2: PolicyGroup = new PolicyGroup(sourcePolicyOptions); + const sourcePolicy3: PolicyGroup = new PolicyGroup(sourcePolicyOptions); + const secondPolicy1: PolicyGroup = new PolicyGroup(secondPolicyOptions); + const secondPolicy2: PolicyGroup = new PolicyGroup(secondPolicyOptions); + const secondPolicy3: PolicyGroup = new PolicyGroup(secondPolicyOptions); + const thirdPolicy1: PolicyGroup = new PolicyGroup(thirdPolicyOptions); + const thirdPolicy2: PolicyGroup = new PolicyGroup(thirdPolicyOptions); + const thirdPolicy3: PolicyGroup = new PolicyGroup(thirdPolicyOptions); + + secondPolicy1.addGroup(thirdPolicy1); + sourcePolicy1.addGroup(secondPolicy1); + + secondPolicy2.addGroup(thirdPolicy2); + sourcePolicy2.addGroup(secondPolicy2); + + secondPolicy3.addGroup(thirdPolicy3); + sourcePolicy3.addGroup(secondPolicy3); + + const packageConfigs = { + "@hyperledger/cactus-api-server": { + apiTlsEnabled: false, + }, + }; + + const ledger1: Ledger = { + id: "my_cool_ledger_that_i_want_to_transact_on", + ledgerType: LedgerType.Besu2X, + }; + const ledger2: Ledger = { + id: "other_ledger_that_is_just_taking_up_space", + ledgerType: LedgerType.Besu2X, + }; + + beforeAll(async () => { + const pruning = pruneDockerAllIfGithubAction({ logLevel }); + await expect(pruning).resolves.toBeTruthy; + }); + + beforeAll(async () => { + await besuTestLedger1.start(); + await besuTestLedger2.start(); + + httpServer1 = await Servers.startOnPreferredPort(4050); + addressInfo1 = httpServer1.address() as AddressInfo; + const node1Host = `http://${addressInfo1.address}:${addressInfo1.port}`; + + httpServer2 = await Servers.startOnPreferredPort(4100); + addressInfo2 = httpServer2.address() as AddressInfo; + const node2Host = `http://${addressInfo2.address}:${addressInfo2.port}`; + + httpServer3 = await Servers.startOnPreferredPort(4150); + addressInfo3 = httpServer2.address() as AddressInfo; + const node3Host = `http://${addressInfo2.address}:${addressInfo2.port}`; + + keyPair1 = await generateKeyPair("ES256K"); + const pubKeyPem1 = await exportSPKI(keyPair1.publicKey); + + keyPair2 = await generateKeyPair("ES256K"); + const pubKeyPem2 = await exportSPKI(keyPair2.publicKey); + + keyPair3 = await generateKeyPair("ES256K"); + const pubKeyPem3 = await exportSPKI(keyPair3.publicKey); + + const consortiumId = uuidV4(); + const consortiumName = "Example Corp. & Friends Crypto Consortium"; + const memberId1 = uuidV4(); + const memberId2 = uuidV4(); + + node1 = { + nodeApiHost: node1Host, + publicKeyPem: pubKeyPem1, + consortiumId, + id: uuidV4(), + ledgerIds: [ledger1.id], + memberId: memberId1, + pluginInstanceIds: [], + }; + + member1 = { + id: memberId1, + name: "Example Corp 1", + nodeIds: [node1.id], + }; + + entity1JWK = await generateES256JWK(); + + node2 = { + nodeApiHost: node2Host, + publicKeyPem: pubKeyPem2, + consortiumId, + id: uuidV4(), + ledgerIds: [ledger2.id], + memberId: memberId2, + pluginInstanceIds: [], + }; + + member2 = { + id: memberId2, + name: "Example Corp 2", + nodeIds: [], + }; + + entity2JWK = await generateES256JWK(); + entitiesJWK = { [memberId1]: entity1JWK.pub, [memberId2]: entity2JWK.pub }; + + node3 = { + nodeApiHost: node3Host, + publicKeyPem: pubKeyPem3, + consortiumId, + id: uuidV4(), + ledgerIds: [ledger2.id], + memberId: memberId2, + pluginInstanceIds: [], + }; + + consortium = { + id: consortiumId, + mainApiHost: node1Host, + name: consortiumName, + memberIds: [member1.id, member2.id], + }; + + consortiumDatabase = { + cactusNode: [node1], + consortium: [consortium], + consortiumMember: [member1, member2], + ledger: [ledger1], + pluginInstance: [], + }; + + const config = new Configuration({ basePath: consortium.mainApiHost }); + mainApiClient = new ApiClient(config); + }); + + afterAll(async () => { + await besuTestLedger1.stop(); + await besuTestLedger1.destroy(); + await besuTestLedger2.stop(); + await besuTestLedger2.destroy(); + await apiServer1.shutdown(); + await apiServer2.shutdown(); + await apiServer3.shutdown(); + await pruneDockerAllIfGithubAction({ logLevel }); + }); + + test(testCase1, async () => { + const rpcApiHttpHost1 = await besuTestLedger1.getRpcApiHttpHost(); + const rpcApiWsHost1 = await besuTestLedger1.getRpcApiWsHost(); + + const rpcApiHttpHost2 = await besuTestLedger2.getRpcApiHttpHost(); + const rpcApiWsHost2 = await besuTestLedger2.getRpcApiWsHost(); + + { + const pluginRegistry = new PluginRegistry({ plugins: [] }); + + const pluginBesuConnector = new PluginLedgerConnectorBesu({ + instanceId: uuidV4(), + rpcApiHttpHost: rpcApiHttpHost1, + rpcApiWsHost: rpcApiWsHost1, + logLevel, + pluginRegistry: new PluginRegistry(), + }); + + const keyPairPem = await exportPKCS8(keyPair1.privateKey); + const pub = await exportSPKI(keyPair1.publicKey); + + const options: IPluginConsortiumStaticOptions = { + instanceId: uuidV4(), + pluginRegistry, + keyPairPem: keyPairPem, + keyPairPub: pub, + consortiumDatabase: consortiumDatabase, + node: node1, + ledgers: [ledger1], + pluginInstances: [], + rootPolicyGroup: sourcePolicy1, + packageConfigs, + memberId: member1.id, + logLevel, + entitiesJWK, + }; + pluginConsortiumStatic1 = new PluginConsortiumStatic(options); + + const configService = new ConfigService(); + const apiServerOptions = await configService.newExampleConfig(); + apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE; + apiServerOptions.configFile = ""; + apiServerOptions.apiCorsDomainCsv = "*"; + apiServerOptions.apiPort = addressInfo1.port; + apiServerOptions.cockpitPort = 0; + apiServerOptions.grpcPort = 0; + apiServerOptions.crpcPort = 0; + apiServerOptions.apiTlsEnabled = false; + apiServerOptions.crpcPort = 0; + const config = + await configService.newExampleConfigConvict(apiServerOptions); + + pluginRegistry.add(pluginConsortiumStatic1); + pluginRegistry.add(pluginBesuConnector); + + apiServer1 = new ApiServer({ + httpServerApi: httpServer1, + config: config.getProperties(), + pluginRegistry, + }); + + await apiServer1.start(); + } + + { + const pluginRegistry = new PluginRegistry({ plugins: [] }); + + const pluginBesuConnector = new PluginLedgerConnectorBesu({ + instanceId: uuidV4(), + rpcApiHttpHost: rpcApiHttpHost2, + rpcApiWsHost: rpcApiWsHost2, + logLevel, + pluginRegistry: new PluginRegistry(), + }); + + const consortiumDatabase1 = { + cactusNode: [], + consortium: [], + consortiumMember: [], + ledger: [], + pluginInstance: [], + }; + + const keyPairPem = await exportPKCS8(keyPair2.privateKey); + const pub = await exportSPKI(keyPair2.publicKey); + + const options: IPluginConsortiumStaticOptions = { + instanceId: uuidV4(), + pluginRegistry, + keyPairPem: keyPairPem, + keyPairPub: pub, + consortiumDatabase: consortiumDatabase1, + node: node2, + ledgers: [ledger2], + rootPolicyGroup: sourcePolicy2, + packageConfigs, + pluginInstances: [], + memberId: member2.id, + logLevel, + entitiesJWK, + }; + pluginConsortiumStatic2 = new PluginConsortiumStatic(options); + + const configService = new ConfigService(); + const apiServerOptions = await configService.newExampleConfig(); + apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE; + apiServerOptions.configFile = ""; + apiServerOptions.apiCorsDomainCsv = "*"; + apiServerOptions.apiPort = addressInfo2.port; + apiServerOptions.cockpitPort = 0; + apiServerOptions.grpcPort = 0; + apiServerOptions.crpcPort = 0; + apiServerOptions.apiTlsEnabled = false; + apiServerOptions.plugins = []; + apiServerOptions.crpcPort = 0; + const config = + await configService.newExampleConfigConvict(apiServerOptions); + + pluginRegistry.add(pluginConsortiumStatic2); + pluginRegistry.add(pluginBesuConnector); + + apiServer2 = new ApiServer({ + httpServerApi: httpServer2, + config: config.getProperties(), + pluginRegistry, + }); + + await apiServer2.start(); + + const consortApi = mainApiClient.extendWith(ConsortiumStaticApi); + + const jwt = await issueOrgToken( + entity2JWK.priv, + { + iss: member2.name, + exp: Date.now() + 5 * 60 * 1000, //expires in 5min + }, + member2.id, + pub, + ); + await pluginConsortiumStatic2.joinConsortium(consortApi, jwt); + + const promMetricsOutput = + "# HELP " + + K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT + + " Total cactus node count\n" + + "# TYPE " + + K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT + + " gauge\n" + + K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT + + '{type="' + + K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT + + '"} 2'; + const res1 = await pluginConsortiumStatic1.getPrometheusExporterMetrics(); + const res2 = await pluginConsortiumStatic2.getPrometheusExporterMetrics(); + expect(res1).toEqual(promMetricsOutput); + expect(res2).toEqual(promMetricsOutput); + } + + { + const pluginRegistry = new PluginRegistry({ plugins: [] }); + + const pluginBesuConnector = new PluginLedgerConnectorBesu({ + instanceId: uuidV4(), + rpcApiHttpHost: rpcApiHttpHost2, + rpcApiWsHost: rpcApiWsHost2, + logLevel, + pluginRegistry: new PluginRegistry(), + }); + + const consortiumDatabase1 = { + cactusNode: [], + consortium: [], + consortiumMember: [], + ledger: [], + pluginInstance: [], + }; + + const keyPairPem = await exportPKCS8(keyPair3.privateKey); + const pub = await exportSPKI(keyPair3.publicKey); + + const options: IPluginConsortiumStaticOptions = { + instanceId: uuidV4(), + pluginRegistry, + keyPairPem: keyPairPem, + keyPairPub: pub, + consortiumDatabase: consortiumDatabase1, + node: node3, + rootPolicyGroup: sourcePolicy3, + packageConfigs, + ledgers: [ledger2], + pluginInstances: [], + memberId: member2.id, + logLevel, + entitiesJWK, + }; + pluginConsortiumStatic3 = new PluginConsortiumStatic(options); + + const configService = new ConfigService(); + const apiServerOptions = await configService.newExampleConfig(); + apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE; + apiServerOptions.configFile = ""; + apiServerOptions.apiCorsDomainCsv = "*"; + apiServerOptions.apiPort = addressInfo3.port; + apiServerOptions.cockpitPort = 0; + apiServerOptions.grpcPort = 0; + apiServerOptions.crpcPort = 0; + apiServerOptions.apiTlsEnabled = false; + apiServerOptions.plugins = []; + apiServerOptions.crpcPort = 0; + const config = + await configService.newExampleConfigConvict(apiServerOptions); + + pluginRegistry.add(pluginConsortiumStatic3); + pluginRegistry.add(pluginBesuConnector); + + apiServer3 = new ApiServer({ + httpServerApi: httpServer3, + config: config.getProperties(), + pluginRegistry, + }); + + await apiServer3.start(); + + const consortApi = mainApiClient.extendWith(ConsortiumStaticApi); + const jwt = await issueOrgToken( + entity2JWK.priv, + { + iss: member2.name, + exp: Date.now() + 5 * 60 * 1000, //expires in 5min + }, + member2.id, + pub, + ); + await pluginConsortiumStatic3.joinConsortium(consortApi, jwt); + } + { + //final test + const res1 = await pluginConsortiumStatic1.getPrometheusExporterMetrics(); + const res2 = await pluginConsortiumStatic2.getPrometheusExporterMetrics(); + const res3 = await pluginConsortiumStatic3.getPrometheusExporterMetrics(); + const promMetricsOutput = + "# HELP " + + K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT + + " Total cactus node count\n" + + "# TYPE " + + K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT + + " gauge\n" + + K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT + + '{type="' + + K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT + + '"} 3'; + + //all plugins have consortium updated + expect(res1.includes(promMetricsOutput)).toBeTruthy(); + expect(res2.includes(promMetricsOutput)).toBeTruthy(); + expect(res3.includes(promMetricsOutput)).toBeTruthy(); + } + }); +}); diff --git a/packages/cacti-plugin-consortium-static/src/test/typescript/integration/api-test-new-node-broadcast.test.ts b/packages/cacti-plugin-consortium-static/src/test/typescript/integration/api-test-new-node-broadcast.test.ts new file mode 100644 index 00000000000..d4407077347 --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/test/typescript/integration/api-test-new-node-broadcast.test.ts @@ -0,0 +1,452 @@ +import { AddressInfo } from "net"; + +import "jest-extended"; +import { v4 as uuidV4 } from "uuid"; +import { generateKeyPair, exportSPKI, exportPKCS8 } from "jose"; + +import { ApiClient } from "@hyperledger/cactus-api-client"; +import { + ApiServer, + AuthorizationProtocol, + ConfigService, +} from "@hyperledger/cactus-cmd-api-server"; +import { + CactusNode, + Configuration, + Consortium, + ConsortiumDatabase, + ConsortiumMember, + Ledger, + LedgerType, +} from "@hyperledger/cactus-core-api"; +import { PluginRegistry } from "@hyperledger/cactus-core"; +import { DefaultApi as ConsortiumStaticApi } from "../../../main/typescript"; +import { PluginLedgerConnectorBesu } from "@hyperledger/cactus-plugin-ledger-connector-besu"; +import { + pruneDockerAllIfGithubAction, + BesuTestLedger, +} from "@hyperledger/cactus-test-tooling"; +import { LogLevelDesc, Servers } from "@hyperledger/cactus-common"; + +import { + IPluginConsortiumStaticOptions, + PluginConsortiumStatic, +} from "../../../main/typescript"; +import { K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT } from "../../../main/typescript/prometheus-exporter/metrics"; +import { + generateES256JWK, + issueOrgToken, +} from "../../../main/typescript/utils"; + +const logLevel: LogLevelDesc = "TRACE"; +const testCase = "Broadcasts new node request to all consortium"; +const testCase1 = "Set Up Test ledgers, Consortium, Cactus Nodes"; + +describe(testCase, () => { + const besuTestLedger1 = new BesuTestLedger(); + const besuTestLedger2 = new BesuTestLedger(); + let consortiumDatabase: ConsortiumDatabase; + let mainApiClient: ApiClient; + + let keyPair1: any; + let keyPair2: any; + let keyPair3: any; + let addressInfo1: AddressInfo; + let addressInfo2: AddressInfo; + let addressInfo3: AddressInfo; + let httpServer1: any; + let httpServer2: any; + let httpServer3: any; + + let node1: CactusNode; + let node2: CactusNode; + let node3: CactusNode; + let consortium: Consortium; + let member1: ConsortiumMember; + let member2: ConsortiumMember; + + let apiServer1: ApiServer; + let apiServer2: ApiServer; + let apiServer3: ApiServer; + + let pluginConsortiumStatic1: PluginConsortiumStatic; + let pluginConsortiumStatic2: PluginConsortiumStatic; + let pluginConsortiumStatic3: PluginConsortiumStatic; + + let entitiesJWK: any; + let entity1JWK: any; + let entity2JWK: any; + + const ledger1: Ledger = { + id: "my_cool_ledger_that_i_want_to_transact_on", + ledgerType: LedgerType.Besu2X, + }; + const ledger2: Ledger = { + id: "other_ledger_that_is_just_taking_up_space", + ledgerType: LedgerType.Besu2X, + }; + + beforeAll(async () => { + const pruning = pruneDockerAllIfGithubAction({ logLevel }); + await expect(pruning).resolves.toBeTruthy; + }); + + beforeAll(async () => { + await besuTestLedger1.start(); + await besuTestLedger2.start(); + + httpServer1 = await Servers.startOnPreferredPort(4050); + addressInfo1 = httpServer1.address() as AddressInfo; + const node1Host = `http://${addressInfo1.address}:${addressInfo1.port}`; + + httpServer2 = await Servers.startOnPreferredPort(4100); + addressInfo2 = httpServer2.address() as AddressInfo; + const node2Host = `http://${addressInfo2.address}:${addressInfo2.port}`; + + httpServer3 = await Servers.startOnPreferredPort(4150); + addressInfo3 = httpServer2.address() as AddressInfo; + const node3Host = `http://${addressInfo2.address}:${addressInfo2.port}`; + + keyPair1 = await generateKeyPair("ES256K"); + const pubKeyPem1 = await exportSPKI(keyPair1.publicKey); + + keyPair2 = await generateKeyPair("ES256K"); + const pubKeyPem2 = await exportSPKI(keyPair2.publicKey); + + keyPair3 = await generateKeyPair("ES256K"); + const pubKeyPem3 = await exportSPKI(keyPair3.publicKey); + + const consortiumId = uuidV4(); + const consortiumName = "Example Corp. & Friends Crypto Consortium"; + const memberId1 = uuidV4(); + const memberId2 = uuidV4(); + + node1 = { + nodeApiHost: node1Host, + publicKeyPem: pubKeyPem1, + consortiumId, + id: uuidV4(), + ledgerIds: [ledger1.id], + memberId: memberId1, + pluginInstanceIds: [], + }; + + member1 = { + id: memberId1, + name: "Example Corp 1", + nodeIds: [node1.id], + }; + entity1JWK = await generateES256JWK(); + + node2 = { + nodeApiHost: node2Host, + publicKeyPem: pubKeyPem2, + consortiumId, + id: uuidV4(), + ledgerIds: [ledger2.id], + memberId: memberId2, + pluginInstanceIds: [], + }; + + member2 = { + id: memberId2, + name: "Example Corp 2", + nodeIds: [], + }; + entity2JWK = await generateES256JWK(); + entitiesJWK = { [memberId1]: entity1JWK.pub, [memberId2]: entity2JWK.pub }; + + node3 = { + nodeApiHost: node3Host, + publicKeyPem: pubKeyPem3, + consortiumId, + id: uuidV4(), + ledgerIds: [ledger2.id], + memberId: memberId2, + pluginInstanceIds: [], + }; + + consortium = { + id: consortiumId, + mainApiHost: node1Host, + name: consortiumName, + memberIds: [member1.id, member2.id], + }; + + consortiumDatabase = { + cactusNode: [node1], + consortium: [consortium], + consortiumMember: [member1, member2], + ledger: [ledger1], + pluginInstance: [], + }; + + const config = new Configuration({ basePath: consortium.mainApiHost }); + mainApiClient = new ApiClient(config); + }); + + afterAll(async () => { + await besuTestLedger1.stop(); + await besuTestLedger1.destroy(); + await besuTestLedger2.stop(); + await besuTestLedger2.destroy(); + await apiServer1.shutdown(); + await apiServer2.shutdown(); + await apiServer3.shutdown(); + await pruneDockerAllIfGithubAction({ logLevel }); + }); + + test(testCase1, async () => { + const rpcApiHttpHost1 = await besuTestLedger1.getRpcApiHttpHost(); + const rpcApiWsHost1 = await besuTestLedger1.getRpcApiWsHost(); + + const rpcApiHttpHost2 = await besuTestLedger2.getRpcApiHttpHost(); + const rpcApiWsHost2 = await besuTestLedger2.getRpcApiWsHost(); + + { + const pluginRegistry = new PluginRegistry({ plugins: [] }); + + const pluginBesuConnector = new PluginLedgerConnectorBesu({ + instanceId: uuidV4(), + rpcApiHttpHost: rpcApiHttpHost1, + rpcApiWsHost: rpcApiWsHost1, + logLevel, + pluginRegistry: new PluginRegistry(), + }); + + const keyPairPem = await exportPKCS8(keyPair1.privateKey); + const pub = await exportSPKI(keyPair1.publicKey); + + const options: IPluginConsortiumStaticOptions = { + instanceId: uuidV4(), + pluginRegistry, + keyPairPem: keyPairPem, + keyPairPub: pub, + consortiumDatabase: consortiumDatabase, + node: node1, + ledgers: [ledger1], + pluginInstances: [], + memberId: member1.id, + logLevel, + entitiesJWK, + }; + pluginConsortiumStatic1 = new PluginConsortiumStatic(options); + + const configService = new ConfigService(); + const apiServerOptions = await configService.newExampleConfig(); + apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE; + apiServerOptions.configFile = ""; + apiServerOptions.apiCorsDomainCsv = "*"; + apiServerOptions.apiPort = addressInfo1.port; + apiServerOptions.cockpitPort = 0; + apiServerOptions.grpcPort = 0; + apiServerOptions.crpcPort = 0; + apiServerOptions.apiTlsEnabled = false; + apiServerOptions.crpcPort = 0; + const config = + await configService.newExampleConfigConvict(apiServerOptions); + + pluginRegistry.add(pluginConsortiumStatic1); + pluginRegistry.add(pluginBesuConnector); + + apiServer1 = new ApiServer({ + httpServerApi: httpServer1, + config: config.getProperties(), + pluginRegistry, + }); + + await apiServer1.start(); + } + + { + const pluginRegistry = new PluginRegistry({ plugins: [] }); + + const pluginBesuConnector = new PluginLedgerConnectorBesu({ + instanceId: uuidV4(), + rpcApiHttpHost: rpcApiHttpHost2, + rpcApiWsHost: rpcApiWsHost2, + logLevel, + pluginRegistry: new PluginRegistry(), + }); + + const consortiumDatabase1 = { + cactusNode: [], + consortium: [], + consortiumMember: [], + ledger: [], + pluginInstance: [], + }; + + const keyPairPem = await exportPKCS8(keyPair2.privateKey); + const pub = await exportSPKI(keyPair2.publicKey); + + const options: IPluginConsortiumStaticOptions = { + instanceId: uuidV4(), + pluginRegistry, + keyPairPem: keyPairPem, + keyPairPub: pub, + consortiumDatabase: consortiumDatabase1, + node: node2, + ledgers: [ledger2], + pluginInstances: [], + memberId: member2.id, + logLevel, + entitiesJWK, + }; + pluginConsortiumStatic2 = new PluginConsortiumStatic(options); + + const configService = new ConfigService(); + const apiServerOptions = await configService.newExampleConfig(); + apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE; + apiServerOptions.configFile = ""; + apiServerOptions.apiCorsDomainCsv = "*"; + apiServerOptions.apiPort = addressInfo2.port; + apiServerOptions.cockpitPort = 0; + apiServerOptions.grpcPort = 0; + apiServerOptions.crpcPort = 0; + apiServerOptions.apiTlsEnabled = false; + apiServerOptions.plugins = []; + apiServerOptions.crpcPort = 0; + const config = + await configService.newExampleConfigConvict(apiServerOptions); + + pluginRegistry.add(pluginConsortiumStatic2); + pluginRegistry.add(pluginBesuConnector); + + apiServer2 = new ApiServer({ + httpServerApi: httpServer2, + config: config.getProperties(), + pluginRegistry, + }); + + await apiServer2.start(); + + const consortApi = mainApiClient.extendWith(ConsortiumStaticApi); + const jwt = await issueOrgToken( + entity2JWK.priv, + { + iss: member2.name, + exp: Date.now() + 5 * 60 * 1000, //expires in 5min + }, + member2.id, + pub, + ); + await pluginConsortiumStatic2.joinConsortium(consortApi, jwt); + // test.onFinish(() => apiServer.shutdown()); + // afterAll(async () => await apiServer.shutdown()); + const promMetricsOutput = + "# HELP " + + K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT + + " Total cactus node count\n" + + "# TYPE " + + K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT + + " gauge\n" + + K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT + + '{type="' + + K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT + + '"} 2'; + const res1 = await pluginConsortiumStatic1.getPrometheusExporterMetrics(); + const res2 = await pluginConsortiumStatic2.getPrometheusExporterMetrics(); + expect(res1).toEqual(promMetricsOutput); + expect(res2).toEqual(promMetricsOutput); + } + + { + const pluginRegistry = new PluginRegistry({ plugins: [] }); + + const pluginBesuConnector = new PluginLedgerConnectorBesu({ + instanceId: uuidV4(), + rpcApiHttpHost: rpcApiHttpHost2, + rpcApiWsHost: rpcApiWsHost2, + logLevel, + pluginRegistry: new PluginRegistry(), + }); + + const consortiumDatabase1 = { + cactusNode: [], + consortium: [], + consortiumMember: [], + ledger: [], + pluginInstance: [], + }; + + const keyPairPem = await exportPKCS8(keyPair3.privateKey); + const pub = await exportSPKI(keyPair3.publicKey); + + const options: IPluginConsortiumStaticOptions = { + instanceId: uuidV4(), + pluginRegistry, + keyPairPem: keyPairPem, + keyPairPub: pub, + consortiumDatabase: consortiumDatabase1, + node: node3, + ledgers: [ledger2], + pluginInstances: [], + memberId: member2.id, + logLevel, + entitiesJWK, + }; + pluginConsortiumStatic3 = new PluginConsortiumStatic(options); + + const configService = new ConfigService(); + const apiServerOptions = await configService.newExampleConfig(); + apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE; + apiServerOptions.configFile = ""; + apiServerOptions.apiCorsDomainCsv = "*"; + apiServerOptions.apiPort = addressInfo3.port; + apiServerOptions.cockpitPort = 0; + apiServerOptions.grpcPort = 0; + apiServerOptions.crpcPort = 0; + apiServerOptions.apiTlsEnabled = false; + apiServerOptions.plugins = []; + apiServerOptions.crpcPort = 0; + const config = + await configService.newExampleConfigConvict(apiServerOptions); + + pluginRegistry.add(pluginConsortiumStatic3); + pluginRegistry.add(pluginBesuConnector); + + apiServer3 = new ApiServer({ + httpServerApi: httpServer3, + config: config.getProperties(), + pluginRegistry, + }); + + await apiServer3.start(); + + const consortApi = mainApiClient.extendWith(ConsortiumStaticApi); + const jwt = await issueOrgToken( + entity2JWK.priv, + { + iss: member2.name, + exp: Date.now() + 5 * 60 * 1000, //expires in 5min + }, + member2.id, + pub, + ); + await pluginConsortiumStatic3.joinConsortium(consortApi, jwt); + } + { + //final test + const res1 = await pluginConsortiumStatic1.getPrometheusExporterMetrics(); + const res2 = await pluginConsortiumStatic2.getPrometheusExporterMetrics(); + const res3 = await pluginConsortiumStatic3.getPrometheusExporterMetrics(); + const promMetricsOutput = + "# HELP " + + K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT + + " Total cactus node count\n" + + "# TYPE " + + K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT + + " gauge\n" + + K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT + + '{type="' + + K_CACTUS_CONSORTIUM_MANUAL_TOTAL_NODE_COUNT + + '"} 3'; + + //all plugins have consortium updated + expect(res1.includes(promMetricsOutput)).toBeTruthy(); + expect(res2.includes(promMetricsOutput)).toBeTruthy(); + expect(res3.includes(promMetricsOutput)).toBeTruthy(); + } + }); +}); diff --git a/packages/cacti-plugin-consortium-static/src/test/typescript/unit/api-surface.test.ts b/packages/cacti-plugin-consortium-static/src/test/typescript/unit/api-surface.test.ts new file mode 100644 index 00000000000..34aba3a0aea --- /dev/null +++ b/packages/cacti-plugin-consortium-static/src/test/typescript/unit/api-surface.test.ts @@ -0,0 +1,6 @@ +import * as apiSurface from "../../../main/typescript/public-api"; +import "jest-extended"; + +test("Library can be loaded", async () => { + expect(apiSurface).toBeTruthy(); +}); diff --git a/packages/cacti-plugin-consortium-static/tsconfig.json b/packages/cacti-plugin-consortium-static/tsconfig.json new file mode 100644 index 00000000000..c47050d1c6a --- /dev/null +++ b/packages/cacti-plugin-consortium-static/tsconfig.json @@ -0,0 +1,25 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./dist/lib/", + "declarationDir": "dist/lib", + "rootDir": "./src", + "tsBuildInfoFile": "../../.build-cache/cactus-plugin-consortium-new.tsbuildinfo" + }, + "include": [ + "./src", + "**/openapi.json" + ], + "references": [ + { + "path": "../cactus-common/tsconfig.json" + }, + { + "path": "../cactus-core/tsconfig.json" + }, + { + "path": "../cactus-core-api/tsconfig.json" + } + ] +} \ No newline at end of file diff --git a/packages/cactus-api-client/src/main/typescript/api-client.ts b/packages/cactus-api-client/src/main/typescript/api-client.ts index df344f0f204..634b3f3a4b4 100644 --- a/packages/cactus-api-client/src/main/typescript/api-client.ts +++ b/packages/cactus-api-client/src/main/typescript/api-client.ts @@ -83,6 +83,7 @@ export class ApiClient extends BaseAPI { ledgerOrId: string | Ledger, ctor: new (configuration?: Configuration) => T, ctorArgs: Record, + consortiumDbProvider?: IAsyncProvider, ): Promise; /** * Constructs a new `ApiClient` object that is tied to whichever Cactus node diff --git a/tsconfig.json b/tsconfig.json index ce7a9f42f89..ff0e6964d92 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -28,6 +28,9 @@ { "path": "./packages/cactus-plugin-consortium-manual/tsconfig.json" }, + { + "path": "./packages/cacti-plugin-consortium-static/tsconfig.json" + }, { "path": "./packages/cactus-plugin-htlc-eth-besu/tsconfig.json" }, diff --git a/yarn.lock b/yarn.lock index 9d7b282d75f..307ad6fb0f6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9071,6 +9071,34 @@ __metadata: languageName: unknown linkType: soft +"@hyperledger/cacti-plugin-consortium-static@workspace:packages/cacti-plugin-consortium-static": + version: 0.0.0-use.local + resolution: "@hyperledger/cacti-plugin-consortium-static@workspace:packages/cacti-plugin-consortium-static" + dependencies: + "@hyperledger/cactus-api-client": "npm:2.0.0-rc.3" + "@hyperledger/cactus-cmd-api-server": "npm:2.0.0-rc.3" + "@hyperledger/cactus-common": "npm:2.0.0-rc.3" + "@hyperledger/cactus-core": "npm:2.0.0-rc.3" + "@hyperledger/cactus-core-api": "npm:2.0.0-rc.3" + "@hyperledger/cactus-plugin-ledger-connector-besu": "npm:2.0.0-rc.3" + "@hyperledger/cactus-test-tooling": "npm:2.0.0-rc.3" + "@types/express": "npm:4.17.21" + "@types/json-stable-stringify": "npm:1.0.33" + "@types/uuid": "npm:10.0.0" + axios: "npm:1.6.0" + body-parser: "npm:1.20.2" + express: "npm:4.19.2" + http-errors-enhanced-cjs: "npm:2.0.1" + jose: "npm:4.15.5" + merkletreejs: "npm:0.4.0" + prom-client: "npm:15.1.3" + safe-stable-stringify: "npm:2.4.3" + typescript-optional: "npm:2.0.1" + uuid: "npm:10.0.0" + web3: "npm:1.6.1" + languageName: unknown + linkType: soft + "@hyperledger/cacti-plugin-ledger-connector-stellar@workspace:packages/cacti-plugin-ledger-connector-stellar": version: 0.0.0-use.local resolution: "@hyperledger/cacti-plugin-ledger-connector-stellar@workspace:packages/cacti-plugin-ledger-connector-stellar" @@ -38837,6 +38865,19 @@ __metadata: languageName: node linkType: hard +"merkletreejs@npm:0.4.0": + version: 0.4.0 + resolution: "merkletreejs@npm:0.4.0" + dependencies: + bignumber.js: "npm:^9.0.1" + buffer-reverse: "npm:^1.0.1" + crypto-js: "npm:^4.2.0" + treeify: "npm:^1.1.0" + web3-utils: "npm:^1.3.4" + checksum: 10/ebf8bd2ebb42b7f489c8da8ed39e230fa131c0a5b23a2e3be667a0589671df118f996b73d44e5b83f2c70a3c956515328386e94b2841cd279033eca8caf71aee + languageName: node + linkType: hard + "methods@npm:^1.1.2, methods@npm:~1.1.2": version: 1.1.2 resolution: "methods@npm:1.1.2" From 229c45c08856cc870922e8e4e6c222b3af9a97d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jun 2024 22:26:21 +0000 Subject: [PATCH 2/8] build(deps): bump the npm_and_yarn group across 12 directories with 14 updates Bumps the npm_and_yarn group with 13 updates in the / directory: --- updated-dependencies: - dependency-name: "@grpc/grpc-js" dependency-type: direct:production dependency-group: npm_and_yarn - dependency-name: axios dependency-type: direct:production dependency-group: npm_and_yarn - dependency-name: bl dependency-type: direct:production dependency-group: npm_and_yarn - dependency-name: undici dependency-type: direct:production dependency-group: npm_and_yarn - dependency-name: qs dependency-type: direct:development dependency-group: npm_and_yarn - dependency-name: vite dependency-type: direct:development dependency-group: npm_and_yarn - dependency-name: pkg dependency-type: direct:development dependency-group: npm_and_yarn - dependency-name: "@adobe/css-tools" dependency-type: indirect dependency-group: npm_and_yarn - dependency-name: apollo-server-core dependency-type: indirect dependency-group: npm_and_yarn - dependency-name: browserify-sign dependency-type: indirect dependency-group: npm_and_yarn - dependency-name: es5-ext dependency-type: indirect dependency-group: npm_and_yarn - dependency-name: react-devtools-core dependency-type: indirect dependency-group: npm_and_yarn - dependency-name: word-wrap dependency-type: indirect dependency-group: npm_and_yarn - dependency-name: jsonwebtoken dependency-type: direct:production dependency-group: npm_and_yarn - dependency-name: jsonwebtoken dependency-type: direct:production dependency-group: npm_and_yarn - dependency-name: "@grpc/grpc-js" dependency-type: direct:production dependency-group: npm_and_yarn - dependency-name: axios dependency-type: direct:production dependency-group: npm_and_yarn - dependency-name: "@grpc/grpc-js" dependency-type: direct:development dependency-group: npm_and_yarn - dependency-name: "@grpc/grpc-js" dependency-type: direct:development dependency-group: npm_and_yarn - dependency-name: axios dependency-type: direct:production dependency-group: npm_and_yarn - dependency-name: jsonwebtoken dependency-type: direct:production dependency-group: npm_and_yarn - dependency-name: "@grpc/grpc-js" dependency-type: direct:production dependency-group: npm_and_yarn - dependency-name: "@grpc/grpc-js" dependency-type: direct:production dependency-group: npm_and_yarn - dependency-name: "@grpc/grpc-js" dependency-type: direct:production dependency-group: npm_and_yarn - dependency-name: "@grpc/grpc-js" dependency-type: direct:development dependency-group: npm_and_yarn - dependency-name: pkg dependency-type: direct:development dependency-group: npm_and_yarn - dependency-name: "@grpc/grpc-js" dependency-type: direct:production dependency-group: npm_and_yarn ... Co-authored-by: Peter Somogyvari Signed-off-by: dependabot[bot] Signed-off-by: Peter Somogyvari --- .../package.json | 2 +- package.json | 2 +- packages/cactus-cmd-api-server/package.json | 8 +- packages/cactus-core-api/package.json | 4 +- .../package.json | 4 +- weaver/common/protos-js/package.json | 4 +- .../fabric/fabric-cli/package-local.json | 6 + weaver/samples/fabric/fabric-cli/package.json | 6 + .../package-local.json | 2 +- .../interoperation-node-sdk/package.json | 2 +- yarn.lock | 320 ++++++++++++++---- 11 files changed, 282 insertions(+), 78 deletions(-) diff --git a/examples/cactus-example-carbon-accounting-backend/package.json b/examples/cactus-example-carbon-accounting-backend/package.json index 97b42d7d982..1acac656b84 100644 --- a/examples/cactus-example-carbon-accounting-backend/package.json +++ b/examples/cactus-example-carbon-accounting-backend/package.json @@ -85,7 +85,7 @@ "http-status-codes": "2.1.4", "jose": "4.15.5", "json-stable-stringify": "1.0.2", - "qs": "6.9.7" + "qs": "6.8.3" }, "engines": { "node": ">=18", diff --git a/package.json b/package.json index 5d86658506a..d07d7561ed8 100644 --- a/package.json +++ b/package.json @@ -174,7 +174,7 @@ "fast-safe-stringify": "2.1.1", "fs-extra": "11.2.0", "globby": "12.2.0", - "google-protobuf": "3.21.2", + "google-protobuf": "3.21.4", "grpc-tools": "1.12.4", "grpc_tools_node_protoc_ts": "5.3.3", "husky": "7.0.4", diff --git a/packages/cactus-cmd-api-server/package.json b/packages/cactus-cmd-api-server/package.json index fd259b4525d..24cd3e58391 100644 --- a/packages/cactus-cmd-api-server/package.json +++ b/packages/cactus-cmd-api-server/package.json @@ -68,7 +68,7 @@ "@connectrpc/connect-fastify": "1.4.0", "@connectrpc/connect-node": "1.4.0", "@grpc/grpc-js": "1.11.1", - "@grpc/proto-loader": "0.7.8", + "@grpc/proto-loader": "0.7.13", "@hyperledger/cactus-common": "2.0.0-rc.3", "@hyperledger/cactus-core": "2.0.0-rc.3", "@hyperledger/cactus-core-api": "2.0.0-rc.3", @@ -88,7 +88,7 @@ "express-rate-limit": "6.7.0", "fastify": "4.26.2", "fs-extra": "11.2.0", - "google-protobuf": "3.18.0-rc.2", + "google-protobuf": "3.21.4", "jose": "4.15.5", "json-stable-stringify": "1.0.2", "lmify": "0.3.0", @@ -131,11 +131,11 @@ "@types/xml2js": "0.4.9", "@vercel/ncc": "0.38.1", "benchmark": "2.1.4", - "google-protobuf": "3.18.0-rc.2", + "google-protobuf": "3.21.4", "grpc-tools": "1.12.4", "grpc_tools_node_protoc_ts": "5.3.3", "http-status-codes": "2.1.4", - "protobufjs": "7.2.5", + "protobufjs": "7.4.0", "tsx": "4.16.2" }, "engines": { diff --git a/packages/cactus-core-api/package.json b/packages/cactus-core-api/package.json index dcb731c5958..2f06a3155e1 100644 --- a/packages/cactus-core-api/package.json +++ b/packages/cactus-core-api/package.json @@ -63,12 +63,12 @@ "@grpc/grpc-js": "1.11.1", "@hyperledger/cactus-common": "2.0.0-rc.3", "axios": "1.7.2", - "google-protobuf": "3.21.2" + "google-protobuf": "3.21.4" }, "devDependencies": { "@bufbuild/protobuf": "1.10.0", "@connectrpc/connect": "1.4.0", - "@grpc/proto-loader": "0.7.8", + "@grpc/proto-loader": "0.7.13", "@types/express": "4.17.21", "@types/google-protobuf": "3.15.5", "grpc-tools": "1.12.4", diff --git a/packages/cactus-plugin-ledger-connector-besu/package.json b/packages/cactus-plugin-ledger-connector-besu/package.json index a8bacd6e40a..4515193d633 100644 --- a/packages/cactus-plugin-ledger-connector-besu/package.json +++ b/packages/cactus-plugin-ledger-connector-besu/package.json @@ -65,7 +65,7 @@ "@hyperledger/cactus-core-api": "2.0.0-rc.3", "axios": "1.7.2", "express": "4.19.2", - "google-protobuf": "3.21.2", + "google-protobuf": "3.21.4", "http-errors": "2.0.0", "http-errors-enhanced-cjs": "2.0.1", "joi": "17.13.3", @@ -100,7 +100,7 @@ "grpc_tools_node_protoc_ts": "5.3.3", "key-encoder": "2.0.3", "npm-run-all2": "6.1.2", - "protobufjs": "7.2.5", + "protobufjs": "7.4.0", "socket.io": "4.6.2", "tsx": "4.16.2", "uuid": "10.0.0", diff --git a/weaver/common/protos-js/package.json b/weaver/common/protos-js/package.json index 7ebbfddc602..e5e677178fd 100644 --- a/weaver/common/protos-js/package.json +++ b/weaver/common/protos-js/package.json @@ -39,8 +39,8 @@ }, "dependencies": { "@grpc/grpc-js": "1.11.1", - "@grpc/proto-loader": "0.7.8", - "google-protobuf": "3.21.2", + "@grpc/proto-loader": "0.7.13", + "google-protobuf": "3.21.4", "grpc-tools": "1.12.4" }, "devDependencies": { diff --git a/weaver/samples/fabric/fabric-cli/package-local.json b/weaver/samples/fabric/fabric-cli/package-local.json index c828f661208..ec4d2499aea 100644 --- a/weaver/samples/fabric/fabric-cli/package-local.json +++ b/weaver/samples/fabric/fabric-cli/package-local.json @@ -49,8 +49,14 @@ "winston": "3.10.0" }, "devDependencies": { + "@grpc/grpc-js": "1.11.1", + "@grpc/proto-loader": "0.7.13", "@types/express": "4.17.21", "@types/node": "18.11.9", + "google-protobuf": "3.21.4", + "jest": "29.6.2", + "pkg": "5.8.1", + "protobufjs": "7.4.0", "ts-jest": "29.1.1", "ts-node": "10.9.1", "typescript": "5.5.2" diff --git a/weaver/samples/fabric/fabric-cli/package.json b/weaver/samples/fabric/fabric-cli/package.json index ba2df066478..7bb8cf2fae7 100644 --- a/weaver/samples/fabric/fabric-cli/package.json +++ b/weaver/samples/fabric/fabric-cli/package.json @@ -49,8 +49,14 @@ "winston": "3.10.0" }, "devDependencies": { + "@grpc/grpc-js": "1.11.1", + "@grpc/proto-loader": "0.7.13", "@types/express": "4.17.21", "@types/node": "18.11.9", + "google-protobuf": "3.21.4", + "jest": "29.6.2", + "pkg": "5.8.1", + "protobufjs": "7.4.0", "ts-jest": "29.1.1", "ts-node": "10.9.1", "typescript": "5.5.2" diff --git a/weaver/sdks/fabric/interoperation-node-sdk/package-local.json b/weaver/sdks/fabric/interoperation-node-sdk/package-local.json index 70e77d3757f..564d9d0c55c 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/package-local.json +++ b/weaver/sdks/fabric/interoperation-node-sdk/package-local.json @@ -38,7 +38,7 @@ }, "dependencies": { "@grpc/grpc-js": "1.11.1", - "@grpc/proto-loader": "0.7.8", + "@grpc/proto-loader": "0.7.13", "@hyperledger/cacti-weaver-protos-js": "file:./protos-js", "elliptic": "6.5.4", "fabric-common": "2.2.20", diff --git a/weaver/sdks/fabric/interoperation-node-sdk/package.json b/weaver/sdks/fabric/interoperation-node-sdk/package.json index de72bef8ec7..adaab89eaf1 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/package.json +++ b/weaver/sdks/fabric/interoperation-node-sdk/package.json @@ -38,7 +38,7 @@ }, "dependencies": { "@grpc/grpc-js": "1.11.1", - "@grpc/proto-loader": "0.7.8", + "@grpc/proto-loader": "0.7.13", "@hyperledger/cacti-weaver-protos-js": "2.0.0-rc.3", "elliptic": "6.5.4", "fabric-common": "2.2.20", diff --git a/yarn.lock b/yarn.lock index 307ad6fb0f6..6fc568abf66 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1751,6 +1751,17 @@ __metadata: languageName: node linkType: hard +"@babel/generator@npm:7.18.2": + version: 7.18.2 + resolution: "@babel/generator@npm:7.18.2" + dependencies: + "@babel/types": "npm:^7.18.2" + "@jridgewell/gen-mapping": "npm:^0.3.0" + jsesc: "npm:^2.5.1" + checksum: 10/961191f7548794711730e21adf215302c2f5f95bdc025ce997a31c4de39ec17c91e27d3ecdc1d641e7b1756872599045145a9334acbb80a5abfb626f678280e5 + languageName: node + linkType: hard + "@babel/generator@npm:7.22.9, @babel/generator@npm:^7.22.9": version: 7.22.9 resolution: "@babel/generator@npm:7.22.9" @@ -2666,6 +2677,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-string-parser@npm:^7.18.10, @babel/helper-string-parser@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-string-parser@npm:7.24.8" + checksum: 10/6d1bf8f27dd725ce02bdc6dffca3c95fb9ab8a06adc2edbd9c1c9d68500274230d1a609025833ed81981eff560045b6b38f7b4c6fb1ab19fc90e5004e3932535 + languageName: node + linkType: hard + "@babel/helper-string-parser@npm:^7.19.4": version: 7.19.4 resolution: "@babel/helper-string-parser@npm:7.19.4" @@ -2694,13 +2712,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.24.8": - version: 7.24.8 - resolution: "@babel/helper-string-parser@npm:7.24.8" - checksum: 10/6d1bf8f27dd725ce02bdc6dffca3c95fb9ab8a06adc2edbd9c1c9d68500274230d1a609025833ed81981eff560045b6b38f7b4c6fb1ab19fc90e5004e3932535 - languageName: node - linkType: hard - "@babel/helper-validator-identifier@npm:^7.16.7": version: 7.16.7 resolution: "@babel/helper-validator-identifier@npm:7.16.7" @@ -3023,6 +3034,15 @@ __metadata: languageName: node linkType: hard +"@babel/parser@npm:7.18.4": + version: 7.18.4 + resolution: "@babel/parser@npm:7.18.4" + bin: + parser: ./bin/babel-parser.js + checksum: 10/7aca0241b2ee45ac1aafd39b58af6f1d57e2fdefd98ffd5f3834cb1f1fc0577315e21931fe9356810b2c0613fd3af6ed94a2774ecf79c5da14315bc5a319b216 + languageName: node + linkType: hard + "@babel/parser@npm:7.24.7, @babel/parser@npm:^7.21.8": version: 7.24.7 resolution: "@babel/parser@npm:7.24.7" @@ -5560,7 +5580,18 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:7.24.7": +"@babel/types@npm:7.19.0": + version: 7.19.0 + resolution: "@babel/types@npm:7.19.0" + dependencies: + "@babel/helper-string-parser": "npm:^7.18.10" + "@babel/helper-validator-identifier": "npm:^7.18.6" + to-fast-properties: "npm:^2.0.0" + checksum: 10/6839d041b69746f35c74d25d82f49ea4e5844cf7f2d781f57aafd8ce4f5ac14ab7749f690454ea25147c9b2251cc753ae9733094e7a6f72f4e1f785f275cb174 + languageName: node + linkType: hard + +"@babel/types@npm:7.24.7, @babel/types@npm:^7.18.2": version: 7.24.7 resolution: "@babel/types@npm:7.24.7" dependencies: @@ -8840,18 +8871,17 @@ __metadata: languageName: node linkType: hard -"@grpc/proto-loader@npm:0.7.8": - version: 0.7.8 - resolution: "@grpc/proto-loader@npm:0.7.8" +"@grpc/proto-loader@npm:0.7.13, @grpc/proto-loader@npm:^0.7.13": + version: 0.7.13 + resolution: "@grpc/proto-loader@npm:0.7.13" dependencies: - "@types/long": "npm:^4.0.1" lodash.camelcase: "npm:^4.3.0" - long: "npm:^4.0.0" - protobufjs: "npm:^7.2.4" + long: "npm:^5.0.0" + protobufjs: "npm:^7.2.5" yargs: "npm:^17.7.2" bin: proto-loader-gen-types: build/bin/proto-loader-gen-types.js - checksum: 10/a7dde023f8209e7a97eecad5f627c31b796c663e0bf4a3bc81b848a8bdf0c2ba5de712189e4b6f759a2a766599b2a0ea197cdd4a45ab9d091329ca9ffb053bb8 + checksum: 10/7e2d842c2061cbaf6450c71da0077263be3bab165454d5c8a3e1ae4d3c6d2915f02fd27da63ff01f05e127b1221acd40705273f5d29303901e60514e852992f4 languageName: node linkType: hard @@ -8870,20 +8900,6 @@ __metadata: languageName: node linkType: hard -"@grpc/proto-loader@npm:^0.7.13": - version: 0.7.13 - resolution: "@grpc/proto-loader@npm:0.7.13" - dependencies: - lodash.camelcase: "npm:^4.3.0" - long: "npm:^5.0.0" - protobufjs: "npm:^7.2.5" - yargs: "npm:^17.7.2" - bin: - proto-loader-gen-types: build/bin/proto-loader-gen-types.js - checksum: 10/7e2d842c2061cbaf6450c71da0077263be3bab165454d5c8a3e1ae4d3c6d2915f02fd27da63ff01f05e127b1221acd40705273f5d29303901e60514e852992f4 - languageName: node - linkType: hard - "@grpc/proto-loader@npm:^0.7.8": version: 0.7.10 resolution: "@grpc/proto-loader@npm:0.7.10" @@ -9216,6 +9232,8 @@ __metadata: resolution: "@hyperledger/cacti-weaver-fabric-cli@workspace:weaver/samples/fabric/fabric-cli" dependencies: "@fidm/x509": "npm:1.2.1" + "@grpc/grpc-js": "npm:1.11.1" + "@grpc/proto-loader": "npm:0.7.13" "@hyperledger/cacti-weaver-protos-js": "npm:2.0.0-rc.3" "@hyperledger/cacti-weaver-sdk-fabric": "npm:2.0.0-rc.3" "@types/express": "npm:4.17.21" @@ -9227,6 +9245,10 @@ __metadata: fabric-common: "npm:2.2.20" fabric-network: "npm:2.2.20" gluegun: "npm:5.1.6" + google-protobuf: "npm:3.21.4" + jest: "npm:29.6.2" + pkg: "npm:5.8.1" + protobufjs: "npm:7.4.0" ts-jest: "npm:29.1.1" ts-node: "npm:10.9.1" typescript: "npm:5.5.2" @@ -9274,8 +9296,8 @@ __metadata: resolution: "@hyperledger/cacti-weaver-protos-js@workspace:weaver/common/protos-js" dependencies: "@grpc/grpc-js": "npm:1.11.1" - "@grpc/proto-loader": "npm:0.7.8" - google-protobuf: "npm:3.21.2" + "@grpc/proto-loader": "npm:0.7.13" + google-protobuf: "npm:3.21.4" grpc-tools: "npm:1.12.4" grpc_tools_node_protoc_ts: "npm:5.3.3" languageName: unknown @@ -9308,7 +9330,7 @@ __metadata: resolution: "@hyperledger/cacti-weaver-sdk-fabric@workspace:weaver/sdks/fabric/interoperation-node-sdk" dependencies: "@grpc/grpc-js": "npm:1.11.1" - "@grpc/proto-loader": "npm:0.7.8" + "@grpc/proto-loader": "npm:0.7.13" "@hyperledger/cacti-weaver-protos-js": "npm:2.0.0-rc.3" "@types/node": "npm:18.11.9" chai: "npm:4.3.7" @@ -9367,7 +9389,7 @@ __metadata: "@connectrpc/connect-node": "npm:1.4.0" "@connectrpc/protoc-gen-connect-es": "npm:1.4.0" "@grpc/grpc-js": "npm:1.11.1" - "@grpc/proto-loader": "npm:0.7.8" + "@grpc/proto-loader": "npm:0.7.13" "@hyperledger/cactus-common": "npm:2.0.0-rc.3" "@hyperledger/cactus-core": "npm:2.0.0-rc.3" "@hyperledger/cactus-core-api": "npm:2.0.0-rc.3" @@ -9411,7 +9433,7 @@ __metadata: express-rate-limit: "npm:6.7.0" fastify: "npm:4.26.2" fs-extra: "npm:11.2.0" - google-protobuf: "npm:3.18.0-rc.2" + google-protobuf: "npm:3.21.4" grpc-tools: "npm:1.12.4" grpc_tools_node_protoc_ts: "npm:5.3.3" http-status-codes: "npm:2.1.4" @@ -9420,7 +9442,7 @@ __metadata: lmify: "npm:0.3.0" node-forge: "npm:1.3.0" prom-client: "npm:15.1.3" - protobufjs: "npm:7.2.5" + protobufjs: "npm:7.4.0" run-time-error-cjs: "npm:1.4.0" rxjs: "npm:7.8.1" safe-stable-stringify: "npm:2.4.3" @@ -9520,12 +9542,12 @@ __metadata: "@bufbuild/protobuf": "npm:1.10.0" "@connectrpc/connect": "npm:1.4.0" "@grpc/grpc-js": "npm:1.11.1" - "@grpc/proto-loader": "npm:0.7.8" + "@grpc/proto-loader": "npm:0.7.13" "@hyperledger/cactus-common": "npm:2.0.0-rc.3" "@types/express": "npm:4.17.21" "@types/google-protobuf": "npm:3.15.5" axios: "npm:1.7.2" - google-protobuf: "npm:3.21.2" + google-protobuf: "npm:3.21.4" grpc-tools: "npm:1.12.4" grpc_tools_node_protoc_ts: "npm:5.3.3" make-dir-cli: "npm:3.1.0" @@ -9590,7 +9612,7 @@ __metadata: jose: "npm:4.15.5" json-stable-stringify: "npm:1.0.2" openapi-types: "npm:12.1.3" - qs: "npm:6.9.7" + qs: "npm:6.8.3" typescript-optional: "npm:2.0.1" uuid: "npm:10.0.0" web3-core: "npm:1.6.1" @@ -10252,7 +10274,7 @@ __metadata: body-parser: "npm:1.20.2" express: "npm:4.19.2" fs-extra: "npm:11.2.0" - google-protobuf: "npm:3.21.2" + google-protobuf: "npm:3.21.4" grpc-tools: "npm:1.12.4" grpc_tools_node_protoc_ts: "npm:5.3.3" http-errors: "npm:2.0.0" @@ -10262,7 +10284,7 @@ __metadata: npm-run-all2: "npm:6.1.2" openapi-types: "npm:12.1.3" prom-client: "npm:15.1.3" - protobufjs: "npm:7.2.5" + protobufjs: "npm:7.4.0" run-time-error-cjs: "npm:1.4.0" rxjs: "npm:7.8.1" socket.io: "npm:4.6.2" @@ -11053,7 +11075,7 @@ __metadata: fast-safe-stringify: "npm:2.1.1" fs-extra: "npm:11.2.0" globby: "npm:12.2.0" - google-protobuf: "npm:3.21.2" + google-protobuf: "npm:3.21.4" grpc-tools: "npm:1.12.4" grpc_tools_node_protoc_ts: "npm:5.3.3" husky: "npm:7.0.4" @@ -28824,6 +28846,13 @@ __metadata: languageName: node linkType: hard +"expand-template@npm:^2.0.3": + version: 2.0.3 + resolution: "expand-template@npm:2.0.3" + checksum: 10/588c19847216421ed92befb521767b7018dc88f88b0576df98cb242f20961425e96a92cbece525ef28cc5becceae5d544ae0f5b9b5e2aa05acb13716ca5b3099 + languageName: node + linkType: hard + "expand-tilde@npm:^2.0.0, expand-tilde@npm:^2.0.2": version: 2.0.2 resolution: "expand-tilde@npm:2.0.2" @@ -30258,6 +30287,16 @@ __metadata: languageName: node linkType: hard +"from2@npm:^2.3.0": + version: 2.3.0 + resolution: "from2@npm:2.3.0" + dependencies: + inherits: "npm:^2.0.1" + readable-stream: "npm:^2.0.0" + checksum: 10/9164fbe5bbf9a48864bb8960296ccd1173c570ba1301a1c20de453b06eee39b52332f72279f2393948789afe938d8e951d50fea01064ba69fb5674b909f102b6 + languageName: node + linkType: hard + "fromentries@npm:^1.2.0": version: 1.3.2 resolution: "fromentries@npm:1.3.2" @@ -31021,6 +31060,13 @@ __metadata: languageName: node linkType: hard +"github-from-package@npm:0.0.0": + version: 0.0.0 + resolution: "github-from-package@npm:0.0.0" + checksum: 10/2a091ba07fbce22205642543b4ea8aaf068397e1433c00ae0f9de36a3607baf5bcc14da97fbb798cfca6393b3c402031fca06d8b491a44206d6efef391c58537 + languageName: node + linkType: hard + "glob-base@npm:^0.3.0": version: 0.3.0 resolution: "glob-base@npm:0.3.0" @@ -31504,17 +31550,10 @@ __metadata: languageName: node linkType: hard -"google-protobuf@npm:3.18.0-rc.2": - version: 3.18.0-rc.2 - resolution: "google-protobuf@npm:3.18.0-rc.2" - checksum: 10/71cc1d20fd52bba970a3485165f78cb453725ef5f4c1146e9a8c23d2850072867ad29e58ebf25da3f2a990f129f7b5d23f4aeea0476e827c4bf61d1cecc922cc - languageName: node - linkType: hard - -"google-protobuf@npm:3.21.2": - version: 3.21.2 - resolution: "google-protobuf@npm:3.21.2" - checksum: 10/b376c2e47fb0419b41b901e4da8f3827fe9594ffb7887708b9c241f36005d0b9f2edc7b3f05795f6793924a241e767f67831732eae0f23bdbb337b56a6ab4e26 +"google-protobuf@npm:3.21.4": + version: 3.21.4 + resolution: "google-protobuf@npm:3.21.4" + checksum: 10/0d87fe8ef221d105cbaa808f4024bd577638524d8e461469e3733f2e4933391ad4da86b7fcbd11e8781bee04eacf2e8ba19aaacd5f9deb336a220485841d980f languageName: node linkType: hard @@ -33228,6 +33267,16 @@ __metadata: languageName: node linkType: hard +"into-stream@npm:^6.0.0": + version: 6.0.0 + resolution: "into-stream@npm:6.0.0" + dependencies: + from2: "npm:^2.3.0" + p-is-promise: "npm:^3.0.0" + checksum: 10/8df24c9eadd7cdd1cbc160bc20914b961dfd0ca29767785b69e698f799e85466b6f7c637d237dca1472d09d333399f70cc05a2fb8d08cb449dc9a80d92193980 + languageName: node + linkType: hard + "invariant@npm:^2.2.4": version: 2.2.4 resolution: "invariant@npm:2.2.4" @@ -33552,6 +33601,15 @@ __metadata: languageName: node linkType: hard +"is-core-module@npm:2.9.0": + version: 2.9.0 + resolution: "is-core-module@npm:2.9.0" + dependencies: + has: "npm:^1.0.3" + checksum: 10/1a17939da6f9c6c90073a2a13a6b79c423ed375b9ba1f87ca5daab6e706ccef6b5aaba7ebede08514441ba773ce21a0f8ce29ff2b88e68d5ede8b8de2b157bde + languageName: node + linkType: hard + "is-core-module@npm:^2.11.0": version: 2.12.0 resolution: "is-core-module@npm:2.12.0" @@ -39396,7 +39454,7 @@ __metadata: languageName: node linkType: hard -"mkdirp-classic@npm:^0.5.2": +"mkdirp-classic@npm:^0.5.2, mkdirp-classic@npm:^0.5.3": version: 0.5.3 resolution: "mkdirp-classic@npm:0.5.3" checksum: 10/3f4e088208270bbcc148d53b73e9a5bd9eef05ad2cbf3b3d0ff8795278d50dd1d11a8ef1875ff5aea3fa888931f95bfcb2ad5b7c1061cfefd6284d199e6776ac @@ -39768,6 +39826,16 @@ __metadata: languageName: node linkType: hard +"multistream@npm:^4.1.0": + version: 4.1.0 + resolution: "multistream@npm:4.1.0" + dependencies: + once: "npm:^1.4.0" + readable-stream: "npm:^3.6.0" + checksum: 10/305c49a1aadcb7f63f64d8ca2bb6e7852e5f7dba94c7329e9a72ce53cd0046686b71668dc1adbf123f17d2dd107765fc946e64c36a26b15c470a3146ea3bc923 + languageName: node + linkType: hard + "mustache@npm:^2.2.1": version: 2.3.2 resolution: "mustache@npm:2.3.2" @@ -39923,6 +39991,13 @@ __metadata: languageName: node linkType: hard +"napi-build-utils@npm:^1.0.1": + version: 1.0.2 + resolution: "napi-build-utils@npm:1.0.2" + checksum: 10/276feb8e30189fe18718e85b6f82e4f952822baa2e7696f771cc42571a235b789dc5907a14d9ffb6838c3e4ff4c25717c2575e5ce1cf6e02e496e204c11e57f6 + languageName: node + linkType: hard + "napi-macros@npm:^2.2.2": version: 2.2.2 resolution: "napi-macros@npm:2.2.2" @@ -40142,6 +40217,15 @@ __metadata: languageName: node linkType: hard +"node-abi@npm:^3.3.0": + version: 3.67.0 + resolution: "node-abi@npm:3.67.0" + dependencies: + semver: "npm:^7.3.5" + checksum: 10/fe47dfd9a0770d300ce1dd9b527441e691cba077c19fdbcb304796a5bc182f8cbe40933f2a013127b98a32bd6d06e0efa2b5f76ca38d791d44f83307920bafac + languageName: node + linkType: hard + "node-abort-controller@npm:^3.0.1": version: 3.1.1 resolution: "node-abort-controller@npm:3.1.1" @@ -40206,7 +40290,7 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:2.7.0, node-fetch@npm:^2.6.8, node-fetch@npm:^2.6.9": +"node-fetch@npm:2.7.0, node-fetch@npm:^2.6.6, node-fetch@npm:^2.6.8, node-fetch@npm:^2.6.9": version: 2.7.0 resolution: "node-fetch@npm:2.7.0" dependencies: @@ -41847,6 +41931,13 @@ __metadata: languageName: node linkType: hard +"p-is-promise@npm:^3.0.0": + version: 3.0.0 + resolution: "p-is-promise@npm:3.0.0" + checksum: 10/161e526ce5ba4f053afce094110fdf6cae250d28002b874b30d5f7525d1abb18911ae040d7f0ed3d202af6df87c84acb04109f39e34d7072af6088b3fc6a27fa + languageName: node + linkType: hard + "p-limit@npm:^1.1.0": version: 1.3.0 resolution: "p-limit@npm:1.3.0" @@ -43065,6 +43156,24 @@ __metadata: languageName: node linkType: hard +"pkg-fetch@npm:3.4.2": + version: 3.4.2 + resolution: "pkg-fetch@npm:3.4.2" + dependencies: + chalk: "npm:^4.1.2" + fs-extra: "npm:^9.1.0" + https-proxy-agent: "npm:^5.0.0" + node-fetch: "npm:^2.6.6" + progress: "npm:^2.0.3" + semver: "npm:^7.3.5" + tar-fs: "npm:^2.1.1" + yargs: "npm:^16.2.0" + bin: + pkg-fetch: lib-es5/bin.js + checksum: 10/e8b1f5852fa426ba793508e947901ed2863e5a5455191209843874ec769e0bfcdf16d2c92cf2128db2fd494be0203ada5eaf68a4d9ace3a7dc30e2e83bd7bbce + languageName: node + linkType: hard + "pkg-up@npm:^1.0.0": version: 1.0.0 resolution: "pkg-up@npm:1.0.0" @@ -43083,6 +43192,35 @@ __metadata: languageName: node linkType: hard +"pkg@npm:5.8.1": + version: 5.8.1 + resolution: "pkg@npm:5.8.1" + dependencies: + "@babel/generator": "npm:7.18.2" + "@babel/parser": "npm:7.18.4" + "@babel/types": "npm:7.19.0" + chalk: "npm:^4.1.2" + fs-extra: "npm:^9.1.0" + globby: "npm:^11.1.0" + into-stream: "npm:^6.0.0" + is-core-module: "npm:2.9.0" + minimist: "npm:^1.2.6" + multistream: "npm:^4.1.0" + pkg-fetch: "npm:3.4.2" + prebuild-install: "npm:7.1.1" + resolve: "npm:^1.22.0" + stream-meter: "npm:^1.0.4" + peerDependencies: + node-notifier: ">=9.0.1" + peerDependenciesMeta: + node-notifier: + optional: true + bin: + pkg: lib-es5/bin.js + checksum: 10/917cee784f8928ecb443b11f51a618fca238af5783a42244b873d8ac455c1e2000497f888eb78be4cfe9ec9193cafe127eb00553ec80f7035d1b6dc94a3e688a + languageName: node + linkType: hard + "platform@npm:^1.3.3": version: 1.3.6 resolution: "platform@npm:1.3.6" @@ -44315,6 +44453,28 @@ __metadata: languageName: node linkType: hard +"prebuild-install@npm:7.1.1": + version: 7.1.1 + resolution: "prebuild-install@npm:7.1.1" + dependencies: + detect-libc: "npm:^2.0.0" + expand-template: "npm:^2.0.3" + github-from-package: "npm:0.0.0" + minimist: "npm:^1.2.3" + mkdirp-classic: "npm:^0.5.3" + napi-build-utils: "npm:^1.0.1" + node-abi: "npm:^3.3.0" + pump: "npm:^3.0.0" + rc: "npm:^1.2.7" + simple-get: "npm:^4.0.0" + tar-fs: "npm:^2.0.0" + tunnel-agent: "npm:^0.6.0" + bin: + prebuild-install: bin.js + checksum: 10/6c70a2f82fbda8903497c560a761b000d861a3e772322c8bed012be0f0a084b5aaca4438a3fad1bd3a24210765f4fae06ddd89ea04dc4c034dde693cc0d9d5f4 + languageName: node + linkType: hard + "precinct@npm:^11.0.5": version: 11.0.5 resolution: "precinct@npm:11.0.5" @@ -44510,7 +44670,7 @@ __metadata: languageName: node linkType: hard -"progress@npm:^2.0.0": +"progress@npm:^2.0.0, progress@npm:^2.0.3": version: 2.0.3 resolution: "progress@npm:2.0.3" checksum: 10/e6f0bcb71f716eee9dfac0fe8a2606e3704d6a64dd93baaf49fbadbc8499989a610fe14cf1bc6f61b6d6653c49408d94f4a94e124538084efd8e4cf525e0293d @@ -44848,10 +45008,10 @@ __metadata: languageName: node linkType: hard -"qs@npm:6.9.7": - version: 6.9.7 - resolution: "qs@npm:6.9.7" - checksum: 10/fb364b54bf4f092a095554968f5abf06036cfe359c9aba258a81b0c0366f625a46098fe1224b2a71ee2f88642470af391c7a8a1496508eca29c37093293f91a9 +"qs@npm:6.8.3": + version: 6.8.3 + resolution: "qs@npm:6.8.3" + checksum: 10/ba108daa907e6e532af3caa8e8ff7d46a133850b51dcde2b1a8596f3eec9c6e77f82ac9b07120c96145b7a7239a98712617b9d2942289b2a30818e7a6ad364d2 languageName: node linkType: hard @@ -45052,7 +45212,7 @@ __metadata: languageName: node linkType: hard -"rc@npm:^1.2.8": +"rc@npm:^1.2.7, rc@npm:^1.2.8": version: 1.2.8 resolution: "rc@npm:1.2.8" dependencies: @@ -45561,7 +45721,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^2.0.0, readable-stream@npm:^2.3.6, readable-stream@npm:^2.3.8": +"readable-stream@npm:^2.0.0, readable-stream@npm:^2.1.4, readable-stream@npm:^2.3.6, readable-stream@npm:^2.3.8": version: 2.3.8 resolution: "readable-stream@npm:2.3.8" dependencies: @@ -46503,7 +46663,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:1.22.8, resolve@npm:^1.19.0, resolve@npm:^1.22.2, resolve@npm:^1.22.3": +"resolve@npm:1.22.8, resolve@npm:^1.19.0, resolve@npm:^1.22.0, resolve@npm:^1.22.2, resolve@npm:^1.22.3": version: 1.22.8 resolution: "resolve@npm:1.22.8" dependencies: @@ -46577,7 +46737,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@npm%3A1.22.8#optional!builtin, resolve@patch:resolve@npm%3A^1.19.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.2#optional!builtin, resolve@patch:resolve@npm%3A^1.22.3#optional!builtin": +"resolve@patch:resolve@npm%3A1.22.8#optional!builtin, resolve@patch:resolve@npm%3A^1.19.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.2#optional!builtin, resolve@patch:resolve@npm%3A^1.22.3#optional!builtin": version: 1.22.8 resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" dependencies: @@ -47977,6 +48137,17 @@ __metadata: languageName: node linkType: hard +"simple-get@npm:^4.0.0": + version: 4.0.1 + resolution: "simple-get@npm:4.0.1" + dependencies: + decompress-response: "npm:^6.0.0" + once: "npm:^1.3.1" + simple-concat: "npm:^1.0.0" + checksum: 10/93f1b32319782f78f2f2234e9ce34891b7ab6b990d19d8afefaa44423f5235ce2676aae42d6743fecac6c8dfff4b808d4c24fe5265be813d04769917a9a44f36 + languageName: node + linkType: hard + "simple-git@npm:3.19.1": version: 3.19.1 resolution: "simple-git@npm:3.19.1" @@ -49051,6 +49222,15 @@ __metadata: languageName: node linkType: hard +"stream-meter@npm:^1.0.4": + version: 1.0.4 + resolution: "stream-meter@npm:1.0.4" + dependencies: + readable-stream: "npm:^2.1.4" + checksum: 10/b560f652cb2c62d1e117aab611737376f3086c125f464c23dcfec8a73e0e6416d20a334dca450a2d0527ce9c14299f1023553bf47a3d65892c73640dc3c401e8 + languageName: node + linkType: hard + "stream-shift@npm:^1.0.0": version: 1.0.1 resolution: "stream-shift@npm:1.0.1" @@ -50141,6 +50321,18 @@ __metadata: languageName: node linkType: hard +"tar-fs@npm:^2.0.0, tar-fs@npm:^2.1.1": + version: 2.1.1 + resolution: "tar-fs@npm:2.1.1" + dependencies: + chownr: "npm:^1.1.1" + mkdirp-classic: "npm:^0.5.2" + pump: "npm:^3.0.0" + tar-stream: "npm:^2.1.4" + checksum: 10/526deae025453e825f87650808969662fbb12eb0461d033e9b447de60ec951c6c4607d0afe7ce057defe9d4e45cf80399dd74bc15f9d9e0773d5e990a78ce4ac + languageName: node + linkType: hard + "tar-fs@npm:~2.0.1": version: 2.0.1 resolution: "tar-fs@npm:2.0.1" @@ -50153,7 +50345,7 @@ __metadata: languageName: node linkType: hard -"tar-stream@npm:2.2.0, tar-stream@npm:^2.0.0": +"tar-stream@npm:2.2.0, tar-stream@npm:^2.0.0, tar-stream@npm:^2.1.4": version: 2.2.0 resolution: "tar-stream@npm:2.2.0" dependencies: From d509dadd0349266bb754fe2621982e9c0302b79e Mon Sep 17 00:00:00 2001 From: ashnashahgrover Date: Thu, 8 Aug 2024 18:25:07 +0000 Subject: [PATCH 3/8] test(besu): refactor jest test negative test cases Primary Changes ---------------- 1. Refactored all negative test case exception assertions for cactus-plugin-ledger-connector-besu. Removed try-catch blocks, replaced with declarations through jest and jest-extended's own API. 2. Noted two tests within openapi-validation.test.ts (GetPastLogsEndpoint and GetBesuRecordEndpointV1 with empty parameters) where the status code returned should be 400 but is 200. This could be investigated in a seperate issue. Fixes #3467 Signed-off-by: ashnashahgrover --- .../get-record-locator.test.ts | 25 +- .../deploy-contract/invoke-contract.test.ts | 26 +- .../openapi/openapi-validation.test.ts | 589 ++++++++++-------- 3 files changed, 364 insertions(+), 276 deletions(-) diff --git a/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/get-record-locator.test.ts b/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/get-record-locator.test.ts index bdcb244cfbf..63b2161aa8c 100644 --- a/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/get-record-locator.test.ts +++ b/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/get-record-locator.test.ts @@ -265,8 +265,8 @@ describe("PluginLedgerConnectorBesu", () => { }); expect(setNameOut).toBeTruthy(); - try { - await connector.invokeContract({ + await expect( + connector.invokeContract({ contractName: HelloWorldContractJson.contractName, contractAbi: HelloWorldContractJson.abi, contractAddress, @@ -280,19 +280,14 @@ describe("PluginLedgerConnectorBesu", () => { type: Web3SigningCredentialType.PrivateKeyHex, }, nonce: 1, - }); - throw new Error("This operation should not have succeeded, but it did."); - } catch (ex: unknown) { - // 'Returned error: Nonce too low' - expect(ex).toHaveProperty( - "message", - expect.stringContaining("Nonce too low"), - ); - expect(ex).toHaveProperty( - "stack", - expect.stringContaining("Nonce too low"), - ); - } + }), + ).rejects.toThrowError( + expect.objectContaining({ + message: expect.stringContaining("Nonce too low"), + stack: expect.stringContaining("Nonce too low"), + }), + ); + const req: InvokeContractV1Request = { contractName: HelloWorldContractJson.contractName, contractAbi: HelloWorldContractJson.abi, diff --git a/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/invoke-contract.test.ts b/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/invoke-contract.test.ts index d596bceea26..4dddf7203d2 100644 --- a/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/invoke-contract.test.ts +++ b/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/invoke-contract.test.ts @@ -183,8 +183,8 @@ describe(testCase, () => { }); expect(setNameOut).toBeTruthy(); - try { - const setNameOutInvalid = await connector.invokeContract({ + await expect( + connector.invokeContract({ contractName, keychainId: keychainPlugin.getKeychainId(), invocationType: EthContractInvocationType.Send, @@ -197,11 +197,12 @@ describe(testCase, () => { type: Web3SigningCredentialType.PrivateKeyHex, }, nonce: 1, - }); - expect(setNameOutInvalid.transactionReceipt).toBeFalsy(); - } catch (error) { - expect(error.message).toMatch("Nonce too low"); - } + }), + ).rejects.toThrowError( + expect.objectContaining({ + message: expect.stringContaining("Nonce too low"), + }), + ); const { callOutput: getNameOut } = await connector.invokeContract({ contractName, @@ -286,8 +287,8 @@ describe(testCase, () => { }); expect(setNameOut).toBeTruthy(); - try { - const setNameOutInvalid = await connector.invokeContract({ + await expect( + connector.invokeContract({ contractName, keychainId: keychainPlugin.getKeychainId(), invocationType: EthContractInvocationType.Send, @@ -296,11 +297,8 @@ describe(testCase, () => { gas: 1000000, signingCredential, nonce: 4, - }); - expect(setNameOutInvalid.transactionReceipt).toBeFalsy(); - } catch (error) { - expect(error.message).toMatch("Nonce too low"); - } + }), + ).rejects.toThrow("Nonce too low"); const { callOutput: getNameOut } = await connector.invokeContract({ contractName, diff --git a/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/openapi/openapi-validation.test.ts b/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/openapi/openapi-validation.test.ts index 95ae330f709..33f24ccaa24 100644 --- a/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/openapi/openapi-validation.test.ts +++ b/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/openapi/openapi-validation.test.ts @@ -198,58 +198,67 @@ describe("PluginLedgerConnectorBesu", () => { }); test(`${testCase} - ${fDeploy} - ${cWithoutParams}`, async () => { - try { - const parameters = { - keychainId: keychainIdForUnsigned, - contractAbi: HelloWorldContractJson.abi, - constructorArgs: [], - web3SigningCredential: { - ethAccount: testEthAccount1.address, - secret: testEthAccount1.privateKey, - type: Web3SigningCredentialType.PrivateKeyHex, - }, - }; - await apiClient.deployContractSolBytecodeV1( - parameters as unknown as DeployContractSolidityBytecodeV1Request, - ); - } catch (e) { - expect(e.response.status).toEqual(400); - const fields = e.response.data.map((param: { readonly path: string }) => - param.path.replace("/body/", ""), - ); + const parameters = { + keychainId: keychainIdForUnsigned, + contractAbi: HelloWorldContractJson.abi, + constructorArgs: [], + web3SigningCredential: { + ethAccount: testEthAccount1.address, + secret: testEthAccount1.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + }; - expect(fields.includes("contractName")).toBeTrue(); - expect(fields.includes("bytecode")).toBeTrue(); - expect(fields.includes("gas")).toBeFalse(); - } + await expect( + apiClient.deployContractSolBytecodeV1( + parameters as unknown as DeployContractSolidityBytecodeV1Request, + ), + ).rejects.toMatchObject({ + response: { + status: 400, + data: expect.arrayContaining([ + expect.objectContaining({ + path: expect.stringContaining("/body/contractName"), + }), + expect.objectContaining({ + path: expect.stringContaining("/body/bytecode"), + }), + expect.not.objectContaining({ + path: expect.stringContaining("/body/gas"), + }), + ]), + }, + }); }); test(`${testCase} - ${fDeploy} - ${cInvalidParams}`, async () => { - try { - const parameters = { - keychainId: keychainIdForUnsigned, - contractName: HelloWorldContractJson.contractName, - contractAbi: HelloWorldContractJson.abi, - constructorArgs: [], - web3SigningCredential: { - ethAccount: testEthAccount1.address, - secret: testEthAccount1.privateKey, - type: Web3SigningCredentialType.PrivateKeyHex, - }, - bytecode: HelloWorldContractJson.bytecode, - gas: 1000000, - fake: 4, - }; - await apiClient.deployContractSolBytecodeV1( + const parameters = { + keychainId: keychainIdForUnsigned, + contractName: HelloWorldContractJson.contractName, + contractAbi: HelloWorldContractJson.abi, + constructorArgs: [], + web3SigningCredential: { + ethAccount: testEthAccount1.address, + secret: testEthAccount1.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + bytecode: HelloWorldContractJson.bytecode, + gas: 1000000, + fake: 4, + }; + + await expect( + apiClient.deployContractSolBytecodeV1( parameters as DeployContractSolidityBytecodeV1Request, - ); - } catch (e) { - expect(e.response.status).toEqual(400); - const fields = e.response.data.map((param: { readonly path: string }) => - param.path.replace("/body/", ""), - ); - expect(fields.includes("fake")).toBeTrue(); - } + ), + ).rejects.toMatchObject({ + response: { + status: 400, + data: expect.arrayContaining([ + expect.objectContaining({ path: "/body/fake" }), + ]), + }, + }); }); test(`${testCase} - ${fInvoke} - ${cOk}`, async () => { @@ -274,54 +283,62 @@ describe("PluginLedgerConnectorBesu", () => { }); test(`${testCase} - ${fInvoke} - ${cWithoutParams}`, async () => { - try { - const parameters = { - keychainId: keychainIdForUnsigned, - invocationType: EthContractInvocationType.Call, - methodName: "sayHello", - params: [], - signingCredential: { - ethAccount: testEthAccount1.address, - secret: testEthAccount1.privateKey, - type: Web3SigningCredentialType.PrivateKeyHex, - }, - }; - await apiClient.invokeContractV1( - parameters as any as InvokeContractV1Request, - ); - } catch (e) { - expect(e.response.status).toEqual(400); - const fields = e.response.data.map((param: { readonly path: string }) => - param.path.replace("/body/", ""), - ); - expect(fields.includes("contractName")).toBeTrue(); - expect(fields.includes("gas")).toBeFalse(); - } + const parameters = { + keychainId: keychainIdForUnsigned, + invocationType: EthContractInvocationType.Call, + methodName: "sayHello", + params: [], + signingCredential: { + ethAccount: testEthAccount1.address, + secret: testEthAccount1.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + }; + + await expect( + apiClient.invokeContractV1(parameters as any as InvokeContractV1Request), + ).rejects.toMatchObject({ + response: { + status: 400, + data: expect.arrayContaining([ + expect.objectContaining({ + path: expect.stringContaining("/body/contractName"), + }), + expect.not.objectContaining({ + path: expect.stringContaining("/body/gas"), + }), + ]), + }, + }); }); test(`${testCase} - ${fInvoke} - ${cInvalidParams}`, async () => { - try { - const parameters = { - contractName: "HelloWorld", - keychainId: keychainIdForUnsigned, - invocationType: EthContractInvocationType.Call, - methodName: "sayHello", - params: [], - signingCredential: { - ethAccount: testEthAccount1.address, - secret: testEthAccount1.privateKey, - type: Web3SigningCredentialType.PrivateKeyHex, - }, - fake: 4, - }; - await apiClient.invokeContractV1(parameters as InvokeContractV1Request); - } catch (e) { - expect(e.response.status).toEqual(400); - const fields = e.response.data.map((param: { readonly path: string }) => - param.path.replace("/body/", ""), - ); - expect(fields.includes("fake")).toBeTrue(); - } + const parameters = { + contractName: "HelloWorld", + keychainId: keychainIdForUnsigned, + invocationType: EthContractInvocationType.Call, + methodName: "sayHello", + params: [], + signingCredential: { + ethAccount: testEthAccount1.address, + secret: testEthAccount1.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + fake: 4, + }; + + await expect( + apiClient.invokeContractV1(parameters as InvokeContractV1Request), + ).rejects.toMatchObject({ + response: { + status: 400, + data: expect.arrayContaining([ + expect.objectContaining({ + path: expect.stringContaining("/body/fake"), + }), + ]), + }, + }); }); test(`${testCase} - ${fRun} - ${cOk}`, async () => { @@ -353,59 +370,67 @@ describe("PluginLedgerConnectorBesu", () => { }); test(`${testCase} - ${fRun} - ${cWithoutParams}`, async () => { - try { - const parameters = { - web3SigningCredential: { - ethAccount: testEthAccount1.address, - secret: testEthAccount1.privateKey, - type: Web3SigningCredentialType.PrivateKeyHex, - }, - transactionConfig: { - from: testEthAccount1.address, - to: testEthAccount2.address, - value: 10e7, - gas: 1000000, - }, - }; - await apiClient.runTransactionV1(parameters as RunTransactionRequest); - } catch (e) { - expect(e.response.status).toEqual(400); - const fields = e.response.data.map((param: { readonly path: string }) => - param.path.replace("/body/", ""), - ); - expect(fields.includes("consistencyStrategy")).toBeTrue(); - } + const parameters = { + web3SigningCredential: { + ethAccount: testEthAccount1.address, + secret: testEthAccount1.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + transactionConfig: { + from: testEthAccount1.address, + to: testEthAccount2.address, + value: 10e7, + gas: 1000000, + }, + }; + + await expect( + apiClient.runTransactionV1(parameters as RunTransactionRequest), + ).rejects.toMatchObject({ + response: { + status: 400, + data: expect.arrayContaining([ + expect.objectContaining({ + path: expect.stringContaining("/body/consistencyStrategy"), + }), + ]), + }, + }); }); test(`${testCase} - ${fRun} - ${cInvalidParams}`, async () => { - try { - const parameters = { - web3SigningCredential: { - ethAccount: testEthAccount1.address, - secret: testEthAccount1.privateKey, - type: Web3SigningCredentialType.PrivateKeyHex, - }, - transactionConfig: { - from: testEthAccount1.address, - to: testEthAccount2.address, - value: 10e7, - gas: 1000000, - }, - consistencyStrategy: { - blockConfirmations: 0, - receiptType: ReceiptType.NodeTxPoolAck, - timeoutMs: 5000, - }, - fake: 4, - }; - await apiClient.runTransactionV1(parameters as RunTransactionRequest); - } catch (e) { - expect(e.response.status).toEqual(400); - const fields = e.response.data.map((param: { readonly path: string }) => - param.path.replace("/body/", ""), - ); - expect(fields.includes("fake")).toBeTrue(); - } + const parameters = { + web3SigningCredential: { + ethAccount: testEthAccount1.address, + secret: testEthAccount1.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + transactionConfig: { + from: testEthAccount1.address, + to: testEthAccount2.address, + value: 10e7, + gas: 1000000, + }, + consistencyStrategy: { + blockConfirmations: 0, + receiptType: ReceiptType.NodeTxPoolAck, + timeoutMs: 5000, + }, + fake: 4, + }; + + await expect( + apiClient.runTransactionV1(parameters as RunTransactionRequest), + ).rejects.toMatchObject({ + response: { + status: 400, + data: expect.arrayContaining([ + expect.objectContaining({ + path: expect.stringContaining("/body/fake"), + }), + ]), + }, + }); }); test(`${testCase} - ${fSign} - ${cOk}`, async () => { @@ -482,21 +507,24 @@ describe("PluginLedgerConnectorBesu", () => { expect(runTxRes.data).toBeTruthy(); expect((runTxRes.data as any).data.transactionReceipt).toBeTruthy(); - try { - const parameters = { - keychainRef: keychainRefForSigned, - transactionHash: (runTxRes.data as any).data.transactionReceipt - .transactionHash, - }; + const parameters = { + keychainRef: keychainRefForSigned, + transactionHash: (runTxRes.data as any).data.transactionReceipt + .transactionHash, + }; - await apiClient.signTransactionV1(parameters as SignTransactionRequest); - } catch (e) { - expect(e.response.status).toEqual(400); - const fields = e.response.data.map((param: any) => - param.path.replace("/body/", ""), - ); - expect(fields.includes("keychainId")).toBeTrue(); - } + await expect( + apiClient.signTransactionV1(parameters as SignTransactionRequest), + ).rejects.toMatchObject({ + response: { + status: 400, + data: expect.arrayContaining([ + expect.objectContaining({ + path: expect.stringContaining("/body/keychainId"), + }), + ]), + }, + }); }); test(`${testCase} - ${fSign} - ${cInvalidParams}`, async () => { @@ -523,23 +551,26 @@ describe("PluginLedgerConnectorBesu", () => { expect(runTxRes.data).toBeTruthy(); expect((runTxRes.data as any).data.transactionReceipt).toBeTruthy(); - try { - const parameters = { - keychainId: keychainIdForSigned, - keychainRef: keychainRefForSigned, - transactionHash: (runTxRes.data as any).data.transactionReceipt - .transactionHash, - fake: 4, - }; - - await apiClient.signTransactionV1(parameters as SignTransactionRequest); - } catch (e) { - expect(e.response.status).toEqual(400); - const fields = e.response.data.map((param: { readonly path: string }) => - param.path.replace("/body/", ""), - ); - expect(fields.includes("fake")).toBeTrue(); - } + const parameters = { + keychainId: keychainIdForSigned, + keychainRef: keychainRefForSigned, + transactionHash: (runTxRes.data as any).data.transactionReceipt + .transactionHash, + fake: 4, + }; + + await expect( + apiClient.signTransactionV1(parameters as SignTransactionRequest), + ).rejects.toMatchObject({ + response: { + status: 400, + data: expect.arrayContaining([ + expect.objectContaining({ + path: expect.stringContaining("/body/fake"), + }), + ]), + }, + }); }); test(`${testCase} - ${fBalance} - ${cOk}`, async () => { @@ -550,32 +581,40 @@ describe("PluginLedgerConnectorBesu", () => { }); test(`${testCase} - ${fBalance} - ${cWithoutParams}`, async () => { - try { - const parameters = {}; - await apiClient.getBalanceV1(parameters as GetBalanceV1Request); - } catch (e) { - expect(e.response.status).toEqual(400); - const fields = e.response.data.map((param: { readonly path: string }) => - param.path.replace("/body/", ""), - ); - expect(fields.includes("address")).toBeTrue(); - } + const parameters = {}; // Empty parameters object + + await expect( + apiClient.getBalanceV1(parameters as GetBalanceV1Request), + ).rejects.toMatchObject({ + response: { + status: 400, + data: expect.arrayContaining([ + expect.objectContaining({ + path: expect.stringContaining("/body/address"), + }), + ]), + }, + }); }); test(`${testCase} - ${fBalance} - ${cInvalidParams}`, async () => { - try { - const parameters = { - address: firstHighNetWorthAccount, - fake: 4, - }; - await apiClient.getBalanceV1(parameters as GetBalanceV1Request); - } catch (e) { - expect(e.response.status).toEqual(400); - const fields = e.response.data.map((param: { readonly path: string }) => - param.path.replace("/body/", ""), - ); - expect(fields.includes("fake")).toBeTrue(); - } + const parameters = { + address: firstHighNetWorthAccount, + fake: 4, + }; + + await expect( + apiClient.getBalanceV1(parameters as GetBalanceV1Request), + ).rejects.toMatchObject({ + response: { + status: 400, + data: expect.arrayContaining([ + expect.objectContaining({ + path: expect.stringContaining("/body/fake"), + }), + ]), + }, + }); }); test(`${testCase} - ${fBlock} - ${cOk}`, async () => { @@ -586,32 +625,40 @@ describe("PluginLedgerConnectorBesu", () => { }); test(`${testCase} - ${fBlock} - ${cWithoutParams}`, async () => { - try { - const parameters = {}; - await apiClient.getBlockV1(parameters as GetBlockV1Request); - } catch (e) { - expect(e.response.status).toEqual(400); - const fields = e.response.data.map((param: { readonly path: string }) => - param.path.replace("/body/", ""), - ); - expect(fields.includes("blockHashOrBlockNumber")).toBeTrue(); - } + const parameters = {}; // Empty parameters object + + await expect( + apiClient.getBlockV1(parameters as GetBlockV1Request), + ).rejects.toMatchObject({ + response: { + status: 400, + data: expect.arrayContaining([ + expect.objectContaining({ + path: expect.stringContaining("/body/blockHashOrBlockNumber"), + }), + ]), + }, + }); }); test(`${testCase} - ${fBlock} - ${cInvalidParams}`, async () => { - try { - const parameters = { - blockHashOrBlockNumber: 0, - fake: 4, - }; - await apiClient.getBlockV1(parameters as GetBlockV1Request); - } catch (e) { - expect(e.response.status).toEqual(400); - const fields = e.response.data.map((param: { readonly path: string }) => - param.path.replace("/body/", ""), - ); - expect(fields.includes("fake")).toBeTrue(); - } + const parameters = { + blockHashOrBlockNumber: 0, + fake: 4, + }; + + await expect( + apiClient.getBlockV1(parameters as GetBlockV1Request), + ).rejects.toMatchObject({ + response: { + status: 400, + data: expect.arrayContaining([ + expect.objectContaining({ + path: expect.stringContaining("/body/fake"), + }), + ]), + }, + }); }); test(`${testCase} - ${fPastLogs} - ${cOk}`, async () => { @@ -626,7 +673,13 @@ describe("PluginLedgerConnectorBesu", () => { test(`${testCase} - ${fPastLogs} - ${cWithoutParams}`, async () => { try { const parameters = {}; - await apiClient.getPastLogsV1(parameters as GetPastLogsV1Request); + const response = await apiClient.getPastLogsV1( + parameters as GetPastLogsV1Request, + ); + console.log( + "e.response.status should be 400 but actually is,", + response.status, + ); } catch (e) { expect(e.response.status).toEqual(400); const fields = e.response.data.map((param: { readonly path: string }) => @@ -634,22 +687,40 @@ describe("PluginLedgerConnectorBesu", () => { ); expect(fields.includes("address")).toBeTrue(); } + + //since status code is actually 200 refactored approach does not work + + // const parameters = {}; // Empty parameters object + + // await expect(apiClient.getPastLogsV1(parameters as GetPastLogsV1Request)) + // .rejects.toMatchObject({ + // response: { + // status: 400, + // data: expect.arrayContaining([ + // expect.objectContaining({ path: expect.stringContaining("/body/address") }) + // ]) + // } + // }); }); test(`${testCase} - ${fPastLogs} - ${cInvalidParams}`, async () => { - try { - const parameters = { - address: firstHighNetWorthAccount, - fake: 4, - }; - await apiClient.getPastLogsV1(parameters as GetPastLogsV1Request); - } catch (e) { - expect(e.response.status).toEqual(400); - const fields = e.response.data.map((param: { readonly path: string }) => - param.path.replace("/body/", ""), - ); - expect(fields.includes("fake")).toBeTrue(); - } + const parameters = { + address: firstHighNetWorthAccount, + fake: 4, + }; + + await expect( + apiClient.getPastLogsV1(parameters as GetPastLogsV1Request), + ).rejects.toMatchObject({ + response: { + status: 400, + data: expect.arrayContaining([ + expect.objectContaining({ + path: expect.stringContaining("/body/fake"), + }), + ]), + }, + }); }); test(`${testCase} - ${fRecord} - ${cOk}`, async () => { @@ -692,7 +763,13 @@ describe("PluginLedgerConnectorBesu", () => { test(`${testCase} - ${fRecord} - ${cWithoutParams}`, async () => { try { const parameters = {}; - await apiClient.getBesuRecordV1(parameters as GetBesuRecordV1Request); + const response = await apiClient.getBesuRecordV1( + parameters as GetBesuRecordV1Request, + ); + console.log( + "e.response.status should be 400 but actually is,", + response.status, + ); } catch (e) { expect(e.response.status).toEqual(400); const fields = e.response.data.map((param: any) => @@ -700,22 +777,40 @@ describe("PluginLedgerConnectorBesu", () => { ); expect(fields.includes("transactionHash")).toBeTrue(); } + + // since status code is actually 200 refactored approach does not work + + // const parameters = {}; // Empty parameters object + + // await expect(apiClient.getBesuRecordV1(parameters as GetBesuRecordV1Request)) + // .rejects.toMatchObject({ + // response: { + // status: 400, + // data: expect.arrayContaining([ + // expect.objectContaining({ path: expect.stringContaining("/body/transactionHash") }) + // ]) + // } + // }); }); test(`${testCase} - ${fRecord} - ${cInvalidParams}`, async () => { - try { - const parameters = { - transactionHash: "", - fake: 5, - }; - await apiClient.getBesuRecordV1(parameters as GetBesuRecordV1Request); - } catch (e) { - expect(e.response.status).toEqual(400); - const fields = e.response.data.map((param: { readonly path: string }) => - param.path.replace("/body/", ""), - ); - expect(fields.includes("fake")).toBeTrue(); - } + const parameters = { + transactionHash: "", + fake: 5, + }; + + await expect( + apiClient.getBesuRecordV1(parameters as GetBesuRecordV1Request), + ).rejects.toMatchObject({ + response: { + status: 400, + data: expect.arrayContaining([ + expect.objectContaining({ + path: expect.stringContaining("/body/fake"), + }), + ]), + }, + }); }); afterAll(async () => { From 6872ec53485b3b960fc3f88d162510646a2272ab Mon Sep 17 00:00:00 2001 From: Peter Somogyvari Date: Wed, 28 Aug 2024 09:21:43 -0700 Subject: [PATCH 4/8] test(test-tooling): jest migrate postgres container constructor options Signed-off-by: Peter Somogyvari --- .github/workflows/ci.yaml | 2 +- .taprc | 1 - jest.config.js | 1 - .../constructor-validates-options.test.ts | 58 ++++++++++--------- 4 files changed, 32 insertions(+), 30 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4ce1f2261cc..06dfcbab853 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -2469,7 +2469,7 @@ jobs: JEST_TEST_COVERAGE_PATH: ./code-coverage-ts/cactus-test-tooling JEST_TEST_CODE_COVERAGE_ENABLED: true TAPE_TEST_PATTERN: >- - --files={./packages/cactus-test-tooling/src/test/typescript/integration/besu/besu-test-ledger/constructor-validates-options.test.ts,./packages/cactus-test-tooling/src/test/typescript/integration/fabric/fabric-test-ledger-v1/constructor-validates-options.test.ts,./packages/cactus-test-tooling/src/test/typescript/integration/postgres/postgres-test-container/constructor-validates-options.test.ts,./packages/cactus-test-tooling/src/test/typescript/integration/substrate/substrate-test-ledger-constructor.test.ts,./packages/cactus-test-tooling/src/test/typescript/integration/substrate/substrate-test-ledger-multiple-concurrent.test.ts} + --files={./packages/cactus-test-tooling/src/test/typescript/integration/besu/besu-test-ledger/constructor-validates-options.test.ts,./packages/cactus-test-tooling/src/test/typescript/integration/fabric/fabric-test-ledger-v1/constructor-validates-options.test.ts,./packages/cactus-test-tooling/src/test/typescript/integration/substrate/substrate-test-ledger-constructor.test.ts,./packages/cactus-test-tooling/src/test/typescript/integration/substrate/substrate-test-ledger-multiple-concurrent.test.ts} TAPE_TEST_RUNNER_DISABLED: false runs-on: ubuntu-22.04 steps: diff --git a/.taprc b/.taprc index 4708a6f5bfe..778acc0186b 100644 --- a/.taprc +++ b/.taprc @@ -44,7 +44,6 @@ files: - ./packages/cactus-plugin-keychain-vault/src/test/typescript/integration/cactus-keychain-vault-server.test.ts - ./packages/cactus-plugin-keychain-vault/src/test/typescript/integration/plugin-keychain-vault.test.ts - ./packages/cactus-plugin-keychain-vault/src/test/typescript/integration/openapi/openapi-validation.test.ts - - ./packages/cactus-test-tooling/src/test/typescript/integration/postgres/postgres-test-container/constructor-validates-options.test.ts - ./packages/cactus-test-tooling/src/test/typescript/integration/fabric/fabric-test-ledger-v1/constructor-validates-options.test.ts - ./packages/cactus-test-tooling/src/test/typescript/integration/substrate/substrate-test-ledger-constructor.test.ts - ./packages/cactus-test-tooling/src/test/typescript/integration/substrate/substrate-test-ledger-multiple-concurrent.test.ts diff --git a/jest.config.js b/jest.config.js index c42adbdcab5..d369e76fe64 100644 --- a/jest.config.js +++ b/jest.config.js @@ -56,7 +56,6 @@ module.exports = { `./packages/cactus-plugin-keychain-vault/src/test/typescript/integration/cactus-keychain-vault-server.test.ts`, `./packages/cactus-plugin-keychain-vault/src/test/typescript/integration/plugin-keychain-vault.test.ts`, `./packages/cactus-plugin-keychain-vault/src/test/typescript/integration/openapi/openapi-validation.test.ts`, - `./packages/cactus-test-tooling/src/test/typescript/integration/postgres/postgres-test-container/constructor-validates-options.test.ts`, `./packages/cactus-test-tooling/src/test/typescript/integration/fabric/fabric-test-ledger-v1/constructor-validates-options.test.ts`, `./packages/cactus-test-tooling/src/test/typescript/integration/substrate/substrate-test-ledger-constructor.test.ts`, `./packages/cactus-test-tooling/src/test/typescript/integration/substrate/substrate-test-ledger-multiple-concurrent.test.ts`, diff --git a/packages/cactus-test-tooling/src/test/typescript/integration/postgres/postgres-test-container/constructor-validates-options.test.ts b/packages/cactus-test-tooling/src/test/typescript/integration/postgres/postgres-test-container/constructor-validates-options.test.ts index d2bd7938a11..217fbf6c7e6 100644 --- a/packages/cactus-test-tooling/src/test/typescript/integration/postgres/postgres-test-container/constructor-validates-options.test.ts +++ b/packages/cactus-test-tooling/src/test/typescript/integration/postgres/postgres-test-container/constructor-validates-options.test.ts @@ -1,42 +1,46 @@ -import test, { Test } from "tape-promise/tape"; +import "jest-extended"; import isPortReachable from "is-port-reachable"; import { Container } from "dockerode"; import { PostgresTestContainer } from "../../../../../main/typescript/public-api"; import { LogLevelDesc } from "@hyperledger/cactus-common"; -const logLevel: LogLevelDesc = "TRACE"; +const logLevel: LogLevelDesc = "INFO"; -test("constructor throws if invalid input is provided", (assert: Test) => { - assert.ok(PostgresTestContainer); - assert.throws(() => new PostgresTestContainer({ imageVersion: "nope" })); - assert.end(); -}); - -test("constructor does not throw if valid input is provided", (assert: Test) => { - assert.ok(PostgresTestContainer); - assert.doesNotThrow(() => new PostgresTestContainer()); - assert.end(); -}); - -test("starts/stops/destroys a docker container", async (assert: Test) => { +describe("PostgresTestContainer", () => { const postgresTestContainer = new PostgresTestContainer({ logLevel }); + let postgresContainer: Container; + + beforeAll(async () => { + postgresContainer = await postgresTestContainer.start(); + }); - const postgresContainer: Container = await postgresTestContainer.start(); - test.onFinish(async () => { + afterAll(async () => { await postgresTestContainer.stop(); }); - assert.ok(postgresContainer); - const ipAddress: string = await postgresTestContainer.getContainerIpAddress(); - assert.ok(ipAddress); - assert.ok(ipAddress.length); + it("constructor throws if invalid input is provided", () => { + expect(PostgresTestContainer).toBeTruthy(); + expect( + () => new PostgresTestContainer({ imageVersion: "nope" }), + ).toThrowError(); + }); - const hostPort: number = await postgresTestContainer.getPostgresPort(); - assert.ok(hostPort, "getRpcApiPublicPort() returns truthy OK"); - assert.ok(isFinite(hostPort), "getRpcApiPublicPort() returns finite OK"); + it("constructor does not throw if valid input is provided", () => { + expect(PostgresTestContainer).toBeTruthy(); + expect(() => new PostgresTestContainer()).not.toThrow(); + }); - const isReachable = await isPortReachable(hostPort, { host: "127.0.0.1" }); - assert.ok(isReachable, `HostPort ${hostPort} is reachable via 127.0.0.1`); + it("starts/stops/destroys a docker container", async () => { + expect(postgresContainer).toBeTruthy(); + const ip: string = await postgresTestContainer.getContainerIpAddress(); + expect(ip).toBeString(); + expect(ip).not.toBeEmpty(); - assert.end(); + const hostPort: number = await postgresTestContainer.getPostgresPort(); + expect(hostPort).toBeTruthy(); + expect(hostPort).toBeFinite(); + + const reachabilityCheck = isPortReachable(hostPort, { host: "127.0.0.1" }); + expect(reachabilityCheck).resolves.toBeTrue(); + }); }); From e97e27bca0a8fb4b52c716ee25437d69efff74d4 Mon Sep 17 00:00:00 2001 From: Peter Somogyvari Date: Thu, 25 Jul 2024 08:19:31 -0700 Subject: [PATCH 5/8] fix(security): address CVE-2022-3517 - minimatch < 3.0.5 ReDoS vuln Updated mocha to newer versions which do not depend on the old minimatch Signed-off-by: Peter Somogyvari --- .../iin-agent/package-local.json | 2 +- .../iin-agent/package.json | 2 +- weaver/sdks/besu/node/package-local.json | 2 +- weaver/sdks/besu/node/package.json | 2 +- .../package-local.json | 2 +- .../interoperation-node-sdk/package.json | 2 +- yarn.lock | 203 +++++++++--------- 7 files changed, 103 insertions(+), 112 deletions(-) diff --git a/weaver/core/identity-management/iin-agent/package-local.json b/weaver/core/identity-management/iin-agent/package-local.json index 4d8e86b9e98..33a014fbbce 100644 --- a/weaver/core/identity-management/iin-agent/package-local.json +++ b/weaver/core/identity-management/iin-agent/package-local.json @@ -35,7 +35,7 @@ "chai": "4.3.7", "chai-as-promised": "7.1.1", "jsrsasign": "11.0.0", - "mocha": "5.2.0", + "mocha": "10.7.3", "nodemon": "2.0.22", "nyc": "12.0.2", "proto3-json-serializer": "1.1.1", diff --git a/weaver/core/identity-management/iin-agent/package.json b/weaver/core/identity-management/iin-agent/package.json index 3d463cc9977..c953b31b6be 100644 --- a/weaver/core/identity-management/iin-agent/package.json +++ b/weaver/core/identity-management/iin-agent/package.json @@ -35,7 +35,7 @@ "chai": "4.3.7", "chai-as-promised": "7.1.1", "jsrsasign": "11.0.0", - "mocha": "5.2.0", + "mocha": "10.7.3", "nodemon": "2.0.22", "nyc": "12.0.2", "proto3-json-serializer": "1.1.1", diff --git a/weaver/sdks/besu/node/package-local.json b/weaver/sdks/besu/node/package-local.json index 75a148dcbd3..0cb443b661c 100644 --- a/weaver/sdks/besu/node/package-local.json +++ b/weaver/sdks/besu/node/package-local.json @@ -23,7 +23,7 @@ "@types/node": "18.11.9", "chai": "4.3.7", "chai-as-promised": "7.1.1", - "mocha": "5.2.0", + "mocha": "10.7.3", "nyc": "12.0.2", "rewire": "4.0.1", "sinon": "6.3.5", diff --git a/weaver/sdks/besu/node/package.json b/weaver/sdks/besu/node/package.json index 7b22dceeaee..fa703fe8bab 100644 --- a/weaver/sdks/besu/node/package.json +++ b/weaver/sdks/besu/node/package.json @@ -23,7 +23,7 @@ "@types/node": "18.11.9", "chai": "4.3.7", "chai-as-promised": "7.1.1", - "mocha": "5.2.0", + "mocha": "10.7.3", "nyc": "12.0.2", "rewire": "4.0.1", "sinon": "6.3.5", diff --git a/weaver/sdks/fabric/interoperation-node-sdk/package-local.json b/weaver/sdks/fabric/interoperation-node-sdk/package-local.json index 564d9d0c55c..ce9bbdf3e89 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/package-local.json +++ b/weaver/sdks/fabric/interoperation-node-sdk/package-local.json @@ -56,7 +56,7 @@ "@types/node": "18.11.9", "chai": "4.3.7", "chai-as-promised": "7.1.1", - "mocha": "5.2.0", + "mocha": "10.7.3", "nyc": "12.0.2", "rewire": "4.0.1", "sinon": "6.3.5", diff --git a/weaver/sdks/fabric/interoperation-node-sdk/package.json b/weaver/sdks/fabric/interoperation-node-sdk/package.json index adaab89eaf1..841d5555613 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/package.json +++ b/weaver/sdks/fabric/interoperation-node-sdk/package.json @@ -56,7 +56,7 @@ "@types/node": "18.11.9", "chai": "4.3.7", "chai-as-promised": "7.1.1", - "mocha": "5.2.0", + "mocha": "10.7.3", "nyc": "12.0.2", "rewire": "4.0.1", "sinon": "6.3.5", diff --git a/yarn.lock b/yarn.lock index 6fc568abf66..cd9906a5a14 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9277,7 +9277,7 @@ __metadata: fabric-common: "npm:2.2.20" fabric-network: "npm:2.2.20" jsrsasign: "npm:11.0.0" - mocha: "npm:5.2.0" + mocha: "npm:10.7.3" nodemon: "npm:2.0.22" nyc: "npm:12.0.2" proto3-json-serializer: "npm:1.1.1" @@ -9312,7 +9312,7 @@ __metadata: chai: "npm:4.3.7" chai-as-promised: "npm:7.1.1" log4js: "npm:6.9.1" - mocha: "npm:5.2.0" + mocha: "npm:10.7.3" nyc: "npm:12.0.2" rewire: "npm:4.0.1" sinon: "npm:6.3.5" @@ -9342,7 +9342,7 @@ __metadata: js-sha3: "npm:0.8.0" jsrsasign: "npm:11.0.0" log4js: "npm:6.9.1" - mocha: "npm:5.2.0" + mocha: "npm:10.7.3" nyc: "npm:12.0.2" pkcs11js: "npm:1.3.1" rewire: "npm:4.0.1" @@ -19384,7 +19384,7 @@ __metadata: languageName: node linkType: hard -"ansi-colors@npm:4.1.3": +"ansi-colors@npm:4.1.3, ansi-colors@npm:^4.1.3": version: 4.1.3 resolution: "ansi-colors@npm:4.1.3" checksum: 10/43d6e2fc7b1c6e4dc373de708ee76311ec2e0433e7e8bd3194e7ff123ea6a747428fc61afdcf5969da5be3a5f0fd054602bec56fc0ebe249ce2fcde6e649e3c2 @@ -21474,7 +21474,7 @@ __metadata: languageName: node linkType: hard -"browser-stdout@npm:1.3.1": +"browser-stdout@npm:1.3.1, browser-stdout@npm:^1.3.1": version: 1.3.1 resolution: "browser-stdout@npm:1.3.1" checksum: 10/ac70a84e346bb7afc5045ec6f22f6a681b15a4057447d4cc1c48a25c6dedb302a49a46dd4ddfb5cdd9c96e0c905a8539be1b98ae7bc440512152967009ec7015 @@ -23278,13 +23278,6 @@ __metadata: languageName: node linkType: hard -"commander@npm:2.15.1": - version: 2.15.1 - resolution: "commander@npm:2.15.1" - checksum: 10/6f4545833348d61dd0c3b285c7f0dc9bc8b1bdac38b512d263184918811382c646c38d58c1102caeff0eb57d4bbd526efc5e6116a78b6af7c1aad6fb628678a8 - languageName: node - linkType: hard - "commander@npm:3.0.2": version: 3.0.2 resolution: "commander@npm:3.0.2" @@ -25083,6 +25076,18 @@ __metadata: languageName: node linkType: hard +"debug@npm:^4.3.5": + version: 4.3.6 + resolution: "debug@npm:4.3.6" + dependencies: + ms: "npm:2.1.2" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10/d3adb9af7d57a9e809a68f404490cf776122acca16e6359a2702c0f462e510e91f9765c07f707b8ab0d91e03bad57328f3256f5082631cefb5393d0394d50fb7 + languageName: node + linkType: hard + "decamelize-keys@npm:^1.1.0": version: 1.1.0 resolution: "decamelize-keys@npm:1.1.0" @@ -25849,13 +25854,6 @@ __metadata: languageName: node linkType: hard -"diff@npm:3.5.0, diff@npm:^3.0.0, diff@npm:^3.1.0, diff@npm:^3.5.0": - version: 3.5.0 - resolution: "diff@npm:3.5.0" - checksum: 10/cfbc2df98d6f8eb82c0f7735c8468695f65189d31f95a708d4c97cd96a8083fdfd83d87a067a29924ae7d8ff64f578e7da78391af537815750268555fe0df9f0 - languageName: node - linkType: hard - "diff@npm:5.0.0": version: 5.0.0 resolution: "diff@npm:5.0.0" @@ -25863,6 +25861,13 @@ __metadata: languageName: node linkType: hard +"diff@npm:^3.0.0, diff@npm:^3.1.0, diff@npm:^3.5.0": + version: 3.5.0 + resolution: "diff@npm:3.5.0" + checksum: 10/cfbc2df98d6f8eb82c0f7735c8468695f65189d31f95a708d4c97cd96a8083fdfd83d87a067a29924ae7d8ff64f578e7da78391af537815750268555fe0df9f0 + languageName: node + linkType: hard + "diff@npm:^4.0.1, diff@npm:^4.0.2": version: 4.0.2 resolution: "diff@npm:4.0.2" @@ -25870,6 +25875,13 @@ __metadata: languageName: node linkType: hard +"diff@npm:^5.2.0": + version: 5.2.0 + resolution: "diff@npm:5.2.0" + checksum: 10/01b7b440f83a997350a988e9d2f558366c0f90f15be19f4aa7f1bb3109a4e153dfc3b9fbf78e14ea725717017407eeaa2271e3896374a0181e8f52445740846d + languageName: node + linkType: hard + "diffie-hellman@npm:^5.0.0": version: 5.0.3 resolution: "diffie-hellman@npm:5.0.3" @@ -27434,13 +27446,6 @@ __metadata: languageName: node linkType: hard -"escape-string-regexp@npm:1.0.5, escape-string-regexp@npm:^1.0.2, escape-string-regexp@npm:^1.0.5": - version: 1.0.5 - resolution: "escape-string-regexp@npm:1.0.5" - checksum: 10/6092fda75c63b110c706b6a9bfde8a612ad595b628f0bd2147eea1d3406723020810e591effc7db1da91d80a71a737a313567c5abb3813e8d9c71f4aa595b410 - languageName: node - linkType: hard - "escape-string-regexp@npm:4.0.0, escape-string-regexp@npm:^4.0.0": version: 4.0.0 resolution: "escape-string-regexp@npm:4.0.0" @@ -27455,6 +27460,13 @@ __metadata: languageName: node linkType: hard +"escape-string-regexp@npm:^1.0.2, escape-string-regexp@npm:^1.0.5": + version: 1.0.5 + resolution: "escape-string-regexp@npm:1.0.5" + checksum: 10/6092fda75c63b110c706b6a9bfde8a612ad595b628f0bd2147eea1d3406723020810e591effc7db1da91d80a71a737a313567c5abb3813e8d9c71f4aa595b410 + languageName: node + linkType: hard + "escape-string-regexp@npm:^2.0.0": version: 2.0.0 resolution: "escape-string-regexp@npm:2.0.0" @@ -31093,20 +31105,6 @@ __metadata: languageName: node linkType: hard -"glob@npm:7.1.2": - version: 7.1.2 - resolution: "glob@npm:7.1.2" - dependencies: - fs.realpath: "npm:^1.0.0" - inflight: "npm:^1.0.4" - inherits: "npm:2" - minimatch: "npm:^3.0.4" - once: "npm:^1.3.0" - path-is-absolute: "npm:^1.0.0" - checksum: 10/0ce897e53cdb4c8e5ade0d8b93ecc2200cf32a4e929a884d4fdbbb47d52217607d8f88f21e4be68bbcfa5c3a9c5bcda8db42d86ca25c759c94dc2a829c84fee3 - languageName: node - linkType: hard - "glob@npm:7.1.6": version: 7.1.6 resolution: "glob@npm:7.1.6" @@ -31209,6 +31207,19 @@ __metadata: languageName: node linkType: hard +"glob@npm:^8.1.0": + version: 8.1.0 + resolution: "glob@npm:8.1.0" + dependencies: + fs.realpath: "npm:^1.0.0" + inflight: "npm:^1.0.4" + inherits: "npm:2" + minimatch: "npm:^5.0.1" + once: "npm:^1.3.0" + checksum: 10/9aab1c75eb087c35dbc41d1f742e51d0507aa2b14c910d96fb8287107a10a22f4bbdce26fc0a3da4c69a20f7b26d62f1640b346a4f6e6becfff47f335bb1dc5e + languageName: node + linkType: hard + "glob@npm:^9.3.0, glob@npm:^9.3.1": version: 9.3.4 resolution: "glob@npm:9.3.4" @@ -31686,13 +31697,6 @@ __metadata: languageName: node linkType: hard -"growl@npm:1.10.5": - version: 1.10.5 - resolution: "growl@npm:1.10.5" - checksum: 10/1391a9add951964de566adc0aee8b0e2b2321e768c1fdccb7a8e156d6a6cd7ea72782883ba8c2c307baf524e3059519423b72e585eba5e7a5f6e83a1e2359b0d - languageName: node - linkType: hard - "grpc-tools@npm:1.12.4": version: 1.12.4 resolution: "grpc-tools@npm:1.12.4" @@ -32166,15 +32170,6 @@ __metadata: languageName: node linkType: hard -"he@npm:1.1.1": - version: 1.1.1 - resolution: "he@npm:1.1.1" - bin: - he: bin/he - checksum: 10/b5c86603e9a109caa54d95d0ea6f00ac0c1d09a6299bbe72102f96fd11f0ab889869cdb4519894cfb5bc553bcb55ae1bcd53c04a123b66c01d0198de43a47c61 - languageName: node - linkType: hard - "he@npm:1.2.0, he@npm:^1.2.0": version: 1.2.0 resolution: "he@npm:1.2.0" @@ -39170,15 +39165,6 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:3.0.4": - version: 3.0.4 - resolution: "minimatch@npm:3.0.4" - dependencies: - brace-expansion: "npm:^1.1.7" - checksum: 10/3b3f17f76582417dd139646505f1d1bb5f148ea5191eb98fe73cd41224a678dadb94cc674c7d06b36de4ab5c303f039cfd7cd2d089348d6f70d04db169cf3770 - languageName: node - linkType: hard - "minimatch@npm:3.0.5": version: 3.0.5 resolution: "minimatch@npm:3.0.5" @@ -39215,7 +39201,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^5.0.1": +"minimatch@npm:^5.0.1, minimatch@npm:^5.1.6": version: 5.1.6 resolution: "minimatch@npm:5.1.6" dependencies: @@ -39479,17 +39465,6 @@ __metadata: languageName: node linkType: hard -"mkdirp@npm:0.5.1": - version: 0.5.1 - resolution: "mkdirp@npm:0.5.1" - dependencies: - minimist: "npm:0.0.8" - bin: - mkdirp: bin/cmd.js - checksum: 10/8651af2facdfa53f39e68fd93cf1653c11f7c1d49c6d1b4e53bcedc52e669cc64f1b5e95c49cfde7e99dbbcad26d3e61f4f2b4812f18c871c6455d9592f02806 - languageName: node - linkType: hard - "mkdirp@npm:^0.5.0, mkdirp@npm:^0.5.1, mkdirp@npm:^0.5.3, mkdirp@npm:^0.5.4, mkdirp@npm:^0.5.5, mkdirp@npm:~0.5.1": version: 0.5.6 resolution: "mkdirp@npm:0.5.6" @@ -39542,25 +39517,34 @@ __metadata: languageName: node linkType: hard -"mocha@npm:5.2.0": - version: 5.2.0 - resolution: "mocha@npm:5.2.0" +"mocha@npm:10.7.3": + version: 10.7.3 + resolution: "mocha@npm:10.7.3" dependencies: - browser-stdout: "npm:1.3.1" - commander: "npm:2.15.1" - debug: "npm:3.1.0" - diff: "npm:3.5.0" - escape-string-regexp: "npm:1.0.5" - glob: "npm:7.1.2" - growl: "npm:1.10.5" - he: "npm:1.1.1" - minimatch: "npm:3.0.4" - mkdirp: "npm:0.5.1" - supports-color: "npm:5.4.0" + ansi-colors: "npm:^4.1.3" + browser-stdout: "npm:^1.3.1" + chokidar: "npm:^3.5.3" + debug: "npm:^4.3.5" + diff: "npm:^5.2.0" + escape-string-regexp: "npm:^4.0.0" + find-up: "npm:^5.0.0" + glob: "npm:^8.1.0" + he: "npm:^1.2.0" + js-yaml: "npm:^4.1.0" + log-symbols: "npm:^4.1.0" + minimatch: "npm:^5.1.6" + ms: "npm:^2.1.3" + serialize-javascript: "npm:^6.0.2" + strip-json-comments: "npm:^3.1.1" + supports-color: "npm:^8.1.1" + workerpool: "npm:^6.5.1" + yargs: "npm:^16.2.0" + yargs-parser: "npm:^20.2.9" + yargs-unparser: "npm:^2.0.0" bin: - _mocha: ./bin/_mocha - mocha: ./bin/mocha - checksum: 10/a0ba00626d4875e0d144b40accea1cc071d46ae31e90e17e19f90a23bfd3cc3d369957268d6315dfb0d5eb107a9bb6619bb30503a1d3015f21f45fc0a2754b83 + _mocha: bin/_mocha + mocha: bin/mocha.js + checksum: 10/5757aeb320df2507338bfba41731070ce16d27177c5876672fff4bcc4f7b7bcf1afe6ec761bfded43a5d28032d7b797b8b905b5b44c9420203f3ee71457732c1 languageName: node linkType: hard @@ -39697,7 +39681,7 @@ __metadata: languageName: node linkType: hard -"ms@npm:2.1.3, ms@npm:^2.0.0, ms@npm:^2.1.1, ms@npm:^2.1.2": +"ms@npm:2.1.3, ms@npm:^2.0.0, ms@npm:^2.1.1, ms@npm:^2.1.2, ms@npm:^2.1.3": version: 2.1.3 resolution: "ms@npm:2.1.3" checksum: 10/aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d @@ -47784,6 +47768,15 @@ __metadata: languageName: node linkType: hard +"serialize-javascript@npm:^6.0.2": + version: 6.0.2 + resolution: "serialize-javascript@npm:6.0.2" + dependencies: + randombytes: "npm:^2.1.0" + checksum: 10/445a420a6fa2eaee4b70cbd884d538e259ab278200a2ededd73253ada17d5d48e91fb1f4cd224a236ab62ea7ba0a70c6af29fc93b4f3d3078bf7da1c031fde58 + languageName: node + linkType: hard + "serve-index@npm:^1.9.1": version: 1.9.1 resolution: "serve-index@npm:1.9.1" @@ -49840,16 +49833,7 @@ __metadata: languageName: node linkType: hard -"supports-color@npm:5.4.0": - version: 5.4.0 - resolution: "supports-color@npm:5.4.0" - dependencies: - has-flag: "npm:^3.0.0" - checksum: 10/11a1faa8e02c1c4f528cdfea6a41d4c823c0b9d7280e14684bbac554c6a32a1c800c0fcc5d148764a071fd94be5c2dbd301cd1fe95daa029296c4ef36ae62d01 - languageName: node - linkType: hard - -"supports-color@npm:8.1.1, supports-color@npm:^8.0.0, supports-color@npm:^8.1.0": +"supports-color@npm:8.1.1, supports-color@npm:^8.0.0, supports-color@npm:^8.1.0, supports-color@npm:^8.1.1": version: 8.1.1 resolution: "supports-color@npm:8.1.1" dependencies: @@ -56052,6 +56036,13 @@ __metadata: languageName: node linkType: hard +"workerpool@npm:^6.5.1": + version: 6.5.1 + resolution: "workerpool@npm:6.5.1" + checksum: 10/b1b00139fe62f2ebec556a2af8085bf6e7502ad26cf2a4dcb34fb4408b2e68aa12c88b0a50cb463b24f2806d60fa491fc0da933b56ec3b53646aeec0025d14cb + languageName: node + linkType: hard + "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": version: 7.0.0 resolution: "wrap-ansi@npm:7.0.0" @@ -56507,7 +56498,7 @@ __metadata: languageName: node linkType: hard -"yargs-unparser@npm:2.0.0": +"yargs-unparser@npm:2.0.0, yargs-unparser@npm:^2.0.0": version: 2.0.0 resolution: "yargs-unparser@npm:2.0.0" dependencies: From 444e04cf796f29aac9fd4a860638ca064645dc08 Mon Sep 17 00:00:00 2001 From: Peter Somogyvari Date: Sat, 22 Jun 2024 00:20:16 +0000 Subject: [PATCH 6/8] build(connector-corda): upgrade to Spring Boot v3.3.1 IMPORTANT: The project now needs JDK 17 and Gradle 8 for development. 1. The bean validation has been replaced to the jakarta flavor as mandated by the spring boot upgrade. 2. Request bodies in the OpenAPI spec for Corda v4 were made mandatory where applicable (which is most of the endpoints) 3. The Open API spec based request validation test case has been moved to the new Corda v4.12 test case which now builds both the connector JVM app and the AIO image at runtime so that we can guarantee that the latest code changes are being verified. 4. Added quicker and easier steps in the readme of the corda connector to run trivy scans on the .jar files instead of the container images. The .jar files are 20x faster to build and scanning them instead of the container images doesn't suffer from the problem that the dev build dependencies are showing up in the scans (creating false positives) 5. Updated the CI to use the .jar file for scanning as well instead of the container image. Signed-off-by: Peter Somogyvari --- .cspell.json | 2 + .devcontainer/devcontainer.json | 11 +- .github/workflows/ci.yaml | 31 +- .../README.md | 15 +- .../src/main-server/Dockerfile | 10 +- .../src/main-server/healthcheck.sh | 4 +- .../gen/kotlin-spring/.idea/compiler.xml | 2 +- .../kotlin-spring/.idea/jarRepositories.xml | 10 + .../kotlin/gen/kotlin-spring/.idea/misc.xml | 3 +- .../kotlin/gen/kotlin-spring/.trivyignore | 17 + .../kotlin/gen/kotlin-spring/README.md | 2 +- .../kotlin/gen/kotlin-spring/build.gradle.kts | 56 +- .../gen/kotlin-spring/gradle.properties | 2 +- .../gradle/wrapper/gradle-wrapper.jar | Bin 59203 -> 62076 bytes .../gradle/wrapper/gradle-wrapper.properties | 3 +- .../kotlin/gen/kotlin-spring/gradlew | 276 +++++--- .../kotlin/gen/kotlin-spring/gradlew.bat | 15 +- .../kotlin/gen/kotlin-spring/pom.xml | 130 ---- .../kotlin/gen/kotlin-spring/settings.gradle | 6 + .../connector/corda/server/Application.kt | 25 +- ...ApiPluginLedgerConnectorCordaController.kt | 50 +- .../ApiPluginLedgerConnectorCordaService.kt | 28 +- .../connector/corda/server/api/ApiUtil.kt | 2 +- ...piPluginLedgerConnectorCordaServiceImpl.kt | 84 +-- .../CordaNetworkMapSnapshotJsonSerializer.kt | 76 +++ .../server/impl/InMemoryHostKeyVerifier.kt | 8 + .../corda/server/impl/NodeRPCConnection.kt | 19 +- .../server/impl/StateMonitorClientSession.kt | 2 +- .../impl/StateMonitorSessionsManager.kt | 2 +- .../connector/corda/server/model/CPIIDV1.kt | 18 +- .../ClearMonitorTransactionsV1Request.kt | 18 +- .../ClearMonitorTransactionsV1Response.kt | 18 +- .../server/model/CordaNodeSshCredentials.kt | 18 +- .../corda/server/model/CordaRpcCredentials.kt | 18 +- .../corda/server/model/CordaX500Name.kt | 18 +- .../server/model/CordappDeploymentConfig.kt | 18 +- .../corda/server/model/CordappInfo.kt | 18 +- .../DeployContractJarsBadRequestV1Response.kt | 18 +- .../DeployContractJarsSuccessV1Response.kt | 18 +- .../model/DeployContractJarsV1Request.kt | 18 +- .../server/model/DiagnoseNodeV1Request.kt | 18 +- .../server/model/DiagnoseNodeV1Response.kt | 18 +- .../corda/server/model/FlowInvocationType.kt | 18 +- .../server/model/FlowStatusV1Responses.kt | 18 +- ...atusV1ResponsesFlowStatusResponsesInner.kt | 18 +- .../corda/server/model/FlowV1Error.kt | 18 +- .../corda/server/model/GetFlowCidV1Request.kt | 18 +- .../server/model/GetFlowCidV1Response.kt | 18 +- .../model/GetMonitorTransactionsV1Request.kt | 18 +- .../model/GetMonitorTransactionsV1Response.kt | 18 +- ...GetMonitorTransactionsV1ResponseTxInner.kt | 18 +- .../server/model/InvokeContractV1Request.kt | 18 +- .../server/model/InvokeContractV1Response.kt | 18 +- .../connector/corda/server/model/JarFile.kt | 18 +- .../connector/corda/server/model/JvmObject.kt | 18 +- .../connector/corda/server/model/JvmType.kt | 18 +- .../corda/server/model/JvmTypeKind.kt | 18 +- .../corda/server/model/ListCpiV1Request.kt | 18 +- .../corda/server/model/ListCpiV1Response.kt | 18 +- .../model/ListCpiV1ResponseCpisInner.kt | 18 +- .../ListCpiV1ResponseCpisInnerCpksInner.kt | 18 +- .../corda/server/model/ListFlowsV1Request.kt | 18 +- .../corda/server/model/ListFlowsV1Response.kt | 18 +- .../corda/server/model/NetworkHostAndPort.kt | 18 +- .../corda/server/model/NodeDiagnosticInfo.kt | 18 +- .../connector/corda/server/model/NodeInfo.kt | 18 +- .../connector/corda/server/model/Party.kt | 18 +- .../connector/corda/server/model/PublicKey.kt | 18 +- .../connector/corda/server/model/SHA256.kt | 18 +- .../corda/server/model/StartFlowV1Request.kt | 18 +- .../model/StartFlowV1RequestRequestBody.kt | 18 +- .../corda/server/model/StartFlowV1Response.kt | 18 +- .../server/model/StartMonitorV1Request.kt | 18 +- .../server/model/StartMonitorV1Response.kt | 18 +- .../server/model/StopMonitorV1Request.kt | 18 +- .../server/model/StopMonitorV1Response.kt | 18 +- .../corda/server/model/VaultQueryV1Request.kt | 18 +- .../corda/server/model/X500Principal.kt | 18 +- .../src/main/resources/application.yaml | 2 +- .../generator-template-overrides/api.mustache | 95 +++ .../spring-boot/settingsGradle.mustache | 21 + .../main-server/openapi-generator-config.yaml | 10 +- .../src/main-server/start-app.sh | 3 +- .../openapi/go-client/api/openapi.yaml | 10 + .../openapi/go-client/api_default.go | 21 + .../src/main/json/openapi.json | 10 + .../src/main/json/openapi.tpl.json | 10 + .../openapitools/client/apis/DefaultApi.kt | 84 +-- .../generated/openapi/typescript-axios/api.ts | 126 ++-- .../src/main/typescript/index.web.ts | 42 +- ...orda-v4-deploy-and-invoke-contract.test.ts | 621 ++++++++++++++++++ .../flow-database-access-v4.8.test.ts | 21 +- .../jvm-kotlin-spring-server.test.ts | 399 ----------- .../common/build-container-image.ts | 46 +- .../corda-connector-container.ts | 10 + .../typescript/corda/corda-test-ledger.ts | 67 +- .../typescript/corda/sample-cordapp-enum.ts | 4 +- tools/docker/corda-all-in-one/README.md | 4 +- .../corda-all-in-one/corda-v4_12/Dockerfile | 31 +- .../corda-v4_12/constants.properties | 15 + .../negotiation-cordapp/build.gradle | 18 +- .../contracts/build.gradle | 45 ++ .../workflows/build.gradle | 49 ++ 103 files changed, 2160 insertions(+), 1377 deletions(-) create mode 100644 packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/.trivyignore mode change 100644 => 100755 packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/gradlew delete mode 100644 packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/pom.xml create mode 100644 packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/CordaNetworkMapSnapshotJsonSerializer.kt create mode 100644 packages/cactus-plugin-ledger-connector-corda/src/main-server/mustache/generator-template-overrides/api.mustache create mode 100644 packages/cactus-plugin-ledger-connector-corda/src/main-server/mustache/generator-template-overrides/libraries/spring-boot/settingsGradle.mustache create mode 100644 packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/corda-v4-deploy-and-invoke-contract.test.ts delete mode 100644 packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts create mode 100644 tools/docker/corda-all-in-one/corda-v4_12/constants.properties create mode 100644 tools/docker/corda-all-in-one/corda-v4_12/negotiation-cordapp/contracts/build.gradle create mode 100644 tools/docker/corda-all-in-one/corda-v4_12/negotiation-cordapp/workflows/build.gradle diff --git a/.cspell.json b/.cspell.json index b1aa74f7b5a..37c45699434 100644 --- a/.cspell.json +++ b/.cspell.json @@ -35,6 +35,7 @@ "ccid", "celo", "cids", + "clazz", "clsx", "cmds", "Codecov", @@ -139,6 +140,7 @@ "NETWORKSCOPEALLFORTX", "NETWORKSCOPEANYFORTX", "NODETXPOOLACK", + "NOTARISED", "notok", "Odap", "Oidc", diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index b0e6cd76ee0..f2578c90156 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -21,13 +21,12 @@ }, "ghcr.io/devcontainers/features/java:1": { "installGradle": true, - "installMaven": false, + "installMaven": true, "installAnt": false, - "version": "8.0.392-amzn", - "jdkDistro": "amzn", - "gradleVersion": "5.6.4", - "mavenVersion": "3.9.5", - "antVersion": "1.10.13" + "version": "17.0.9-tem", + "jdkDistro": "tem", + "gradleVersion": "8.1.1", + "mavenVersion": "3.9.5" }, "ghcr.io/devcontainers/features/node:1": { "nodeGypDependencies": true, diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 06dfcbab853..8ba10ca6fd9 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1376,6 +1376,7 @@ jobs: uses: actions/setup-node@v4.0.3 with: node-version: ${{ env.NODEJS_VERSION }} + - uses: actions/checkout@v4.1.7 - id: yarn-cache @@ -1386,15 +1387,32 @@ jobs: path: ./.yarn/ restore-keys: | ${{ runner.os }}-yarn-${{ hashFiles('./yarn.lock') }} + - run: ./tools/ci.sh - if: ${{ env.RUN_CODE_COVERAGE == 'true' }} - name: Upload coverage reports as artifacts + if: ${{ env.RUN_CODE_COVERAGE == 'true' }} uses: actions/upload-artifact@v4.3.3 with: name: coverage-reports-26 path: ./code-coverage-ts/**/ + - name: build cacti-connector-corda-server-dev.jar + working-directory: packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/ + run: ./gradlew clean build -Pversion=dev -DrootProjectName=cacti-connector-corda-server + + - if: ${{ env.RUN_TRIVY_SCAN == 'true' }} + name: Run Trivy vulnerability scan for cactus-connector-corda-server + uses: aquasecurity/trivy-action@0.19.0 + with: + scan-type: 'rootfs' + scan-ref: 'packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/build/libs/cacti-connector-corda-server-dev.jar' + format: 'table' + exit-code: '1' + ignore-unfixed: false + vuln-type: 'os,library' + severity: 'CRITICAL,HIGH' + cpl-connector-stellar: continue-on-error: false needs: @@ -2576,16 +2594,7 @@ jobs: - uses: actions/checkout@v4.1.7 - name: ghcr.io/hyperledger/cactus-connector-corda-server run: DOCKER_BUILDKIT=1 docker build ./packages/cactus-plugin-ledger-connector-corda/src/main-server/ -f ./packages/cactus-plugin-ledger-connector-corda/src/main-server/Dockerfile -t cactus-connector-corda-server - - if: ${{ env.RUN_TRIVY_SCAN == 'true' }} - name: Run Trivy vulnerability scan for cactus-connector-corda-server - uses: aquasecurity/trivy-action@0.19.0 - with: - image-ref: 'cactus-connector-corda-server' - format: 'table' - exit-code: '1' - ignore-unfixed: false - vuln-type: 'os,library' - severity: 'CRITICAL,HIGH' + ghcr-corda-all-in-one-flowdb: runs-on: ubuntu-22.04 steps: diff --git a/packages/cactus-plugin-ledger-connector-corda/README.md b/packages/cactus-plugin-ledger-connector-corda/README.md index c89eae3af17..7b3c3786c64 100644 --- a/packages/cactus-plugin-ledger-connector-corda/README.md +++ b/packages/cactus-plugin-ledger-connector-corda/README.md @@ -19,6 +19,7 @@ - [Testing Environment for Manual Tests via Docker Compose](#testing-environment-for-manual-tests-via-docker-compose) - [Building Docker Image Locally](#building-docker-image-locally) - [Scan The Locally Built Container Image for Vulnerabilities with Trivy](#scan-the-locally-built-container-image-for-vulnerabilities-with-trivy) +- [Scan The Locally Built .jar File For Vulnerabilities with Trivy](#scan-the-locally-built-jar-file-for-vulnerabilities-with-trivy) - [Example NodeDiagnosticInfo JSON Response](#example-nodediagnosticinfo-json-response) - [Monitoring](#monitoring) - [Usage Prometheus](#usage-prometheus) @@ -306,7 +307,8 @@ const res = await apiClient.invokeContractV1({ docker compose \ --project-directory=./ \ --file=./packages/cactus-plugin-ledger-connector-corda/src/test/yaml/fixtures/docker-compose.yaml \ - up + up \ + --build connector ``` 2. Deploy contract: ```sh @@ -574,6 +576,7 @@ DOCKER_BUILDKIT=1 docker build \ ./packages/cactus-plugin-ledger-connector-corda/src/main-server/ \ --progress=plain \ --tag cccs \ + --tag cccs:latest \ --tag "ghcr.io/hyperledger/cactus-connector-corda-server:$(date +%F)-$(git rev-parse --symbolic-full-name --abbrev-ref HEAD)-$(git rev-parse --short HEAD)" ``` @@ -588,6 +591,16 @@ on your host OS or you are using the VSCode Dev Container which ships with Trivy trivy image cccs --scanners=vuln --severity=CRITICAL --severity=HIGH ``` +## Scan The Locally Built .jar File For Vulnerabilities with Trivy + +```sh +cd packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/ + +./gradlew clean build -Pversion=dev -DrootProjectName=cacti-connector-corda-server + +trivy rootfs ./build/libs/cacti-connector-corda-server-dev.jar --scanners=vuln --severity=CRITICAL --severity=HIGH +``` + ## Example NodeDiagnosticInfo JSON Response ```json diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/Dockerfile b/packages/cactus-plugin-ledger-connector-corda/src/main-server/Dockerfile index 60872d9b19f..2f9f83a0ba0 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/Dockerfile +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/Dockerfile @@ -1,11 +1,11 @@ -FROM gradle:6.8.0-jdk8 as builder +FROM gradle:8.1.1-jdk17-jammy as builder WORKDIR / COPY ./kotlin/gen/kotlin-spring /kotlin-spring/ WORKDIR /kotlin-spring/ -RUN gradle build +RUN gradle clean build WORKDIR / FROM openjdk:24-slim-bookworm @@ -14,7 +14,7 @@ ARG APP=/usr/src/app ENV APP=/usr/src/app RUN apt update -RUN apt install -y ca-certificates tzdata curl tini +RUN apt install -y ca-certificates tzdata curl tini iputils-ping netcat-openbsd RUN rm -rf /var/lib/apt/lists/* ENV TZ=Etc/UTC \ @@ -24,7 +24,7 @@ RUN groupadd $APP_USER \ && useradd -g $APP_USER $APP_USER \ && mkdir -p ${APP} -COPY --from=builder /kotlin-spring/build/ ${APP}/kotlin-spring/build/ +COPY --from=builder /kotlin-spring/build/libs/ ${APP}/kotlin-spring/build/libs/ RUN chown -R $APP_USER:$APP_USER ${APP} @@ -38,4 +38,4 @@ EXPOSE 8080 ENTRYPOINT ["/usr/bin/tini", "--"] CMD ["/start-app.sh"] -HEALTHCHECK --interval=1s --timeout=5s --start-period=1s --retries=30 CMD /healthcheck.sh +HEALTHCHECK --interval=1s --timeout=5s --start-period=1s --retries=90 CMD /healthcheck.sh diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/healthcheck.sh b/packages/cactus-plugin-ledger-connector-corda/src/main-server/healthcheck.sh index e04f27f9ffe..20796597a7c 100755 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/healthcheck.sh +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/healthcheck.sh @@ -1,3 +1,5 @@ #!/bin/sh -curl -vv -i -X OPTIONS http://127.0.0.1:8080/ +curl -vv -i -X POST http://127.0.0.1:8080/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/network-map + +# curl -vv -i -X OPTIONS http://127.0.0.1:8080/ diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/.idea/compiler.xml b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/.idea/compiler.xml index 05fe05f8fb3..a756f943146 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/.idea/compiler.xml +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/.idea/compiler.xml @@ -1,7 +1,7 @@ - + \ No newline at end of file diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/.idea/misc.xml b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/.idea/misc.xml index bc8893e0dd6..15d18a0640a 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/.idea/misc.xml +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/.idea/misc.xml @@ -1,7 +1,6 @@ - - + diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/.trivyignore b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/.trivyignore new file mode 100644 index 00000000000..f2bc18b79e2 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/.trivyignore @@ -0,0 +1,17 @@ +# SNYK-JAVA-ORGYAML-3016888: +# - '*': +# reason: >- +# Snakeyaml is being used by Jackson and liquidbase. Corda does not use +# Jackson for deserialization except in the optional shell which we +# recommend using standalone. The Corda node itself is not exposed. +# Corda does however provide mappings of Corda types to allow CorDapps +# to use Jackson, and CorDapps using Jackson should make their own +# assessment. Liquibase is used to apply the database migration changes. +# XML files are used here to define the changes not YAML and therefore +# the Corda node itself is not exposed to this deserialisation +# vulnerability. +# expires: 2023-07-21T13:39:49.450Z +# created: 2022-12-29T13:39:49.470Z +# +# Source: https://github.com/corda/corda/blob/release/os/4.12/.snyk +CVE-2022-1471 diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/README.md b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/README.md index 504f3f22266..4af8b5d7e15 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/README.md +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/README.md @@ -1,4 +1,4 @@ -# Hyperledger Cactus - Corda Ledger Connector Plugin Server +# Hyperledger Cacti - Corda V4 JVM Ledger Connector Plugin This Kotlin based [Spring Boot](https://spring.io/projects/spring-boot) application has been generated using the [OpenAPI Generator](https://github.com/OpenAPITools/openapi-generator). diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/build.gradle.kts b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/build.gradle.kts index 5af8b989630..f1f3314bc58 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/build.gradle.kts +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/build.gradle.kts @@ -5,9 +5,10 @@ version = project.properties["version"]!! val corda_release_group = "net.corda" val corda_core_release_group = "net.corda" -val corda_release_version = "4.6" -val corda_core_release_version = "4.6" -val corda_platform_version = 5 +val corda_release_version = "4.12" +val corda_core_release_version = "4.12" +val spring_boot_version = "3.3.1" +val jackson_version = "2.16.1" tasks.named("test") { useJUnitPlatform() @@ -16,35 +17,38 @@ tasks.named("test") { buildscript { repositories { maven { url = uri("https://repo1.maven.org/maven2") } + maven { url = uri("https://download.corda.net/maven/corda-releases") } + maven { url = uri("https://jitpack.io") } } dependencies { - classpath("org.springframework.boot:spring-boot-gradle-plugin:2.2.0.M3") + classpath("org.springframework.boot:spring-boot-gradle-plugin:3.3.1") } } repositories { maven { url = uri("https://repo1.maven.org/maven2") } + maven { url = uri("https://download.corda.net/maven/corda-releases") } + maven { url = uri("https://jitpack.io") } } tasks.withType { - kotlinOptions.jvmTarget = "1.8" + kotlinOptions.jvmTarget = JavaVersion.VERSION_17.toString() } plugins { - val kotlinVersion = "1.3.30" + val kotlinVersion = "1.9.24" id("org.jetbrains.kotlin.jvm") version kotlinVersion - id("org.jetbrains.kotlin.plugin.jpa") version kotlinVersion - id("org.jetbrains.kotlin.plugin.spring") version kotlinVersion - id("org.springframework.boot") version "2.2.0.M3" - id("io.spring.dependency-management") version "1.0.5.RELEASE" + id("org.springframework.boot") version "3.3.1" } dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") implementation("org.jetbrains.kotlin:kotlin-reflect") - implementation("org.springframework.boot:spring-boot-starter-web") - implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml") - implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1") + implementation("org.springframework.boot:spring-boot-starter-web:$spring_boot_version") + implementation("org.springframework.boot:spring-boot-starter-validation:$spring_boot_version") + implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$jackson_version") + implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jackson_version") implementation("javax.json:javax.json-api:1.1.4") implementation("$corda_core_release_group:corda-core:$corda_core_release_version") implementation("$corda_core_release_group:corda-rpc:$corda_core_release_version") @@ -55,15 +59,16 @@ dependencies { implementation("co.paralleluniverse:quasar-core:0.7.12_r3") implementation("org.xeustechnologies:jcl-core:2.8") implementation("org.xeustechnologies:jcl-spring:2.8") - implementation("com.fasterxml.jackson.core:jackson-core:2.12.1") - implementation("com.fasterxml.jackson.core:jackson-databind:2.12.1") - implementation("com.fasterxml.jackson.core:jackson-annotations:2.12.1") - implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.12.1") + implementation("com.fasterxml.jackson.core:jackson-core:$jackson_version") + implementation("com.fasterxml.jackson.core:jackson-databind:$jackson_version") + implementation("com.fasterxml.jackson.core:jackson-annotations:$jackson_version") + implementation("com.fasterxml.jackson.module:jackson-module-kotlin:$jackson_version") - implementation("com.hierynomus:sshj:0.31.0") + implementation("com.hierynomus:sshj:0.38.0") testImplementation("org.jetbrains.kotlin:kotlin-test-junit5") - testImplementation("org.springframework.boot:spring-boot-starter-test") { + testImplementation("org.springframework.boot:spring-boot-starter-validation:$spring_boot_version") + testImplementation("org.springframework.boot:spring-boot-starter-test:$spring_boot_version") { exclude(module = "junit") } } @@ -72,6 +77,19 @@ configurations { all { exclude(group = "junit", module = "junit") exclude(group = "org.junit.vintage", module = "junit-vintage-engine") + + resolutionStrategy.eachDependency { + if (requested.group == "org.yaml" && requested.name == "snakeyaml") { + useVersion("2.+") + because("CVE-2022-1471, CVE-2022-25857, CVE-2022-1471 - SnakeYaml: Constructor Deserialization Remote Code Execution, snakeyaml: Denial of Service due to missing nested depth limitation for collections") + } else if (requested.group == "org.springframework" && requested.name == "spring-web") { + useVersion("[6.0.0,99[") + because("CVE-2016-1000027 - https://avd.aquasec.com/nvd/cve-2016-1000027 spring: HttpInvokerServiceExporter readRemoteInvocation method untrusted java deserialization") + } else if (requested.group == "org.apache.commons" && requested.name == "commons-configuration2") { + useVersion("[2.8.0,99[") + because("CVE-2022-33980 - CRITICAL - https://avd.aquasec.com/nvd/cve-2022-33980 - apache-commons-configuration: Apache Commons Configuration insecure interpolation defaults") + } + } } } diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/gradle.properties b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/gradle.properties index 23e3e8e0d77..85f4fa836c7 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/gradle.properties +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/gradle.properties @@ -1 +1 @@ -version = 2.0.0-rc.3 \ No newline at end of file +version = 2.0.0-rc.3 diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/gradle/wrapper/gradle-wrapper.jar b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/gradle/wrapper/gradle-wrapper.jar index e708b1c023ec8b20f512888fe07c5bd3ff77bb8f..c1962a79e29d3e0ab67b14947c167a862655af9b 100644 GIT binary patch delta 42507 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 AFaQ7m delta 39488 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 SjTjh$z-I$+9LbEIUi}{|+iFq( diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/gradle/wrapper/gradle-wrapper.properties b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/gradle/wrapper/gradle-wrapper.properties index be52383ef49..37aef8d3f0c 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/gradle/wrapper/gradle-wrapper.properties +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/gradlew b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/gradlew old mode 100644 new mode 100755 index 4f906e0c811..aeb74cbb43e --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/gradlew +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,98 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# 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/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$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"' +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +118,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,7 +129,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + 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. Please set the JAVA_HOME variable in your environment to match the @@ -106,80 +137,109 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +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=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=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +# 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, 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. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + 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. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/gradlew.bat b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/gradlew.bat index 107acd32c4e..93e3f59f135 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/gradlew.bat +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/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/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/pom.xml b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/pom.xml deleted file mode 100644 index 17c0b36b27c..00000000000 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/pom.xml +++ /dev/null @@ -1,130 +0,0 @@ - - 4.0.0 - org.hyperledger.cactus - cactus-connector-corda-server - jar - cactus-connector-corda-server - 2.0.0-rc.3 - - 3.0.2 - 2.1.0 - 1.6.21 - - 1.6.21 - UTF-8 - - - org.springframework.boot - spring-boot-starter-parent - 2.6.7 - - - ${project.basedir}/src/main/kotlin - ${project.basedir}/src/test/kotlin - - - org.springframework.boot - spring-boot-maven-plugin - - - - repackage - - - - - - kotlin-maven-plugin - org.jetbrains.kotlin - ${kotlin.version} - - - spring - - 1.8 - - - - compile - compile - - compile - - - - test-compile - test-compile - - test-compile - - - - - - org.jetbrains.kotlin - kotlin-maven-allopen - ${kotlin.version} - - - - - - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - ${kotlin.version} - - - org.jetbrains.kotlin - kotlin-reflect - ${kotlin.version} - - - org.springframework.boot - spring-boot-starter-web - - - - - - - com.google.code.findbugs - jsr305 - ${findbugs-jsr305.version} - - - com.fasterxml.jackson.dataformat - jackson-dataformat-yaml - - - com.fasterxml.jackson.dataformat - jackson-dataformat-xml - - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - - - com.fasterxml.jackson.module - jackson-module-kotlin - - - - jakarta.validation - jakarta.validation-api - - - jakarta.annotation - jakarta.annotation-api - ${jakarta-annotation.version} - provided - - - org.jetbrains.kotlin - kotlin-test-junit5 - ${kotlin-test-junit5.version} - test - - - diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/settings.gradle b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/settings.gradle index 0a80c90f8db..1b10305b321 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/settings.gradle +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/settings.gradle @@ -12,4 +12,10 @@ pluginManagement { } } } + rootProject.name = "cactus-connector-corda-server" +// The template modification Cacti needs so that we can alter the artifact name +// at build time in our scripts. This is handy when we build a .jar to be scanned +// by trivy and we don't want to have to guess what the .jar filename ended up being +// (which is different after each release) +rootProject.name = System.getProperty('rootProjectName') ?: rootProject.name diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/Application.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/Application.kt index 4b1388b5f9e..9e8653e0ff4 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/Application.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/Application.kt @@ -2,12 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.databind.SerializationFeature +// import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule import net.corda.client.jackson.JacksonSupport import org.hyperledger.cactus.plugin.ledger.connector.corda.server.impl.NodeRPCConnection import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Value import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.CommandLineRunner import org.springframework.boot.runApplication +import org.springframework.context.ApplicationContext import org.springframework.context.annotation.Bean import org.springframework.context.annotation.ComponentScan import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter @@ -19,9 +22,9 @@ private const val ThreadPoolCount = "cactus.threadCount" private const val ThreadPoolCountDefault = "3" @SpringBootApplication -@ComponentScan(basePackages = ["org.hyperledger.cactus.plugin.ledger.connector.corda.server", "org.hyperledger.cactus.plugin.ledger.connector.corda.server.api", "org.hyperledger.cactus.plugin.ledger.connector.corda.server.model"]) +@ComponentScan( basePackages = ["org.hyperledger.cactus.plugin.ledger.connector.corda.server", "org.hyperledger.cactus.plugin.ledger.connector.corda.server.impl", "org.hyperledger.cactus.plugin.ledger.connector.corda.server.api", "org.hyperledger.cactus.plugin.ledger.connector.corda.server.model"]) @EnableScheduling -class Application(@Value("\${$ThreadPoolCount:$ThreadPoolCountDefault}") val threadCount: Int) { +open class Application(@Value("\${$ThreadPoolCount:$ThreadPoolCountDefault}") val threadCount: Int) { /** * Spring Bean that binds a Corda Jackson object-mapper to HTTP message types used in Spring. */ @@ -30,17 +33,33 @@ class Application(@Value("\${$ThreadPoolCount:$ThreadPoolCountDefault}") val thr val mapper = JacksonSupport.createDefaultMapper(rpcConnection.proxy) .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS) .disable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE) + // .registerModule(JavaTimeModule()) val converter = MappingJackson2HttpMessageConverter() converter.objectMapper = mapper return converter } @Bean - fun taskScheduler(): TaskScheduler? { + open fun taskScheduler(): TaskScheduler? { val taskScheduler = ThreadPoolTaskScheduler() taskScheduler.poolSize = this.threadCount return taskScheduler } + + @Bean + open fun commandLineRunner(ctx: ApplicationContext): CommandLineRunner { + return object : CommandLineRunner { + override fun run(vararg args: String?) { + System.out.println("Let's inspect the beans provided by Spring Boot:"); + + val beanNames = ctx.getBeanDefinitionNames() + beanNames.sortedArray() + for (beanName in beanNames) { + System.out.println(beanName) + } + } + } + } } fun main(args: Array) { diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/api/ApiPluginLedgerConnectorCordaController.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/api/ApiPluginLedgerConnectorCordaController.kt index f8cb2099e01..5006a309172 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/api/ApiPluginLedgerConnectorCordaController.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/api/ApiPluginLedgerConnectorCordaController.kt @@ -35,15 +35,15 @@ import org.springframework.validation.annotation.Validated import org.springframework.web.context.request.NativeWebRequest import org.springframework.beans.factory.annotation.Autowired -import javax.validation.Valid -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size +import jakarta.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size import kotlin.collections.List import kotlin.collections.Map @@ -51,7 +51,7 @@ import kotlin.collections.Map @RestController @Validated @RequestMapping("\${api.base-path:}") -class ApiPluginLedgerConnectorCordaController(@Autowired(required = true) val service: ApiPluginLedgerConnectorCordaService) { +open class ApiPluginLedgerConnectorCordaController(@Autowired(required = true) val service: ApiPluginLedgerConnectorCordaService) { @RequestMapping( @@ -60,7 +60,7 @@ class ApiPluginLedgerConnectorCordaController(@Autowired(required = true) val se produces = ["application/json"], consumes = ["application/json"] ) - fun clearMonitorTransactionsV1( @Valid @RequestBody(required = false) clearMonitorTransactionsV1Request: ClearMonitorTransactionsV1Request?): ResponseEntity { + open fun clearMonitorTransactionsV1( @Valid @RequestBody clearMonitorTransactionsV1Request: ClearMonitorTransactionsV1Request): ResponseEntity { return ResponseEntity(service.clearMonitorTransactionsV1(clearMonitorTransactionsV1Request), HttpStatus.valueOf(200)) } @@ -71,7 +71,7 @@ class ApiPluginLedgerConnectorCordaController(@Autowired(required = true) val se produces = ["application/json"], consumes = ["application/json"] ) - fun deployContractJarsV1( @Valid @RequestBody(required = false) deployContractJarsV1Request: DeployContractJarsV1Request?): ResponseEntity { + open fun deployContractJarsV1( @Valid @RequestBody deployContractJarsV1Request: DeployContractJarsV1Request): ResponseEntity { return ResponseEntity(service.deployContractJarsV1(deployContractJarsV1Request), HttpStatus.valueOf(200)) } @@ -82,7 +82,7 @@ class ApiPluginLedgerConnectorCordaController(@Autowired(required = true) val se produces = ["application/json"], consumes = ["application/json"] ) - fun diagnoseNodeV1( @Valid @RequestBody(required = false) diagnoseNodeV1Request: DiagnoseNodeV1Request?): ResponseEntity { + open fun diagnoseNodeV1( @Valid @RequestBody(required = false) diagnoseNodeV1Request: DiagnoseNodeV1Request?): ResponseEntity { return ResponseEntity(service.diagnoseNodeV1(diagnoseNodeV1Request), HttpStatus.valueOf(200)) } @@ -93,7 +93,7 @@ class ApiPluginLedgerConnectorCordaController(@Autowired(required = true) val se produces = ["text/plain"], consumes = ["application/json"] ) - fun getFlowV1( @Valid @RequestBody getFlowCidV1Request: GetFlowCidV1Request): ResponseEntity { + open fun getFlowV1( @Valid @RequestBody getFlowCidV1Request: GetFlowCidV1Request): ResponseEntity { return ResponseEntity(service.getFlowV1(getFlowCidV1Request), HttpStatus.valueOf(200)) } @@ -104,7 +104,7 @@ class ApiPluginLedgerConnectorCordaController(@Autowired(required = true) val se produces = ["application/json"], consumes = ["application/json"] ) - fun getMonitorTransactionsV1( @Valid @RequestBody(required = false) getMonitorTransactionsV1Request: GetMonitorTransactionsV1Request?): ResponseEntity { + open fun getMonitorTransactionsV1( @Valid @RequestBody getMonitorTransactionsV1Request: GetMonitorTransactionsV1Request): ResponseEntity { return ResponseEntity(service.getMonitorTransactionsV1(getMonitorTransactionsV1Request), HttpStatus.valueOf(200)) } @@ -114,7 +114,7 @@ class ApiPluginLedgerConnectorCordaController(@Autowired(required = true) val se value = ["/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/get-prometheus-exporter-metrics"], produces = ["text/plain"] ) - fun getPrometheusMetricsV1(): ResponseEntity { + open fun getPrometheusMetricsV1(): ResponseEntity { return ResponseEntity(service.getPrometheusMetricsV1(), HttpStatus.valueOf(200)) } @@ -125,7 +125,7 @@ class ApiPluginLedgerConnectorCordaController(@Autowired(required = true) val se produces = ["application/json"], consumes = ["application/json"] ) - fun invokeContractV1( @Valid @RequestBody(required = false) invokeContractV1Request: InvokeContractV1Request?): ResponseEntity { + open fun invokeContractV1( @Valid @RequestBody invokeContractV1Request: InvokeContractV1Request): ResponseEntity { return ResponseEntity(service.invokeContractV1(invokeContractV1Request), HttpStatus.valueOf(200)) } @@ -136,7 +136,7 @@ class ApiPluginLedgerConnectorCordaController(@Autowired(required = true) val se produces = ["application/json"], consumes = ["application/json"] ) - fun listCpiV1( @Valid @RequestBody listCpiV1Request: ListCpiV1Request): ResponseEntity { + open fun listCpiV1( @Valid @RequestBody listCpiV1Request: ListCpiV1Request): ResponseEntity { return ResponseEntity(service.listCpiV1(listCpiV1Request), HttpStatus.valueOf(200)) } @@ -147,7 +147,7 @@ class ApiPluginLedgerConnectorCordaController(@Autowired(required = true) val se produces = ["text/plain"], consumes = ["application/json"] ) - fun listFlowV1( @Valid @RequestBody getFlowCidV1Request: GetFlowCidV1Request): ResponseEntity { + open fun listFlowV1( @Valid @RequestBody getFlowCidV1Request: GetFlowCidV1Request): ResponseEntity { return ResponseEntity(service.listFlowV1(getFlowCidV1Request), HttpStatus.valueOf(200)) } @@ -158,7 +158,7 @@ class ApiPluginLedgerConnectorCordaController(@Autowired(required = true) val se produces = ["application/json"], consumes = ["application/json"] ) - fun listFlowsV1( @Valid @RequestBody(required = false) listFlowsV1Request: ListFlowsV1Request?): ResponseEntity { + open fun listFlowsV1( @Valid @RequestBody(required = false) listFlowsV1Request: ListFlowsV1Request?): ResponseEntity { return ResponseEntity(service.listFlowsV1(listFlowsV1Request), HttpStatus.valueOf(200)) } @@ -169,7 +169,7 @@ class ApiPluginLedgerConnectorCordaController(@Autowired(required = true) val se produces = ["application/json"], consumes = ["application/json"] ) - fun networkMapV1( @Valid @RequestBody(required = false) body: kotlin.Any?): ResponseEntity> { + open fun networkMapV1( @Valid @RequestBody(required = false) body: kotlin.Any?): ResponseEntity> { return ResponseEntity(service.networkMapV1(body), HttpStatus.valueOf(200)) } @@ -180,7 +180,7 @@ class ApiPluginLedgerConnectorCordaController(@Autowired(required = true) val se produces = ["application/json"], consumes = ["application/json"] ) - fun startFlowV1( @Valid @RequestBody startFlowV1Request: StartFlowV1Request): ResponseEntity { + open fun startFlowV1( @Valid @RequestBody startFlowV1Request: StartFlowV1Request): ResponseEntity { return ResponseEntity(service.startFlowV1(startFlowV1Request), HttpStatus.valueOf(200)) } @@ -191,7 +191,7 @@ class ApiPluginLedgerConnectorCordaController(@Autowired(required = true) val se produces = ["application/json"], consumes = ["application/json"] ) - fun startMonitorV1( @Valid @RequestBody(required = false) startMonitorV1Request: StartMonitorV1Request?): ResponseEntity { + open fun startMonitorV1( @Valid @RequestBody startMonitorV1Request: StartMonitorV1Request): ResponseEntity { return ResponseEntity(service.startMonitorV1(startMonitorV1Request), HttpStatus.valueOf(200)) } @@ -202,7 +202,7 @@ class ApiPluginLedgerConnectorCordaController(@Autowired(required = true) val se produces = ["application/json"], consumes = ["application/json"] ) - fun stopMonitorV1( @Valid @RequestBody(required = false) stopMonitorV1Request: StopMonitorV1Request?): ResponseEntity { + open fun stopMonitorV1( @Valid @RequestBody stopMonitorV1Request: StopMonitorV1Request): ResponseEntity { return ResponseEntity(service.stopMonitorV1(stopMonitorV1Request), HttpStatus.valueOf(200)) } @@ -213,7 +213,7 @@ class ApiPluginLedgerConnectorCordaController(@Autowired(required = true) val se produces = ["application/json"], consumes = ["application/json"] ) - fun vaultQueryV1( @Valid @RequestBody(required = false) vaultQueryV1Request: VaultQueryV1Request?): ResponseEntity { + open fun vaultQueryV1( @Valid @RequestBody vaultQueryV1Request: VaultQueryV1Request): ResponseEntity { return ResponseEntity(service.vaultQueryV1(vaultQueryV1Request), HttpStatus.valueOf(200)) } } diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/api/ApiPluginLedgerConnectorCordaService.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/api/ApiPluginLedgerConnectorCordaService.kt index c806c30c03a..5d22e8b386e 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/api/ApiPluginLedgerConnectorCordaService.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/api/ApiPluginLedgerConnectorCordaService.kt @@ -32,21 +32,21 @@ interface ApiPluginLedgerConnectorCordaService { /** * DELETE /api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/clear-monitor-transactions : Clear transactions from internal store so they'll not be available by GetMonitorTransactionsV1 anymore. * - * @param clearMonitorTransactionsV1Request (optional) + * @param clearMonitorTransactionsV1Request (required) * @return OK (status code 200) * @see ApiPluginLedgerConnectorCorda#clearMonitorTransactionsV1 */ - fun clearMonitorTransactionsV1(clearMonitorTransactionsV1Request: ClearMonitorTransactionsV1Request?): ClearMonitorTransactionsV1Response + fun clearMonitorTransactionsV1(clearMonitorTransactionsV1Request: ClearMonitorTransactionsV1Request): ClearMonitorTransactionsV1Response /** * POST /api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/deploy-contract-jars : Deploys a set of jar files (Cordapps, e.g. the contracts in Corda speak). * - * @param deployContractJarsV1Request (optional) + * @param deployContractJarsV1Request (required) * @return OK (status code 200) * or Bad Request (status code 400) * @see ApiPluginLedgerConnectorCorda#deployContractJarsV1 */ - fun deployContractJarsV1(deployContractJarsV1Request: DeployContractJarsV1Request?): DeployContractJarsSuccessV1Response + fun deployContractJarsV1(deployContractJarsV1Request: DeployContractJarsV1Request): DeployContractJarsSuccessV1Response /** * POST /api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/diagnose-node @@ -72,11 +72,11 @@ interface ApiPluginLedgerConnectorCordaService { /** * GET /api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/get-monitor-transactions : Get transactions for monitored state classes. * - * @param getMonitorTransactionsV1Request (optional) + * @param getMonitorTransactionsV1Request (required) * @return OK (status code 200) * @see ApiPluginLedgerConnectorCorda#getMonitorTransactionsV1 */ - fun getMonitorTransactionsV1(getMonitorTransactionsV1Request: GetMonitorTransactionsV1Request?): GetMonitorTransactionsV1Response + fun getMonitorTransactionsV1(getMonitorTransactionsV1Request: GetMonitorTransactionsV1Request): GetMonitorTransactionsV1Response /** * GET /api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/get-prometheus-exporter-metrics : Get the Prometheus Metrics @@ -89,11 +89,11 @@ interface ApiPluginLedgerConnectorCordaService { /** * POST /api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/invoke-contract : Invokes a contract on a Corda ledger (e.g. a flow) * - * @param invokeContractV1Request (optional) + * @param invokeContractV1Request (required) * @return OK (status code 200) * @see ApiPluginLedgerConnectorCorda#invokeContractV1 */ - fun invokeContractV1(invokeContractV1Request: InvokeContractV1Request?): InvokeContractV1Response + fun invokeContractV1(invokeContractV1Request: InvokeContractV1Request): InvokeContractV1Response /** * GET /api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/list-cpi : List all CPIs uploaded to the cluster @@ -147,28 +147,28 @@ interface ApiPluginLedgerConnectorCordaService { /** * POST /api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/start-monitor : Start monitoring corda changes (transactions) of given state class * - * @param startMonitorV1Request (optional) + * @param startMonitorV1Request (required) * @return OK (status code 200) * @see ApiPluginLedgerConnectorCorda#startMonitorV1 */ - fun startMonitorV1(startMonitorV1Request: StartMonitorV1Request?): StartMonitorV1Response + fun startMonitorV1(startMonitorV1Request: StartMonitorV1Request): StartMonitorV1Response /** * DELETE /api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/stop-monitor : Stop monitoring corda changes (transactions) of given state class * - * @param stopMonitorV1Request (optional) + * @param stopMonitorV1Request (required) * @return OK (status code 200) * @see ApiPluginLedgerConnectorCorda#stopMonitorV1 */ - fun stopMonitorV1(stopMonitorV1Request: StopMonitorV1Request?): StopMonitorV1Response + fun stopMonitorV1(stopMonitorV1Request: StopMonitorV1Request): StopMonitorV1Response /** * POST /api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/vault-query * Queryes the vault service for state references based on JVM class names. Custom filters are not supported by this endpoint. * - * @param vaultQueryV1Request (optional) + * @param vaultQueryV1Request (required) * @return OK (status code 200) * @see ApiPluginLedgerConnectorCorda#vaultQueryV1 */ - fun vaultQueryV1(vaultQueryV1Request: VaultQueryV1Request?): kotlin.Any + fun vaultQueryV1(vaultQueryV1Request: VaultQueryV1Request): kotlin.Any } diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/api/ApiUtil.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/api/ApiUtil.kt index 7bf767601b3..634125a3062 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/api/ApiUtil.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/api/ApiUtil.kt @@ -2,7 +2,7 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.api import org.springframework.web.context.request.NativeWebRequest -import javax.servlet.http.HttpServletResponse +import jakarta.servlet.http.HttpServletResponse import java.io.IOException object ApiUtil { diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/ApiPluginLedgerConnectorCordaServiceImpl.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/ApiPluginLedgerConnectorCordaServiceImpl.kt index 4201cc78035..ed9d456da17 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/ApiPluginLedgerConnectorCordaServiceImpl.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/ApiPluginLedgerConnectorCordaServiceImpl.kt @@ -1,7 +1,12 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.impl +// import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule + +import com.fasterxml.jackson.annotation.JsonInclude import com.fasterxml.jackson.core.type.TypeReference import com.fasterxml.jackson.databind.* +import com.fasterxml.jackson.databind.module.SimpleModule +import com.fasterxml.jackson.databind.ser.BeanSerializerModifier import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import net.corda.core.contracts.ContractState import net.corda.core.flows.FlowLogic @@ -19,6 +24,7 @@ import net.schmizz.sshj.xfer.InMemorySourceFile import org.hyperledger.cactus.plugin.ledger.connector.corda.server.api.ApiPluginLedgerConnectorCordaService import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.* import org.springframework.http.HttpStatus +import org.springframework.http.HttpStatusCode import org.springframework.stereotype.Service import org.springframework.web.server.ResponseStatusException import org.springframework.web.util.HtmlUtils.htmlEscape @@ -54,9 +60,14 @@ class ApiPluginLedgerConnectorCordaServiceImpl( val jsonJvmObjectDeserializer = JsonJvmObjectDeserializer() } - fun dynamicInvoke(rpc: CordaRPCOps, req: InvokeContractV1Request): InvokeContractV1Response { - @Suppress("UNCHECKED_CAST") - val classFlowLogic = jsonJvmObjectDeserializer.getOrInferType(req.flowFullClassName) as Class> + private fun dynamicInvoke(rpc: CordaRPCOps, req: InvokeContractV1Request): InvokeContractV1Response { + val classFlowLogic = try { + @Suppress("UNCHECKED_CAST") + jsonJvmObjectDeserializer.getOrInferType(req.flowFullClassName) as Class> + } catch (ex: ClassNotFoundException) { + val reason = "flowFullClassName ${req.flowFullClassName} could not be loaded. Are you sure you have installed the correct .jar file(s)?" + throw ResponseStatusException(HttpStatus.BAD_REQUEST, reason, ex) + } val params = req.params.map { p -> jsonJvmObjectDeserializer.instantiate(p) }.toTypedArray() logger.info("params={}", params) @@ -148,10 +159,7 @@ class ApiPluginLedgerConnectorCordaServiceImpl( // https://docs.corda.net/docs/corda-enterprise/4.6/node-upgrade-notes.html#step-1-drain-the-node // The other solution is of course to make it so that this endpoint is a fully fledged, robust, production ready // implementation and that would be preferred over the longer term, but maybe it's actually just scope creep... - override fun deployContractJarsV1(deployContractJarsV1Request: DeployContractJarsV1Request?): DeployContractJarsSuccessV1Response { - if (deployContractJarsV1Request == null) { - throw IllegalArgumentException("DeployContractJarsV1Request cannot be null") - } + override fun deployContractJarsV1(deployContractJarsV1Request: DeployContractJarsV1Request): DeployContractJarsSuccessV1Response { try { val decoder = Base64.getDecoder() @@ -173,6 +181,7 @@ class ApiPluginLedgerConnectorCordaServiceImpl( fun tryConnectingToSshHost () { tries++ try { + logger.debug("Connecting to node via SSH... ${cred.hostname}:${cred.port}") ssh.connect(cred.hostname, cred.port) } catch (ex: TransportException) { if (tries < maxTries) { @@ -331,9 +340,8 @@ class ApiPluginLedgerConnectorCordaServiceImpl( TODO("Not yet implemented") } - override fun invokeContractV1(invokeContractV1Request: InvokeContractV1Request?): InvokeContractV1Response { - Objects.requireNonNull(invokeContractV1Request, "InvokeContractV1Request must be non-null!") - return dynamicInvoke(rpc.proxy, invokeContractV1Request!!) + override fun invokeContractV1(invokeContractV1Request: InvokeContractV1Request): InvokeContractV1Response { + return dynamicInvoke(rpc.proxy, invokeContractV1Request) } override fun listFlowsV1(listFlowsV1Request: ListFlowsV1Request?): ListFlowsV1Response { @@ -343,20 +351,18 @@ class ApiPluginLedgerConnectorCordaServiceImpl( override fun networkMapV1(body: Any?): List { val reader = mapper.readerFor(object : TypeReference?>() {}) - val networkMapSnapshot = rpc.proxy.networkMapSnapshot() - val networkMapJson = writer.writeValueAsString(networkMapSnapshot) + val serializer = CordaNetworkMapSnapshotJsonSerializer(networkMapSnapshot) + val x = serializer.asListOfMaps() + val networkMapJson = writer.writeValueAsString(x) logger.trace("networkMapSnapshot=\n{}", networkMapJson) val nodeInfoList = reader.readValue>(networkMapJson) - logger.info("Returning {} NodeInfo elements in response.", nodeInfoList.size) + logger.debug("Returning {} NodeInfo elements in response.", nodeInfoList.size) return nodeInfoList } - override fun vaultQueryV1(vaultQueryV1Request: VaultQueryV1Request?): Any { - if (vaultQueryV1Request == null) { - throw ResponseStatusException(HttpStatus.BAD_REQUEST, "QueryBySimpleV1Request cannot be null") - } + override fun vaultQueryV1(vaultQueryV1Request: VaultQueryV1Request): Any { if (vaultQueryV1Request.contractStateType == null) { throw ResponseStatusException(HttpStatus.BAD_REQUEST, "QueryBySimpleV1Request.contractStateType cannot be null") } @@ -385,17 +391,17 @@ class ApiPluginLedgerConnectorCordaServiceImpl( /** * Start monitoring state changes for clientAppID of stateClass specified in the request body. */ - override fun startMonitorV1(startMonitorV1Request: StartMonitorV1Request?): StartMonitorV1Response { - val clientAppId = startMonitorV1Request?.clientAppId - val stateName = startMonitorV1Request?.stateFullClassName + override fun startMonitorV1(startMonitorV1Request: StartMonitorV1Request): StartMonitorV1Response { + val clientAppId = startMonitorV1Request.clientAppId + val stateName = startMonitorV1Request.stateFullClassName - if (clientAppId.isNullOrEmpty()) { + if (clientAppId.isEmpty()) { val message = "Request rejected because missing client app ID" logger.info(message) return StartMonitorV1Response(false, message) } - if (stateName.isNullOrEmpty()) { + if (stateName.isEmpty()) { val message = "Request rejected because missing state class name" logger.info(message) return StartMonitorV1Response(false, message) @@ -424,17 +430,17 @@ class ApiPluginLedgerConnectorCordaServiceImpl( * Must be called after startMonitorV1 and before stopMonitorV1. * Transactions buffer must be explicitly cleared with clearMonitorTransactionsV1 */ - override fun getMonitorTransactionsV1(getMonitorTransactionsV1Request: GetMonitorTransactionsV1Request?): GetMonitorTransactionsV1Response { - val clientAppId = getMonitorTransactionsV1Request?.clientAppId - val stateName = getMonitorTransactionsV1Request?.stateFullClassName + override fun getMonitorTransactionsV1(getMonitorTransactionsV1Request: GetMonitorTransactionsV1Request): GetMonitorTransactionsV1Response { + val clientAppId = getMonitorTransactionsV1Request.clientAppId + val stateName = getMonitorTransactionsV1Request.stateFullClassName - if (clientAppId.isNullOrEmpty()) { + if (clientAppId.isEmpty()) { val message = "Request rejected because missing client app ID" logger.info(message) return GetMonitorTransactionsV1Response(false, message) } - if (stateName.isNullOrEmpty()) { + if (stateName.isEmpty()) { val message = "Request rejected because missing state class name" logger.info(message) return GetMonitorTransactionsV1Response(false, message) @@ -455,24 +461,24 @@ class ApiPluginLedgerConnectorCordaServiceImpl( * Clear monitored transactions based on index from internal client buffer. * Any future call to getMonitorTransactionsV1 will not return transactions removed by this call. */ - override fun clearMonitorTransactionsV1(clearMonitorTransactionsV1Request: ClearMonitorTransactionsV1Request?): ClearMonitorTransactionsV1Response { - val clientAppId = clearMonitorTransactionsV1Request?.clientAppId - val stateName = clearMonitorTransactionsV1Request?.stateFullClassName - val indexesToRemove = clearMonitorTransactionsV1Request?.txIndexes + override fun clearMonitorTransactionsV1(clearMonitorTransactionsV1Request: ClearMonitorTransactionsV1Request): ClearMonitorTransactionsV1Response { + val clientAppId = clearMonitorTransactionsV1Request.clientAppId + val stateName = clearMonitorTransactionsV1Request.stateFullClassName + val indexesToRemove = clearMonitorTransactionsV1Request.txIndexes - if (clientAppId.isNullOrEmpty()) { + if (clientAppId.isEmpty()) { val message = "Request rejected because missing client app ID" logger.info(message) return ClearMonitorTransactionsV1Response(false, message) } - if (stateName.isNullOrEmpty()) { + if (stateName.isEmpty()) { val message = "Request rejected because missing state class name" logger.info(message) return ClearMonitorTransactionsV1Response(false, message) } - if (indexesToRemove.isNullOrEmpty()) { + if (indexesToRemove.isEmpty()) { val message = "No indexes to remove" logger.info(message) return ClearMonitorTransactionsV1Response(true, message) @@ -494,17 +500,17 @@ class ApiPluginLedgerConnectorCordaServiceImpl( * Stop monitoring state changes for clientAppID of stateClass specified in the request body. * Removes all transactions that were not read yet, unsubscribes from the monitor. */ - override fun stopMonitorV1(stopMonitorV1Request: StopMonitorV1Request?): StopMonitorV1Response { - val clientAppId = stopMonitorV1Request?.clientAppId - val stateName = stopMonitorV1Request?.stateFullClassName + override fun stopMonitorV1(stopMonitorV1Request: StopMonitorV1Request): StopMonitorV1Response { + val clientAppId = stopMonitorV1Request.clientAppId + val stateName = stopMonitorV1Request.stateFullClassName - if (clientAppId.isNullOrEmpty()) { + if (clientAppId.isEmpty()) { val message = "Request rejected because missing client app ID" logger.info(message) return StopMonitorV1Response(false, message) } - if (stateName.isNullOrEmpty()) { + if (stateName.isEmpty()) { val message = "Request rejected because missing state class name" logger.info(message) return StopMonitorV1Response(false, message) diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/CordaNetworkMapSnapshotJsonSerializer.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/CordaNetworkMapSnapshotJsonSerializer.kt new file mode 100644 index 00000000000..9ac7f8a9f76 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/CordaNetworkMapSnapshotJsonSerializer.kt @@ -0,0 +1,76 @@ +package org.hyperledger.cactus.plugin.ledger.connector.corda.server.impl + +import net.corda.core.crypto.keys +import net.corda.core.node.NodeInfo +import net.corda.core.utilities.toBase58String +import net.corda.nodeapi.internal.config.toConfig + +// org.bouncycastle.math.ec.custom.sec.SecP256R1Curve["infinity"] + +/** + * We need this to avoid the serialization exception of the Corda Network map in Corda v4.12 where without this, the + * Jackson serialization of the network map will crash with the following error: + * + * ```sh + * com.fasterxml.jackson.databind.JsonMappingException: + * Document nesting depth (1001) exceeds the maximum allowed (1000, from `StreamWriteConstraints.getMaxNestingDepth()`) + * (through reference chain: + * net.corda.core.node.NodeInfo["legalIdentitiesAndCerts"] + * ->java.util.Collections$UnmodifiableRandomAccessList[0] + * ->net.corda.core.identity.PartyAndCertificate["certPath"] + * ->sun.security.provider.certpath.X509CertPath["certificates"] + * ->java.util.Collections$UnmodifiableRandomAccessList[1] + * ->sun.security.x509.X509CertImpl["publicKey"] + * ->org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey["parameters"] + * ->org.bouncycastle.jce.spec.ECNamedCurveParameterSpec["curve"] + * ->org.bouncycastle.math.ec.custom.sec.SecP256R1Curve["infinity"] + * ->org.bouncycastle.math.ec.custom.sec.SecP256R1Point["curve"] + * ->org.bouncycastle.math.ec.custom.sec.SecP256R1Curve["infinity"] + * ->org.bouncycastle.math.ec.custom.sec.SecP256R1Point["curve"] + * ... + * ``` + * + */ +class CordaNetworkMapSnapshotJsonSerializer(private val data: List) { + fun asListOfMaps(): List> { + return data.map { nodeInfo -> asMap(nodeInfo) }; + } + + private fun asMap(ni: NodeInfo): Map { + ni.legalIdentitiesAndCerts + return mapOf( + "legalIdentitiesAndCerts" to ni.legalIdentitiesAndCerts.map { pac -> + mapOf( + "name" to pac.name, + "certificate" to pac.certificate, + "party" to pac.party, + "owningKey" to pac.owningKey, + "certPath" to mapOf( + "type" to pac.certPath.type, + "certificates" to pac.certPath.certificates.map { c -> + mapOf( + "type" to c.type, + "publicKey" to mapOf( + "algorithm" to c.publicKey.algorithm, + "format" to c.publicKey.format, + "toBase58String" to c.publicKey.toBase58String(), + "keys" to c.publicKey.keys.map { k -> + mapOf( + "algorithm" to k.algorithm, + "format" to k.format, + "toBase58String" to k.toBase58String() + ) + } + ), + ) + } + ) + ) + }, + "serial" to ni.serial, + "legalIdentities" to ni.legalIdentities, + "addresses" to ni.addresses, + "platformVersion" to ni.platformVersion, + ); + } +} \ No newline at end of file diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/InMemoryHostKeyVerifier.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/InMemoryHostKeyVerifier.kt index 3f033bd3027..be2d860c84f 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/InMemoryHostKeyVerifier.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/InMemoryHostKeyVerifier.kt @@ -71,4 +71,12 @@ class InMemoryHostKeyVerifier(inputStream: InputStream?, charset: Charset?) : logger.debug("Rejecting due to none of the {} entries being acceptable.", entries.size) return false } + + // FIXME: 2024-01-03 Peter - host key verification is needed. SSH is only used + // for contract deployment via the connector which is an experimental feature not + // ready for production use so this is not an issue until we decide to make it + // production ready (the contract deployment endpoint) + override fun findExistingAlgorithms(hostname: String, port: Int): List { + return listOf() + } } \ No newline at end of file diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/NodeRPCConnection.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/NodeRPCConnection.kt index a35f9d77243..47eb7d88f05 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/NodeRPCConnection.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/NodeRPCConnection.kt @@ -1,5 +1,8 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.impl +import kotlinx.coroutines.* +import kotlin.time.toDuration +import kotlin.time.DurationUnit import net.corda.client.rpc.CordaRPCClient import net.corda.client.rpc.CordaRPCClientConfiguration @@ -11,17 +14,17 @@ import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.loggerFor import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Component -import javax.annotation.PostConstruct -import javax.annotation.PreDestroy -import javax.validation.Valid +import jakarta.annotation.PostConstruct +import jakarta.annotation.PreDestroy +import jakarta.validation.Valid import java.net.InetAddress import org.springframework.boot.context.properties.ConfigurationProperties import org.springframework.validation.annotation.Validated import java.util.concurrent.CountDownLatch -import javax.validation.constraints.NotEmpty -import javax.validation.constraints.NotNull +import jakarta.validation.constraints.NotEmpty +import jakarta.validation.constraints.NotNull private const val CACTUS_CORDA_RPC_USERNAME = "cactus.corda.rpc.username" @@ -72,12 +75,18 @@ open class NodeRPCConnection( // this workaround here is due to the Graceful Reconnect above not actually doing what it's supposed to // either because it has a bug or because I misread the documentation. // So this manual retry on top of the graceful reconnects is to make it resilient + var tryIntervalSec = 2 var numberOfTriesRemaining = 5 while (numberOfTriesRemaining > 0) { numberOfTriesRemaining-- try { logger.info("Trying to connect to RPC numberOfTriesRemaining=$numberOfTriesRemaining") rpcConnection = rpcClient.start(username, password, gracefulReconnect = gracefulReconnect) + runBlocking { + val tryIntervalDuration = tryIntervalSec.toDuration(DurationUnit.SECONDS) + delay(tryIntervalDuration) + tryIntervalSec *= 2 + } break; } catch (ex: net.corda.client.rpc.RPCException) { logger.info("ManualReconnect:numberOfTriesRemaining=$numberOfTriesRemaining") diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/StateMonitorClientSession.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/StateMonitorClientSession.kt index 61941137bbb..94095b1c761 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/StateMonitorClientSession.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/StateMonitorClientSession.kt @@ -10,7 +10,7 @@ import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.GetMoni import rx.Subscription import java.math.BigInteger import java.time.LocalDateTime -import javax.annotation.PreDestroy +import jakarta.annotation.PreDestroy /** * Monitoring session for single client, can track multiple state changes. diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/StateMonitorSessionsManager.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/StateMonitorSessionsManager.kt index 478ed59d497..68612be09ec 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/StateMonitorSessionsManager.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/StateMonitorSessionsManager.kt @@ -4,7 +4,7 @@ import net.corda.core.utilities.loggerFor import org.springframework.beans.factory.annotation.Value import org.springframework.scheduling.annotation.Scheduled import org.springframework.stereotype.Component -import javax.annotation.PreDestroy +import jakarta.annotation.PreDestroy private const val SessionExpireMinutes = "cactus.sessionExpireMinutes" private const val SessionExpireMinutesDefault = "30" diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CPIIDV1.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CPIIDV1.kt index 143fea9f02c..2e7171ff647 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CPIIDV1.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CPIIDV1.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ClearMonitorTransactionsV1Request.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ClearMonitorTransactionsV1Request.kt index bc44d5f87ce..bebd7e96bfc 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ClearMonitorTransactionsV1Request.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ClearMonitorTransactionsV1Request.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ClearMonitorTransactionsV1Response.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ClearMonitorTransactionsV1Response.kt index 39c71000b67..f435606cb2f 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ClearMonitorTransactionsV1Response.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ClearMonitorTransactionsV1Response.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CordaNodeSshCredentials.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CordaNodeSshCredentials.kt index 50e153b11f2..7a0e3c2aaf5 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CordaNodeSshCredentials.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CordaNodeSshCredentials.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CordaRpcCredentials.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CordaRpcCredentials.kt index 60dc4b9ff55..9f852bf2869 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CordaRpcCredentials.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CordaRpcCredentials.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CordaX500Name.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CordaX500Name.kt index 356992db1a8..9e429e1f51f 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CordaX500Name.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CordaX500Name.kt @@ -3,15 +3,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.X500Principal -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CordappDeploymentConfig.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CordappDeploymentConfig.kt index a0238b5b8d7..88b4022e0a2 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CordappDeploymentConfig.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CordappDeploymentConfig.kt @@ -4,15 +4,15 @@ import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.CordaNodeSshCredentials import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.CordaRpcCredentials -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CordappInfo.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CordappInfo.kt index 3a7d70d818b..738d8cac90d 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CordappInfo.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/CordappInfo.kt @@ -3,15 +3,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.SHA256 -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * A CordappInfo describes a single CorDapp currently installed on the node diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/DeployContractJarsBadRequestV1Response.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/DeployContractJarsBadRequestV1Response.kt index f245cd7489f..0835a699f8f 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/DeployContractJarsBadRequestV1Response.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/DeployContractJarsBadRequestV1Response.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/DeployContractJarsSuccessV1Response.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/DeployContractJarsSuccessV1Response.kt index 8b07a85c485..55f96b68c09 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/DeployContractJarsSuccessV1Response.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/DeployContractJarsSuccessV1Response.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/DeployContractJarsV1Request.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/DeployContractJarsV1Request.kt index fd41b4e5df8..f99ef6793db 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/DeployContractJarsV1Request.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/DeployContractJarsV1Request.kt @@ -4,15 +4,15 @@ import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.CordappDeploymentConfig import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.JarFile -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/DiagnoseNodeV1Request.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/DiagnoseNodeV1Request.kt index c2979e93483..86891696089 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/DiagnoseNodeV1Request.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/DiagnoseNodeV1Request.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/DiagnoseNodeV1Response.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/DiagnoseNodeV1Response.kt index 43e8e20100a..f2882bf68e7 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/DiagnoseNodeV1Response.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/DiagnoseNodeV1Response.kt @@ -3,15 +3,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.NodeDiagnosticInfo -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/FlowInvocationType.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/FlowInvocationType.kt index bfe5af907e9..eef42f04ec6 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/FlowInvocationType.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/FlowInvocationType.kt @@ -3,15 +3,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonValue import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * Determines which flow starting method will be used on the back-end when invoking the flow. Based on the value here the plugin back-end might invoke the rpc.startFlowDynamic() method or the rpc.startTrackedFlowDynamic() method. Streamed responses are aggregated and returned in a single response to HTTP callers who are not equipped to handle streams like WebSocket/gRPC/etc. do. diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/FlowStatusV1Responses.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/FlowStatusV1Responses.kt index 23e16451a35..10f256de802 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/FlowStatusV1Responses.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/FlowStatusV1Responses.kt @@ -3,15 +3,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.FlowStatusV1ResponsesFlowStatusResponsesInner -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/FlowStatusV1ResponsesFlowStatusResponsesInner.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/FlowStatusV1ResponsesFlowStatusResponsesInner.kt index 4c175dc0abf..bbecc6b24df 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/FlowStatusV1ResponsesFlowStatusResponsesInner.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/FlowStatusV1ResponsesFlowStatusResponsesInner.kt @@ -3,15 +3,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.FlowV1Error -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/FlowV1Error.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/FlowV1Error.kt index e4873b9bded..3433ce5b63b 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/FlowV1Error.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/FlowV1Error.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/GetFlowCidV1Request.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/GetFlowCidV1Request.kt index 42e6d75247f..f5156c7fffa 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/GetFlowCidV1Request.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/GetFlowCidV1Request.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * This method gets the current status of the specified flow instance. diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/GetFlowCidV1Response.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/GetFlowCidV1Response.kt index a79f7120ca1..5a884fdd8c0 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/GetFlowCidV1Response.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/GetFlowCidV1Response.kt @@ -3,15 +3,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.FlowV1Error -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/GetMonitorTransactionsV1Request.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/GetMonitorTransactionsV1Request.kt index 744656d3366..970fbebcf11 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/GetMonitorTransactionsV1Request.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/GetMonitorTransactionsV1Request.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/GetMonitorTransactionsV1Response.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/GetMonitorTransactionsV1Response.kt index 18cddccbab7..4274f8f0e8f 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/GetMonitorTransactionsV1Response.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/GetMonitorTransactionsV1Response.kt @@ -3,15 +3,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.GetMonitorTransactionsV1ResponseTxInner -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/GetMonitorTransactionsV1ResponseTxInner.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/GetMonitorTransactionsV1ResponseTxInner.kt index e94e873ee28..1c00b2c9381 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/GetMonitorTransactionsV1ResponseTxInner.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/GetMonitorTransactionsV1ResponseTxInner.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/InvokeContractV1Request.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/InvokeContractV1Request.kt index 1e6b3cfc0d8..376bcebdbac 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/InvokeContractV1Request.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/InvokeContractV1Request.kt @@ -5,15 +5,15 @@ import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonValue import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.FlowInvocationType import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.JvmObject -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/InvokeContractV1Response.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/InvokeContractV1Response.kt index 14fe6309935..b80ad21f3e5 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/InvokeContractV1Response.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/InvokeContractV1Response.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/JarFile.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/JarFile.kt index 38305d4ab69..f3a757715c1 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/JarFile.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/JarFile.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/JvmObject.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/JvmObject.kt index e99f2420b56..bcb31caeb10 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/JvmObject.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/JvmObject.kt @@ -5,15 +5,15 @@ import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonValue import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.JvmType import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.JvmTypeKind -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * Can represent JVM primitive and reference types as well. The jvmTypeKind field indicates which one is being stored. If the jvmTypeKind field is set to REFERENCE then the jvmCtorArgs array is expected to be filled, otherwise (e.g. PRIMITIVE jvmTypeKind) it is expected that the primitiveValue property is filled with a primitive data type supported by the JSON standard such as strings, booleans, numbers, etc. diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/JvmType.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/JvmType.kt index 37f7c6e3e77..1e0919bb4b3 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/JvmType.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/JvmType.kt @@ -3,15 +3,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.JvmObject -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * Represents a reference to a JVM type (such as a Java class) diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/JvmTypeKind.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/JvmTypeKind.kt index a4a3c51084d..1be2461e045 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/JvmTypeKind.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/JvmTypeKind.kt @@ -3,15 +3,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonValue import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListCpiV1Request.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListCpiV1Request.kt index aca3b6dd396..4bb5669f48f 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListCpiV1Request.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListCpiV1Request.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListCpiV1Response.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListCpiV1Response.kt index b55eb9335fb..29cb9e163ef 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListCpiV1Response.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListCpiV1Response.kt @@ -3,15 +3,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.ListCpiV1ResponseCpisInner -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListCpiV1ResponseCpisInner.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListCpiV1ResponseCpisInner.kt index 909630fbf7a..0d8c291817c 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListCpiV1ResponseCpisInner.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListCpiV1ResponseCpisInner.kt @@ -4,15 +4,15 @@ import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.CPIIDV1 import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.ListCpiV1ResponseCpisInnerCpksInner -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListCpiV1ResponseCpisInnerCpksInner.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListCpiV1ResponseCpisInnerCpksInner.kt index 28ef9d1b62f..34e91309fba 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListCpiV1ResponseCpisInnerCpksInner.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListCpiV1ResponseCpisInnerCpksInner.kt @@ -3,15 +3,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.CPIIDV1 -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListFlowsV1Request.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListFlowsV1Request.kt index aad5c105e9f..4c8c2f836ce 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListFlowsV1Request.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListFlowsV1Request.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListFlowsV1Response.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListFlowsV1Response.kt index 660e823aefa..1e963b18878 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListFlowsV1Response.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/ListFlowsV1Response.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/NetworkHostAndPort.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/NetworkHostAndPort.kt index 435be03ea34..c0bff400c10 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/NetworkHostAndPort.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/NetworkHostAndPort.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/NodeDiagnosticInfo.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/NodeDiagnosticInfo.kt index d5d0b241616..77eba1ac3cf 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/NodeDiagnosticInfo.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/NodeDiagnosticInfo.kt @@ -3,15 +3,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.CordappInfo -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * A NodeDiagnosticInfo holds information about the current node version. diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/NodeInfo.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/NodeInfo.kt index ef886f1bbac..c822eb1877a 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/NodeInfo.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/NodeInfo.kt @@ -4,15 +4,15 @@ import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.NetworkHostAndPort import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.Party -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/Party.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/Party.kt index 3357599b145..972dc973178 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/Party.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/Party.kt @@ -4,15 +4,15 @@ import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.CordaX500Name import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.PublicKey -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/PublicKey.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/PublicKey.kt index 1028a74e769..d373dedce52 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/PublicKey.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/PublicKey.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * An instance of a java.security.PublicKey (which is an interface) implementation such as org.hyperledger.cactus.plugin.ledger.connector.corda.server.impl.PublicKeyImpl diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/SHA256.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/SHA256.kt index dd82e7f257b..fb1de54dbb1 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/SHA256.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/SHA256.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * SHA-256 is part of the SHA-2 hash function family. Generated hash is fixed size, 256-bits (32-bytes). diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StartFlowV1Request.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StartFlowV1Request.kt index d5ea76eca04..d164e8a01ef 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StartFlowV1Request.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StartFlowV1Request.kt @@ -3,15 +3,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.StartFlowV1RequestRequestBody -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * This method starts a new instance for the specified flow for the specified holding identity. diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StartFlowV1RequestRequestBody.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StartFlowV1RequestRequestBody.kt index cb010c02e57..1ff348e505f 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StartFlowV1RequestRequestBody.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StartFlowV1RequestRequestBody.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StartFlowV1Response.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StartFlowV1Response.kt index 48965e722f5..73343822948 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StartFlowV1Response.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StartFlowV1Response.kt @@ -3,15 +3,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty import org.hyperledger.cactus.plugin.ledger.connector.corda.server.model.FlowV1Error -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StartMonitorV1Request.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StartMonitorV1Request.kt index 29c3be5b86d..cf28717052a 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StartMonitorV1Request.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StartMonitorV1Request.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StartMonitorV1Response.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StartMonitorV1Response.kt index 887b86e8281..c5a79e042d4 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StartMonitorV1Response.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StartMonitorV1Response.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StopMonitorV1Request.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StopMonitorV1Request.kt index a37c21aacc4..c6821d462f5 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StopMonitorV1Request.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StopMonitorV1Request.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StopMonitorV1Response.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StopMonitorV1Response.kt index 62aab56d124..c156bdaeab9 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StopMonitorV1Response.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/StopMonitorV1Response.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/VaultQueryV1Request.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/VaultQueryV1Request.kt index 9bce65fe322..15adf7af166 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/VaultQueryV1Request.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/VaultQueryV1Request.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/X500Principal.kt b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/X500Principal.kt index dd8a56df0bc..3278c037fa8 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/X500Principal.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/X500Principal.kt @@ -2,15 +2,15 @@ package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model import java.util.Objects import com.fasterxml.jackson.annotation.JsonProperty -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Email -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -import javax.validation.Valid +import jakarta.validation.constraints.DecimalMax +import jakarta.validation.constraints.DecimalMin +import jakarta.validation.constraints.Email +import jakarta.validation.constraints.Max +import jakarta.validation.constraints.Min +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import jakarta.validation.constraints.Size +import jakarta.validation.Valid /** * diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/resources/application.yaml b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/resources/application.yaml index 30cd4d063bc..c421877f07e 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/resources/application.yaml +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/resources/application.yaml @@ -1,6 +1,6 @@ spring: application: - name: Hyperledger Cactus - Corda Ledger Connector Plugin Server + name: Hyperledger Cacti - Corda V4 JVM Ledger Connector Plugin jackson: serialization: diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/mustache/generator-template-overrides/api.mustache b/packages/cactus-plugin-ledger-connector-corda/src/main-server/mustache/generator-template-overrides/api.mustache new file mode 100644 index 00000000000..fa61f4a7b05 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/mustache/generator-template-overrides/api.mustache @@ -0,0 +1,95 @@ +package {{package}} + +{{#imports}}import {{import}} +{{/imports}} +{{#swagger2AnnotationLibrary}} +import io.swagger.v3.oas.annotations.* +import io.swagger.v3.oas.annotations.enums.* +import io.swagger.v3.oas.annotations.media.* +import io.swagger.v3.oas.annotations.responses.* +import io.swagger.v3.oas.annotations.security.* +{{/swagger2AnnotationLibrary}} +{{#swagger1AnnotationLibrary}} +import io.swagger.annotations.Api +import io.swagger.annotations.ApiOperation +import io.swagger.annotations.ApiParam +import io.swagger.annotations.ApiResponse +import io.swagger.annotations.ApiResponses +import io.swagger.annotations.Authorization +import io.swagger.annotations.AuthorizationScope +{{/swagger1AnnotationLibrary}} +import org.springframework.http.HttpStatus +import org.springframework.http.MediaType +import org.springframework.http.ResponseEntity + +import org.springframework.web.bind.annotation.* +{{#useBeanValidation}} +import org.springframework.validation.annotation.Validated +{{/useBeanValidation}} +import org.springframework.web.context.request.NativeWebRequest +import org.springframework.beans.factory.annotation.Autowired + +{{#useBeanValidation}} +import {{javaxPackage}}.validation.Valid +import {{javaxPackage}}.validation.constraints.DecimalMax +import {{javaxPackage}}.validation.constraints.DecimalMin +import {{javaxPackage}}.validation.constraints.Email +import {{javaxPackage}}.validation.constraints.Max +import {{javaxPackage}}.validation.constraints.Min +import {{javaxPackage}}.validation.constraints.NotNull +import {{javaxPackage}}.validation.constraints.Pattern +import {{javaxPackage}}.validation.constraints.Size +{{/useBeanValidation}} + +{{#reactive}} +import kotlinx.coroutines.flow.Flow +{{/reactive}} +import kotlin.collections.List +import kotlin.collections.Map + +@RestController{{#beanQualifiers}}("{{package}}.{{classname}}Controller"){{/beanQualifiers}} +{{#useBeanValidation}} +@Validated +{{/useBeanValidation}} +{{#swagger1AnnotationLibrary}} +@Api(value = "{{{baseName}}}", description = "The {{{baseName}}} API") +{{/swagger1AnnotationLibrary}} +{{=<% %>=}} +@RequestMapping("\${api.base-path:<%contextPath%>}") +<%={{ }}=%> +{{#operations}} +open class {{classname}}Controller({{#serviceInterface}}@Autowired(required = true) val service: {{classname}}Service{{/serviceInterface}}) { +{{#operation}} + + {{#swagger2AnnotationLibrary}} + @Operation( + summary = "{{{summary}}}", + operationId = "{{{operationId}}}", + description = """{{{unescapedNotes}}}""", + responses = [{{#responses}} + ApiResponse(responseCode = "{{{code}}}", description = "{{{message}}}"{{#baseType}}, content = [Content(schema = Schema(implementation = {{{baseType}}}::class))]{{/baseType}}){{^-last}},{{/-last}}{{/responses}} ]{{#hasAuthMethods}}, + security = [ {{#authMethods}}SecurityRequirement(name = "{{name}}"{{#isOAuth}}, scopes = [ {{#scopes}}"{{scope}}"{{^-last}}, {{/-last}}{{/scopes}} ]{{/isOAuth}}){{^-last}},{{/-last}}{{/authMethods}} ]{{/hasAuthMethods}} + ){{/swagger2AnnotationLibrary}}{{#swagger1AnnotationLibrary}} + @ApiOperation( + value = "{{{summary}}}", + nickname = "{{{operationId}}}", + notes = "{{{notes}}}"{{#returnBaseType}}, + response = {{{.}}}::class{{/returnBaseType}}{{#returnContainer}}, + responseContainer = "{{{.}}}"{{/returnContainer}}{{#hasAuthMethods}}, + authorizations = [{{#authMethods}}Authorization(value = "{{name}}"{{#isOAuth}}, scopes = [{{#scopes}}AuthorizationScope(scope = "{{scope}}", description = "{{description}}"){{^-last}}, {{/-last}}{{/scopes}}]{{/isOAuth}}){{^-last}}, {{/-last}}{{/authMethods}}]{{/hasAuthMethods}}) + @ApiResponses( + value = [{{#responses}}ApiResponse(code = {{{code}}}, message = "{{{message}}}"{{#baseType}}, response = {{{.}}}::class{{/baseType}}{{#containerType}}, responseContainer = "{{{.}}}"{{/containerType}}){{^-last}},{{/-last}}{{/responses}}]){{/swagger1AnnotationLibrary}} + @RequestMapping( + method = [RequestMethod.{{httpMethod}}], + value = ["{{#lambda.escapeDoubleQuote}}{{path}}{{/lambda.escapeDoubleQuote}}"]{{#singleContentTypes}}{{#hasProduces}}, + produces = "{{{vendorExtensions.x-accepts}}}"{{/hasProduces}}{{#hasConsumes}}, + consumes = "{{{vendorExtensions.x-content-type}}}"{{/hasConsumes}}{{/singleContentTypes}}{{^singleContentTypes}}{{#hasProduces}}, + produces = [{{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}}]{{/hasProduces}}{{#hasConsumes}}, + consumes = [{{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}}]{{/hasConsumes}}{{/singleContentTypes}} + ) + {{#reactive}}{{^isArray}}suspend {{/isArray}}{{/reactive}}open fun {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{^-last}},{{/-last}}{{/allParams}}): ResponseEntity<{{>returnTypes}}> { + return {{>returnValue}} + } +{{/operation}} +} +{{/operations}} diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/mustache/generator-template-overrides/libraries/spring-boot/settingsGradle.mustache b/packages/cactus-plugin-ledger-connector-corda/src/main-server/mustache/generator-template-overrides/libraries/spring-boot/settingsGradle.mustache new file mode 100644 index 00000000000..4deed84141e --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/mustache/generator-template-overrides/libraries/spring-boot/settingsGradle.mustache @@ -0,0 +1,21 @@ +pluginManagement { + repositories { + maven { url = uri("https://repo.spring.io/snapshot") } + maven { url = uri("https://repo.spring.io/milestone") } + gradlePluginPortal() + } + resolutionStrategy { + eachPlugin { + if (requested.id.id == "org.springframework.boot") { + useModule("org.springframework.boot:spring-boot-gradle-plugin:${requested.version}") + } + } + } +} + +rootProject.name = "{{artifactId}}" +// The template modification Cacti needs so that we can alter the artifact name +// at build time in our scripts. This is handy when we build a .jar to be scanned +// by trivy and we don't want to have to guess what the .jar filename ended up being +// (which is different after each release) +rootProject.name = System.getProperty('rootProjectName') ?: rootProject.name diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/openapi-generator-config.yaml b/packages/cactus-plugin-ledger-connector-corda/src/main-server/openapi-generator-config.yaml index 15e31b1d285..e221feaacfe 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/openapi-generator-config.yaml +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/openapi-generator-config.yaml @@ -1,7 +1,7 @@ templateDir: src/main-server/mustache/generator-template-overrides/ additionalProperties: - title: "Hyperledger Cactus - Corda Ledger Connector Plugin Server" + title: "Hyperledger Cacti - Corda V4 JVM Ledger Connector Plugin" groupId: org.hyperledger.cactus artifactId: cactus-connector-corda-server # TODO: Make sure this automatically gets bumped during releases so that it @@ -29,4 +29,10 @@ additionalProperties: # e: /kotlin-spring/src/test/kotlin/org/openapitools/api/ApiApiTest.kt: (45, 39): Unresolved reference: runBlockingTest # e: /kotlin-spring/src/test/kotlin/org/openapitools/api/ApiApiTest.kt: (47, 70): Suspend function 'cordaInvokeContractV1' should be called only from a coroutine or another suspend function # - reactive: false \ No newline at end of file + reactive: false + + # annotationLibrary: none + # useSwaggerUI: "false" + # serializableModel: "true" + # beanValidations: "true" + useSpringBoot3: "true" diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main-server/start-app.sh b/packages/cactus-plugin-ledger-connector-corda/src/main-server/start-app.sh index 7caeb6a0008..017a38e78bb 100755 --- a/packages/cactus-plugin-ledger-connector-corda/src/main-server/start-app.sh +++ b/packages/cactus-plugin-ledger-connector-corda/src/main-server/start-app.sh @@ -3,7 +3,8 @@ # Without these we get crashes on JDK 17 an above since the introduction of the # Java Modules system. -EXTRA_JVM_ARGS="--add-exports java.base/sun.security.provider.certpath=ALL-UNNAMED" +EXTRA_JVM_ARGS="--add-exports java.base/sun.security.ec.ed=ALL-UNNAMED" +EXTRA_JVM_ARGS="--add-exports java.base/sun.security.provider.certpath=ALL-UNNAMED ${EXTRA_JVM_ARGS}" EXTRA_JVM_ARGS="--add-exports java.base/sun.security.util=ALL-UNNAMED ${EXTRA_JVM_ARGS}" EXTRA_JVM_ARGS="--add-exports java.base/sun.security.rsa=ALL-UNNAMED ${EXTRA_JVM_ARGS}" EXTRA_JVM_ARGS="--add-exports jdk.crypto.ec/sun.security.ec=ALL-UNNAMED ${EXTRA_JVM_ARGS}" diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main/go/generated/openapi/go-client/api/openapi.yaml b/packages/cactus-plugin-ledger-connector-corda/src/main/go/generated/openapi/go-client/api/openapi.yaml index d6698f19dfe..641ef660c53 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main/go/generated/openapi/go-client/api/openapi.yaml +++ b/packages/cactus-plugin-ledger-connector-corda/src/main/go/generated/openapi/go-client/api/openapi.yaml @@ -20,6 +20,7 @@ paths: application/json: schema: $ref: '#/components/schemas/VaultQueryV1Request' + required: true responses: "200": content: @@ -40,6 +41,7 @@ paths: application/json: schema: $ref: '#/components/schemas/DeployContractJarsV1Request' + required: true responses: "200": content: @@ -68,6 +70,7 @@ paths: application/json: schema: $ref: '#/components/schemas/InvokeContractV1Request' + required: true responses: "200": content: @@ -89,6 +92,7 @@ paths: application/json: schema: $ref: '#/components/schemas/StartMonitorV1Request' + required: true responses: "200": content: @@ -110,6 +114,7 @@ paths: application/json: schema: $ref: '#/components/schemas/GetMonitorTransactionsV1Request' + required: true responses: "200": content: @@ -131,6 +136,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ClearMonitorTransactionsV1Request' + required: true responses: "200": content: @@ -153,6 +159,7 @@ paths: application/json: schema: $ref: '#/components/schemas/StopMonitorV1Request' + required: true responses: "200": content: @@ -177,6 +184,7 @@ paths: application/json: schema: $ref: '#/components/schemas/NetworkMapV1Request' + required: false responses: "200": content: @@ -198,6 +206,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ListFlowsV1Request' + required: false responses: "200": content: @@ -219,6 +228,7 @@ paths: application/json: schema: $ref: '#/components/schemas/DiagnoseNodeV1Request' + required: false responses: "200": content: diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main/go/generated/openapi/go-client/api_default.go b/packages/cactus-plugin-ledger-connector-corda/src/main/go/generated/openapi/go-client/api_default.go index 7a76db5938a..25ccea4c393 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main/go/generated/openapi/go-client/api_default.go +++ b/packages/cactus-plugin-ledger-connector-corda/src/main/go/generated/openapi/go-client/api_default.go @@ -70,6 +70,9 @@ func (a *DefaultApiService) ClearMonitorTransactionsV1Execute(r ApiClearMonitorT localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} + if r.clearMonitorTransactionsV1Request == nil { + return localVarReturnValue, nil, reportError("clearMonitorTransactionsV1Request is required and must be specified") + } // to determine the Content-Type header localVarHTTPContentTypes := []string{"application/json"} @@ -175,6 +178,9 @@ func (a *DefaultApiService) DeployContractJarsV1Execute(r ApiDeployContractJarsV localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} + if r.deployContractJarsV1Request == nil { + return localVarReturnValue, nil, reportError("deployContractJarsV1Request is required and must be specified") + } // to determine the Content-Type header localVarHTTPContentTypes := []string{"application/json"} @@ -506,6 +512,9 @@ func (a *DefaultApiService) GetMonitorTransactionsV1Execute(r ApiGetMonitorTrans localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} + if r.getMonitorTransactionsV1Request == nil { + return localVarReturnValue, nil, reportError("getMonitorTransactionsV1Request is required and must be specified") + } // to determine the Content-Type header localVarHTTPContentTypes := []string{"application/json"} @@ -708,6 +717,9 @@ func (a *DefaultApiService) InvokeContractV1Execute(r ApiInvokeContractV1Request localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} + if r.invokeContractV1Request == nil { + return localVarReturnValue, nil, reportError("invokeContractV1Request is required and must be specified") + } // to determine the Content-Type header localVarHTTPContentTypes := []string{"application/json"} @@ -1353,6 +1365,9 @@ func (a *DefaultApiService) StartMonitorV1Execute(r ApiStartMonitorV1Request) (* localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} + if r.startMonitorV1Request == nil { + return localVarReturnValue, nil, reportError("startMonitorV1Request is required and must be specified") + } // to determine the Content-Type header localVarHTTPContentTypes := []string{"application/json"} @@ -1458,6 +1473,9 @@ func (a *DefaultApiService) StopMonitorV1Execute(r ApiStopMonitorV1Request) (*St localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} + if r.stopMonitorV1Request == nil { + return localVarReturnValue, nil, reportError("stopMonitorV1Request is required and must be specified") + } // to determine the Content-Type header localVarHTTPContentTypes := []string{"application/json"} @@ -1565,6 +1583,9 @@ func (a *DefaultApiService) VaultQueryV1Execute(r ApiVaultQueryV1Request) (map[s localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} + if r.vaultQueryV1Request == nil { + return localVarReturnValue, nil, reportError("vaultQueryV1Request is required and must be specified") + } // to determine the Content-Type header localVarHTTPContentTypes := []string{"application/json"} diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main/json/openapi.json b/packages/cactus-plugin-ledger-connector-corda/src/main/json/openapi.json index 91340c6046f..0ffb43bdac0 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main/json/openapi.json +++ b/packages/cactus-plugin-ledger-connector-corda/src/main/json/openapi.json @@ -1242,6 +1242,7 @@ "description": "Queryes the vault service for state references based on JVM class names. Custom filters are not supported by this endpoint.", "parameters": [], "requestBody": { + "required": true, "content": { "application/json": { "schema": { @@ -1276,6 +1277,7 @@ "summary": "Deploys a set of jar files (Cordapps, e.g. the contracts in Corda speak).", "parameters": [], "requestBody": { + "required": true, "content": { "application/json": { "schema": { @@ -1320,6 +1322,7 @@ "summary": "Invokes a contract on a Corda ledger (e.g. a flow)", "parameters": [], "requestBody": { + "required": true, "content": { "application/json": { "schema": { @@ -1354,6 +1357,7 @@ "summary": "Start monitoring corda changes (transactions) of given state class", "parameters": [], "requestBody": { + "required": true, "content": { "application/json": { "schema": { @@ -1388,6 +1392,7 @@ "summary": "Get transactions for monitored state classes.", "parameters": [], "requestBody": { + "required": true, "content": { "application/json": { "schema": { @@ -1422,6 +1427,7 @@ "summary": "Clear transactions from internal store so they'll not be available by GetMonitorTransactionsV1 anymore.", "parameters": [], "requestBody": { + "required": true, "content": { "application/json": { "schema": { @@ -1456,6 +1462,7 @@ "summary": "Stop monitoring corda changes (transactions) of given state class", "parameters": [], "requestBody": { + "required": true, "content": { "application/json": { "schema": { @@ -1490,6 +1497,7 @@ "description": "Responds with a snapshot of the network map as provided by the Corda RPC call: net.corda.core.messaging.CordaRPCOps public abstract fun networkMapSnapshot(): List", "parameters": [], "requestBody": { + "required": false, "content": { "application/json": { "schema": { @@ -1524,6 +1532,7 @@ "description": "Responds with a list of the flows on the Corda node.", "parameters": [], "requestBody": { + "required": false, "content": { "application/json": { "schema": { @@ -1558,6 +1567,7 @@ "description": "Responds with diagnostic information about the Corda node", "parameters": [], "requestBody": { + "required": false, "content": { "application/json": { "schema": { diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main/json/openapi.tpl.json b/packages/cactus-plugin-ledger-connector-corda/src/main/json/openapi.tpl.json index 91340c6046f..0ffb43bdac0 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main/json/openapi.tpl.json +++ b/packages/cactus-plugin-ledger-connector-corda/src/main/json/openapi.tpl.json @@ -1242,6 +1242,7 @@ "description": "Queryes the vault service for state references based on JVM class names. Custom filters are not supported by this endpoint.", "parameters": [], "requestBody": { + "required": true, "content": { "application/json": { "schema": { @@ -1276,6 +1277,7 @@ "summary": "Deploys a set of jar files (Cordapps, e.g. the contracts in Corda speak).", "parameters": [], "requestBody": { + "required": true, "content": { "application/json": { "schema": { @@ -1320,6 +1322,7 @@ "summary": "Invokes a contract on a Corda ledger (e.g. a flow)", "parameters": [], "requestBody": { + "required": true, "content": { "application/json": { "schema": { @@ -1354,6 +1357,7 @@ "summary": "Start monitoring corda changes (transactions) of given state class", "parameters": [], "requestBody": { + "required": true, "content": { "application/json": { "schema": { @@ -1388,6 +1392,7 @@ "summary": "Get transactions for monitored state classes.", "parameters": [], "requestBody": { + "required": true, "content": { "application/json": { "schema": { @@ -1422,6 +1427,7 @@ "summary": "Clear transactions from internal store so they'll not be available by GetMonitorTransactionsV1 anymore.", "parameters": [], "requestBody": { + "required": true, "content": { "application/json": { "schema": { @@ -1456,6 +1462,7 @@ "summary": "Stop monitoring corda changes (transactions) of given state class", "parameters": [], "requestBody": { + "required": true, "content": { "application/json": { "schema": { @@ -1490,6 +1497,7 @@ "description": "Responds with a snapshot of the network map as provided by the Corda RPC call: net.corda.core.messaging.CordaRPCOps public abstract fun networkMapSnapshot(): List", "parameters": [], "requestBody": { + "required": false, "content": { "application/json": { "schema": { @@ -1524,6 +1532,7 @@ "description": "Responds with a list of the flows on the Corda node.", "parameters": [], "requestBody": { + "required": false, "content": { "application/json": { "schema": { @@ -1558,6 +1567,7 @@ "description": "Responds with diagnostic information about the Corda node", "parameters": [], "requestBody": { + "required": false, "content": { "application/json": { "schema": { diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/apis/DefaultApi.kt b/packages/cactus-plugin-ledger-connector-corda/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/apis/DefaultApi.kt index 55d83cd9f14..ef8c09c4518 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/apis/DefaultApi.kt +++ b/packages/cactus-plugin-ledger-connector-corda/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/apis/DefaultApi.kt @@ -73,7 +73,7 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient /** * Clear transactions from internal store so they'll not be available by GetMonitorTransactionsV1 anymore. * - * @param clearMonitorTransactionsV1Request (optional) + * @param clearMonitorTransactionsV1Request * @return ClearMonitorTransactionsV1Response * @throws IllegalStateException If the request is not correctly configured * @throws IOException Rethrows the OkHttp execute method exception @@ -83,7 +83,7 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient */ @Suppress("UNCHECKED_CAST") @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) - fun clearMonitorTransactionsV1(clearMonitorTransactionsV1Request: ClearMonitorTransactionsV1Request? = null) : ClearMonitorTransactionsV1Response { + fun clearMonitorTransactionsV1(clearMonitorTransactionsV1Request: ClearMonitorTransactionsV1Request) : ClearMonitorTransactionsV1Response { val localVarResponse = clearMonitorTransactionsV1WithHttpInfo(clearMonitorTransactionsV1Request = clearMonitorTransactionsV1Request) return when (localVarResponse.responseType) { @@ -104,14 +104,14 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient /** * Clear transactions from internal store so they'll not be available by GetMonitorTransactionsV1 anymore. * - * @param clearMonitorTransactionsV1Request (optional) + * @param clearMonitorTransactionsV1Request * @return ApiResponse * @throws IllegalStateException If the request is not correctly configured * @throws IOException Rethrows the OkHttp execute method exception */ @Suppress("UNCHECKED_CAST") @Throws(IllegalStateException::class, IOException::class) - fun clearMonitorTransactionsV1WithHttpInfo(clearMonitorTransactionsV1Request: ClearMonitorTransactionsV1Request?) : ApiResponse { + fun clearMonitorTransactionsV1WithHttpInfo(clearMonitorTransactionsV1Request: ClearMonitorTransactionsV1Request) : ApiResponse { val localVariableConfig = clearMonitorTransactionsV1RequestConfig(clearMonitorTransactionsV1Request = clearMonitorTransactionsV1Request) return request( @@ -122,10 +122,10 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient /** * To obtain the request config of the operation clearMonitorTransactionsV1 * - * @param clearMonitorTransactionsV1Request (optional) + * @param clearMonitorTransactionsV1Request * @return RequestConfig */ - fun clearMonitorTransactionsV1RequestConfig(clearMonitorTransactionsV1Request: ClearMonitorTransactionsV1Request?) : RequestConfig { + fun clearMonitorTransactionsV1RequestConfig(clearMonitorTransactionsV1Request: ClearMonitorTransactionsV1Request) : RequestConfig { val localVariableBody = clearMonitorTransactionsV1Request val localVariableQuery: MultiValueMap = mutableMapOf() val localVariableHeaders: MutableMap = mutableMapOf() @@ -145,7 +145,7 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient /** * Deploys a set of jar files (Cordapps, e.g. the contracts in Corda speak). * - * @param deployContractJarsV1Request (optional) + * @param deployContractJarsV1Request * @return DeployContractJarsSuccessV1Response * @throws IllegalStateException If the request is not correctly configured * @throws IOException Rethrows the OkHttp execute method exception @@ -155,7 +155,7 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient */ @Suppress("UNCHECKED_CAST") @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) - fun deployContractJarsV1(deployContractJarsV1Request: DeployContractJarsV1Request? = null) : DeployContractJarsSuccessV1Response { + fun deployContractJarsV1(deployContractJarsV1Request: DeployContractJarsV1Request) : DeployContractJarsSuccessV1Response { val localVarResponse = deployContractJarsV1WithHttpInfo(deployContractJarsV1Request = deployContractJarsV1Request) return when (localVarResponse.responseType) { @@ -176,14 +176,14 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient /** * Deploys a set of jar files (Cordapps, e.g. the contracts in Corda speak). * - * @param deployContractJarsV1Request (optional) + * @param deployContractJarsV1Request * @return ApiResponse * @throws IllegalStateException If the request is not correctly configured * @throws IOException Rethrows the OkHttp execute method exception */ @Suppress("UNCHECKED_CAST") @Throws(IllegalStateException::class, IOException::class) - fun deployContractJarsV1WithHttpInfo(deployContractJarsV1Request: DeployContractJarsV1Request?) : ApiResponse { + fun deployContractJarsV1WithHttpInfo(deployContractJarsV1Request: DeployContractJarsV1Request) : ApiResponse { val localVariableConfig = deployContractJarsV1RequestConfig(deployContractJarsV1Request = deployContractJarsV1Request) return request( @@ -194,10 +194,10 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient /** * To obtain the request config of the operation deployContractJarsV1 * - * @param deployContractJarsV1Request (optional) + * @param deployContractJarsV1Request * @return RequestConfig */ - fun deployContractJarsV1RequestConfig(deployContractJarsV1Request: DeployContractJarsV1Request?) : RequestConfig { + fun deployContractJarsV1RequestConfig(deployContractJarsV1Request: DeployContractJarsV1Request) : RequestConfig { val localVariableBody = deployContractJarsV1Request val localVariableQuery: MultiValueMap = mutableMapOf() val localVariableHeaders: MutableMap = mutableMapOf() @@ -360,7 +360,7 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient /** * Get transactions for monitored state classes. * - * @param getMonitorTransactionsV1Request (optional) + * @param getMonitorTransactionsV1Request * @return GetMonitorTransactionsV1Response * @throws IllegalStateException If the request is not correctly configured * @throws IOException Rethrows the OkHttp execute method exception @@ -370,7 +370,7 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient */ @Suppress("UNCHECKED_CAST") @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) - fun getMonitorTransactionsV1(getMonitorTransactionsV1Request: GetMonitorTransactionsV1Request? = null) : GetMonitorTransactionsV1Response { + fun getMonitorTransactionsV1(getMonitorTransactionsV1Request: GetMonitorTransactionsV1Request) : GetMonitorTransactionsV1Response { val localVarResponse = getMonitorTransactionsV1WithHttpInfo(getMonitorTransactionsV1Request = getMonitorTransactionsV1Request) return when (localVarResponse.responseType) { @@ -391,14 +391,14 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient /** * Get transactions for monitored state classes. * - * @param getMonitorTransactionsV1Request (optional) + * @param getMonitorTransactionsV1Request * @return ApiResponse * @throws IllegalStateException If the request is not correctly configured * @throws IOException Rethrows the OkHttp execute method exception */ @Suppress("UNCHECKED_CAST") @Throws(IllegalStateException::class, IOException::class) - fun getMonitorTransactionsV1WithHttpInfo(getMonitorTransactionsV1Request: GetMonitorTransactionsV1Request?) : ApiResponse { + fun getMonitorTransactionsV1WithHttpInfo(getMonitorTransactionsV1Request: GetMonitorTransactionsV1Request) : ApiResponse { val localVariableConfig = getMonitorTransactionsV1RequestConfig(getMonitorTransactionsV1Request = getMonitorTransactionsV1Request) return request( @@ -409,10 +409,10 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient /** * To obtain the request config of the operation getMonitorTransactionsV1 * - * @param getMonitorTransactionsV1Request (optional) + * @param getMonitorTransactionsV1Request * @return RequestConfig */ - fun getMonitorTransactionsV1RequestConfig(getMonitorTransactionsV1Request: GetMonitorTransactionsV1Request?) : RequestConfig { + fun getMonitorTransactionsV1RequestConfig(getMonitorTransactionsV1Request: GetMonitorTransactionsV1Request) : RequestConfig { val localVariableBody = getMonitorTransactionsV1Request val localVariableQuery: MultiValueMap = mutableMapOf() val localVariableHeaders: MutableMap = mutableMapOf() @@ -499,7 +499,7 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient /** * Invokes a contract on a Corda ledger (e.g. a flow) * - * @param invokeContractV1Request (optional) + * @param invokeContractV1Request * @return InvokeContractV1Response * @throws IllegalStateException If the request is not correctly configured * @throws IOException Rethrows the OkHttp execute method exception @@ -509,7 +509,7 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient */ @Suppress("UNCHECKED_CAST") @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) - fun invokeContractV1(invokeContractV1Request: InvokeContractV1Request? = null) : InvokeContractV1Response { + fun invokeContractV1(invokeContractV1Request: InvokeContractV1Request) : InvokeContractV1Response { val localVarResponse = invokeContractV1WithHttpInfo(invokeContractV1Request = invokeContractV1Request) return when (localVarResponse.responseType) { @@ -530,14 +530,14 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient /** * Invokes a contract on a Corda ledger (e.g. a flow) * - * @param invokeContractV1Request (optional) + * @param invokeContractV1Request * @return ApiResponse * @throws IllegalStateException If the request is not correctly configured * @throws IOException Rethrows the OkHttp execute method exception */ @Suppress("UNCHECKED_CAST") @Throws(IllegalStateException::class, IOException::class) - fun invokeContractV1WithHttpInfo(invokeContractV1Request: InvokeContractV1Request?) : ApiResponse { + fun invokeContractV1WithHttpInfo(invokeContractV1Request: InvokeContractV1Request) : ApiResponse { val localVariableConfig = invokeContractV1RequestConfig(invokeContractV1Request = invokeContractV1Request) return request( @@ -548,10 +548,10 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient /** * To obtain the request config of the operation invokeContractV1 * - * @param invokeContractV1Request (optional) + * @param invokeContractV1Request * @return RequestConfig */ - fun invokeContractV1RequestConfig(invokeContractV1Request: InvokeContractV1Request?) : RequestConfig { + fun invokeContractV1RequestConfig(invokeContractV1Request: InvokeContractV1Request) : RequestConfig { val localVariableBody = invokeContractV1Request val localVariableQuery: MultiValueMap = mutableMapOf() val localVariableHeaders: MutableMap = mutableMapOf() @@ -930,7 +930,7 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient /** * Start monitoring corda changes (transactions) of given state class * - * @param startMonitorV1Request (optional) + * @param startMonitorV1Request * @return StartMonitorV1Response * @throws IllegalStateException If the request is not correctly configured * @throws IOException Rethrows the OkHttp execute method exception @@ -940,7 +940,7 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient */ @Suppress("UNCHECKED_CAST") @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) - fun startMonitorV1(startMonitorV1Request: StartMonitorV1Request? = null) : StartMonitorV1Response { + fun startMonitorV1(startMonitorV1Request: StartMonitorV1Request) : StartMonitorV1Response { val localVarResponse = startMonitorV1WithHttpInfo(startMonitorV1Request = startMonitorV1Request) return when (localVarResponse.responseType) { @@ -961,14 +961,14 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient /** * Start monitoring corda changes (transactions) of given state class * - * @param startMonitorV1Request (optional) + * @param startMonitorV1Request * @return ApiResponse * @throws IllegalStateException If the request is not correctly configured * @throws IOException Rethrows the OkHttp execute method exception */ @Suppress("UNCHECKED_CAST") @Throws(IllegalStateException::class, IOException::class) - fun startMonitorV1WithHttpInfo(startMonitorV1Request: StartMonitorV1Request?) : ApiResponse { + fun startMonitorV1WithHttpInfo(startMonitorV1Request: StartMonitorV1Request) : ApiResponse { val localVariableConfig = startMonitorV1RequestConfig(startMonitorV1Request = startMonitorV1Request) return request( @@ -979,10 +979,10 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient /** * To obtain the request config of the operation startMonitorV1 * - * @param startMonitorV1Request (optional) + * @param startMonitorV1Request * @return RequestConfig */ - fun startMonitorV1RequestConfig(startMonitorV1Request: StartMonitorV1Request?) : RequestConfig { + fun startMonitorV1RequestConfig(startMonitorV1Request: StartMonitorV1Request) : RequestConfig { val localVariableBody = startMonitorV1Request val localVariableQuery: MultiValueMap = mutableMapOf() val localVariableHeaders: MutableMap = mutableMapOf() @@ -1002,7 +1002,7 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient /** * Stop monitoring corda changes (transactions) of given state class * - * @param stopMonitorV1Request (optional) + * @param stopMonitorV1Request * @return StopMonitorV1Response * @throws IllegalStateException If the request is not correctly configured * @throws IOException Rethrows the OkHttp execute method exception @@ -1012,7 +1012,7 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient */ @Suppress("UNCHECKED_CAST") @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) - fun stopMonitorV1(stopMonitorV1Request: StopMonitorV1Request? = null) : StopMonitorV1Response { + fun stopMonitorV1(stopMonitorV1Request: StopMonitorV1Request) : StopMonitorV1Response { val localVarResponse = stopMonitorV1WithHttpInfo(stopMonitorV1Request = stopMonitorV1Request) return when (localVarResponse.responseType) { @@ -1033,14 +1033,14 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient /** * Stop monitoring corda changes (transactions) of given state class * - * @param stopMonitorV1Request (optional) + * @param stopMonitorV1Request * @return ApiResponse * @throws IllegalStateException If the request is not correctly configured * @throws IOException Rethrows the OkHttp execute method exception */ @Suppress("UNCHECKED_CAST") @Throws(IllegalStateException::class, IOException::class) - fun stopMonitorV1WithHttpInfo(stopMonitorV1Request: StopMonitorV1Request?) : ApiResponse { + fun stopMonitorV1WithHttpInfo(stopMonitorV1Request: StopMonitorV1Request) : ApiResponse { val localVariableConfig = stopMonitorV1RequestConfig(stopMonitorV1Request = stopMonitorV1Request) return request( @@ -1051,10 +1051,10 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient /** * To obtain the request config of the operation stopMonitorV1 * - * @param stopMonitorV1Request (optional) + * @param stopMonitorV1Request * @return RequestConfig */ - fun stopMonitorV1RequestConfig(stopMonitorV1Request: StopMonitorV1Request?) : RequestConfig { + fun stopMonitorV1RequestConfig(stopMonitorV1Request: StopMonitorV1Request) : RequestConfig { val localVariableBody = stopMonitorV1Request val localVariableQuery: MultiValueMap = mutableMapOf() val localVariableHeaders: MutableMap = mutableMapOf() @@ -1074,7 +1074,7 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient /** * * Queryes the vault service for state references based on JVM class names. Custom filters are not supported by this endpoint. - * @param vaultQueryV1Request (optional) + * @param vaultQueryV1Request * @return kotlin.Any * @throws IllegalStateException If the request is not correctly configured * @throws IOException Rethrows the OkHttp execute method exception @@ -1084,7 +1084,7 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient */ @Suppress("UNCHECKED_CAST") @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) - fun vaultQueryV1(vaultQueryV1Request: VaultQueryV1Request? = null) : kotlin.Any { + fun vaultQueryV1(vaultQueryV1Request: VaultQueryV1Request) : kotlin.Any { val localVarResponse = vaultQueryV1WithHttpInfo(vaultQueryV1Request = vaultQueryV1Request) return when (localVarResponse.responseType) { @@ -1105,14 +1105,14 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient /** * * Queryes the vault service for state references based on JVM class names. Custom filters are not supported by this endpoint. - * @param vaultQueryV1Request (optional) + * @param vaultQueryV1Request * @return ApiResponse * @throws IllegalStateException If the request is not correctly configured * @throws IOException Rethrows the OkHttp execute method exception */ @Suppress("UNCHECKED_CAST") @Throws(IllegalStateException::class, IOException::class) - fun vaultQueryV1WithHttpInfo(vaultQueryV1Request: VaultQueryV1Request?) : ApiResponse { + fun vaultQueryV1WithHttpInfo(vaultQueryV1Request: VaultQueryV1Request) : ApiResponse { val localVariableConfig = vaultQueryV1RequestConfig(vaultQueryV1Request = vaultQueryV1Request) return request( @@ -1123,10 +1123,10 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient /** * To obtain the request config of the operation vaultQueryV1 * - * @param vaultQueryV1Request (optional) + * @param vaultQueryV1Request * @return RequestConfig */ - fun vaultQueryV1RequestConfig(vaultQueryV1Request: VaultQueryV1Request?) : RequestConfig { + fun vaultQueryV1RequestConfig(vaultQueryV1Request: VaultQueryV1Request) : RequestConfig { val localVariableBody = vaultQueryV1Request val localVariableQuery: MultiValueMap = mutableMapOf() val localVariableHeaders: MutableMap = mutableMapOf() diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main/typescript/generated/openapi/typescript-axios/api.ts b/packages/cactus-plugin-ledger-connector-corda/src/main/typescript/generated/openapi/typescript-axios/api.ts index 0ea6c3fea52..c6e8acd680d 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main/typescript/generated/openapi/typescript-axios/api.ts +++ b/packages/cactus-plugin-ledger-connector-corda/src/main/typescript/generated/openapi/typescript-axios/api.ts @@ -1362,11 +1362,13 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati /** * * @summary Clear transactions from internal store so they\'ll not be available by GetMonitorTransactionsV1 anymore. - * @param {ClearMonitorTransactionsV1Request} [clearMonitorTransactionsV1Request] + * @param {ClearMonitorTransactionsV1Request} clearMonitorTransactionsV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} */ - clearMonitorTransactionsV1: async (clearMonitorTransactionsV1Request?: ClearMonitorTransactionsV1Request, options: AxiosRequestConfig = {}): Promise => { + clearMonitorTransactionsV1: async (clearMonitorTransactionsV1Request: ClearMonitorTransactionsV1Request, options: AxiosRequestConfig = {}): Promise => { + // verify required parameter 'clearMonitorTransactionsV1Request' is not null or undefined + assertParamExists('clearMonitorTransactionsV1', 'clearMonitorTransactionsV1Request', clearMonitorTransactionsV1Request) const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/clear-monitor-transactions`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -1396,11 +1398,13 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati /** * * @summary Deploys a set of jar files (Cordapps, e.g. the contracts in Corda speak). - * @param {DeployContractJarsV1Request} [deployContractJarsV1Request] + * @param {DeployContractJarsV1Request} deployContractJarsV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} */ - deployContractJarsV1: async (deployContractJarsV1Request?: DeployContractJarsV1Request, options: AxiosRequestConfig = {}): Promise => { + deployContractJarsV1: async (deployContractJarsV1Request: DeployContractJarsV1Request, options: AxiosRequestConfig = {}): Promise => { + // verify required parameter 'deployContractJarsV1Request' is not null or undefined + assertParamExists('deployContractJarsV1', 'deployContractJarsV1Request', deployContractJarsV1Request) const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/deploy-contract-jars`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -1499,11 +1503,13 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati /** * * @summary Get transactions for monitored state classes. - * @param {GetMonitorTransactionsV1Request} [getMonitorTransactionsV1Request] + * @param {GetMonitorTransactionsV1Request} getMonitorTransactionsV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getMonitorTransactionsV1: async (getMonitorTransactionsV1Request?: GetMonitorTransactionsV1Request, options: AxiosRequestConfig = {}): Promise => { + getMonitorTransactionsV1: async (getMonitorTransactionsV1Request: GetMonitorTransactionsV1Request, options: AxiosRequestConfig = {}): Promise => { + // verify required parameter 'getMonitorTransactionsV1Request' is not null or undefined + assertParamExists('getMonitorTransactionsV1', 'getMonitorTransactionsV1Request', getMonitorTransactionsV1Request) const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/get-monitor-transactions`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -1563,11 +1569,13 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati /** * * @summary Invokes a contract on a Corda ledger (e.g. a flow) - * @param {InvokeContractV1Request} [invokeContractV1Request] + * @param {InvokeContractV1Request} invokeContractV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} */ - invokeContractV1: async (invokeContractV1Request?: InvokeContractV1Request, options: AxiosRequestConfig = {}): Promise => { + invokeContractV1: async (invokeContractV1Request: InvokeContractV1Request, options: AxiosRequestConfig = {}): Promise => { + // verify required parameter 'invokeContractV1Request' is not null or undefined + assertParamExists('invokeContractV1', 'invokeContractV1Request', invokeContractV1Request) const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/invoke-contract`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -1771,11 +1779,13 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati /** * * @summary Start monitoring corda changes (transactions) of given state class - * @param {StartMonitorV1Request} [startMonitorV1Request] + * @param {StartMonitorV1Request} startMonitorV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} */ - startMonitorV1: async (startMonitorV1Request?: StartMonitorV1Request, options: AxiosRequestConfig = {}): Promise => { + startMonitorV1: async (startMonitorV1Request: StartMonitorV1Request, options: AxiosRequestConfig = {}): Promise => { + // verify required parameter 'startMonitorV1Request' is not null or undefined + assertParamExists('startMonitorV1', 'startMonitorV1Request', startMonitorV1Request) const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/start-monitor`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -1805,11 +1815,13 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati /** * * @summary Stop monitoring corda changes (transactions) of given state class - * @param {StopMonitorV1Request} [stopMonitorV1Request] + * @param {StopMonitorV1Request} stopMonitorV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} */ - stopMonitorV1: async (stopMonitorV1Request?: StopMonitorV1Request, options: AxiosRequestConfig = {}): Promise => { + stopMonitorV1: async (stopMonitorV1Request: StopMonitorV1Request, options: AxiosRequestConfig = {}): Promise => { + // verify required parameter 'stopMonitorV1Request' is not null or undefined + assertParamExists('stopMonitorV1', 'stopMonitorV1Request', stopMonitorV1Request) const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/stop-monitor`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -1838,11 +1850,13 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati }, /** * Queryes the vault service for state references based on JVM class names. Custom filters are not supported by this endpoint. - * @param {VaultQueryV1Request} [vaultQueryV1Request] + * @param {VaultQueryV1Request} vaultQueryV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} */ - vaultQueryV1: async (vaultQueryV1Request?: VaultQueryV1Request, options: AxiosRequestConfig = {}): Promise => { + vaultQueryV1: async (vaultQueryV1Request: VaultQueryV1Request, options: AxiosRequestConfig = {}): Promise => { + // verify required parameter 'vaultQueryV1Request' is not null or undefined + assertParamExists('vaultQueryV1', 'vaultQueryV1Request', vaultQueryV1Request) const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/vault-query`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -1882,22 +1896,22 @@ export const DefaultApiFp = function(configuration?: Configuration) { /** * * @summary Clear transactions from internal store so they\'ll not be available by GetMonitorTransactionsV1 anymore. - * @param {ClearMonitorTransactionsV1Request} [clearMonitorTransactionsV1Request] + * @param {ClearMonitorTransactionsV1Request} clearMonitorTransactionsV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async clearMonitorTransactionsV1(clearMonitorTransactionsV1Request?: ClearMonitorTransactionsV1Request, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async clearMonitorTransactionsV1(clearMonitorTransactionsV1Request: ClearMonitorTransactionsV1Request, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.clearMonitorTransactionsV1(clearMonitorTransactionsV1Request, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, /** * * @summary Deploys a set of jar files (Cordapps, e.g. the contracts in Corda speak). - * @param {DeployContractJarsV1Request} [deployContractJarsV1Request] + * @param {DeployContractJarsV1Request} deployContractJarsV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async deployContractJarsV1(deployContractJarsV1Request?: DeployContractJarsV1Request, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async deployContractJarsV1(deployContractJarsV1Request: DeployContractJarsV1Request, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.deployContractJarsV1(deployContractJarsV1Request, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -1925,11 +1939,11 @@ export const DefaultApiFp = function(configuration?: Configuration) { /** * * @summary Get transactions for monitored state classes. - * @param {GetMonitorTransactionsV1Request} [getMonitorTransactionsV1Request] + * @param {GetMonitorTransactionsV1Request} getMonitorTransactionsV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getMonitorTransactionsV1(getMonitorTransactionsV1Request?: GetMonitorTransactionsV1Request, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async getMonitorTransactionsV1(getMonitorTransactionsV1Request: GetMonitorTransactionsV1Request, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.getMonitorTransactionsV1(getMonitorTransactionsV1Request, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -1946,11 +1960,11 @@ export const DefaultApiFp = function(configuration?: Configuration) { /** * * @summary Invokes a contract on a Corda ledger (e.g. a flow) - * @param {InvokeContractV1Request} [invokeContractV1Request] + * @param {InvokeContractV1Request} invokeContractV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async invokeContractV1(invokeContractV1Request?: InvokeContractV1Request, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async invokeContractV1(invokeContractV1Request: InvokeContractV1Request, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.invokeContractV1(invokeContractV1Request, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -2010,32 +2024,32 @@ export const DefaultApiFp = function(configuration?: Configuration) { /** * * @summary Start monitoring corda changes (transactions) of given state class - * @param {StartMonitorV1Request} [startMonitorV1Request] + * @param {StartMonitorV1Request} startMonitorV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async startMonitorV1(startMonitorV1Request?: StartMonitorV1Request, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async startMonitorV1(startMonitorV1Request: StartMonitorV1Request, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.startMonitorV1(startMonitorV1Request, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, /** * * @summary Stop monitoring corda changes (transactions) of given state class - * @param {StopMonitorV1Request} [stopMonitorV1Request] + * @param {StopMonitorV1Request} stopMonitorV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async stopMonitorV1(stopMonitorV1Request?: StopMonitorV1Request, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async stopMonitorV1(stopMonitorV1Request: StopMonitorV1Request, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.stopMonitorV1(stopMonitorV1Request, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, /** * Queryes the vault service for state references based on JVM class names. Custom filters are not supported by this endpoint. - * @param {VaultQueryV1Request} [vaultQueryV1Request] + * @param {VaultQueryV1Request} vaultQueryV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async vaultQueryV1(vaultQueryV1Request?: VaultQueryV1Request, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async vaultQueryV1(vaultQueryV1Request: VaultQueryV1Request, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.vaultQueryV1(vaultQueryV1Request, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -2052,21 +2066,21 @@ export const DefaultApiFactory = function (configuration?: Configuration, basePa /** * * @summary Clear transactions from internal store so they\'ll not be available by GetMonitorTransactionsV1 anymore. - * @param {ClearMonitorTransactionsV1Request} [clearMonitorTransactionsV1Request] + * @param {ClearMonitorTransactionsV1Request} clearMonitorTransactionsV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} */ - clearMonitorTransactionsV1(clearMonitorTransactionsV1Request?: ClearMonitorTransactionsV1Request, options?: any): AxiosPromise { + clearMonitorTransactionsV1(clearMonitorTransactionsV1Request: ClearMonitorTransactionsV1Request, options?: any): AxiosPromise { return localVarFp.clearMonitorTransactionsV1(clearMonitorTransactionsV1Request, options).then((request) => request(axios, basePath)); }, /** * * @summary Deploys a set of jar files (Cordapps, e.g. the contracts in Corda speak). - * @param {DeployContractJarsV1Request} [deployContractJarsV1Request] + * @param {DeployContractJarsV1Request} deployContractJarsV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} */ - deployContractJarsV1(deployContractJarsV1Request?: DeployContractJarsV1Request, options?: any): AxiosPromise { + deployContractJarsV1(deployContractJarsV1Request: DeployContractJarsV1Request, options?: any): AxiosPromise { return localVarFp.deployContractJarsV1(deployContractJarsV1Request, options).then((request) => request(axios, basePath)); }, /** @@ -2091,11 +2105,11 @@ export const DefaultApiFactory = function (configuration?: Configuration, basePa /** * * @summary Get transactions for monitored state classes. - * @param {GetMonitorTransactionsV1Request} [getMonitorTransactionsV1Request] + * @param {GetMonitorTransactionsV1Request} getMonitorTransactionsV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getMonitorTransactionsV1(getMonitorTransactionsV1Request?: GetMonitorTransactionsV1Request, options?: any): AxiosPromise { + getMonitorTransactionsV1(getMonitorTransactionsV1Request: GetMonitorTransactionsV1Request, options?: any): AxiosPromise { return localVarFp.getMonitorTransactionsV1(getMonitorTransactionsV1Request, options).then((request) => request(axios, basePath)); }, /** @@ -2110,11 +2124,11 @@ export const DefaultApiFactory = function (configuration?: Configuration, basePa /** * * @summary Invokes a contract on a Corda ledger (e.g. a flow) - * @param {InvokeContractV1Request} [invokeContractV1Request] + * @param {InvokeContractV1Request} invokeContractV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} */ - invokeContractV1(invokeContractV1Request?: InvokeContractV1Request, options?: any): AxiosPromise { + invokeContractV1(invokeContractV1Request: InvokeContractV1Request, options?: any): AxiosPromise { return localVarFp.invokeContractV1(invokeContractV1Request, options).then((request) => request(axios, basePath)); }, /** @@ -2168,30 +2182,30 @@ export const DefaultApiFactory = function (configuration?: Configuration, basePa /** * * @summary Start monitoring corda changes (transactions) of given state class - * @param {StartMonitorV1Request} [startMonitorV1Request] + * @param {StartMonitorV1Request} startMonitorV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} */ - startMonitorV1(startMonitorV1Request?: StartMonitorV1Request, options?: any): AxiosPromise { + startMonitorV1(startMonitorV1Request: StartMonitorV1Request, options?: any): AxiosPromise { return localVarFp.startMonitorV1(startMonitorV1Request, options).then((request) => request(axios, basePath)); }, /** * * @summary Stop monitoring corda changes (transactions) of given state class - * @param {StopMonitorV1Request} [stopMonitorV1Request] + * @param {StopMonitorV1Request} stopMonitorV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} */ - stopMonitorV1(stopMonitorV1Request?: StopMonitorV1Request, options?: any): AxiosPromise { + stopMonitorV1(stopMonitorV1Request: StopMonitorV1Request, options?: any): AxiosPromise { return localVarFp.stopMonitorV1(stopMonitorV1Request, options).then((request) => request(axios, basePath)); }, /** * Queryes the vault service for state references based on JVM class names. Custom filters are not supported by this endpoint. - * @param {VaultQueryV1Request} [vaultQueryV1Request] + * @param {VaultQueryV1Request} vaultQueryV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} */ - vaultQueryV1(vaultQueryV1Request?: VaultQueryV1Request, options?: any): AxiosPromise { + vaultQueryV1(vaultQueryV1Request: VaultQueryV1Request, options?: any): AxiosPromise { return localVarFp.vaultQueryV1(vaultQueryV1Request, options).then((request) => request(axios, basePath)); }, }; @@ -2207,24 +2221,24 @@ export class DefaultApi extends BaseAPI { /** * * @summary Clear transactions from internal store so they\'ll not be available by GetMonitorTransactionsV1 anymore. - * @param {ClearMonitorTransactionsV1Request} [clearMonitorTransactionsV1Request] + * @param {ClearMonitorTransactionsV1Request} clearMonitorTransactionsV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DefaultApi */ - public clearMonitorTransactionsV1(clearMonitorTransactionsV1Request?: ClearMonitorTransactionsV1Request, options?: AxiosRequestConfig) { + public clearMonitorTransactionsV1(clearMonitorTransactionsV1Request: ClearMonitorTransactionsV1Request, options?: AxiosRequestConfig) { return DefaultApiFp(this.configuration).clearMonitorTransactionsV1(clearMonitorTransactionsV1Request, options).then((request) => request(this.axios, this.basePath)); } /** * * @summary Deploys a set of jar files (Cordapps, e.g. the contracts in Corda speak). - * @param {DeployContractJarsV1Request} [deployContractJarsV1Request] + * @param {DeployContractJarsV1Request} deployContractJarsV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DefaultApi */ - public deployContractJarsV1(deployContractJarsV1Request?: DeployContractJarsV1Request, options?: AxiosRequestConfig) { + public deployContractJarsV1(deployContractJarsV1Request: DeployContractJarsV1Request, options?: AxiosRequestConfig) { return DefaultApiFp(this.configuration).deployContractJarsV1(deployContractJarsV1Request, options).then((request) => request(this.axios, this.basePath)); } @@ -2254,12 +2268,12 @@ export class DefaultApi extends BaseAPI { /** * * @summary Get transactions for monitored state classes. - * @param {GetMonitorTransactionsV1Request} [getMonitorTransactionsV1Request] + * @param {GetMonitorTransactionsV1Request} getMonitorTransactionsV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DefaultApi */ - public getMonitorTransactionsV1(getMonitorTransactionsV1Request?: GetMonitorTransactionsV1Request, options?: AxiosRequestConfig) { + public getMonitorTransactionsV1(getMonitorTransactionsV1Request: GetMonitorTransactionsV1Request, options?: AxiosRequestConfig) { return DefaultApiFp(this.configuration).getMonitorTransactionsV1(getMonitorTransactionsV1Request, options).then((request) => request(this.axios, this.basePath)); } @@ -2277,12 +2291,12 @@ export class DefaultApi extends BaseAPI { /** * * @summary Invokes a contract on a Corda ledger (e.g. a flow) - * @param {InvokeContractV1Request} [invokeContractV1Request] + * @param {InvokeContractV1Request} invokeContractV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DefaultApi */ - public invokeContractV1(invokeContractV1Request?: InvokeContractV1Request, options?: AxiosRequestConfig) { + public invokeContractV1(invokeContractV1Request: InvokeContractV1Request, options?: AxiosRequestConfig) { return DefaultApiFp(this.configuration).invokeContractV1(invokeContractV1Request, options).then((request) => request(this.axios, this.basePath)); } @@ -2347,35 +2361,35 @@ export class DefaultApi extends BaseAPI { /** * * @summary Start monitoring corda changes (transactions) of given state class - * @param {StartMonitorV1Request} [startMonitorV1Request] + * @param {StartMonitorV1Request} startMonitorV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DefaultApi */ - public startMonitorV1(startMonitorV1Request?: StartMonitorV1Request, options?: AxiosRequestConfig) { + public startMonitorV1(startMonitorV1Request: StartMonitorV1Request, options?: AxiosRequestConfig) { return DefaultApiFp(this.configuration).startMonitorV1(startMonitorV1Request, options).then((request) => request(this.axios, this.basePath)); } /** * * @summary Stop monitoring corda changes (transactions) of given state class - * @param {StopMonitorV1Request} [stopMonitorV1Request] + * @param {StopMonitorV1Request} stopMonitorV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DefaultApi */ - public stopMonitorV1(stopMonitorV1Request?: StopMonitorV1Request, options?: AxiosRequestConfig) { + public stopMonitorV1(stopMonitorV1Request: StopMonitorV1Request, options?: AxiosRequestConfig) { return DefaultApiFp(this.configuration).stopMonitorV1(stopMonitorV1Request, options).then((request) => request(this.axios, this.basePath)); } /** * Queryes the vault service for state references based on JVM class names. Custom filters are not supported by this endpoint. - * @param {VaultQueryV1Request} [vaultQueryV1Request] + * @param {VaultQueryV1Request} vaultQueryV1Request * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DefaultApi */ - public vaultQueryV1(vaultQueryV1Request?: VaultQueryV1Request, options?: AxiosRequestConfig) { + public vaultQueryV1(vaultQueryV1Request: VaultQueryV1Request, options?: AxiosRequestConfig) { return DefaultApiFp(this.configuration).vaultQueryV1(vaultQueryV1Request, options).then((request) => request(this.axios, this.basePath)); } } diff --git a/packages/cactus-plugin-ledger-connector-corda/src/main/typescript/index.web.ts b/packages/cactus-plugin-ledger-connector-corda/src/main/typescript/index.web.ts index 4c10a937d04..d926319e63b 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/main/typescript/index.web.ts +++ b/packages/cactus-plugin-ledger-connector-corda/src/main/typescript/index.web.ts @@ -1,4 +1,44 @@ -export * from "./generated/openapi/typescript-axios/index"; +export { ClearMonitorTransactionsV1Request } from "./generated/openapi/typescript-axios/index"; +export { ClearMonitorTransactionsV1Response } from "./generated/openapi/typescript-axios/index"; +export { Configuration } from "./generated/openapi/typescript-axios/index"; +export { ConfigurationParameters } from "./generated/openapi/typescript-axios/index"; +export { CordaNodeSshCredentials } from "./generated/openapi/typescript-axios/index"; +export { CordaRpcCredentials } from "./generated/openapi/typescript-axios/index"; +export { CordaX500Name } from "./generated/openapi/typescript-axios/index"; +export { CordappDeploymentConfig } from "./generated/openapi/typescript-axios/index"; +export { CordappInfo } from "./generated/openapi/typescript-axios/index"; +export { DefaultApi } from "./generated/openapi/typescript-axios/index"; +export { DefaultApiAxiosParamCreator } from "./generated/openapi/typescript-axios/index"; +export { DefaultApiFactory } from "./generated/openapi/typescript-axios/index"; +export { DefaultApiFp } from "./generated/openapi/typescript-axios/index"; +export { DeployContractJarsBadRequestV1Response } from "./generated/openapi/typescript-axios/index"; +export { DeployContractJarsSuccessV1Response } from "./generated/openapi/typescript-axios/index"; +export { DeployContractJarsV1Request } from "./generated/openapi/typescript-axios/index"; +export { DiagnoseNodeV1Request } from "./generated/openapi/typescript-axios/index"; +export { DiagnoseNodeV1Response } from "./generated/openapi/typescript-axios/index"; +export { FlowInvocationType } from "./generated/openapi/typescript-axios/index"; +export { GetMonitorTransactionsV1Request } from "./generated/openapi/typescript-axios/index"; +export { GetMonitorTransactionsV1Response } from "./generated/openapi/typescript-axios/index"; +export { GetMonitorTransactionsV1ResponseTxInner } from "./generated/openapi/typescript-axios/index"; +export { InvokeContractV1Request } from "./generated/openapi/typescript-axios/index"; +export { InvokeContractV1Response } from "./generated/openapi/typescript-axios/index"; +export { JarFile } from "./generated/openapi/typescript-axios/index"; +export { JvmObject } from "./generated/openapi/typescript-axios/index"; +export { JvmType } from "./generated/openapi/typescript-axios/index"; +export { JvmTypeKind } from "./generated/openapi/typescript-axios/index"; +export { ListFlowsV1Request } from "./generated/openapi/typescript-axios/index"; +export { ListFlowsV1Response } from "./generated/openapi/typescript-axios/index"; +export { NetworkHostAndPort } from "./generated/openapi/typescript-axios/index"; +export { NodeDiagnosticInfo } from "./generated/openapi/typescript-axios/index"; +export { NodeInfo } from "./generated/openapi/typescript-axios/index"; +export { Party } from "./generated/openapi/typescript-axios/index"; +export { PublicKey } from "./generated/openapi/typescript-axios/index"; +export { SHA256 } from "./generated/openapi/typescript-axios/index"; +export { StartMonitorV1Request } from "./generated/openapi/typescript-axios/index"; +export { StartMonitorV1Response } from "./generated/openapi/typescript-axios/index"; +export { StopMonitorV1Request } from "./generated/openapi/typescript-axios/index"; +export { StopMonitorV1Response } from "./generated/openapi/typescript-axios/index"; +export { X500Principal } from "./generated/openapi/typescript-axios/index"; export { createJvmBoolean } from "./jvm/serde/factory/create-jvm-boolean"; diff --git a/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/corda-v4-deploy-and-invoke-contract.test.ts b/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/corda-v4-deploy-and-invoke-contract.test.ts new file mode 100644 index 00000000000..000fc50cf0f --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/corda-v4-deploy-and-invoke-contract.test.ts @@ -0,0 +1,621 @@ +import "jest-extended"; + +import { BAD_REQUEST, OK } from "http-errors-enhanced-cjs"; +import { v4 as internalIpV4 } from "internal-ip"; + +import { Configuration } from "@hyperledger/cactus-core-api"; +import { LoggerProvider, LogLevelDesc } from "@hyperledger/cactus-common"; +import { + buildImageConnectorCordaServer, + buildImageCordaAllInOneV412, + Containers, + CordaTestLedger, + pruneDockerAllIfGithubAction, + SAMPLE_CORDAPP_DATA, +} from "@hyperledger/cactus-test-tooling"; +import { + SampleCordappEnum, + CordaConnectorContainer, +} from "@hyperledger/cactus-test-tooling"; + +import { + CordappDeploymentConfig, + DefaultApi as CordaApi, + DeployContractJarsV1Request, + FlowInvocationType, + InvokeContractV1Request, + DiagnoseNodeV1Request, + ListFlowsV1Request, + JvmTypeKind, + CordaRpcCredentials, +} from "../../../main/typescript/generated/openapi/typescript-axios/index"; + +import { createJvmBoolean } from "../../../main/typescript/jvm/serde/factory/create-jvm-boolean"; +import { createJvmLong } from "../../../main/typescript/jvm/serde/factory/create-jvm-long"; +import { createJvmCordaIdentityParty } from "../../../main/typescript/jvm/serde/factory/create-jvm-corda-identity-party"; +import { + createJvmCordaAmount, + createJvmCordaUniqueIdentifier, +} from "../../../main/typescript"; + +describe("Corda V4 Connector", () => { + const logLevel: LogLevelDesc = "INFO"; + const logLevelJvmApp: LogLevelDesc = "INFO"; + const logLevelJvmRoot: LogLevelDesc = "WARN"; + + const cInvalidParams = "sending invalid parameters"; + const fDiagnose = "diagnoseNodeV1"; + const fDeploy = "deployContractJarsV1"; + const fInvoke = "invokeContractV1"; + const fFlows = "listFlowsV1"; + const cWithoutParams = "not sending all required parameters"; + + const REG_EXP_UUID = new RegExp( + "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}", + ); + + const log = LoggerProvider.getOrCreate({ + label: "corda-v4-deploy-and-invoke-contract.test.ts", + level: logLevel, + }); + + let apiClient: CordaApi; + let ledger: CordaTestLedger; + let connector: CordaConnectorContainer; + let testAppearsSuccessful = false; + let partyARpcPort: number; + let partyBRpcPort: number; + let publicSshPort: number; + let lanIp: string; + let rpcCredentialsA: CordaRpcCredentials; + let rpcCredentialsB: CordaRpcCredentials; + + afterAll(async () => { + if (testAppearsSuccessful !== true) { + log.error("Test appears to have failed. Logging container diagnostics"); + await Containers.logDiagnostics({ logLevel }); + } + }); + + beforeAll(async () => { + await pruneDockerAllIfGithubAction({ logLevel }); + }); + + beforeAll(async () => { + const imgLedger = await buildImageCordaAllInOneV412({ logLevel }); + const imgConnectorJvm = await buildImageConnectorCordaServer({ + logLevel, + }); + + ledger = new CordaTestLedger({ + imageName: imgLedger.imageName, + imageVersion: imgLedger.imageVersion, + logLevel, + sshPort: 2222, + rpcPortNotary: 10003, + rpcPortA: 10006, + rpcPortB: 10009, + }); + expect(ledger).toBeTruthy(); + + const ledgerContainer = await ledger.start(true); + expect(ledgerContainer).toBeTruthy(); + + await ledger.logDebugPorts(); + partyARpcPort = await ledger.getRpcAPublicPort(); + partyBRpcPort = await ledger.getRpcBPublicPort(); + log.info("Ledger container partyARpcPort: %d", partyARpcPort); + log.info("Ledger container partyBRpcPort: %d", partyBRpcPort); + + publicSshPort = await ledger.getSSHPublicPort(); + log.info("Ledger container publicSshPort: %d", publicSshPort); + + const internalIpOrUndefined = await internalIpV4(); + expect(internalIpOrUndefined).toBeTruthy(); + + lanIp = internalIpOrUndefined as string; + log.info(`Internal/LAN IP (based on default gateway): ${lanIp}`); + + rpcCredentialsA = { + hostname: lanIp, + port: partyARpcPort, + username: "user1", + password: "test", + }; + + rpcCredentialsB = { + hostname: lanIp, + port: partyBRpcPort, + username: "user1", + password: "test", + }; + + const springAppConfig = { + logging: { + level: { + root: logLevelJvmRoot, + "org.hyperledger.cactus": logLevelJvmApp, + }, + }, + cactus: { + corda: { + node: { host: lanIp }, + // TODO: parse the gradle build files to extract the credentials? + rpc: { port: partyARpcPort, username: "user1", password: "test" }, + }, + }, + }; + const springApplicationJson = JSON.stringify(springAppConfig); + const envVarSpringAppJson = `SPRING_APPLICATION_JSON=${springApplicationJson}`; + log.debug("Spring App Config Env Var: ", envVarSpringAppJson); + + connector = new CordaConnectorContainer({ + logLevel, + imageName: imgConnectorJvm.imageName, + imageVersion: imgConnectorJvm.imageVersion, + envVars: [envVarSpringAppJson], + }); + // Set to true if you are testing an image that you've built locally and have not + // yet uploaded to the container registry where it would be publicly available. + // Do not forget to set it back to `false` afterwards! + const skipContainerImagePull = true; + expect(CordaConnectorContainer).toBeTruthy(); + + const connectorContainer = await connector.start(skipContainerImagePull); + expect(connectorContainer).toBeTruthy(); + + await connector.logDebugPorts(); + const apiUrl = await connector.getApiLocalhostUrl(); + const config = new Configuration({ basePath: apiUrl }); + apiClient = new CordaApi(config); + }); + + afterAll(async () => { + if (!ledger) { + log.info("Ledger container falsy, skipping stop & destroy."); + return; + } + try { + await ledger.stop(); + } finally { + await ledger.destroy(); + } + await pruneDockerAllIfGithubAction({ logLevel }); + }); + + afterAll(async () => { + if (!connector) { + log.info("Connector container falsy, skipping stop & destroy."); + return; + } + try { + await connector.stop(); + } finally { + await connector.destroy(); + } + }); + + it("Runs listFlowsV1()", async () => { + const flowsRes = await apiClient.listFlowsV1(); + expect(flowsRes.status).toEqual(200); + expect(flowsRes.data).toBeTruthy(); + expect(flowsRes.data.flowNames).toBeTruthy(); + log.debug(`apiClient.listFlowsV1() => ${JSON.stringify(flowsRes.data)}`); + }); + + it("Runs diagnoseNodeV1()", async () => { + const diagRes = await apiClient.diagnoseNodeV1(); + expect(diagRes.status).toEqual(200); + expect(diagRes.data).toBeTruthy(); + expect(diagRes.data.nodeDiagnosticInfo).toBeTruthy(); + + const ndi = diagRes.data.nodeDiagnosticInfo; + expect(ndi.cordapps).toBeTruthy(); + expect(ndi.cordapps).toBeArray(); + expect(ndi.cordapps).not.toBeEmpty(); + expect(Array.isArray(ndi.cordapps)).toBeTrue(); + expect(ndi.cordapps.length > 0).toBeTrue(); + + expect(ndi.vendor).toBeTruthy(); + expect(ndi.version).toBeTruthy(); + expect(ndi.revision).toBeTruthy(); + expect(ndi.platformVersion).toBeTruthy(); + + log.debug(`apiClient.diagnoseNodeV1() => ${JSON.stringify(diagRes.data)}`); + }); + + it(`Runs deployContractJarsV1() - ${SampleCordappEnum.ADVANCED_NEGOTIATION}`, async () => { + const cordappDeploymentConfigs: CordappDeploymentConfig[] = []; + + cordappDeploymentConfigs.push({ + cordappDir: + SAMPLE_CORDAPP_DATA[SampleCordappEnum.ADVANCED_NEGOTIATION] + .cordappDirPartyA, + cordaNodeStartCmd: "supervisorctl start corda-a", + + cordaJarPath: SAMPLE_CORDAPP_DATA[ + SampleCordappEnum.ADVANCED_NEGOTIATION + ].cordappDirPartyA.replace("cordapps", "corda.jar"), + + nodeBaseDirPath: SAMPLE_CORDAPP_DATA[ + SampleCordappEnum.ADVANCED_NEGOTIATION + ].cordappDirPartyA.replace("cordapps", ""), + + rpcCredentials: rpcCredentialsA, + + sshCredentials: { + hostKeyEntry: "not-used-right-now-so-this-does-not-matter... ;-(", + hostname: lanIp, + password: "root", + port: publicSshPort, + username: "root", + }, + }); + + cordappDeploymentConfigs.push({ + cordappDir: + SAMPLE_CORDAPP_DATA[SampleCordappEnum.ADVANCED_NEGOTIATION] + .cordappDirPartyB, + cordaNodeStartCmd: "supervisorctl start corda-b", + + cordaJarPath: SAMPLE_CORDAPP_DATA[ + SampleCordappEnum.ADVANCED_NEGOTIATION + ].cordappDirPartyB.replace("cordapps", "corda.jar"), + + nodeBaseDirPath: SAMPLE_CORDAPP_DATA[ + SampleCordappEnum.ADVANCED_NEGOTIATION + ].cordappDirPartyB.replace("cordapps", ""), + + rpcCredentials: rpcCredentialsB, + + sshCredentials: { + hostKeyEntry: "not-used-right-now-so-this-does-not-matter... ;-(", + hostname: lanIp, + password: "root", + port: publicSshPort, + username: "root", + }, + }); + + const jarFiles = await ledger.pullCordappJars( + SampleCordappEnum.ADVANCED_NEGOTIATION, + ); + + await ledger.cleanCordapp(SampleCordappEnum.ADVANCED_NEGOTIATION); + + const req: DeployContractJarsV1Request = { + jarFiles, + cordappDeploymentConfigs, + }; + const res = await apiClient.deployContractJarsV1(req); + expect(res).toBeTruthy(); + expect(res.status).toEqual(200); + expect(res.data).toBeTruthy(); + expect(res.data.deployedJarFiles).toBeTruthy(); + expect(res.data.deployedJarFiles.length).toEqual(jarFiles.length); + }); + + it(`Validates Requests: - ${fDeploy} - ${cWithoutParams}`, async () => { + const req = { + cordappDeploymentConfigs: [], + } as unknown as DeployContractJarsV1Request; + const contractDeployment = apiClient.deployContractJarsV1(req); + await expect(contractDeployment).rejects.toMatchObject({ + response: { data: { status: BAD_REQUEST } }, + }); + }); + + it(`Validates Requests: - ${fDiagnose} - ${cInvalidParams}`, async () => { + const req = { fake: 4 } as unknown as DiagnoseNodeV1Request; + const diagnoseNodeRequest = apiClient.diagnoseNodeV1(req); + + await expect(diagnoseNodeRequest).rejects.toMatchObject({ + response: { data: { status: BAD_REQUEST } }, + }); + }); + + it(`Validates Requests: - ${fInvoke} - ${cWithoutParams}`, async () => { + const req = { + flowFullClassName: "net.corda.samples.obligation.flows.IOUIssueFlow", + flowInvocationType: FlowInvocationType.TrackedFlowDynamic, + timeoutMs: 60000, + } as InvokeContractV1Request; + const contractInvocation = apiClient.invokeContractV1(req); + await expect(contractInvocation).rejects.toMatchObject({ + response: { + data: { + status: BAD_REQUEST, + }, + }, + }); + }); + + it(`Validates Requests: - ${fDeploy} - ${cInvalidParams} - rpcCredentials`, async () => { + const req = { + jarFiles: [], + cordappDeploymentConfigs: [ + { + sshCredentials: { + hostKeyEntry: "fake", + username: "fake", + password: "fake", + hostname: "localhost", + port: -1, + }, + // omitting the rpcCredentials property + cordaNodeStartCmd: null as unknown as string, + cordappDir: "/does/not/exist/diretory", + cordaJarPath: "/does/not/exist/", + nodeBaseDirPath: "/does/not/exist/", + } as CordappDeploymentConfig, + ], + fake: 4, + }; + const contractDeployment = apiClient.deployContractJarsV1(req); + await expect(contractDeployment).rejects.toMatchObject({ + response: { data: { status: BAD_REQUEST } }, + }); + }); + + it(`Validates Requests: - ${fDeploy} - ${cInvalidParams} - sshCredentials`, async () => { + const req = { + jarFiles: [], + cordappDeploymentConfigs: [ + { + // omitting the sshCredentials property + rpcCredentials: { + hostname: "-", + port: -1, + username: "-", + password: "-", + }, + cordaNodeStartCmd: null as unknown as string, + cordappDir: "/does/not/exist/diretory", + cordaJarPath: "/does/not/exist/", + nodeBaseDirPath: "/does/not/exist/", + } as CordappDeploymentConfig, + ], + fake: 4, + }; + const contractDeployment = apiClient.deployContractJarsV1(req); + await expect(contractDeployment).rejects.toMatchObject({ + response: { data: { status: BAD_REQUEST } }, + }); + }); + + it(`Validates Requests: - ${fFlows} - ${cInvalidParams}`, async () => { + const req = { fake: 4 } as ListFlowsV1Request; + const flowListRequest = apiClient.listFlowsV1(req); + await expect(flowListRequest).rejects.toMatchObject({ + response: { data: { status: BAD_REQUEST } }, + }); + }); + + it(`Validates Requests: - ${fInvoke} - ${cInvalidParams}`, async () => { + const req: InvokeContractV1Request = { + flowFullClassName: "net.corda.samples.obligation.flows.IOUIssueFlow", + flowInvocationType: FlowInvocationType.TrackedFlowDynamic, + params: [{}], + timeoutMs: 60000, + fake: 4, + } as unknown as InvokeContractV1Request; + + const contractInvocation = apiClient.invokeContractV1(req); + await expect(contractInvocation).rejects.toMatchObject({ + response: { data: { status: BAD_REQUEST } }, + }); + }); + + it("Runs invokeContractV1() - net.corda.samples.negotiation.flows.ProposalFlow$Initiator", async () => { + const networkMapRes = await apiClient.networkMapV1({}); + + const partyB = networkMapRes.data.find((it) => + it.legalIdentities.some((it2) => it2.name.organisation === "PartyB"), + ); + + if (process.env.VERBOSE === "true") { + const networkMapJson = JSON.stringify(networkMapRes.data, null, 4); + console.log("Corda Network Map Snapshot JSON:", networkMapJson); + } + + if (!partyB) { + throw new Error("PartyB was falsy. Cannot continue the test."); + } + + if (!partyB.legalIdentities[0]) { + throw new Error( + "PartyB had no legalIdentities. Cannot continue the test.", + ); + } + + const req: InvokeContractV1Request = { + flowFullClassName: + "net.corda.samples.negotiation.flows.ProposalFlow$Initiator", + flowInvocationType: FlowInvocationType.TrackedFlowDynamic, + params: [ + createJvmBoolean(true), + createJvmLong(42), + createJvmCordaIdentityParty({ party: partyB.legalIdentities[0] }), + ], + timeoutMs: 60000, + }; + + const contractInvocation = apiClient.invokeContractV1(req); + await expect(contractInvocation).resolves.toMatchObject({ + status: OK, + data: { + success: true, + callOutput: expect.toBeString(), + flowId: expect.stringMatching(REG_EXP_UUID), + progress: expect.toBeArray(), + }, + }); + }); + + it(`Runs deployContractJarsV1() - ${SampleCordappEnum.ADVANCED_OBLIGATION}`, async () => { + // Using the ADVANCED_NEGOTIATION sample app data here because that's the + // one that has the node up and running within the ledger container so + // even though we are deploying an obligation cordapp, we need to use the + // deployment config associated with the negotiation one. + const sampleAppNegotiation = SampleCordappEnum.ADVANCED_NEGOTIATION; + const sampleAppObligation = SampleCordappEnum.ADVANCED_OBLIGATION; + const sampleAppData = SAMPLE_CORDAPP_DATA[sampleAppNegotiation]; + + const cordappDeploymentConfigs: CordappDeploymentConfig[] = []; + + cordappDeploymentConfigs.push({ + cordappDir: sampleAppData.cordappDirPartyA, + cordaNodeStartCmd: "supervisorctl start corda-a", + + cordaJarPath: sampleAppData.cordappDirPartyA.replace( + "cordapps", + "corda.jar", + ), + + nodeBaseDirPath: sampleAppData.cordappDirPartyA.replace("cordapps", ""), + + rpcCredentials: rpcCredentialsA, + + sshCredentials: { + hostKeyEntry: "FIXME_this_does_not_yet_get_verified", + hostname: lanIp, + password: "root", + port: publicSshPort, + username: "root", + }, + }); + + cordappDeploymentConfigs.push({ + cordappDir: sampleAppData.cordappDirPartyB, + cordaNodeStartCmd: "supervisorctl start corda-b", + + cordaJarPath: sampleAppData.cordappDirPartyB.replace( + "cordapps", + "corda.jar", + ), + + nodeBaseDirPath: sampleAppData.cordappDirPartyB.replace("cordapps", ""), + + rpcCredentials: rpcCredentialsB, + + sshCredentials: { + hostKeyEntry: "FIXME_this_does_not_yet_get_verified", + hostname: lanIp, + password: "root", + port: publicSshPort, + username: "root", + }, + }); + + const jarFiles = await ledger.pullCordappJars(sampleAppObligation); + + const req: DeployContractJarsV1Request = { + jarFiles, + cordappDeploymentConfigs, + }; + const res = await apiClient.deployContractJarsV1(req); + expect(res).toBeTruthy(); + expect(res.status).toEqual(200); + expect(res.data).toBeTruthy(); + expect(res.data.deployedJarFiles).toBeTruthy(); + expect(res.data.deployedJarFiles.length).toEqual(jarFiles.length); + }); + + /** + * FIXME: Need to fix this test case. For now it hangs with the ledger logging the mesage below. + * If you list the flows available, it shows that the flows we are invoking in this test case is + * available on the corda node so it is not yet know what is the actual problem since the .jar files + * are installed by the previous test case but it claims that they are not there... + * + * W 00:15:38 190 SingleThreadedStateMachineManager. - Unable to initiate flow from O=PartyA, L=London, C=GB + * (appName=ADVANCED_OBLIGATION_workflows-1.0 flowVersion=1), sending to the flow hospital + * + * net.corda.node.services.statemachine.SessionRejectException$UnknownClass: Don't know net.corda.samples.obligation.flows.IOUIssueFlow + * at net.corda.node.services.statemachine.SingleThreadedStateMachineManager.getInitiatedFlowFactory(SingleThreadedStateMachineManager.kt:899) ~[corda-node-4.12-SNAPSHOT.jar:?] + * at net.corda.node.services.statemachine.SingleThreadedStateMachineManager.onSessionInit(SingleThreadedStateMachineManager.kt:863) ~[corda-node-4.12-SNAPSHOT.jar:?] + * at net.corda.node.services.statemachine.SingleThreadedStateMachineManager.onSessionMessage(SingleThreadedStateMachineManager.kt:817) ~[corda-node-4.12-SNAPSHOT.jar:?] + * at net.corda.node.services.statemachine.SingleThreadedStateMachineManager.deliverExternalEvent(SingleThreadedStateMachineManager.kt:786) ~[corda-node-4.12-SNAPSHOT.jar:?] + * at net.corda.node.services.statemachine.SingleThreadedStateMachineManager$start$7$1.invoke$lambda$0(SingleThreadedStateMachineManager.kt:236) ~[corda-node-4.12-SNAPSHOT.jar:?] + * at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) ~[?:?] + * at java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[?:?] + * at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) ~[?:?] + * at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[?:?] + * at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[?:?] + * at net.corda.node.utilities.AffinityExecutor$ServiceAffinityExecutor$1$thread$1.run(AffinityExecutor.kt:63) ~[corda-node-4.12-SNAPSHOT.jar:?] + * + * W 00:15:38 190 StaffedFlowHospital. - O=PartyA, L=London, C=GB has sent a flow request for an unknown flow net.corda.samples.obligation.flows.IOUIssueFlow. Install the missing CorDapp this flow belongs to and restart. + * W 00:15:38 190 StaffedFlowHospital. - If you know it's safe to ignore this flow request then it can be deleted permanently using the killFlow RPC and the UUID [a0078a26-15ae-4328-9cbe-afe321194177] (from the node shell you can run 'flow kill [a0078a26-15ae-4328-9cbe-afe321194177]'). + * BE VERY CAUTIOUS OF THIS SECOND APPROACH AS THE REQUEST MAY CONTAIN A NOTARISED TRANSACTION THAT NEEDS TO BE RECORDED IN YOUR VAULT. + * + * W 00:16:32 110 StaffedFlowHospital. - There are 1 erroneous session initiations kept for overnight observation. Erroneous session initiation ids: [a0078a26-15ae-4328-9cbe-afe321194177] + * + */ + it("Runs invokeContractV1() - net.corda.samples.obligation.flows.IOUIssueFlow", async () => { + const { data: netMap } = await apiClient.networkMapV1(); + const pNameA = "PartyA"; + const pNameB = "PartyB"; + + const partyA = netMap.find((it) => + it.legalIdentities.some((it2) => it2.name.organisation === pNameA), + ); + if (!partyA) { + throw new TypeError(`No Party with name ${pNameA} found in Network Map`); + } + + const partyB = netMap.find((it) => + it.legalIdentities.some((it2) => it2.name.organisation === pNameB), + ); + if (!partyB) { + throw new TypeError(`No Party with name ${pNameB} found in Network Map`); + } + + const flowsRes = await apiClient.listFlowsV1(); + log.debug("flowRes.data", flowsRes.data); + + const req: InvokeContractV1Request = { + flowFullClassName: "net.corda.samples.obligation.flows.IOUIssueFlow", + flowInvocationType: FlowInvocationType.TrackedFlowDynamic, + params: [ + { + jvmTypeKind: JvmTypeKind.Reference, + jvmType: { + fqClassName: "net.corda.samples.obligation.states.IOUState", + }, + + jvmCtorArgs: [ + createJvmCordaAmount({ amount: 42, currencyCode: "USD" }), + createJvmCordaIdentityParty({ party: partyA.legalIdentities[0] }), + createJvmCordaIdentityParty({ party: partyB.legalIdentities[0] }), + createJvmCordaAmount({ amount: 1, currencyCode: "USD" }), + createJvmCordaUniqueIdentifier({ + uniqueidentifier: "7fc2161e-f8d0-4c86-a596-08326bdafd56", + }), + ], + }, + ], + timeoutMs: 60000, + }; + + const contractInvocation = apiClient.invokeContractV1(req); + + await expect(contractInvocation).resolves.toMatchObject({ + status: OK, + data: { + success: true, + callOutput: { + id: expect.toBeString(), + inputs: expect.toBeArray(), + networkParametersHash: expect.toBeString(), + notary: expect.not.toBeEmpty(), + sigs: expect.toBeArray(), + tx: expect.toBeObject(), + }, + flowId: expect.stringMatching(REG_EXP_UUID), + progress: expect.toBeArray(), + }, + }); + + testAppearsSuccessful = true; + log.debug("The test appears to be successfully finished."); + }); +}); diff --git a/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/flow-database-access-v4.8.test.ts b/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/flow-database-access-v4.8.test.ts index 3c9bfb02675..5b9ce9a5534 100644 --- a/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/flow-database-access-v4.8.test.ts +++ b/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/flow-database-access-v4.8.test.ts @@ -6,6 +6,7 @@ import { CordaTestLedger, pruneDockerAllIfGithubAction, CordaConnectorContainer, + SampleCordappEnum, } from "@hyperledger/cactus-test-tooling"; import { LogLevelDesc } from "@hyperledger/cactus-common"; @@ -21,7 +22,9 @@ import { createJvmString } from "../../../main/typescript/jvm/serde/factory/crea import { createJvmInt } from "../../../main/typescript"; const testCase = "Tests are passing on the JVM side"; -const logLevel: LogLevelDesc = "TRACE"; +const logLevel: LogLevelDesc = "INFO"; +const logLevelJvmApp: LogLevelDesc = "INFO"; +const logLevelJvmRoot: LogLevelDesc = "WARN"; test.onFailure(async () => { await Containers.logDiagnostics({ logLevel }); @@ -56,13 +59,7 @@ test(testCase, async (t: Test) => { await ledger.logDebugPorts(); const partyARpcPort = await ledger.getRpcAPublicPort(); - // We cannot import SampleCordappEnum here because it causes a circular - // import cycle which means that the import statement does compile but will - // yield undefinedat runtime and the test will crash on this line. - // So, instead of importing the enum, we just hardcode a magic string which is - // the exact opposite of what we should be doing but until we figure out the - // circular imports problem it's an acceptable workaround. - const jarFiles = await ledger.pullCordappJars("BASIC_FLOW" as never); + const jarFiles = await ledger.pullCordappJars(SampleCordappEnum.BASIC_FLOW); t.comment(`Fetched ${jarFiles.length} cordapp jars OK`); const internalIpOrUndefined = await internalIpV4(); @@ -75,10 +72,10 @@ test(testCase, async (t: Test) => { const springAppConfig = { logging: { level: { - root: "INFO", - "net.corda": "INFO", - "org.hyperledger.cactus": "DEBUG", - "org.hyperledger.cacti": "DEBUG", + root: logLevelJvmRoot, + "net.corda": logLevelJvmRoot, + "org.hyperledger.cactus": logLevelJvmApp, + "org.hyperledger.cacti": logLevelJvmApp, }, }, cactus: { diff --git a/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts b/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts deleted file mode 100644 index 4a3e88d46e8..00000000000 --- a/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts +++ /dev/null @@ -1,399 +0,0 @@ -import "jest-extended"; -import { v4 as internalIpV4 } from "internal-ip"; - -import { - Containers, - CordaTestLedger, - pruneDockerAllIfGithubAction, -} from "@hyperledger/cactus-test-tooling"; -import { LogLevelDesc } from "@hyperledger/cactus-common"; -import { - SampleCordappEnum, - CordaConnectorContainer, -} from "@hyperledger/cactus-test-tooling"; - -import { - CordappDeploymentConfig, - DefaultApi as CordaApi, - DeployContractJarsV1Request, - FlowInvocationType, - InvokeContractV1Request, - JvmTypeKind, -} from "../../../main/typescript/generated/openapi/typescript-axios/index"; -import { Configuration } from "@hyperledger/cactus-core-api"; - -const testCase = "Tests are passing on the JVM side"; -const logLevel: LogLevelDesc = "TRACE"; - -describe(testCase, () => { - let connector: any; - - const ledger = new CordaTestLedger({ - imageName: "ghcr.io/hyperledger/cactus-corda-4-6-all-in-one-obligation", - imageVersion: "2021-03-19-feat-686", - logLevel, - }); - - beforeAll(async () => { - const pruning = pruneDockerAllIfGithubAction({ logLevel }); - await Containers.logDiagnostics({ logLevel }); //this was in the onFailure - await expect(pruning).resolves.toBeTruthy(); - }); - - afterAll(async () => { - await ledger.stop(); - await ledger.destroy(); - await pruneDockerAllIfGithubAction({ logLevel }); - try { - await connector.stop(); - } finally { - await connector.destroy(); - } - }); - - test(testCase, async () => { - expect(ledger).toBeTruthy(); - const ledgerContainer = await ledger.start(); - expect(ledgerContainer).toBeTruthy(); - - await ledger.logDebugPorts(); - const partyARpcPort = await ledger.getRpcAPublicPort(); - - const jarFiles = await ledger.pullCordappJars( - SampleCordappEnum.ADVANCED_OBLIGATION, - ); - console.log(`Fetched ${jarFiles.length} cordapp jars OK`); - - const internalIpOrUndefined = await internalIpV4(); - expect(internalIpOrUndefined).toBeTruthy(); - const internalIp = internalIpOrUndefined as string; - console.log(`Internal IP (based on default gateway): ${internalIp}`); - - const springAppConfig = { - logging: { - level: { - root: "INFO", - "org.hyperledger.cactus": "DEBUG", - }, - }, - cactus: { - corda: { - node: { host: internalIp }, - // TODO: parse the gradle build files to extract the credentials? - rpc: { port: partyARpcPort, username: "user1", password: "password" }, - }, - }, - }; - const springApplicationJson = JSON.stringify(springAppConfig); - const envVarSpringAppJson = `SPRING_APPLICATION_JSON=${springApplicationJson}`; - console.log(envVarSpringAppJson); - - connector = new CordaConnectorContainer({ - logLevel, - imageName: "ghcr.io/hyperledger/cactus-connector-corda-server", - imageVersion: "2021-11-23--feat-1493", - envVars: [envVarSpringAppJson], - }); - expect(CordaConnectorContainer).toBeTruthy(); - const connectorContainer = await connector.start(); - expect(connectorContainer).toBeTruthy(); - - await connector.logDebugPorts(); - const apiUrl = await connector.getApiLocalhostUrl(); - const config = new Configuration({ basePath: apiUrl }); - const apiClient = new CordaApi(config); - - const flowsRes = await apiClient.listFlowsV1(); - expect(flowsRes.status).toEqual(200); - expect(flowsRes.data).toBeTruthy(); - expect(flowsRes.data.flowNames).toBeTruthy(); - console.log(`apiClient.listFlowsV1() => ${JSON.stringify(flowsRes.data)}`); - - const diagRes = await apiClient.diagnoseNodeV1(); - expect(diagRes.status).toEqual(200); - expect(diagRes.data).toBeTruthy(); - expect(diagRes.data.nodeDiagnosticInfo).toBeTruthy(); - const ndi = diagRes.data.nodeDiagnosticInfo; - expect(ndi.cordapps).toBeTruthy(); - expect(Array.isArray(ndi.cordapps)).toBeTruthy(); - expect((ndi.cordapps as []).length > 0).toBeTrue(); - expect(ndi.vendor).toBeTruthy(); - expect(ndi.version).toBeTruthy(); - expect(ndi.revision).toBeTruthy(); - expect(ndi.platformVersion).toBeTruthy(); - - console.log( - `apiClient.diagnoseNodeV1() => ${JSON.stringify(diagRes.data)}`, - ); - - const cordappDeploymentConfigs: CordappDeploymentConfig[] = []; - const depReq: DeployContractJarsV1Request = { - jarFiles, - cordappDeploymentConfigs, - }; - const depRes = await apiClient.deployContractJarsV1(depReq); - expect(depRes).toBeTruthy(); - expect(depRes.status).toEqual(200); - expect(depRes.data).toBeTruthy(); - expect(depRes.data.deployedJarFiles).toBeTruthy(); - expect(depRes.data.deployedJarFiles.length).toEqual(jarFiles.length); - - const networkMapRes = await apiClient.networkMapV1(); - const partyA = networkMapRes.data.find((it) => - it.legalIdentities.some( - (it2) => it2.name.organisation === "ParticipantA", - ), - ); - const partyAPublicKey = partyA?.legalIdentities[0].owningKey; - - const partyB = networkMapRes.data.find((it) => - it.legalIdentities.some( - (it2) => it2.name.organisation === "ParticipantB", - ), - ); - const partyBPublicKey = partyB?.legalIdentities[0].owningKey; - - const req: InvokeContractV1Request = { - flowFullClassName: "net.corda.samples.obligation.flows.IOUIssueFlow", - flowInvocationType: FlowInvocationType.TrackedFlowDynamic, - params: [ - { - jvmTypeKind: JvmTypeKind.Reference, - jvmType: { - fqClassName: "net.corda.samples.obligation.states.IOUState", - }, - - jvmCtorArgs: [ - { - jvmTypeKind: JvmTypeKind.Reference, - jvmType: { - fqClassName: "net.corda.core.contracts.Amount", - }, - - jvmCtorArgs: [ - { - jvmTypeKind: JvmTypeKind.Primitive, - jvmType: { - fqClassName: "long", - }, - primitiveValue: 42, - }, - { - jvmTypeKind: JvmTypeKind.Reference, - jvmType: { - fqClassName: "java.util.Currency", - constructorName: "getInstance", - }, - - jvmCtorArgs: [ - { - jvmTypeKind: JvmTypeKind.Primitive, - jvmType: { - fqClassName: "java.lang.String", - }, - primitiveValue: "USD", - }, - ], - }, - ], - }, - { - jvmTypeKind: JvmTypeKind.Reference, - jvmType: { - fqClassName: "net.corda.core.identity.Party", - }, - - jvmCtorArgs: [ - { - jvmTypeKind: JvmTypeKind.Reference, - jvmType: { - fqClassName: "net.corda.core.identity.CordaX500Name", - }, - - jvmCtorArgs: [ - { - jvmTypeKind: JvmTypeKind.Primitive, - jvmType: { - fqClassName: "java.lang.String", - }, - primitiveValue: "ParticipantA", - }, - { - jvmTypeKind: JvmTypeKind.Primitive, - jvmType: { - fqClassName: "java.lang.String", - }, - primitiveValue: "London", - }, - { - jvmTypeKind: JvmTypeKind.Primitive, - jvmType: { - fqClassName: "java.lang.String", - }, - primitiveValue: "GB", - }, - ], - }, - { - jvmTypeKind: JvmTypeKind.Reference, - jvmType: { - fqClassName: - "org.hyperledger.cactus.plugin.ledger.connector.corda.server.impl.PublicKeyImpl", - }, - - jvmCtorArgs: [ - { - jvmTypeKind: JvmTypeKind.Primitive, - jvmType: { - fqClassName: "java.lang.String", - }, - primitiveValue: partyAPublicKey?.algorithm, - }, - { - jvmTypeKind: JvmTypeKind.Primitive, - jvmType: { - fqClassName: "java.lang.String", - }, - primitiveValue: partyAPublicKey?.format, - }, - { - jvmTypeKind: JvmTypeKind.Primitive, - jvmType: { - fqClassName: "java.lang.String", - }, - primitiveValue: partyAPublicKey?.encoded, - }, - ], - }, - ], - }, - { - jvmTypeKind: JvmTypeKind.Reference, - jvmType: { - fqClassName: "net.corda.core.identity.Party", - }, - - jvmCtorArgs: [ - { - jvmTypeKind: JvmTypeKind.Reference, - jvmType: { - fqClassName: "net.corda.core.identity.CordaX500Name", - }, - - jvmCtorArgs: [ - { - jvmTypeKind: JvmTypeKind.Primitive, - jvmType: { - fqClassName: "java.lang.String", - }, - primitiveValue: "ParticipantB", - }, - { - jvmTypeKind: JvmTypeKind.Primitive, - jvmType: { - fqClassName: "java.lang.String", - }, - primitiveValue: "New York", - }, - { - jvmTypeKind: JvmTypeKind.Primitive, - jvmType: { - fqClassName: "java.lang.String", - }, - primitiveValue: "US", - }, - ], - }, - { - jvmTypeKind: JvmTypeKind.Reference, - jvmType: { - fqClassName: - "org.hyperledger.cactus.plugin.ledger.connector.corda.server.impl.PublicKeyImpl", - }, - - jvmCtorArgs: [ - { - jvmTypeKind: JvmTypeKind.Primitive, - jvmType: { - fqClassName: "java.lang.String", - }, - primitiveValue: partyBPublicKey?.algorithm, - }, - { - jvmTypeKind: JvmTypeKind.Primitive, - jvmType: { - fqClassName: "java.lang.String", - }, - primitiveValue: partyBPublicKey?.format, - }, - { - jvmTypeKind: JvmTypeKind.Primitive, - jvmType: { - fqClassName: "java.lang.String", - }, - primitiveValue: partyBPublicKey?.encoded, - }, - ], - }, - ], - }, - { - jvmTypeKind: JvmTypeKind.Reference, - jvmType: { - fqClassName: "net.corda.core.contracts.Amount", - }, - - jvmCtorArgs: [ - { - jvmTypeKind: JvmTypeKind.Primitive, - jvmType: { - fqClassName: "long", - }, - primitiveValue: 1, - }, - { - jvmTypeKind: JvmTypeKind.Reference, - jvmType: { - fqClassName: "java.util.Currency", - constructorName: "getInstance", - }, - - jvmCtorArgs: [ - { - jvmTypeKind: JvmTypeKind.Primitive, - jvmType: { - fqClassName: "java.lang.String", - }, - primitiveValue: "USD", - }, - ], - }, - ], - }, - { - jvmTypeKind: JvmTypeKind.Reference, - jvmType: { - fqClassName: "net.corda.core.contracts.UniqueIdentifier", - }, - - jvmCtorArgs: [ - { - jvmTypeKind: JvmTypeKind.Primitive, - jvmType: { - fqClassName: "java.lang.String", - }, - primitiveValue: "7fc2161e-f8d0-4c86-a596-08326bdafd56", - }, - ], - }, - ], - }, - ], - timeoutMs: 60000, - } as unknown as InvokeContractV1Request; - - const res = await apiClient.invokeContractV1(req); - expect(res).toBeTruthy(); - expect(res.status).toEqual(200); - }); -}); diff --git a/packages/cactus-test-tooling/src/main/typescript/common/build-container-image.ts b/packages/cactus-test-tooling/src/main/typescript/common/build-container-image.ts index e73e16a515c..9bdd7d471e1 100644 --- a/packages/cactus-test-tooling/src/main/typescript/common/build-container-image.ts +++ b/packages/cactus-test-tooling/src/main/typescript/common/build-container-image.ts @@ -1,6 +1,10 @@ import Docker, { ImageBuildContext, ImageBuildOptions } from "dockerode"; -import { LoggerProvider, LogLevelDesc } from "@hyperledger/cactus-common"; +import { + createRuntimeErrorWithCause, + LoggerProvider, + LogLevelDesc, +} from "@hyperledger/cactus-common"; export interface IBuildContainerImageRequest { readonly logLevel: LogLevelDesc; @@ -12,9 +16,31 @@ export interface IBuildContainerImageRequest { readonly dockerodeImageBuildContext?: Partial; } +export interface IBuildImageResultFail { + readonly errorDetail: { + readonly code: Readonly; + readonly message: Readonly; + }; + readonly error: string; +} + +export function isIBuildImageResultFail( + x: unknown, +): x is IBuildImageResultFail { + if (!x) { + return false; + } + return ( + typeof (x as IBuildImageResultFail).error === "string" && + typeof (x as IBuildImageResultFail).errorDetail === "object" && + typeof (x as IBuildImageResultFail).errorDetail.code === "number" && + typeof (x as IBuildImageResultFail).errorDetail.message === "string" + ); +} + export async function buildContainerImage( req: Readonly, -): Promise { +): Promise { if (!req) { throw new Error("Expected arg req to be truthy."); } @@ -50,15 +76,27 @@ export async function buildContainerImage( imageBuildOptions, ); + const buildErrors: IBuildImageResultFail[] = []; stream.on("data", (data: unknown) => { if (data instanceof Buffer) { - log.debug("[Build]: ", data.toString("utf-8")); + const logRowJson = data.toString("utf-8"); + const logRow = JSON.parse(logRowJson); + if (isIBuildImageResultFail(logRow)) { + buildErrors.push(logRow); + } + log.debug("[Build]: %s", logRowJson); } }); - await new Promise((resolve, reject) => { + const out = await new Promise((resolve, reject) => { dockerEngine.modem.followProgress(stream, (err, res) => err ? reject(err) : resolve(res), ); }); + + if (buildErrors.length > 0) { + const eMsg = `Could not build image ${req.imageTag} from ${req.buildDir}/${req.imageFile}`; + throw createRuntimeErrorWithCause(eMsg, { buildErrors }); + } + return out; } diff --git a/packages/cactus-test-tooling/src/main/typescript/corda-connector/corda-connector-container.ts b/packages/cactus-test-tooling/src/main/typescript/corda-connector/corda-connector-container.ts index 06633ba9267..aed3beda766 100644 --- a/packages/cactus-test-tooling/src/main/typescript/corda-connector/corda-connector-container.ts +++ b/packages/cactus-test-tooling/src/main/typescript/corda-connector/corda-connector-container.ts @@ -121,6 +121,16 @@ export class CordaConnectorContainer { [`${this.apiPort}/tcp`]: {}, // REST API HTTP port [`9001/tcp`]: {}, // SupervisorD Web UI }, + Healthcheck: { + Test: [ + "CMD-SHELL", + `curl -vv -i -X POST http://127.0.0.1:8080/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/network-map`, + ], + Interval: 5000000000, // 5 seconds + Timeout: 3000000000, // 3 seconds + Retries: 50, + StartPeriod: 1000000000, // 5 second + }, HostConfig: { PublishAllPorts: true, }, diff --git a/packages/cactus-test-tooling/src/main/typescript/corda/corda-test-ledger.ts b/packages/cactus-test-tooling/src/main/typescript/corda/corda-test-ledger.ts index d453dfc1db7..d9174b55e1a 100644 --- a/packages/cactus-test-tooling/src/main/typescript/corda/corda-test-ledger.ts +++ b/packages/cactus-test-tooling/src/main/typescript/corda/corda-test-ledger.ts @@ -26,6 +26,7 @@ export interface ICordaTestLedgerConstructorOptions { imageVersion?: string; imageName?: string; rpcPortNotary?: number; + sshPort?: number; rpcPortA?: number; rpcPortB?: number; rpcPortC?: number; @@ -41,6 +42,7 @@ const DEFAULTS = Object.freeze({ imageVersion: "2021-03-01-7e07b5b", imageName: "petermetz/cactus-corda-4-6-all-in-one-obligation", rpcPortNotary: 10003, + sshPort: 22, rpcPortA: 10008, rpcPortB: 10011, rpcPortC: 10014, @@ -59,6 +61,7 @@ export const JOI_SCHEMA: Joi.Schema = Joi.object().keys({ imageVersion: Joi.string().min(5).required(), imageName: Joi.string().min(1).required(), rpcPortNotary: Joi.number().min(1).max(65535).required(), + sshPort: Joi.number().min(1).max(65535).required(), rpcPortA: Joi.number().min(1).max(65535).required(), rpcPortB: Joi.number().min(1).max(65535).required(), rpcPortC: Joi.number().min(1).max(65535).required(), @@ -78,6 +81,7 @@ export class CordaTestLedger implements ITestLedger { public readonly imageVersion: string; public readonly imageName: string; public readonly rpcPortNotary: number; + public readonly sshPort: number; public readonly rpcPortA: number; public readonly rpcPortB: number; public readonly rpcPortC: number; @@ -93,6 +97,7 @@ export class CordaTestLedger implements ITestLedger { this.imageVersion = opts.imageVersion || DEFAULTS.imageVersion; this.imageName = opts.imageName || DEFAULTS.imageName; + this.sshPort = opts.sshPort || DEFAULTS.sshPort; this.rpcPortA = opts.rpcPortA || DEFAULTS.rpcPortA; this.rpcPortB = opts.rpcPortB || DEFAULTS.rpcPortB; this.rpcPortC = opts.rpcPortC || DEFAULTS.rpcPortC; @@ -143,7 +148,7 @@ export class CordaTestLedger implements ITestLedger { [`${this.rpcPortA}/tcp`]: {}, // corda PartyA RPC [`${this.rpcPortB}/tcp`]: {}, // corda PartyB RPC [`${this.rpcPortC}/tcp`]: {}, // corda PartyC RPC - "22/tcp": {}, // ssh server + [`${this.sshPort}/tcp`]: {}, // ssh server }, HostConfig: { PublishAllPorts: true, @@ -205,9 +210,11 @@ export class CordaTestLedger implements ITestLedger { public async logDebugPorts(): Promise { const partyNotaryRpcPort = await this.getRpcNotaryPublicPort(); + const sshPort = await this.getSSHPublicPort(); const partyARpcPort = await this.getRpcAPublicPort(); const partyBRpcPort = await this.getRpcBPublicPort(); const partyCRpcPort = await this.getRpcCPublicPort(); + this.log.info(`AIO Image SSH Port: ${sshPort}`); this.log.info(`Party Notary RPC Port: ${partyNotaryRpcPort}`); this.log.info(`Party A RPC Port: ${partyARpcPort}`); this.log.info(`Party B RPC Port: ${partyBRpcPort}`); @@ -250,12 +257,11 @@ export class CordaTestLedger implements ITestLedger { public async pullCordappJars( sampleCordapp: SampleCordappEnum, ): Promise { + await new Promise((resolve2) => setTimeout(resolve2, 1000)); const fnTag = `${this.className}.pullCordappJars()`; Checks.truthy(sampleCordapp, `${fnTag}:sampleCordapp`); await this.buildCordapp(sampleCordapp); const container = this.getContainer(); - // const cordappRootDir = SAMPLE_CORDAPP_ROOT_DIRS[sampleCordapp]; - // const cordaRelativePaths = SAMPLE_CORDAPP_JAR_RELATIVE_PATHS[sampleCordapp]; const cordappData = SAMPLE_CORDAPP_DATA[sampleCordapp]; const jars: ICordappJarFile[] = []; @@ -280,6 +286,7 @@ export class CordaTestLedger implements ITestLedger { } public async buildCordapp(sampleCordapp: SampleCordappEnum): Promise { + await new Promise((resolve2) => setTimeout(resolve2, 1000)); const fnTag = `${this.className}.buildCordapp()`; Checks.truthy(sampleCordapp, `${fnTag}:sampleCordapp`); const sshConfig = await this.getSshConfig(); @@ -302,7 +309,55 @@ export class CordaTestLedger implements ITestLedger { this.log.debug(`${fnTag}:signal=%o`, signal); this.log.debug(`${fnTag}:stderr=%o`, stderr); this.log.debug(`${fnTag}:stdout=%o`, stdout); - // const jarPath = `${cwd}contracts/build/libs/contracts-1.0.jar`; + } finally { + ssh.dispose(); + } + } + + /** + * Used for deleting the exiting build files of a sample cordapp. This is + * useful because if you are writing a test case that builds the jars and then + * uploads them as part of the deployment to the corda node then you end up with + * a duplicate contract error that looks something like this (on a single row): + * + * ```sh + * E 04:20:01 1 NodeStartupLogging. - The CorDapp ( + * name: Negotiation CorDapp, + * file: ADVANCED_NEGOTIATION_workflows-0.2) is installed multiple times on the node. + * The following files correspond to the exact same content: + * [workflows-0.2] + * [Error Code: cordapp-duplicate-cordapps-installed + * For further information, please go to https://docs.corda.net/docs/corda-os/4.12/error-codes.html] + * ``` + * + * @param sampleCordapp The sample cordapp that you wish to clean + */ + public async cleanCordapp(sampleCordapp: SampleCordappEnum): Promise { + await new Promise((resolve2) => setTimeout(resolve2, 2000)); + const fnTag = `${this.className}.cleanCordapp()`; + Checks.truthy(sampleCordapp, `${fnTag}:sampleCordapp`); + const sshConfig = await this.getSshConfig(); + const ssh = new NodeSSH(); + try { + await ssh.connect(sshConfig); + } catch (ex) { + this.log.error(`Failed to establish SSH connection to Corda node.`, ex); + throw ex; + } + + const cwd = "/"; + + try { + const deletePathPattern = `${SAMPLE_CORDAPP_DATA[sampleCordapp].rootDir}build/nodes/{PartyA,PartyB,PartyC,Notary}/cordapps/*`; + const cmd = `rm -rf ${deletePathPattern}`; + + this.log.debug(`${fnTag}:CMD=%o, CWD=%o`, cmd, cwd); + const response = await ssh.execCommand(cmd, { cwd }); + const { code, signal, stderr, stdout } = response; + this.log.debug(`${fnTag}:code=%o`, code); + this.log.debug(`${fnTag}:signal=%o`, signal); + this.log.debug(`${fnTag}:stderr=%o`, stderr); + this.log.debug(`${fnTag}:stdout=%o`, stdout); } finally { ssh.dispose(); } @@ -340,7 +395,7 @@ export class CordaTestLedger implements ITestLedger { public async getSSHPublicPort(): Promise { const aContainerInfo = await this.getContainerInfo(); - return Containers.getPublicPort(22, aContainerInfo); + return Containers.getPublicPort(this.sshPort, aContainerInfo); } public async getCorDappsDirPartyA( @@ -376,6 +431,7 @@ export class CordaTestLedger implements ITestLedger { host: "127.0.0.1", port: publicPort, username: "root", + password: "root", privateKey, }; @@ -400,6 +456,7 @@ export class CordaTestLedger implements ITestLedger { const validationResult = JOI_SCHEMA.validate({ imageVersion: this.imageVersion, imageName: this.imageName, + sshPort: this.sshPort, rpcPortNotary: this.rpcPortNotary, rpcPortA: this.rpcPortA, rpcPortB: this.rpcPortB, diff --git a/packages/cactus-test-tooling/src/main/typescript/corda/sample-cordapp-enum.ts b/packages/cactus-test-tooling/src/main/typescript/corda/sample-cordapp-enum.ts index d557a2db7b2..cec9a830c9a 100644 --- a/packages/cactus-test-tooling/src/main/typescript/corda/sample-cordapp-enum.ts +++ b/packages/cactus-test-tooling/src/main/typescript/corda/sample-cordapp-enum.ts @@ -42,9 +42,9 @@ export const SAMPLE_CORDAPP_DATA = Object.freeze({ [SampleCordappEnum.ADVANCED_NEGOTIATION]: { rootDir: "/samples-kotlin/Advanced/negotiation-cordapp/", cordappDirPartyA: - "/samples-kotlin/Advanced/negotiation-cordapp/build/nodes/ParticipantA/cordapps", + "/samples-kotlin/Advanced/negotiation-cordapp/build/nodes/PartyA/cordapps", cordappDirPartyB: - "/samples-kotlin/Advanced/negotiation-cordapp/build/nodes/ParticipantB/cordapps", + "/samples-kotlin/Advanced/negotiation-cordapp/build/nodes/PartyB/cordapps", cordappDirPartyC: "NOT_APPLICABLE__THIS_SAMPLE_ONLY_HAS_A_AND_B_PARTIES", cordappDirNotary: "/samples-kotlin/Advanced/negotiation-cordapp/build/nodes/Notary/cordapps", diff --git a/tools/docker/corda-all-in-one/README.md b/tools/docker/corda-all-in-one/README.md index 7ba5dd13316..226446d3e4e 100644 --- a/tools/docker/corda-all-in-one/README.md +++ b/tools/docker/corda-all-in-one/README.md @@ -44,7 +44,7 @@ docker run --rm --privileged caio48 ### Build and Run Image Locally ```sh -DOCKER_BUILDKIT=1 docker build ./tools/docker/corda-all-in-one/corda-v4_8-flowdb/ -t caio48-flowdb +DOCKER_BUILDKIT=1 docker build --progress=plain ./tools/docker/corda-all-in-one/corda-v4_8-flowdb/ -t caio48-flowdb docker run --rm --privileged caio48-flowdb ``` @@ -58,7 +58,7 @@ docker run --rm --privileged caio48-flowdb ### Build and Run Image Locally ```sh -DOCKER_BUILDKIT=1 docker build ./tools/docker/corda-all-in-one/corda-v4_12/ -f ./tools/docker/corda-all-in-one/corda-v4_12/Dockerfile -t caio412 +DOCKER_BUILDKIT=1 docker build --progress=plain ./tools/docker/corda-all-in-one/corda-v4_12/ -f ./tools/docker/corda-all-in-one/corda-v4_12/Dockerfile -t caio412 docker run --rm --privileged caio412 ``` diff --git a/tools/docker/corda-all-in-one/corda-v4_12/Dockerfile b/tools/docker/corda-all-in-one/corda-v4_12/Dockerfile index 893dba2c2ed..4f8e47b1e0f 100644 --- a/tools/docker/corda-all-in-one/corda-v4_12/Dockerfile +++ b/tools/docker/corda-all-in-one/corda-v4_12/Dockerfile @@ -11,7 +11,7 @@ WORKDIR /opt/corda/ # # ENT-11443 Function sig changes to support removing enterprise compiler warnings (#7671) RUN git switch release/os/4.12 -RUN git checkout c7514e1c603c077b49987fd79bd77060612967ed +RUN git fetch --all && git checkout d578cae797ac5551d8a3c959354d7c6d69f0f97a RUN ./gradlew jar -x test FROM ubuntu:22.04 @@ -24,36 +24,34 @@ RUN echo 'root:root' | chpasswd RUN mkdir /var/run/sshd -ARG CORDA_TOOLS_SHELL_CLI_VERSION=4.8.11 - WORKDIR / -ENV CACTUS_CFG_PATH=/etc/hyperledger/cactus -RUN mkdir -p $CACTUS_CFG_PATH - -RUN curl https://download.corda.net/maven/corda-releases/net/corda/corda-tools-shell-cli/${CORDA_TOOLS_SHELL_CLI_VERSION}/corda-tools-shell-cli-${CORDA_TOOLS_SHELL_CLI_VERSION}-all.jar --output /corda-tools-shell-cli-all.jar -# Make the "corda-shell" alias avaialble on the terminal -RUN java -jar /corda-tools-shell-cli-all.jar install-shell-extensions # The image has a bleeding edge version of corda baked in for testing conveniece RUN mkdir -p /opt/bin/ COPY --from=builder /opt/corda/node/capsule/build/libs/corda-4.12-SNAPSHOT.jar /opt/bin/corda.jar +# Make the "corda-shell" alias avaialble on the terminal +RUN java -jar /opt/bin/corda.jar install-shell-extensions + RUN git clone https://github.com/corda/samples-kotlin.git WORKDIR /samples-kotlin -ARG SAMPLES_KOTLIN_SHA=219750f8da2fd491c3b55c8eea821b1f345fef7d -ARG SAMPLES_KOTLIN_BRANCH=arshadm/ent-6914-upgrade-kotlin19-jdk17 +ARG SAMPLES_KOTLIN_SHA=a5bb03027d7a6e1a5bca880e338a811b875f2815 +ARG SAMPLES_KOTLIN_BRANCH=release/4.12 -RUN git switch ${SAMPLES_KOTLIN_BRANCH} +RUN git fetch --all && git switch ${SAMPLES_KOTLIN_BRANCH} RUN git checkout ${SAMPLES_KOTLIN_SHA} ARG SAMPLES_KOTLIN_CORDAPP_SUB_DIR_PATH="./Advanced/negotiation-cordapp/" WORKDIR /samples-kotlin/${SAMPLES_KOTLIN_CORDAPP_SUB_DIR_PATH} COPY ./negotiation-cordapp/build.gradle /samples-kotlin/Advanced/negotiation-cordapp/build.gradle +COPY ./negotiation-cordapp/contracts/build.gradle /samples-kotlin/Advanced/negotiation-cordapp/contracts/build.gradle +COPY ./negotiation-cordapp/workflows/build.gradle /samples-kotlin/Advanced/negotiation-cordapp/workflows/build.gradle +COPY ./constants.properties /samples-kotlin/Advanced/constants.properties -RUN ./gradlew build deployNodes +RUN ./gradlew build deployNodes -x test WORKDIR / @@ -62,7 +60,7 @@ RUN augtool 'set /files/etc/ssh/sshd_config/AuthorizedKeysFile ".ssh/authorized_ augtool 'set /files/etc/ssh/sshd_config/PermitRootLogin yes' && \ augtool 'set /files/etc/ssh/sshd_config/PasswordAuthentication yes' && \ augtool 'set /files/etc/ssh/sshd_config/PermitEmptyPasswords yes' && \ - augtool 'set /files/etc/ssh/sshd_config/Port 22' && \ + augtool 'set /files/etc/ssh/sshd_config/Port 2222' && \ augtool 'set /files/etc/ssh/sshd_config/LogLevel DEBUG2' && \ augtool 'set /files/etc/ssh/sshd_config/LoginGraceTime 10' @@ -76,6 +74,9 @@ RUN mkdir ~/.ssh && \ chmod 700 ~/.ssh/ && \ touch ~/.ssh/authorized_keys +ENV CACTUS_CFG_PATH=/etc/hyperledger/cactus +RUN mkdir -p $CACTUS_CFG_PATH + RUN ["/bin/bash", "-c", "ssh-keygen -t rsa -N '' -f $CACTUS_CFG_PATH/corda-aio-image"] RUN mv $CACTUS_CFG_PATH/corda-aio-image $CACTUS_CFG_PATH/corda-aio-image.key RUN cp $CACTUS_CFG_PATH/corda-aio-image.pub ~/.ssh/authorized_keys @@ -83,7 +84,7 @@ RUN cp $CACTUS_CFG_PATH/corda-aio-image.pub ~/.ssh/authorized_keys WORKDIR /samples-kotlin/${SAMPLES_KOTLIN_CORDAPP_SUB_DIR_PATH} # OpenSSH server -EXPOSE 22 +EXPOSE 2222 # supervisord web ui/dashboard EXPOSE 9001 diff --git a/tools/docker/corda-all-in-one/corda-v4_12/constants.properties b/tools/docker/corda-all-in-one/corda-v4_12/constants.properties new file mode 100644 index 00000000000..b58360bf79b --- /dev/null +++ b/tools/docker/corda-all-in-one/corda-v4_12/constants.properties @@ -0,0 +1,15 @@ +cordaReleaseGroup=net.corda +cordaCoreReleaseGroup=net.corda +cordaVersion=4.12 +cordaCoreVersion=4.12 +cordaShellVersion=4.12 +gradlePluginsVersion=5.1.1 +kotlinVersion=1.9.20 +junitVersion=4.12 +quasarVersion=0.9.0_r3 +log4jVersion=2.23.1 +platformVersion=140 +slf4jVersion=2.0.12 +nettyVersion=4.1.77.Final +snappyVersion=0.4 +rxJavaVersion=1.3.8 diff --git a/tools/docker/corda-all-in-one/corda-v4_12/negotiation-cordapp/build.gradle b/tools/docker/corda-all-in-one/corda-v4_12/negotiation-cordapp/build.gradle index 70235fb10af..e0457ee2c7e 100644 --- a/tools/docker/corda-all-in-one/corda-v4_12/negotiation-cordapp/build.gradle +++ b/tools/docker/corda-all-in-one/corda-v4_12/negotiation-cordapp/build.gradle @@ -1,8 +1,5 @@ -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile - -import static org.gradle.api.JavaVersion.VERSION_17 import static org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 -import static org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_8 +import static org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9 buildscript { //properties that you need to build the project @@ -25,8 +22,8 @@ buildscript { //properties that you need to build the project rxjava_version = constants.getProperty("rxJavaVersion") snappy_version = constants.getProperty("snappyVersion") //springboot - spring_boot_version = '2.0.2.RELEASE' - spring_boot_gradle_plugin_version = '2.0.2.RELEASE' + spring_boot_version = '3.2.5' + spring_boot_gradle_plugin_version = '3.2.5' testJvmArgs = ['--add-opens', 'java.base/java.time=ALL-UNNAMED', '--add-opens', 'java.base/java.io=ALL-UNNAMED', '--add-opens', 'java.base/java.util=ALL-UNNAMED', '--add-opens', 'java.base/java.net=ALL-UNNAMED', @@ -34,9 +31,6 @@ buildscript { //properties that you need to build the project '--add-opens', 'java.base/java.security.cert=ALL-UNNAMED', '--add-opens', 'java.base/java.security=ALL-UNNAMED', '--add-opens', 'java.base/javax.net.ssl=ALL-UNNAMED', '--add-opens', 'java.base/java.lang=ALL-UNNAMED', '--add-opens', 'java.base/java.util.concurrent=ALL-UNNAMED', '--add-opens', 'java.sql/java.sql=ALL-UNNAMED',] - testJvmFxArgs = [ '--add-exports', 'java.base/sun.nio.ch=ALL-UNNAMED', - '--add-exports', 'javafx.base/com.sun.javafx=ALL-UNNAMED', - '--add-exports', 'javafx.base/com.sun.javafx.collections=ALL-UNNAMED'] } repositories { @@ -69,8 +63,8 @@ allprojects { //Properties that you need to compile your project (The applicatio tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile) { compilerOptions { - languageVersion = KOTLIN_1_8 - apiVersion = KOTLIN_1_8 + languageVersion = KOTLIN_1_9 + apiVersion = KOTLIN_1_9 jvmTarget = JVM_17 javaParameters = true // Useful for reflection. freeCompilerArgs = ['-Xjvm-default=all-compatibility'] @@ -112,7 +106,7 @@ dependencies { cordapp project(":workflows") cordapp project(":contracts") - cordaProvided "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}" + cordaProvided "org.apache.logging.log4j:log4j-slf4j2-impl:${log4j_version}" cordaProvided "org.apache.logging.log4j:log4j-web:${log4j_version}" cordaProvided "org.slf4j:jul-to-slf4j:$slf4j_version" cordaDriver "net.corda:corda-shell:$corda_shell_version" diff --git a/tools/docker/corda-all-in-one/corda-v4_12/negotiation-cordapp/contracts/build.gradle b/tools/docker/corda-all-in-one/corda-v4_12/negotiation-cordapp/contracts/build.gradle new file mode 100644 index 00000000000..a602ce49af1 --- /dev/null +++ b/tools/docker/corda-all-in-one/corda-v4_12/negotiation-cordapp/contracts/build.gradle @@ -0,0 +1,45 @@ +apply plugin: 'org.jetbrains.kotlin.jvm' +apply plugin: 'net.corda.plugins.cordapp' + +cordapp { + targetPlatformVersion corda_platform_version.toInteger() + minimumPlatformVersion corda_platform_version.toInteger() + contract { + name "Negotiation CorDapp" + vendor "Corda Open Source" + licence "Apache License, Version 2.0" + versionId 1 + } +} +sourceSets { + test { + resources { + srcDir "../config/test" + } + } +} +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" + testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version" + testImplementation "junit:junit:$junit_version" + testImplementation "$corda_release_group:corda-node-driver:$corda_release_version" + + // Corda dependencies. + cordaProvided "$corda_core_release_group:corda-core:$corda_core_release_version" + + cordaProvided "$corda_release_group:corda-finance-contracts:$corda_release_version" + cordaProvided "$corda_release_group:corda:$corda_release_version" + cordaProvided "$corda_core_release_group:corda-core-test-utils:$corda_core_release_version" + cordaProvided "$corda_core_release_group:corda-test-utils:$corda_core_release_version" +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" + + // Corda dependencies. + cordaProvided "$corda_release_group:corda-core:$corda_release_version" +} + +test { + jvmArgs = rootProject.ext.testJvmArgs +} diff --git a/tools/docker/corda-all-in-one/corda-v4_12/negotiation-cordapp/workflows/build.gradle b/tools/docker/corda-all-in-one/corda-v4_12/negotiation-cordapp/workflows/build.gradle new file mode 100644 index 00000000000..05db178cf18 --- /dev/null +++ b/tools/docker/corda-all-in-one/corda-v4_12/negotiation-cordapp/workflows/build.gradle @@ -0,0 +1,49 @@ +apply plugin: 'org.jetbrains.kotlin.jvm' +apply plugin: 'net.corda.plugins.cordapp' +apply plugin: 'net.corda.plugins.quasar-utils' +apply plugin: 'net.corda.plugins.cordformation' + +cordapp { + targetPlatformVersion corda_platform_version.toInteger() + minimumPlatformVersion corda_platform_version.toInteger() + workflow { + name "Negotiation CorDapp" + vendor "Corda Open Source" + licence "Apache License, Version 2.0" + versionId 1 + } +} + +sourceSets { + test { + resources { + srcDir "../config/test" + } + } +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" + testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version" + testImplementation "junit:junit:$junit_version" + + // Corda dependencies. + cordaProvided "$corda_core_release_group:corda-core:$corda_core_release_version" + cordaProvided "$corda_release_group:corda-jackson:$corda_release_version" + cordaProvided "$corda_release_group:corda-rpc:$corda_release_version" + cordaProvided "$corda_release_group:corda-node-api:$corda_release_version" + + testImplementation "$corda_release_group:corda-node-driver:$corda_release_version" + testImplementation "io.reactivex:rxjava:$rxjava_version" + // Needed by deployNodes task. + corda "$corda_release_group:corda:$corda_release_version" + cordaProvided "$corda_core_release_group:corda-core-test-utils:$corda_core_release_version" + cordaProvided "$corda_core_release_group:corda-test-utils:$corda_core_release_version" + // CorDapp dependencies. + cordapp project(":contracts") + testRuntimeOnly "org.iq80.snappy:snappy:$snappy_version" +} + +test { + jvmArgs = rootProject.ext.testJvmArgs +} From 7e7bb44c01a2d19306ecaaaa2ba2e3c574039c87 Mon Sep 17 00:00:00 2001 From: Peter Somogyvari Date: Wed, 28 Aug 2024 15:42:20 -0700 Subject: [PATCH 7/8] fix(security): address CVE-2024-39338 SSRF in axios >= 1.3.2, <= 1.7.3 https://github.com/hyperledger/cacti/security/dependabot/1172 CVE ID CVE-2024-39338 GHSA ID GHSA-8hc4-vh64-cxmj axios 1.7.2 allows SSRF via unexpected behavior where requests for path relative URLs get processed as protocol relative URLs. Signed-off-by: Peter Somogyvari --- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- packages/cactus-cmd-api-server/package.json | 2 +- packages/cactus-core-api/package.json | 2 +- .../cactus-plugin-bungee-hermes/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../cactus-plugin-htlc-eth-besu/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../cactus-plugin-keychain-vault/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../cactus-plugin-satp-hermes/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- packages/cactus-test-tooling/package.json | 2 +- yarn.lock | 82 +++++++++---------- 42 files changed, 82 insertions(+), 82 deletions(-) diff --git a/examples/cactus-example-carbon-accounting-business-logic-plugin/package.json b/examples/cactus-example-carbon-accounting-business-logic-plugin/package.json index c5fa7b2000c..c641d203a34 100644 --- a/examples/cactus-example-carbon-accounting-business-logic-plugin/package.json +++ b/examples/cactus-example-carbon-accounting-business-logic-plugin/package.json @@ -64,7 +64,7 @@ "@hyperledger/cactus-plugin-ledger-connector-fabric": "2.0.0-rc.3", "@hyperledger/cactus-plugin-ledger-connector-xdai": "2.0.0-rc.3", "async-exit-hook": "2.0.1", - "axios": "1.6.0", + "axios": "1.7.5", "express": "4.19.2", "openapi-types": "12.1.3", "typescript-optional": "2.0.1", diff --git a/examples/cactus-example-cbdc-bridging-backend/package.json b/examples/cactus-example-cbdc-bridging-backend/package.json index 00d32b46511..ca8be72271e 100644 --- a/examples/cactus-example-cbdc-bridging-backend/package.json +++ b/examples/cactus-example-cbdc-bridging-backend/package.json @@ -70,7 +70,7 @@ "@openzeppelin/contracts": "4.9.6", "@openzeppelin/contracts-upgradeable": "4.9.6", "async-exit-hook": "2.0.1", - "axios": "1.6.0", + "axios": "1.7.5", "crypto-js": "4.2.0", "dotenv": "16.0.1", "fabric-network": "2.2.20", diff --git a/examples/cactus-example-cbdc-bridging-frontend/package.json b/examples/cactus-example-cbdc-bridging-frontend/package.json index b6c37cd1326..bae722f5327 100644 --- a/examples/cactus-example-cbdc-bridging-frontend/package.json +++ b/examples/cactus-example-cbdc-bridging-frontend/package.json @@ -33,7 +33,7 @@ "@types/node": "18.11.9", "@types/react": "^18.2.39", "@types/react-dom": "^18.2.17", - "axios": "1.6.0", + "axios": "1.7.5", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "5.0.1", diff --git a/examples/cactus-example-discounted-asset-trade-client/package.json b/examples/cactus-example-discounted-asset-trade-client/package.json index 820a888709a..e21a5399803 100644 --- a/examples/cactus-example-discounted-asset-trade-client/package.json +++ b/examples/cactus-example-discounted-asset-trade-client/package.json @@ -61,7 +61,7 @@ "@hyperledger/anoncreds-nodejs": "0.2.0", "@hyperledger/aries-askar-nodejs": "0.2.0", "@hyperledger/indy-vdr-nodejs": "0.2.0", - "axios": "1.6.0", + "axios": "1.7.5", "inquirer": "8.2.6", "loglevel": "1.8.1" }, diff --git a/examples/cactus-example-discounted-asset-trade/package.json b/examples/cactus-example-discounted-asset-trade/package.json index e8bfe1bd71f..f030f9a445b 100644 --- a/examples/cactus-example-discounted-asset-trade/package.json +++ b/examples/cactus-example-discounted-asset-trade/package.json @@ -23,7 +23,7 @@ "@hyperledger/cactus-plugin-ledger-connector-ethereum": "2.0.0-rc.3", "@hyperledger/cactus-plugin-ledger-connector-fabric": "2.0.0-rc.3", "@types/node": "18.11.9", - "axios": "1.7.2", + "axios": "1.7.5", "body-parser": "1.20.2", "cookie-parser": "1.4.6", "debug": "3.1.0", diff --git a/examples/cactus-example-supply-chain-backend/package.json b/examples/cactus-example-supply-chain-backend/package.json index 37ccaf57ba2..d2d70b38ed3 100644 --- a/examples/cactus-example-supply-chain-backend/package.json +++ b/examples/cactus-example-supply-chain-backend/package.json @@ -66,7 +66,7 @@ "@hyperledger/cactus-plugin-ledger-connector-xdai": "2.0.0-rc.3", "@hyperledger/cactus-test-tooling": "2.0.0-rc.3", "async-exit-hook": "2.0.1", - "axios": "1.6.0", + "axios": "1.7.5", "dotenv": "16.0.0", "express": "4.19.2", "express-jwt": "8.4.1", diff --git a/examples/cactus-example-supply-chain-business-logic-plugin/package.json b/examples/cactus-example-supply-chain-business-logic-plugin/package.json index dd909b0e70e..5dcc85c89eb 100644 --- a/examples/cactus-example-supply-chain-business-logic-plugin/package.json +++ b/examples/cactus-example-supply-chain-business-logic-plugin/package.json @@ -65,7 +65,7 @@ "@hyperledger/cactus-plugin-ledger-connector-fabric": "2.0.0-rc.3", "@hyperledger/cactus-plugin-ledger-connector-xdai": "2.0.0-rc.3", "async-exit-hook": "2.0.1", - "axios": "1.6.0", + "axios": "1.7.5", "express": "4.19.2", "openapi-types": "12.1.3", "run-time-error-cjs": "1.4.0", diff --git a/extensions/cactus-plugin-htlc-coordinator-besu/package.json b/extensions/cactus-plugin-htlc-coordinator-besu/package.json index 823a44dd381..5e56dac7af1 100644 --- a/extensions/cactus-plugin-htlc-coordinator-besu/package.json +++ b/extensions/cactus-plugin-htlc-coordinator-besu/package.json @@ -65,7 +65,7 @@ "@hyperledger/cactus-plugin-htlc-eth-besu-erc20": "2.0.0-rc.3", "@hyperledger/cactus-plugin-ledger-connector-besu": "2.0.0-rc.3", "@hyperledger/cactus-test-plugin-htlc-eth-besu-erc20": "2.0.0-rc.3", - "axios": "1.7.2", + "axios": "1.7.5", "body-parser": "1.20.2", "fast-safe-stringify": "2.1.1", "joi": "17.13.3", diff --git a/extensions/cactus-plugin-object-store-ipfs/package.json b/extensions/cactus-plugin-object-store-ipfs/package.json index 50224df4500..69e4c6aa6ec 100644 --- a/extensions/cactus-plugin-object-store-ipfs/package.json +++ b/extensions/cactus-plugin-object-store-ipfs/package.json @@ -59,7 +59,7 @@ "@hyperledger/cactus-common": "2.0.0-rc.3", "@hyperledger/cactus-core": "2.0.0-rc.3", "@hyperledger/cactus-core-api": "2.0.0-rc.3", - "axios": "1.6.0", + "axios": "1.7.5", "run-time-error-cjs": "1.4.0", "typescript-optional": "2.0.1", "uuid": "10.0.0" diff --git a/packages/cacti-plugin-consortium-static/package.json b/packages/cacti-plugin-consortium-static/package.json index 34969fc645e..36bb37b2565 100644 --- a/packages/cacti-plugin-consortium-static/package.json +++ b/packages/cacti-plugin-consortium-static/package.json @@ -58,7 +58,7 @@ "@hyperledger/cactus-common": "2.0.0-rc.3", "@hyperledger/cactus-core": "2.0.0-rc.3", "@hyperledger/cactus-core-api": "2.0.0-rc.3", - "axios": "1.6.0", + "axios": "1.7.5", "body-parser": "1.20.2", "express": "4.19.2", "http-errors-enhanced-cjs": "2.0.1", diff --git a/packages/cacti-plugin-ledger-connector-stellar/package.json b/packages/cacti-plugin-ledger-connector-stellar/package.json index 22e75ae8bfa..7efb908b625 100644 --- a/packages/cacti-plugin-ledger-connector-stellar/package.json +++ b/packages/cacti-plugin-ledger-connector-stellar/package.json @@ -62,7 +62,7 @@ "@hyperledger/cactus-common": "2.0.0-rc.3", "@hyperledger/cactus-core": "2.0.0-rc.3", "@hyperledger/cactus-core-api": "2.0.0-rc.3", - "axios": "1.7.2", + "axios": "1.7.5", "express": "4.19.2", "http-errors-enhanced-cjs": "2.0.1", "joi": "17.13.3", diff --git a/packages/cactus-cmd-api-server/package.json b/packages/cactus-cmd-api-server/package.json index 24cd3e58391..7180fc73e54 100644 --- a/packages/cactus-cmd-api-server/package.json +++ b/packages/cactus-cmd-api-server/package.json @@ -74,7 +74,7 @@ "@hyperledger/cactus-core-api": "2.0.0-rc.3", "@thream/socketio-jwt": "2.1.1", "async-exit-hook": "2.0.1", - "axios": "1.7.2", + "axios": "1.7.5", "bluebird": "3.7.2", "body-parser": "1.20.2", "compression": "1.7.4", diff --git a/packages/cactus-core-api/package.json b/packages/cactus-core-api/package.json index 2f06a3155e1..bcf26eece0b 100644 --- a/packages/cactus-core-api/package.json +++ b/packages/cactus-core-api/package.json @@ -62,7 +62,7 @@ "dependencies": { "@grpc/grpc-js": "1.11.1", "@hyperledger/cactus-common": "2.0.0-rc.3", - "axios": "1.7.2", + "axios": "1.7.5", "google-protobuf": "3.21.4" }, "devDependencies": { diff --git a/packages/cactus-plugin-bungee-hermes/package.json b/packages/cactus-plugin-bungee-hermes/package.json index 986dbbc8a32..15942e71b7d 100644 --- a/packages/cactus-plugin-bungee-hermes/package.json +++ b/packages/cactus-plugin-bungee-hermes/package.json @@ -66,7 +66,7 @@ "@hyperledger/cactus-plugin-ledger-connector-besu": "2.0.0-rc.3", "@hyperledger/cactus-plugin-ledger-connector-ethereum": "2.0.0-rc.3", "@hyperledger/cactus-plugin-ledger-connector-fabric": "2.0.0-rc.3", - "axios": "1.7.2", + "axios": "1.7.5", "body-parser": "1.20.2", "fs-extra": "11.2.0", "http-errors-enhanced-cjs": "2.0.1", diff --git a/packages/cactus-plugin-consortium-manual/package.json b/packages/cactus-plugin-consortium-manual/package.json index 70256ed616e..bca3f0235d4 100644 --- a/packages/cactus-plugin-consortium-manual/package.json +++ b/packages/cactus-plugin-consortium-manual/package.json @@ -59,7 +59,7 @@ "@hyperledger/cactus-common": "2.0.0-rc.3", "@hyperledger/cactus-core": "2.0.0-rc.3", "@hyperledger/cactus-core-api": "2.0.0-rc.3", - "axios": "1.6.0", + "axios": "1.7.5", "body-parser": "1.20.2", "express": "4.19.2", "jose": "4.15.5", diff --git a/packages/cactus-plugin-htlc-eth-besu-erc20/package.json b/packages/cactus-plugin-htlc-eth-besu-erc20/package.json index 6d2c688435f..84fb8adfde3 100644 --- a/packages/cactus-plugin-htlc-eth-besu-erc20/package.json +++ b/packages/cactus-plugin-htlc-eth-besu-erc20/package.json @@ -65,7 +65,7 @@ "@hyperledger/cactus-core": "2.0.0-rc.3", "@hyperledger/cactus-core-api": "2.0.0-rc.3", "@hyperledger/cactus-plugin-ledger-connector-besu": "2.0.0-rc.3", - "axios": "1.6.0", + "axios": "1.7.5", "express": "4.19.2", "joi": "17.13.3", "openapi-types": "12.1.3", diff --git a/packages/cactus-plugin-htlc-eth-besu/package.json b/packages/cactus-plugin-htlc-eth-besu/package.json index b023f506629..a4e663bacd2 100644 --- a/packages/cactus-plugin-htlc-eth-besu/package.json +++ b/packages/cactus-plugin-htlc-eth-besu/package.json @@ -73,7 +73,7 @@ "@hyperledger/cactus-plugin-keychain-memory": "2.0.0-rc.3", "@hyperledger/cactus-plugin-ledger-connector-besu": "2.0.0-rc.3", "@hyperledger/cactus-test-tooling": "2.0.0-rc.3", - "axios": "1.6.0", + "axios": "1.7.5", "bn.js": "5.2.1", "dotenv": "16.0.3", "ethers": "6.3.0", diff --git a/packages/cactus-plugin-keychain-aws-sm/package.json b/packages/cactus-plugin-keychain-aws-sm/package.json index 6f50c2e476c..af4422b6212 100644 --- a/packages/cactus-plugin-keychain-aws-sm/package.json +++ b/packages/cactus-plugin-keychain-aws-sm/package.json @@ -60,7 +60,7 @@ "@hyperledger/cactus-core": "2.0.0-rc.3", "@hyperledger/cactus-core-api": "2.0.0-rc.3", "aws-sdk": "2.965.0", - "axios": "1.6.0", + "axios": "1.7.5", "http-status-codes": "2.1.4", "prom-client": "15.1.3", "typescript-optional": "2.0.1" diff --git a/packages/cactus-plugin-keychain-azure-kv/package.json b/packages/cactus-plugin-keychain-azure-kv/package.json index 8abe0f2955b..989c3d42a09 100644 --- a/packages/cactus-plugin-keychain-azure-kv/package.json +++ b/packages/cactus-plugin-keychain-azure-kv/package.json @@ -66,7 +66,7 @@ "@hyperledger/cactus-common": "2.0.0-rc.3", "@hyperledger/cactus-core": "2.0.0-rc.3", "@hyperledger/cactus-core-api": "2.0.0-rc.3", - "axios": "1.7.2", + "axios": "1.7.5", "http-status-codes": "2.1.4", "typescript-optional": "2.0.1" }, diff --git a/packages/cactus-plugin-keychain-google-sm/package.json b/packages/cactus-plugin-keychain-google-sm/package.json index 5fd37285ed6..e7fa709eadc 100644 --- a/packages/cactus-plugin-keychain-google-sm/package.json +++ b/packages/cactus-plugin-keychain-google-sm/package.json @@ -60,7 +60,7 @@ "@hyperledger/cactus-common": "2.0.0-rc.3", "@hyperledger/cactus-core": "2.0.0-rc.3", "@hyperledger/cactus-core-api": "2.0.0-rc.3", - "axios": "1.6.0", + "axios": "1.7.5", "http-status-codes": "2.1.4", "typescript-optional": "2.0.1", "uuid": "10.0.0" diff --git a/packages/cactus-plugin-keychain-memory-wasm/package.json b/packages/cactus-plugin-keychain-memory-wasm/package.json index a3679e58a34..ba43f9d0615 100644 --- a/packages/cactus-plugin-keychain-memory-wasm/package.json +++ b/packages/cactus-plugin-keychain-memory-wasm/package.json @@ -64,7 +64,7 @@ "@hyperledger/cactus-common": "2.0.0-rc.3", "@hyperledger/cactus-core": "2.0.0-rc.3", "@hyperledger/cactus-core-api": "2.0.0-rc.3", - "axios": "1.6.0", + "axios": "1.7.5", "express": "4.19.2", "prom-client": "15.1.3", "uuid": "10.0.0" diff --git a/packages/cactus-plugin-keychain-memory/package.json b/packages/cactus-plugin-keychain-memory/package.json index a95b20b2df1..bbd2824bc6a 100644 --- a/packages/cactus-plugin-keychain-memory/package.json +++ b/packages/cactus-plugin-keychain-memory/package.json @@ -64,7 +64,7 @@ "@hyperledger/cactus-common": "2.0.0-rc.3", "@hyperledger/cactus-core": "2.0.0-rc.3", "@hyperledger/cactus-core-api": "2.0.0-rc.3", - "axios": "1.6.0", + "axios": "1.7.5", "express": "4.19.2", "prom-client": "15.1.3", "rxjs": "7.8.1", diff --git a/packages/cactus-plugin-keychain-vault/package.json b/packages/cactus-plugin-keychain-vault/package.json index 45d27eac9ba..6f1dcc78d50 100644 --- a/packages/cactus-plugin-keychain-vault/package.json +++ b/packages/cactus-plugin-keychain-vault/package.json @@ -59,7 +59,7 @@ "@hyperledger/cactus-common": "2.0.0-rc.3", "@hyperledger/cactus-core": "2.0.0-rc.3", "@hyperledger/cactus-core-api": "2.0.0-rc.3", - "axios": "1.6.0", + "axios": "1.7.5", "http-status-codes": "2.1.4", "node-vault": "0.9.22", "prom-client": "15.1.3", diff --git a/packages/cactus-plugin-ledger-connector-aries/package.json b/packages/cactus-plugin-ledger-connector-aries/package.json index 4b444826f94..2480ba8598f 100644 --- a/packages/cactus-plugin-ledger-connector-aries/package.json +++ b/packages/cactus-plugin-ledger-connector-aries/package.json @@ -68,7 +68,7 @@ "@hyperledger/cactus-core": "2.0.0-rc.3", "@hyperledger/cactus-core-api": "2.0.0-rc.3", "@hyperledger/indy-vdr-nodejs": "0.2.0", - "axios": "1.7.2", + "axios": "1.7.5", "rxjs": "7.8.1", "socket.io-client-fixed-types": "4.5.4" }, diff --git a/packages/cactus-plugin-ledger-connector-besu/package.json b/packages/cactus-plugin-ledger-connector-besu/package.json index 4515193d633..12e5f64274d 100644 --- a/packages/cactus-plugin-ledger-connector-besu/package.json +++ b/packages/cactus-plugin-ledger-connector-besu/package.json @@ -63,7 +63,7 @@ "@hyperledger/cactus-common": "2.0.0-rc.3", "@hyperledger/cactus-core": "2.0.0-rc.3", "@hyperledger/cactus-core-api": "2.0.0-rc.3", - "axios": "1.7.2", + "axios": "1.7.5", "express": "4.19.2", "google-protobuf": "3.21.4", "http-errors": "2.0.0", diff --git a/packages/cactus-plugin-ledger-connector-cdl/package.json b/packages/cactus-plugin-ledger-connector-cdl/package.json index 1a932ce5e46..bca4361ac6a 100644 --- a/packages/cactus-plugin-ledger-connector-cdl/package.json +++ b/packages/cactus-plugin-ledger-connector-cdl/package.json @@ -58,7 +58,7 @@ "@hyperledger/cactus-common": "2.0.0-rc.3", "@hyperledger/cactus-core": "2.0.0-rc.3", "@hyperledger/cactus-core-api": "2.0.0-rc.3", - "axios": "1.6.0", + "axios": "1.7.5", "sanitize-html": "2.12.1" }, "devDependencies": { diff --git a/packages/cactus-plugin-ledger-connector-corda/package.json b/packages/cactus-plugin-ledger-connector-corda/package.json index 2fbcec0150a..14bf9ce56ec 100644 --- a/packages/cactus-plugin-ledger-connector-corda/package.json +++ b/packages/cactus-plugin-ledger-connector-corda/package.json @@ -60,7 +60,7 @@ "@hyperledger/cactus-common": "2.0.0-rc.3", "@hyperledger/cactus-core": "2.0.0-rc.3", "@hyperledger/cactus-core-api": "2.0.0-rc.3", - "axios": "1.6.0", + "axios": "1.7.5", "express": "4.19.2", "express-openapi-validator": "5.2.0", "http-errors-enhanced-cjs": "2.0.1", diff --git a/packages/cactus-plugin-ledger-connector-ethereum/package.json b/packages/cactus-plugin-ledger-connector-ethereum/package.json index 2f2ffe6af11..5b851a0224c 100644 --- a/packages/cactus-plugin-ledger-connector-ethereum/package.json +++ b/packages/cactus-plugin-ledger-connector-ethereum/package.json @@ -71,7 +71,7 @@ "@hyperledger/cactus-common": "2.0.0-rc.3", "@hyperledger/cactus-core": "2.0.0-rc.3", "@hyperledger/cactus-core-api": "2.0.0-rc.3", - "axios": "1.7.2", + "axios": "1.7.5", "ethers": "6.8.1", "express": "4.19.2", "http-proxy-middleware": "2.0.6", diff --git a/packages/cactus-plugin-ledger-connector-fabric/package.json b/packages/cactus-plugin-ledger-connector-fabric/package.json index 791b6b6665b..5d04f467644 100644 --- a/packages/cactus-plugin-ledger-connector-fabric/package.json +++ b/packages/cactus-plugin-ledger-connector-fabric/package.json @@ -60,7 +60,7 @@ "@hyperledger/cactus-common": "2.0.0-rc.3", "@hyperledger/cactus-core": "2.0.0-rc.3", "@hyperledger/cactus-core-api": "2.0.0-rc.3", - "axios": "1.7.2", + "axios": "1.7.5", "bl": "6.0.12", "bn.js": "4.12.0", "elliptic": "6.5.4", diff --git a/packages/cactus-plugin-ledger-connector-iroha2/package.json b/packages/cactus-plugin-ledger-connector-iroha2/package.json index 31e71536032..5722a7d4baa 100644 --- a/packages/cactus-plugin-ledger-connector-iroha2/package.json +++ b/packages/cactus-plugin-ledger-connector-iroha2/package.json @@ -54,7 +54,7 @@ "@iroha2/crypto-core": "0.1.1", "@iroha2/crypto-target-node": "0.4.0", "@iroha2/data-model": "4.0.0", - "axios": "1.7.2", + "axios": "1.7.5", "express": "4.19.2", "fast-safe-stringify": "2.1.1", "hada": "0.0.8", diff --git a/packages/cactus-plugin-ledger-connector-polkadot/package.json b/packages/cactus-plugin-ledger-connector-polkadot/package.json index f8fe4ef3e7b..51f4b16b5bf 100644 --- a/packages/cactus-plugin-ledger-connector-polkadot/package.json +++ b/packages/cactus-plugin-ledger-connector-polkadot/package.json @@ -73,7 +73,7 @@ "@polkadot/rpc-provider": "10.9.1", "@polkadot/types": "10.9.1", "@polkadot/util": "12.6.2", - "axios": "1.6.0", + "axios": "1.7.5", "bl": "6.0.0", "express": "4.19.2", "express-openapi-validator": "5.2.0", diff --git a/packages/cactus-plugin-ledger-connector-sawtooth/package.json b/packages/cactus-plugin-ledger-connector-sawtooth/package.json index 27c485c5f63..d8d1a74f133 100644 --- a/packages/cactus-plugin-ledger-connector-sawtooth/package.json +++ b/packages/cactus-plugin-ledger-connector-sawtooth/package.json @@ -59,7 +59,7 @@ "@hyperledger/cactus-common": "2.0.0-rc.3", "@hyperledger/cactus-core": "2.0.0-rc.3", "@hyperledger/cactus-core-api": "2.0.0-rc.3", - "axios": "1.7.2", + "axios": "1.7.5", "cbor": "9.0.1", "rxjs": "7.8.1", "socket.io-client-fixed-types": "4.5.4" diff --git a/packages/cactus-plugin-ledger-connector-xdai/package.json b/packages/cactus-plugin-ledger-connector-xdai/package.json index 674492c262b..74202488d66 100644 --- a/packages/cactus-plugin-ledger-connector-xdai/package.json +++ b/packages/cactus-plugin-ledger-connector-xdai/package.json @@ -58,7 +58,7 @@ "@hyperledger/cactus-common": "2.0.0-rc.3", "@hyperledger/cactus-core": "2.0.0-rc.3", "@hyperledger/cactus-core-api": "2.0.0-rc.3", - "axios": "1.6.0", + "axios": "1.7.5", "express": "4.19.2", "joi": "17.13.3", "openapi-types": "12.1.3", diff --git a/packages/cactus-plugin-persistence-ethereum/package.json b/packages/cactus-plugin-persistence-ethereum/package.json index a4ebffe3380..1a04db00144 100644 --- a/packages/cactus-plugin-persistence-ethereum/package.json +++ b/packages/cactus-plugin-persistence-ethereum/package.json @@ -67,7 +67,7 @@ "@hyperledger/cactus-core-api": "2.0.0-rc.3", "@hyperledger/cactus-plugin-ledger-connector-ethereum": "2.0.0-rc.3", "async-mutex": "0.4.0", - "axios": "1.7.2", + "axios": "1.7.5", "pg": "8.8.0", "run-time-error-cjs": "1.4.0", "uuid": "10.0.0", diff --git a/packages/cactus-plugin-persistence-fabric/package.json b/packages/cactus-plugin-persistence-fabric/package.json index 0bf022be3e8..80d22efac27 100644 --- a/packages/cactus-plugin-persistence-fabric/package.json +++ b/packages/cactus-plugin-persistence-fabric/package.json @@ -67,7 +67,7 @@ "@hyperledger/cactus-core-api": "2.0.0-rc.3", "@hyperledger/cactus-plugin-ledger-connector-fabric": "2.0.0-rc.3", "async-mutex": "0.4.0", - "axios": "1.7.2", + "axios": "1.7.5", "pg": "8.8.0", "run-time-error-cjs": "1.4.0", "uuid": "10.0.0" diff --git a/packages/cactus-plugin-satp-hermes/package.json b/packages/cactus-plugin-satp-hermes/package.json index 3ee1fa3c153..d95612d63cc 100644 --- a/packages/cactus-plugin-satp-hermes/package.json +++ b/packages/cactus-plugin-satp-hermes/package.json @@ -59,7 +59,7 @@ "@hyperledger/cactus-plugin-ledger-connector-fabric": "2.0.0-rc.3", "@hyperledger/cactus-plugin-object-store-ipfs": "2.0.0-rc.3", "@hyperledger/cactus-test-tooling": "2.0.0-rc.3", - "axios": "1.7.2", + "axios": "1.7.5", "crypto-js": "4.2.0", "fs-extra": "11.2.0", "knex": "2.4.0", diff --git a/packages/cactus-test-plugin-consortium-manual/package.json b/packages/cactus-test-plugin-consortium-manual/package.json index a71b1aa34f0..031a37efbfe 100644 --- a/packages/cactus-test-plugin-consortium-manual/package.json +++ b/packages/cactus-test-plugin-consortium-manual/package.json @@ -56,7 +56,7 @@ "@hyperledger/cactus-core-api": "2.0.0-rc.3", "@hyperledger/cactus-plugin-consortium-manual": "2.0.0-rc.3", "@hyperledger/cactus-plugin-keychain-memory": "2.0.0-rc.3", - "axios": "1.6.0", + "axios": "1.7.5", "jose": "4.15.5" }, "devDependencies": { diff --git a/packages/cactus-test-plugin-htlc-eth-besu-erc20/package.json b/packages/cactus-test-plugin-htlc-eth-besu-erc20/package.json index 31ac42733ad..334572555e9 100644 --- a/packages/cactus-test-plugin-htlc-eth-besu-erc20/package.json +++ b/packages/cactus-test-plugin-htlc-eth-besu-erc20/package.json @@ -58,7 +58,7 @@ "@hyperledger/cactus-plugin-keychain-memory": "2.0.0-rc.3", "@hyperledger/cactus-plugin-ledger-connector-besu": "2.0.0-rc.3", "@hyperledger/cactus-test-tooling": "2.0.0-rc.3", - "axios": "1.6.0", + "axios": "1.7.5", "express": "4.19.2", "web3-eth-abi": "4.0.3", "web3-utils": "4.2.1" diff --git a/packages/cactus-test-plugin-htlc-eth-besu/package.json b/packages/cactus-test-plugin-htlc-eth-besu/package.json index ac9d60fd1b1..53cf7751db0 100644 --- a/packages/cactus-test-plugin-htlc-eth-besu/package.json +++ b/packages/cactus-test-plugin-htlc-eth-besu/package.json @@ -58,7 +58,7 @@ "@hyperledger/cactus-plugin-keychain-memory": "2.0.0-rc.3", "@hyperledger/cactus-plugin-ledger-connector-besu": "2.0.0-rc.3", "@hyperledger/cactus-test-tooling": "2.0.0-rc.3", - "axios": "1.6.0", + "axios": "1.7.5", "key-encoder": "2.0.3", "web3": "1.6.1", "web3js-quorum": "22.4.0" diff --git a/packages/cactus-test-plugin-ledger-connector-besu/package.json b/packages/cactus-test-plugin-ledger-connector-besu/package.json index 448ab095e8a..ce2edeb15f0 100644 --- a/packages/cactus-test-plugin-ledger-connector-besu/package.json +++ b/packages/cactus-test-plugin-ledger-connector-besu/package.json @@ -67,7 +67,7 @@ "devDependencies": { "@types/express": "4.17.21", "@types/uuid": "10.0.0", - "axios": "1.7.2", + "axios": "1.7.5", "express": "4.19.2", "uuid": "10.0.0", "web3-core": "1.6.1" diff --git a/packages/cactus-test-tooling/package.json b/packages/cactus-test-tooling/package.json index f0d49e8d694..5430911b1df 100644 --- a/packages/cactus-test-tooling/package.json +++ b/packages/cactus-test-tooling/package.json @@ -66,7 +66,7 @@ }, "dependencies": { "@hyperledger/cactus-common": "2.0.0-rc.3", - "axios": "1.7.2", + "axios": "1.7.5", "compare-versions": "3.6.0", "dockerode": "3.3.0", "elliptic": "6.5.4", diff --git a/yarn.lock b/yarn.lock index cd9906a5a14..3bd5600caff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9048,7 +9048,7 @@ __metadata: "@types/react": "npm:^18.2.39" "@types/react-dom": "npm:^18.2.17" "@types/uuid": "npm:10.0.0" - axios: "npm:1.6.0" + axios: "npm:1.7.5" react: "npm:^18.2.0" react-dom: "npm:^18.2.0" react-scripts: "npm:5.0.1" @@ -9101,7 +9101,7 @@ __metadata: "@types/express": "npm:4.17.21" "@types/json-stable-stringify": "npm:1.0.33" "@types/uuid": "npm:10.0.0" - axios: "npm:1.6.0" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" express: "npm:4.19.2" http-errors-enhanced-cjs: "npm:2.0.1" @@ -9128,7 +9128,7 @@ __metadata: "@types/express": "npm:4.17.21" "@types/http-errors": "npm:2.0.4" "@types/uuid": "npm:10.0.0" - axios: "npm:1.7.2" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" express: "npm:4.19.2" http-errors-enhanced-cjs: "npm:2.0.1" @@ -9418,7 +9418,7 @@ __metadata: "@types/xml2js": "npm:0.4.9" "@vercel/ncc": "npm:0.38.1" async-exit-hook: "npm:2.0.1" - axios: "npm:1.7.2" + axios: "npm:1.7.5" benchmark: "npm:2.1.4" bluebird: "npm:3.7.2" body-parser: "npm:1.20.2" @@ -9546,7 +9546,7 @@ __metadata: "@hyperledger/cactus-common": "npm:2.0.0-rc.3" "@types/express": "npm:4.17.21" "@types/google-protobuf": "npm:3.15.5" - axios: "npm:1.7.2" + axios: "npm:1.7.5" google-protobuf: "npm:3.21.4" grpc-tools: "npm:1.12.4" grpc_tools_node_protoc_ts: "npm:5.3.3" @@ -9636,7 +9636,7 @@ __metadata: "@types/ssh2": "npm:0.5.47" "@types/uuid": "npm:10.0.0" async-exit-hook: "npm:2.0.1" - axios: "npm:1.6.0" + axios: "npm:1.7.5" express: "npm:4.19.2" openapi-types: "npm:12.1.3" typescript-optional: "npm:2.0.1" @@ -9710,7 +9710,7 @@ __metadata: "@types/node": "npm:18.11.9" "@types/uuid": "npm:10.0.0" async-exit-hook: "npm:2.0.1" - axios: "npm:1.6.0" + axios: "npm:1.7.5" crypto-js: "npm:4.2.0" cucumber: "npm:5.0.3" dotenv: "npm:16.0.1" @@ -9748,7 +9748,7 @@ __metadata: "@hyperledger/aries-askar-nodejs": "npm:0.2.0" "@hyperledger/indy-vdr-nodejs": "npm:0.2.0" "@types/inquirer": "npm:8.2.6" - axios: "npm:1.6.0" + axios: "npm:1.7.5" inquirer: "npm:8.2.6" loglevel: "npm:1.8.1" bin: @@ -9776,7 +9776,7 @@ __metadata: "@types/jsrsasign": "npm:10.5.8" "@types/node": "npm:18.11.9" "@types/uuid": "npm:10.0.0" - axios: "npm:1.7.2" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" cookie-parser: "npm:1.4.6" debug: "npm:3.1.0" @@ -9860,7 +9860,7 @@ __metadata: "@types/express": "npm:4.17.21" "@types/uuid": "npm:10.0.0" async-exit-hook: "npm:2.0.1" - axios: "npm:1.6.0" + axios: "npm:1.7.5" dotenv: "npm:16.0.0" express: "npm:4.19.2" express-jwt: "npm:8.4.1" @@ -9891,7 +9891,7 @@ __metadata: "@types/ssh2": "npm:0.5.47" "@types/uuid": "npm:10.0.0" async-exit-hook: "npm:2.0.1" - axios: "npm:1.6.0" + axios: "npm:1.7.5" express: "npm:4.19.2" openapi-types: "npm:12.1.3" run-time-error-cjs: "npm:1.4.0" @@ -9964,7 +9964,7 @@ __metadata: "@types/fs-extra": "npm:11.0.4" "@types/tape": "npm:4.13.4" "@types/uuid": "npm:10.0.0" - axios: "npm:1.7.2" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" express: "npm:4.19.2" fabric-network: "npm:2.2.20" @@ -9990,7 +9990,7 @@ __metadata: "@types/express": "npm:4.17.21" "@types/json-stable-stringify": "npm:1.0.33" "@types/uuid": "npm:10.0.0" - axios: "npm:1.6.0" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" express: "npm:4.19.2" jose: "npm:4.15.5" @@ -10016,7 +10016,7 @@ __metadata: "@hyperledger/cactus-test-tooling": "npm:2.0.0-rc.3" "@types/express": "npm:4.17.21" "@types/uuid": "npm:10.0.0" - axios: "npm:1.7.2" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" express: "npm:4.19.2" fast-safe-stringify: "npm:2.1.1" @@ -10042,7 +10042,7 @@ __metadata: "@hyperledger/cactus-core-api": "npm:2.0.0-rc.3" "@hyperledger/cactus-plugin-ledger-connector-besu": "npm:2.0.0-rc.3" "@types/express": "npm:4.17.21" - axios: "npm:1.6.0" + axios: "npm:1.7.5" express: "npm:4.19.2" joi: "npm:17.13.3" openapi-types: "npm:12.1.3" @@ -10061,7 +10061,7 @@ __metadata: "@hyperledger/cactus-plugin-ledger-connector-besu": "npm:2.0.0-rc.3" "@hyperledger/cactus-test-tooling": "npm:2.0.0-rc.3" "@types/express": "npm:4.17.21" - axios: "npm:1.6.0" + axios: "npm:1.7.5" bn.js: "npm:5.2.1" dotenv: "npm:16.0.3" ds-test: "https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0" @@ -10088,7 +10088,7 @@ __metadata: "@types/request": "npm:2.48.7" "@types/uuid": "npm:10.0.0" aws-sdk: "npm:2.965.0" - axios: "npm:1.6.0" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" express: "npm:4.19.2" http-status-codes: "npm:2.1.4" @@ -10113,7 +10113,7 @@ __metadata: "@types/body-parser": "npm:1.19.4" "@types/express": "npm:4.17.21" "@types/request": "npm:2.48.7" - axios: "npm:1.7.2" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" express: "npm:4.19.2" http-status-codes: "npm:2.1.4" @@ -10137,7 +10137,7 @@ __metadata: "@types/express": "npm:4.17.21" "@types/request": "npm:2.48.7" "@types/uuid": "npm:10.0.0" - axios: "npm:1.6.0" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" express: "npm:4.19.2" google-gax: "npm:4.0.5" @@ -10158,7 +10158,7 @@ __metadata: "@hyperledger/cactus-core-api": "npm:2.0.0-rc.3" "@types/body-parser": "npm:1.19.4" "@types/express": "npm:4.17.21" - axios: "npm:1.6.0" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" cpy-cli: "npm:4.2.0" del-cli: "npm:5.1.0" @@ -10182,7 +10182,7 @@ __metadata: "@hyperledger/cactus-core-api": "npm:2.0.0-rc.3" "@types/body-parser": "npm:1.19.4" "@types/express": "npm:4.17.21" - axios: "npm:1.6.0" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" express: "npm:4.19.2" npm-run-all2: "npm:6.1.2" @@ -10206,7 +10206,7 @@ __metadata: "@types/request": "npm:2.48.7" "@types/tape-promise": "npm:4.0.1" "@types/uuid": "npm:10.0.0" - axios: "npm:1.6.0" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" express: "npm:4.19.2" http-status-codes: "npm:2.1.4" @@ -10239,7 +10239,7 @@ __metadata: "@types/body-parser": "npm:1.19.4" "@types/express": "npm:4.17.21" "@types/uuid": "npm:10.0.0" - axios: "npm:1.7.2" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" express: "npm:4.19.2" jest: "npm:29.6.2" @@ -10269,7 +10269,7 @@ __metadata: "@types/google-protobuf": "npm:3.15.5" "@types/http-errors": "npm:2.0.4" "@types/uuid": "npm:10.0.0" - axios: "npm:1.7.2" + axios: "npm:1.7.5" benchmark: "npm:2.1.4" body-parser: "npm:1.20.2" express: "npm:4.19.2" @@ -10311,7 +10311,7 @@ __metadata: "@types/express": "npm:4.17.21" "@types/node": "npm:18.11.9" "@types/sanitize-html": "npm:2.6.2" - axios: "npm:1.6.0" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" express: "npm:4.19.2" jest-extended: "npm:4.0.1" @@ -10333,7 +10333,7 @@ __metadata: "@types/multer": "npm:1.4.7" "@types/temp": "npm:0.9.1" "@types/uuid": "npm:10.0.0" - axios: "npm:1.6.0" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" express: "npm:4.19.2" express-openapi-validator: "npm:5.2.0" @@ -10369,7 +10369,7 @@ __metadata: "@types/minimist": "npm:1.2.2" "@types/sanitize-html": "npm:2.9.5" "@types/uuid": "npm:10.0.0" - axios: "npm:1.7.2" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" chalk: "npm:4.1.2" ethers: "npm:6.8.1" @@ -10415,7 +10415,7 @@ __metadata: "@types/sanitize-html": "npm:2.9.5" "@types/temp": "npm:0.9.1" "@types/uuid": "npm:10.0.0" - axios: "npm:1.7.2" + axios: "npm:1.7.5" bl: "npm:6.0.12" bn.js: "npm:4.12.0" body-parser: "npm:1.20.2" @@ -10468,7 +10468,7 @@ __metadata: "@iroha2/data-model": "npm:4.0.0" "@types/express": "npm:4.17.21" "@types/sanitize-html": "npm:2.9.5" - axios: "npm:1.7.2" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" express: "npm:4.19.2" fast-safe-stringify: "npm:2.1.1" @@ -10505,7 +10505,7 @@ __metadata: "@types/supertest": "npm:2.0.11" "@types/temp": "npm:0.9.1" "@types/uuid": "npm:10.0.0" - axios: "npm:1.6.0" + axios: "npm:1.7.5" bl: "npm:6.0.0" express: "npm:4.19.2" express-openapi-validator: "npm:5.2.0" @@ -10537,7 +10537,7 @@ __metadata: "@hyperledger/cactus-test-tooling": "npm:2.0.0-rc.3" "@types/express": "npm:4.17.21" "@types/uuid": "npm:10.0.0" - axios: "npm:1.7.2" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" cbor: "npm:9.0.1" express: "npm:4.19.2" @@ -10559,7 +10559,7 @@ __metadata: "@hyperledger/cactus-test-tooling": "npm:2.0.0-rc.3" "@types/body-parser": "npm:1.19.4" "@types/express": "npm:4.17.21" - axios: "npm:1.6.0" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" express: "npm:4.19.2" joi: "npm:17.13.3" @@ -10587,7 +10587,7 @@ __metadata: "@multiformats/multiaddr": "npm:11.6.1" "@types/body-parser": "npm:1.19.4" "@types/express": "npm:4.17.21" - axios: "npm:1.6.0" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" express: "npm:4.19.2" ipfs-core-types: "npm:0.14.1" @@ -10618,7 +10618,7 @@ __metadata: "@types/express": "npm:4.17.21" "@types/pg": "npm:8.6.5" async-mutex: "npm:0.4.0" - axios: "npm:1.7.2" + axios: "npm:1.7.5" body-parser: "npm:1.19.0" express: "npm:4.19.2" jest-extended: "npm:4.0.1" @@ -10650,7 +10650,7 @@ __metadata: "@types/express": "npm:4.17.21" "@types/pg": "npm:8.6.5" async-mutex: "npm:0.4.0" - axios: "npm:1.7.2" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" express: "npm:4.19.2" fabric-network: "npm:2.5.0-snapshot.23" @@ -10682,7 +10682,7 @@ __metadata: "@types/fs-extra": "npm:11.0.4" "@types/tape": "npm:4.13.4" "@types/uuid": "npm:10.0.0" - axios: "npm:1.7.2" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" crypto-js: "npm:4.2.0" express: "npm:4.19.2" @@ -10763,7 +10763,7 @@ __metadata: "@hyperledger/cactus-plugin-consortium-manual": "npm:2.0.0-rc.3" "@hyperledger/cactus-plugin-keychain-memory": "npm:2.0.0-rc.3" "@types/uuid": "npm:10.0.0" - axios: "npm:1.6.0" + axios: "npm:1.7.5" jose: "npm:4.15.5" uuid: "npm:10.0.0" languageName: unknown @@ -10784,7 +10784,7 @@ __metadata: "@types/body-parser": "npm:1.19.4" "@types/express": "npm:4.17.21" "@types/uuid": "npm:10.0.0" - axios: "npm:1.6.0" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" express: "npm:4.19.2" uuid: "npm:10.0.0" @@ -10808,7 +10808,7 @@ __metadata: "@types/body-parser": "npm:1.19.4" "@types/express": "npm:4.17.21" "@types/uuid": "npm:10.0.0" - axios: "npm:1.6.0" + axios: "npm:1.7.5" body-parser: "npm:1.20.2" express: "npm:4.19.2" key-encoder: "npm:2.0.3" @@ -10850,7 +10850,7 @@ __metadata: "@hyperledger/cactus-verifier-client": "npm:2.0.0-rc.3" "@types/express": "npm:4.17.21" "@types/uuid": "npm:10.0.0" - axios: "npm:1.7.2" + axios: "npm:1.7.5" express: "npm:4.19.2" key-encoder: "npm:2.0.3" socket.io: "npm:4.6.2" @@ -10905,7 +10905,7 @@ __metadata: "@types/ssh2-streams": "npm:0.1.9" "@types/tar-stream": "npm:2.2.1" "@types/temp": "npm:0.9.1" - axios: "npm:1.7.2" + axios: "npm:1.7.5" compare-versions: "npm:3.6.0" dockerode: "npm:3.3.0" elliptic: "npm:6.5.4" From 957da7c3e1d80068391485a825ba6bb1e68333ac Mon Sep 17 00:00:00 2001 From: Peter Somogyvari Date: Mon, 26 Aug 2024 19:19:18 -0700 Subject: [PATCH 8/8] feat(core-api): add createIsJwsGeneralTypeGuard, createAjvTypeGuard 1. createAjvTypeGuard() is the lower level utility which can be used to construct the more convenient, higher level type predicates/type guards such as createIsJwsGeneralTypeGuard() which uses createAjvTypeGuard under the hood. 2. This commit is also meant to be establishing a larger, more generic pattern of us being able to create type guards out of the Open API specs in a convenient way instead of having to write the validation code by hand. An example usage of the new createAjvTypeGuard() utility is the createIsJwsGeneralTypeGuard() function itself. An example usage of the new createIsJwsGeneralTypeGuard() can be found in packages/cactus-plugin-consortium-manual/src/main/typescript/plugin-consortium-manual.ts The code documentation contains examples as well for maximum discoverabilty and I'll also include it here: ```typescript import { JWSGeneral } from "@hyperledger/cactus-core-api"; import { createIsJwsGeneralTypeGuard } from "@hyperledger/cactus-core-api"; export class PluginConsortiumManual { private readonly isJwsGeneral: (x: unknown) => x is JWSGeneral; constructor() { // Creating the type-guard function is relatively costly due to the Ajv schema // compilation that needs to happen as part of it so it is good practice to // cache the type-guard function as much as possible, for examle by adding it // as a class member on a long-lived object such as a plugin instance which is // expected to match the life-cycle of the API server NodeJS process itself. // The specific anti-pattern would be to create a new type-guard function // for each request received by a plugin as this would affect performance // negatively. this.isJwsGeneral = createIsJwsGeneralTypeGuard(); } public async getNodeJws(): Promise { // rest of the implementation that produces a JWS ... const jws = await joseGeneralSign.sign(); if (!this.isJwsGeneral(jws)) { throw new TypeError("Jose GeneralSign.sign() gave non-JWSGeneral type"); } return jws; } } ``` Relevant discussion took place here: https://github.com/hyperledger/cacti/pull/3471#discussion_r1731894747 Signed-off-by: Peter Somogyvari --- packages/cactus-core-api/package.json | 3 + .../open-api/create-ajv-type-guard.ts | 66 +++++++++++++++++++ .../create-is-jws-general-type-guard.ts | 61 +++++++++++++++++ .../src/main/typescript/public-api.ts | 3 + .../open-api/create-ajv-type-guard.test.ts | 36 ++++++++++ .../create-is-jws-general-type-guard.test.ts | 25 +++++++ .../typescript/plugin-consortium-manual.ts | 19 ++++-- yarn.lock | 43 ++++++++---- 8 files changed, 238 insertions(+), 18 deletions(-) create mode 100644 packages/cactus-core-api/src/main/typescript/open-api/create-ajv-type-guard.ts create mode 100644 packages/cactus-core-api/src/main/typescript/open-api/create-is-jws-general-type-guard.ts create mode 100644 packages/cactus-core-api/src/test/typescript/unit/open-api/create-ajv-type-guard.test.ts create mode 100644 packages/cactus-core-api/src/test/typescript/unit/open-api/create-is-jws-general-type-guard.test.ts diff --git a/packages/cactus-core-api/package.json b/packages/cactus-core-api/package.json index bcf26eece0b..9ef936270b9 100644 --- a/packages/cactus-core-api/package.json +++ b/packages/cactus-core-api/package.json @@ -62,6 +62,9 @@ "dependencies": { "@grpc/grpc-js": "1.11.1", "@hyperledger/cactus-common": "2.0.0-rc.3", + "ajv": "8.17.1", + "ajv-draft-04": "1.0.0", + "ajv-formats": "3.0.1", "axios": "1.7.5", "google-protobuf": "3.21.4" }, diff --git a/packages/cactus-core-api/src/main/typescript/open-api/create-ajv-type-guard.ts b/packages/cactus-core-api/src/main/typescript/open-api/create-ajv-type-guard.ts new file mode 100644 index 00000000000..e1b292d6aa1 --- /dev/null +++ b/packages/cactus-core-api/src/main/typescript/open-api/create-ajv-type-guard.ts @@ -0,0 +1,66 @@ +import type { ValidateFunction } from "ajv"; + +/** + * Creates a TypeScript type guard based on an `ajv` validator. + * + * @template T The type of the data that the validator expects. This can be + * one of the data model types that we generate from the OpenAPI specifications. + * It could also be a schema that you defined in your code directly, but that is + * not recommended since if you are going to define a schema then it's best to + * do so within the Open API specification file(s) (`openapi.tpl.json` files). + * + * @param {ValidateFunction} validator An `ajv` validator that validates data against a specific JSON schema. + * You must make sure that this parameter was indeed constructed to validate the + * specific `T` type that you are intending it for. See the example below for + * further details on this. + * @returns {(x: unknown) => x is T} A user-defined TypeScript type guard that + * checks if an unknown value matches the schema defined in the validator and + * also performs the ever-useful type-narrowing which helps writing less buggy + * code and enhance the compiler's ability to catch issues during development. + * + * @example + * + * ### Define a validator for the `JWSGeneral` type from the openapi.json + * + * ```typescript + * import Ajv from "ajv"; + * + * import * as OpenApiJson from "../../json/openapi.json"; + * import { JWSGeneral } from "../generated/openapi/typescript-axios/api"; + * import { createAjvTypeGuard } from "./create-ajv-type-guard"; + * + * export function createIsJwsGeneral(): (x: unknown) => x is JWSGeneral { + * const ajv = new Ajv(); + * const validator = ajv.compile( + * OpenApiJson.components.schemas.JWSGeneral, + * ); + * return createAjvTypeGuard(validator); + * } + * ``` + * + * ### Then use it elsewhere in the code for validation & type-narrowing + * + * ```typescript + * // make sure to cache the validator you created here because it's costly to + * // re-create it (in terms of hardware resources such as CPU time) + * const isJWSGeneral = createAjvTypeGuard(validateJWSGeneral); + * + * const data: unknown = { payload: "some-payload" }; + * + * if (!isJWSGeneral(data)) { + * throw new TypeError('Data is not a JWSGeneral object'); + * } + * // Now you can safely access properties of data as a JWSGeneral object + * // **without** having to perform unsafe type casting such as `as JWSGeneral` + * console.log(data.payload); + * console.log(data.signatures); + * ``` + * + */ +export function createAjvTypeGuard( + validator: ValidateFunction, +): (x: unknown) => x is T { + return (x: unknown): x is T => { + return validator(x); + }; +} diff --git a/packages/cactus-core-api/src/main/typescript/open-api/create-is-jws-general-type-guard.ts b/packages/cactus-core-api/src/main/typescript/open-api/create-is-jws-general-type-guard.ts new file mode 100644 index 00000000000..40044813413 --- /dev/null +++ b/packages/cactus-core-api/src/main/typescript/open-api/create-is-jws-general-type-guard.ts @@ -0,0 +1,61 @@ +import Ajv from "ajv-draft-04"; +import addFormats from "ajv-formats"; + +import * as OpenApiJson from "../../json/openapi.json"; +import { JWSGeneral } from "../generated/openapi/typescript-axios/api"; +import { createAjvTypeGuard } from "./create-ajv-type-guard"; + +/** + * + * @example + * + * ```typescript + * import { JWSGeneral } from "@hyperledger/cactus-core-api"; + * import { createIsJwsGeneralTypeGuard } from "@hyperledger/cactus-core-api"; + * + * export class PluginConsortiumManual { + * private readonly isJwsGeneral: (x: unknown) => x is JWSGeneral; + * + * constructor() { + * // Creating the type-guard function is relatively costly due to the Ajv schema + * // compilation that needs to happen as part of it so it is good practice to + * // cache the type-guard function as much as possible, for example by adding it + * // as a class member on a long-lived object such as a plugin instance which is + * // expected to match the life-cycle of the API server NodeJS process itself. + * // The specific anti-pattern would be to create a new type-guard function + * // for each request received by a plugin as this would affect performance + * // negatively. + * this.isJwsGeneral = createIsJwsGeneralTypeGuard(); + * } + * + * public async getNodeJws(): Promise { + * // rest of the implementation that produces a JWS ... + * const jws = await joseGeneralSign.sign(); + * + * if (!this.isJwsGeneral(jws)) { + * throw new TypeError("Jose GeneralSign.sign() gave non-JWSGeneral type"); + * } + * return jws; + * } + * } + * + * ``` + * + * @returns A user-defined Typescript type-guard (which is just another function) + * that is primed to do type-narrowing and runtime type-checking as well. + * + * @see {createAjvTypeGuard()} + * @see https://www.typescriptlang.org/docs/handbook/2/narrowing.html + * @see https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates + */ +export function createIsJwsGeneralTypeGuard(): (x: unknown) => x is JWSGeneral { + const ajv = new Ajv({ allErrors: true, strict: false }); + addFormats(ajv); + ajv.addSchema(OpenApiJson, "core-api"); + + const validator = ajv.compile({ + $ref: "core-api#/components/schemas/JWSGeneral", + }); + + return createAjvTypeGuard(validator); +} diff --git a/packages/cactus-core-api/src/main/typescript/public-api.ts b/packages/cactus-core-api/src/main/typescript/public-api.ts index 7221bf1a6c1..5e4a258e8a8 100755 --- a/packages/cactus-core-api/src/main/typescript/public-api.ts +++ b/packages/cactus-core-api/src/main/typescript/public-api.ts @@ -52,3 +52,6 @@ export { isIPluginGrpcService } from "./plugin/grpc-service/i-plugin-grpc-servic export { ICrpcSvcRegistration } from "./plugin/crpc-service/i-plugin-crpc-service"; export { IPluginCrpcService } from "./plugin/crpc-service/i-plugin-crpc-service"; export { isIPluginCrpcService } from "./plugin/crpc-service/i-plugin-crpc-service"; + +export { createAjvTypeGuard } from "./open-api/create-ajv-type-guard"; +export { createIsJwsGeneralTypeGuard } from "./open-api/create-is-jws-general-type-guard"; diff --git a/packages/cactus-core-api/src/test/typescript/unit/open-api/create-ajv-type-guard.test.ts b/packages/cactus-core-api/src/test/typescript/unit/open-api/create-ajv-type-guard.test.ts new file mode 100644 index 00000000000..22bd23a8a03 --- /dev/null +++ b/packages/cactus-core-api/src/test/typescript/unit/open-api/create-ajv-type-guard.test.ts @@ -0,0 +1,36 @@ +import "jest-extended"; +import Ajv from "ajv-draft-04"; +import addFormats from "ajv-formats"; + +import * as OpenApiJson from "../../../../main/json/openapi.json"; +import { JWSGeneral } from "../../../../main/typescript/generated/openapi/typescript-axios/api"; +import { createAjvTypeGuard } from "../../../../main/typescript/open-api/create-ajv-type-guard"; + +describe("createAjvTypeGuard()", () => { + it("creates Generic type-guards that work", () => { + const ajv = new Ajv({ allErrors: true, strict: false }); + addFormats(ajv); + ajv.addSchema(OpenApiJson, "core-api"); + + const validator = ajv.compile({ + $ref: "core-api#/components/schemas/JWSGeneral", + }); + + const isJwsGeneral = createAjvTypeGuard(validator); + + const jwsGeneralGood1: JWSGeneral = { payload: "stuff", signatures: [] }; + const jwsGeneralBad1 = { payload: "stuff", signatures: {} } as JWSGeneral; + const jwsGeneralBad2 = { payload: "", signatures: {} } as JWSGeneral; + + expect(isJwsGeneral(jwsGeneralGood1)).toBeTrue(); + expect(isJwsGeneral(jwsGeneralBad1)).toBeFalse(); + expect(isJwsGeneral(jwsGeneralBad2)).toBeFalse(); + + // verify type-narrowing to be working + const jwsGeneralGood2: unknown = { payload: "stuff", signatures: [] }; + if (!isJwsGeneral(jwsGeneralGood2)) { + throw new Error("isJwsGeneral test misclassified valid JWSGeneral."); + } + expect(jwsGeneralGood2.payload).toEqual("stuff"); + }); +}); diff --git a/packages/cactus-core-api/src/test/typescript/unit/open-api/create-is-jws-general-type-guard.test.ts b/packages/cactus-core-api/src/test/typescript/unit/open-api/create-is-jws-general-type-guard.test.ts new file mode 100644 index 00000000000..5c7730c5cbc --- /dev/null +++ b/packages/cactus-core-api/src/test/typescript/unit/open-api/create-is-jws-general-type-guard.test.ts @@ -0,0 +1,25 @@ +import "jest-extended"; + +import { JWSGeneral } from "../../../../main/typescript/generated/openapi/typescript-axios/api"; +import { createIsJwsGeneralTypeGuard } from "../../../../main/typescript/open-api/create-is-jws-general-type-guard"; + +describe("createIsJwsGeneralTypeGuard()", () => { + it("creates JWSGeneral type-guards that work", () => { + const isJwsGeneral = createIsJwsGeneralTypeGuard(); + + const jwsGeneralGood1: JWSGeneral = { payload: "stuff", signatures: [] }; + const jwsGeneralBad1 = { payload: "stuff", signatures: {} } as JWSGeneral; + const jwsGeneralBad2 = { payload: "", signatures: {} } as JWSGeneral; + + expect(isJwsGeneral(jwsGeneralGood1)).toBeTrue(); + expect(isJwsGeneral(jwsGeneralBad1)).toBeFalse(); + expect(isJwsGeneral(jwsGeneralBad2)).toBeFalse(); + + // verify type-narrowing to be working + const jwsGeneralGood2: unknown = { payload: "stuff", signatures: [] }; + if (!isJwsGeneral(jwsGeneralGood2)) { + throw new Error("isJwsGeneral test misclassified valid JWSGeneral."); + } + expect(jwsGeneralGood2.payload).toEqual("stuff"); + }); +}); diff --git a/packages/cactus-plugin-consortium-manual/src/main/typescript/plugin-consortium-manual.ts b/packages/cactus-plugin-consortium-manual/src/main/typescript/plugin-consortium-manual.ts index 94ebc6fe325..403929b1e17 100644 --- a/packages/cactus-plugin-consortium-manual/src/main/typescript/plugin-consortium-manual.ts +++ b/packages/cactus-plugin-consortium-manual/src/main/typescript/plugin-consortium-manual.ts @@ -13,6 +13,7 @@ import { ICactusPluginOptions, JWSGeneral, JWSRecipient, + createIsJwsGeneralTypeGuard, } from "@hyperledger/cactus-core-api"; import { PluginRegistry, ConsortiumRepository } from "@hyperledger/cactus-core"; @@ -59,6 +60,7 @@ export class PluginConsortiumManual private readonly log: Logger; private readonly instanceId: string; private readonly repo: ConsortiumRepository; + private readonly isJwsGeneral: (x: unknown) => x is JWSGeneral; private endpoints: IWebServiceEndpoint[] | undefined; public get className(): string { @@ -82,6 +84,7 @@ export class PluginConsortiumManual this.instanceId = this.options.instanceId; this.repo = new ConsortiumRepository({ db: options.consortiumDatabase }); + this.isJwsGeneral = createIsJwsGeneralTypeGuard(); this.prometheusExporter = options.prometheusExporter || @@ -204,16 +207,22 @@ export class PluginConsortiumManual const _protected = { iat: Date.now(), jti: uuidv4(), - iss: "Hyperledger Cactus", + iss: "Cacti", }; - // TODO: double check if this casting is safe (it is supposed to be) + const encoder = new TextEncoder(); - const sign = new GeneralSign(encoder.encode(payloadJson)); + const encodedPayload = encoder.encode(payloadJson); + const sign = new GeneralSign(encodedPayload); sign .addSignature(keyPair) .setProtectedHeader({ alg: "ES256K", _protected }); - const jwsGeneral = await sign.sign(); - return jwsGeneral as JWSGeneral; + + const jws = await sign.sign(); + + if (!this.isJwsGeneral(jws)) { + throw new TypeError("Jose GeneralSign.sign() gave non-JWSGeneral type"); + } + return jws; } public async getConsortiumJws(): Promise { diff --git a/yarn.lock b/yarn.lock index 3bd5600caff..13638456aee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9546,6 +9546,9 @@ __metadata: "@hyperledger/cactus-common": "npm:2.0.0-rc.3" "@types/express": "npm:4.17.21" "@types/google-protobuf": "npm:3.15.5" + ajv: "npm:8.17.1" + ajv-draft-04: "npm:1.0.0" + ajv-formats: "npm:3.0.1" axios: "npm:1.7.5" google-protobuf: "npm:3.21.4" grpc-tools: "npm:1.12.4" @@ -19222,7 +19225,7 @@ __metadata: languageName: node linkType: hard -"ajv-draft-04@npm:^1.0.0": +"ajv-draft-04@npm:1.0.0, ajv-draft-04@npm:^1.0.0": version: 1.0.0 resolution: "ajv-draft-04@npm:1.0.0" peerDependencies: @@ -19248,6 +19251,20 @@ __metadata: languageName: node linkType: hard +"ajv-formats@npm:3.0.1": + version: 3.0.1 + resolution: "ajv-formats@npm:3.0.1" + dependencies: + ajv: "npm:^8.0.0" + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + checksum: 10/5679b9f9ced9d0213a202a37f3aa91efcffe59a6de1a6e3da5c873344d3c161820a1f11cc29899661fee36271fd2895dd3851b6461c902a752ad661d1c1e8722 + languageName: node + linkType: hard + "ajv-keywords@npm:^1.0.0": version: 1.5.1 resolution: "ajv-keywords@npm:1.5.1" @@ -19298,6 +19315,18 @@ __metadata: languageName: node linkType: hard +"ajv@npm:8.17.1, ajv@npm:^8.14.0": + version: 8.17.1 + resolution: "ajv@npm:8.17.1" + dependencies: + fast-deep-equal: "npm:^3.1.3" + fast-uri: "npm:^3.0.1" + json-schema-traverse: "npm:^1.0.0" + require-from-string: "npm:^2.0.2" + checksum: 10/ee3c62162c953e91986c838f004132b6a253d700f1e51253b99791e2dbfdb39161bc950ebdc2f156f8568035bb5ed8be7bd78289cd9ecbf3381fe8f5b82e3f33 + languageName: node + linkType: hard + "ajv@npm:^4.7.0": version: 4.11.8 resolution: "ajv@npm:4.11.8" @@ -19344,18 +19373,6 @@ __metadata: languageName: node linkType: hard -"ajv@npm:^8.14.0": - version: 8.17.1 - resolution: "ajv@npm:8.17.1" - dependencies: - fast-deep-equal: "npm:^3.1.3" - fast-uri: "npm:^3.0.1" - json-schema-traverse: "npm:^1.0.0" - require-from-string: "npm:^2.0.2" - checksum: 10/ee3c62162c953e91986c838f004132b6a253d700f1e51253b99791e2dbfdb39161bc950ebdc2f156f8568035bb5ed8be7bd78289cd9ecbf3381fe8f5b82e3f33 - languageName: node - linkType: hard - "ajv@npm:^8.8.0": version: 8.11.0 resolution: "ajv@npm:8.11.0"