Added authentication for Swagger ui, added extended documentation on description queries endpoint
This commit is contained in:
parent
f05962a3b2
commit
37243dba2a
|
@ -0,0 +1,49 @@
|
|||
package org.opencdmp.configurations;
|
||||
|
||||
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.models.security.*;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class OpenAPISecurityConfig {
|
||||
|
||||
@Value("${keycloak-client.serverUrl}")
|
||||
String authServerUrl;
|
||||
@Value("${keycloak-client.realm}")
|
||||
String realm;
|
||||
|
||||
private static final String OAUTH_SCHEME_NAME = "oAuth_security_schema";
|
||||
|
||||
@Bean
|
||||
public OpenAPI openAPI() {
|
||||
Components oauthComponent = new Components();
|
||||
oauthComponent.addSecuritySchemes(OAUTH_SCHEME_NAME, createOAuthScheme());
|
||||
OpenAPI openAPI = new OpenAPI();
|
||||
openAPI.components(oauthComponent);
|
||||
openAPI.addSecurityItem(new SecurityRequirement().addList(OAUTH_SCHEME_NAME));
|
||||
return openAPI;
|
||||
}
|
||||
|
||||
private SecurityScheme createOAuthScheme() {
|
||||
OAuthFlows flows = createOAuthFlows();
|
||||
return new SecurityScheme().type(SecurityScheme.Type.OAUTH2)
|
||||
.flows(flows);
|
||||
}
|
||||
|
||||
private OAuthFlows createOAuthFlows() {
|
||||
OAuthFlow flow = createAuthorizationCodeFlow();
|
||||
return new OAuthFlows().implicit(flow);
|
||||
}
|
||||
|
||||
private OAuthFlow createAuthorizationCodeFlow() {
|
||||
return new OAuthFlow()
|
||||
.authorizationUrl(authServerUrl + "/realms/" + realm + "/protocol/openid-connect/auth")
|
||||
.scopes(new Scopes().addString("read_access", "read data")
|
||||
.addString("write_access", "modify data"));
|
||||
}
|
||||
|
||||
}
|
|
@ -11,6 +11,7 @@ import gr.cite.tools.fieldset.FieldSet;
|
|||
import gr.cite.tools.logging.LoggerService;
|
||||
import gr.cite.tools.logging.MapLogEntry;
|
||||
import gr.cite.tools.validation.ValidationFilterAnnotation;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.xml.bind.JAXBException;
|
||||
|
@ -108,6 +109,7 @@ public class DescriptionController {
|
|||
|
||||
@PostMapping("public/query")
|
||||
@Operation(summary = "Query public descriptions")
|
||||
@Hidden
|
||||
public QueryResult<PublicDescription> publicQuery(@RequestBody DescriptionLookup lookup) throws MyApplicationException, MyForbiddenException {
|
||||
logger.debug("querying {}", PublicDescription.class.getSimpleName());
|
||||
|
||||
|
@ -123,6 +125,7 @@ public class DescriptionController {
|
|||
|
||||
@GetMapping("public/{id}")
|
||||
@Operation(summary = "Fetch a specific public description by id")
|
||||
@Hidden
|
||||
public PublicDescription publicGet(@PathVariable("id") UUID id, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
|
||||
logger.debug(new MapLogEntry("retrieving" + PublicDescription.class.getSimpleName()).And("id", id).And("fields", fieldSet));
|
||||
fieldSet = this.fieldSetExpanderService.expand(fieldSet);
|
||||
|
@ -143,7 +146,7 @@ public class DescriptionController {
|
|||
}
|
||||
|
||||
@PostMapping("query")
|
||||
@Operation(summary = "Query all descriptions")
|
||||
@Operation(summary = "Query all descriptions", description = SwaggerHelpers.endpoint_query)
|
||||
public QueryResult<Description> query(@RequestBody DescriptionLookup lookup) throws MyApplicationException, MyForbiddenException {
|
||||
logger.debug("querying {}", Description.class.getSimpleName());
|
||||
|
||||
|
@ -216,6 +219,7 @@ public class DescriptionController {
|
|||
|
||||
@PostMapping("get-description-section-permissions")
|
||||
@Operation(summary = "Fetch the section specific user permissions")
|
||||
@Hidden
|
||||
@ValidationFilterAnnotation(validator = DescriptionSectionPermissionResolver.DescriptionSectionPermissionResolverPersistValidator.ValidatorName, argumentName = "model")
|
||||
public Map<UUID, List<String>> getDescriptionSectionPermissions(@RequestBody DescriptionSectionPermissionResolver model) {
|
||||
logger.debug(new MapLogEntry("persisting" + Description.class.getSimpleName()).And("model", model));
|
||||
|
@ -230,6 +234,7 @@ public class DescriptionController {
|
|||
|
||||
@GetMapping("validate")
|
||||
@Operation(summary = "Validate if a description is ready for finalization by id")
|
||||
@Hidden
|
||||
public List<DescriptionValidationResult> validate(@RequestParam("descriptionIds") List<UUID> descriptionIds) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException {
|
||||
logger.debug(new MapLogEntry("validating" + Description.class.getSimpleName()).And("descriptionIds", descriptionIds));
|
||||
|
||||
|
@ -331,4 +336,125 @@ public class DescriptionController {
|
|||
));
|
||||
return response;
|
||||
}
|
||||
|
||||
protected static class SwaggerHelpers {
|
||||
static final String endpoint_query =
|
||||
"""
|
||||
This endpoint is used to fetch all the available descriptions.<br/>
|
||||
It also allows to restrict the results using a query object passed in the request body.<br/>
|
||||
Let's explore the options this object gives us.
|
||||
|
||||
### <u>General query parameters:</u>
|
||||
|
||||
<ul>
|
||||
<li><b>page:</b>
|
||||
This is an object controlling the pagination of the results. It contains two properties.
|
||||
</li>
|
||||
<ul>
|
||||
<li><b>offset:</b>
|
||||
How many records to omit.
|
||||
</li>
|
||||
<li><b>size:</b>
|
||||
How many records to include in each page.
|
||||
</li>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
For example, if we want the third page, and our pages to contain 15 elements, we would pass the following object:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"offset": 30,
|
||||
"size": 15
|
||||
}
|
||||
```
|
||||
|
||||
<ul>
|
||||
<li><b>order:</b>
|
||||
This is an object controlling the ordering of the results.
|
||||
It contains a list of strings called <i>items</i> with the names of the properties to use.
|
||||
<br/>If the name of the property is prefixed with a <b>'-'</b>, the ordering direction is <b>DESC</b>. Otherwise, it is <b>ASC</b>.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
For example, if we wanted to order based on the field 'createdAt' in descending order, we would pass the following object:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"items": [
|
||||
"-createdAt"
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
<ul>
|
||||
<li><b>metadata:</b>
|
||||
This is an object containing metadata for the request. There is only one available option.
|
||||
<ul>
|
||||
<li><b>countAll:</b>
|
||||
If this is set to true, the count property included in the response will account for all the records regardless the pagination,
|
||||
with all the rest of filtering options applied of course.
|
||||
Otherwise, if it is set to false or not present, only the returned results will be counted.
|
||||
<br/>The first option is useful for the UI clients to calculate how many result pages are available.
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><b>project:</b>
|
||||
This is an object controlling the data projection of the results.
|
||||
It contains a list of strings called <i>fields</i> with the names of the properties to project.
|
||||
<br/>You can also include properties that are deeper in the object tree by prefixing them with dots.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
### <u>Description specific query parameters:</u>
|
||||
|
||||
<ul>
|
||||
<li><b>like:</b>
|
||||
If there is a like parameter present in the query, only the description entities that include the contents of the parameter either in their labels or the descriptions will be in the response.
|
||||
</li>
|
||||
<li><b>ids:</b>
|
||||
This is a list and contains the ids we want to include in the response. <br/>If empty, every record is included.
|
||||
</li>
|
||||
<li><b>excludedIds:</b>
|
||||
This is a list and contains the ids we want to exclude from the response. <br/>If empty, no record gets excluded.
|
||||
</li>
|
||||
<li><b>isActive:</b>
|
||||
This is a list and determines which records we want to include in the response, based on if they are deleted or not.
|
||||
This filter works like this. If we want to view only the active records we pass [1] and for only the deleted records we pass [0].
|
||||
<br/>If not present or if we pass [0,1], every record is included.
|
||||
</li>
|
||||
<li><b>statuses:</b>
|
||||
This is a list and determines which records we want to include in the response, based on their status.
|
||||
The status can be <i>Draft</i>, <i>Finalized</i> or <i>Canceled</i>. We add 0, 1 or 2 to the list respectively.
|
||||
<br/>If not present, every record is included.
|
||||
</li>
|
||||
<li><b>createdAfter:</b>
|
||||
This is a date and determines which records we want to include in the response, based on their creation date.
|
||||
Specifically, only the records created after the given date are included.
|
||||
<br/>If not present, every record is included.
|
||||
</li>
|
||||
<li><b>createdBefore:</b>
|
||||
This is a date and determines which records we want to include in the response, based on their creation date.
|
||||
Specifically, only the records created before the given date are included.
|
||||
<br/>If not present, every record is included.
|
||||
</li>
|
||||
<li><b>finalizedAfter:</b>
|
||||
This is a date and determines which records we want to include in the response, based on their finalization date.
|
||||
Specifically, only the records finalized after the given date are included.
|
||||
<br/>If not present, every record is included.
|
||||
</li>
|
||||
<li><b>finalizedBefore:</b>
|
||||
This is a date and determines which records we want to include in the response, based on their finalization date.
|
||||
Specifically, only the records finalized before the given date are included.
|
||||
<br/>If not present, every record is included.
|
||||
</li>
|
||||
</ul>
|
||||
""";
|
||||
|
||||
static final String endpoint_ =
|
||||
"""
|
||||
|
||||
""";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,15 +4,17 @@ springdoc:
|
|||
enabled: true
|
||||
groupConfigs:
|
||||
- group: public-api
|
||||
displayName: Public API
|
||||
displayName: Legacy
|
||||
packagesToScan: org.opencdmp.controllers.publicapi
|
||||
pathsToMatch: "/api/public/dmps/**, /api/public/datasets/**"
|
||||
- group: internal-api
|
||||
displayName: Internal API
|
||||
displayName: Current
|
||||
packagesToScan: org.opencdmp.controllers
|
||||
packagesToExclude: org.opencdmp.controllers.publicapi
|
||||
pathsToMatch: "/api/dmp/**, /api/description/**"
|
||||
swagger-ui:
|
||||
swaggerUi:
|
||||
enabled: true
|
||||
useRootPath: true
|
||||
docExpansion: none
|
||||
oauth:
|
||||
clientId: dmp_swagger
|
Loading…
Reference in New Issue