Merge branch 'dmp-refactoring' of https://code-repo.d4science.org/MaDgiK-CITE/argos into dmp-refactoring
This commit is contained in:
commit
61ec8e7523
|
@ -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.LoggerService;
|
||||||
import gr.cite.tools.logging.MapLogEntry;
|
import gr.cite.tools.logging.MapLogEntry;
|
||||||
import gr.cite.tools.validation.ValidationFilterAnnotation;
|
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.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.xml.bind.JAXBException;
|
import jakarta.xml.bind.JAXBException;
|
||||||
|
@ -108,6 +109,7 @@ public class DescriptionController {
|
||||||
|
|
||||||
@PostMapping("public/query")
|
@PostMapping("public/query")
|
||||||
@Operation(summary = "Query public descriptions")
|
@Operation(summary = "Query public descriptions")
|
||||||
|
@Hidden
|
||||||
public QueryResult<PublicDescription> publicQuery(@RequestBody DescriptionLookup lookup) throws MyApplicationException, MyForbiddenException {
|
public QueryResult<PublicDescription> publicQuery(@RequestBody DescriptionLookup lookup) throws MyApplicationException, MyForbiddenException {
|
||||||
logger.debug("querying {}", PublicDescription.class.getSimpleName());
|
logger.debug("querying {}", PublicDescription.class.getSimpleName());
|
||||||
|
|
||||||
|
@ -123,6 +125,7 @@ public class DescriptionController {
|
||||||
|
|
||||||
@GetMapping("public/{id}")
|
@GetMapping("public/{id}")
|
||||||
@Operation(summary = "Fetch a specific public description by id")
|
@Operation(summary = "Fetch a specific public description by id")
|
||||||
|
@Hidden
|
||||||
public PublicDescription publicGet(@PathVariable("id") UUID id, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
|
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));
|
logger.debug(new MapLogEntry("retrieving" + PublicDescription.class.getSimpleName()).And("id", id).And("fields", fieldSet));
|
||||||
fieldSet = this.fieldSetExpanderService.expand(fieldSet);
|
fieldSet = this.fieldSetExpanderService.expand(fieldSet);
|
||||||
|
@ -143,7 +146,7 @@ public class DescriptionController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("query")
|
@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 {
|
public QueryResult<Description> query(@RequestBody DescriptionLookup lookup) throws MyApplicationException, MyForbiddenException {
|
||||||
logger.debug("querying {}", Description.class.getSimpleName());
|
logger.debug("querying {}", Description.class.getSimpleName());
|
||||||
|
|
||||||
|
@ -216,6 +219,7 @@ public class DescriptionController {
|
||||||
|
|
||||||
@PostMapping("get-description-section-permissions")
|
@PostMapping("get-description-section-permissions")
|
||||||
@Operation(summary = "Fetch the section specific user permissions")
|
@Operation(summary = "Fetch the section specific user permissions")
|
||||||
|
@Hidden
|
||||||
@ValidationFilterAnnotation(validator = DescriptionSectionPermissionResolver.DescriptionSectionPermissionResolverPersistValidator.ValidatorName, argumentName = "model")
|
@ValidationFilterAnnotation(validator = DescriptionSectionPermissionResolver.DescriptionSectionPermissionResolverPersistValidator.ValidatorName, argumentName = "model")
|
||||||
public Map<UUID, List<String>> getDescriptionSectionPermissions(@RequestBody DescriptionSectionPermissionResolver model) {
|
public Map<UUID, List<String>> getDescriptionSectionPermissions(@RequestBody DescriptionSectionPermissionResolver model) {
|
||||||
logger.debug(new MapLogEntry("persisting" + Description.class.getSimpleName()).And("model", model));
|
logger.debug(new MapLogEntry("persisting" + Description.class.getSimpleName()).And("model", model));
|
||||||
|
@ -230,6 +234,7 @@ public class DescriptionController {
|
||||||
|
|
||||||
@GetMapping("validate")
|
@GetMapping("validate")
|
||||||
@Operation(summary = "Validate if a description is ready for finalization by id")
|
@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 {
|
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));
|
logger.debug(new MapLogEntry("validating" + Description.class.getSimpleName()).And("descriptionIds", descriptionIds));
|
||||||
|
|
||||||
|
@ -331,4 +336,125 @@ public class DescriptionController {
|
||||||
));
|
));
|
||||||
return response;
|
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
|
enabled: true
|
||||||
groupConfigs:
|
groupConfigs:
|
||||||
- group: public-api
|
- group: public-api
|
||||||
displayName: Public API
|
displayName: Legacy
|
||||||
packagesToScan: org.opencdmp.controllers.publicapi
|
packagesToScan: org.opencdmp.controllers.publicapi
|
||||||
pathsToMatch: "/api/public/dmps/**, /api/public/datasets/**"
|
pathsToMatch: "/api/public/dmps/**, /api/public/datasets/**"
|
||||||
- group: internal-api
|
- group: internal-api
|
||||||
displayName: Internal API
|
displayName: Current
|
||||||
packagesToScan: org.opencdmp.controllers
|
packagesToScan: org.opencdmp.controllers
|
||||||
packagesToExclude: org.opencdmp.controllers.publicapi
|
packagesToExclude: org.opencdmp.controllers.publicapi
|
||||||
pathsToMatch: "/api/dmp/**, /api/description/**"
|
pathsToMatch: "/api/dmp/**, /api/description/**"
|
||||||
swagger-ui:
|
swaggerUi:
|
||||||
enabled: true
|
enabled: true
|
||||||
useRootPath: true
|
useRootPath: true
|
||||||
docExpansion: none
|
docExpansion: none
|
||||||
|
oauth:
|
||||||
|
clientId: dmp_swagger
|
Loading…
Reference in New Issue