diff --git a/NOTICE b/NOTICE index 0f7c883ca601465627f6fc1273df9f74edcf7698..64f1eca4a10bf5a4f5f406bd74c1d7783882f14e 100644 --- a/NOTICE +++ b/NOTICE @@ -98,7 +98,7 @@ The following software have components provided under the terms of this license: - GSON extensions to the Google HTTP Client Library for Java. (from https://repo1.maven.org/maven2/com/google/http-client/google-http-client-gson) - Google APIs Client Library for Java (from https://repo1.maven.org/maven2/com/google/api-client/google-api-client) - Google App Engine extensions to the Google HTTP Client Library for Java. (from https://repo1.maven.org/maven2/com/google/http-client/google-http-client-appengine) -- Google Cloud Core (from https://github.com/googleapis/google-cloud-java, https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-core, https://github.com/googleapis/java-core) +- Google Cloud Core (from https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-core, https://github.com/googleapis/java-core, https://repo1.maven.org/maven2/com/google/cloud/google-cloud-core) - Google Cloud Core HTTP (from https://github.com/GoogleCloudPlatform/google-cloud-java/tree/master/google-cloud-core-http, https://github.com/googleapis/google-cloud-java, https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-core-http, https://github.com/googleapis/java-core) - Google Cloud Core gRPC (from https://github.com/googleapis/google-cloud-java, https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-core-grpc, https://github.com/googleapis/java-core) - Google Cloud Datastore (from https://github.com/googleapis/google-cloud-java/tree/master/google-cloud-clients/google-cloud-datastore, https://github.com/googleapis/java-datastore) diff --git a/README.md b/README.md index 238cfcf1b9ffbf0a2fcc6811bccc39b4733feb08..2dc88bb4da3c6b65a8087c6180cb8ecbc96ea0ee 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,13 @@ Instructions for running the Google Cloud implementation locally can be found [h ## Running integration tests See Integration-Testing [Readme](./testing/README.md). +## Open API 3.0 - Swagger +- Swagger UI : https://host/context-path/swagger (will redirect to https://host/context-path/swagger-ui/index.html) +- api-docs (JSON) : https://host/context-path/api-docs +- api-docs (YAML) : https://host/context-path/api-docs.yaml + +All the Swagger and OpenAPI related common properties are managed here [swagger.properties](./entitlements-v2-core/src/main/resources/swagger.properties) + # Updated github url test2 ## AWS diff --git a/devops/aws/chart/values.yaml b/devops/aws/chart/values.yaml index addca7e69376b5ed043b7335269234d3efcc883a..85f8d7b78476e40dd997044f2b8164f1b11fa3dc 100644 --- a/devops/aws/chart/values.yaml +++ b/devops/aws/chart/values.yaml @@ -36,6 +36,8 @@ environmentVariables: value: "xxx" - name: SUBSCRIBER_SECRET value: "02030405060708090A0B0C0D0E0F" + - name: TMP_VOLUME_PATH + value: "/tmp" # Resource Config replicaCount: 1 @@ -70,7 +72,7 @@ cors: securityContext: runAsUser: 10001 runAsNonRoot: true - readOnlyRootFilesystem: false + readOnlyRootFilesystem: true allowPrivilegeEscalation: false capabilities: drop: diff --git a/pom.xml b/pom.xml index 4cdd6014b8d2b027d97116752906e98609975664..2268e1c9a67e76e5ebe098918aec84a72b9b8015 100644 --- a/pom.xml +++ b/pom.xml @@ -30,7 +30,7 @@ <maven.compiler.source>1.8</maven.compiler.source> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!-- <springfox.version>3.0.0</springfox.version> --> - <openapi.version>1.6.9</openapi.version> + <openapi.version>1.6.14</openapi.version> <osdu.oscorecommon.version>0.19.0</osdu.oscorecommon.version> <log4j2.version>2.17.1</log4j2.version> <gson.version>2.8.9</gson.version> diff --git a/provider/register-aws/build-aws/Dockerfile b/provider/register-aws/build-aws/Dockerfile index d597087c62f80d6959c1f06cc7f8c0126fb625ee..cce6b0eed8ddcb8aa264150fd6d38b0f385104db 100644 --- a/provider/register-aws/build-aws/Dockerfile +++ b/provider/register-aws/build-aws/Dockerfile @@ -19,12 +19,10 @@ ARG JAR_FILE=provider/register-aws/target/*spring-boot.jar # Harcoding this value since Register-core requires this variable. AWS does not use it. Might change in future ENV ENVIRONMENT=DEV -#Default to using self signed generated TLS cert -ENV USE_SELF_SIGNED_SSL_CERT true + WORKDIR / COPY ${JAR_FILE} app.jar -COPY /provider/register-aws/build-aws/ssl.sh /ssl.sh COPY /provider/register-aws/build-aws/entrypoint.sh /entrypoint.sh EXPOSE 8080 diff --git a/provider/register-aws/build-aws/entrypoint.sh b/provider/register-aws/build-aws/entrypoint.sh index 6de22440c56314856be70353f783c911206372c3..d719372c1f072ab26d5e81c3d7518c7bd251e2e6 100755 --- a/provider/register-aws/build-aws/entrypoint.sh +++ b/provider/register-aws/build-aws/entrypoint.sh @@ -1,15 +1,4 @@ -if [ -n $USE_SELF_SIGNED_SSL_CERT ]; -then - export SSL_KEY_PASSWORD=$RANDOM$RANDOM$RANDOM; - export SSL_KEY_STORE_PASSWORD=$SSL_KEY_PASSWORD; - export SSL_KEY_STORE_DIR=/tmp/certs; - export SSL_KEY_STORE_NAME=osduonaws.p12; - export SSL_KEY_STORE_PATH=$SSL_KEY_STORE_DIR/$SSL_KEY_STORE_NAME; - export SSL_KEY_ALIAS=osduonaws; - - ./ssl.sh; -fi java $JAVA_OPTS -jar /app.jar diff --git a/provider/register-aws/build-aws/ssl.sh b/provider/register-aws/build-aws/ssl.sh deleted file mode 100755 index 9ede565684bdd46cb09e56fce721ced55206ca07..0000000000000000000000000000000000000000 --- a/provider/register-aws/build-aws/ssl.sh +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright © 2021 Amazon Web Services -# -# 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. - -#!/usr/bin/env bash - -#Future: Support for using Amazon Cert Manager -# if [ "$1" == "webserver" ] && [ -n $ACM_CERTIFICATE_ARN ]; -# then - -# aws acm export-certificate --certificate-arn $ACM_CERTIFICATE_ARN --passphrase $(echo -n 'aws123' | openssl base64 -e) | jq -r '"\(.PrivateKey)"' > ${SSL_KEY_PATH}.enc -# openssl rsa -in ${SSL_KEY_PATH}.enc -out $SSL_KEY_PATH -passin pass:aws123 -# aws acm get-certificate --certificate-arn $ACM_CERTIFICATE_ARN | jq -r '"\(.CertificateChain)"' > $SSL_CERT_PATH -# aws acm get-certificate --certificate-arn $ACM_CERTIFICATE_ARN | jq -r '"\(.Certificate)"' >> $SSL_CERT_PATH - -# fi - -if [ -n $USE_SELF_SIGNED_SSL_CERT ]; -then - mkdir -p $SSL_KEY_STORE_DIR - pushd $SSL_KEY_STORE_DIR - keytool -genkeypair -alias $SSL_KEY_ALIAS -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore $SSL_KEY_STORE_NAME -validity 3650 -keypass $SSL_KEY_PASSWORD -storepass $SSL_KEY_PASSWORD -dname "CN=localhost, OU=AWS, O=Energy, L=Houston, ST=TX, C=US" - popd -fi diff --git a/provider/register-aws/src/main/java/org/opengroup/osdu/register/provider/aws/RegisterApplication.java b/provider/register-aws/src/main/java/org/opengroup/osdu/register/provider/aws/RegisterApplication.java index 4997a8656ba28c71cb9ab5e0ef08fece86c8b5d3..0ab125bd5d49cba0f28d30ffe40e7b7e2d53e1e2 100644 --- a/provider/register-aws/src/main/java/org/opengroup/osdu/register/provider/aws/RegisterApplication.java +++ b/provider/register-aws/src/main/java/org/opengroup/osdu/register/provider/aws/RegisterApplication.java @@ -16,6 +16,7 @@ package org.opengroup.osdu.register.provider.aws; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.PropertySource; @ComponentScan(value = { @@ -24,6 +25,7 @@ import org.springframework.context.annotation.ComponentScan; "org.opengroup.osdu.aws" }) @SpringBootApplication +@PropertySource("classpath:swagger.properties") public class RegisterApplication { public static void main(String[] args) { SpringApplication.run(RegisterApplication.class, args); diff --git a/provider/register-aws/src/main/java/org/opengroup/osdu/register/provider/aws/pushApi/AwsSubscriberTestListenerApi.java b/provider/register-aws/src/main/java/org/opengroup/osdu/register/provider/aws/pushApi/AwsSubscriberTestListenerApi.java index 0620cc9f9cfe003b5a843037417509240d776a30..068eb40d006eca508b91c84cc2b72b8bc9abb906 100644 --- a/provider/register-aws/src/main/java/org/opengroup/osdu/register/provider/aws/pushApi/AwsSubscriberTestListenerApi.java +++ b/provider/register-aws/src/main/java/org/opengroup/osdu/register/provider/aws/pushApi/AwsSubscriberTestListenerApi.java @@ -18,6 +18,7 @@ import com.amazonaws.services.sns.AmazonSNS; import com.amazonaws.services.sns.model.ConfirmSubscriptionRequest; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.hash.Hashing; +import io.swagger.v3.oas.annotations.Hidden; import org.opengroup.osdu.core.aws.sns.AmazonSNSConfig; import org.opengroup.osdu.core.common.cryptographic.ISignatureService; import org.opengroup.osdu.core.common.cryptographic.SignatureServiceException; @@ -46,6 +47,7 @@ import java.util.Map; import java.util.Scanner; //used by integration test to validate challenge response logic and confirm subscription +@Hidden @RestController @RequestMapping("/awstest") @RequestScope diff --git a/provider/register-azure/README.md b/provider/register-azure/README.md index c274b37b6038964e833cd450e78c67a35be55a05..9649defea271aed902b67b0b3fc9e261ae4cb72e 100644 --- a/provider/register-azure/README.md +++ b/provider/register-azure/README.md @@ -109,7 +109,14 @@ $ cd provider/register-azure/ && java -jar target\register-azure-1.0.0-spring-bo Jet Brains - the authors of Intellij IDEA, have written an [excellent guide](https://www.jetbrains.com/help/idea/debugging-your-first-java-application.html) on how to debug java programs. ### Test the application -After the service has started it should be accessible via a web browser by visiting [http://localhost:8080/api/register/v1/swagger-ui.html](http://localhost:8080/api/register/v1/swagger-ui.html). If the request does not fail, you can then run the integration tests. +After the service has started it should be accessible via a web browser by visiting [http://localhost:8080/api/register/v1/swagger](http://localhost:8080/api/register/v1/swagger). If the request does not fail, you can then run the integration tests. + +## Open API 3.0 - Swagger +- Swagger UI: http://localhost:8080/api/register/v1/swagger (will redirect to http://localhost:8080/api/register/v1/swagger-ui/index.html) +- api-docs (JSON) : http://localhost:8080/api/register/v1/api-docs +- api-docs (YAML) : http://localhost:8080/api/register/v1/api-docs.yaml + +All the Swagger and OpenAPI related common properties are managed here [swagger.properties](../../register-core/src/main/resources/swagger.properties) ### Commands to run tests * Integration tests are refactored into two pieces: Core and Provider. Core contains business logic for tests and is a dependency for executing the tests from provider module. To build the core module, simply navigate to `register-test-core` directory and run `mvn clean install`. This will build the core module @@ -128,4 +135,4 @@ 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. \ No newline at end of file +limitations under the License. diff --git a/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/RegisterApplication.java b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/RegisterApplication.java index a81eb4079915a3117fa37f3869b306344c33ce07..228fa244c554da9e05c27adb00b4eba9161b78c8 100644 --- a/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/RegisterApplication.java +++ b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/RegisterApplication.java @@ -20,6 +20,7 @@ import org.opengroup.osdu.register.provider.azure.di.CosmosContainerConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.PropertySource; @ComponentScan(value = { "org.opengroup.osdu.register", @@ -28,6 +29,7 @@ import org.springframework.context.annotation.ComponentScan; }) @SpringBootApplication +@PropertySource("classpath:swagger.properties") public class RegisterApplication { public static void main(String[] args) { diff --git a/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/security/WhoamiController.java b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/security/WhoamiController.java index db37944c350d5646085e318ddd2da9554aa3501b..40a05ad44b69bcc535f27ca547d9007d78f982f3 100644 --- a/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/security/WhoamiController.java +++ b/provider/register-azure/src/main/java/org/opengroup/osdu/register/provider/azure/security/WhoamiController.java @@ -14,12 +14,14 @@ package org.opengroup.osdu.register.provider.azure.security; +import io.swagger.v3.oas.annotations.Hidden; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; +@Hidden @Controller public class WhoamiController { @RequestMapping(value = "/whoami") diff --git a/provider/register-gc/src/main/java/org/opengroup/osdu/register/provider/gcp/RegisterApplication.java b/provider/register-gc/src/main/java/org/opengroup/osdu/register/provider/gcp/RegisterApplication.java index ce1e28bb5f5ba055ff40b8f760a9c35df1e97d1e..841bf78aaa4ca0e9a37ae809ef7bc7bc785b0d4a 100644 --- a/provider/register-gc/src/main/java/org/opengroup/osdu/register/provider/gcp/RegisterApplication.java +++ b/provider/register-gc/src/main/java/org/opengroup/osdu/register/provider/gcp/RegisterApplication.java @@ -21,9 +21,11 @@ import javax.annotation.PostConstruct; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.PropertySource; @ComponentScan(value = {"org.opengroup.osdu"}) @SpringBootApplication +@PropertySource("classpath:swagger.properties") public class RegisterApplication { @PostConstruct diff --git a/provider/register-ibm/src/main/java/org/opengroup/osdu/register/provider/ibm/RegisterApplication.java b/provider/register-ibm/src/main/java/org/opengroup/osdu/register/provider/ibm/RegisterApplication.java index c56c6bd17500f4b0e612c46dcad4df0688521fc5..12e1de8faa671c3412fe0a3dcfc0aa06a45ec920 100644 --- a/provider/register-ibm/src/main/java/org/opengroup/osdu/register/provider/ibm/RegisterApplication.java +++ b/provider/register-ibm/src/main/java/org/opengroup/osdu/register/provider/ibm/RegisterApplication.java @@ -9,6 +9,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration; import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.PropertySource; import javax.annotation.PostConstruct; @@ -17,6 +18,7 @@ import javax.annotation.PostConstruct; MongoDataAutoConfiguration.class }) @ComponentScan({"org.opengroup.osdu"}) +@PropertySource("classpath:swagger.properties") public class RegisterApplication { @PostConstruct void f() { diff --git a/register-core/src/main/java/org/opengroup/osdu/register/action/model/Action.java b/register-core/src/main/java/org/opengroup/osdu/register/action/model/Action.java index e7c1bf3073b2a494e555d874b57a70f82df8c3ab..4f8a0b211e4f7388bc398faccc30c24edf85b984 100644 --- a/register-core/src/main/java/org/opengroup/osdu/register/action/model/Action.java +++ b/register-core/src/main/java/org/opengroup/osdu/register/action/model/Action.java @@ -19,11 +19,13 @@ package org.opengroup.osdu.register.action.model; import java.sql.Timestamp; import java.time.Instant; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor +@Schema(description = "Represents a model for Action") public class Action { public Action(CreateActionDto dto){ this.id = dto.getId(); @@ -35,12 +37,23 @@ public class Action { this.filter = dto.getFilter(); } + @Schema(example = "petrel-launch-project") private String id; + + @Schema(example = "Petrel Project") private String name; + @Schema(example = "This action launches the Petrel projects landing page that holds the selected data.") private String description; + + @Schema(example = "https://mycdn.com/img.png") private String img; + + @Schema(example = "https://myapp.osdu.com/action/{type}/{id}") private String url; + + @Schema(example = "abc@test.com") private String contactEmail; + private Timestamp createdOnEpoch = Timestamp.from(Instant.now()); private Filter filter = new Filter(); } diff --git a/register-core/src/main/java/org/opengroup/osdu/register/action/model/CreateActionDto.java b/register-core/src/main/java/org/opengroup/osdu/register/action/model/CreateActionDto.java index d4ac616e96c68cabba078c2919c0fb01cf86bdaa..3be10529c9809781dacf5a4aa453e17557a173bf 100644 --- a/register-core/src/main/java/org/opengroup/osdu/register/action/model/CreateActionDto.java +++ b/register-core/src/main/java/org/opengroup/osdu/register/action/model/CreateActionDto.java @@ -16,6 +16,7 @@ package org.opengroup.osdu.register.action.model; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -31,21 +32,34 @@ import javax.validation.constraints.Pattern; @Builder @NoArgsConstructor @AllArgsConstructor +@Schema(description = "Represents a model to create Action") public class CreateActionDto { + @Schema(example = "petrel-launch-project") @Pattern(regexp = "^[A-Za-z0-9-]{2,50}") private String id; + + @Schema(example = "Petrel Project") @NotEmpty @Pattern(regexp = "^[A-Za-z0-9- ]{2,50}") private String name; + + @Schema(example = "This action launches the Petrel projects landing page that holds the selected data.") @Pattern(regexp = "^[A-Za-z0-9. ]{0,255}") private String description; + + @Schema(example = "https://mycdn.com/img.png") @URL(protocol = "https") private String img; + + @Schema(example = "https://myapp.osdu.com/action/{type}/{id}") @URL(protocol = "https") private String url; + + @Schema(example = "abc@test.com") @Email private String contactEmail; + @Valid @Builder.Default private Filter filter = new Filter(); diff --git a/register-core/src/main/java/org/opengroup/osdu/register/action/model/Filter.java b/register-core/src/main/java/org/opengroup/osdu/register/action/model/Filter.java index 5354040d0eade9de6133b8248785d8b950ab5128..25b73ed0e3fac58f178903acd83474de8d889bcb 100644 --- a/register-core/src/main/java/org/opengroup/osdu/register/action/model/Filter.java +++ b/register-core/src/main/java/org/opengroup/osdu/register/action/model/Filter.java @@ -16,6 +16,8 @@ package org.opengroup.osdu.register.action.model; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Schema; import org.opengroup.osdu.register.action.model.validators.ValidFilter; import lombok.AllArgsConstructor; import lombok.Builder; @@ -30,8 +32,18 @@ import java.util.List; @NoArgsConstructor @AllArgsConstructor @ValidFilter +@Schema(description = "Represents a model for Filter") public class Filter { - @Builder.Default private List<String> entityType = new ArrayList<>(); - @Builder.Default private List<String> source = new ArrayList<>(); - @Builder.Default private List<String> version = new ArrayList<>(); + + @ArraySchema(arraySchema = @Schema(implementation = String.class, example = "[\"regularheightfield\"]")) + @Builder.Default + private List<String> entityType = new ArrayList<>(); + + @ArraySchema(arraySchema = @Schema(implementation = String.class, example = "[\"petrel\"]")) + @Builder.Default + private List<String> source = new ArrayList<>(); + + @ArraySchema(arraySchema = @Schema(implementation = String.class, example = "[\"*\"]")) + @Builder.Default + private List<String> version = new ArrayList<>(); } diff --git a/register-core/src/main/java/org/opengroup/osdu/register/action/model/ParsedAction.java b/register-core/src/main/java/org/opengroup/osdu/register/action/model/ParsedAction.java index 634e5f166e6da59230dab2a06e9fb2c3ed53766b..4a67753e857b94f86683c3b5de7e5813b935b92a 100644 --- a/register-core/src/main/java/org/opengroup/osdu/register/action/model/ParsedAction.java +++ b/register-core/src/main/java/org/opengroup/osdu/register/action/model/ParsedAction.java @@ -17,6 +17,7 @@ package org.opengroup.osdu.register.action.model; import com.google.common.base.Strings; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -26,8 +27,12 @@ import lombok.NoArgsConstructor; @Builder @NoArgsConstructor @AllArgsConstructor +@Schema(description = "Represents a model for ParsedAction") public class ParsedAction { + + @Schema(example = "https://myapp.osdu.com/action/abc123") private String url; + @Schema(example = "") @Builder.Default private String errors = ""; diff --git a/register-core/src/main/java/org/opengroup/osdu/register/action/model/TestActionRequest.java b/register-core/src/main/java/org/opengroup/osdu/register/action/model/TestActionRequest.java index a17092750e06788a346644b1188699f7d8b3a60a..dd5d926854eaba156634efbc46d73c9393aa4333 100644 --- a/register-core/src/main/java/org/opengroup/osdu/register/action/model/TestActionRequest.java +++ b/register-core/src/main/java/org/opengroup/osdu/register/action/model/TestActionRequest.java @@ -17,6 +17,7 @@ package org.opengroup.osdu.register.action.model; import com.fasterxml.jackson.databind.JsonNode; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -29,9 +30,18 @@ import javax.validation.constraints.NotNull; @Builder @NoArgsConstructor @AllArgsConstructor +@Schema(description = "Represents a model for TestActionRequest") public class TestActionRequest { @Valid private CreateActionDto action; + + @Schema(description = "testPayload", example = "{\n" + + " \"id\": \"common:regularheightfield:123456\",\n" + + " \"kind\": \"common:petrel:regularheightfield:1.0.0\",\n" + + " \"data\": {\n" + + " \"uri\": \"https://myproj.com/abc123\"\n" + + " }\n" + + " }") @NotNull private JsonNode testPayload; } diff --git a/register-core/src/main/java/org/opengroup/osdu/register/api/ActionApi.java b/register-core/src/main/java/org/opengroup/osdu/register/api/ActionApi.java index 99f10f53872f7930fb4dd2ea705e1024ae268bbf..b407aab21ed0d8cd8720316c79c9d7850050fc7c 100644 --- a/register-core/src/main/java/org/opengroup/osdu/register/api/ActionApi.java +++ b/register-core/src/main/java/org/opengroup/osdu/register/api/ActionApi.java @@ -17,29 +17,46 @@ package org.opengroup.osdu.register.api; import com.fasterxml.jackson.databind.JsonNode; -import java.util.Collections; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.opengroup.osdu.core.common.logging.JaxRsDpsLog; +import org.opengroup.osdu.core.common.model.http.AppError; +import org.opengroup.osdu.core.common.model.http.AppException; import org.opengroup.osdu.register.action.model.Action; import org.opengroup.osdu.register.action.model.CreateActionDto; import org.opengroup.osdu.register.action.model.ParsedAction; import org.opengroup.osdu.register.action.model.TestActionRequest; -import org.opengroup.osdu.register.provider.interfaces.action.IActionRepo; -import org.opengroup.osdu.register.provider.interfaces.action.IRetrieveActionService; import org.opengroup.osdu.register.action.services.TestActionService; -import org.opengroup.osdu.core.common.logging.JaxRsDpsLog; -import org.opengroup.osdu.core.common.model.http.AppException; import org.opengroup.osdu.register.logging.AuditLogger; +import org.opengroup.osdu.register.provider.interfaces.action.IActionRepo; +import org.opengroup.osdu.register.provider.interfaces.action.IRetrieveActionService; import org.opengroup.osdu.register.utils.ServiceRole; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.annotation.RequestScope; import javax.validation.Valid; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Pattern; +import java.util.Collections; import java.util.List; import static org.apache.http.HttpStatus.SC_NOT_FOUND; @@ -48,6 +65,7 @@ import static org.apache.http.HttpStatus.SC_NOT_FOUND; @RequestScope @RequestMapping("/") @Validated +@Tag(name = "action-api", description = "Action API") public class ActionApi { @Autowired @@ -61,6 +79,19 @@ public class ActionApi { @Autowired private IRetrieveActionService retrieveActionService; + @Operation(summary = "${actionApi.createAction.summary}", description = "${actionApi.createAction.description}", + security = {@SecurityRequirement(name = "Authorization")}, tags = { "action-api" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "201", description = "Created", content = { @Content(schema = @Schema(implementation = Action.class)) }), + @ApiResponse(responseCode = "400", description = "Bad Request", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "403", description = "User not authorized to perform the action.", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "404", description = "Not Found", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "409", description = "Conflict", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "500", description = "Internal Server Error", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "502", description = "Bad Gateway", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "503", description = "Service Unavailable", content = {@Content(schema = @Schema(implementation = AppError.class ))}) + }) @PostMapping("action") @PreAuthorize("@authorizationFilter.hasAnyPermission('" + ServiceRole.OPS + "', '" + ServiceRole.ADMIN + "')") public ResponseEntity<Action> createAction(@RequestBody @Valid CreateActionDto createActionDto) { @@ -70,6 +101,20 @@ public class ActionApi { return new ResponseEntity<>(output, HttpStatus.CREATED); } + @Operation(summary = "${actionApi.retrieveAction.summary}", description = "${actionApi.retrieveAction.description}", + security = {@SecurityRequirement(name = "Authorization")}, tags = { "action-api" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = { @Content(array = @ArraySchema(schema = @Schema(implementation = Action.class)))}), + @ApiResponse(responseCode = "400", description = "Bad Request", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "403", description = "User not authorized to perform the action.", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "404", description = "Not Found", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "409", description = "Conflict", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "429", description = "Too Many Requests", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "500", description = "Internal Server Error", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "502", description = "Bad Gateway", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "503", description = "Service Unavailable", content = {@Content(schema = @Schema(implementation = AppError.class ))}) + }) @PostMapping("action:retrieve") @PreAuthorize("@authorizationFilter.hasAnyPermission('" + ServiceRole.OPS + "', '" + ServiceRole.ADMIN + "', '" + ServiceRole.EDITOR + "', '" + ServiceRole.VIEWER + "')") public ResponseEntity<List<Action>> retrieveAction(@RequestBody JsonNode jsonObject) { @@ -84,9 +129,24 @@ public class ActionApi { } } + @Operation(summary = "${actionApi.deleteAction.summary}", description = "${actionApi.deleteAction.description}", + security = {@SecurityRequirement(name = "Authorization")}, tags = { "action-api" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "204", description = "No Content"), + @ApiResponse(responseCode = "400", description = "Bad Request", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "403", description = "User not authorized to perform the action.", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "404", description = "Not Found", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "429", description = "Too Many Requests", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "500", description = "Internal Server Error", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "502", description = "Bad Gateway", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "503", description = "Service Unavailable", content = {@Content(schema = @Schema(implementation = AppError.class ))}) + }) @DeleteMapping("action/{id}") @PreAuthorize("@authorizationFilter.hasAnyPermission('" + ServiceRole.OPS + "', '" + ServiceRole.ADMIN + "')") - public ResponseEntity deleteAction(@PathVariable("id") @NotBlank @Pattern(regexp = "^[A-Za-z0-9-]{2,50}") String id) { + public ResponseEntity deleteAction(@Parameter(description = "Action Registration Id", example = "petrel-launch-project", + in = ParameterIn.PATH, schema = @Schema(implementation = String.class, pattern = "^[A-Za-z0-9-]{2,50}")) + @PathVariable("id") @NotBlank @Pattern(regexp = "^[A-Za-z0-9-]{2,50}") String id) { if (repo.delete(id)) { this.auditLogger.deleteActionSuccess(Collections.singletonList(id)); return new ResponseEntity(HttpStatus.NO_CONTENT); @@ -95,14 +155,44 @@ public class ActionApi { } } + @Operation(summary = "${actionApi.getAction.summary}", description = "${actionApi.getAction.description}", + security = {@SecurityRequirement(name = "Authorization")}, tags = { "action-api" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = {@Content(schema = @Schema(implementation = Action.class ))}), + @ApiResponse(responseCode = "400", description = "Bad Request", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "403", description = "User not authorized to perform the action.", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "404", description = "Not Found", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "409", description = "Conflict", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "429", description = "Too Many Requests", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "500", description = "Internal Server Error", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "502", description = "Bad Gateway", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "503", description = "Service Unavailable", content = {@Content(schema = @Schema(implementation = AppError.class ))}) + }) @GetMapping("action/{id}") @PreAuthorize("@authorizationFilter.hasAnyPermission('" + ServiceRole.OPS + "', '" + ServiceRole.ADMIN + "', '" + ServiceRole.EDITOR + "', '" + ServiceRole.VIEWER + "')") - public ResponseEntity<Action> getAction(@PathVariable("id") @NotBlank @Pattern(regexp = "^[A-Za-z0-9-]{2,50}") String id) { + public ResponseEntity<Action> getAction(@Parameter(description = "Action Registration Id", example = "petrel-launch-project", + in = ParameterIn.PATH, schema = @Schema(implementation = String.class, pattern = "^[A-Za-z0-9-]{2,50}")) + @PathVariable("id") @NotBlank @Pattern(regexp = "^[A-Za-z0-9-]{2,50}") String id) { Action action = this.repo.get(id); this.auditLogger.readActionSuccess(Collections.singletonList(action.toString())); return new ResponseEntity<>(action, HttpStatus.OK); } + @Operation(summary = "${actionApi.testAction.summary}", description = "${actionApi.testAction.description}", + security = {@SecurityRequirement(name = "Authorization")}, tags = { "action-api" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = {@Content(schema = @Schema(implementation = ParsedAction.class ))}), + @ApiResponse(responseCode = "400", description = "Bad Request", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "403", description = "User not authorized to perform the action.", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "404", description = "Not Found", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "409", description = "Conflict", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "429", description = "Too Many Requests", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "500", description = "Internal Server Error", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "502", description = "Bad Gateway", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "503", description = "Service Unavailable", content = {@Content(schema = @Schema(implementation = AppError.class ))}) + }) @PostMapping("action:test") @PreAuthorize("@authorizationFilter.hasAnyPermission('" + ServiceRole.OPS + "', '" + ServiceRole.ADMIN + "', '" + ServiceRole.EDITOR + "', '" + ServiceRole.VIEWER + "')") public ResponseEntity<ParsedAction> testAction(@RequestBody @Valid TestActionRequest testActionRequest) { diff --git a/register-core/src/main/java/org/opengroup/osdu/register/api/DdmsApi.java b/register-core/src/main/java/org/opengroup/osdu/register/api/DdmsApi.java index d98bd0bc04d5c8a57e4ceba942d063ca33a098cc..8ac3ecfeb6c7654f2b93f56993e15e14dbc57a50 100644 --- a/register-core/src/main/java/org/opengroup/osdu/register/api/DdmsApi.java +++ b/register-core/src/main/java/org/opengroup/osdu/register/api/DdmsApi.java @@ -16,32 +16,52 @@ package org.opengroup.osdu.register.api; -import java.util.Collections; -import javax.validation.constraints.NotBlank; -import org.opengroup.osdu.register.ddms.model.Ddms; -import org.opengroup.osdu.register.provider.interfaces.ddms.IDdmsRepository; -import org.opengroup.osdu.register.ddms.services.ConsumptionService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.headers.Header; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.opengroup.osdu.core.common.model.http.AppError; import org.opengroup.osdu.core.common.model.http.AppException; import org.opengroup.osdu.core.common.model.storage.validation.ValidationDoc; +import org.opengroup.osdu.register.ddms.model.Ddms; +import org.opengroup.osdu.register.ddms.services.ConsumptionService; import org.opengroup.osdu.register.logging.AuditLogger; +import org.opengroup.osdu.register.provider.interfaces.ddms.IDdmsRepository; import org.opengroup.osdu.register.utils.ServiceRole; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.annotation.RequestScope; import javax.validation.Valid; +import javax.validation.constraints.NotBlank; import javax.validation.constraints.Pattern; import java.net.URI; +import java.util.Collections; import java.util.List; @RestController @RequestMapping("/") @RequestScope @Validated +@Tag(name = "ddms-api", description = "Domain Data Management Service (DDMS) API") public class DdmsApi { @Autowired @@ -51,6 +71,19 @@ public class DdmsApi { @Autowired private ConsumptionService consumptionService; + @Operation(summary = "${ddmsApi.postDMS.summary}", description = "${ddmsApi.postDMS.description}", + security = {@SecurityRequirement(name = "Authorization")}, tags = { "ddms-api" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "201", description = "Created", content = { @Content(schema = @Schema(implementation = Ddms.class)) }), + @ApiResponse(responseCode = "400", description = "Bad Request", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "403", description = "User not authorized to perform the action.", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "404", description = "Not Found", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "409", description = "Conflict", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "500", description = "Internal Server Error", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "502", description = "Bad Gateway", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "503", description = "Service Unavailable", content = {@Content(schema = @Schema(implementation = AppError.class ))}) + }) @PostMapping("ddms") @PreAuthorize("@authorizationFilter.hasAnyPermission('" + ServiceRole.EDITOR + "', '" + ServiceRole.ADMIN + "', '" + ServiceRole.OPS + "')") public ResponseEntity<Ddms> postDMS(@RequestBody @Valid Ddms spec) { @@ -59,23 +92,68 @@ public class DdmsApi { return new ResponseEntity<>(spec, HttpStatus.CREATED); } + @Operation(summary = "${ddmsApi.getDMS.summary}", description = "${ddmsApi.getDMS.description}", + security = {@SecurityRequirement(name = "Authorization")}, tags = { "ddms-api" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = { @Content(schema = @Schema(implementation = Ddms.class)) }), + @ApiResponse(responseCode = "400", description = "Bad Request", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "403", description = "User not authorized to perform the action.", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "404", description = "Not Found", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "409", description = "Conflict", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "500", description = "Internal Server Error", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "502", description = "Bad Gateway", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "503", description = "Service Unavailable", content = {@Content(schema = @Schema(implementation = AppError.class ))}) + }) @GetMapping("ddms/{id}") @PreAuthorize("@authorizationFilter.hasAnyPermission('" + ServiceRole.OPS + "', '" + ServiceRole.ADMIN + "', '" + ServiceRole.EDITOR + "', '" + ServiceRole.VIEWER + "')") - public ResponseEntity<Ddms> getDMS(@PathVariable("id") @NotBlank @Pattern(regexp = "^[A-Za-z0-9-]{2,50}") String id) { + public ResponseEntity<Ddms> getDMS(@Parameter(description = "Id", example = "example-id-123", + in = ParameterIn.PATH, schema = @Schema(implementation = String.class, pattern = "^[A-Za-z0-9-]{2,50}")) + @PathVariable("id") @NotBlank @Pattern(regexp = "^[A-Za-z0-9-]{2,50}") String id) { Ddms result = dmsRepository.get(id); return new ResponseEntity<>(result, HttpStatus.OK); } + @Operation(summary = "${ddmsApi.queryDMS.summary}", description = "${ddmsApi.queryDMS.description}", + security = {@SecurityRequirement(name = "Authorization")}, tags = { "ddms-api" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = { @Content(array = @ArraySchema(schema = @Schema(implementation = Ddms.class)))}), + @ApiResponse(responseCode = "400", description = "Bad Request", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "403", description = "User not authorized to perform the action.", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "404", description = "Not Found", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "409", description = "Conflict", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "500", description = "Internal Server Error", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "502", description = "Bad Gateway", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "503", description = "Service Unavailable", content = {@Content(schema = @Schema(implementation = AppError.class ))}) + }) @GetMapping("ddms") @PreAuthorize("@authorizationFilter.hasAnyPermission('" + ServiceRole.OPS + "', '" + ServiceRole.ADMIN + "', '" + ServiceRole.EDITOR + "', '" + ServiceRole.VIEWER + "')") - public ResponseEntity<List<Ddms>> queryDMS(@RequestParam("type") @NotBlank @Pattern(regexp = "^[A-Za-z0-9]{1,50}") String type) { + public ResponseEntity<List<Ddms>> queryDMS(@Parameter(description = "Specifies the type in ddms I.E wellbores", + schema = @Schema(implementation = String.class, pattern = "^[A-Za-z0-9]{1,50}")) + @RequestParam("type") @NotBlank @Pattern(regexp = "^[A-Za-z0-9]{1,50}") String type) { List<Ddms> result = dmsRepository.query(type); return new ResponseEntity<>(result, HttpStatus.OK); } + @Operation(summary = "${ddmsApi.deleteDMS.summary}", description = "${ddmsApi.deleteDMS.description}", + security = {@SecurityRequirement(name = "Authorization")}, tags = { "ddms-api" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "204", description = "No Content"), + @ApiResponse(responseCode = "400", description = "Bad Request", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "403", description = "User not authorized to perform the action.", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "404", description = "Not Found", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "409", description = "Conflict", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "500", description = "Internal Server Error", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "502", description = "Bad Gateway", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "503", description = "Service Unavailable", content = {@Content(schema = @Schema(implementation = AppError.class ))}) + }) @DeleteMapping("ddms/{id}") @PreAuthorize("@authorizationFilter.hasAnyPermission('" + ServiceRole.ADMIN + "', '" + ServiceRole.OPS + "')") - public ResponseEntity deleteDMS(@PathVariable("id") @NotBlank @Pattern(regexp = "^[A-Za-z0-9-]{2,50}") String id) { + public ResponseEntity deleteDMS(@Parameter(description = "Id", example = "example-id-123", + in = ParameterIn.PATH, schema = @Schema(implementation = String.class, pattern = "^[A-Za-z0-9-]{2,50}")) + @PathVariable("id") @NotBlank @Pattern(regexp = "^[A-Za-z0-9-]{2,50}") String id) { boolean result = dmsRepository.delete(id); if (result) { this.auditLogger.deleteDmsSuccess(Collections.singletonList(id)); @@ -84,11 +162,30 @@ public class DdmsApi { throw new AppException(org.apache.http.HttpStatus.SC_NOT_FOUND, "Not found", String.format("Could not delete DDMS with id %s because it could not be found", id)); } } + + @Operation(summary = "${ddmsApi.redirectToDms.summary}", description = "${ddmsApi.redirectToDms.description}", + security = {@SecurityRequirement(name = "Authorization")}, tags = { "ddms-api" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "307", description = "Temporary Redirect", headers = @Header(name = "location", + schema = @Schema(type = "string"), description = "Redirection to DDMS Single entity retrieve URL")), + @ApiResponse(responseCode = "400", description = "Bad Request", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "403", description = "User not authorized to perform the action.", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "404", description = "Not Found", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "409", description = "Conflict", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "500", description = "Internal Server Error", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "502", description = "Bad Gateway", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "503", description = "Service Unavailable", content = {@Content(schema = @Schema(implementation = AppError.class ))}) + }) @GetMapping("ddms/{id}/{type}/{localid}") @PreAuthorize("@authorizationFilter.hasAnyPermission('" + ServiceRole.OPS + "', '" + ServiceRole.ADMIN + "', '" + ServiceRole.EDITOR + "', '" + ServiceRole.VIEWER + "')") public ResponseEntity redirectToDms( + @Parameter(description = "Id", example = "example-id-123", in = ParameterIn.PATH, schema = @Schema(implementation = String.class, pattern = "^[\\w\\.-]{2,50}")) @PathVariable("id") @NotBlank @Pattern(regexp = "^[\\w\\.-]{2,50}") String id, + @Parameter(description = "Specifies the type in ddms I.E wellbores", in = ParameterIn.PATH, schema = @Schema(implementation = String.class, pattern = "^[\\w\\.-]{2,50}")) @PathVariable("type") @NotBlank @Pattern(regexp = "^[\\w\\.-]{2,50}") String type, + @Parameter(description = "Specifies the record id with Optional version partition-id:group-type--IndividualType:UniqueRecordID:<OptionalVersionNumber>", + in = ParameterIn.PATH, schema = @Schema(implementation = String.class, pattern = ValidationDoc.RECORD_ID_REGEX)) @PathVariable("localid") @NotBlank @Pattern(regexp = ValidationDoc.RECORD_ID_REGEX) String localid) throws Exception { URI targetURIForRedirection = this.consumptionService.getSingleEntityRetrivalUri(id, type, localid); return ResponseEntity.status(HttpStatus.TEMPORARY_REDIRECT).location(targetURIForRedirection).build(); diff --git a/register-core/src/main/java/org/opengroup/osdu/register/api/HealthChecksApi.java b/register-core/src/main/java/org/opengroup/osdu/register/api/HealthChecksApi.java index b84e9a3b1fdc66e4d648c6b5a7fd541d385ba901..ec49e6a1f10a5d032c5d3e10430cf4009e0d1f2d 100644 --- a/register-core/src/main/java/org/opengroup/osdu/register/api/HealthChecksApi.java +++ b/register-core/src/main/java/org/opengroup/osdu/register/api/HealthChecksApi.java @@ -16,6 +16,12 @@ package org.opengroup.osdu.register.api; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -25,14 +31,25 @@ import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/ah") +@Tag(name = "health-checks-api", description = "Health Checks API") public class HealthChecksApi { + @Operation(summary = "${healthChecksApi.livenessCheck.summary}", + description = "${healthChecksApi.livenessCheck.description}", tags = { "health-checks-api" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = { @Content(schema = @Schema(implementation = String.class)) }) + }) @GetMapping("/liveness_check") public ResponseEntity livenessCheck() { return new ResponseEntity(HttpStatus.OK); } + @Operation(summary = "${healthChecksApi.readinessCheck.summary}", + description = "${healthChecksApi.readinessCheck.description}", tags = { "health-checks-api" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "OK", content = { @Content(schema = @Schema(implementation = String.class)) }) + }) @GetMapping("/readiness_check") public ResponseEntity readinessCheck() { diff --git a/register-core/src/main/java/org/opengroup/osdu/register/api/InfoApi.java b/register-core/src/main/java/org/opengroup/osdu/register/api/InfoApi.java index 43af319d547e67b5512cb6154c63f56f77b15c6a..52ad2bd65e5dbb5a32709964d31c2328a542ad02 100644 --- a/register-core/src/main/java/org/opengroup/osdu/register/api/InfoApi.java +++ b/register-core/src/main/java/org/opengroup/osdu/register/api/InfoApi.java @@ -18,6 +18,13 @@ package org.opengroup.osdu.register.api; import java.io.IOException; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; import org.opengroup.osdu.core.common.info.VersionInfoBuilder; import org.opengroup.osdu.core.common.model.info.VersionInfo; import org.springframework.beans.factory.annotation.Autowired; @@ -28,13 +35,18 @@ import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping +@Tag(name = "info", description = "Version info endpoint") public class InfoApi { @Autowired private VersionInfoBuilder versionInfoBuilder; + @Operation(summary = "${infoApi.info.summary}", description = "${infoApi.info.description}", tags = { "info" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Version info.", content = { @Content(schema = @Schema(implementation = VersionInfo.class)) }) + }) @GetMapping(value = "/info", produces = MediaType.APPLICATION_JSON_VALUE) public VersionInfo info() throws IOException { return versionInfoBuilder.buildVersionInfo(); } -} \ No newline at end of file +} diff --git a/register-core/src/main/java/org/opengroup/osdu/register/api/SubscriberApi.java b/register-core/src/main/java/org/opengroup/osdu/register/api/SubscriberApi.java index 21c275658bb3df1ebbd24ef741585953d06ba5c1..f6309778ed3c0125a77c48647c15d05b4da0e72f 100644 --- a/register-core/src/main/java/org/opengroup/osdu/register/api/SubscriberApi.java +++ b/register-core/src/main/java/org/opengroup/osdu/register/api/SubscriberApi.java @@ -16,14 +16,24 @@ package org.opengroup.osdu.register.api; -import java.util.Collections; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.opengroup.osdu.core.common.model.http.AppError; +import org.opengroup.osdu.core.common.model.http.AppException; import org.opengroup.osdu.core.common.model.notification.Topic; +import org.opengroup.osdu.register.action.model.Action; import org.opengroup.osdu.register.api.dto.SubscriptionInfo; -import org.opengroup.osdu.core.common.model.http.AppException; import org.opengroup.osdu.register.logging.AuditLogger; +import org.opengroup.osdu.register.provider.interfaces.subscriber.ISubscriptionRepository; import org.opengroup.osdu.register.subscriber.model.Secret; import org.opengroup.osdu.register.subscriber.model.Subscription; -import org.opengroup.osdu.register.provider.interfaces.subscriber.ISubscriptionRepository; import org.opengroup.osdu.register.subscriber.services.AvailableTopics; import org.opengroup.osdu.register.subscriber.services.CreateSubscription; import org.opengroup.osdu.register.subscriber.services.DeleteSubscription; @@ -34,19 +44,29 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.annotation.RequestScope; import javax.inject.Inject; import javax.inject.Provider; import javax.validation.Valid; import javax.validation.constraints.NotBlank; +import java.util.Collections; import java.util.List; @RestController @RequestMapping("/") @RequestScope @Validated +@Tag(name = "subscriber-api", description = "Subscriber API") public class SubscriberApi { @Inject @@ -62,6 +82,19 @@ public class SubscriberApi { @Autowired private AuditLogger auditLogger; + @Operation(summary = "${subscriberApi.createSubscription.summary}", description = "${subscriberApi.createSubscription.description}", + security = {@SecurityRequirement(name = "Authorization")}, tags = { "subscriber-api" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "201", description = "Created", content = { @Content(schema = @Schema(implementation = Subscription.class)) }), + @ApiResponse(responseCode = "400", description = "Bad Request", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "403", description = "User not authorized to perform the action.", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "404", description = "Not Found", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "409", description = "Conflict", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "500", description = "Internal Server Error", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "502", description = "Bad Gateway", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "503", description = "Service Unavailable", content = {@Content(schema = @Schema(implementation = AppError.class ))}) + }) @PostMapping("subscription") @PreAuthorize("@authorizationFilter.hasAnyPermission('" + ServiceRole.OPS + "', '" + ServiceRole.ADMIN + "', '" + ServiceRole.EDITOR + "')") public ResponseEntity<Subscription> createSubscription(@RequestBody @Valid Subscription input) throws Exception { @@ -70,24 +103,66 @@ public class SubscriberApi { return new ResponseEntity<>(input, HttpStatus.CREATED); } + @Operation(summary = "${subscriberApi.querySubscription.summary}", description = "${subscriberApi.querySubscription.description}", + security = {@SecurityRequirement(name = "Authorization")}, tags = { "subscriber-api" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Created", content = { @Content(array = @ArraySchema(schema = @Schema(implementation = Subscription.class)))}), + @ApiResponse(responseCode = "400", description = "Bad Request", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "403", description = "User not authorized to perform the action.", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "404", description = "Not Found", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "409", description = "Conflict", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "500", description = "Internal Server Error", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "502", description = "Bad Gateway", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "503", description = "Service Unavailable", content = {@Content(schema = @Schema(implementation = AppError.class ))}) + }) @GetMapping("subscription") @PreAuthorize("@authorizationFilter.hasAnyPermission('" + ServiceRole.OPS + "', '" + ServiceRole.ADMIN + "', '" + ServiceRole.EDITOR + "')") - public ResponseEntity<List<Subscription>> querySubscription(@RequestParam("notificationId") String notificationId) { + public ResponseEntity<List<Subscription>> querySubscription(@Parameter(description = "Notification Id") + @RequestParam("notificationId") String notificationId) { List<Subscription> output = subscriptionRepository.get().query(notificationId); return new ResponseEntity<>(output, HttpStatus.OK); } + @Operation(summary = "${subscriberApi.getSubscription.summary}", description = "${subscriberApi.getSubscription.description}", + security = {@SecurityRequirement(name = "Authorization")}, tags = { "subscriber-api" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Created", content = { @Content(schema = @Schema(implementation = SubscriptionInfo.class)) }), + @ApiResponse(responseCode = "400", description = "Bad Request", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "403", description = "User not authorized to perform the action.", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "404", description = "Not Found", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "409", description = "Conflict", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "500", description = "Internal Server Error", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "502", description = "Bad Gateway", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "503", description = "Service Unavailable", content = {@Content(schema = @Schema(implementation = AppError.class ))}) + }) @GetMapping("subscription/{id}") @PreAuthorize("@authorizationFilter.hasAnyPermission('" + ServiceRole.OPS + "', '" + ServiceRole.ADMIN + "', '" + ServiceRole.EDITOR + "')") - public ResponseEntity<SubscriptionInfo> getSubscription(@PathVariable("id") @NotBlank String id) { + public ResponseEntity<SubscriptionInfo> getSubscription(@Parameter(description = "Subscription Id") + @PathVariable("id") @NotBlank String id) { Subscription output = subscriptionRepository.get().get(id); this.auditLogger.readSubscriptionSuccess(Collections.singletonList(output.getId())); return new ResponseEntity<>(new SubscriptionInfo(output), HttpStatus.OK); } + @Operation(summary = "${subscriberApi.updateSecret.summary}", description = "${subscriberApi.updateSecret.description}", + security = {@SecurityRequirement(name = "Authorization")}, tags = { "subscriber-api" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "204", description = "No Content"), + @ApiResponse(responseCode = "400", description = "Bad Request", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "403", description = "User not authorized to perform the action.", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "404", description = "Not Found", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "409", description = "Conflict", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "500", description = "Internal Server Error", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "502", description = "Bad Gateway", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "503", description = "Service Unavailable", content = {@Content(schema = @Schema(implementation = AppError.class ))}) + }) @PutMapping("subscription/{id}/secret") @PreAuthorize("@authorizationFilter.hasAnyPermission('" + ServiceRole.OPS + "', '" + ServiceRole.ADMIN + "', '" + ServiceRole.EDITOR + "')") - public ResponseEntity updateSecret(@RequestBody @Valid Secret input, @PathVariable("id") @NotBlank String id) { + public ResponseEntity updateSecret(@RequestBody @Valid Secret input, @Parameter(description = "Subscription Id") + @PathVariable("id") @NotBlank String id) { if (updateSubscriptionSecret.get().run(input, id)) { this.auditLogger.updateSubscriptionSecretSuccess(Collections.singletonList(input.toString())); return new ResponseEntity(HttpStatus.NO_CONTENT); @@ -97,9 +172,22 @@ public class SubscriberApi { } } + @Operation(summary = "${subscriberApi.deleteSubscription.summary}", description = "${subscriberApi.deleteSubscription.description}", + security = {@SecurityRequirement(name = "Authorization")}, tags = { "subscriber-api" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "204", description = "No Content"), + @ApiResponse(responseCode = "400", description = "Bad Request", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "403", description = "User not authorized to perform the action.", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "404", description = "Not Found", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "409", description = "Conflict", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "500", description = "Internal Server Error", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "502", description = "Bad Gateway", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "503", description = "Service Unavailable", content = {@Content(schema = @Schema(implementation = AppError.class ))}) + }) @DeleteMapping("subscription/{id}") @PreAuthorize("@authorizationFilter.hasAnyPermission('" + ServiceRole.OPS + "', '" + ServiceRole.ADMIN + "')") - public ResponseEntity deleteSubscription(@PathVariable("id") @NotBlank String id) { + public ResponseEntity deleteSubscription(@Parameter(description = "Subscription Id") @PathVariable("id") @NotBlank String id) { if (deleteSubscription.get().run(id)) { this.auditLogger.deleteSubscriptionSuccess(Collections.singletonList(id)); return new ResponseEntity(HttpStatus.NO_CONTENT); @@ -110,6 +198,19 @@ public class SubscriberApi { } } + @Operation(summary = "${subscriberApi.listMessages.summary}", description = "${subscriberApi.listMessages.description}", + security = {@SecurityRequirement(name = "Authorization")}, tags = { "subscriber-api" }) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Created", content = { @Content(array = @ArraySchema(schema = @Schema(implementation = Topic.class)))}), + @ApiResponse(responseCode = "400", description = "Bad Request", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "401", description = "Unauthorized", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "403", description = "User not authorized to perform the action.", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "404", description = "Not Found", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "409", description = "Conflict", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "500", description = "Internal Server Error", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "502", description = "Bad Gateway", content = {@Content(schema = @Schema(implementation = AppError.class ))}), + @ApiResponse(responseCode = "503", description = "Service Unavailable", content = {@Content(schema = @Schema(implementation = AppError.class ))}) + }) @GetMapping("topics") @PreAuthorize("@authorizationFilter.hasAnyPermission('" + ServiceRole.OPS + "', '" + ServiceRole.ADMIN + "', '" + ServiceRole.EDITOR + "')") public ResponseEntity<List<Topic>> listMessages() { diff --git a/register-core/src/main/java/org/opengroup/osdu/register/api/dto/SubscriptionInfo.java b/register-core/src/main/java/org/opengroup/osdu/register/api/dto/SubscriptionInfo.java index ced3d8aac8b25b8a56da2441907a9c6146c14648..c9d773a56a326e9d3b589df1805a73a2c09f2570 100644 --- a/register-core/src/main/java/org/opengroup/osdu/register/api/dto/SubscriptionInfo.java +++ b/register-core/src/main/java/org/opengroup/osdu/register/api/dto/SubscriptionInfo.java @@ -16,17 +16,33 @@ package org.opengroup.osdu.register.api.dto; +import io.swagger.v3.oas.annotations.media.Schema; import org.opengroup.osdu.register.subscriber.model.Subscription; import lombok.Data; @Data +@Schema(description = "Represents a model for SubscriptionInfo") public class SubscriptionInfo { + + @Schema(example = "dGVzdC1uYW1l") private String id; + + @Schema(example = "test-subscription") private String name; + + @Schema(example = "test description") private String description; + + @Schema(example = "data-changed-v1") private String topic; + + @Schema(example = "https://myListener.com") private String pushEndpoint; + + @Schema(example = "test@myapp.com") private String createdBy; + + @Schema(example = "de-6ee609b9-620e-477b-86f9-3b8907643a12") private String notificationId; public SubscriptionInfo(Subscription subscription) { diff --git a/register-core/src/main/java/org/opengroup/osdu/register/api/test/GsaSubscriberListenerApi.java b/register-core/src/main/java/org/opengroup/osdu/register/api/test/GsaSubscriberListenerApi.java index 403dc54ee055cd44190954d3d6ae79d78171a16f..4a6717cb297c0364b2ebcc413ef91011855cd27c 100644 --- a/register-core/src/main/java/org/opengroup/osdu/register/api/test/GsaSubscriberListenerApi.java +++ b/register-core/src/main/java/org/opengroup/osdu/register/api/test/GsaSubscriberListenerApi.java @@ -5,6 +5,7 @@ import javax.inject.Provider; import javax.validation.ValidationException; import javax.validation.constraints.NotBlank; +import io.swagger.v3.oas.annotations.Hidden; import org.opengroup.osdu.core.common.logging.JaxRsDpsLog; import org.opengroup.osdu.core.common.model.http.DpsHeaders; import org.opengroup.osdu.register.api.dto.ChallengeResponse; @@ -22,6 +23,7 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.annotation.RequestScope; //used as both documentation and by integration test to validate challenge response logic +@Hidden @RestController @RequestMapping("/test") @RequestScope diff --git a/register-core/src/main/java/org/opengroup/osdu/register/api/test/SubscriberListenerApi.java b/register-core/src/main/java/org/opengroup/osdu/register/api/test/SubscriberListenerApi.java index 72bd9ad3d039573157eab854e8c5f43ba4473e5c..3a0a7a41857d752712337b6311ec3b59c5a3d52b 100644 --- a/register-core/src/main/java/org/opengroup/osdu/register/api/test/SubscriberListenerApi.java +++ b/register-core/src/main/java/org/opengroup/osdu/register/api/test/SubscriberListenerApi.java @@ -19,6 +19,7 @@ package org.opengroup.osdu.register.api.test; import javax.validation.ValidationException; import javax.validation.constraints.NotBlank; +import io.swagger.v3.oas.annotations.Hidden; import org.opengroup.osdu.core.common.cryptographic.ISignatureService; import org.opengroup.osdu.core.common.cryptographic.SignatureServiceException; import org.opengroup.osdu.core.common.logging.JaxRsDpsLog; @@ -37,6 +38,7 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.annotation.RequestScope; //used as both documentation and by integration test to validate challenge response logic +@Hidden @RestController @RequestMapping("/test") @RequestScope diff --git a/register-core/src/main/java/org/opengroup/osdu/register/ddms/model/Ddms.java b/register-core/src/main/java/org/opengroup/osdu/register/ddms/model/Ddms.java index 39903ca92d52856df174636564639a35bb023708..8d3504a88a80cbe1586058d70f9e6cbb639d7443 100644 --- a/register-core/src/main/java/org/opengroup/osdu/register/ddms/model/Ddms.java +++ b/register-core/src/main/java/org/opengroup/osdu/register/ddms/model/Ddms.java @@ -27,6 +27,7 @@ import javax.validation.constraints.Email; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Pattern; +import io.swagger.v3.oas.annotations.media.Schema; import org.opengroup.osdu.register.ddms.model.validators.ValidRegisteredInterfaces; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @@ -35,18 +36,24 @@ import lombok.Data; @Data @JsonIgnoreProperties({"first"}) +@Schema(description = "Represents a model for Ddms") public class Ddms { + + @Schema(example = "example-id-123") @NotBlank @Pattern(regexp = "^[A-Za-z0-9-]{2,50}") private String id; + @Schema(example = "example-name") @NotBlank @Pattern(regexp = "^[A-Za-z0-9- ]{2,50}") private String name; + @Schema(example = "example-description") @Pattern(regexp = "^[A-Za-z0-9. ]{0,255}") private String description; + @Schema(example = "abc@test.com") @Email private String contactEmail; diff --git a/register-core/src/main/java/org/opengroup/osdu/register/ddms/model/RegisteredInterface.java b/register-core/src/main/java/org/opengroup/osdu/register/ddms/model/RegisteredInterface.java index e563c2d89ccdd855a04d50cc53287acdb95e8bac..663605b91a0f8866d9a8601442d37a4ef16a51ae 100644 --- a/register-core/src/main/java/org/opengroup/osdu/register/ddms/model/RegisteredInterface.java +++ b/register-core/src/main/java/org/opengroup/osdu/register/ddms/model/RegisteredInterface.java @@ -24,6 +24,7 @@ import com.reprezen.kaizen.oasparser.model3.OpenApi3; import com.reprezen.kaizen.oasparser.model3.Operation; import com.reprezen.kaizen.oasparser.model3.Path; import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AccessLevel; import lombok.Data; import lombok.Getter; @@ -45,7 +46,10 @@ import java.util.stream.Collectors; @ValidOpenApi3Spec @Data +@Schema(description = "Represents a model for RegisteredInterface") public class RegisteredInterface { + + @Schema(example = "wellbore") @NotBlank @Pattern(regexp = "^[A-Za-z0-9 ]{2,50}") private String entityType; diff --git a/register-core/src/main/java/org/opengroup/osdu/register/subscriber/model/GsaSecret.java b/register-core/src/main/java/org/opengroup/osdu/register/subscriber/model/GsaSecret.java index 216091491ada28eb530d5574a9c6836e0fc2ee5f..9b55c345a873149a18f4805255a259651df9f4e9 100644 --- a/register-core/src/main/java/org/opengroup/osdu/register/subscriber/model/GsaSecret.java +++ b/register-core/src/main/java/org/opengroup/osdu/register/subscriber/model/GsaSecret.java @@ -16,12 +16,14 @@ package org.opengroup.osdu.register.subscriber.model; +import io.swagger.v3.oas.annotations.media.Schema; import org.opengroup.osdu.register.utils.Constants; import lombok.Data; import lombok.EqualsAndHashCode; @Data @EqualsAndHashCode(callSuper = true) +@Schema(description = "Represents a model for 'GSA' Secret type") public class GsaSecret extends Secret { private GsaSecretValue value; diff --git a/register-core/src/main/java/org/opengroup/osdu/register/subscriber/model/HmacSecret.java b/register-core/src/main/java/org/opengroup/osdu/register/subscriber/model/HmacSecret.java index a7e144ac8ef8104c589c0c91d1f626eb138331f0..0ed7fcbe0c6af3f2bd1efdd8213bf8b4a59c6857 100644 --- a/register-core/src/main/java/org/opengroup/osdu/register/subscriber/model/HmacSecret.java +++ b/register-core/src/main/java/org/opengroup/osdu/register/subscriber/model/HmacSecret.java @@ -16,12 +16,14 @@ package org.opengroup.osdu.register.subscriber.model; +import io.swagger.v3.oas.annotations.media.Schema; import org.opengroup.osdu.register.utils.Constants; import lombok.Data; import lombok.EqualsAndHashCode; @Data @EqualsAndHashCode(callSuper = true) +@Schema(description = "Represents a model for 'HMAC' Secret type") public class HmacSecret extends Secret { private String value; diff --git a/register-core/src/main/java/org/opengroup/osdu/register/subscriber/model/Secret.java b/register-core/src/main/java/org/opengroup/osdu/register/subscriber/model/Secret.java index 4509547d85b6ebddf8487efaea44d159419e5f19..6f6ee06e8cca98a84b8ffc8a85405d4b93c81636 100644 --- a/register-core/src/main/java/org/opengroup/osdu/register/subscriber/model/Secret.java +++ b/register-core/src/main/java/org/opengroup/osdu/register/subscriber/model/Secret.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; +import io.swagger.v3.oas.annotations.media.Schema; import org.opengroup.osdu.register.utils.Constants; import org.opengroup.osdu.register.subscriber.model.validators.ValidSecret; import lombok.Data; @@ -37,7 +38,9 @@ import lombok.experimental.SuperBuilder; @SuperBuilder @ValidSecret @NoArgsConstructor +@Schema(description = "Represents a model for Secret") public abstract class Secret { + @JsonIgnore private String secretType = ""; diff --git a/register-core/src/main/java/org/opengroup/osdu/register/subscriber/model/Subscription.java b/register-core/src/main/java/org/opengroup/osdu/register/subscriber/model/Subscription.java index 7c13bbc358bedb880f8f56a5291f308fab5e114f..1c6dead50ba346703cbff6db636d24234b5bdfb1 100644 --- a/register-core/src/main/java/org/opengroup/osdu/register/subscriber/model/Subscription.java +++ b/register-core/src/main/java/org/opengroup/osdu/register/subscriber/model/Subscription.java @@ -19,6 +19,7 @@ package org.opengroup.osdu.register.subscriber.model; import java.sql.Timestamp; import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -32,21 +33,38 @@ import javax.validation.constraints.Pattern; @Builder @NoArgsConstructor @AllArgsConstructor +@Schema(description = "Represents a model for Subscription") public class Subscription { + + @Schema(description = "Subscription Id") private String id; + + @Schema(example = "test-subscription") @NotBlank @Pattern(regexp = "^[A-Za-z0-9- ]{2,50}") private String name; + + @Schema(example = "test-subscription") @Pattern(regexp = "^[A-Za-z0-9. ]{0,255}") private String description; + + @Schema(example = "data-changed-v1") @NotBlank private String topic; + + @Schema(example = " https://myListener.com") @NotBlank private String pushEndpoint; + + @Schema(example = "test@myapp.com") private String createdBy; + @JsonIgnore private Timestamp createdOnEpoch; + + @Schema(example = "de-6ee609b9-620e-477b-86f9-3b8907643a12") private String notificationId; + @Valid @Builder.Default private Secret secret = null; diff --git a/register-core/src/main/java/org/opengroup/osdu/register/swagger/HomeController.java b/register-core/src/main/java/org/opengroup/osdu/register/swagger/HomeController.java deleted file mode 100644 index f443a5823c3f1d0535c58ebbb2d98488f4b47d87..0000000000000000000000000000000000000000 --- a/register-core/src/main/java/org/opengroup/osdu/register/swagger/HomeController.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.opengroup.osdu.register.swagger; - -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; - -@Controller -public class HomeController { - @RequestMapping(value = {"/", "/swagger"}) - public String swagger() { - System.out.println("swagger-ui.html"); - return "redirect:swagger-ui.html"; - } -} \ No newline at end of file diff --git a/register-core/src/main/java/org/opengroup/osdu/register/swagger/SwaggerConfiguration.java b/register-core/src/main/java/org/opengroup/osdu/register/swagger/SwaggerConfiguration.java index 62adfaea27b725c2669dee295bddb979e6bd3a4c..196b0c881d856a2db05143c324b2f612675a0871 100644 --- a/register-core/src/main/java/org/opengroup/osdu/register/swagger/SwaggerConfiguration.java +++ b/register-core/src/main/java/org/opengroup/osdu/register/swagger/SwaggerConfiguration.java @@ -1,53 +1,53 @@ package org.opengroup.osdu.register.swagger; - -import io.swagger.v3.oas.models.servers.Server; -import org.springframework.context.annotation.Configuration; -import io.swagger.v3.oas.models.Components; -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; +import io.swagger.v3.oas.annotations.info.Contact; +import io.swagger.v3.oas.annotations.info.Info; +import io.swagger.v3.oas.annotations.info.License; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.security.SecurityScheme; +import io.swagger.v3.oas.annotations.servers.Server; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.models.media.StringSchema; import io.swagger.v3.oas.models.parameters.Parameter; -import io.swagger.v3.oas.models.security.SecurityRequirement; -import io.swagger.v3.oas.models.security.SecurityScheme; import org.opengroup.osdu.core.common.model.http.DpsHeaders; import org.springdoc.core.customizers.OperationCustomizer; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; -import javax.servlet.ServletContext; -import java.util.Collections; - +@OpenAPIDefinition( + info = @Info( + title = "${api.title}", + description = "${api.description}", + version = "${api.version}", + contact = @Contact(name = "${api.contact.name}", email = "${api.contact.email}"), + license = @License(name = "${api.license.name}", url = "${api.license.url}")), + servers = @Server(url = "${api.server.url}"), + security = @SecurityRequirement(name = "Authorization"), + tags = { + @Tag(name = "action-api", description = "Action API"), + @Tag(name = "ddms-api", description = "Domain Data Management Service (DDMS) API"), + @Tag(name = "subscriber-api", description = "Subscriber API"), + @Tag(name = "health-checks-api", description = "Health Checks API"), + @Tag(name = "info", description = "Version info endpoint") + } +) +@SecurityScheme(name = "Authorization", scheme = "bearer", bearerFormat = "Authorization", type = SecuritySchemeType.HTTP) @Configuration public class SwaggerConfiguration { - @Bean - public OpenAPI openApi(ServletContext servletContext) { - Server server = new Server().url(servletContext.getContextPath()); - return new OpenAPI() - .servers(Collections.singletonList(server)) - .info(new Info() - .description("API Documetation") - .title("Register Service") - .version("1.0")) - .components(new Components() - .addSecuritySchemes("Authorization", - new SecurityScheme() - .type(SecurityScheme.Type.HTTP) - .scheme("bearer") - .bearerFormat("Authorization") - .in(SecurityScheme.In.HEADER) - .name("Authorization"))) - .addSecurityItem( - new SecurityRequirement() - .addList("Authorization")); - } - @Bean public OperationCustomizer customize() { - return (operation, handlerMethod) -> operation.addParametersItem( - new Parameter() - .in("header") - .required(true) - .description("Tenant Id") - .name(DpsHeaders.DATA_PARTITION_ID)); + return (operation, handlerMethod) -> { + Parameter dataPartitionId = new Parameter() + .name(DpsHeaders.DATA_PARTITION_ID) + .description("Tenant Id") + .in("header") + .required(true) + .schema(new StringSchema()); + return operation.addParametersItem(dataPartitionId); + }; } -} \ No newline at end of file + +} diff --git a/register-core/src/main/resources/swagger.properties b/register-core/src/main/resources/swagger.properties new file mode 100644 index 0000000000000000000000000000000000000000..fadacda453e81554a6460961ec191642a5727f28 --- /dev/null +++ b/register-core/src/main/resources/swagger.properties @@ -0,0 +1,67 @@ +#Manage common SpringDoc and OpenAPI related properties + +#SpringDoc related properties +springdoc.swagger-ui.tagsSorter=alpha +springdoc.swagger-ui.operationsSorter=alpha +springdoc.swagger-ui.doc-expansion=none +springdoc.swagger-ui.path=/swagger +springdoc.swagger-ui.displayOperationId=true +springdoc.api-docs.path=/api-docs + +#OpenAPI 3.0 - Register Service properties +api.title=Register Service +api.description=APIs to manage registrations in the OSDU. +api.version=1.0 +api.contact.name=OSDU Data Platform Team +api.contact.email=dps@OSDU.org +api.license.name=Apache 2.0 +api.license.url=https://www.apache.org/licenses/LICENSE-2.0.html +api.server.url=${server.servlet.contextPath} + +#Action API related properties +actionApi.createAction.summary=Create an action registration +actionApi.createAction.description=Create an action registration. Required role: `users.datalake.ops` or `users.datalake.admins` +actionApi.retrieveAction.summary=Query for action registrations and substitutes any action with the given parameters +actionApi.retrieveAction.description=Retrieve an action registration. Required roles: `users.datalake.ops` or `users.datalake.admins` or `users.datalake.editors` or `users.datalake.viewers` +actionApi.deleteAction.summary=Delete an action registration +actionApi.deleteAction.description=Delete an action registration with the given id. Required role: `users.datalake.ops` or `users.datalake.admins` +actionApi.getAction.summary=Get an action registration +actionApi.getAction.description=Get an action registration with the given id. Required roles: `users.datalake.ops` or `users.datalake.admins` or `users.datalake.editors` or `users.datalake.viewers` +actionApi.testAction.summary=Test an action registration +actionApi.testAction.description=Test an action registration. Required roles: `users.datalake.ops` or `users.datalake.admins` or `users.datalake.editors` or `users.datalake.viewers` + +#DDMS API related properties +ddmsApi.postDMS.summary=Create a DDMS registration +ddmsApi.postDMS.description=Create a DDMS registration using an OpenApi spec V3 document. Required roles: `users.datalake.editors` or `users.datalake.admins` or `users.datalake.ops` +ddmsApi.getDMS.summary=Get a DDMS registration +ddmsApi.getDMS.description=Get a DDMS registration with the given id. Required roles: `users.datalake.ops` or `users.datalake.admins` or `users.datalake.editors` or `users.datalake.viewers` +ddmsApi.queryDMS.summary=Query for DDMS registrations +ddmsApi.queryDMS.description=Query for DDMS registrations allowing retrievals by type. Required roles: `users.datalake.ops` or `users.datalake.admins` or `users.datalake.editors` or `users.datalake.viewers` +ddmsApi.deleteDMS.summary=Delete a DDMS registration +ddmsApi.deleteDMS.description=Delete a DDMS registration with the given id. Required roles: `users.datalake.ops` or `users.datalake.admins` +ddmsApi.redirectToDms.summary=Retrieves Single Entity record id +ddmsApi.redirectToDms.description=Get a Single DDMS record id. Required roles: `users.datalake.ops` or `users.datalake.admins` or `users.datalake.editors` or `users.datalake.viewers` + +#Subscription API related properties +subscriberApi.createSubscription.summary=Create a subscription +subscriberApi.createSubscription.description=Create a subscription. Required roles: `users.datalake.ops` or `users.datalake.admins` or `users.datalake.editors` +subscriberApi.querySubscription.summary=Query Subscription +subscriberApi.querySubscription.description=Query Subscription by notification Id. Required roles: `users.datalake.ops` or `users.datalake.admins` or `users.datalake.editors` +subscriberApi.getSubscription.summary=Get a subscription +subscriberApi.getSubscription.description=Get a subscription with its Id. Required roles: `users.datalake.ops` or `users.datalake.admins` or `users.datalake.editors` +subscriberApi.updateSecret.summary=Update secret for a subscription +subscriberApi.updateSecret.description=Update secret for a subscription. Required roles : `users.datalake.ops` or `users.datalake.admins` or `users.datalake.editors` +subscriberApi.deleteSubscription.summary=Delete a subscription +subscriberApi.deleteSubscription.description=Delete a subscription with its Id. Required roles : `users.datalake.ops` or `users.datalake.admins` +subscriberApi.listMessages.summary=List all topics +subscriberApi.listMessages.description=List all topics that you can create a subscription for, along with the corresponding sample messages. \ +<p> Required roles : `users.datalake.ops` or `users.datalake.admins` or `users.datalake.editors` + + +#Info & Health API related properties +infoApi.info.summary=Version info +infoApi.info.description=For deployment available public `/info` endpoint, which provides build and git related information. +healthChecksApi.livenessCheck.summary=Liveness Check endpoint +healthChecksApi.livenessCheck.description=For deployment available public `/liveness_check` endpoint. +healthChecksApi.readinessCheck.summary=Readiness Check endpoint +healthChecksApi.readinessCheck.description=For deployment available public `/readiness_check` endpoint.