diff --git a/.github/settings.xml b/.github/settings.xml new file mode 100644 index 0000000000..59d889141e --- /dev/null +++ b/.github/settings.xml @@ -0,0 +1,13 @@ + + + + + gha + + true + + + + + diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d118728506..ba849b4647 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,23 +14,12 @@ jobs: build: strategy: matrix: - jdk_version: ['17'] + jdk_version: [ '17' ] fail-fast: false - runs-on: self-hosted + runs-on: ubuntu-latest steps: - - name: Clear /tmp - run: | - docker run --rm -v /tmp:/data alpine find /data -ctime +2 -exec rm -rf '{}' \; 2>&1 > /dev/null || true - - - name: Clear old Docker resources - run: | - docker rm -f $(docker ps -aq) || true - docker volume rm $(docker volume ps -q) || true - docker system prune -af || true - docker image prune -af || true - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 with: @@ -42,21 +31,17 @@ jobs: username: ${{ secrets.OSS_DOCKERHUB_USERNAME }} password: ${{ secrets.OSS_DOCKERHUB_PASSWORD }} - - uses: actions/checkout@v3 - - name: Set up JDK uses: actions/setup-java@v3 with: java-version: '${{ matrix.jdk_version }}' distribution: 'temurin' - - name: Remove old Concord artifacts - run: | - rm -rf ~/.m2/repository/com/walmartlabs/concord - rm -rf ~/actions-runner/.m2/repository/com/walmartlabs/concord + - name: Checkout + uses: actions/checkout@v3 - name: Build and test with Maven - run: ./mvnw -B clean install -Pdocker -Pit -Pjdk${{ matrix.jdk_version }} - + run: ./mvnw -s .github/settings.xml -B clean install -Pgha -Pdocker -Pit -Pjdk${{ matrix.jdk_version }} + - name: Build with debian docker images - run: ./mvnw -C -B -f docker-images install -DskipTests -Pdocker -Pdebian -Pjdk${{ matrix.jdk_version }} + run: ./mvnw -s .github/settings.xml -C -B -f docker-images install -DskipTests -Pgha -Pdocker -Pdebian -Pjdk${{ matrix.jdk_version }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e1702d23b..46e8c41cbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,44 @@ # Change log +## [2.1.0] - 2023-10-10 + +### Added + +- new concord-client-v2 +([#810](https://github.com/walmartlabs/concord/pull/810)); +- runtime-v2: hasFlow function +([#813](https://github.com/walmartlabs/concord/pull/813)); +- runtime-v2: uuid function +([#812](https://github.com/walmartlabs/concord/pull/812)); +- runtime-v2: allow listen to project load events at runtime +([#785](https://github.com/walmartlabs/concord/pull/785)); +- console2: allow changing JSON store org +([#790](https://github.com/walmartlabs/concord/pull/790)). + +### Changed +- runtime-v2: automatically convert non serializable map.entry to serializable in exp +([#815](https://github.com/walmartlabs/concord/pull/815)); +- server: return 404 when repository is not found +([#806](https://github.com/walmartlabs/concord/pull/806)); +- runtime-v2: fix global vars update after resume +([#809](https://github.com/walmartlabs/concord/pull/809)); +- console2: handle procesess with commitId, but without repoUrl +([#807](https://github.com/walmartlabs/concord/pull/807)); +- runtime-v2: fix initialize of array expression +([#800](https://github.com/walmartlabs/concord/pull/800)); +- server: only admins can access policies +([#792](https://github.com/walmartlabs/concord/pull/792)); +- cli: active profiles fix +([#789](https://github.com/walmartlabs/concord/pull/789)). + ## [2.0.0] - 2023-08-16 + # Breaking - project: drop support for JDK 8 and JDK 11. Make JDK 17 the new default version. - - ## [1.103.0] - 2023-07-16 ### Added diff --git a/README.md b/README.md index 60ff3d9000..5aac69899c 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ different systems together using scenarios and plugins created by users. Dependencies: - [Git](https://git-scm.com/) 2.18+ -- [Java 8](https://adoptium.net/) +- [Java 17](https://adoptium.net/) - [Docker Community Edition](https://www.docker.com/community-edition) - [Docker Buildx](https://docs.docker.com/build/buildx/install/) - (Optional) [NodeJS and NPM](https://nodejs.org/en/download/) (Node 16 or greater) @@ -41,7 +41,7 @@ Available Maven profiles: - `docker` - build Docker images; - `debian` - build Debian-based Docker images instead of the default CentOS base; - `it` - run integration tests; -- `jdk17`, `jdk17-aarch64` - use a different JDK version for building artifacts and Docker images. +- ``jdk17-aarch64` - use a different JDK version for building artifacts and Docker images. Profiles can be combined, e.g. @@ -122,4 +122,4 @@ See the [examples](examples) directory. ## Development Notes -See [NOTES.md](NOTES.md). \ No newline at end of file +See [NOTES.md](NOTES.md). diff --git a/agent/pom.xml b/agent/pom.xml index 2f845e628a..64c4001982 100644 --- a/agent/pom.xml +++ b/agent/pom.xml @@ -6,7 +6,7 @@ com.walmartlabs.concord parent - 2.0.1-SNAPSHOT + 2.1.1-SNAPSHOT ../pom.xml @@ -100,6 +100,7 @@ com.squareup.okhttp okhttp + 2.7.5 org.jboss.spec.javax.ws.rs diff --git a/cli/pom.xml b/cli/pom.xml index 2a1adb4289..e4a5d95703 100644 --- a/cli/pom.xml +++ b/cli/pom.xml @@ -6,7 +6,7 @@ com.walmartlabs.concord parent - 2.0.1-SNAPSHOT + 2.1.1-SNAPSHOT ../pom.xml diff --git a/client/pom.xml b/client/pom.xml index 411f877aa7..711f114d0b 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -6,13 +6,21 @@ com.walmartlabs.concord parent - 2.0.1-SNAPSHOT + 2.1.1-SNAPSHOT ../pom.xml concord-client jar + + 1.5.20 + 2.10 + 1.8.3 + 2.7.5 + 1.17.2 + + com.walmartlabs.concord.server @@ -31,27 +39,40 @@ com.squareup.okhttp okhttp + ${okhttp.version} com.squareup.okhttp logging-interceptor + ${okhttp.version} com.squareup.okio okio + ${okio.version} com.google.code.gson gson - - - io.gsonfire - gson-fire + ${gson.version} io.swagger swagger-annotations + ${swagger.version} + + io.gsonfire + gson-fire + ${gson.fire.version} + + + com.google.code.gson + gson + + + + org.slf4j slf4j-api @@ -123,6 +144,7 @@ io.swagger swagger-codegen-maven-plugin + 2.3.1 server @@ -131,7 +153,7 @@ - ${project.basedir}/../server/impl/target/classes/com/walmartlabs/concord/server/swagger/swagger.json + ${project.basedir}/swagger.json java diff --git a/client/swagger.json b/client/swagger.json new file mode 100644 index 0000000000..d983b66093 --- /dev/null +++ b/client/swagger.json @@ -0,0 +1,9799 @@ +{ + "swagger" : "2.0", + "info" : { + "version" : "v1", + "title" : "Concord Server API" + }, + "host" : "localhost:8001", + "basePath" : "/", + "tags" : [ { + "name" : "API keys" + }, { + "name" : "Agents" + }, { + "name" : "Audit Log" + }, { + "name" : "Checkpoint" + }, { + "name" : "CheckpointV2" + }, { + "name" : "External Events" + }, { + "name" : "GitHub Events" + }, { + "name" : "Inventories" + }, { + "name" : "Inventory Data" + }, { + "name" : "Inventory Queries" + }, { + "name" : "JsonStore" + }, { + "name" : "JsonStoreData" + }, { + "name" : "JsonStoreQuery" + }, { + "name" : "Organizations" + }, { + "name" : "Policy" + }, { + "name" : "PolicyCheck" + }, { + "name" : "Process" + }, { + "name" : "Process Events" + }, { + "name" : "Process Forms" + }, { + "name" : "Process KV store" + }, { + "name" : "Process Locks" + }, { + "name" : "ProcessHeartbeat" + }, { + "name" : "ProcessLogV2" + }, { + "name" : "ProcessV2" + }, { + "name" : "Project Processes" + }, { + "name" : "Projects" + }, { + "name" : "Repositories" + }, { + "name" : "RepositoriesV2" + }, { + "name" : "Roles" + }, { + "name" : "Secret stores" + }, { + "name" : "Secrets" + }, { + "name" : "SecretsV2" + }, { + "name" : "Teams" + }, { + "name" : "TemplateAlias" + }, { + "name" : "Triggers" + }, { + "name" : "TriggersV2" + }, { + "name" : "UserLdapGroup" + }, { + "name" : "UserV2" + }, { + "name" : "Users" + } ], + "schemes" : [ "http" ], + "paths" : { + "/api/service/console/apikey/{name}/exists" : { + "get" : { + "operationId" : "isApiTokenExists", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "name", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "boolean" + } + } + } + } + }, + "/api/service/console/logout" : { + "post" : { + "operationId" : "logout", + "responses" : { + "default" : { + "description" : "successful operation" + } + } + } + }, + "/api/service/console/org/{orgName}/jsonstore/{storageName}/exists" : { + "get" : { + "operationId" : "isStorageExists", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "storageName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "boolean" + } + } + } + } + }, + "/api/service/console/org/{orgName}/jsonstore/{storeName}/query/{queryName}/exists" : { + "get" : { + "operationId" : "isStorageQueryExists", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "storeName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "queryName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "boolean" + } + } + } + } + }, + "/api/service/console/org/{orgName}/project/{projectName}/exists" : { + "get" : { + "operationId" : "isProjectExists", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "boolean" + } + } + } + } + }, + "/api/service/console/org/{orgName}/project/{projectName}/repo/{repoName}/exists" : { + "get" : { + "operationId" : "isRepositoryExists", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "repoName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "boolean" + } + } + } + } + }, + "/api/service/console/org/{orgName}/secret/{secretName}/exists" : { + "get" : { + "operationId" : "isSecretExists", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "secretName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "boolean" + } + } + } + } + }, + "/api/service/console/org/{orgName}/team/{teamName}/exists" : { + "get" : { + "operationId" : "isTeamExists", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "teamName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "boolean" + } + } + } + } + }, + "/api/service/console/repository/test" : { + "post" : { + "operationId" : "testRepository", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "boolean" + } + } + } + } + }, + "/api/service/console/search/ldapGroups" : { + "get" : { + "operationId" : "searchLdapGroups", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "filter", + "in" : "query", + "required" : false, + "type" : "string", + "maxLength" : 256, + "minLength" : 5 + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/LdapGroupSearchResult" + } + } + } + } + } + }, + "/api/service/console/user/activity" : { + "get" : { + "operationId" : "activity", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "maxProjectsPerOrg", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 5, + "format" : "int32" + }, { + "name" : "maxOwnProcesses", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 5, + "format" : "int32" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/UserActivityResponse" + } + } + } + } + }, + "/api/service/console/validate-password" : { + "post" : { + "operationId" : "validatePassword", + "consumes" : [ "text/plain" ], + "produces" : [ "application/json" ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "boolean" + } + } + } + } + }, + "/api/service/console/whoami" : { + "get" : { + "operationId" : "whoami", + "produces" : [ "application/json" ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/UserResponse" + } + } + } + } + }, + "/api/service/custom_form/{processInstanceId}/{formName}/continue" : { + "post" : { + "operationId" : "continueSession", + "consumes" : [ "application/x-www-form-urlencoded" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "processInstanceId", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "formName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + } + } + }, + "/api/service/custom_form/{processInstanceId}/{formName}/start" : { + "post" : { + "operationId" : "startSession", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "processInstanceId", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "formName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/FormSessionResponse" + } + } + } + } + }, + "/api/v1/agent/all/workers" : { + "get" : { + "tags" : [ "Agents" ], + "summary" : "List currently available agent workers", + "description" : "", + "operationId" : "listWorkers", + "produces" : [ "application/json" ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/AgentWorkerEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/agent/all/workersCount" : { + "get" : { + "tags" : [ "Agents" ], + "summary" : "Counts the currently connected workers based on the specified capabilities property", + "description" : "", + "operationId" : "aggregate", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "capabilities", + "in" : "query", + "required" : false, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "object", + "additionalProperties" : { + "type" : "integer", + "format" : "int64" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/apikey" : { + "get" : { + "tags" : [ "API keys" ], + "summary" : "List user api keys", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "userId", + "in" : "query", + "required" : false, + "type" : "string", + "format" : "uuid" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ApiKeyEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "API keys" ], + "summary" : "Create a new API key", + "description" : "", + "operationId" : "create", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/CreateApiKeyRequest" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/CreateApiKeyResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/apikey/{id}" : { + "delete" : { + "tags" : [ "API keys" ], + "summary" : "Delete an existing API key", + "description" : "", + "operationId" : "delete", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/audit" : { + "get" : { + "tags" : [ "Audit Log" ], + "summary" : "List audit log entries for the specified organization", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "object", + "in" : "query", + "required" : false, + "type" : "string", + "enum" : [ "API_KEY", "EXTERNAL_EVENT", "JSON_STORE", "JSON_STORE_DATA", "JSON_STORE_QUERY", "ORGANIZATION", "POLICY", "PROJECT", "PROCESS", "ROLE", "SECRET", "SYSTEM", "TEAM", "USER", "INVENTORY" ] + }, { + "name" : "action", + "in" : "query", + "required" : false, + "type" : "string", + "enum" : [ "CREATE", "UPDATE", "DELETE", "ACCESS" ] + }, { + "name" : "userId", + "in" : "query", + "required" : false, + "type" : "string", + "format" : "uuid" + }, { + "name" : "username", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "after", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "before", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "offset", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 0, + "format" : "int32" + }, { + "name" : "limit", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 30, + "format" : "int32" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/AuditLogEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/events/{eventName}" : { + "post" : { + "tags" : [ "External Events" ], + "summary" : "Handles an external event", + "description" : "", + "operationId" : "event", + "consumes" : [ "application/json" ], + "parameters" : [ { + "name" : "eventName", + "in" : "path", + "required" : true, + "type" : "string", + "pattern" : ".*" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "object", + "additionalProperties" : { + "type" : "object" + } + } + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org" : { + "get" : { + "tags" : [ "Organizations" ], + "summary" : "List organizations", + "description" : "", + "operationId" : "find", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "onlyCurrent", + "in" : "query", + "required" : false, + "type" : "boolean", + "default" : false + }, { + "name" : "offset", + "in" : "query", + "required" : false, + "type" : "integer", + "format" : "int32" + }, { + "name" : "limit", + "in" : "query", + "required" : false, + "type" : "integer", + "format" : "int32" + }, { + "name" : "filter", + "in" : "query", + "required" : false, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/OrganizationEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "Organizations" ], + "summary" : "Create or update an organization", + "description" : "", + "operationId" : "createOrUpdate", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/OrganizationEntry" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/CreateOrganizationResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/trigger/refresh" : { + "post" : { + "tags" : [ "Triggers" ], + "summary" : "Refresh trigger definitions for all projects", + "description" : "", + "operationId" : "refreshAll", + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}" : { + "get" : { + "tags" : [ "Organizations" ], + "summary" : "Get an existing organization", + "description" : "", + "operationId" : "get", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/OrganizationEntry" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "delete" : { + "tags" : [ "Organizations" ], + "summary" : "Remove an existing organization", + "description" : "", + "operationId" : "delete", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "confirmation", + "in" : "query", + "required" : false, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/inventory" : { + "get" : { + "tags" : [ "Inventories" ], + "summary" : "List existing inventories", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/InventoryEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "Inventories" ], + "summary" : "Create or update inventory", + "description" : "", + "operationId" : "createOrUpdate", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/InventoryEntry" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/CreateInventoryResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/inventory/{inventoryName}" : { + "get" : { + "tags" : [ "Inventories" ], + "summary" : "Get existing inventory", + "description" : "", + "operationId" : "get", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "inventoryName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/InventoryEntry" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "delete" : { + "tags" : [ "Inventories" ], + "summary" : "Delete inventory", + "description" : "", + "operationId" : "delete", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "inventoryName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/inventory/{inventoryName}/access" : { + "post" : { + "tags" : [ "Inventories" ], + "summary" : "Updates the access level for the specified inventory", + "description" : "", + "operationId" : "updateAccessLevel", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "inventoryName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/ResourceAccessEntry" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/inventory/{inventoryName}/data" : { + "get" : { + "tags" : [ "Inventory Data" ], + "summary" : "List inventory data", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "inventoryName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "type" : "object", + "additionalProperties" : { + "type" : "object" + } + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/inventory/{inventoryName}/data/{itemPath}" : { + "get" : { + "tags" : [ "Inventory Data" ], + "summary" : "Get inventory data", + "description" : "", + "operationId" : "get", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "inventoryName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "itemPath", + "in" : "path", + "required" : true, + "type" : "string", + "pattern" : ".*" + }, { + "name" : "singleItem", + "in" : "query", + "required" : false, + "type" : "boolean", + "default" : false + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "object" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "Inventory Data" ], + "summary" : "Modify inventory data", + "description" : "", + "operationId" : "data", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "inventoryName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "itemPath", + "in" : "path", + "required" : true, + "type" : "string", + "pattern" : ".*" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "object" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "object" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "delete" : { + "tags" : [ "Inventory Data" ], + "summary" : "Delete inventory data", + "description" : "", + "operationId" : "delete", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "inventoryName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "itemPath", + "in" : "path", + "required" : true, + "type" : "string", + "pattern" : ".*" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/DeleteInventoryDataResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/inventory/{inventoryName}/query" : { + "get" : { + "tags" : [ "Inventory Queries" ], + "summary" : "List inventory queries", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "inventoryName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/InventoryQueryEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/inventory/{inventoryName}/query/{queryName}" : { + "get" : { + "tags" : [ "Inventory Queries" ], + "summary" : "Get inventory query", + "description" : "", + "operationId" : "get", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "inventoryName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "queryName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/InventoryQueryEntry" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "Inventory Queries" ], + "summary" : "Create or update inventory query", + "description" : "", + "operationId" : "createOrUpdate", + "consumes" : [ "application/json", "text/plain" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "inventoryName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "queryName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/CreateInventoryQueryResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "delete" : { + "tags" : [ "Inventory Queries" ], + "summary" : "Delete inventory query", + "description" : "", + "operationId" : "delete", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "inventoryName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "queryName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/DeleteInventoryQueryResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/inventory/{inventoryName}/query/{queryName}/exec" : { + "post" : { + "tags" : [ "Inventory Queries" ], + "summary" : "Execute inventory query", + "description" : "", + "operationId" : "exec", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "inventoryName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "queryName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "object", + "additionalProperties" : { + "type" : "object" + } + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "type" : "object" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/jsonstore" : { + "get" : { + "tags" : [ "JsonStore" ], + "summary" : "List existing stores", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "offset", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 0, + "format" : "int32" + }, { + "name" : "limit", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 30, + "format" : "int32" + }, { + "name" : "filter", + "in" : "query", + "required" : false, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/JsonStoreEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "JsonStore" ], + "summary" : "Create or update a store", + "description" : "", + "operationId" : "createOrUpdate", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/JsonStoreRequest" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/jsonstore/{storeName}" : { + "get" : { + "tags" : [ "JsonStore" ], + "summary" : "Get an existing store", + "description" : "", + "operationId" : "get", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "storeName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/JsonStoreEntry" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "delete" : { + "tags" : [ "JsonStore" ], + "summary" : "Delete an existing store", + "description" : "", + "operationId" : "delete", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "storeName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/jsonstore/{storeName}/access" : { + "get" : { + "tags" : [ "JsonStore" ], + "summary" : "Get a store's team access parameters", + "description" : "", + "operationId" : "getAccessLevel", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "storeName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ResourceAccessEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "JsonStore" ], + "summary" : "Updates the access level for the specified store", + "description" : "", + "operationId" : "updateAccessLevel", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "storeName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/ResourceAccessEntry" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/jsonstore/{storeName}/access/bulk" : { + "post" : { + "tags" : [ "JsonStore" ], + "summary" : "Updates the access level for the specified store and team", + "description" : "", + "operationId" : "updateAccessLevel", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "storeName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ResourceAccessEntry" + } + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/jsonstore/{storeName}/capacity" : { + "get" : { + "tags" : [ "JsonStore" ], + "operationId" : "getCapacity", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "storeName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/JsonStoreCapacity" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/jsonstore/{storeName}/execQuery" : { + "post" : { + "tags" : [ "JsonStoreQuery" ], + "operationId" : "execQuery", + "consumes" : [ "text/plain" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "storeName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "maxLimit", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 10, + "format" : "int32" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "type" : "object" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/jsonstore/{storeName}/item" : { + "get" : { + "tags" : [ "JsonStoreData" ], + "summary" : "List items in a JSON store", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "storeName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "offset", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 0, + "format" : "int32" + }, { + "name" : "limit", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 30, + "format" : "int32" + }, { + "name" : "filter", + "in" : "query", + "required" : false, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/jsonstore/{storeName}/item/{itemPath}" : { + "get" : { + "tags" : [ "JsonStoreData" ], + "summary" : "Get store data", + "description" : "", + "operationId" : "get", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "storeName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "itemPath", + "in" : "path", + "required" : true, + "type" : "string", + "pattern" : ".*" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "object" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "JsonStoreData" ], + "operationId" : "update", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "storeName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "itemPath", + "in" : "path", + "required" : true, + "type" : "string", + "pattern" : ".*" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "object" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "put" : { + "tags" : [ "JsonStoreData" ], + "summary" : "Update an item in a store", + "description" : "", + "operationId" : "data", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "storeName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "itemPath", + "in" : "path", + "required" : true, + "type" : "string", + "pattern" : ".*" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "object" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "delete" : { + "tags" : [ "JsonStoreData" ], + "summary" : "Remove an item from a store", + "description" : "", + "operationId" : "delete", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "storeName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "itemPath", + "in" : "path", + "required" : true, + "type" : "string", + "pattern" : ".*" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/jsonstore/{storeName}/query" : { + "get" : { + "tags" : [ "JsonStoreQuery" ], + "summary" : "List JSON Store queries", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "storeName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "offset", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 0, + "format" : "int32" + }, { + "name" : "limit", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 30, + "format" : "int32" + }, { + "name" : "filter", + "in" : "query", + "required" : false, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/JsonStoreQueryEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "JsonStoreQuery" ], + "summary" : "Create or update a JSON store query", + "description" : "", + "operationId" : "createOrUpdate", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "storeName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/JsonStoreQueryRequest" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/jsonstore/{storeName}/query/{queryName}" : { + "get" : { + "tags" : [ "JsonStoreQuery" ], + "summary" : "Get an existing JSON store query", + "description" : "", + "operationId" : "get", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "storeName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "queryName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/JsonStoreQueryEntry" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "delete" : { + "tags" : [ "JsonStoreQuery" ], + "summary" : "Delete an existing JSON query query", + "description" : "", + "operationId" : "delete", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "storeName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "queryName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/jsonstore/{storeName}/query/{queryName}/exec" : { + "post" : { + "tags" : [ "JsonStoreQuery" ], + "summary" : "Execute an existing JSON store query", + "description" : "", + "operationId" : "exec", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "storeName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "queryName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "object", + "additionalProperties" : { + "type" : "object" + } + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "type" : "object" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/process" : { + "get" : { + "tags" : [ "Project Processes" ], + "summary" : "List processes for the specified organization", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "status", + "in" : "query", + "required" : false, + "type" : "string", + "enum" : [ "NEW", "PREPARING", "ENQUEUED", "WAITING", "STARTING", "RUNNING", "SUSPENDED", "RESUMING", "FINISHED", "FAILED", "CANCELLED", "TIMED_OUT" ] + }, { + "name" : "afterCreatedAt", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "beforeCreatedAt", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "limit", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 100, + "format" : "int32" + }, { + "name" : "offset", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 0, + "format" : "int32" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ProcessEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ], + "deprecated" : true + } + }, + "/api/v1/org/{orgName}/project" : { + "get" : { + "tags" : [ "Projects" ], + "summary" : "List existing projects", + "description" : "", + "operationId" : "find", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "offset", + "in" : "query", + "required" : false, + "type" : "integer", + "format" : "int32" + }, { + "name" : "limit", + "in" : "query", + "required" : false, + "type" : "integer", + "format" : "int32" + }, { + "name" : "filter", + "in" : "query", + "required" : false, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ProjectEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "Projects" ], + "summary" : "Creates a new project or updates an existing one", + "description" : "", + "operationId" : "createOrUpdate", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/ProjectEntry" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/ProjectOperationResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/project/{projectName}" : { + "get" : { + "tags" : [ "Projects" ], + "summary" : "Get an existing project", + "description" : "", + "operationId" : "get", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/ProjectEntry" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ], + "deprecated" : true + }, + "delete" : { + "tags" : [ "Projects" ], + "summary" : "Delete an existing project", + "description" : "", + "operationId" : "delete", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/project/{projectName}/access" : { + "get" : { + "tags" : [ "Projects" ], + "summary" : "Get project team access", + "description" : "", + "operationId" : "getAccessLevel", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ResourceAccessEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "Projects" ], + "summary" : "Updates the access level for the specified project and team", + "description" : "", + "operationId" : "updateAccessLevel", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/ResourceAccessEntry" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/project/{projectName}/access/bulk" : { + "post" : { + "tags" : [ "Projects" ], + "summary" : "Updates the access level for the specified project and team", + "description" : "", + "operationId" : "updateAccessLevel", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ResourceAccessEntry" + } + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/project/{projectName}/cfg" : { + "put" : { + "tags" : [ "Projects" ], + "summary" : "Update a project's configuration parameter", + "description" : "", + "operationId" : "updateConfiguration", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "object" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/project/{projectName}/cfg{path}" : { + "get" : { + "tags" : [ "Projects" ], + "summary" : "Get a project's configuration", + "description" : "", + "operationId" : "getConfiguration", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "path", + "in" : "path", + "required" : true, + "type" : "string", + "pattern" : "(.*)?" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "object" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "put" : { + "tags" : [ "Projects" ], + "summary" : "Update a project's configuration parameter", + "description" : "", + "operationId" : "updateConfiguration", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "path", + "in" : "path", + "required" : true, + "type" : "string", + "pattern" : "(.*)?" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "object" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "delete" : { + "tags" : [ "Projects" ], + "summary" : "Delete a project's configuration parameter", + "description" : "", + "operationId" : "deleteConfiguration", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "path", + "in" : "path", + "required" : true, + "type" : "string", + "pattern" : "(.*)?" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/project/{projectName}/encrypt" : { + "post" : { + "tags" : [ "Projects" ], + "summary" : "Encrypts a string with the project's key", + "description" : "", + "operationId" : "encrypt", + "consumes" : [ "text/plain" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/EncryptValueResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/project/{projectName}/kv" : { + "get" : { + "tags" : [ "Projects" ], + "summary" : "list KV", + "description" : "", + "operationId" : "findKV", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "offset", + "in" : "query", + "required" : false, + "type" : "integer", + "format" : "int32" + }, { + "name" : "limit", + "in" : "query", + "required" : false, + "type" : "integer", + "format" : "int32" + }, { + "name" : "filter", + "in" : "query", + "required" : false, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/KvEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/project/{projectName}/process" : { + "get" : { + "tags" : [ "Project Processes" ], + "summary" : "List processes for the specified project", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "status", + "in" : "query", + "required" : false, + "type" : "string", + "enum" : [ "NEW", "PREPARING", "ENQUEUED", "WAITING", "STARTING", "RUNNING", "SUSPENDED", "RESUMING", "FINISHED", "FAILED", "CANCELLED", "TIMED_OUT" ] + }, { + "name" : "afterCreatedAt", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "beforeCreatedAt", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "limit", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 100, + "format" : "int32" + }, { + "name" : "offset", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 0, + "format" : "int32" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ProcessEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ], + "deprecated" : true + } + }, + "/api/v1/org/{orgName}/project/{projectName}/repo/{repoName}/start/{entryPoint}" : { + "get" : { + "tags" : [ "Project Processes" ], + "summary" : "Start a new process", + "description" : "", + "operationId" : "start", + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "repoName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "repoBranchOrTag", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "repoCommitId", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "entryPoint", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "activeProfiles", + "in" : "query", + "required" : false, + "type" : "string" + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/project/{projectName}/repo/{repositoryName}/trigger" : { + "get" : { + "tags" : [ "Triggers" ], + "summary" : "List trigger definitions", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "repositoryName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/TriggerEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "Triggers" ], + "summary" : "Refresh trigger definitions for the specified project and repository", + "description" : "", + "operationId" : "refresh", + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "repositoryName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/project/{projectName}/repository" : { + "get" : { + "tags" : [ "Repositories" ], + "summary" : "List existing repositories", + "description" : "", + "operationId" : "find", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "offset", + "in" : "query", + "required" : false, + "type" : "integer", + "format" : "int32" + }, { + "name" : "limit", + "in" : "query", + "required" : false, + "type" : "integer", + "format" : "int32" + }, { + "name" : "filter", + "in" : "query", + "required" : false, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/RepositoryEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "Repositories" ], + "summary" : "Creates a new repository or updates an existing one", + "description" : "", + "operationId" : "createOrUpdate", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/RepositoryEntry" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/project/{projectName}/repository/{repositoryName}" : { + "get" : { + "tags" : [ "Repositories" ], + "summary" : "Get an existing repository", + "description" : "", + "operationId" : "get", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "repositoryName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/RepositoryEntry" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "delete" : { + "tags" : [ "Repositories" ], + "summary" : "Delete an existing repository", + "description" : "", + "operationId" : "delete", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "repositoryName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/project/{projectName}/repository/{repositoryName}/refresh" : { + "post" : { + "tags" : [ "Repositories" ], + "summary" : "Refresh a local copy of the repository", + "description" : "", + "operationId" : "refreshRepository", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "repositoryName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "sync", + "in" : "query", + "required" : false, + "type" : "boolean", + "default" : false + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/project/{projectName}/repository/{repositoryName}/validate" : { + "post" : { + "tags" : [ "Repositories" ], + "summary" : "Validate an existing repository", + "description" : "", + "operationId" : "validateRepository", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "repositoryName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/RepositoryValidationResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/secret" : { + "get" : { + "tags" : [ "Secrets" ], + "summary" : "List secrets", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "offset", + "in" : "query", + "required" : false, + "type" : "integer", + "format" : "int32" + }, { + "name" : "limit", + "in" : "query", + "required" : false, + "type" : "integer", + "format" : "int32" + }, { + "name" : "filter", + "in" : "query", + "required" : false, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/SecretEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "Secrets" ], + "summary" : "Creates a new secret", + "description" : "", + "operationId" : "create", + "consumes" : [ "multipart/form-data" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/MultipartInput" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/SecretOperationResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/secret/{secretName}" : { + "get" : { + "tags" : [ "Secrets" ], + "summary" : "Get an existing secret", + "description" : "", + "operationId" : "get", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "secretName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/SecretEntry" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "Secrets" ], + "summary" : "Updates an existing secret", + "description" : "", + "operationId" : "update", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "secretName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/SecretUpdateRequest" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ], + "deprecated" : true + }, + "delete" : { + "tags" : [ "Secrets" ], + "summary" : "Delete an existing secret", + "description" : "", + "operationId" : "delete", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "secretName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/secret/{secretName}/access" : { + "get" : { + "tags" : [ "Secrets" ], + "summary" : "Get secret team access", + "description" : "", + "operationId" : "getAccessLevel", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "secretName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ResourceAccessEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "Secrets" ], + "summary" : "Updates the access level for the specified secret and team", + "description" : "", + "operationId" : "updateAccessLevel", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "secretName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/ResourceAccessEntry" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/secret/{secretName}/access/bulk" : { + "post" : { + "tags" : [ "Secrets" ], + "summary" : "Updates the access level for the specified secret and team", + "description" : "", + "operationId" : "updateAccessLevel", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "secretName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ResourceAccessEntry" + } + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/secret/{secretName}/data" : { + "post" : { + "tags" : [ "Secrets" ], + "summary" : "Get an existing secret's data", + "description" : "", + "operationId" : "getData", + "consumes" : [ "multipart/form-data" ], + "produces" : [ "application/octet-stream" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "secretName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/MultipartInput" + } + } ], + "responses" : { + "200" : { + "description" : "OK", + "schema" : { + "type" : "file" + }, + "headers" : { + "X-Concord-SecretType" : { + "type" : "string", + "description" : "Secret type" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/secret/{secretName}/public" : { + "get" : { + "tags" : [ "Secrets" ], + "summary" : "Retrieves the public key of a key pair", + "description" : "", + "operationId" : "getPublicKey", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "secretName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/PublicKeyResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/team" : { + "get" : { + "tags" : [ "Teams" ], + "summary" : "List teams", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/TeamEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "Teams" ], + "summary" : "Create or update a team", + "description" : "", + "operationId" : "createOrUpdate", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/TeamEntry" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/CreateTeamResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/team/{teamName}" : { + "get" : { + "tags" : [ "Teams" ], + "summary" : "Get an existing team", + "description" : "", + "operationId" : "get", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "teamName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/TeamEntry" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "delete" : { + "tags" : [ "Teams" ], + "summary" : "Delete an existing team", + "description" : "", + "operationId" : "delete", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "teamName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/team/{teamName}/ldapGroups" : { + "get" : { + "tags" : [ "Teams" ], + "summary" : "List ldap roles of a team", + "description" : "", + "operationId" : "listLdapGroups", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "teamName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/TeamLdapGroupEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "put" : { + "tags" : [ "Teams" ], + "summary" : "Add LDAP groups to a team", + "description" : "", + "operationId" : "addLdapGroups", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "teamName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "replace", + "in" : "query", + "required" : false, + "type" : "boolean", + "default" : false + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/TeamLdapGroupEntry" + } + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/AddTeamLdapGroupsResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{orgName}/team/{teamName}/users" : { + "get" : { + "tags" : [ "Teams" ], + "summary" : "List users of a team", + "description" : "", + "operationId" : "listUsers", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "teamName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/TeamUserEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "put" : { + "tags" : [ "Teams" ], + "summary" : "Add users to a team", + "description" : "", + "operationId" : "addUsers", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "teamName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "replace", + "in" : "query", + "required" : false, + "type" : "boolean", + "default" : false + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/TeamUserEntry" + } + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/AddTeamUsersResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "delete" : { + "tags" : [ "Teams" ], + "summary" : "Remove users from a team", + "description" : "", + "operationId" : "removeUsers", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "teamName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/RemoveTeamUsersResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/org/{processInstanceId}/next" : { + "post" : { + "tags" : [ "Project Processes" ], + "summary" : "Proceed to next step for the process", + "description" : "", + "operationId" : "proceed", + "consumes" : [ "application/x-www-form-urlencoded" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "processInstanceId", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process" : { + "get" : { + "tags" : [ "Process" ], + "summary" : "List processes for all user's organizations", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "org", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "project", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "projectId", + "in" : "query", + "required" : false, + "type" : "string", + "format" : "uuid" + }, { + "name" : "afterCreatedAt", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "beforeCreatedAt", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "tags", + "in" : "query", + "required" : false, + "type" : "array", + "items" : { + "type" : "string" + }, + "collectionFormat" : "multi" + }, { + "name" : "status", + "in" : "query", + "required" : false, + "type" : "string", + "enum" : [ "NEW", "PREPARING", "ENQUEUED", "WAITING", "STARTING", "RUNNING", "SUSPENDED", "RESUMING", "FINISHED", "FAILED", "CANCELLED", "TIMED_OUT" ] + }, { + "name" : "initiator", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "parentInstanceId", + "in" : "query", + "required" : false, + "type" : "string", + "format" : "uuid" + }, { + "name" : "limit", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 30, + "format" : "int32" + }, { + "name" : "offset", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 0, + "format" : "int32" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ProcessEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ], + "deprecated" : true + }, + "post" : { + "tags" : [ "Process" ], + "summary" : "Start a new process using multipart request data", + "description" : "", + "operationId" : "start", + "consumes" : [ "multipart/form-data" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/MultipartInput" + } + }, { + "name" : "parentId", + "in" : "query", + "required" : false, + "type" : "string", + "format" : "uuid" + }, { + "name" : "sync", + "in" : "query", + "required" : false, + "type" : "boolean", + "default" : false + }, { + "name" : "out", + "in" : "query", + "required" : false, + "type" : "array", + "items" : { + "type" : "string" + }, + "collectionFormat" : "multi" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/StartProcessResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/bulk" : { + "delete" : { + "tags" : [ "Process" ], + "summary" : "Forcefully stop processes", + "description" : "", + "operationId" : "batchKill", + "parameters" : [ { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "array", + "items" : { + "type" : "string", + "format" : "uuid" + } + } + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{id}" : { + "get" : { + "tags" : [ "Process" ], + "summary" : "Get a process' details", + "description" : "", + "operationId" : "get", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/ProcessEntry" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ], + "deprecated" : true + }, + "delete" : { + "tags" : [ "Process" ], + "summary" : "Forcefully stops a process", + "description" : "", + "operationId" : "kill", + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{id}/attachment" : { + "get" : { + "tags" : [ "Process" ], + "summary" : "List attachments", + "description" : "", + "operationId" : "listAttachments", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "Process" ], + "operationId" : "uploadAttachments", + "consumes" : [ "application/octet-stream" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{id}/attachment/{name}" : { + "get" : { + "tags" : [ "Process" ], + "summary" : "Download a process' attachment", + "description" : "", + "operationId" : "downloadAttachment", + "produces" : [ "application/octet-stream" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "name", + "in" : "path", + "required" : true, + "type" : "string", + "maxLength" : 2147483647, + "minLength" : 1, + "pattern" : ".*" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "file" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{id}/cascade" : { + "delete" : { + "tags" : [ "Process" ], + "summary" : "Forcefully stops a process and its all children", + "description" : "", + "operationId" : "killCascade", + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{id}/checkpoint" : { + "get" : { + "tags" : [ "Checkpoint" ], + "summary" : "List the process checkpoints", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ProcessCheckpointEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "Checkpoint" ], + "operationId" : "uploadCheckpoint", + "consumes" : [ "multipart/form-data" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/MultipartInput" + } + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{id}/checkpoint/restore" : { + "post" : { + "tags" : [ "Checkpoint" ], + "summary" : "Restore process from checkpoint", + "description" : "", + "operationId" : "restore", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/RestoreCheckpointRequest" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/ResumeProcessResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{id}/decrypt" : { + "post" : { + "tags" : [ "Process" ], + "operationId" : "decrypt", + "consumes" : [ "application/octet-stream" ], + "produces" : [ "application/octet-stream" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{id}/disable/{disabled}" : { + "post" : { + "tags" : [ "Process" ], + "summary" : "Disable a process", + "description" : "", + "operationId" : "disable", + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "disabled", + "in" : "path", + "required" : true, + "type" : "boolean" + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{id}/fork" : { + "post" : { + "tags" : [ "Process" ], + "summary" : "Fork a process", + "description" : "", + "operationId" : "fork", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "object", + "additionalProperties" : { + "type" : "object" + } + } + }, { + "name" : "sync", + "in" : "query", + "required" : false, + "type" : "boolean", + "default" : false + }, { + "name" : "out", + "in" : "query", + "required" : false, + "type" : "array", + "items" : { + "type" : "string" + }, + "collectionFormat" : "multi" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/StartProcessResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{id}/kv/{key}" : { + "delete" : { + "tags" : [ "Process KV store" ], + "summary" : "Delete KV", + "description" : "", + "operationId" : "removeKey", + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "key", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{id}/kv/{key}/inc" : { + "post" : { + "tags" : [ "Process KV store" ], + "summary" : "Inc long KV", + "description" : "", + "operationId" : "incLong", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "key", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "integer", + "format" : "int64" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{id}/kv/{key}/long" : { + "get" : { + "tags" : [ "Process KV store" ], + "summary" : "Get long KV", + "description" : "", + "operationId" : "getLong", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "key", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "integer", + "format" : "int64" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "put" : { + "tags" : [ "Process KV store" ], + "summary" : "Put long KV", + "description" : "", + "operationId" : "putLong", + "consumes" : [ "application/json" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "key", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : true, + "schema" : { + "type" : "integer", + "format" : "int64" + } + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{id}/kv/{key}/string" : { + "get" : { + "tags" : [ "Process KV store" ], + "summary" : "Get string KV", + "description" : "", + "operationId" : "getString", + "produces" : [ "text/plain" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "key", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "string" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "put" : { + "tags" : [ "Process KV store" ], + "summary" : "Put string KV", + "description" : "", + "operationId" : "putString", + "consumes" : [ "application/json" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "key", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : true, + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{id}/log" : { + "get" : { + "tags" : [ "Process" ], + "summary" : "Retrieve the log", + "description" : "", + "operationId" : "getLog", + "produces" : [ "application/octet-stream" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "range", + "in" : "header", + "required" : false, + "type" : "string" + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ], + "deprecated" : true + }, + "post" : { + "tags" : [ "Process" ], + "operationId" : "appendLog", + "consumes" : [ "application/octet-stream" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ], + "deprecated" : true + } + }, + "/api/v1/process/{id}/meta" : { + "post" : { + "tags" : [ "Process" ], + "summary" : "Update process metadata", + "description" : "", + "operationId" : "updateMetadata", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "object", + "additionalProperties" : { + "type" : "object" + } + } + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{id}/ping" : { + "post" : { + "tags" : [ "ProcessHeartbeat" ], + "summary" : "Process heartbeat", + "description" : "", + "operationId" : "ping", + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + } ] + } + }, + "/api/v1/process/{id}/resume/{eventName}" : { + "post" : { + "tags" : [ "Process" ], + "summary" : "Resume a process", + "description" : "", + "operationId" : "resume", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "eventName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "saveAs", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "object", + "additionalProperties" : { + "type" : "object" + } + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/ResumeProcessResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{id}/state/snapshot" : { + "get" : { + "tags" : [ "Process" ], + "summary" : "Download a process state snapshot", + "description" : "", + "operationId" : "downloadState", + "produces" : [ "application/zip" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "file" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{id}/state/snapshot/{name}" : { + "get" : { + "tags" : [ "Process" ], + "summary" : "Download a single file from a process state snapshot", + "description" : "", + "operationId" : "downloadStateFile", + "produces" : [ "application/octet-stream" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "name", + "in" : "path", + "required" : true, + "type" : "string", + "maxLength" : 2147483647, + "minLength" : 1, + "pattern" : ".*" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "file" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{id}/status" : { + "post" : { + "tags" : [ "Process" ], + "summary" : "Update process status", + "description" : "", + "operationId" : "updateStatus", + "consumes" : [ "text/plain" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "agentId", + "in" : "query", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : true, + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{id}/subprocess" : { + "get" : { + "tags" : [ "Process" ], + "summary" : "List subprocesses of a parent process", + "description" : "", + "operationId" : "listSubprocesses", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "tags", + "in" : "query", + "required" : false, + "type" : "array", + "items" : { + "type" : "string" + }, + "collectionFormat" : "multi" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ProcessEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{id}/wait" : { + "post" : { + "tags" : [ "Process" ], + "summary" : "Set the process' wait condition", + "description" : "", + "operationId" : "setWaitCondition", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "object", + "additionalProperties" : { + "type" : "object" + } + } + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{id}/waitForCompletion" : { + "get" : { + "tags" : [ "Process" ], + "summary" : "Wait for a process to finish", + "description" : "", + "operationId" : "waitForCompletion", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "timeout", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : -1, + "format" : "int64" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/ProcessEntry" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{instanceId}/history" : { + "get" : { + "tags" : [ "Process" ], + "summary" : "Get process status history", + "description" : "", + "operationId" : "getStatusHistory", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "instanceId", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ProcessStatusHistoryEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{instanceId}/waits" : { + "get" : { + "tags" : [ "Process" ], + "summary" : "Get process' wait conditions", + "description" : "", + "operationId" : "getWait", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "instanceId", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/ProcessWaitEntry" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{processInstanceId}/event" : { + "get" : { + "tags" : [ "Process Events" ], + "summary" : "List process events", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "processInstanceId", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "type", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "after", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "fromId", + "in" : "query", + "required" : false, + "type" : "integer", + "format" : "int64" + }, { + "name" : "eventCorrelationId", + "in" : "query", + "required" : false, + "type" : "string", + "format" : "uuid" + }, { + "name" : "eventPhase", + "in" : "query", + "required" : false, + "type" : "string", + "enum" : [ "PRE", "POST" ] + }, { + "name" : "includeAll", + "in" : "query", + "required" : false, + "type" : "boolean", + "default" : false + }, { + "name" : "limit", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : -1, + "format" : "int32" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ProcessEventEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "Process Events" ], + "summary" : "Register a process event", + "description" : "", + "operationId" : "event", + "consumes" : [ "application/json" ], + "parameters" : [ { + "name" : "processInstanceId", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/ProcessEventRequest" + } + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "session_key" : [ ] + }, { + "api_key" : [ ] + }, { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{processInstanceId}/eventBatch" : { + "post" : { + "tags" : [ "Process Events" ], + "summary" : "Register multiple events for the specified process", + "description" : "", + "operationId" : "batchEvent", + "consumes" : [ "application/json" ], + "parameters" : [ { + "name" : "processInstanceId", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ProcessEventRequest" + } + } + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "session_key" : [ ] + }, { + "api_key" : [ ] + }, { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{processInstanceId}/form" : { + "get" : { + "tags" : [ "Process Forms" ], + "summary" : "List the available forms", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "processInstanceId", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/FormListEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{processInstanceId}/form/{formName}" : { + "get" : { + "tags" : [ "Process Forms" ], + "summary" : "Get the current state of a form", + "description" : "", + "operationId" : "get", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "processInstanceId", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "formName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/FormInstanceEntry" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "Process Forms" ], + "summary" : "Submit JSON form data", + "description" : "", + "operationId" : "submit", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "processInstanceId", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "formName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "object", + "additionalProperties" : { + "type" : "object" + } + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/FormSubmitResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{processInstanceId}/form/{formName}/multipart" : { + "post" : { + "tags" : [ "Process Forms" ], + "summary" : "Submit multipart form data", + "description" : "", + "operationId" : "submit", + "consumes" : [ "multipart/form-data" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "processInstanceId", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "formName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/FormSubmitResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/process/{processInstanceId}/lock/{lockName}" : { + "post" : { + "tags" : [ "Process Locks" ], + "summary" : "Try lock", + "description" : "", + "operationId" : "tryLock", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "processInstanceId", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "lockName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "scope", + "in" : "query", + "required" : false, + "type" : "string", + "default" : "PROJECT", + "enum" : [ "ORG", "PROJECT" ] + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/LockResult" + } + } + }, + "security" : [ { + "session_key" : [ ] + } ] + } + }, + "/api/v1/process/{processInstanceId}/unlock/{lockName}" : { + "post" : { + "tags" : [ "Process Locks" ], + "summary" : "Releases the lock", + "description" : "", + "operationId" : "unlock", + "parameters" : [ { + "name" : "processInstanceId", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "lockName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "scope", + "in" : "query", + "required" : false, + "type" : "string", + "default" : "PROJECT", + "enum" : [ "ORG", "PROJECT" ] + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "session_key" : [ ] + } ] + } + }, + "/api/v1/role" : { + "get" : { + "tags" : [ "Roles" ], + "summary" : "List roles", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/RoleEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "Roles" ], + "summary" : "Create or update a role", + "description" : "", + "operationId" : "createOrUpdate", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/RoleEntry" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/RoleOperationResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/role/{roleName}" : { + "get" : { + "tags" : [ "Roles" ], + "summary" : "Get a role's details", + "description" : "", + "operationId" : "get", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "roleName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/RoleEntry" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "delete" : { + "tags" : [ "Roles" ], + "summary" : "Delete an existing role", + "description" : "", + "operationId" : "delete", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "roleName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/role/{roleName}/ldapGroups" : { + "get" : { + "tags" : [ "Roles" ], + "summary" : "List ldap groups of a role", + "description" : "", + "operationId" : "listLdapGroups", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "roleName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "put" : { + "tags" : [ "Roles" ], + "summary" : "Add LDAP groups to a role", + "description" : "", + "operationId" : "addLdapGroups", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "roleName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "replace", + "in" : "query", + "required" : false, + "type" : "boolean", + "default" : false + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/secret/store" : { + "get" : { + "tags" : [ "Secret stores" ], + "summary" : "List of active secret stores", + "description" : "", + "operationId" : "listActiveStores", + "produces" : [ "application/json" ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/SecretStoreEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/server/maintenance-mode" : { + "post" : { + "operationId" : "maintenanceMode", + "responses" : { + "default" : { + "description" : "successful operation" + } + } + } + }, + "/api/v1/server/ping" : { + "get" : { + "operationId" : "ping", + "produces" : [ "application/json" ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/PingResponse" + } + } + } + } + }, + "/api/v1/server/version" : { + "get" : { + "operationId" : "version", + "produces" : [ "application/json" ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/VersionResponse" + } + } + } + } + }, + "/api/v1/template/alias" : { + "get" : { + "tags" : [ "TemplateAlias" ], + "summary" : "List current template aliases", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/TemplateAliasEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "TemplateAlias" ], + "summary" : "Create or update a template alias", + "description" : "", + "operationId" : "createOrUpdate", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/TemplateAliasEntry" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/TemplateAliasResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/template/alias/{alias}" : { + "delete" : { + "tags" : [ "TemplateAlias" ], + "summary" : "Delete existing template alias", + "description" : "", + "operationId" : "delete", + "parameters" : [ { + "name" : "alias", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/TemplateAliasResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/user" : { + "post" : { + "tags" : [ "Users" ], + "summary" : "Create a new user or update an existing one", + "description" : "", + "operationId" : "createOrUpdate", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/CreateUserRequest" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/CreateUserResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/user/{id}" : { + "delete" : { + "tags" : [ "Users" ], + "summary" : "Delete an existing user", + "description" : "", + "operationId" : "delete", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/DeleteUserResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/user/{username}" : { + "get" : { + "tags" : [ "Users" ], + "summary" : "Find a user", + "description" : "", + "operationId" : "findByUsername", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "username", + "in" : "path", + "required" : true, + "type" : "string", + "maxLength" : 128, + "minLength" : 0 + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/UserEntry" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/user/{username}/roles" : { + "post" : { + "tags" : [ "Users" ], + "summary" : "Update the list of roles for the existing user", + "description" : "", + "operationId" : "updateUserRoles", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "username", + "in" : "path", + "required" : true, + "type" : "string", + "maxLength" : 128, + "minLength" : 0 + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/UpdateUserRolesRequest" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/userldapgroup/sync" : { + "post" : { + "tags" : [ "UserLdapGroup" ], + "summary" : "Sync ldap groups for a user", + "description" : "", + "operationId" : "sync", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/SyncUserLdapGroupRequest" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v1/{entityType}/canCreate" : { + "get" : { + "tags" : [ "PolicyCheck" ], + "summary" : "Check for new entity creation", + "description" : "", + "operationId" : "canCreate", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "entityType", + "in" : "path", + "required" : true, + "type" : "string", + "enum" : [ "ORGANIZATION", "PROJECT", "REPOSITORY", "SECRET", "JSON_STORE", "JSON_STORE_ITEM", "JSON_STORE_QUERY", "TRIGGER" ] + }, { + "name" : "orgName", + "in" : "query", + "required" : false, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "boolean" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v2/org/{orgName}/project/{projectName}" : { + "get" : { + "tags" : [ "Projects" ], + "summary" : "Get an existing project", + "description" : "", + "operationId" : "get", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "projectName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/ProjectEntry" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v2/org/{orgName}/secret" : { + "get" : { + "tags" : [ "SecretsV2" ], + "summary" : "List secrets", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "offset", + "in" : "query", + "required" : false, + "type" : "integer", + "format" : "int32" + }, { + "name" : "limit", + "in" : "query", + "required" : false, + "type" : "integer", + "format" : "int32" + }, { + "name" : "filter", + "in" : "query", + "required" : false, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/SecretEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v2/org/{orgName}/secret/{secretName}" : { + "get" : { + "tags" : [ "SecretsV2" ], + "summary" : "Get an existing secret", + "description" : "", + "operationId" : "get", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "secretName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/SecretEntryV2" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "SecretsV2" ], + "summary" : "Updates an existing secret", + "description" : "", + "operationId" : "update", + "consumes" : [ "multipart/form-data" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "secretName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/MultipartInput" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v2/policy" : { + "get" : { + "tags" : [ "Policy" ], + "summary" : "List policies, optionally filtering by organization, project and/or user links", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgName", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "projectName", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "userName", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "userDomain", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "userType", + "in" : "query", + "required" : false, + "type" : "string", + "enum" : [ "LOCAL", "LDAP", "SSO" ] + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/PolicyEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "Policy" ], + "summary" : "Create or update a policy", + "description" : "", + "operationId" : "createOrUpdate", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/PolicyEntry" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/PolicyOperationResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v2/policy/refresh" : { + "post" : { + "tags" : [ "Policy" ], + "operationId" : "refresh", + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v2/policy/{policyName}" : { + "get" : { + "tags" : [ "Policy" ], + "summary" : "Get an existing policy", + "description" : "", + "operationId" : "get", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "policyName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/PolicyEntry" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "delete" : { + "tags" : [ "Policy" ], + "summary" : "Delete an existing policy", + "description" : "", + "operationId" : "delete", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "policyName", + "in" : "path", + "required" : true, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v2/policy/{policyName}/link" : { + "put" : { + "tags" : [ "Policy" ], + "summary" : "Link an existing policy to an organization, a project or user", + "description" : "", + "operationId" : "link", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "policyName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/PolicyLinkEntry" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "delete" : { + "tags" : [ "Policy" ], + "summary" : "Unlink an existing policy", + "description" : "", + "operationId" : "unlink", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "policyName", + "in" : "path", + "required" : true, + "type" : "string" + }, { + "name" : "orgName", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "projectName", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "userName", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "userDomain", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "userType", + "in" : "query", + "required" : false, + "type" : "string", + "enum" : [ "LOCAL", "LDAP", "SSO" ] + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v2/process" : { + "get" : { + "tags" : [ "ProcessV2" ], + "summary" : "List processes", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgId", + "in" : "query", + "required" : false, + "type" : "string", + "format" : "uuid" + }, { + "name" : "orgName", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "projectId", + "in" : "query", + "required" : false, + "type" : "string", + "format" : "uuid" + }, { + "name" : "projectName", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "repoId", + "in" : "query", + "required" : false, + "type" : "string", + "format" : "uuid" + }, { + "name" : "repoName", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "afterCreatedAt", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "beforeCreatedAt", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "tags", + "in" : "query", + "required" : false, + "type" : "array", + "items" : { + "type" : "string" + }, + "collectionFormat" : "multi" + }, { + "name" : "status", + "in" : "query", + "required" : false, + "type" : "string", + "enum" : [ "NEW", "PREPARING", "ENQUEUED", "WAITING", "STARTING", "RUNNING", "SUSPENDED", "RESUMING", "FINISHED", "FAILED", "CANCELLED", "TIMED_OUT" ] + }, { + "name" : "initiator", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "parentInstanceId", + "in" : "query", + "required" : false, + "type" : "string", + "format" : "uuid" + }, { + "name" : "include", + "in" : "query", + "required" : false, + "type" : "array", + "items" : { + "type" : "string", + "enum" : [ "CHECKPOINTS", "CHECKPOINTS_HISTORY", "CHILDREN_IDS", "STATUS_HISTORY" ] + }, + "collectionFormat" : "multi" + }, { + "name" : "limit", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 30, + "format" : "int32" + }, { + "name" : "offset", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 0, + "format" : "int32" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ProcessEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v2/process/count" : { + "get" : { + "tags" : [ "ProcessV2" ], + "summary" : "Count processes", + "description" : "", + "operationId" : "count", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "orgId", + "in" : "query", + "required" : false, + "type" : "string", + "format" : "uuid" + }, { + "name" : "orgName", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "projectId", + "in" : "query", + "required" : false, + "type" : "string", + "format" : "uuid" + }, { + "name" : "projectName", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "repoId", + "in" : "query", + "required" : false, + "type" : "string", + "format" : "uuid" + }, { + "name" : "repoName", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "afterCreatedAt", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "beforeCreatedAt", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "tags", + "in" : "query", + "required" : false, + "type" : "array", + "items" : { + "type" : "string" + }, + "collectionFormat" : "multi" + }, { + "name" : "status", + "in" : "query", + "required" : false, + "type" : "string", + "enum" : [ "NEW", "PREPARING", "ENQUEUED", "WAITING", "STARTING", "RUNNING", "SUSPENDED", "RESUMING", "FINISHED", "FAILED", "CANCELLED", "TIMED_OUT" ] + }, { + "name" : "initiator", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "parentInstanceId", + "in" : "query", + "required" : false, + "type" : "string", + "format" : "uuid" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "integer", + "format" : "int32" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v2/process/requirements" : { + "get" : { + "tags" : [ "ProcessV2" ], + "summary" : "List process requirements", + "description" : "", + "operationId" : "listRequirements", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "status", + "in" : "query", + "required" : false, + "type" : "string", + "enum" : [ "NEW", "PREPARING", "ENQUEUED", "WAITING", "STARTING", "RUNNING", "SUSPENDED", "RESUMING", "FINISHED", "FAILED", "CANCELLED", "TIMED_OUT" ] + }, { + "name" : "limit", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 30, + "format" : "int32" + }, { + "name" : "offset", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 0, + "format" : "int32" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ProcessRequirementsEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v2/process/{id}" : { + "get" : { + "tags" : [ "ProcessV2" ], + "summary" : "Get a process' details", + "description" : "", + "operationId" : "get", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "include", + "in" : "query", + "required" : false, + "type" : "array", + "items" : { + "type" : "string", + "enum" : [ "CHECKPOINTS", "CHECKPOINTS_HISTORY", "CHILDREN_IDS", "STATUS_HISTORY" ] + }, + "collectionFormat" : "multi" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/ProcessEntry" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v2/process/{id}/checkpoint" : { + "get" : { + "tags" : [ "CheckpointV2" ], + "summary" : "Process checkpoint", + "description" : "", + "operationId" : "processCheckpoint", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "name", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "action", + "in" : "query", + "required" : false, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericCheckpointResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v2/process/{id}/log/segment" : { + "get" : { + "tags" : [ "ProcessLogV2" ], + "summary" : "List process log segments", + "description" : "", + "operationId" : "segments", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "limit", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 30, + "format" : "int32" + }, { + "name" : "offset", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 0, + "format" : "int32" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/LogSegment" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "ProcessLogV2" ], + "summary" : "Create process log segment", + "description" : "", + "operationId" : "segment", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/LogSegmentRequest" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/LogSegmentOperationResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v2/process/{id}/log/segment/{segmentId}" : { + "post" : { + "tags" : [ "ProcessLogV2" ], + "summary" : "Update process log segment", + "description" : "", + "operationId" : "updateSegment", + "consumes" : [ "application/json" ], + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "segmentId", + "in" : "path", + "required" : true, + "type" : "integer", + "format" : "int64" + }, { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/LogSegmentUpdateRequest" + } + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/LogSegmentOperationResponse" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v2/process/{id}/log/segment/{segmentId}/data" : { + "get" : { + "tags" : [ "ProcessLogV2" ], + "summary" : "Retrieve the log", + "description" : "", + "operationId" : "data", + "produces" : [ "application/octet-stream" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "segmentId", + "in" : "path", + "required" : true, + "type" : "integer", + "format" : "int64" + }, { + "name" : "range", + "in" : "header", + "required" : false, + "type" : "string" + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + }, + "post" : { + "tags" : [ "ProcessLogV2" ], + "operationId" : "append", + "consumes" : [ "application/octet-stream" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + }, { + "name" : "segmentId", + "in" : "path", + "required" : true, + "type" : "integer", + "format" : "int64" + } ], + "responses" : { + "default" : { + "description" : "successful operation" + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v2/repository/refresh" : { + "post" : { + "tags" : [ "RepositoriesV2" ], + "summary" : "Refresh repositories by their IDs", + "description" : "", + "operationId" : "refreshRepository", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "ids", + "in" : "query", + "required" : false, + "type" : "array", + "items" : { + "type" : "string", + "format" : "uuid" + }, + "collectionFormat" : "multi" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/GenericOperationResult" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v2/trigger" : { + "get" : { + "tags" : [ "TriggersV2" ], + "summary" : "List trigger definitions", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "type", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "orgId", + "in" : "query", + "required" : false, + "type" : "string", + "format" : "uuid" + }, { + "name" : "orgName", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "projectId", + "in" : "query", + "required" : false, + "type" : "string", + "format" : "uuid" + }, { + "name" : "projectName", + "in" : "query", + "required" : false, + "type" : "string" + }, { + "name" : "repoId", + "in" : "query", + "required" : false, + "type" : "string", + "format" : "uuid" + }, { + "name" : "repoName", + "in" : "query", + "required" : false, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/TriggerEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v2/user" : { + "get" : { + "tags" : [ "UserV2" ], + "summary" : "Returns a list of existing active users matching the supplied filter", + "description" : "", + "operationId" : "list", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "offset", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 0, + "format" : "int32" + }, { + "name" : "limit", + "in" : "query", + "required" : false, + "type" : "integer", + "default" : 10, + "format" : "int32" + }, { + "name" : "filter", + "in" : "query", + "required" : false, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/UserEntry" + } + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/api/v2/user/{id}" : { + "get" : { + "tags" : [ "UserV2" ], + "summary" : "Get an existing user", + "description" : "", + "operationId" : "get", + "produces" : [ "application/json" ], + "parameters" : [ { + "name" : "id", + "in" : "path", + "required" : true, + "type" : "string", + "format" : "uuid" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "$ref" : "#/definitions/UserEntry" + } + } + }, + "security" : [ { + "api_key" : [ ] + }, { + "session_key" : [ ] + }, { + "ldap" : [ ] + } ] + } + }, + "/events/github/webhook" : { + "post" : { + "tags" : [ "GitHub Events" ], + "summary" : "Handles GitHub repository level events", + "description" : "", + "operationId" : "onEvent", + "consumes" : [ "application/json" ], + "produces" : [ "text/plain" ], + "parameters" : [ { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "type" : "object", + "additionalProperties" : { + "type" : "object" + } + } + }, { + "name" : "X-GitHub-Delivery", + "in" : "header", + "required" : false, + "type" : "string" + }, { + "name" : "X-GitHub-Event", + "in" : "header", + "required" : false, + "type" : "string" + } ], + "responses" : { + "200" : { + "description" : "successful operation", + "schema" : { + "type" : "string" + } + } + } + } + } + }, + "securityDefinitions" : { + "api_key" : { + "description" : "API key", + "type" : "apiKey", + "name" : "api_key", + "in" : "header" + }, + "ldap" : { + "description" : "AD/LDAP username/password", + "type" : "basic" + }, + "session_key" : { + "description" : "Process session key", + "type" : "apiKey", + "name" : "session_key", + "in" : "header" + } + }, + "definitions" : { + "AddTeamLdapGroupsResponse" : { + "type" : "object", + "properties" : { + "ok" : { + "type" : "boolean" + } + } + }, + "AddTeamUsersResponse" : { + "type" : "object", + "properties" : { + "ok" : { + "type" : "boolean" + } + } + }, + "AgentWorkerEntry" : { + "type" : "object", + "properties" : { + "channelId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "agentId" : { + "type" : "string", + "readOnly" : true + }, + "userAgent" : { + "type" : "string", + "readOnly" : true + }, + "capabilities" : { + "type" : "object", + "readOnly" : true, + "additionalProperties" : { + "type" : "object" + } + } + } + }, + "ApiKeyEntry" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "userId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "name" : { + "type" : "string", + "readOnly" : true + }, + "expiredAt" : { + "type" : "string", + "format" : "date-time", + "readOnly" : true + } + } + }, + "AuditLogEntry" : { + "type" : "object", + "properties" : { + "entryDate" : { + "type" : "string", + "format" : "date-time", + "readOnly" : true + }, + "action" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "CREATE", "UPDATE", "DELETE", "ACCESS" ] + }, + "object" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "API_KEY", "EXTERNAL_EVENT", "JSON_STORE", "JSON_STORE_DATA", "JSON_STORE_QUERY", "ORGANIZATION", "POLICY", "PROJECT", "PROCESS", "ROLE", "SECRET", "SYSTEM", "TEAM", "USER", "INVENTORY" ] + }, + "details" : { + "type" : "object", + "readOnly" : true, + "additionalProperties" : { + "type" : "object" + } + }, + "user" : { + "readOnly" : true, + "$ref" : "#/definitions/EntityOwner" + } + } + }, + "CheckpointRestoreHistoryEntry" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "integer", + "format" : "int64", + "readOnly" : true + }, + "checkpointId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "processStatus" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "NEW", "PREPARING", "ENQUEUED", "WAITING", "STARTING", "RUNNING", "SUSPENDED", "RESUMING", "FINISHED", "FAILED", "CANCELLED", "TIMED_OUT" ] + }, + "changeDate" : { + "type" : "string", + "format" : "date-time", + "readOnly" : true + } + } + }, + "CreateApiKeyRequest" : { + "type" : "object", + "properties" : { + "userId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "username" : { + "type" : "string", + "readOnly" : true + }, + "userDomain" : { + "type" : "string", + "readOnly" : true + }, + "userType" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "LOCAL", "LDAP", "SSO" ] + }, + "name" : { + "type" : "string", + "readOnly" : true + } + } + }, + "CreateApiKeyResponse" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "key" : { + "type" : "string", + "readOnly" : true + }, + "ok" : { + "type" : "boolean" + } + } + }, + "CreateInventoryQueryResponse" : { + "type" : "object", + "properties" : { + "result" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "CREATED", "UPDATED", "DELETED", "ALREADY_EXISTS", "NOT_FOUND", "VALIDATED" ] + }, + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "ok" : { + "type" : "boolean" + } + } + }, + "CreateInventoryResponse" : { + "type" : "object", + "properties" : { + "result" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "CREATED", "UPDATED", "DELETED", "ALREADY_EXISTS", "NOT_FOUND", "VALIDATED" ] + }, + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "ok" : { + "type" : "boolean" + } + } + }, + "CreateOrganizationResponse" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "result" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "CREATED", "UPDATED", "DELETED", "ALREADY_EXISTS", "NOT_FOUND", "VALIDATED" ] + }, + "ok" : { + "type" : "boolean" + } + } + }, + "CreateTeamResponse" : { + "type" : "object", + "properties" : { + "result" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "CREATED", "UPDATED", "DELETED", "ALREADY_EXISTS", "NOT_FOUND", "VALIDATED" ] + }, + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "ok" : { + "type" : "boolean" + } + } + }, + "CreateUserRequest" : { + "type" : "object", + "required" : [ "username" ], + "properties" : { + "username" : { + "type" : "string", + "readOnly" : true, + "minLength" : 0, + "maxLength" : 128 + }, + "userDomain" : { + "type" : "string", + "readOnly" : true, + "minLength" : 0, + "maxLength" : 512 + }, + "displayName" : { + "type" : "string", + "readOnly" : true, + "minLength" : 0, + "maxLength" : 1024 + }, + "email" : { + "type" : "string", + "readOnly" : true, + "minLength" : 0, + "maxLength" : 512 + }, + "disabled" : { + "type" : "boolean", + "readOnly" : true + }, + "roles" : { + "type" : "array", + "readOnly" : true, + "uniqueItems" : true, + "items" : { + "type" : "string" + } + }, + "type" : { + "type" : "string", + "enum" : [ "LOCAL", "LDAP", "SSO" ] + } + } + }, + "CreateUserResponse" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "username" : { + "type" : "string", + "readOnly" : true + }, + "result" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "CREATED", "UPDATED", "DELETED", "ALREADY_EXISTS", "NOT_FOUND", "VALIDATED" ] + }, + "ok" : { + "type" : "boolean" + } + } + }, + "DeleteInventoryDataResponse" : { + "type" : "object", + "properties" : { + "ok" : { + "type" : "boolean" + } + } + }, + "DeleteInventoryQueryResponse" : { + "type" : "object", + "properties" : { + "ok" : { + "type" : "boolean" + } + } + }, + "DeleteUserResponse" : { + "type" : "object", + "properties" : { + "ok" : { + "type" : "boolean" + } + } + }, + "EncryptValueResponse" : { + "type" : "object", + "properties" : { + "data" : { + "type" : "string", + "readOnly" : true + }, + "ok" : { + "type" : "boolean" + } + } + }, + "EntityOwner" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "username" : { + "type" : "string", + "readOnly" : true + }, + "userDomain" : { + "type" : "string", + "readOnly" : true + }, + "displayName" : { + "type" : "string", + "readOnly" : true + }, + "userType" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "LOCAL", "LDAP", "SSO" ] + } + } + }, + "Field" : { + "type" : "object", + "properties" : { + "name" : { + "type" : "string" + }, + "label" : { + "type" : "string" + }, + "type" : { + "type" : "string" + }, + "cardinality" : { + "type" : "string", + "enum" : [ "ONE_OR_NONE", "ONE_AND_ONLY_ONE", "AT_LEAST_ONE", "ANY" ] + }, + "value" : { + "type" : "object" + }, + "allowedValue" : { + "type" : "object" + }, + "options" : { + "type" : "object", + "additionalProperties" : { + "type" : "object" + } + } + } + }, + "FormInstanceEntry" : { + "type" : "object", + "properties" : { + "processInstanceId" : { + "type" : "string", + "readOnly" : true + }, + "name" : { + "type" : "string", + "readOnly" : true + }, + "fields" : { + "type" : "array", + "readOnly" : true, + "items" : { + "$ref" : "#/definitions/Field" + } + }, + "custom" : { + "type" : "boolean", + "readOnly" : true + }, + "yield" : { + "type" : "boolean", + "readOnly" : true + } + } + }, + "FormListEntry" : { + "type" : "object", + "properties" : { + "name" : { + "type" : "string", + "readOnly" : true + }, + "custom" : { + "type" : "boolean", + "readOnly" : true + }, + "yield" : { + "type" : "boolean", + "readOnly" : true + }, + "runAs" : { + "type" : "object", + "readOnly" : true, + "additionalProperties" : { + "type" : "object" + } + } + } + }, + "FormSessionResponse" : { + "type" : "object", + "properties" : { + "uri" : { + "type" : "string", + "readOnly" : true + } + } + }, + "FormSubmitResponse" : { + "type" : "object", + "properties" : { + "processInstanceId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "errors" : { + "type" : "object", + "readOnly" : true, + "additionalProperties" : { + "type" : "string" + } + }, + "ok" : { + "type" : "boolean" + } + } + }, + "GenericCheckpointResponse" : { + "type" : "object", + "properties" : { + "ok" : { + "type" : "boolean" + } + } + }, + "GenericOperationResult" : { + "type" : "object", + "properties" : { + "result" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "CREATED", "UPDATED", "DELETED", "ALREADY_EXISTS", "NOT_FOUND", "VALIDATED" ] + }, + "ok" : { + "type" : "boolean" + } + } + }, + "InputPart" : { + "type" : "object", + "properties" : { + "headers" : { + "type" : "object", + "additionalProperties" : { + "type" : "array", + "items" : { + "type" : "string" + } + } + }, + "mediaType" : { + "$ref" : "#/definitions/MediaType" + }, + "bodyAsString" : { + "type" : "string" + }, + "contentTypeFromMessage" : { + "type" : "boolean" + } + } + }, + "InventoryEntry" : { + "type" : "object", + "required" : [ "name" ], + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "name" : { + "type" : "string", + "readOnly" : true + }, + "orgId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "orgName" : { + "type" : "string", + "readOnly" : true + }, + "visibility" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "PUBLIC", "PRIVATE" ] + }, + "owner" : { + "readOnly" : true, + "$ref" : "#/definitions/InventoryOwner" + }, + "parent" : { + "readOnly" : true, + "$ref" : "#/definitions/InventoryEntry" + }, + "parentId" : { + "type" : "string", + "format" : "uuid" + } + } + }, + "InventoryOwner" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "username" : { + "type" : "string", + "readOnly" : true + } + } + }, + "InventoryQueryEntry" : { + "type" : "object", + "required" : [ "name", "text" ], + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "name" : { + "type" : "string", + "readOnly" : true + }, + "inventoryId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "text" : { + "type" : "string", + "readOnly" : true + } + } + }, + "JsonStoreCapacity" : { + "type" : "object", + "properties" : { + "size" : { + "type" : "integer", + "format" : "int64", + "readOnly" : true + }, + "maxSize" : { + "type" : "integer", + "format" : "int64", + "readOnly" : true + } + } + }, + "JsonStoreEntry" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "name" : { + "type" : "string", + "readOnly" : true + }, + "orgId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "orgName" : { + "type" : "string", + "readOnly" : true + }, + "visibility" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "PUBLIC", "PRIVATE" ] + }, + "owner" : { + "readOnly" : true, + "$ref" : "#/definitions/EntityOwner" + } + } + }, + "JsonStoreQueryEntry" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "storeId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "name" : { + "type" : "string", + "readOnly" : true + }, + "text" : { + "type" : "string", + "readOnly" : true + } + } + }, + "JsonStoreQueryRequest" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "name" : { + "type" : "string", + "readOnly" : true + }, + "text" : { + "type" : "string", + "readOnly" : true + } + } + }, + "JsonStoreRequest" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "name" : { + "type" : "string", + "readOnly" : true + }, + "visibility" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "PUBLIC", "PRIVATE" ] + }, + "orgName" : { + "type" : "string", + "readOnly" : true + }, + "owner" : { + "readOnly" : true, + "$ref" : "#/definitions/EntityOwner" + } + } + }, + "KvEntry" : { + "type" : "object", + "properties" : { + "key" : { + "type" : "string", + "readOnly" : true + }, + "value" : { + "type" : "object", + "readOnly" : true + }, + "lastUpdatedAt" : { + "type" : "string", + "format" : "date-time", + "readOnly" : true + } + } + }, + "LdapGroupSearchResult" : { + "type" : "object", + "properties" : { + "groupName" : { + "type" : "string", + "readOnly" : true + }, + "displayName" : { + "type" : "string", + "readOnly" : true + } + } + }, + "LockEntry" : { + "type" : "object", + "properties" : { + "instanceId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "orgId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "projectId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "name" : { + "type" : "string", + "readOnly" : true + }, + "scope" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "ORG", "PROJECT" ] + } + } + }, + "LockResult" : { + "type" : "object", + "properties" : { + "info" : { + "readOnly" : true, + "$ref" : "#/definitions/LockEntry" + }, + "acquired" : { + "type" : "boolean", + "readOnly" : true + } + } + }, + "LogSegment" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "integer", + "format" : "int64", + "readOnly" : true + }, + "correlationId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "name" : { + "type" : "string", + "readOnly" : true + }, + "status" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "OK", "FAILED", "RUNNING" ] + }, + "statusUpdatedAt" : { + "type" : "string", + "format" : "date-time", + "readOnly" : true + }, + "createdAt" : { + "type" : "string", + "format" : "date-time", + "readOnly" : true + }, + "warnings" : { + "type" : "integer", + "format" : "int32", + "readOnly" : true + }, + "errors" : { + "type" : "integer", + "format" : "int32", + "readOnly" : true + } + } + }, + "LogSegmentOperationResponse" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "integer", + "format" : "int64", + "readOnly" : true + }, + "result" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "CREATED", "UPDATED", "DELETED", "ALREADY_EXISTS", "NOT_FOUND", "VALIDATED" ] + }, + "ok" : { + "type" : "boolean" + } + } + }, + "LogSegmentRequest" : { + "type" : "object", + "properties" : { + "correlationId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "name" : { + "type" : "string", + "readOnly" : true + }, + "createdAt" : { + "type" : "string", + "format" : "date-time", + "readOnly" : true + } + } + }, + "LogSegmentUpdateRequest" : { + "type" : "object", + "properties" : { + "status" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "OK", "FAILED", "RUNNING" ] + }, + "warnings" : { + "type" : "integer", + "format" : "int32", + "readOnly" : true + }, + "errors" : { + "type" : "integer", + "format" : "int32", + "readOnly" : true + } + } + }, + "MediaType" : { + "type" : "object", + "properties" : { + "type" : { + "type" : "string" + }, + "subtype" : { + "type" : "string" + }, + "parameters" : { + "type" : "object", + "additionalProperties" : { + "type" : "string" + } + }, + "wildcardType" : { + "type" : "boolean" + }, + "wildcardSubtype" : { + "type" : "boolean" + } + } + }, + "MultipartInput" : { + "type" : "object", + "properties" : { + "parts" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/InputPart" + } + }, + "preamble" : { + "type" : "string" + } + } + }, + "OrganizationEntry" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "name" : { + "type" : "string", + "readOnly" : true + }, + "owner" : { + "readOnly" : true, + "$ref" : "#/definitions/EntityOwner" + }, + "visibility" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "PUBLIC", "PRIVATE" ] + }, + "meta" : { + "type" : "object", + "readOnly" : true, + "additionalProperties" : { + "type" : "object" + } + }, + "cfg" : { + "type" : "object", + "readOnly" : true, + "additionalProperties" : { + "type" : "object" + } + } + } + }, + "PingResponse" : { + "type" : "object", + "properties" : { + "ok" : { + "type" : "boolean", + "readOnly" : true + } + } + }, + "PolicyEntry" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "parentId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "name" : { + "type" : "string", + "readOnly" : true + }, + "rules" : { + "type" : "object", + "readOnly" : true, + "additionalProperties" : { + "type" : "object" + } + } + } + }, + "PolicyLinkEntry" : { + "type" : "object", + "properties" : { + "orgName" : { + "type" : "string", + "readOnly" : true + }, + "projectName" : { + "type" : "string", + "readOnly" : true + }, + "userName" : { + "type" : "string", + "readOnly" : true + }, + "userDomain" : { + "type" : "string", + "readOnly" : true + } + } + }, + "PolicyOperationResponse" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "result" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "CREATED", "UPDATED", "DELETED", "ALREADY_EXISTS", "NOT_FOUND", "VALIDATED" ] + } + } + }, + "ProcessCheckpointEntry" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "name" : { + "type" : "string", + "readOnly" : true + }, + "createdAt" : { + "type" : "string", + "format" : "date-time", + "readOnly" : true + }, + "correlationId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + } + } + }, + "ProcessEntry" : { + "type" : "object", + "properties" : { + "instanceId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "kind" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "DEFAULT", "FAILURE_HANDLER", "CANCEL_HANDLER", "TIMEOUT_HANDLER" ] + }, + "parentInstanceId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "orgId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "orgName" : { + "type" : "string", + "readOnly" : true + }, + "projectId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "projectName" : { + "type" : "string", + "readOnly" : true + }, + "repoId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "repoName" : { + "type" : "string", + "readOnly" : true + }, + "repoUrl" : { + "type" : "string", + "readOnly" : true + }, + "repoPath" : { + "type" : "string", + "readOnly" : true + }, + "commitId" : { + "type" : "string", + "readOnly" : true + }, + "commitBranch" : { + "type" : "string", + "readOnly" : true + }, + "commitMsg" : { + "type" : "string", + "readOnly" : true + }, + "createdAt" : { + "type" : "string", + "format" : "date-time", + "readOnly" : true + }, + "initiator" : { + "type" : "string", + "readOnly" : true + }, + "initiatorId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "status" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "NEW", "PREPARING", "ENQUEUED", "WAITING", "STARTING", "RUNNING", "SUSPENDED", "RESUMING", "FINISHED", "FAILED", "CANCELLED", "TIMED_OUT" ] + }, + "lastAgentId" : { + "type" : "string", + "readOnly" : true + }, + "startAt" : { + "type" : "string", + "format" : "date-time", + "readOnly" : true + }, + "lastUpdatedAt" : { + "type" : "string", + "format" : "date-time", + "readOnly" : true + }, + "lastRunAt" : { + "type" : "string", + "format" : "date-time", + "readOnly" : true + }, + "logFileName" : { + "type" : "string", + "readOnly" : true + }, + "tags" : { + "type" : "array", + "readOnly" : true, + "uniqueItems" : true, + "items" : { + "type" : "string" + } + }, + "childrenIds" : { + "type" : "array", + "readOnly" : true, + "uniqueItems" : true, + "items" : { + "type" : "string", + "format" : "uuid" + } + }, + "meta" : { + "type" : "object", + "readOnly" : true, + "additionalProperties" : { + "type" : "object" + } + }, + "handlers" : { + "type" : "array", + "readOnly" : true, + "uniqueItems" : true, + "items" : { + "type" : "string" + } + }, + "requirements" : { + "type" : "object", + "readOnly" : true, + "additionalProperties" : { + "type" : "object" + } + }, + "disabled" : { + "type" : "boolean", + "readOnly" : true + }, + "checkpoints" : { + "type" : "array", + "readOnly" : true, + "items" : { + "$ref" : "#/definitions/ProcessCheckpointEntry" + } + }, + "checkpointRestoreHistory" : { + "type" : "array", + "readOnly" : true, + "items" : { + "$ref" : "#/definitions/CheckpointRestoreHistoryEntry" + } + }, + "statusHistory" : { + "type" : "array", + "readOnly" : true, + "items" : { + "$ref" : "#/definitions/ProcessStatusHistoryEntry" + } + }, + "triggeredBy" : { + "readOnly" : true, + "$ref" : "#/definitions/TriggeredByEntry" + }, + "timeout" : { + "type" : "integer", + "format" : "int64", + "readOnly" : true + }, + "suspendTimeout" : { + "type" : "integer", + "format" : "int64", + "readOnly" : true + }, + "runtime" : { + "type" : "string", + "readOnly" : true + } + } + }, + "ProcessEventEntry" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "seqId" : { + "type" : "integer", + "format" : "int64", + "readOnly" : true + }, + "eventType" : { + "type" : "string", + "readOnly" : true + }, + "data" : { + "type" : "object", + "readOnly" : true, + "additionalProperties" : { + "type" : "object" + } + }, + "eventDate" : { + "type" : "string", + "format" : "date-time", + "readOnly" : true + } + } + }, + "ProcessEventRequest" : { + "type" : "object", + "properties" : { + "eventType" : { + "type" : "string", + "readOnly" : true + }, + "eventDate" : { + "type" : "string", + "format" : "date-time", + "readOnly" : true + }, + "data" : { + "type" : "object", + "readOnly" : true, + "additionalProperties" : { + "type" : "object" + } + } + } + }, + "ProcessRequirementsEntry" : { + "type" : "object", + "properties" : { + "instanceId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "createdAt" : { + "type" : "string", + "format" : "date-time", + "readOnly" : true + }, + "requirements" : { + "type" : "object", + "readOnly" : true, + "additionalProperties" : { + "type" : "object" + } + } + } + }, + "ProcessStatusHistoryEntry" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "status" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "NEW", "PREPARING", "ENQUEUED", "WAITING", "STARTING", "RUNNING", "SUSPENDED", "RESUMING", "FINISHED", "FAILED", "CANCELLED", "TIMED_OUT" ] + }, + "changeDate" : { + "type" : "string", + "format" : "date-time", + "readOnly" : true + } + } + }, + "ProcessWaitEntry" : { + "type" : "object", + "properties" : { + "waits" : { + "type" : "array", + "readOnly" : true, + "items" : { + "type" : "object", + "additionalProperties" : { + "type" : "object" + } + } + }, + "isWaiting" : { + "type" : "boolean", + "readOnly" : true + } + } + }, + "ProjectEntry" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "name" : { + "type" : "string" + }, + "description" : { + "type" : "string", + "readOnly" : true, + "minLength" : 0, + "maxLength" : 1024 + }, + "orgId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "orgName" : { + "type" : "string", + "readOnly" : true + }, + "repositories" : { + "type" : "object", + "readOnly" : true, + "additionalProperties" : { + "$ref" : "#/definitions/RepositoryEntry" + } + }, + "cfg" : { + "type" : "object", + "readOnly" : true, + "additionalProperties" : { + "type" : "object" + } + }, + "visibility" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "PUBLIC", "PRIVATE" ] + }, + "owner" : { + "readOnly" : true, + "$ref" : "#/definitions/EntityOwner" + }, + "acceptsRawPayload" : { + "type" : "boolean", + "readOnly" : true + }, + "rawPayloadMode" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "DISABLED", "OWNERS", "TEAM_MEMBERS", "ORG_MEMBERS", "EVERYONE" ] + }, + "meta" : { + "type" : "object", + "readOnly" : true, + "additionalProperties" : { + "type" : "object" + } + }, + "outVariablesMode" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "DISABLED", "OWNERS", "TEAM_MEMBERS", "ORG_MEMBERS", "EVERYONE" ] + }, + "createdAt" : { + "type" : "string", + "format" : "date-time", + "readOnly" : true + } + } + }, + "ProjectOperationResponse" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "result" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "CREATED", "UPDATED", "DELETED", "ALREADY_EXISTS", "NOT_FOUND", "VALIDATED" ] + }, + "ok" : { + "type" : "boolean" + } + } + }, + "ProjectProcesses" : { + "type" : "object", + "properties" : { + "projectName" : { + "type" : "string", + "readOnly" : true + }, + "running" : { + "type" : "integer", + "format" : "int32", + "readOnly" : true + } + } + }, + "PublicKeyResponse" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "result" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "CREATED", "UPDATED", "DELETED", "ALREADY_EXISTS", "NOT_FOUND", "VALIDATED" ] + }, + "password" : { + "type" : "string", + "readOnly" : true + }, + "publicKey" : { + "type" : "string", + "readOnly" : true + }, + "ok" : { + "type" : "boolean" + } + } + }, + "RemoveTeamUsersResponse" : { + "type" : "object", + "properties" : { + "ok" : { + "type" : "boolean" + } + } + }, + "RepositoryEntry" : { + "type" : "object", + "required" : [ "url" ], + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "projectId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "name" : { + "type" : "string", + "readOnly" : true + }, + "url" : { + "type" : "string", + "readOnly" : true, + "minLength" : 0, + "maxLength" : 2048 + }, + "branch" : { + "type" : "string", + "readOnly" : true, + "minLength" : 0, + "maxLength" : 255 + }, + "commitId" : { + "type" : "string", + "readOnly" : true, + "minLength" : 0, + "maxLength" : 64 + }, + "path" : { + "type" : "string", + "readOnly" : true, + "minLength" : 0, + "maxLength" : 2048 + }, + "disabled" : { + "type" : "boolean", + "readOnly" : true + }, + "secretId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "secretName" : { + "type" : "string", + "readOnly" : true + }, + "secretStoreType" : { + "type" : "string", + "readOnly" : true + }, + "meta" : { + "type" : "object", + "readOnly" : true, + "additionalProperties" : { + "type" : "object" + } + }, + "triggersDisabled" : { + "type" : "boolean", + "readOnly" : true + } + } + }, + "RepositoryValidationResponse" : { + "type" : "object", + "properties" : { + "ok" : { + "type" : "boolean", + "readOnly" : true + }, + "result" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "CREATED", "UPDATED", "DELETED", "ALREADY_EXISTS", "NOT_FOUND", "VALIDATED" ] + }, + "errors" : { + "type" : "array", + "readOnly" : true, + "items" : { + "type" : "string" + } + }, + "warnings" : { + "type" : "array", + "readOnly" : true, + "items" : { + "type" : "string" + } + } + } + }, + "ResourceAccessEntry" : { + "type" : "object", + "required" : [ "level" ], + "properties" : { + "teamId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "orgName" : { + "type" : "string", + "readOnly" : true + }, + "teamName" : { + "type" : "string", + "readOnly" : true + }, + "level" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "OWNER", "WRITER", "READER" ] + } + } + }, + "RestoreCheckpointRequest" : { + "type" : "object", + "required" : [ "id" ], + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + } + } + }, + "ResumeProcessResponse" : { + "type" : "object", + "properties" : { + "ok" : { + "type" : "boolean" + } + } + }, + "RoleEntry" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "name" : { + "type" : "string", + "readOnly" : true + }, + "permissions" : { + "type" : "array", + "readOnly" : true, + "uniqueItems" : true, + "items" : { + "type" : "string" + } + } + } + }, + "RoleOperationResponse" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "result" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "CREATED", "UPDATED", "DELETED", "ALREADY_EXISTS", "NOT_FOUND", "VALIDATED" ] + } + } + }, + "Secret" : { + "type" : "object" + }, + "SecretEntry" : { + "type" : "object", + "required" : [ "name", "storeType", "type" ], + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "name" : { + "type" : "string", + "readOnly" : true + }, + "orgId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "orgName" : { + "type" : "string", + "readOnly" : true + }, + "projectId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "projectName" : { + "type" : "string", + "readOnly" : true + }, + "type" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "KEY_PAIR", "USERNAME_PASSWORD", "DATA" ] + }, + "encryptedBy" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "SERVER_KEY", "PASSWORD" ] + }, + "storeType" : { + "type" : "string", + "readOnly" : true + }, + "visibility" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "PUBLIC", "PRIVATE" ] + }, + "owner" : { + "readOnly" : true, + "$ref" : "#/definitions/EntityOwner" + } + } + }, + "SecretEntryV2" : { + "type" : "object", + "required" : [ "name", "storeType", "type" ], + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "name" : { + "type" : "string", + "readOnly" : true + }, + "orgId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "orgName" : { + "type" : "string", + "readOnly" : true + }, + "projects" : { + "type" : "array", + "readOnly" : true, + "uniqueItems" : true, + "items" : { + "$ref" : "#/definitions/ProjectEntry" + } + }, + "type" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "KEY_PAIR", "USERNAME_PASSWORD", "DATA" ] + }, + "encryptedBy" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "SERVER_KEY", "PASSWORD" ] + }, + "storeType" : { + "type" : "string", + "readOnly" : true + }, + "visibility" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "PUBLIC", "PRIVATE" ] + }, + "owner" : { + "readOnly" : true, + "$ref" : "#/definitions/EntityOwner" + }, + "createdAt" : { + "type" : "string", + "format" : "date-time", + "readOnly" : true + }, + "lastUpdatedAt" : { + "type" : "string", + "format" : "date-time", + "readOnly" : true + }, + "projectId" : { + "type" : "string", + "format" : "uuid" + }, + "projectName" : { + "type" : "string" + } + } + }, + "SecretOperationResponse" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "result" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "CREATED", "UPDATED", "DELETED", "ALREADY_EXISTS", "NOT_FOUND", "VALIDATED" ] + }, + "password" : { + "type" : "string", + "readOnly" : true + }, + "ok" : { + "type" : "boolean" + } + } + }, + "SecretStoreEntry" : { + "type" : "object", + "required" : [ "description", "storeType" ], + "properties" : { + "storeType" : { + "type" : "string", + "readOnly" : true + }, + "description" : { + "type" : "string", + "readOnly" : true + } + } + }, + "SecretUpdateRequest" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "name" : { + "type" : "string", + "readOnly" : true + }, + "owner" : { + "readOnly" : true, + "$ref" : "#/definitions/EntityOwner" + }, + "visibility" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "PUBLIC", "PRIVATE" ] + }, + "storePassword" : { + "type" : "string", + "readOnly" : true + }, + "newStorePassword" : { + "type" : "string", + "readOnly" : true + }, + "projectName" : { + "type" : "string", + "readOnly" : true + }, + "projectId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "orgId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "orgName" : { + "type" : "string", + "readOnly" : true + }, + "data" : { + "type" : "string", + "readOnly" : true + } + } + }, + "StartProcessResponse" : { + "type" : "object", + "properties" : { + "instanceId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "ok" : { + "type" : "boolean" + } + } + }, + "SyncUserLdapGroupRequest" : { + "type" : "object", + "required" : [ "username" ], + "properties" : { + "username" : { + "type" : "string", + "readOnly" : true + }, + "userDomain" : { + "type" : "string", + "readOnly" : true + } + } + }, + "TeamEntry" : { + "type" : "object", + "required" : [ "name" ], + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "orgId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "orgName" : { + "type" : "string", + "readOnly" : true + }, + "name" : { + "type" : "string", + "readOnly" : true + }, + "description" : { + "type" : "string", + "readOnly" : true, + "minLength" : 0, + "maxLength" : 2048 + } + } + }, + "TeamLdapGroupEntry" : { + "type" : "object", + "properties" : { + "group" : { + "type" : "string", + "readOnly" : true + }, + "role" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "OWNER", "MAINTAINER", "MEMBER" ] + } + } + }, + "TeamUserEntry" : { + "type" : "object", + "properties" : { + "userId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "username" : { + "type" : "string", + "readOnly" : true, + "minLength" : 0, + "maxLength" : 128 + }, + "userDomain" : { + "type" : "string", + "readOnly" : true, + "minLength" : 0, + "maxLength" : 512 + }, + "displayName" : { + "type" : "string", + "readOnly" : true + }, + "userType" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "LOCAL", "LDAP", "SSO" ] + }, + "role" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "OWNER", "MAINTAINER", "MEMBER" ] + }, + "memberType" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "SINGLE", "LDAP_GROUP" ] + }, + "ldapGroupSource" : { + "type" : "string", + "readOnly" : true + } + } + }, + "TemplateAliasEntry" : { + "type" : "object", + "required" : [ "alias", "url" ], + "properties" : { + "alias" : { + "type" : "string", + "readOnly" : true + }, + "url" : { + "type" : "string", + "readOnly" : true, + "minLength" : 0, + "maxLength" : 2048 + } + } + }, + "TemplateAliasResponse" : { + "type" : "object", + "properties" : { + "ok" : { + "type" : "boolean" + } + } + }, + "TriggerEntry" : { + "type" : "object", + "required" : [ "cfg", "eventSource" ], + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "orgId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "orgName" : { + "type" : "string", + "readOnly" : true + }, + "projectId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "projectName" : { + "type" : "string", + "readOnly" : true + }, + "repositoryId" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "repositoryName" : { + "type" : "string", + "readOnly" : true + }, + "eventSource" : { + "type" : "string", + "readOnly" : true + }, + "activeProfiles" : { + "type" : "array", + "readOnly" : true, + "items" : { + "type" : "string" + } + }, + "arguments" : { + "type" : "object", + "readOnly" : true, + "additionalProperties" : { + "type" : "object" + } + }, + "conditions" : { + "type" : "object", + "readOnly" : true, + "additionalProperties" : { + "type" : "object" + } + }, + "cfg" : { + "type" : "object", + "readOnly" : true, + "additionalProperties" : { + "type" : "object" + } + } + } + }, + "TriggeredByEntry" : { + "type" : "object", + "properties" : { + "externalEventId" : { + "type" : "string", + "readOnly" : true + }, + "trigger" : { + "readOnly" : true, + "$ref" : "#/definitions/TriggerEntry" + } + } + }, + "UpdateUserRolesRequest" : { + "type" : "object", + "required" : [ "roles" ], + "properties" : { + "roles" : { + "type" : "array", + "readOnly" : true, + "uniqueItems" : true, + "items" : { + "type" : "string" + } + } + } + }, + "UserActivityResponse" : { + "type" : "object", + "properties" : { + "processStats" : { + "type" : "object", + "readOnly" : true, + "additionalProperties" : { + "type" : "integer", + "format" : "int32" + } + }, + "orgProcesses" : { + "type" : "object", + "readOnly" : true, + "additionalProperties" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/ProjectProcesses" + } + } + }, + "processes" : { + "type" : "array", + "readOnly" : true, + "items" : { + "$ref" : "#/definitions/ProcessEntry" + } + } + } + }, + "UserEntry" : { + "type" : "object", + "properties" : { + "id" : { + "type" : "string", + "format" : "uuid", + "readOnly" : true + }, + "name" : { + "type" : "string", + "readOnly" : true, + "minLength" : 0, + "maxLength" : 128 + }, + "domain" : { + "type" : "string", + "readOnly" : true, + "minLength" : 0, + "maxLength" : 512 + }, + "displayName" : { + "type" : "string", + "readOnly" : true, + "minLength" : 0, + "maxLength" : 1024 + }, + "orgs" : { + "type" : "array", + "readOnly" : true, + "uniqueItems" : true, + "items" : { + "$ref" : "#/definitions/OrganizationEntry" + } + }, + "type" : { + "type" : "string", + "readOnly" : true, + "enum" : [ "LOCAL", "LDAP", "SSO" ] + }, + "email" : { + "type" : "string", + "readOnly" : true, + "minLength" : 0, + "maxLength" : 512 + }, + "roles" : { + "type" : "array", + "readOnly" : true, + "uniqueItems" : true, + "items" : { + "$ref" : "#/definitions/RoleEntry" + } + }, + "disabled" : { + "type" : "boolean", + "readOnly" : true + }, + "disabledDate" : { + "type" : "string", + "format" : "date-time", + "readOnly" : true + } + } + }, + "UserResponse" : { + "type" : "object", + "properties" : { + "realm" : { + "type" : "string", + "readOnly" : true + }, + "username" : { + "type" : "string", + "readOnly" : true + }, + "userDomain" : { + "type" : "string", + "readOnly" : true + }, + "displayName" : { + "type" : "string", + "readOnly" : true + }, + "orgs" : { + "type" : "array", + "readOnly" : true, + "uniqueItems" : true, + "items" : { + "$ref" : "#/definitions/OrganizationEntry" + } + } + } + }, + "VersionResponse" : { + "type" : "object", + "properties" : { + "version" : { + "type" : "string", + "readOnly" : true + }, + "commitId" : { + "type" : "string", + "readOnly" : true + }, + "env" : { + "type" : "string", + "readOnly" : true + }, + "ok" : { + "type" : "boolean" + } + } + } + } +} \ No newline at end of file diff --git a/client2/README.md b/client2/README.md new file mode 100644 index 0000000000..f83af3b0db --- /dev/null +++ b/client2/README.md @@ -0,0 +1,4 @@ +# concord-client + +A Concord API client based on Swagger codegen. +Build `server/impl` first to generate Swagger spec. diff --git a/client2/pom.xml b/client2/pom.xml new file mode 100644 index 0000000000..b4bd0b0986 --- /dev/null +++ b/client2/pom.xml @@ -0,0 +1,174 @@ + + + + 4.0.0 + + + com.walmartlabs.concord + parent + 2.1.1-SNAPSHOT + ../pom.xml + + + concord-client2 + jar + + + + com.walmartlabs.concord.server + concord-server + provided + + + com.walmartlabs.concord + concord-common + provided + + + org.slf4j + slf4j-api + + + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-annotations + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + + + org.immutables + value + provided + + + com.google.code.findbugs + jsr305 + provided + + + com.google.errorprone + error_prone_annotations + provided + + + + + javax.annotation + javax.annotation-api + + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + com.github.tomakehurst + wiremock-jre8 + test + + + + + + + false + ${project.basedir}/src/main/resources + + **/* + + + + true + ${project.basedir}/src/main/filtered-resources + + **/* + + + + + + + org.codehaus.mojo + cobertura-maven-plugin + + + org.openapitools + openapi-generator-maven-plugin + + + + generate + + + ${project.basedir}/../server/impl/target/classes/com/walmartlabs/concord/server/swagger/swagger.yaml + java + com.walmartlabs.concord.client2 + com.walmartlabs.concord.client2 + com.walmartlabs.concord.client2 + com.walmartlabs.concord.client2 + + src/gen/java/main + java8 + true + false + false + + false + native + false + false + false + false + true + ApiClient.java,ApiResponse.java,ApiException.java,Pair.java + ${project.basedir}/src/main/template + true + string+binary=InputStream + InputStream=java.io.InputStream + + + + + + + org.revapi + revapi-maven-plugin + + true + + + + java.field.serialVersionUIDUnchanged + + + java.method.parameterTypeParameterChanged + + + java.method.returnTypeTypeParametersChanged + + + + + + + + diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/ApiClientConfiguration.java b/client2/src/main/java/com/walmartlabs/concord/client2/ApiClientConfiguration.java new file mode 100644 index 0000000000..990e65b04e --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/ApiClientConfiguration.java @@ -0,0 +1,52 @@ +package com.walmartlabs.concord.client2; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2019 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import org.immutables.value.Value; + +import javax.annotation.Nullable; + +@Value.Immutable +@Value.Style(jdkOnly = true) +public interface ApiClientConfiguration { + + /** + * Base URL of the API, e.g. {@code http://localhost:8001} + */ + @Nullable + String baseUrl(); + + /** + * The process' session token. + */ + @Nullable + String sessionToken(); + + /** + * The user's API key. If set then the session token will be ignored. + */ + @Nullable + String apiKey(); + + static ImmutableApiClientConfiguration.Builder builder() { + return ImmutableApiClientConfiguration.builder(); + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/ApiClientFactory.java b/client2/src/main/java/com/walmartlabs/concord/client2/ApiClientFactory.java new file mode 100644 index 0000000000..f0670a40c4 --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/ApiClientFactory.java @@ -0,0 +1,27 @@ +package com.walmartlabs.concord.client2; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2018 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +public interface ApiClientFactory { + + ApiClient create(ApiClientConfiguration cfg); +} + diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/ClientUtils.java b/client2/src/main/java/com/walmartlabs/concord/client2/ClientUtils.java new file mode 100644 index 0000000000..70f59f1575 --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/ClientUtils.java @@ -0,0 +1,109 @@ +package com.walmartlabs.concord.client2; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2018 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; + +public final class ClientUtils { + + private static final Logger log = LoggerFactory.getLogger(ClientUtils.class); + + public static T withRetry(int retryCount, long retryInterval, Callable c) throws ApiException { + Exception exception = null; + int tryCount = 0; + while (!Thread.currentThread().isInterrupted() && tryCount < retryCount + 1) { + try { + return c.call(); + } catch (ApiException e) { + exception = e; + + if (e.getCode() >= 400 && e.getCode() < 500) { + break; + } + log.warn("call error: '{}'", getErrorMessage(e)); + } catch (Exception e) { + exception = e; + log.error("call error", e); + } + log.info("retry after {} sec", retryInterval / 1000); + sleep(retryInterval); + tryCount++; + } + + if (exception instanceof ApiException) { + throw (ApiException) exception; + } + + throw new ApiException(exception); + } + + /** + * Returns a value of the specified header. + * Only the first value is returned. + * The header's {@code name} is case-insensitive. + */ + public static String getHeader(String name, ApiResponse resp) { + Map> headers = resp.getHeaders(); + if (headers == null) { + return null; + } + + for (Map.Entry> e : headers.entrySet()) { + if (!e.getKey().equalsIgnoreCase(name)) { + continue; + } + + List values = e.getValue(); + + if (values == null || values.isEmpty()) { + return null; + } + + return values.get(0); + } + + return null; + } + + private static void sleep(long t) { + try { + Thread.sleep(t); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + private static String getErrorMessage(ApiException e) { + String error = e.getMessage(); + if (e.getResponseBody() != null && !e.getResponseBody().isEmpty()) { + error += ": " + e.getResponseBody(); + } + return error; + } + + private ClientUtils() { + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/ConcordApiClient.java b/client2/src/main/java/com/walmartlabs/concord/client2/ConcordApiClient.java new file mode 100644 index 0000000000..7ab6a66385 --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/ConcordApiClient.java @@ -0,0 +1,30 @@ +package com.walmartlabs.concord.client2; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2018 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import java.net.http.HttpClient; + +public class ConcordApiClient extends ApiClient { + + public ConcordApiClient(HttpClient httpClient) { + super(httpClient); + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/CreateSecretRequest.java b/client2/src/main/java/com/walmartlabs/concord/client2/CreateSecretRequest.java new file mode 100644 index 0000000000..1953a00c50 --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/CreateSecretRequest.java @@ -0,0 +1,104 @@ +package com.walmartlabs.concord.client2; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2020 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + + +import com.walmartlabs.concord.client2.ImmutableCreateSecretRequest; +import com.walmartlabs.concord.client2.ImmutableKeyPair; +import com.walmartlabs.concord.client2.ImmutableUsernamePassword; +import org.immutables.value.Value; + +import javax.annotation.Nullable; +import java.nio.file.Path; +import java.util.List; +import java.util.UUID; + +@Value.Immutable +@Value.Style(jdkOnly = true) +public interface CreateSecretRequest { + + String org(); + + String name(); + + @Value.Default + default boolean generatePassword() { + return false; + } + + @Nullable + String storePassword(); + + @Nullable + SecretEntryV2.VisibilityEnum visibility(); + + @Nullable + List projectNames(); + + @Nullable + List projectIds(); + + @Nullable + byte[] data(); + + @Nullable + KeyPair keyPair(); + + @Nullable + UsernamePassword usernamePassword(); + + static ImmutableCreateSecretRequest.Builder builder() { + return ImmutableCreateSecretRequest.builder(); + } + + @Value.Immutable + @Value.Style(jdkOnly = true) + interface KeyPair { + + long serialVersionUID = 1L; + + Path privateKey(); + + Path publicKey(); + + static ImmutableKeyPair.Builder builder() { + return ImmutableKeyPair.builder(); + } + } + + @Value.Immutable + @Value.Style(jdkOnly = true) + interface UsernamePassword { + + long serialVersionUID = 1L; + + String username(); + + String password(); + + static UsernamePassword of(String username, String password) { + return ImmutableUsernamePassword.builder() + .username(username) + .password(password) + .build(); + } + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/DefaultApiClientFactory.java b/client2/src/main/java/com/walmartlabs/concord/client2/DefaultApiClientFactory.java new file mode 100644 index 0000000000..cd41b77476 --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/DefaultApiClientFactory.java @@ -0,0 +1,115 @@ +package com.walmartlabs.concord.client2; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2023 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.net.http.HttpClient; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.time.Duration; + +public class DefaultApiClientFactory { + + private static final Duration DEFAULT_CONNECT_TIMEOUT = Duration.ofSeconds(30); + + private final HttpClient httpClient; + private final String defaultApiUrl; + + public DefaultApiClientFactory(String defaultApiUrl) { + this(defaultApiUrl, null, true); + } + + public DefaultApiClientFactory(String defaultApiUrl, Duration connectTimeout) { + this(defaultApiUrl, connectTimeout, true); + } + + public DefaultApiClientFactory(String defaultApiUrl, Duration connectTimeout, boolean verifySsl) { + this.defaultApiUrl = defaultApiUrl; + + this.httpClient = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_1_1) + .connectTimeout(connectTimeout != null ? connectTimeout : DEFAULT_CONNECT_TIMEOUT) + .sslContext(sslContext(verifySsl)) + .build(); + } + + public ApiClient create() { + return new ConcordApiClient(httpClient) + .setBaseUrl(defaultApiUrl); + } + + public ApiClient create(ApiClientConfiguration overrides) { + String baseUrl = overrides.baseUrl() != null ? overrides.baseUrl() : defaultApiUrl; + + String sessionToken = null; + if (overrides.apiKey() == null) { + sessionToken = overrides.sessionToken(); + } + + String apiKey = overrides.apiKey(); + if (apiKey != null) { + sessionToken = null; + } + + if (sessionToken == null && apiKey == null) { + throw new IllegalArgumentException("Session token or an API key is required"); + } + + return new ConcordApiClient(httpClient) + .setBaseUrl(baseUrl) + .setSessionToken(sessionToken) + .setApiKey(apiKey) + .addDefaultHeader("Accept", "*/*"); + } + + private static SSLContext sslContext(boolean verifySsl) { + try { + SSLContext sslContext = SSLContext.getInstance("TLS"); + if (verifySsl) { + sslContext.init(null, null, null); + } else { + TrustManager trustAll = new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) { + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) { + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + }; + TrustManager[] trustManagers = new TrustManager[]{trustAll}; + System.getProperties().setProperty("jdk.internal.httpclient.disableHostnameVerification", Boolean.TRUE.toString()); + + sslContext.init(null, trustManagers, new SecureRandom()); + } + return sslContext; + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/ProcessDataInclude.java b/client2/src/main/java/com/walmartlabs/concord/client2/ProcessDataInclude.java new file mode 100644 index 0000000000..e896b5bbcb --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/ProcessDataInclude.java @@ -0,0 +1,39 @@ +package com.walmartlabs.concord.client2; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2023 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +public enum ProcessDataInclude { + + CHECKPOINTS ("checkpoints"), + CHECKPOINTS_HISTORY ("checkpointsHistory"), + CHILDREN_IDS ("childrenIds"), + STATUS_HISTORY ("history"); + + private final String value; + + ProcessDataInclude(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/ProcessListFilter.java b/client2/src/main/java/com/walmartlabs/concord/client2/ProcessListFilter.java new file mode 100644 index 0000000000..0adc230159 --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/ProcessListFilter.java @@ -0,0 +1,111 @@ +package com.walmartlabs.concord.client2; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2023 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import com.walmartlabs.concord.client2.ImmutableProcessListFilter; +import com.walmartlabs.concord.client2.ProcessDataInclude; +import org.immutables.value.Value; + +import javax.annotation.Nullable; +import java.time.OffsetDateTime; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +@Value.Immutable +@Value.Style(jdkOnly = true) +public interface ProcessListFilter { + + @Nullable + UUID orgId(); + + @Nullable + String orgName(); + + @Nullable + UUID projectId(); + + @Nullable + String projectName(); + + @Nullable + UUID repoId(); + + @Nullable + String repoName(); + + @Nullable + OffsetDateTimeParam afterCreatedAt(); + + @Nullable + OffsetDateTimeParam beforeCreatedAt(); + + @Nullable + Set tags(); + + @Nullable + String status(); + + @Nullable + String initiator(); + + @Nullable + UUID parentInstanceId(); + + @Nullable + Set include(); + + @Nullable + Integer limit(); + + @Nullable + Integer offset(); + + @Nullable + Map meta(); + + class Builder extends ImmutableProcessListFilter.Builder { + + public Builder status(ProcessEntry.StatusEnum status) { + return status(status.getValue()); + } + + public Builder addInclude(ProcessDataInclude... elements) { + for (ProcessDataInclude e : elements) { + addInclude(e.getValue()); + } + return this; + } + + public Builder afterCreatedAt(OffsetDateTime afterCreatedAt) { + if (afterCreatedAt == null) { + return this; + } + + afterCreatedAt(new OffsetDateTimeParam().value(afterCreatedAt)); + return this; + } + } + + static ImmutableProcessListFilter.Builder builder() { + return new Builder(); + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/ProcessUtils.java b/client2/src/main/java/com/walmartlabs/concord/client2/ProcessUtils.java new file mode 100644 index 0000000000..6c91edeec9 --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/ProcessUtils.java @@ -0,0 +1,33 @@ +package com.walmartlabs.concord.client2; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2019 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import com.walmartlabs.concord.client2.ProcessEntry.StatusEnum; + +public class ProcessUtils { + + public static boolean isFinal(StatusEnum s) { + return s == StatusEnum.FINISHED || s == StatusEnum.FAILED || s == StatusEnum.CANCELLED || s == StatusEnum.SUSPENDED || s == StatusEnum.TIMED_OUT; + } + + private ProcessUtils() { + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/SecretClient.java b/client2/src/main/java/com/walmartlabs/concord/client2/SecretClient.java new file mode 100644 index 0000000000..e529d25c8b --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/SecretClient.java @@ -0,0 +1,243 @@ +package com.walmartlabs.concord.client2; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2018 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import com.walmartlabs.concord.common.secret.BinaryDataSecret; +import com.walmartlabs.concord.common.secret.KeyPair; +import com.walmartlabs.concord.common.secret.UsernamePassword; +import com.walmartlabs.concord.sdk.Constants; +import com.walmartlabs.concord.sdk.Secret; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; +import java.util.stream.Collectors; + +public class SecretClient { + + private static final int DEFAULT_RETRY_COUNT = 3; + private static final long DEFAULT_RETRY_INTERVAL = 5000; + + private final ApiClient apiClient; + private final int retryCount; + private final long retryInterval; + + public SecretClient(ApiClient apiClient) { + this(apiClient, DEFAULT_RETRY_COUNT, DEFAULT_RETRY_INTERVAL); + } + + public SecretClient(ApiClient apiClient, int retryCount, long retryInterval) { + this.apiClient = apiClient; + this.retryCount = retryCount; + this.retryInterval = retryInterval; + } + + /** + * Fetches a decrypted Concord secret from the server. + */ + public T getData(String orgName, String secretName, String password, SecretEntryV2.TypeEnum expectedType) throws Exception { + SecretsApi.GetSecretDataRequest req = new SecretsApi.GetSecretDataRequest() + .storePassword(password); + + SecretsApi api = new SecretsApi(apiClient); + + ApiResponse r = null; + try { + r = ClientUtils.withRetry(retryCount, retryInterval, + () -> api.getSecretDataWithHttpInfo(orgName, secretName, req.asMap())); + + if (r.getData() == null) { + throw new SecretNotFoundException(orgName, secretName); + } + + String secretType = ClientUtils.getHeader(Constants.Headers.SECRET_TYPE, r); + if (secretType == null) { + throw new IllegalStateException("Can't determine the secret's expectedType. Server response: code=" + r.getStatusCode()); + } + + SecretEntryV2.TypeEnum actualSecretType = SecretEntryV2.TypeEnum.valueOf(secretType); + + if (expectedType != null && expectedType != actualSecretType) { + String msg = "Unexpected type of %s/%s. Expected %s, got %s. " + + "Check the secret's expectedType and its usage - some secrets can only be used for specific purposes " + + "(e.g. %s is typically used for key-based authentication)."; + throw new IllegalArgumentException(String.format(msg, orgName, secretName, expectedType, actualSecretType, SecretEntryV2.TypeEnum.KEY_PAIR)); + } + + try (InputStream is = r.getData()) { + return readSecret(actualSecretType, is.readAllBytes()); + } + } catch (ApiException e) { + if (e.getCode() == 404) { + throw new SecretNotFoundException(orgName, secretName); + } + throw e; + } finally { + if (r != null && r.getData() != null) { + r.getData().close(); + } + } + } + + /** + * Decrypt the provided string using the project's key. + */ + public byte[] decryptString(UUID instanceId, byte[] input) throws Exception { + ProcessApi api = new ProcessApi(apiClient); + return ClientUtils.withRetry(retryCount, retryInterval, () -> api.decryptString(instanceId, input)); + } + + /** + * Encrypts the provided string using the project's key. + */ + public String encryptString(String orgName, String projectName, String input) throws Exception { + ProjectsApi api = new ProjectsApi(apiClient); + EncryptValueResponse r = ClientUtils.withRetry(retryCount, retryInterval, + () -> api.encrypt(orgName, projectName, input)); + + return r.getData(); + } + + /** + * Creates a new Concord secret. + */ + public SecretOperationResponse createSecret(CreateSecretRequest secretRequest) throws ApiException { + String path = "/api/v1/org/" + secretRequest.org() + "/secret"; + + Map params = new HashMap<>(); + params.put(Constants.Multipart.NAME, secretRequest.name()); + params.put(Constants.Multipart.GENERATE_PASSWORD, secretRequest.generatePassword()); + if (secretRequest.storePassword() != null) { + params.put(Constants.Multipart.STORE_PASSWORD, secretRequest.storePassword()); + } + + SecretEntryV2.VisibilityEnum visibility = secretRequest.visibility(); + if (visibility != null) { + params.put(Constants.Multipart.VISIBILITY, visibility.getValue()); + } + + if (secretRequest.projectIds() != null) { + params.put(Constants.Multipart.PROJECT_IDS, secretRequest.projectIds().stream().map(UUID::toString).collect(Collectors.joining(","))); + } else if (secretRequest.projectNames() != null) { + params.put(Constants.Multipart.PROJECT_NAMES, String.join(",", secretRequest.projectNames())); + } + + byte[] data = secretRequest.data(); + CreateSecretRequest.KeyPair keyPair = secretRequest.keyPair(); + CreateSecretRequest.UsernamePassword usernamePassword = secretRequest.usernamePassword(); + + if (data != null) { + params.put(Constants.Multipart.TYPE, SecretEntryV2.TypeEnum.DATA.getValue()); + params.put(Constants.Multipart.DATA, data); + } else if (keyPair != null) { + params.put(Constants.Multipart.TYPE, SecretEntryV2.TypeEnum.KEY_PAIR.getValue()); + params.put(Constants.Multipart.PUBLIC, readFile(keyPair.publicKey())); + params.put(Constants.Multipart.PRIVATE, readFile(keyPair.privateKey())); + } else if (usernamePassword != null) { + params.put(Constants.Multipart.TYPE, SecretEntryV2.TypeEnum.USERNAME_PASSWORD.getValue()); + params.put(Constants.Multipart.USERNAME, usernamePassword.username()); + params.put(Constants.Multipart.PASSWORD, usernamePassword.password()); + } else { + throw new IllegalArgumentException("Secret data, a key pair or username/password must be specified."); + } + + SecretsApi api = new SecretsApi(apiClient); + + SecretOperationResponse response = ClientUtils.withRetry(retryCount, retryInterval, + () -> api.createSecret(secretRequest.org(), params)); + return response; + } + + public void updateSecret(String orgName, String secretName, UpdateSecretRequest request) throws ApiException { + String path = "/api/v2/org/" + orgName + "/secret/" + secretName; + + Map params = new HashMap<>(); + params.put(Constants.Multipart.ORG_ID, request.newOrgId()); + params.put(Constants.Multipart.ORG_NAME, request.newOrgName()); + params.put("removeProjectLink", request.removeProjectLink()); + params.put("ownerId", request.newOwnerId()); + params.put(Constants.Multipart.STORE_PASSWORD, request.currentPassword()); + params.put("newStorePassword", request.newPassword()); + params.put(Constants.Multipart.NAME, request.newName()); + params.put(Constants.Multipart.VISIBILITY, request.newVisibility()); + if (request.newProjectIds() != null) { + params.put(Constants.Multipart.PROJECT_IDS, request.newProjectIds().stream().map(UUID::toString).collect(Collectors.joining(","))); + } else if (request.newProjectNames() != null) { + params.put(Constants.Multipart.PROJECT_NAMES, String.join(",", request.newProjectNames())); + } + + byte[] data = request.data(); + CreateSecretRequest.KeyPair keyPair = request.keyPair(); + CreateSecretRequest.UsernamePassword usernamePassword = request.usernamePassword(); + + if (data != null) { + params.put(Constants.Multipart.TYPE, SecretEntryV2.TypeEnum.DATA.getValue()); + params.put(Constants.Multipart.DATA, data); + } else if (keyPair != null) { + params.put(Constants.Multipart.TYPE, SecretEntryV2.TypeEnum.KEY_PAIR.getValue()); + params.put(Constants.Multipart.PUBLIC, readFile(keyPair.publicKey())); + params.put(Constants.Multipart.PRIVATE, readFile(keyPair.privateKey())); + } else if (usernamePassword != null) { + params.put(Constants.Multipart.TYPE, SecretEntryV2.TypeEnum.USERNAME_PASSWORD.getValue()); + params.put(Constants.Multipart.USERNAME, usernamePassword.username()); + params.put(Constants.Multipart.PASSWORD, usernamePassword.password()); + } + + params.values().removeIf(Objects::isNull); + + SecretsV2Api api = new SecretsV2Api(apiClient); + + ClientUtils.withRetry(retryCount, retryInterval, + () -> api.updateSecret(orgName, secretName, params)); + } + + private static byte[] readFile(Path file) { + if (file == null) { + return null; + } + + if (Files.notExists(file)) { + throw new IllegalArgumentException("File '" + file + "' not found"); + } + + try { + return Files.readAllBytes(file); + } catch (IOException e) { + throw new RuntimeException("Error while reading " + file + ": " + e.getMessage()); + } + } + + @SuppressWarnings("unchecked") + private static T readSecret(SecretEntryV2.TypeEnum type, byte[] bytes) { + switch (type) { + case DATA: + return (T) new BinaryDataSecret(bytes); + case KEY_PAIR: + return (T) KeyPair.deserialize(bytes); + case USERNAME_PASSWORD: + return (T) UsernamePassword.deserialize(bytes); + default: + throw new IllegalArgumentException("unknown secret type: " + type); + } + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/SecretNotFoundException.java b/client2/src/main/java/com/walmartlabs/concord/client2/SecretNotFoundException.java new file mode 100644 index 0000000000..7530daaaad --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/SecretNotFoundException.java @@ -0,0 +1,44 @@ +package com.walmartlabs.concord.client2; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2021 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +public class SecretNotFoundException extends IllegalArgumentException { + + private static final long serialVersionUID = 1L; + + private final String orgName; + + private final String secretName; + + public SecretNotFoundException(String orgName, String secretName) { + super("Secret not found: " + orgName + "/" + secretName); + this.orgName = orgName; + this.secretName = secretName; + } + + public String getOrgName() { + return orgName; + } + + public String getSecretName() { + return secretName; + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/UpdateSecretRequest.java b/client2/src/main/java/com/walmartlabs/concord/client2/UpdateSecretRequest.java new file mode 100644 index 0000000000..e8235eeac0 --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/UpdateSecretRequest.java @@ -0,0 +1,78 @@ +package com.walmartlabs.concord.client2; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2020 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + + +import org.immutables.value.Value; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.UUID; + +@Value.Immutable +@Value.Style(jdkOnly = true) +public interface UpdateSecretRequest { + + @Nullable + UUID newOrgId(); + + @Nullable + String newOrgName(); + + @Nullable + List newProjectNames(); + + @Nullable + List newProjectIds(); + + @Value.Default + default boolean removeProjectLink() { + return false; + } + + @Nullable + UUID newOwnerId(); + + @Nullable + String currentPassword(); + + @Nullable + String newPassword(); + + @Nullable + String newName(); + + @Nullable + SecretEntryV2.VisibilityEnum newVisibility(); + + @Nullable + byte[] data(); + + @Nullable + CreateSecretRequest.KeyPair keyPair(); + + @Nullable + CreateSecretRequest.UsernamePassword usernamePassword(); + + static ImmutableUpdateSecretRequest.Builder builder() { + return ImmutableUpdateSecretRequest.builder(); + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/impl/ByteArrayBuffer.java b/client2/src/main/java/com/walmartlabs/concord/client2/impl/ByteArrayBuffer.java new file mode 100644 index 0000000000..b2380c712c --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/impl/ByteArrayBuffer.java @@ -0,0 +1,81 @@ +package com.walmartlabs.concord.client2.impl; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2023 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +public class ByteArrayBuffer { + + private byte[] array; + private int len; + + public ByteArrayBuffer(int capacity) { + super(); + this.array = new byte[capacity]; + } + + public void append(byte[] b) { + append(b, 0, b.length); + } + + public void append(byte[] b, int off, int len) { + if (b == null) { + return; + } + if ((off < 0) || (off > b.length) || (len < 0) || + ((off + len) < 0) || ((off + len) > b.length)) { + throw new IndexOutOfBoundsException("off: "+off+" len: "+len+" b.length: "+b.length); + } + if (len == 0) { + return; + } + int newlen = this.len + len; + if (newlen > this.array.length) { + expand(newlen); + } + System.arraycopy(b, off, this.array, this.len, len); + this.len = newlen; + } + + private void expand(int newlen) { + byte[] newArray = new byte[Math.max(this.array.length << 1, newlen)]; + System.arraycopy(this.array, 0, newArray, 0, this.len); + this.array = newArray; + } + + public byte[] array() { + return this.array; + } + + public byte[] toByteArray() { + final byte[] b = new byte[this.len]; + if (this.len > 0) { + System.arraycopy(this.array, 0, b, 0, this.len); + } + return b; + } + + public int length() { + return this.len; + } + + public void clear() { + this.len = 0; + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/impl/ContentType.java b/client2/src/main/java/com/walmartlabs/concord/client2/impl/ContentType.java new file mode 100644 index 0000000000..0bc83a676c --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/impl/ContentType.java @@ -0,0 +1,100 @@ +package com.walmartlabs.concord.client2.impl; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2023 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.stream.Collectors; + +public class ContentType { + + public static final ContentType APPLICATION_JSON = create( + "application/json", StandardCharsets.UTF_8); + + public static final ContentType APPLICATION_OCTET_STREAM = create( + "application/octet-stream"); + + public static final ContentType TEXT_PLAIN = create("text/plain"); + + public static final ContentType MULTIPART_FORM = create("multipart/form-data"); + + public static ContentType create(String mimeType) { + return create(mimeType, null); + } + + public static ContentType create(String mimeType, Charset charset) { + String normalizedMimeType = mimeType.toLowerCase(); + return new ContentType(normalizedMimeType, charset); + } + + private final String mimeType; + private final Charset charset; + private final List params; + + public ContentType(String mimeType, Charset charset) { + this(mimeType, charset, null); + } + + public ContentType(String mimeType, Charset charset, List params) { + this.mimeType = mimeType; + this.charset = charset; + this.params = params; + } + + public ContentType withCharset(Charset charset) { + return create(getMimeType(), charset); + } + + public ContentType withParameters(List params) { + return new ContentType(getMimeType(), charset, params); + } + + public String getMimeType() { + return mimeType; + } + + public Charset getCharset() { + return charset; + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder(); + buf.append(this.mimeType); + if (this.params != null) { + buf.append("; "); + formatParameters(buf, this.params); + } else if (this.charset != null) { + buf.append("; charset="); + buf.append(this.charset.name().toLowerCase()); + } + return buf.toString(); + } + + private static void formatParameters(StringBuilder buf, List params) { + String s = params.stream() + .map(nvp -> nvp.getName() + "=" + nvp.getValue()) + .collect(Collectors.joining("; ")); + + buf.append(s); + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/impl/Headers.java b/client2/src/main/java/com/walmartlabs/concord/client2/impl/Headers.java new file mode 100644 index 0000000000..195d366de9 --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/impl/Headers.java @@ -0,0 +1,57 @@ +package com.walmartlabs.concord.client2.impl; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2023 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import java.util.Collections; +import java.util.List; + +public class Headers { + + private final List items; + + public static Headers of(String name, String value) { + return new Headers(Collections.singletonList(new NameValuePair(name, value))); + } + + public Headers(List items) { + this.items = items; + } + + public String get(String name) { + return items.stream() + .filter(nvp -> nvp.getName().equalsIgnoreCase(name)) + .map(NameValuePair::getValue) + .findFirst() + .orElse(null); + } + + public int size() { + return items.size(); + } + + public String name(int index) { + return items.get(index).getName(); + } + + public String value(int index) { + return items.get(index).getValue(); + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/impl/HttpEntity.java b/client2/src/main/java/com/walmartlabs/concord/client2/impl/HttpEntity.java new file mode 100644 index 0000000000..6dc56c8b0a --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/impl/HttpEntity.java @@ -0,0 +1,34 @@ +package com.walmartlabs.concord.client2.impl; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2023 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public interface HttpEntity { + + ContentType contentType(); + + long contentLength() throws IOException; + + InputStream getContent() throws IOException; +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/impl/MultipartBuilder.java b/client2/src/main/java/com/walmartlabs/concord/client2/impl/MultipartBuilder.java new file mode 100644 index 0000000000..64f3fdb6a8 --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/impl/MultipartBuilder.java @@ -0,0 +1,258 @@ +package com.walmartlabs.concord.client2.impl; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2023 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import java.io.*; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.*; + +public class MultipartBuilder { + + private static final byte[] COLONSPACE = { ':', ' ' }; + private static final byte[] CRLF = { '\r', '\n' }; + private static final byte[] DASHDASH = { '-', '-' }; + + private final List partHeaders = new ArrayList<>(); + private final List partBodies = new ArrayList<>(); + + private final ContentType type = ContentType.MULTIPART_FORM; + private final String boundary; + + public MultipartBuilder() { + this(UUID.randomUUID().toString()); + } + + public MultipartBuilder(String boundary) { + this.boundary = boundary; + } + + public MultipartBuilder addFormDataPart(String name, String value) { + return addFormDataPart(name, null, RequestBody.create(null, value)); + } + + public MultipartBuilder addFormDataPart(String name, String filename, RequestBody value) { + Objects.requireNonNull(name, "name"); + StringBuilder disposition = new StringBuilder("form-data; name="); + appendQuotedString(disposition, name); + + if (filename != null) { + disposition.append("; filename="); + appendQuotedString(disposition, filename); + } + + return addPart(Headers.of("Content-Disposition", disposition.toString()), value); + } + + public MultipartBuilder addPart(Headers headers, RequestBody body) { + if (body == null) { + throw new NullPointerException("body == null"); + } + if (headers != null && headers.get("Content-Type") != null) { + throw new IllegalArgumentException("Unexpected header: Content-Type"); + } + if (headers != null && headers.get("Content-Length") != null) { + throw new IllegalArgumentException("Unexpected header: Content-Length"); + } + + partHeaders.add(headers); + partBodies.add(body); + return this; + } + + public RequestBody build() { +// if (partHeaders.isEmpty()) { +// throw new IllegalStateException("Multipart body must have at least one part."); +// } + return new MultipartRequestBody(type, boundary, partHeaders, partBodies); + } + + private static void appendQuotedString(StringBuilder target, String key) { + target.append('"'); + for (int i = 0, len = key.length(); i < len; i++) { + char ch = key.charAt(i); + switch (ch) { + case '\n': + target.append("%0A"); + break; + case '\r': + target.append("%0D"); + break; + case '"': + target.append("%22"); + break; + default: + target.append(ch); + break; + } + } + target.append('"'); + } + + private static final class MultipartRequestBody extends RequestBody { + private final String boundary; + private final ContentType contentType; + private final List partHeaders; + private final List partBodies; + + public MultipartRequestBody(ContentType type, String boundary, List partHeaders, + List partBodies) { + + Objects.requireNonNull(type, "type"); + + this.boundary = boundary; + this.contentType = type.withParameters(Collections.singletonList(new NameValuePair("boundary", boundary))); + this.partHeaders = partHeaders; + this.partBodies = partBodies; + } + + @Override + public ContentType contentType() { + return contentType; + } + + @Override + public long contentLength() { + return -1; + } + + @Override + public InputStream getContent() throws IOException { + SequenceInputStreamBuilder result = new SequenceInputStreamBuilder(); + try { + write(result); + return result.build(); + } catch (Exception e) { + result.close(); + throw e; + } + } + + private void write(SequenceInputStreamBuilder result) throws IOException { + ByteArrayBuffer boundaryEncoded = encode(StandardCharsets.US_ASCII, this.boundary); + + for (int p = 0, partCount = partHeaders.size(); p < partCount; p++) { + Headers headers = partHeaders.get(p); + RequestBody body = partBodies.get(p); + + result.write(DASHDASH); + result.write(boundaryEncoded); + result.write(CRLF); + + if (headers != null) { + for (int h = 0, headerCount = headers.size(); h < headerCount; h++) { + writeHeader(headers.name(h), headers.value(h), result); + } + } + + ContentType contentType = body.contentType(); + if (contentType != null) { + writeHeader("Content-Type", contentType.toString(), result); + } + + long contentLength = body.contentLength(); + if (contentLength != -1) { + writeHeader("Content-Length", String.valueOf(contentLength), result); + } + + result.write(CRLF); + result.write(body.getContent()); + result.write(CRLF); + } + + result.write(DASHDASH); + result.write(boundaryEncoded); + result.write(DASHDASH); + result.write(CRLF); + } + + private void writeHeader(String name, String value, SequenceInputStreamBuilder out) throws IOException { + out.write(encodeHeader(name)); + out.write(COLONSPACE); + out.write(encodeHeader(value)); + out.write(CRLF); + } + + private static ByteArrayBuffer encode(Charset charset, String string) { + ByteBuffer encoded = charset.encode(CharBuffer.wrap(string)); + ByteArrayBuffer bab = new ByteArrayBuffer(encoded.remaining()); + bab.append(encoded.array(), encoded.arrayOffset() + encoded.position(), encoded.remaining()); + return bab; + } + + private static ByteArrayBuffer encodeHeader(String value) { + return encode(StandardCharsets.ISO_8859_1, value); + } + } + + static class SequenceInputStreamBuilder { + + private final Vector streams = new Vector<>(); + private final ByteArrayBuffer currentBuffer = new ByteArrayBuffer(1024); + + public void write(byte[] buff) { + currentBuffer.append(buff); + } + + public void write(ByteArrayBuffer buff) { + currentBuffer.append(buff.array(), 0, buff.length()); + } + + public void write(InputStream stream) { + flushCurrentBuffer(); + + streams.add(stream); + } + + public void close() throws IOException { + IOException ioe = null; + for (InputStream in : streams) { + try { + in.close(); + } catch (IOException e) { + if (ioe == null) { + ioe = e; + } else { + ioe.addSuppressed(e); + } + } + } + if (ioe != null) { + throw ioe; + } + } + + public InputStream build() { + flushCurrentBuffer(); + + return new SequenceInputStream(streams.elements()); + } + + private void flushCurrentBuffer() { + if (currentBuffer.length() > 0) { + streams.add(new ByteArrayInputStream(currentBuffer.toByteArray(), 0, currentBuffer.length())); + currentBuffer.clear(); + } + } + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/impl/MultipartRequestBodyHandler.java b/client2/src/main/java/com/walmartlabs/concord/client2/impl/MultipartRequestBodyHandler.java new file mode 100644 index 0000000000..a6c705d22e --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/impl/MultipartRequestBodyHandler.java @@ -0,0 +1,124 @@ +package com.walmartlabs.concord.client2.impl; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2023 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Map; +import java.util.UUID; + +public final class MultipartRequestBodyHandler { + + public static HttpEntity handle(ObjectMapper objectMapper, Map data) { + return handle(new MultipartBuilder(), objectMapper, data); + } + + public static HttpEntity handle(MultipartBuilder b, ObjectMapper objectMapper, Map data) { + for (Map.Entry e : data.entrySet()) { + String k = e.getKey(); + Object v = e.getValue(); + if (v instanceof InputStream) { + b.addFormDataPart(k, null, new InputStreamRequestBody((InputStream) v)); + } else if (v instanceof byte[]) { + b.addFormDataPart(k, null, RequestBody.create(ContentType.APPLICATION_OCTET_STREAM, (byte[]) v)); + } else if (v instanceof String) { + b.addFormDataPart(k, (String) v); + } else if (v instanceof Path) { + b.addFormDataPart(k, null, new PathRequestBody((Path) v)); + } else if (v instanceof Map) { + String json; + try { + json = objectMapper.writeValueAsString(v); + } catch (JsonProcessingException ex) { + throw new RuntimeException(ex); + } + b.addFormDataPart(k, null, RequestBody.create(ContentType.APPLICATION_JSON, json)); + } else if (v instanceof Boolean) { + b.addFormDataPart(k, null, RequestBody.create(ContentType.TEXT_PLAIN, v.toString())); + } else if (v instanceof String[]) { + b.addFormDataPart(k, null, RequestBody.create(ContentType.TEXT_PLAIN, String.join(",", (String[]) v))); + } else if (v instanceof UUID) { + b.addFormDataPart(k, v.toString()); + } else if (v instanceof Enum) { + b.addFormDataPart(k, ((Enum)v).name()); + } else { + throw new IllegalArgumentException("Unknown input type: " + k + "=" + v + (v != null ? " (" + v.getClass() + ")" : "")); + } + } + return b.build(); + } + + private MultipartRequestBodyHandler() { + } + + public static final class InputStreamRequestBody extends RequestBody { + + private final InputStream in; + + public InputStreamRequestBody(InputStream in) { + this.in = in; + } + + @Override + public ContentType contentType() { + return ContentType.APPLICATION_OCTET_STREAM; + } + + @Override + public long contentLength() { + return -1; + } + + @Override + public InputStream getContent() { + return in; + } + } + + public static class PathRequestBody extends RequestBody { + + private final Path path; + + public PathRequestBody(Path path) { + this.path = path; + } + + @Override + public ContentType contentType() { + return ContentType.APPLICATION_OCTET_STREAM; + } + + @Override + public long contentLength() throws IOException { + return Files.size(path); + } + + @Override + public InputStream getContent() throws IOException { + return Files.newInputStream(this.path); + } + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/impl/NameValuePair.java b/client2/src/main/java/com/walmartlabs/concord/client2/impl/NameValuePair.java new file mode 100644 index 0000000000..a494bc17dc --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/impl/NameValuePair.java @@ -0,0 +1,58 @@ +package com.walmartlabs.concord.client2.impl; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2023 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import java.io.Serializable; +import java.util.Objects; + +public class NameValuePair implements Serializable { + + private static final long serialVersionUID = 1L; + + private final String name; + private final String value; + + public NameValuePair(final String name, final String value) { + this.name = name; + this.value = value; + } + + public String getName() { + return this.name; + } + + public String getValue() { + return this.value; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + NameValuePair that = (NameValuePair) o; + return Objects.equals(name, that.name) && Objects.equals(value, that.value); + } + + @Override + public int hashCode() { + return Objects.hash(name, value); + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/impl/OffsetDateTimeDeserializer.java b/client2/src/main/java/com/walmartlabs/concord/client2/impl/OffsetDateTimeDeserializer.java new file mode 100644 index 0000000000..564c8dc785 --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/impl/OffsetDateTimeDeserializer.java @@ -0,0 +1,40 @@ +package com.walmartlabs.concord.client2.impl; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2023 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer; + +import java.time.Instant; +import java.time.OffsetDateTime; + +public class OffsetDateTimeDeserializer extends InstantDeserializer { + + public OffsetDateTimeDeserializer() { + super( + OffsetDateTime.class, OffsetDateTimeSerializer.FORMATTER, + OffsetDateTime::from, + a -> OffsetDateTime.ofInstant(Instant.ofEpochMilli(a.value), a.zoneId), + a -> OffsetDateTime.ofInstant(Instant.ofEpochSecond(a.integer, a.fraction), a.zoneId), + (d, z) -> (d.isEqual(OffsetDateTime.MIN) || d.isEqual(OffsetDateTime.MAX) ? d : d.withOffsetSameInstant(z.getRules().getOffset(d.toLocalDateTime()))), + false + ); + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/impl/OffsetDateTimeSerializer.java b/client2/src/main/java/com/walmartlabs/concord/client2/impl/OffsetDateTimeSerializer.java new file mode 100644 index 0000000000..0eb3496db6 --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/impl/OffsetDateTimeSerializer.java @@ -0,0 +1,43 @@ +package com.walmartlabs.concord.client2.impl; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2023 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import java.io.IOException; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; + +public class OffsetDateTimeSerializer extends JsonSerializer { + + public static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX"); + + @Override + public void serialize(OffsetDateTime value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + if (value == null) { + throw new IOException("OffsetDateTime argument is null."); + } + + jsonGenerator.writeString(FORMATTER.format(value)); + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/impl/RequestBody.java b/client2/src/main/java/com/walmartlabs/concord/client2/impl/RequestBody.java new file mode 100644 index 0000000000..77f116df46 --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/impl/RequestBody.java @@ -0,0 +1,68 @@ +package com.walmartlabs.concord.client2.impl; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2023 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Objects; + +public abstract class RequestBody implements HttpEntity { + + public static RequestBody create(ContentType contentType, String content) { + Charset charset = StandardCharsets.UTF_8; + if (contentType != null) { + charset = contentType.getCharset(); + if (charset == null) { + charset = StandardCharsets.UTF_8; + contentType = contentType.withCharset(charset); + } + } + byte[] bytes = content.getBytes(charset); + return create(contentType, bytes); + } + + public static RequestBody create(ContentType contentType, byte[] content) { + return create(contentType, content, 0, content.length); + } + + public static RequestBody create(ContentType contentType, byte[] content, int offset, int byteCount) { + Objects.requireNonNull(content, "content"); + + return new RequestBody() { + @Override + public ContentType contentType() { + return contentType; + } + + @Override + public long contentLength() { + return byteCount; + } + + @Override + public InputStream getContent() { + return new ByteArrayInputStream(content, offset, byteCount); + } + }; + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/impl/RequestBodyHandler.java b/client2/src/main/java/com/walmartlabs/concord/client2/impl/RequestBodyHandler.java new file mode 100644 index 0000000000..7f5748463d --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/impl/RequestBodyHandler.java @@ -0,0 +1,49 @@ +package com.walmartlabs.concord.client2.impl; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2023 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.io.InputStream; +import java.net.http.HttpRequest; + +public final class RequestBodyHandler { + + public static HttpRequest.BodyPublisher handle(ObjectMapper ignoredObjectMapper, byte[] param) throws IOException { + return HttpRequest.BodyPublishers.ofByteArray(param); + } + + public static HttpRequest.BodyPublisher handle(ObjectMapper ignoredObjectMapper, InputStream param) throws IOException { + return HttpRequest.BodyPublishers.ofInputStream(() -> param); + } + + public static HttpRequest.BodyPublisher handle(ObjectMapper objectMapper, Object param) throws IOException { + if (param instanceof String) { + return HttpRequest.BodyPublishers.ofString((String) param); + } + byte[] localVarPostBody = objectMapper.writeValueAsBytes(param); + return HttpRequest.BodyPublishers.ofByteArray(localVarPostBody); + } + + private RequestBodyHandler() { + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/impl/ResponseBodyHandler.java b/client2/src/main/java/com/walmartlabs/concord/client2/impl/ResponseBodyHandler.java new file mode 100644 index 0000000000..630c746c07 --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/impl/ResponseBodyHandler.java @@ -0,0 +1,110 @@ +package com.walmartlabs.concord.client2.impl; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2023 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.walmartlabs.concord.client2.ApiException; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Type; +import java.net.http.HttpResponse; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public final class ResponseBodyHandler { + + @SuppressWarnings("unchecked") + public static T handle(ObjectMapper objectMapper, + HttpResponse response, + TypeReference returnTypeRef) throws IOException, ApiException { + if (response == null) { + return null; + } + + Type returnType = returnTypeRef.getType(); + InputStream is = response.body(); + if (is == null) { + return null; + } + + try { + if (returnType.equals(byte[].class)) { + return (T)is.readAllBytes(); + } else if (returnType.equals(InputStream.class)) { + return (T)is; + } + + String contentType = response.headers().firstValue("Content-Type").orElse("application/json"); + if (isJsonMime(contentType)) { + return objectMapper.readValue(is, returnTypeRef); + } else if (returnType.equals(String.class)) { + return (T) toString(is, charset(response)); + } else { + throw new ApiException( + "Content type \"" + contentType + "\" is not supported for type: " + returnType, + response.statusCode(), + response.headers(), + "skipped"); + } + } finally { + if (!returnType.equals(InputStream.class)) { + is.close(); + } + } + } + + private static boolean isJsonMime(String mime) { + String jsonMime = "(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$"; + return mime != null && (mime.matches(jsonMime) || mime.equals("*/*")); + } + + private static String toString(InputStream input, Charset charset) throws IOException { + return new String(input.readAllBytes(), charset); + } + + private static Charset charset(HttpResponse response) { + String contentType = response.headers().firstValue("Content-Type").orElse(null); + if (contentType == null) { + return StandardCharsets.UTF_8; + } + + return parseCharset(contentType, StandardCharsets.UTF_8); + } + + // TODO: super simple + private static Charset parseCharset(String contentTypeHeader, Charset defaultCharset) { + Pattern pattern = Pattern.compile("charset=([\\w-]+)", Pattern.CASE_INSENSITIVE); + Matcher matcher = pattern.matcher(contentTypeHeader); + + if (matcher.find()) { + return Charset.forName(matcher.group(1)); + } + + return defaultCharset; + } + + private ResponseBodyHandler() { + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/impl/auth/ApiKey.java b/client2/src/main/java/com/walmartlabs/concord/client2/impl/auth/ApiKey.java new file mode 100644 index 0000000000..295d6b8562 --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/impl/auth/ApiKey.java @@ -0,0 +1,37 @@ +package com.walmartlabs.concord.client2.impl.auth; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2023 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import java.net.http.HttpRequest; + +public class ApiKey implements Authentication { + + private final String key; + + public ApiKey(String key) { + this.key = key; + } + + @Override + public HttpRequest.Builder applyTo(HttpRequest.Builder requesBuilder) { + return requesBuilder.setHeader("Authorization", key); + } +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/impl/auth/Authentication.java b/client2/src/main/java/com/walmartlabs/concord/client2/impl/auth/Authentication.java new file mode 100644 index 0000000000..4b6245c74d --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/impl/auth/Authentication.java @@ -0,0 +1,28 @@ +package com.walmartlabs.concord.client2.impl.auth; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2023 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import java.net.http.HttpRequest; + +public interface Authentication { + + HttpRequest.Builder applyTo(HttpRequest.Builder requesBuilder); +} diff --git a/client2/src/main/java/com/walmartlabs/concord/client2/impl/auth/SessionToken.java b/client2/src/main/java/com/walmartlabs/concord/client2/impl/auth/SessionToken.java new file mode 100644 index 0000000000..d7d31331f0 --- /dev/null +++ b/client2/src/main/java/com/walmartlabs/concord/client2/impl/auth/SessionToken.java @@ -0,0 +1,37 @@ +package com.walmartlabs.concord.client2.impl.auth; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2023 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import java.net.http.HttpRequest; + +public class SessionToken implements Authentication { + + private final String token; + + public SessionToken(String token) { + this.token = token; + } + + @Override + public HttpRequest.Builder applyTo(HttpRequest.Builder requesBuilder) { + return requesBuilder.setHeader("X-Concord-SessionToken", token); + } +} diff --git a/client2/src/main/template/README.md b/client2/src/main/template/README.md new file mode 100644 index 0000000000..8ebe85a07b --- /dev/null +++ b/client2/src/main/template/README.md @@ -0,0 +1 @@ +Check the diff between `*.mustache` and `*.orig` to see the introduced customizations. \ No newline at end of file diff --git a/client2/src/main/template/libraries/native/ApiClient.mustache b/client2/src/main/template/libraries/native/ApiClient.mustache new file mode 100644 index 0000000000..5a58a59fcc --- /dev/null +++ b/client2/src/main/template/libraries/native/ApiClient.mustache @@ -0,0 +1,462 @@ +{{>licenseInfo}} +package {{invokerPackage}}; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +{{#openApiNullable}} +import org.openapitools.jackson.nullable.JsonNullableModule; +{{/openApiNullable}} + +import java.io.InputStream; +import java.net.URI; +import java.net.URLEncoder; +import java.net.http.HttpClient; +import java.net.http.HttpConnectTimeoutException; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import java.util.StringJoiner; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +import com.walmartlabs.concord.client2.impl.auth.Authentication; +import com.walmartlabs.concord.client2.impl.auth.ApiKey; +import com.walmartlabs.concord.client2.impl.auth.SessionToken; +import com.walmartlabs.concord.client2.impl.OffsetDateTimeDeserializer; +import com.walmartlabs.concord.client2.impl.OffsetDateTimeSerializer; + +import static java.nio.charset.StandardCharsets.UTF_8; + +/** + * Configuration and utility class for API clients. + * + *

This class can be constructed and modified, then used to instantiate the + * various API classes. The API classes use the settings in this class to + * configure themselves, but otherwise do not store a link to this class.

+ * + *

This class is mutable and not synchronized, so it is not thread-safe. + * The API classes generated from this are immutable and thread-safe.

+ * + *

The setter methods of this class return the current object to facilitate + * a fluent style of configuration.

+ */ +{{>generatedAnnotation}} +public class ApiClient { + + private final HttpClient httpClient; + private ObjectMapper mapper; + private String baseUri; + private String scheme; + private String host; + private int port; + private String basePath; + private Consumer interceptor; + private Consumer> responseInterceptor; + private Consumer> asyncResponseInterceptor; + private Duration readTimeout; + private Duration connectTimeout; + private Authentication auth; + private final Map defaultHeaderMap = new HashMap(); + + public Authentication getAuth() { + return auth; + } + + public void setAuth(Authentication auth) { + this.auth = auth; + } + + public Map defaultHeaderMap() { + return defaultHeaderMap; + } + + private static String valueToString(Object value) { + if (value == null) { + return ""; + } + if (value instanceof OffsetDateTime) { + return ((OffsetDateTime) value).format(OffsetDateTimeSerializer.FORMATTER); + } + return value.toString(); + } + + /** + * URL encode a string in the UTF-8 encoding. + * + * @param s String to encode. + * @return URL-encoded representation of the input string. + */ + public static String urlEncode(String s) { + return URLEncoder.encode(s, UTF_8).replaceAll("\\+", "%20"); + } + + /** + * Convert a URL query name/value parameter to a list of encoded {@link Pair} + * objects. + * + *

The value can be null, in which case an empty list is returned.

+ * + * @param name The query name parameter. + * @param value The query value, which may not be a collection but may be + * null. + * @return A singleton list of the {@link Pair} objects representing the input + * parameters, which is encoded for use in a URL. If the value is null, an + * empty list is returned. + */ + public static List parameterToPairs(String name, Object value) { + if (name == null || name.isEmpty() || value == null) { + return Collections.emptyList(); + } + return Collections.singletonList(new Pair(urlEncode(name), urlEncode(valueToString(value)))); + } + + /** + * Convert a URL query name/collection parameter to a list of encoded + * {@link Pair} objects. + * + * @param collectionFormat The swagger collectionFormat string (csv, tsv, etc). + * @param name The query name parameter. + * @param values A collection of values for the given query name, which may be + * null. + * @return A list of {@link Pair} objects representing the input parameters, + * which is encoded for use in a URL. If the values collection is null, an + * empty list is returned. + */ + public static List parameterToPairs( + String collectionFormat, String name, Collection values) { + if (name == null || name.isEmpty() || values == null || values.isEmpty()) { + return Collections.emptyList(); + } + + // get the collection format (default: csv) + String format = collectionFormat == null || collectionFormat.isEmpty() ? "csv" : collectionFormat; + + // create the params based on the collection format + if ("multi".equals(format)) { + return values.stream() + .map(value -> new Pair(urlEncode(name), urlEncode(valueToString(value)))) + .collect(Collectors.toList()); + } + + String delimiter; + switch(format) { + case "csv": + delimiter = urlEncode(","); + break; + case "ssv": + delimiter = urlEncode(" "); + break; + case "tsv": + delimiter = urlEncode("\t"); + break; + case "pipes": + delimiter = urlEncode("|"); + break; + default: + throw new IllegalArgumentException("Illegal collection format: " + collectionFormat); + } + + StringJoiner joiner = new StringJoiner(delimiter); + for (Object value : values) { + joiner.add(urlEncode(valueToString(value))); + } + + return Collections.singletonList(new Pair(urlEncode(name), joiner.toString())); + } + + /** + * Create an instance of ApiClient. + */ + public ApiClient(HttpClient httpClient) { + this.httpClient = httpClient; + this.mapper = createDefaultObjectMapper(); + updateBaseUri(getDefaultBaseUri()); + interceptor = null; + readTimeout = null; + connectTimeout = null; + responseInterceptor = null; + asyncResponseInterceptor = null; + } + + public static ObjectMapper createDefaultObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false); + mapper.configure(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS, false); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); + mapper.registerModule(new JavaTimeModule() + .addDeserializer(OffsetDateTime.class, new OffsetDateTimeDeserializer()) + .addSerializer(OffsetDateTime.class, new OffsetDateTimeSerializer())); + {{#openApiNullable}} + mapper.registerModule(new JsonNullableModule()); + {{/openApiNullable}} + return mapper; + } + + public ApiClient setUserAgent(String userAgent) { + addDefaultHeader("User-Agent", userAgent); + return this; + } + + public ApiClient addDefaultHeader(String key, String value) { + defaultHeaderMap.put(key, value); + return this; + } + + protected String getDefaultBaseUri() { + return "{{{basePath}}}"; + } + + public HttpRequest.Builder requestBuilder() { + HttpRequest.Builder result = HttpRequest.newBuilder(); + for (Map.Entry e : defaultHeaderMap.entrySet()) { + result.header(e.getKey(), e.getValue()); + } + if (getAuth() != null) { + result = getAuth().applyTo(result); + } + return result; + } + + public void updateBaseUri(String baseUri) { + this.baseUri = baseUri; + + URI uri = URI.create(baseUri); + scheme = uri.getScheme(); + host = uri.getHost(); + port = uri.getPort(); + basePath = uri.getRawPath(); + } + + public ApiClient setBaseUrl(String baseUrl) { + updateBaseUri(baseUrl); + return this; + } + + public String getBaseUrl() { + return this.baseUri; + } + + public ApiClient setSessionToken(String token) { + if (token == null) { + return this; + } + + setAuth(new SessionToken(token)); + + return this; + } + + public ApiClient setApiKey(String key) { + if (key == null) { + return this; + } + + setAuth(new ApiKey(key)); + + return this; + } + + /** + * Get an {@link HttpClient} based on the current {@link HttpClient.Builder}. + * + *

The returned object is immutable and thread-safe.

+ * + * @return The HTTP client. + */ + public HttpClient getHttpClient() { + return httpClient; + } + + /** + * Set a custom {@link ObjectMapper} to serialize and deserialize the request + * and response bodies. + * + * @param mapper Custom object mapper. + * @return This object. + */ + public ApiClient setObjectMapper(ObjectMapper mapper) { + this.mapper = mapper; + return this; + } + + /** + * Get a copy of the current {@link ObjectMapper}. + * + * @return A copy of the current object mapper. + */ + public ObjectMapper getObjectMapper() { + return mapper.copy(); + } + + /** + * Set a custom host name for the target service. + * + * @param host The host name of the target service. + * @return This object. + */ + public ApiClient setHost(String host) { + this.host = host; + return this; + } + + /** + * Set a custom port number for the target service. + * + * @param port The port of the target service. Set this to -1 to reset the + * value to the default for the scheme. + * @return This object. + */ + public ApiClient setPort(int port) { + this.port = port; + return this; + } + + /** + * Set a custom base path for the target service, for example '/v2'. + * + * @param basePath The base path against which the rest of the path is + * resolved. + * @return This object. + */ + public ApiClient setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + /** + * Get the base URI to resolve the endpoint paths against. + * + * @return The complete base URI that the rest of the API parameters are + * resolved against. + */ + public String getBaseUri() { + return scheme + "://" + host + (port == -1 ? "" : ":" + port) + basePath; + } + + /** + * Set a custom scheme for the target service, for example 'https'. + * + * @param scheme The scheme of the target service + * @return This object. + */ + public ApiClient setScheme(String scheme){ + this.scheme = scheme; + return this; + } + + /** + * Set a custom request interceptor. + * + *

A request interceptor is a mechanism for altering each request before it + * is sent. After the request has been fully configured but not yet built, the + * request builder is passed into this function for further modification, + * after which it is sent out.

+ * + *

This is useful for altering the requests in a custom manner, such as + * adding headers. It could also be used for logging and monitoring.

+ * + * @param interceptor A function invoked before creating each request. A value + * of null resets the interceptor to a no-op. + * @return This object. + */ + public ApiClient setRequestInterceptor(Consumer interceptor) { + this.interceptor = interceptor; + return this; + } + + /** + * Get the custom interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer getRequestInterceptor() { + return interceptor; + } + + /** + * Set a custom response interceptor. + * + *

This is useful for logging, monitoring or extraction of header variables

+ * + * @param interceptor A function invoked before creating each request. A value + * of null resets the interceptor to a no-op. + * @return This object. + */ + public ApiClient setResponseInterceptor(Consumer> interceptor) { + this.responseInterceptor = interceptor; + return this; + } + + /** + * Get the custom response interceptor. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer> getResponseInterceptor() { + return responseInterceptor; + } + + /** + * Set a custom async response interceptor. Use this interceptor when asyncNative is set to 'true'. + * + *

This is useful for logging, monitoring or extraction of header variables

+ * + * @param interceptor A function invoked before creating each request. A value + * of null resets the interceptor to a no-op. + * @return This object. + */ + public ApiClient setAsyncResponseInterceptor(Consumer> interceptor) { + this.asyncResponseInterceptor = interceptor; + return this; + } + + /** + * Get the custom async response interceptor. Use this interceptor when asyncNative is set to 'true'. + * + * @return The custom interceptor that was set, or null if there isn't any. + */ + public Consumer> getAsyncResponseInterceptor() { + return asyncResponseInterceptor; + } + + /** + * Set the read timeout for the http client. + * + *

This is the value used by default for each request, though it can be + * overridden on a per-request basis with a request interceptor.

+ * + * @param readTimeout The read timeout used by default by the http client. + * Setting this value to null resets the timeout to an + * effectively infinite value. + * @return This object. + */ + public ApiClient setReadTimeout(Duration readTimeout) { + this.readTimeout = readTimeout; + return this; + } + + /** + * Get the read timeout that was set. + * + * @return The read timeout, or null if no timeout was set. Null represents + * an infinite wait time. + */ + public Duration getReadTimeout() { + return readTimeout; + } +} \ No newline at end of file diff --git a/client2/src/main/template/libraries/native/api.mustache b/client2/src/main/template/libraries/native/api.mustache new file mode 100644 index 0000000000..93691d39d8 --- /dev/null +++ b/client2/src/main/template/libraries/native/api.mustache @@ -0,0 +1,567 @@ +{{>licenseInfo}} +package {{package}}; + +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.ApiResponse; +import {{invokerPackage}}.Pair; + +{{#imports}} +import {{import}}; +{{/imports}} + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import com.walmartlabs.concord.client2.impl.*; + +{{#hasFormParamsInSpec}} +{{/hasFormParamsInSpec}} +import java.io.InputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.net.http.HttpRequest; +import java.nio.channels.Channels; +import java.nio.channels.Pipe; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; + +{{^fullJavaUtil}} +import java.util.ArrayList; +import java.util.StringJoiner; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.HashMap; +import java.util.function.Consumer; +{{/fullJavaUtil}} +{{#asyncNative}} + +import java.util.concurrent.CompletableFuture; +{{/asyncNative}} + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + private final HttpClient memberVarHttpClient; + private final ObjectMapper memberVarObjectMapper; + private final String memberVarBaseUri; + private final {{#fullJavaUtil}}java.util.function.{{/fullJavaUtil}}Consumer memberVarInterceptor; + private final Duration memberVarReadTimeout; + private final {{#fullJavaUtil}}java.util.function.{{/fullJavaUtil}}Consumer> memberVarResponseInterceptor; + private final {{#fullJavaUtil}}java.util.function.{{/fullJavaUtil}}Consumer> memberVarAsyncResponseInterceptor; + + private final ApiClient apiClient; + + public {{classname}}(ApiClient apiClient) { + memberVarHttpClient = apiClient.getHttpClient(); + memberVarObjectMapper = apiClient.getObjectMapper(); + memberVarBaseUri = apiClient.getBaseUri(); + memberVarInterceptor = apiClient.getRequestInterceptor(); + memberVarReadTimeout = apiClient.getReadTimeout(); + memberVarResponseInterceptor = apiClient.getResponseInterceptor(); + memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor(); + + this.apiClient = apiClient; + } + + public ApiClient getApiClient() { + return this.apiClient; + } + + {{#asyncNative}} + + private ApiException getApiException(String operationId, HttpResponse response) { + String message = formatExceptionMessage(operationId, response.statusCode(), response.body()); + return new ApiException(response.statusCode(), message, response.headers(), response.body()); + } + {{/asyncNative}} + {{^asyncNative}} + + protected ApiException getApiException(String operationId, HttpResponse response) throws IOException { + String body = response.body() == null ? null : new String(response.body().readAllBytes()); + String message = formatExceptionMessage(operationId, response.statusCode(), body); + return new ApiException(response.statusCode(), message, response.headers(), body); + } + {{/asyncNative}} + + private String formatExceptionMessage(String operationId, int statusCode, String body) { + if (body == null || body.isEmpty()) { + body = "[no body]"; + } + return operationId + " call failed with: " + statusCode + " - " + body; + } + + {{#operation}} + {{#vendorExtensions.x-group-parameters}} + {{#hasParams}} + /** + * {{summary}} + * {{notes}} + * @param apiRequest {@link API{{operationId}}Request} + {{#returnType}} + * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}{{returnType}}{{#asyncNative}}>{{/asyncNative}} + {{/returnType}} + {{^returnType}} + {{#asyncNative}} + * @return CompletableFuture<Void> + {{/asyncNative}} + {{/returnType}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}(API{{operationId}}Request apiRequest) throws ApiException { + {{#allParams}} + {{{dataType}}} {{paramName}} = apiRequest.{{paramName}}(); + {{/allParams}} + {{#returnType}}return {{/returnType}}{{^returnType}}{{#asyncNative}}return {{/asyncNative}}{{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + } + + /** + * {{summary}} + * {{notes}} + * @param apiRequest {@link API{{operationId}}Request} + * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}}WithHttpInfo(API{{operationId}}Request apiRequest) throws ApiException { + {{#allParams}} + {{{dataType}}} {{paramName}} = apiRequest.{{paramName}}(); + {{/allParams}} + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + } + + {{/hasParams}} + {{/vendorExtensions.x-group-parameters}} + /** + * {{summary}} + * {{notes}} + {{#isMultipart}} + {{#allParams}} + {{^isFormParam}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}} + {{/isFormParam}} + {{/allParams}} + {{/isMultipart}} + {{^isMultipart}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}} + {{/allParams}} + {{/isMultipart}} + {{#returnType}} + * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}{{returnType}}{{#asyncNative}}>{{/asyncNative}} + {{/returnType}} + {{^returnType}} + {{#asyncNative}} + * @return CompletableFuture<Void> + {{/asyncNative}} + {{/returnType}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + + {{#vendorExtensions.x-concord.groupParams}} + public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{vendorExtensions.x-concord.groupName}} in) throws ApiException { + return {{operationId}}({{#isMultipart}}{{#allParams}}{{^isFormParam}}in.{{paramName}}(),{{/isFormParam}}{{/allParams}} multipartInput{{/isMultipart}}{{^isMultipart}}{{#allParams}}in.{{paramName}}(){{^-last}}, {{/-last}} {{/allParams}}{{/isMultipart}}); + } + {{/vendorExtensions.x-concord.groupParams}} + + public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{#isMultipart}}{{#allParams}}{{^isFormParam}}{{#vendorExtensions.x-concord.customQueryParams}}Map{{/vendorExtensions.x-concord.customQueryParams}}{{^vendorExtensions.x-concord.customQueryParams}}{{{dataType}}}{{/vendorExtensions.x-concord.customQueryParams}} {{paramName}},{{/isFormParam}}{{/allParams}} Map multipartInput{{/isMultipart}}{{^isMultipart}}{{#allParams}} {{#vendorExtensions.x-concord.customQueryParams}}Map{{/vendorExtensions.x-concord.customQueryParams}}{{^vendorExtensions.x-concord.customQueryParams}}{{{dataType}}}{{/vendorExtensions.x-concord.customQueryParams}} {{paramName}}{{^-last}}, {{/-last}} {{/allParams}}{{/isMultipart}}) throws ApiException { + {{^asyncNative}} + {{#returnType}}ApiResponse<{{{.}}}> localVarResponse = {{/returnType}}{{operationId}}WithHttpInfo({{#isMultipart}}{{#allParams}}{{^isFormParam}}{{paramName}},{{/isFormParam}}{{/allParams}} multipartInput{{/isMultipart}}{{^isMultipart}}{{#allParams}}{{paramName}}{{^-last}}, {{/-last}} {{/allParams}}{{/isMultipart}}); + {{#returnType}} + return localVarResponse.getData(); + {{/returnType}} + {{/asyncNative}} + {{#asyncNative}} + try { + HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + return memberVarHttpClient.sendAsync( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> { + if (localVarResponse.statusCode()/ 100 != 2) { + return CompletableFuture.failedFuture(getApiException("{{operationId}}", localVarResponse)); + } + {{#returnType}} + try { + String responseBody = localVarResponse.body(); + return CompletableFuture.completedFuture( + responseBody == null || responseBody.isBlank() ? null : memberVarObjectMapper.readValue(responseBody, new TypeReference<{{{returnType}}}>() {}) + ); + } catch (IOException e) { + return CompletableFuture.failedFuture(new ApiException(e)); + } + {{/returnType}} + {{^returnType}} + return CompletableFuture.completedFuture(null); + {{/returnType}} + }); + } + catch (ApiException e) { + return CompletableFuture.failedFuture(e); + } + {{/asyncNative}} + } + + /** + * {{summary}} + * {{notes}} + {{#isMultipart}} + {{#allParams}} + {{^isFormParam}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}} + {{/isFormParam}} + {{/allParams}} + {{/isMultipart}} + {{^isMultipart}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}} + {{/allParams}} + {{/isMultipart}} + * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}}WithHttpInfo({{#isMultipart}}{{#allParams}}{{^isFormParam}}{{#vendorExtensions.x-concord.customQueryParams}}Map{{/vendorExtensions.x-concord.customQueryParams}}{{^vendorExtensions.x-concord.customQueryParams}}{{{dataType}}}{{/vendorExtensions.x-concord.customQueryParams}} {{paramName}},{{/isFormParam}}{{/allParams}} Map multipartInput{{/isMultipart}}{{^isMultipart}}{{#allParams}} {{#vendorExtensions.x-concord.customQueryParams}}Map{{/vendorExtensions.x-concord.customQueryParams}}{{^vendorExtensions.x-concord.customQueryParams}}{{{dataType}}}{{/vendorExtensions.x-concord.customQueryParams}} {{paramName}}{{^-last}}, {{/-last}} {{/allParams}}{{/isMultipart}}) throws ApiException { + {{^asyncNative}} + HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#isMultipart}}{{#allParams}}{{^isFormParam}}{{paramName}},{{/isFormParam}}{{/allParams}} multipartInput{{/isMultipart}}{{^isMultipart}}{{#allParams}}{{paramName}}{{^-last}}, {{/-last}} {{/allParams}}{{/isMultipart}}); + try { + HttpResponse localVarResponse = memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode()/ 100 != 2) { + throw getApiException("{{operationId}}", localVarResponse); + } + if (localVarResponse.statusCode() == 204) { + return new ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + null + ); + } + + return new ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + {{#returnType}} + ResponseBodyHandler.handle(memberVarObjectMapper, localVarResponse, new TypeReference<{{{returnType}}}>() {}) + {{/returnType}} + {{^returnType}} + null + {{/returnType}} + ); + } finally { + {{^returnType}} + // Drain the InputStream + while (localVarResponse.body().read() != -1) { + // Ignore + } + localVarResponse.body().close(); + {{/returnType}} + } + } catch (IOException e) { + throw new ApiException(e); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + {{/asyncNative}} + {{#asyncNative}} + try { + HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + return memberVarHttpClient.sendAsync( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> { + if (memberVarAsyncResponseInterceptor != null) { + memberVarAsyncResponseInterceptor.accept(localVarResponse); + } + if (localVarResponse.statusCode()/ 100 != 2) { + return CompletableFuture.failedFuture(getApiException("{{operationId}}", localVarResponse)); + } + {{#returnType}} + try { + String responseBody = localVarResponse.body(); + return CompletableFuture.completedFuture( + new ApiResponse<{{{returnType}}}>( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + TODO:) + ); + } catch (IOException e) { + return CompletableFuture.failedFuture(new ApiException(e)); + } + {{/returnType}} + {{^returnType}} + return CompletableFuture.completedFuture( + new ApiResponse(localVarResponse.statusCode(), localVarResponse.headers().map(), null) + ); + {{/returnType}} + } + ); + } + catch (ApiException e) { + return CompletableFuture.failedFuture(e); + } + {{/asyncNative}} + } + + + private HttpRequest.Builder {{operationId}}RequestBuilder({{#isMultipart}}{{#allParams}}{{^isFormParam}}{{#vendorExtensions.x-concord.customQueryParams}}Map{{/vendorExtensions.x-concord.customQueryParams}}{{^vendorExtensions.x-concord.customQueryParams}}{{{dataType}}}{{/vendorExtensions.x-concord.customQueryParams}} {{paramName}},{{/isFormParam}}{{/allParams}} Map multipartInput{{/isMultipart}}{{^isMultipart}}{{#allParams}} {{#vendorExtensions.x-concord.customQueryParams}}Map{{/vendorExtensions.x-concord.customQueryParams}}{{^vendorExtensions.x-concord.customQueryParams}}{{{dataType}}}{{/vendorExtensions.x-concord.customQueryParams}} {{paramName}}{{^-last}}, {{/-last}} {{/allParams}}{{/isMultipart}}) throws ApiException { + {{#allParams}} + {{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + } + {{/required}} + {{/allParams}} + + HttpRequest.Builder localVarRequestBuilder = apiClient.requestBuilder(); + + {{! Switch delimiters for baseName so we can write constants like "{query}" }} + String localVarPath = "{{{path}}}"{{#pathParams}} + .replace({{=<% %>=}}"{<%baseName%>}"<%={{ }}=%>, ApiClient.urlEncode({{{paramName}}}.toString())){{/pathParams}}; + + {{#hasQueryParams}} + {{javaUtilPrefix}}List localVarQueryParams = new {{javaUtilPrefix}}ArrayList<>(); + {{javaUtilPrefix}}StringJoiner localVarQueryStringJoiner = new {{javaUtilPrefix}}StringJoiner("&"); + {{#queryParams}} + {{#vendorExtensions.x-concord.customQueryParams}} + if ({{paramName}} != null) { + for (Map.Entry e : {{paramName}}.entrySet()) { + localVarQueryParams.addAll(ApiClient.parameterToPairs(e.getKey(), e.getValue())); + } + } + {{/vendorExtensions.x-concord.customQueryParams}} + {{#collectionFormat}} + localVarQueryParams.addAll(ApiClient.parameterToPairs("{{{collectionFormat}}}", "{{baseName}}", {{paramName}})); + {{/collectionFormat}} + {{^collectionFormat}} + {{#isDeepObject}} + if ({{paramName}} != null) { + {{#isArray}} + for (int i=0; i < {{paramName}}.size(); i++) { + localVarQueryStringJoiner.add({{paramName}}.get(i).toUrlQueryString(String.format("{{baseName}}[%d]", i))); + } + {{/isArray}} + {{^isArray}} + localVarQueryStringJoiner.add({{paramName}}.toUrlQueryString("{{baseName}}")); + {{/isArray}} + } + {{/isDeepObject}} + {{^isDeepObject}} + {{#isExplode}} + {{#hasVars}} + {{#vars}} + {{#isArray}} + localVarQueryParams.addAll(ApiClient.parameterToPairs("multi", "{{baseName}}", {{paramName}}.{{getter}}())); + {{/isArray}} + {{^isArray}} + if ({{paramName}} != null) { + localVarQueryParams.addAll(ApiClient.parameterToPairs("{{paramName}}", {{paramName}}.{{getter}}())); + } + {{/isArray}} + {{/vars}} + {{/hasVars}} + {{^hasVars}} + {{#isModel}} + localVarQueryStringJoiner.add({{paramName}}.toUrlQueryString()); + {{/isModel}} + {{^isModel}} + {{^vendorExtensions.x-concord.customQueryParams}} + localVarQueryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}})); + {{/vendorExtensions.x-concord.customQueryParams}} + {{/isModel}} + {{/hasVars}} + {{/isExplode}} + {{^isExplode}} + localVarQueryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}})); + {{/isExplode}} + {{/isDeepObject}} + {{/collectionFormat}} + {{/queryParams}} + + if (!localVarQueryParams.isEmpty() || localVarQueryStringJoiner.length() != 0) { + {{javaUtilPrefix}}StringJoiner queryJoiner = new {{javaUtilPrefix}}StringJoiner("&"); + localVarQueryParams.forEach(p -> queryJoiner.add(p.getName() + '=' + p.getValue())); + if (localVarQueryStringJoiner.length() != 0) { + queryJoiner.add(localVarQueryStringJoiner.toString()); + } + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath + '?' + queryJoiner.toString())); + } else { + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + } + {{/hasQueryParams}} + {{^hasQueryParams}} + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + {{/hasQueryParams}} + + {{#headerParams}} + if ({{paramName}} != null) { + localVarRequestBuilder.header("{{baseName}}", {{paramName}}.toString()); + } + {{/headerParams}} + {{#bodyParam}} + localVarRequestBuilder.header("Content-Type", "{{#hasConsumes}}{{#consumes}}{{#-first}}{{mediaType}}{{/-first}}{{/consumes}}{{/hasConsumes}}{{#hasConsumes}}{{^consumes}}application/json{{/consumes}}{{/hasConsumes}}{{^hasConsumes}}application/json{{/hasConsumes}}"); + {{/bodyParam}} + String acceptHeaderValue = "{{#hasProduces}}{{#produces}}{{mediaType}}{{^-last}}, {{/-last}}{{/produces}}{{/hasProduces}}{{#hasProduces}}{{^produces}}application/json{{/produces}}{{/hasProduces}}{{^hasProduces}}application/json{{/hasProduces}}"; + acceptHeaderValue += ",application/vnd.siesta-validation-errors-v1+json"; + localVarRequestBuilder.header("Accept", acceptHeaderValue); + {{#bodyParam}} + {{#isString}} + localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.ofString({{paramName}})); + {{/isString}} + {{^isString}} + try { + localVarRequestBuilder.method("{{httpMethod}}", RequestBodyHandler.handle(memberVarObjectMapper, {{paramName}})); + } catch (IOException e) { + throw new ApiException(e); + } + {{/isString}} + {{/bodyParam}} + {{^bodyParam}} + + {{#isMultipart}} + HttpEntity entity = MultipartRequestBodyHandler.handle(memberVarObjectMapper, multipartInput); + localVarRequestBuilder + .header("Content-Type", entity.contentType().toString()) + .method("{{httpMethod}}", HttpRequest.BodyPublishers.ofInputStream(() -> { + try { + return entity.getContent(); + } catch (IOException e) { + throw new RuntimeException(e); + } + })); + {{/isMultipart}} + {{^isMultipart}} + {{#hasFormParams}} + List formValues = new ArrayList<>(); + {{#formParams}} + {{#isArray}} + for (int i=0; i < {{paramName}}.size(); i++) { + if ({{paramName}}.get(i) != null) { + formValues.add(new NameValuePair("{{{baseName}}}", {{paramName}}.get(i).toString())); + } + } + {{/isArray}} + {{^isArray}} + if ({{paramName}} != null) { + formValues.add(new NameValuePair("{{{baseName}}}", {{paramName}}.toString())); + } + {{/isArray}} + {{/formParams}} + HttpEntity entity = new UrlEncodedFormEntity(formValues, java.nio.charset.StandardCharsets.UTF_8); + ByteArrayOutputStream formOutputStream = new ByteArrayOutputStream(); + try { + entity.writeTo(formOutputStream); + } catch (IOException e) { + throw new RuntimeException(e); + } + localVarRequestBuilder + .header("Content-Type", entity.getContentType().toString()) + .method("{{httpMethod}}", HttpRequest.BodyPublishers + .ofInputStream(() -> new ByteArrayInputStream(formOutputStream.toByteArray()))); + + {{/hasFormParams}} + {{^hasFormParams}} + localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.noBody()); + {{/hasFormParams}} + {{/isMultipart}} + + + {{/bodyParam}} + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); + } + return localVarRequestBuilder; + } + {{#isMultipart}} + {{#hasParams}} + + public static final class {{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}Request { + {{#allParams}} + {{#isFormParam}} + private {{{dataType}}} {{paramName}}; + {{/isFormParam}} + {{/allParams}} + + {{#allParams}} + {{#isFormParam}} + public {{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}Request {{paramName}}({{{dataType}}} {{paramName}}) { + this.{{paramName}} = {{paramName}}; + return this; + } + {{/isFormParam}} + {{/allParams}} + + public Map asMap() { + Map result = new HashMap<>(); + + {{#allParams}} + {{#isFormParam}} + if ({{paramName}} != null) { + result.put("{{baseName}}", {{paramName}}); + } + {{/isFormParam}} + {{/allParams}} + + return result; + } + } + + {{/hasParams}} + {{/isMultipart}} + {{/operation}} +} +{{/operations}} diff --git a/client2/src/main/template/libraries/native/api.mustache.orig b/client2/src/main/template/libraries/native/api.mustache.orig new file mode 100644 index 0000000000..526e565234 --- /dev/null +++ b/client2/src/main/template/libraries/native/api.mustache.orig @@ -0,0 +1,591 @@ +{{>licenseInfo}} +package {{package}}; + +import {{invokerPackage}}.ApiClient; +import {{invokerPackage}}.ApiException; +import {{invokerPackage}}.ApiResponse; +import {{invokerPackage}}.Pair; + +{{#imports}} +import {{import}}; +{{/imports}} + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +{{#hasFormParamsInSpec}} +import org.apache.http.HttpEntity; +import org.apache.http.NameValuePair; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; + +{{/hasFormParamsInSpec}} +import java.io.InputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.net.http.HttpRequest; +import java.nio.channels.Channels; +import java.nio.channels.Pipe; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; + +import java.util.ArrayList; +import java.util.StringJoiner; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Consumer; +{{#asyncNative}} + +import java.util.concurrent.CompletableFuture; +{{/asyncNative}} + +{{>generatedAnnotation}} +{{#operations}} +public class {{classname}} { + private final HttpClient memberVarHttpClient; + private final ObjectMapper memberVarObjectMapper; + private final String memberVarBaseUri; + private final Consumer memberVarInterceptor; + private final Duration memberVarReadTimeout; + private final Consumer> memberVarResponseInterceptor; + private final Consumer> memberVarAsyncResponseInterceptor; + + public {{classname}}() { + this(new ApiClient()); + } + + public {{classname}}(ApiClient apiClient) { + memberVarHttpClient = apiClient.getHttpClient(); + memberVarObjectMapper = apiClient.getObjectMapper(); + memberVarBaseUri = apiClient.getBaseUri(); + memberVarInterceptor = apiClient.getRequestInterceptor(); + memberVarReadTimeout = apiClient.getReadTimeout(); + memberVarResponseInterceptor = apiClient.getResponseInterceptor(); + memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor(); + } + {{#asyncNative}} + + private ApiException getApiException(String operationId, HttpResponse response) { + String message = formatExceptionMessage(operationId, response.statusCode(), response.body()); + return new ApiException(response.statusCode(), message, response.headers(), response.body()); + } + {{/asyncNative}} + {{^asyncNative}} + + protected ApiException getApiException(String operationId, HttpResponse response) throws IOException { + String body = response.body() == null ? null : new String(response.body().readAllBytes()); + String message = formatExceptionMessage(operationId, response.statusCode(), body); + return new ApiException(response.statusCode(), message, response.headers(), body); + } + {{/asyncNative}} + + private String formatExceptionMessage(String operationId, int statusCode, String body) { + if (body == null || body.isEmpty()) { + body = "[no body]"; + } + return operationId + " call failed with: " + statusCode + " - " + body; + } + + {{#operation}} + {{#vendorExtensions.x-group-parameters}} + {{#hasParams}} + /** + * {{summary}} + * {{notes}} + * @param apiRequest {@link API{{operationId}}Request} + {{#returnType}} + * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}{{returnType}}{{#asyncNative}}>{{/asyncNative}} + {{/returnType}} + {{^returnType}} + {{#asyncNative}} + * @return CompletableFuture<Void> + {{/asyncNative}} + {{/returnType}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}(API{{operationId}}Request apiRequest) throws ApiException { + {{#allParams}} + {{{dataType}}} {{paramName}} = apiRequest.{{paramName}}(); + {{/allParams}} + {{#returnType}}return {{/returnType}}{{^returnType}}{{#asyncNative}}return {{/asyncNative}}{{/returnType}}{{operationId}}({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + } + + /** + * {{summary}} + * {{notes}} + * @param apiRequest {@link API{{operationId}}Request} + * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}}WithHttpInfo(API{{operationId}}Request apiRequest) throws ApiException { + {{#allParams}} + {{{dataType}}} {{paramName}} = apiRequest.{{paramName}}(); + {{/allParams}} + return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + } + + {{/hasParams}} + {{/vendorExtensions.x-group-parameters}} + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}} + {{/allParams}} + {{#returnType}} + * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}{{returnType}}{{#asyncNative}}>{{/asyncNative}} + {{/returnType}} + {{^returnType}} + {{#asyncNative}} + * @return CompletableFuture<Void> + {{/asyncNative}} + {{/returnType}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#returnType}}{{#asyncNative}}CompletableFuture<{{{returnType}}}>{{/asyncNative}}{{^asyncNative}}{{{returnType}}}{{/asyncNative}}{{/returnType}}{{^returnType}}{{#asyncNative}}CompletableFuture{{/asyncNative}}{{^asyncNative}}void{{/asyncNative}}{{/returnType}} {{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + {{^asyncNative}} + {{#returnType}}ApiResponse<{{{.}}}> localVarResponse = {{/returnType}}{{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + {{#returnType}} + return localVarResponse.getData(); + {{/returnType}} + {{/asyncNative}} + {{#asyncNative}} + try { + HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + return memberVarHttpClient.sendAsync( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> { + if (localVarResponse.statusCode()/ 100 != 2) { + return CompletableFuture.failedFuture(getApiException("{{operationId}}", localVarResponse)); + } + {{#returnType}} + try { + String responseBody = localVarResponse.body(); + return CompletableFuture.completedFuture( + responseBody == null || responseBody.isBlank() ? null : memberVarObjectMapper.readValue(responseBody, new TypeReference<{{{returnType}}}>() {}) + ); + } catch (IOException e) { + return CompletableFuture.failedFuture(new ApiException(e)); + } + {{/returnType}} + {{^returnType}} + return CompletableFuture.completedFuture(null); + {{/returnType}} + }); + } + catch (ApiException e) { + return CompletableFuture.failedFuture(e); + } + {{/asyncNative}} + } + + /** + * {{summary}} + * {{notes}} + {{#allParams}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}}{{/required}} + {{/allParams}} + * @return {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{returnType}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} + * @throws ApiException if fails to make API call + {{#isDeprecated}} + * @deprecated + {{/isDeprecated}} + {{#externalDocs}} + * {{description}} + * @see {{summary}} Documentation + {{/externalDocs}} + */ + {{#isDeprecated}} + @Deprecated + {{/isDeprecated}} + public {{#asyncNative}}CompletableFuture<{{/asyncNative}}ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>{{#asyncNative}}>{{/asyncNative}} {{operationId}}WithHttpInfo({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + {{^asyncNative}} + HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + try { + HttpResponse localVarResponse = memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode()/ 100 != 2) { + throw getApiException("{{operationId}}", localVarResponse); + } + {{#vendorExtensions.x-java-text-plain-string}} + // for plain text response + if (localVarResponse.headers().map().containsKey("Content-Type") && + "text/plain".equalsIgnoreCase(localVarResponse.headers().map().get("Content-Type").get(0).split(";")[0].trim())) { + java.util.Scanner s = new java.util.Scanner(localVarResponse.body()).useDelimiter("\\A"); + String responseBodyText = s.hasNext() ? s.next() : ""; + return new ApiResponse( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + responseBodyText + ); + } else { + throw new RuntimeException("Error! The response Content-Type is supposed to be `text/plain` but it's not: " + localVarResponse); + } + {{/vendorExtensions.x-java-text-plain-string}} + {{^vendorExtensions.x-java-text-plain-string}} + return new ApiResponse<{{{returnType}}}{{^returnType}}Void{{/returnType}}>( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + {{#returnType}} + localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference<{{{returnType}}}>() {}) // closes the InputStream + {{/returnType}} + {{^returnType}} + null + {{/returnType}} + ); + {{/vendorExtensions.x-java-text-plain-string}} + } finally { + {{^returnType}} + // Drain the InputStream + while (localVarResponse.body().read() != -1) { + // Ignore + } + localVarResponse.body().close(); + {{/returnType}} + } + } catch (IOException e) { + throw new ApiException(e); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + {{/asyncNative}} + {{#asyncNative}} + try { + HttpRequest.Builder localVarRequestBuilder = {{operationId}}RequestBuilder({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}); + return memberVarHttpClient.sendAsync( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofString()).thenComposeAsync(localVarResponse -> { + if (memberVarAsyncResponseInterceptor != null) { + memberVarAsyncResponseInterceptor.accept(localVarResponse); + } + if (localVarResponse.statusCode()/ 100 != 2) { + return CompletableFuture.failedFuture(getApiException("{{operationId}}", localVarResponse)); + } + {{#returnType}} + try { + String responseBody = localVarResponse.body(); + return CompletableFuture.completedFuture( + new ApiResponse<{{{returnType}}}>( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + responseBody == null || responseBody.isBlank() ? null : memberVarObjectMapper.readValue(responseBody, new TypeReference<{{{returnType}}}>() {})) + ); + } catch (IOException e) { + return CompletableFuture.failedFuture(new ApiException(e)); + } + {{/returnType}} + {{^returnType}} + return CompletableFuture.completedFuture( + new ApiResponse(localVarResponse.statusCode(), localVarResponse.headers().map(), null) + ); + {{/returnType}} + } + ); + } + catch (ApiException e) { + return CompletableFuture.failedFuture(e); + } + {{/asyncNative}} + } + + private HttpRequest.Builder {{operationId}}RequestBuilder({{#allParams}}{{{dataType}}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws ApiException { + {{#allParams}} + {{#required}} + // verify the required parameter '{{paramName}}' is set + if ({{paramName}} == null) { + throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{operationId}}"); + } + {{/required}} + {{/allParams}} + + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + + {{! Switch delimiters for baseName so we can write constants like "{query}" }} + String localVarPath = "{{{path}}}"{{#pathParams}} + .replace({{=<% %>=}}"{<%baseName%>}"<%={{ }}=%>, ApiClient.urlEncode({{{paramName}}}.toString())){{/pathParams}}; + + {{#hasQueryParams}} + List localVarQueryParams = new ArrayList<>(); + StringJoiner localVarQueryStringJoiner = new StringJoiner("&"); + String localVarQueryParameterBaseName; + {{#queryParams}} + localVarQueryParameterBaseName = "{{{baseName}}}"; + {{#collectionFormat}} + localVarQueryParams.addAll(ApiClient.parameterToPairs("{{{collectionFormat}}}", "{{baseName}}", {{paramName}})); + {{/collectionFormat}} + {{^collectionFormat}} + {{#isDeepObject}} + if ({{paramName}} != null) { + {{#isArray}} + for (int i=0; i < {{paramName}}.size(); i++) { + localVarQueryStringJoiner.add({{paramName}}.get(i).toUrlQueryString(String.format("{{baseName}}[%d]", i))); + } + {{/isArray}} + {{^isArray}} + localVarQueryStringJoiner.add({{paramName}}.toUrlQueryString("{{baseName}}")); + {{/isArray}} + } + {{/isDeepObject}} + {{^isDeepObject}} + {{#isExplode}} + {{#hasVars}} + {{#vars}} + {{#isArray}} + localVarQueryParams.addAll(ApiClient.parameterToPairs("multi", "{{baseName}}", {{paramName}}.{{getter}}())); + {{/isArray}} + {{^isArray}} + localVarQueryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}}.{{getter}}())); + {{/isArray}} + {{/vars}} + {{/hasVars}} + {{^hasVars}} + {{#isModel}} + localVarQueryStringJoiner.add({{paramName}}.toUrlQueryString()); + {{/isModel}} + {{^isModel}} + localVarQueryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}})); + {{/isModel}} + {{/hasVars}} + {{/isExplode}} + {{^isExplode}} + localVarQueryParams.addAll(ApiClient.parameterToPairs("{{baseName}}", {{paramName}})); + {{/isExplode}} + {{/isDeepObject}} + {{/collectionFormat}} + {{/queryParams}} + + if (!localVarQueryParams.isEmpty() || localVarQueryStringJoiner.length() != 0) { + StringJoiner queryJoiner = new StringJoiner("&"); + localVarQueryParams.forEach(p -> queryJoiner.add(p.getName() + '=' + p.getValue())); + if (localVarQueryStringJoiner.length() != 0) { + queryJoiner.add(localVarQueryStringJoiner.toString()); + } + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath + '?' + queryJoiner.toString())); + } else { + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + } + {{/hasQueryParams}} + {{^hasQueryParams}} + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + {{/hasQueryParams}} + + {{#headerParams}} + if ({{paramName}} != null) { + localVarRequestBuilder.header("{{baseName}}", {{paramName}}.toString()); + } + {{/headerParams}} + {{#bodyParam}} + localVarRequestBuilder.header("Content-Type", "{{#hasConsumes}}{{#consumes}}{{#-first}}{{mediaType}}{{/-first}}{{/consumes}}{{/hasConsumes}}{{#hasConsumes}}{{^consumes}}application/json{{/consumes}}{{/hasConsumes}}{{^hasConsumes}}application/json{{/hasConsumes}}"); + {{/bodyParam}} + localVarRequestBuilder.header("Accept", "{{#hasProduces}}{{#produces}}{{mediaType}}{{^-last}}, {{/-last}}{{/produces}}{{/hasProduces}}{{#hasProduces}}{{^produces}}application/json{{/produces}}{{/hasProduces}}{{^hasProduces}}application/json{{/hasProduces}}"); + + {{#bodyParam}} + {{#isString}} + localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.ofString({{paramName}})); + {{/isString}} + {{^isString}} + try { + byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes({{paramName}}); + localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); + } catch (IOException e) { + throw new ApiException(e); + } + {{/isString}} + {{/bodyParam}} + {{^bodyParam}} + {{#hasFormParams}} + {{#isMultipart}} + MultipartEntityBuilder multiPartBuilder = MultipartEntityBuilder.create(); + boolean hasFiles = false; + {{#formParams}} + {{#isArray}} + for (int i=0; i < {{paramName}}.size(); i++) { + {{#isFile}} + multiPartBuilder.addBinaryBody("{{{baseName}}}", {{paramName}}.get(i)); + hasFiles = true; + {{/isFile}} + {{^isFile}} + multiPartBuilder.addTextBody("{{{baseName}}}", {{paramName}}.get(i).toString()); + {{/isFile}} + } + {{/isArray}} + {{^isArray}} + {{#isFile}} + multiPartBuilder.addBinaryBody("{{{baseName}}}", {{paramName}}); + hasFiles = true; + {{/isFile}} + {{^isFile}} + multiPartBuilder.addTextBody("{{{baseName}}}", {{paramName}}.toString()); + {{/isFile}} + {{/isArray}} + {{/formParams}} + HttpEntity entity = multiPartBuilder.build(); + HttpRequest.BodyPublisher formDataPublisher; + if (hasFiles) { + Pipe pipe; + try { + pipe = Pipe.open(); + } catch (IOException e) { + throw new RuntimeException(e); + } + new Thread(() -> { + try (OutputStream outputStream = Channels.newOutputStream(pipe.sink())) { + entity.writeTo(outputStream); + } catch (IOException e) { + e.printStackTrace(); + } + }).start(); + formDataPublisher = HttpRequest.BodyPublishers.ofInputStream(() -> Channels.newInputStream(pipe.source())); + } else { + ByteArrayOutputStream formOutputStream = new ByteArrayOutputStream(); + try { + entity.writeTo(formOutputStream); + } catch (IOException e) { + throw new RuntimeException(e); + } + formDataPublisher = HttpRequest.BodyPublishers + .ofInputStream(() -> new ByteArrayInputStream(formOutputStream.toByteArray())); + } + localVarRequestBuilder + .header("Content-Type", entity.getContentType().getValue()) + .method("{{httpMethod}}", formDataPublisher); + {{/isMultipart}} + {{^isMultipart}} + List formValues = new ArrayList<>(); + {{#formParams}} + {{#isArray}} + for (int i=0; i < {{paramName}}.size(); i++) { + if ({{paramName}}.get(i) != null) { + formValues.add(new BasicNameValuePair("{{{baseName}}}", {{paramName}}.get(i).toString())); + } + } + {{/isArray}} + {{^isArray}} + if ({{paramName}} != null) { + formValues.add(new BasicNameValuePair("{{{baseName}}}", {{paramName}}.toString())); + } + {{/isArray}} + {{/formParams}} + HttpEntity entity = new UrlEncodedFormEntity(formValues, java.nio.charset.StandardCharsets.UTF_8); + ByteArrayOutputStream formOutputStream = new ByteArrayOutputStream(); + try { + entity.writeTo(formOutputStream); + } catch (IOException e) { + throw new RuntimeException(e); + } + localVarRequestBuilder + .header("Content-Type", entity.getContentType().getValue()) + .method("{{httpMethod}}", HttpRequest.BodyPublishers + .ofInputStream(() -> new ByteArrayInputStream(formOutputStream.toByteArray()))); + {{/isMultipart}} + {{/hasFormParams}} + {{^hasFormParams}} + localVarRequestBuilder.method("{{httpMethod}}", HttpRequest.BodyPublishers.noBody()); + {{/hasFormParams}} + {{/bodyParam}} + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); + } + return localVarRequestBuilder; + } + {{#vendorExtensions.x-group-parameters}} + {{#hasParams}} + + public static final class API{{operationId}}Request { + {{#requiredParams}} + private {{{dataType}}} {{paramName}}; // {{description}} (required) + {{/requiredParams}} + {{#optionalParams}} + private {{{dataType}}} {{paramName}}; // {{description}} (optional{{^isContainer}}{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/isContainer}} + {{/optionalParams}} + + private API{{operationId}}Request(Builder builder) { + {{#requiredParams}} + this.{{paramName}} = builder.{{paramName}}; + {{/requiredParams}} + {{#optionalParams}} + this.{{paramName}} = builder.{{paramName}}; + {{/optionalParams}} + } + {{#allParams}} + public {{{dataType}}} {{paramName}}() { + return {{paramName}}; + } + {{/allParams}} + public static Builder newBuilder() { + return new Builder(); + } + + public static class Builder { + {{#requiredParams}} + private {{{dataType}}} {{paramName}}; + {{/requiredParams}} + {{#optionalParams}} + private {{{dataType}}} {{paramName}}; + {{/optionalParams}} + + {{#allParams}} + public Builder {{paramName}}({{{dataType}}} {{paramName}}) { + this.{{paramName}} = {{paramName}}; + return this; + } + {{/allParams}} + public API{{operationId}}Request build() { + return new API{{operationId}}Request(this); + } + } + } + + {{/hasParams}} + {{/vendorExtensions.x-group-parameters}} + {{/operation}} +} +{{/operations}} diff --git a/client2/src/main/template/libraries/native/pojo.mustache b/client2/src/main/template/libraries/native/pojo.mustache new file mode 100644 index 0000000000..5dd97018f5 --- /dev/null +++ b/client2/src/main/template/libraries/native/pojo.mustache @@ -0,0 +1,596 @@ +{{#discriminator}} +import {{invokerPackage}}.JSON; +{{/discriminator}} +/** + * {{description}}{{^description}}{{classname}}{{/description}}{{#isDeprecated}} + * @deprecated{{/isDeprecated}} + */{{#isDeprecated}} +@Deprecated{{/isDeprecated}} +{{#swagger1AnnotationLibrary}} +{{#description}} +@ApiModel(description = "{{{.}}}") +{{/description}} +{{/swagger1AnnotationLibrary}} +{{#swagger2AnnotationLibrary}} +{{#description}} +@Schema(description = "{{{.}}}") +{{/description}} +{{/swagger2AnnotationLibrary}} +{{#jackson}} +@JsonPropertyOrder({ +{{#vars}} + {{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}} +{{/vars}} +}) +{{/jackson}} +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} +{{#vendorExtensions.x-class-extra-annotation}} +{{{vendorExtensions.x-class-extra-annotation}}} +{{/vendorExtensions.x-class-extra-annotation}} +public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{ +{{#serializableModel}} + private static final long serialVersionUID = 1L; + +{{/serializableModel}} + {{#vars}} + {{#isEnum}} + {{^isContainer}} + {{^vendorExtensions.x-enum-as-string}} +{{>modelInnerEnum}} + {{/vendorExtensions.x-enum-as-string}} + {{/isContainer}} + {{#isContainer}} + {{#mostInnerItems}} +{{>modelInnerEnum}} + {{/mostInnerItems}} + {{/isContainer}} + {{/isEnum}} + {{#gson}} + public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}"; + {{/gson}} + {{#jackson}} + public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}"; + {{/jackson}} + {{#withXml}} + {{#isXmlAttribute}} + @XmlAttribute(name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlAttribute}} + {{^isXmlAttribute}} + {{^isContainer}} + @XmlElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isContainer}} + {{#isContainer}} + // Is a container wrapped={{isXmlWrapped}} + {{#items}} + // items.name={{name}} items.baseName={{baseName}} items.xmlName={{xmlName}} items.xmlNamespace={{xmlNamespace}} + // items.example={{example}} items.type={{dataType}} + @XmlElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/items}} + {{#isXmlWrapped}} + @XmlElementWrapper({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlWrapped}} + {{/isContainer}} + {{/isXmlAttribute}} + {{/withXml}} + {{#gson}} + @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) + {{/gson}} + {{#vendorExtensions.x-field-extra-annotation}} + {{{vendorExtensions.x-field-extra-annotation}}} + {{/vendorExtensions.x-field-extra-annotation}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined(); + {{/isContainer}} + {{^isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + {{/isContainer}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + + {{/vars}} + public {{classname}}() { {{#parent}}{{#parcelableModel}} + super();{{/parcelableModel}}{{/parent}}{{#gson}}{{#discriminator}} + this.{{{discriminatorName}}} = this.getClass().getSimpleName();{{/discriminator}}{{/gson}} + }{{#vendorExtensions.x-has-readonly-properties}}{{^withXml}} + + {{#jackson}}@JsonCreator{{/jackson}} + public {{classname}}( + {{#readOnlyVars}} + @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) {{{datatypeWithEnum}}} {{name}}{{^-last}}, {{/-last}} + {{/readOnlyVars}} + ) { + this(); + {{#readOnlyVars}} + this.{{name}} = {{#vendorExtensions.x-is-jackson-optional-nullable}}{{name}} == null ? JsonNullable.<{{{datatypeWithEnum}}}>undefined() : JsonNullable.of({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{name}}{{/vendorExtensions.x-is-jackson-optional-nullable}}; + {{/readOnlyVars}} + }{{/withXml}}{{/vendorExtensions.x-has-readonly-properties}} + {{#vars}} + + {{^isReadOnly}} + {{#vendorExtensions.x-enum-as-string}} + public static final Set {{{nameInSnakeCase}}}_VALUES = new HashSet<>(Arrays.asList( + {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}} + )); + + {{/vendorExtensions.x-enum-as-string}} + public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-enum-as-string}} + if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) { + throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES)); + } + + {{/vendorExtensions.x-enum-as-string}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + return this; + } + {{#isArray}} + + public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}}); + } + try { + this.{{name}}.get().add({{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}}; + } + this.{{name}}.add({{name}}Item); + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isArray}} + {{#isMap}} + + public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}}); + } + try { + this.{{name}}.get().put(key, {{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}}; + } + this.{{name}}.put(key, {{name}}Item); + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isMap}} + + {{/isReadOnly}} + /** + {{#description}} + * {{.}} + {{/description}} + {{^description}} + * Get {{name}} + {{/description}} + {{#minimum}} + * minimum: {{.}} + {{/minimum}} + {{#maximum}} + * maximum: {{.}} + {{/maximum}} + * @return {{name}} + {{#deprecated}} + * @deprecated + {{/deprecated}} + **/ +{{#deprecated}} + @Deprecated +{{/deprecated}} +// {{#required}} +// {{#isNullable}} +// @{{javaxPackage}}.annotation.Nullable +// {{/isNullable}} +// {{^isNullable}} +// @{{javaxPackage}}.annotation.Nonnull +// {{/isNullable}} +// {{/required}} +// {{^required}} +// @{{javaxPackage}}.annotation.Nullable +// {{/required}} +{{#useBeanValidation}} +{{>beanValidation}} +{{/useBeanValidation}} +{{#swagger1AnnotationLibrary}} + @ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") +{{/swagger1AnnotationLibrary}} +{{#swagger2AnnotationLibrary}} + @Schema({{#example}}example = "{{{.}}}", {{/example}}requiredMode = {{#required}}Schema.RequiredMode.REQUIRED{{/required}}{{^required}}Schema.RequiredMode.NOT_REQUIRED{{/required}}, description = "{{{description}}}") +{{/swagger2AnnotationLibrary}} +{{#vendorExtensions.x-extra-annotation}} + {{{vendorExtensions.x-extra-annotation}}} +{{/vendorExtensions.x-extra-annotation}} +{{#vendorExtensions.x-is-jackson-optional-nullable}} + {{!unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}} + @JsonIgnore +{{/vendorExtensions.x-is-jackson-optional-nullable}} +{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.x-is-jackson-optional-nullable}} + public {{{datatypeWithEnum}}} {{getter}}() { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#isReadOnly}}{{! A readonly attribute doesn't have setter => jackson will set null directly if explicitly returned by API, so make sure we have an empty JsonNullable}} + if ({{name}} == null) { + {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + } + {{/isReadOnly}} + return {{name}}.orElse(null); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + return {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + + {{#vendorExtensions.x-is-jackson-optional-nullable}} +{{> jackson_annotations}} + public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() { + return {{name}}; + } + {{/vendorExtensions.x-is-jackson-optional-nullable}}{{#vendorExtensions.x-is-jackson-optional-nullable}} + @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) + {{#isReadOnly}}private{{/isReadOnly}}{{^isReadOnly}}public{{/isReadOnly}} void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) { + {{! For getters/setters that have name differing from attribute name, we must include setter (albeit private) for jackson to be able to set the attribute}} + this.{{name}} = {{name}}; + } + {{/vendorExtensions.x-is-jackson-optional-nullable}} + + {{^isReadOnly}} +{{#vendorExtensions.x-setter-extra-annotation}} {{{vendorExtensions.x-setter-extra-annotation}}} +{{/vendorExtensions.x-setter-extra-annotation}}{{#jackson}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{> jackson_annotations}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{/jackson}} public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-enum-as-string}} + if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) { + throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES)); + } + + {{/vendorExtensions.x-enum-as-string}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isReadOnly}} + + {{/vars}} +{{>libraries/native/additional_properties}} + {{#parent}} + {{#allVars}} + {{#isOverridden}} + @Override + public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + this.{{setter}}(JsonNullable.<{{{datatypeWithEnum}}}>of({{name}})); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + this.{{setter}}({{name}}); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + return this; + } + + {{/isOverridden}} + {{/allVars}} + {{/parent}} + /** + * Return true if this {{name}} object is equal to o. + */ + @Override + public boolean equals(Object o) { + {{#useReflectionEqualsHashCode}} + return EqualsBuilder.reflectionEquals(this, o, false, null, true); + {{/useReflectionEqualsHashCode}} + {{^useReflectionEqualsHashCode}} + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + }{{#hasVars}} + {{classname}} {{classVarName}} = ({{classname}}) o; + return {{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}equalsNullable(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}} && + {{/-last}}{{/vars}}{{#additionalPropertiesType}}&& + Objects.equals(this.additionalProperties, {{classVarName}}.additionalProperties){{/additionalPropertiesType}}{{#parent}} && + super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} + return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} + {{/useReflectionEqualsHashCode}} + }{{#vendorExtensions.x-jackson-optional-nullable-helpers}} + + private static boolean equalsNullable(JsonNullable a, JsonNullable b) { + return a == b || (a != null && b != null && a.isPresent() && b.isPresent() && Objects.deepEquals(a.get(), b.get())); + }{{/vendorExtensions.x-jackson-optional-nullable-helpers}} + + @Override + public int hashCode() { + {{#useReflectionEqualsHashCode}} + return HashCodeBuilder.reflectionHashCode(this); + {{/useReflectionEqualsHashCode}} + {{^useReflectionEqualsHashCode}} + return Objects.hash({{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}hashCodeNullable({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}{{#additionalPropertiesType}}, additionalProperties{{/additionalPropertiesType}}); + {{/useReflectionEqualsHashCode}} + }{{#vendorExtensions.x-jackson-optional-nullable-helpers}} + + private static int hashCodeNullable(JsonNullable a) { + if (a == null) { + return 1; + } + return a.isPresent() ? Arrays.deepHashCode(new Object[]{a.get()}) : 31; + }{{/vendorExtensions.x-jackson-optional-nullable-helpers}} + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class {{classname}} {\n"); + {{#parent}} + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + {{/parent}} + {{#vars}} + sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n"); + {{/vars}} + {{#additionalPropertiesType}} + sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); + {{/additionalPropertiesType}} + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +{{#supportUrlQuery}} + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + {{#allVars}} + // add `{{baseName}}` to the URL query string + {{#isArray}} + {{#items.isPrimitiveType}} + {{#uniqueItems}} + if ({{getter}}() != null) { + int i = 0; + for ({{{items.dataType}}} _item : {{getter}}()) { + joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix), + URLEncoder.encode(String.valueOf(_item), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + i++; + } + {{/uniqueItems}} + {{^uniqueItems}} + if ({{getter}}() != null) { + for (int i = 0; i < {{getter}}().size(); i++) { + joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix), + URLEncoder.encode(String.valueOf({{getter}}().get(i)), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + } + {{/uniqueItems}} + {{/items.isPrimitiveType}} + {{^items.isPrimitiveType}} + {{#items.isModel}} + {{#uniqueItems}} + if ({{getter}}() != null) { + int i = 0; + for ({{{items.dataType}}} _item : {{getter}}()) { + if (_item != null) { + joiner.add(_item.toUrlQueryString(String.format("%s{{baseName}}%s%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix)))); + } + } + i++; + } + {{/uniqueItems}} + {{^uniqueItems}} + if ({{getter}}() != null) { + for (int i = 0; i < {{getter}}().size(); i++) { + if ({{getter}}().get(i) != null) { + joiner.add({{getter}}().get(i).toUrlQueryString(String.format("%s{{baseName}}%s%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix)))); + } + } + } + {{/uniqueItems}} + {{/items.isModel}} + {{^items.isModel}} + {{#uniqueItems}} + if ({{getter}}() != null) { + int i = 0; + for ({{{items.dataType}}} _item : {{getter}}()) { + if (_item != null) { + joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix), + URLEncoder.encode(String.valueOf(_item), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + i++; + } + } + {{/uniqueItems}} + {{^uniqueItems}} + if ({{getter}}() != null) { + for (int i = 0; i < {{getter}}().size(); i++) { + if ({{getter}}().get(i) != null) { + joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix), + URLEncoder.encode(String.valueOf({{getter}}().get(i)), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + } + } + {{/uniqueItems}} + {{/items.isModel}} + {{/items.isPrimitiveType}} + {{/isArray}} + {{^isArray}} + {{#isMap}} + {{^items.isModel}} + if ({{getter}}() != null) { + for (String _key : {{getter}}().keySet()) { + joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, _key, containerSuffix), + {{getter}}().get(_key), URLEncoder.encode(String.valueOf({{getter}}().get(_key)), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + } + {{/items.isModel}} + {{#items.isModel}} + if ({{getter}}() != null) { + for (String _key : {{getter}}().keySet()) { + if ({{getter}}().get(_key) != null) { + joiner.add({{getter}}().get(_key).toUrlQueryString(String.format("%s{{baseName}}%s%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, _key, containerSuffix)))); + } + } + } + {{/items.isModel}} + {{/isMap}} + {{^isMap}} + {{#isPrimitiveType}} + if ({{getter}}() != null) { + joiner.add(String.format("%s{{{baseName}}}%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf({{{getter}}}()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + {{/isPrimitiveType}} + {{^isPrimitiveType}} + {{#isModel}} + if ({{getter}}() != null) { + joiner.add({{getter}}().toUrlQueryString(prefix + "{{{baseName}}}" + suffix)); + } + {{/isModel}} + {{^isModel}} + if ({{getter}}() != null) { + joiner.add(String.format("%s{{{baseName}}}%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf({{{getter}}}()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + {{/isModel}} + {{/isPrimitiveType}} + {{/isMap}} + {{/isArray}} + + {{/allVars}} + return joiner.toString(); + } +{{/supportUrlQuery}} +{{#parcelableModel}} + + public void writeToParcel(Parcel out, int flags) { +{{#model}} +{{#isArray}} + out.writeList(this); +{{/isArray}} +{{^isArray}} +{{#parent}} + super.writeToParcel(out, flags); +{{/parent}} +{{#vars}} + out.writeValue({{name}}); +{{/vars}} +{{/isArray}} +{{/model}} + } + + {{classname}}(Parcel in) { +{{#isArray}} + in.readTypedList(this, {{arrayModelType}}.CREATOR); +{{/isArray}} +{{^isArray}} +{{#parent}} + super(in); +{{/parent}} +{{#vars}} +{{#isPrimitiveType}} + {{name}} = ({{{datatypeWithEnum}}})in.readValue(null); +{{/isPrimitiveType}} +{{^isPrimitiveType}} + {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader()); +{{/isPrimitiveType}} +{{/vars}} +{{/isArray}} + } + + public int describeContents() { + return 0; + } + + public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() { + public {{classname}} createFromParcel(Parcel in) { +{{#model}} +{{#isArray}} + {{classname}} result = new {{classname}}(); + result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader())); + return result; +{{/isArray}} +{{^isArray}} + return new {{classname}}(in); +{{/isArray}} +{{/model}} + } + public {{classname}}[] newArray(int size) { + return new {{classname}}[size]; + } + }; +{{/parcelableModel}} +{{#discriminator}} +static { + // Initialize and register the discriminator mappings. + Map> mappings = new HashMap>(); + {{#mappedModels}} + mappings.put("{{mappingName}}", {{modelName}}.class); + {{/mappedModels}} + mappings.put("{{name}}", {{classname}}.class); + JSON.registerDiscriminator({{classname}}.class, "{{propertyBaseName}}", mappings); +} +{{/discriminator}} +} diff --git a/client2/src/main/template/libraries/native/pojo.mustache.orig b/client2/src/main/template/libraries/native/pojo.mustache.orig new file mode 100644 index 0000000000..a0c77d53c1 --- /dev/null +++ b/client2/src/main/template/libraries/native/pojo.mustache.orig @@ -0,0 +1,596 @@ +{{#discriminator}} +import {{invokerPackage}}.JSON; +{{/discriminator}} +/** + * {{description}}{{^description}}{{classname}}{{/description}}{{#isDeprecated}} + * @deprecated{{/isDeprecated}} + */{{#isDeprecated}} +@Deprecated{{/isDeprecated}} +{{#swagger1AnnotationLibrary}} +{{#description}} +@ApiModel(description = "{{{.}}}") +{{/description}} +{{/swagger1AnnotationLibrary}} +{{#swagger2AnnotationLibrary}} +{{#description}} +@Schema(description = "{{{.}}}") +{{/description}} +{{/swagger2AnnotationLibrary}} +{{#jackson}} +@JsonPropertyOrder({ +{{#vars}} + {{classname}}.JSON_PROPERTY_{{nameInSnakeCase}}{{^-last}},{{/-last}} +{{/vars}} +}) +{{/jackson}} +{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{#discriminator}}{{>typeInfoAnnotation}}{{/discriminator}}{{>xmlAnnotation}} +{{#vendorExtensions.x-class-extra-annotation}} +{{{vendorExtensions.x-class-extra-annotation}}} +{{/vendorExtensions.x-class-extra-annotation}} +public class {{classname}} {{#parent}}extends {{{.}}} {{/parent}}{{#vendorExtensions.x-implements}}{{#-first}}implements {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{#-last}} {{/-last}}{{/vendorExtensions.x-implements}}{ +{{#serializableModel}} + private static final long serialVersionUID = 1L; + +{{/serializableModel}} + {{#vars}} + {{#isEnum}} + {{^isContainer}} + {{^vendorExtensions.x-enum-as-string}} +{{>modelInnerEnum}} + {{/vendorExtensions.x-enum-as-string}} + {{/isContainer}} + {{#isContainer}} + {{#mostInnerItems}} +{{>modelInnerEnum}} + {{/mostInnerItems}} + {{/isContainer}} + {{/isEnum}} + {{#gson}} + public static final String SERIALIZED_NAME_{{nameInSnakeCase}} = "{{baseName}}"; + {{/gson}} + {{#jackson}} + public static final String JSON_PROPERTY_{{nameInSnakeCase}} = "{{baseName}}"; + {{/jackson}} + {{#withXml}} + {{#isXmlAttribute}} + @XmlAttribute(name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlAttribute}} + {{^isXmlAttribute}} + {{^isContainer}} + @XmlElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isContainer}} + {{#isContainer}} + // Is a container wrapped={{isXmlWrapped}} + {{#items}} + // items.name={{name}} items.baseName={{baseName}} items.xmlName={{xmlName}} items.xmlNamespace={{xmlNamespace}} + // items.example={{example}} items.type={{dataType}} + @XmlElement({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/items}} + {{#isXmlWrapped}} + @XmlElementWrapper({{#xmlNamespace}}namespace="{{.}}", {{/xmlNamespace}}name = "{{xmlName}}{{^xmlName}}{{baseName}}{{/xmlName}}") + {{/isXmlWrapped}} + {{/isContainer}} + {{/isXmlAttribute}} + {{/withXml}} + {{#gson}} + @SerializedName(SERIALIZED_NAME_{{nameInSnakeCase}}) + {{/gson}} + {{#vendorExtensions.x-field-extra-annotation}} + {{{vendorExtensions.x-field-extra-annotation}}} + {{/vendorExtensions.x-field-extra-annotation}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined(); + {{/isContainer}} + {{^isContainer}} + private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + {{/isContainer}} + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + + {{/vars}} + public {{classname}}() { {{#parent}}{{#parcelableModel}} + super();{{/parcelableModel}}{{/parent}}{{#gson}}{{#discriminator}} + this.{{{discriminatorName}}} = this.getClass().getSimpleName();{{/discriminator}}{{/gson}} + }{{#vendorExtensions.x-has-readonly-properties}}{{^withXml}} + + {{#jackson}}@JsonCreator{{/jackson}} + public {{classname}}( + {{#readOnlyVars}} + @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) {{{datatypeWithEnum}}} {{name}}{{^-last}}, {{/-last}} + {{/readOnlyVars}} + ) { + this(); + {{#readOnlyVars}} + this.{{name}} = {{#vendorExtensions.x-is-jackson-optional-nullable}}{{name}} == null ? JsonNullable.<{{{datatypeWithEnum}}}>undefined() : JsonNullable.of({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{name}}{{/vendorExtensions.x-is-jackson-optional-nullable}}; + {{/readOnlyVars}} + }{{/withXml}}{{/vendorExtensions.x-has-readonly-properties}} + {{#vars}} + + {{^isReadOnly}} + {{#vendorExtensions.x-enum-as-string}} + public static final Set {{{nameInSnakeCase}}}_VALUES = new HashSet<>(Arrays.asList( + {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}} + )); + + {{/vendorExtensions.x-enum-as-string}} + public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-enum-as-string}} + if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) { + throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES)); + } + + {{/vendorExtensions.x-enum-as-string}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + return this; + } + {{#isArray}} + + public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}}); + } + try { + this.{{name}}.get().add({{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}}; + } + this.{{name}}.add({{name}}Item); + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isArray}} + {{#isMap}} + + public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null || !this.{{name}}.isPresent()) { + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}}); + } + try { + this.{{name}}.get().put(key, {{name}}Item); + } catch (java.util.NoSuchElementException e) { + // this can never happen, as we make sure above that the value is present + } + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + if (this.{{name}} == null) { + this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}}; + } + this.{{name}}.put(key, {{name}}Item); + return this; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isMap}} + + {{/isReadOnly}} + /** + {{#description}} + * {{.}} + {{/description}} + {{^description}} + * Get {{name}} + {{/description}} + {{#minimum}} + * minimum: {{.}} + {{/minimum}} + {{#maximum}} + * maximum: {{.}} + {{/maximum}} + * @return {{name}} + {{#deprecated}} + * @deprecated + {{/deprecated}} + **/ +{{#deprecated}} + @Deprecated +{{/deprecated}} +{{#required}} +{{#isNullable}} + @{{javaxPackage}}.annotation.Nullable +{{/isNullable}} +{{^isNullable}} + @{{javaxPackage}}.annotation.Nonnull +{{/isNullable}} +{{/required}} +{{^required}} + @{{javaxPackage}}.annotation.Nullable +{{/required}} +{{#useBeanValidation}} +{{>beanValidation}} +{{/useBeanValidation}} +{{#swagger1AnnotationLibrary}} + @ApiModelProperty({{#example}}example = "{{{.}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") +{{/swagger1AnnotationLibrary}} +{{#swagger2AnnotationLibrary}} + @Schema({{#example}}example = "{{{.}}}", {{/example}}requiredMode = {{#required}}Schema.RequiredMode.REQUIRED{{/required}}{{^required}}Schema.RequiredMode.NOT_REQUIRED{{/required}}, description = "{{{description}}}") +{{/swagger2AnnotationLibrary}} +{{#vendorExtensions.x-extra-annotation}} + {{{vendorExtensions.x-extra-annotation}}} +{{/vendorExtensions.x-extra-annotation}} +{{#vendorExtensions.x-is-jackson-optional-nullable}} + {{!unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}} + @JsonIgnore +{{/vendorExtensions.x-is-jackson-optional-nullable}} +{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#jackson}}{{> jackson_annotations}}{{/jackson}}{{/vendorExtensions.x-is-jackson-optional-nullable}} + public {{{datatypeWithEnum}}} {{getter}}() { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + {{#isReadOnly}}{{! A readonly attribute doesn't have setter => jackson will set null directly if explicitly returned by API, so make sure we have an empty JsonNullable}} + if ({{name}} == null) { + {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}}; + } + {{/isReadOnly}} + return {{name}}.orElse(null); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + return {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + + {{#vendorExtensions.x-is-jackson-optional-nullable}} +{{> jackson_annotations}} + public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() { + return {{name}}; + } + {{/vendorExtensions.x-is-jackson-optional-nullable}}{{#vendorExtensions.x-is-jackson-optional-nullable}} + @JsonProperty(JSON_PROPERTY_{{nameInSnakeCase}}) + {{#isReadOnly}}private{{/isReadOnly}}{{^isReadOnly}}public{{/isReadOnly}} void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) { + {{! For getters/setters that have name differing from attribute name, we must include setter (albeit private) for jackson to be able to set the attribute}} + this.{{name}} = {{name}}; + } + {{/vendorExtensions.x-is-jackson-optional-nullable}} + + {{^isReadOnly}} +{{#vendorExtensions.x-setter-extra-annotation}} {{{vendorExtensions.x-setter-extra-annotation}}} +{{/vendorExtensions.x-setter-extra-annotation}}{{#jackson}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{> jackson_annotations}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{/jackson}} public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-enum-as-string}} + if (!{{{nameInSnakeCase}}}_VALUES.contains({{name}})) { + throw new IllegalArgumentException({{name}} + " is invalid. Possible values for {{name}}: " + String.join(", ", {{{nameInSnakeCase}}}_VALUES)); + } + + {{/vendorExtensions.x-enum-as-string}} + {{#vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}}); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + this.{{name}} = {{name}}; + {{/vendorExtensions.x-is-jackson-optional-nullable}} + } + {{/isReadOnly}} + + {{/vars}} +{{>libraries/native/additional_properties}} + {{#parent}} + {{#allVars}} + {{#isOverridden}} + @Override + public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { + {{#vendorExtensions.x-is-jackson-optional-nullable}} + this.{{setter}}(JsonNullable.<{{{datatypeWithEnum}}}>of({{name}})); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + {{^vendorExtensions.x-is-jackson-optional-nullable}} + this.{{setter}}({{name}}); + {{/vendorExtensions.x-is-jackson-optional-nullable}} + return this; + } + + {{/isOverridden}} + {{/allVars}} + {{/parent}} + /** + * Return true if this {{name}} object is equal to o. + */ + @Override + public boolean equals(Object o) { + {{#useReflectionEqualsHashCode}} + return EqualsBuilder.reflectionEquals(this, o, false, null, true); + {{/useReflectionEqualsHashCode}} + {{^useReflectionEqualsHashCode}} + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + }{{#hasVars}} + {{classname}} {{classVarName}} = ({{classname}}) o; + return {{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}equalsNullable(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{#isByteArray}}Arrays{{/isByteArray}}{{^isByteArray}}Objects{{/isByteArray}}.equals(this.{{name}}, {{classVarName}}.{{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}} && + {{/-last}}{{/vars}}{{#additionalPropertiesType}}&& + Objects.equals(this.additionalProperties, {{classVarName}}.additionalProperties){{/additionalPropertiesType}}{{#parent}} && + super.equals(o){{/parent}};{{/hasVars}}{{^hasVars}} + return {{#parent}}super.equals(o){{/parent}}{{^parent}}true{{/parent}};{{/hasVars}} + {{/useReflectionEqualsHashCode}} + }{{#vendorExtensions.x-jackson-optional-nullable-helpers}} + + private static boolean equalsNullable(JsonNullable a, JsonNullable b) { + return a == b || (a != null && b != null && a.isPresent() && b.isPresent() && Objects.deepEquals(a.get(), b.get())); + }{{/vendorExtensions.x-jackson-optional-nullable-helpers}} + + @Override + public int hashCode() { + {{#useReflectionEqualsHashCode}} + return HashCodeBuilder.reflectionHashCode(this); + {{/useReflectionEqualsHashCode}} + {{^useReflectionEqualsHashCode}} + return Objects.hash({{#vars}}{{#vendorExtensions.x-is-jackson-optional-nullable}}hashCodeNullable({{name}}){{/vendorExtensions.x-is-jackson-optional-nullable}}{{^vendorExtensions.x-is-jackson-optional-nullable}}{{^isByteArray}}{{name}}{{/isByteArray}}{{#isByteArray}}Arrays.hashCode({{name}}){{/isByteArray}}{{/vendorExtensions.x-is-jackson-optional-nullable}}{{^-last}}, {{/-last}}{{/vars}}{{#parent}}{{#hasVars}}, {{/hasVars}}super.hashCode(){{/parent}}{{#additionalPropertiesType}}, additionalProperties{{/additionalPropertiesType}}); + {{/useReflectionEqualsHashCode}} + }{{#vendorExtensions.x-jackson-optional-nullable-helpers}} + + private static int hashCodeNullable(JsonNullable a) { + if (a == null) { + return 1; + } + return a.isPresent() ? Arrays.deepHashCode(new Object[]{a.get()}) : 31; + }{{/vendorExtensions.x-jackson-optional-nullable-helpers}} + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class {{classname}} {\n"); + {{#parent}} + sb.append(" ").append(toIndentedString(super.toString())).append("\n"); + {{/parent}} + {{#vars}} + sb.append(" {{name}}: ").append(toIndentedString({{name}})).append("\n"); + {{/vars}} + {{#additionalPropertiesType}} + sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); + {{/additionalPropertiesType}} + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +{{#supportUrlQuery}} + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + {{#allVars}} + // add `{{baseName}}` to the URL query string + {{#isArray}} + {{#items.isPrimitiveType}} + {{#uniqueItems}} + if ({{getter}}() != null) { + int i = 0; + for ({{{items.dataType}}} _item : {{getter}}()) { + joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix), + URLEncoder.encode(String.valueOf(_item), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + i++; + } + {{/uniqueItems}} + {{^uniqueItems}} + if ({{getter}}() != null) { + for (int i = 0; i < {{getter}}().size(); i++) { + joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix), + URLEncoder.encode(String.valueOf({{getter}}().get(i)), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + } + {{/uniqueItems}} + {{/items.isPrimitiveType}} + {{^items.isPrimitiveType}} + {{#items.isModel}} + {{#uniqueItems}} + if ({{getter}}() != null) { + int i = 0; + for ({{{items.dataType}}} _item : {{getter}}()) { + if (_item != null) { + joiner.add(_item.toUrlQueryString(String.format("%s{{baseName}}%s%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix)))); + } + } + i++; + } + {{/uniqueItems}} + {{^uniqueItems}} + if ({{getter}}() != null) { + for (int i = 0; i < {{getter}}().size(); i++) { + if ({{getter}}().get(i) != null) { + joiner.add({{getter}}().get(i).toUrlQueryString(String.format("%s{{baseName}}%s%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix)))); + } + } + } + {{/uniqueItems}} + {{/items.isModel}} + {{^items.isModel}} + {{#uniqueItems}} + if ({{getter}}() != null) { + int i = 0; + for ({{{items.dataType}}} _item : {{getter}}()) { + if (_item != null) { + joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix), + URLEncoder.encode(String.valueOf(_item), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + i++; + } + } + {{/uniqueItems}} + {{^uniqueItems}} + if ({{getter}}() != null) { + for (int i = 0; i < {{getter}}().size(); i++) { + if ({{getter}}().get(i) != null) { + joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix), + URLEncoder.encode(String.valueOf({{getter}}().get(i)), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + } + } + {{/uniqueItems}} + {{/items.isModel}} + {{/items.isPrimitiveType}} + {{/isArray}} + {{^isArray}} + {{#isMap}} + {{^items.isModel}} + if ({{getter}}() != null) { + for (String _key : {{getter}}().keySet()) { + joiner.add(String.format("%s{{baseName}}%s%s=%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, _key, containerSuffix), + {{getter}}().get(_key), URLEncoder.encode(String.valueOf({{getter}}().get(_key)), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + } + {{/items.isModel}} + {{#items.isModel}} + if ({{getter}}() != null) { + for (String _key : {{getter}}().keySet()) { + if ({{getter}}().get(_key) != null) { + joiner.add({{getter}}().get(_key).toUrlQueryString(String.format("%s{{baseName}}%s%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, _key, containerSuffix)))); + } + } + } + {{/items.isModel}} + {{/isMap}} + {{^isMap}} + {{#isPrimitiveType}} + if ({{getter}}() != null) { + joiner.add(String.format("%s{{{baseName}}}%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf({{{getter}}}()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + {{/isPrimitiveType}} + {{^isPrimitiveType}} + {{#isModel}} + if ({{getter}}() != null) { + joiner.add({{getter}}().toUrlQueryString(prefix + "{{{baseName}}}" + suffix)); + } + {{/isModel}} + {{^isModel}} + if ({{getter}}() != null) { + joiner.add(String.format("%s{{{baseName}}}%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf({{{getter}}}()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + {{/isModel}} + {{/isPrimitiveType}} + {{/isMap}} + {{/isArray}} + + {{/allVars}} + return joiner.toString(); + } +{{/supportUrlQuery}} +{{#parcelableModel}} + + public void writeToParcel(Parcel out, int flags) { +{{#model}} +{{#isArray}} + out.writeList(this); +{{/isArray}} +{{^isArray}} +{{#parent}} + super.writeToParcel(out, flags); +{{/parent}} +{{#vars}} + out.writeValue({{name}}); +{{/vars}} +{{/isArray}} +{{/model}} + } + + {{classname}}(Parcel in) { +{{#isArray}} + in.readTypedList(this, {{arrayModelType}}.CREATOR); +{{/isArray}} +{{^isArray}} +{{#parent}} + super(in); +{{/parent}} +{{#vars}} +{{#isPrimitiveType}} + {{name}} = ({{{datatypeWithEnum}}})in.readValue(null); +{{/isPrimitiveType}} +{{^isPrimitiveType}} + {{name}} = ({{{datatypeWithEnum}}})in.readValue({{complexType}}.class.getClassLoader()); +{{/isPrimitiveType}} +{{/vars}} +{{/isArray}} + } + + public int describeContents() { + return 0; + } + + public static final Parcelable.Creator<{{classname}}> CREATOR = new Parcelable.Creator<{{classname}}>() { + public {{classname}} createFromParcel(Parcel in) { +{{#model}} +{{#isArray}} + {{classname}} result = new {{classname}}(); + result.addAll(in.readArrayList({{arrayModelType}}.class.getClassLoader())); + return result; +{{/isArray}} +{{^isArray}} + return new {{classname}}(in); +{{/isArray}} +{{/model}} + } + public {{classname}}[] newArray(int size) { + return new {{classname}}[size]; + } + }; +{{/parcelableModel}} +{{#discriminator}} +static { + // Initialize and register the discriminator mappings. + Map> mappings = new HashMap>(); + {{#mappedModels}} + mappings.put("{{mappingName}}", {{modelName}}.class); + {{/mappedModels}} + mappings.put("{{name}}", {{classname}}.class); + JSON.registerDiscriminator({{classname}}.class, "{{propertyBaseName}}", mappings); +} +{{/discriminator}} +} diff --git a/client2/src/test/java/com/walmartlabs/concord/client2/ApiClientJsonTest.java b/client2/src/test/java/com/walmartlabs/concord/client2/ApiClientJsonTest.java new file mode 100644 index 0000000000..56b3afe081 --- /dev/null +++ b/client2/src/test/java/com/walmartlabs/concord/client2/ApiClientJsonTest.java @@ -0,0 +1,61 @@ +package com.walmartlabs.concord.client2; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2020 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; + +import java.text.SimpleDateFormat; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.Date; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ApiClientJsonTest { + + @Test + public void testParseDate() throws Exception { + ObjectMapper om = ApiClient.createDefaultObjectMapper(); + + Date date = new Date(1587500112000L); + OffsetDateTime offsetDateTime = date.toInstant().atOffset(ZoneOffset.UTC); + + + String toParse = om.writeValueAsString(offsetDateTime); + toParse = toParse.substring(1, toParse.length() - 1); + + // format like a sever entries + Date parsed = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX"). + parse(toParse); + + assertEquals(date, parsed); + } + + @Test + public void testObjectSerialize() throws Exception { + ProjectEntry project = new ProjectEntry() + .name(""); + + String str = ApiClient.createDefaultObjectMapper().writeValueAsString(project); + assertEquals("{\"name\":\"\"}", str); + } +} diff --git a/client2/src/test/java/com/walmartlabs/concord/client2/ProcessApiTest.java b/client2/src/test/java/com/walmartlabs/concord/client2/ProcessApiTest.java new file mode 100644 index 0000000000..6fb4f5458e --- /dev/null +++ b/client2/src/test/java/com/walmartlabs/concord/client2/ProcessApiTest.java @@ -0,0 +1,55 @@ +package com.walmartlabs.concord.client2; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2023 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import com.walmartlabs.concord.client2.impl.auth.ApiKey; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import javax.xml.bind.DatatypeConverter; +import java.util.UUID; + +public class ProcessApiTest { + + @Test + @Disabled + public void testDecrypt() throws Exception { + ApiClient apiClient = new DefaultApiClientFactory("http://localhost:8001").create(); + apiClient.setAuth(new ApiKey("cTFxMXExcTE=")); + + ProjectsApi projectsApi = new ProjectsApi(apiClient); + EncryptValueResponse encrypted = projectsApi.encrypt("org_1692633472807_3d32f7", "project_1692633472833_a1a531", "123qwe"); + + String encryptedValue = encrypted.getData(); + System.out.println(">>>" + encryptedValue); + byte[] input; + + try { + input = DatatypeConverter.parseBase64Binary(encryptedValue); + } catch (Exception e) { + throw new IllegalArgumentException("Invalid encrypted string value, please verify that it was specified/copied correctly: " + e.getMessage()); + } + + ProcessApi api = new ProcessApi(apiClient); + UUID pid = UUID.fromString("f891d797-d97e-4724-b0ba-91d48efce6d8"); + System.out.println(">>>'" + new String(api.decryptString(pid, input)) + "'"); + } +} diff --git a/client2/src/test/java/com/walmartlabs/concord/client2/SecretClientTest.java b/client2/src/test/java/com/walmartlabs/concord/client2/SecretClientTest.java new file mode 100644 index 0000000000..cdfea2ebd0 --- /dev/null +++ b/client2/src/test/java/com/walmartlabs/concord/client2/SecretClientTest.java @@ -0,0 +1,68 @@ +package com.walmartlabs.concord.client2; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2020 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; +import com.walmartlabs.concord.client2.impl.auth.ApiKey; +import com.walmartlabs.concord.common.secret.BinaryDataSecret; +import com.walmartlabs.concord.sdk.Constants; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@WireMockTest +public class SecretClientTest { + + @Test + public void testInvalidSecretType(WireMockRuntimeInfo wmRuntimeInfo) throws Exception { + String orgName = "org_" + System.currentTimeMillis(); + String secretName = "secret_" + System.currentTimeMillis(); + + stubFor(post(urlEqualTo("/api/v1/org/" + orgName + "/secret/" + secretName + "/data")) + .willReturn(aResponse() + .withStatus(200) + .withHeader(Constants.Headers.SECRET_TYPE, SecretEntryV2.TypeEnum.DATA.name()) + .withBody("Hello!"))); + + ApiClient apiClient = new DefaultApiClientFactory("http://localhost:" + wmRuntimeInfo.getHttpPort()).create(); + SecretClient secretClient = new SecretClient(apiClient); + + try { + secretClient.getData(orgName, secretName, null, SecretEntryV2.TypeEnum.KEY_PAIR); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("Unexpected type of " + orgName + "/" + secretName)); + } + } + + @Test + @Disabled + public void testGetSecret() throws Exception { + ApiClient apiClient = new DefaultApiClientFactory("http://localhost:8001").create(); + apiClient.setAuth(new ApiKey("cTFxMXExcTE")); + SecretClient secretClient = new SecretClient(apiClient); + + BinaryDataSecret result = secretClient.getData("Default", "test", null, SecretEntryV2.TypeEnum.DATA); + System.out.println(">>> '" + new String(result.getData()) + "'"); + } +} diff --git a/client2/src/test/java/com/walmartlabs/concord/client2/impl/MultipartRequestBodyHandlerTest.java b/client2/src/test/java/com/walmartlabs/concord/client2/impl/MultipartRequestBodyHandlerTest.java new file mode 100644 index 0000000000..7a01c20061 --- /dev/null +++ b/client2/src/test/java/com/walmartlabs/concord/client2/impl/MultipartRequestBodyHandlerTest.java @@ -0,0 +1,101 @@ +package com.walmartlabs.concord.client2.impl; + +/*- + * ***** + * Concord + * ----- + * Copyright (C) 2017 - 2023 Walmart Inc. + * ----- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ===== + */ + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class MultipartRequestBodyHandlerTest { + + @Test + public void test2() throws Exception { + Map data = new LinkedHashMap<>(); + data.put("string-field", "this stuff"); + data.put("byte[]-field", "byte array".getBytes()); + data.put("inputstream-field", new ByteArrayInputStream("my input stream".getBytes())); + data.put("boolean-field", true); + data.put("json-field", Collections.singletonMap("k", "v")); + data.put("string[]-field", new String[] {"one", "two"}); + data.put("uuid-field", UUID.fromString("f8d30c37-4c84-4817-9cb8-23b27a54c459")); + + MultipartBuilder mpb = new MultipartBuilder("e572b648-941a-4648-97ed-0e3c5350f0ad"); + HttpEntity entity = MultipartRequestBodyHandler.handle(mpb, new ObjectMapper(), data); + + try (InputStream is = entity.getContent()) { + String str = new String(is.readAllBytes(), StandardCharsets.UTF_8); + + assertEquals(body, str); + assertEquals("multipart/form-data; boundary=e572b648-941a-4648-97ed-0e3c5350f0ad", entity.contentType().toString()); + } + } + + private static final String body = "--e572b648-941a-4648-97ed-0e3c5350f0ad\r\n" + + "Content-Disposition: form-data; name=\"string-field\"\r\n" + + "Content-Length: 10\r\n" + + "\r\n" + + "this stuff\r\n" + + "--e572b648-941a-4648-97ed-0e3c5350f0ad\r\n" + + "Content-Disposition: form-data; name=\"byte[]-field\"\r\n" + + "Content-Type: application/octet-stream\r\n" + + "Content-Length: 10\r\n" + + "\r\n" + + "byte array\r\n" + + "--e572b648-941a-4648-97ed-0e3c5350f0ad\r\n" + + "Content-Disposition: form-data; name=\"inputstream-field\"\r\n" + + "Content-Type: application/octet-stream\r\n" + + "\r\n" + + "my input stream\r\n" + + "--e572b648-941a-4648-97ed-0e3c5350f0ad\r\n" + + "Content-Disposition: form-data; name=\"boolean-field\"\r\n" + + "Content-Type: text/plain; charset=utf-8\r\n" + + "Content-Length: 4\r\n" + + "\r\n" + + "true\r\n" + + "--e572b648-941a-4648-97ed-0e3c5350f0ad\r\n" + + "Content-Disposition: form-data; name=\"json-field\"\r\n" + + "Content-Type: application/json; charset=utf-8\r\n" + + "Content-Length: 9\r\n" + + "\r\n" + + "{\"k\":\"v\"}\r\n" + + "--e572b648-941a-4648-97ed-0e3c5350f0ad\r\n" + + "Content-Disposition: form-data; name=\"string[]-field\"\r\n" + + "Content-Type: text/plain; charset=utf-8\r\n" + + "Content-Length: 7\r\n" + + "\r\n" + + "one,two\r\n" + + "--e572b648-941a-4648-97ed-0e3c5350f0ad\r\n" + + "Content-Disposition: form-data; name=\"uuid-field\"\r\n" + + "Content-Length: 36\r\n" + + "\r\n" + + "f8d30c37-4c84-4817-9cb8-23b27a54c459\r\n" + + "--e572b648-941a-4648-97ed-0e3c5350f0ad--" + + "\r\n"; +} diff --git a/common/pom.xml b/common/pom.xml index d787956fd8..d3800d275d 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -6,7 +6,7 @@ com.walmartlabs.concord parent - 2.0.1-SNAPSHOT + 2.1.1-SNAPSHOT ../pom.xml diff --git a/common/src/main/java/com/walmartlabs/concord/common/IOUtils.java b/common/src/main/java/com/walmartlabs/concord/common/IOUtils.java index 8263e084a8..d54a350b0f 100644 --- a/common/src/main/java/com/walmartlabs/concord/common/IOUtils.java +++ b/common/src/main/java/com/walmartlabs/concord/common/IOUtils.java @@ -150,6 +150,13 @@ public static void unzip(Path in, Path targetDir, boolean skipExisting, CopyOpti unzip(in, targetDir, skipExisting, null, options); } + public static void unzip(InputStream in, Path targetDir, boolean skipExisting, FileVisitor visitor, CopyOption... options) throws IOException { + try (TemporaryPath tmpZip = new TemporaryPath(IOUtils.createTempFile("unzip", "zip"))) { + Files.copy(in, tmpZip.path(), StandardCopyOption.REPLACE_EXISTING); + IOUtils.unzip(tmpZip.path(), targetDir, skipExisting, visitor, options); + } + } + public static void unzip(Path in, Path targetDir, boolean skipExisting, FileVisitor visitor, CopyOption... options) throws IOException { targetDir = targetDir.normalize().toAbsolutePath(); diff --git a/console2/pom.xml b/console2/pom.xml index 6b29604e50..3df2f8be18 100644 --- a/console2/pom.xml +++ b/console2/pom.xml @@ -5,7 +5,7 @@ com.walmartlabs.concord parent - 2.0.1-SNAPSHOT + 2.1.1-SNAPSHOT ../pom.xml diff --git a/console2/src/components/molecules/ProcessStatusTable/index.tsx b/console2/src/components/molecules/ProcessStatusTable/index.tsx index 7243498a4d..050523866e 100644 --- a/console2/src/components/molecules/ProcessStatusTable/index.tsx +++ b/console2/src/components/molecules/ProcessStatusTable/index.tsx @@ -48,13 +48,13 @@ const kindToDescription = (k: ProcessKind): string => { class ProcessStatusTable extends React.PureComponent { static renderCommitId(process?: ProcessEntry) { - if (!process || !process.commitId) { + if (!process || !process.commitId || !process.repoUrl) { return ' - '; } return ( @@ -217,7 +217,7 @@ class ProcessStatusTable extends React.PureComponent { } static renderRepoPath(process?: ProcessEntry) { - if (!process || !process.commitId) { + if (!process || !process.commitId || !process.repoUrl) { return '-'; } diff --git a/console2/src/components/organisms/NewSecretActivity/index.tsx b/console2/src/components/organisms/NewSecretActivity/index.tsx index 47103ec711..9b5a487907 100644 --- a/console2/src/components/organisms/NewSecretActivity/index.tsx +++ b/console2/src/components/organisms/NewSecretActivity/index.tsx @@ -18,88 +18,69 @@ * ===== */ -import * as copyToClipboard from 'copy-to-clipboard'; +import copyToClipboard from 'copy-to-clipboard'; import * as React from 'react'; -import { connect } from 'react-redux'; -import { AnyAction, Dispatch } from 'redux'; -import { push as pushHistory } from 'connected-react-router'; -import { Button, Message, Modal, TextArea } from 'semantic-ui-react'; +import {Button, Message, TextArea} from 'semantic-ui-react'; -import { ConcordKey, RequestError } from '../../../api/common'; +import {ConcordKey} from '../../../api/common'; import { - NewSecretEntry, SecretStoreType, SecretTypeExt, SecretVisibility } from '../../../api/org/secret'; -import { validatePassword } from '../../../api/service/console'; -import { actions, State } from '../../../state/data/secrets'; -import { CreateSecretResponse } from '../../../state/data/secrets'; -import { passwordTooWeakError } from '../../../validation'; -import { NewSecretForm, NewSecretFormValues, RequestErrorMessage } from '../../molecules'; +import {CreateSecretResponse} from '../../../state/data/secrets'; +import { + NewSecretFormValues +} from '../../molecules'; import './styles.css'; -import { RequestErrorActivity } from '../index'; - -interface OwnState { - showPasswordConfirm: boolean; - currentEntry?: NewSecretEntry; -} +import {RequestErrorActivity} from '../index'; +import NewSecretForm from '../../molecules/NewSecretForm'; +import {LoadingDispatch} from "../../../App"; +import {useCallback, useState} from "react"; +import {create as apiCreate} from "../../../api/org/secret"; +import {useApi} from "../../../hooks/useApi"; +import {useHistory} from "react-router"; interface ExternalProps { orgName: ConcordKey; } -interface StateProps { - submitting: boolean; - error: RequestError; - response?: CreateSecretResponse; +const INIT_VALUES: NewSecretFormValues = { + name: '', + visibility: SecretVisibility.PRIVATE, + type: SecretTypeExt.NEW_KEY_PAIR, + storeType: SecretStoreType.CONCORD } -interface DispatchProps { - submit: (values: NewSecretFormValues) => void; - reset: () => void; - done: (secretName: ConcordKey) => void; -} +const NewSecretActivity = (props: ExternalProps) => { + const history = useHistory(); -type Props = ExternalProps & StateProps & DispatchProps; + const {orgName} = props; -class NewSecretActivity extends React.Component { - constructor(props: Props) { - super(props); - this.state = { showPasswordConfirm: false }; - } - - componentDidMount() { - this.props.reset(); - } - - async handleSubmit(entry: NewSecretEntry, confirm?: boolean) { - if (confirm) { - this.setState({ showPasswordConfirm: false }); - } else if (entry.type === SecretTypeExt.USERNAME_PASSWORD && entry.password) { - const valid = await validatePassword(entry.password); - if (!valid) { - this.setState({ showPasswordConfirm: true, currentEntry: entry }); - return; - } - } - - this.props.submit(entry); - } + const dispatch = React.useContext(LoadingDispatch); + const [values, setValues] = useState(INIT_VALUES); - renderResponse() { - const { response, done, error } = this.props; + const postQuery = useCallback(() => { + return apiCreate(orgName, values); + }, [orgName, values]); - if (!response) { - return; - } + const {error, isLoading, data, fetch} = useApi(postQuery, { + fetchOnMount: false, + requestByFetch: true, + dispatch: dispatch + }); - if (error) { - return ; - } + const handleSubmit = useCallback( + (values: NewSecretFormValues) => { + setValues(values); + fetch(); + }, + [fetch] + ); - const { name: secretName, publicKey, password } = response; + if (data) { + const {publicKey, password} = data; return ( <> @@ -115,7 +96,7 @@ class NewSecretActivity extends React.Component { basic={true} onClick={() => (copyToClipboard as any)(publicKey)} /> -