diff --git a/datasafe-rest-impl/pom.xml b/datasafe-rest-impl/pom.xml index 217636c3f..f734f1448 100644 --- a/datasafe-rest-impl/pom.xml +++ b/datasafe-rest-impl/pom.xml @@ -17,8 +17,8 @@ 3.1.2 2.9.2 0.10.5 - 2.0.3.RELEASE - 1.5.3 + 3.0.0 + 2.2.4 1.6.0 3.0.2 @@ -60,6 +60,11 @@ spring-boot-starter-web ${spring-boot.version} + + org.yaml + snakeyaml + 2.1 + org.springframework.boot spring-boot-starter-actuator @@ -82,16 +87,6 @@ jakarta.validation-api ${jakarta.validation-api.varsion} - - io.springfox - springfox-swagger2 - ${springfox-swagger.version} - - - io.springfox - springfox-swagger-ui - ${springfox-swagger.version} - com.internetitem logback-elasticsearch-appender @@ -149,8 +144,8 @@ test - junit - junit + org.springframework.boot + spring-boot-starter-logging diff --git a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/config/MvcConfig.java b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/config/MvcConfig.java deleted file mode 100644 index 9cbbc7ed4..000000000 --- a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/config/MvcConfig.java +++ /dev/null @@ -1,112 +0,0 @@ -package de.adorsys.datasafe.rest.impl.config; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.format.support.FormattingConversionService; -import org.springframework.http.MediaType; -import org.springframework.util.AntPathMatcher; -import org.springframework.util.StringUtils; -import org.springframework.web.accept.ContentNegotiationManager; -import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; -import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; -import org.springframework.web.servlet.resource.ResourceUrlProvider; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Custom configuration of Spring MVC that allows using PathVariables that contain slash. For example, when - * doing request path matching mapping {@code /documents/{path:.*}} will be converted to {@code /documents/**}. - */ -@Slf4j -@Configuration -@RequiredArgsConstructor -public class MvcConfig extends WebMvcConfigurationSupport { - - private final DatasafeProperties datasafeProperties; - - /** - * Register customized request matcher that maps /{path:.*} to /** and extracts variables properly. - */ - @Bean - @Override - public RequestMappingHandlerMapping requestMappingHandlerMapping( - @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager, - @Qualifier("mvcConversionService") FormattingConversionService conversionService, - @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider - ) { - RequestMappingHandlerMapping handlerMapping = super.requestMappingHandlerMapping(contentNegotiationManager, conversionService, resourceUrlProvider); - handlerMapping.setPathMatcher(new ExtendedMatcher()); - return handlerMapping; - } - - /** - * Register static resources - frontend UI. - */ - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) { - if (StringUtils.isEmpty(datasafeProperties.getStaticResources())) { - return; - } - - log.info("Serving static resources from {} as /static/**", datasafeProperties.getStaticResources()); - registry - .addResourceHandler("/static/**") - .addResourceLocations(datasafeProperties.getStaticResources()); - } - - /** - * Spring MVC uses URL-ending extension to deduce stream format, we override that to use endpoint output format. - */ - @Override - public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { - configurer - .favorPathExtension(false) - .favorParameter(false) - .ignoreAcceptHeader(false) - .defaultContentType(MediaType.APPLICATION_JSON); - } - - @Override - protected void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { - configurer.enable(); - } - - public static class ExtendedMatcher extends AntPathMatcher { - - private final Pattern expandedUriPattern = Pattern.compile("(\\{(\\w+):\\.\\*})"); - - @Override - protected boolean doMatch(String pattern, String path, boolean fullMatch, Map uriTemplateVariables) { - // /documents/{path:.*} is converted to /documents/** - String expandedPattern = expandedUriPattern.matcher(pattern).replaceAll("**"); - return super.doMatch(expandedPattern, path, fullMatch, uriTemplateVariables); - } - - @Override - public Map extractUriTemplateVariables(String pattern, String path) { - Matcher patternMatcher = expandedUriPattern.matcher(pattern); - if (!patternMatcher.find()) { - return super.extractUriTemplateVariables(pattern, path); - } - - String expandedPattern = expandedUriPattern.matcher(pattern).replaceAll("(.+)"); - Matcher pathMatcher = Pattern.compile(expandedPattern).matcher(path); - if (!pathMatcher.find()) { - return super.extractUriTemplateVariables(pattern, path); - } - - Map variables = new LinkedHashMap<>(); - variables.put(patternMatcher.group(2), pathMatcher.group(1)); - return variables; - } - } -} diff --git a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/config/SwaggerConfig.java b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/config/SwaggerConfig.java deleted file mode 100644 index b49db5cad..000000000 --- a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/config/SwaggerConfig.java +++ /dev/null @@ -1,66 +0,0 @@ -package de.adorsys.datasafe.rest.impl.config; - -import de.adorsys.datasafe.rest.impl.security.SecurityConstants; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.bind.annotation.RequestMethod; -import springfox.documentation.builders.PathSelectors; -import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.builders.ResponseMessageBuilder; -import springfox.documentation.service.ApiKey; -import springfox.documentation.service.AuthorizationScope; -import springfox.documentation.service.ResponseMessage; -import springfox.documentation.service.SecurityReference; -import springfox.documentation.spi.DocumentationType; -import springfox.documentation.spi.service.contexts.SecurityContext; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.swagger2.annotations.EnableSwagger2; - -import java.util.Collections; -import java.util.List; - -import static springfox.documentation.builders.RequestHandlerSelectors.basePackage; - -/** - * Swagger2 UI for REST api. - */ -@EnableSwagger2 -@Configuration -public class SwaggerConfig { - - @Bean - public Docket api() { - List responseMessages = Collections.singletonList( - new ResponseMessageBuilder().code(403).message("Forbidden").build()); - - return new Docket(DocumentationType.SWAGGER_2) - .globalResponseMessage(RequestMethod.POST, responseMessages) - .globalResponseMessage(RequestMethod.PUT, responseMessages) - .globalResponseMessage(RequestMethod.GET, responseMessages) - .globalResponseMessage(RequestMethod.DELETE, responseMessages) - .useDefaultResponseMessages(false) - .select() - .apis(RequestHandlerSelectors.any()) - .apis(basePackage("de.adorsys")) - .paths(PathSelectors.any()) - .build() - .securitySchemes(Collections.singletonList( - new ApiKey( - "JWT", - SecurityConstants.TOKEN_HEADER, - SecurityConstants.TOKEN_HEADER) - ) - ) - .securityContexts(Collections.singletonList(( - SecurityContext.builder() - .securityReferences( - Collections.singletonList(SecurityReference.builder() - .reference("JWT") - .scopes(new AuthorizationScope[0]) - .build() - ) - ) - .build()) - )); - } -} diff --git a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/AuthenticateController.java b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/AuthenticateController.java index efdba1e6c..59f79c43c 100644 --- a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/AuthenticateController.java +++ b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/AuthenticateController.java @@ -7,10 +7,6 @@ import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.security.Keys; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -25,23 +21,16 @@ import java.util.Date; import java.util.List; -import java.util.stream.Collectors; @Slf4j @RestController @RequiredArgsConstructor -@Api(description = "Initial authentication operations") public class AuthenticateController { private final SecurityProperties securityProperties; private final AuthenticationManager authenticationManager; @PostMapping(SecurityConstants.AUTH_LOGIN_URL) - @ApiOperation("Get token for given username and password") - @ApiResponses(value={ - @ApiResponse(code=200, message="Successfully logged in"), - @ApiResponse(code=401, message="Bad credentials") - }) public void authenticate(@RequestBody UserDTO credentialsDTO, HttpServletResponse response) { String username = credentialsDTO.getUserName(); String password = credentialsDTO.getPassword(); @@ -53,7 +42,7 @@ public void authenticate(@RequestBody UserDTO credentialsDTO, HttpServletRespons List roles = user.getAuthorities() .stream() .map(GrantedAuthority::getAuthority) - .collect(Collectors.toList()); + .toList(); byte[] signingKey = securityProperties.getJwtSecret().getBytes(); diff --git a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/DocumentController.java b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/DocumentController.java index 0aa1a7d6b..d28e74c07 100644 --- a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/DocumentController.java +++ b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/DocumentController.java @@ -11,11 +11,6 @@ import de.adorsys.datasafe.types.api.actions.WriteRequest; import de.adorsys.datasafe.types.api.resource.PrivateResource; import de.adorsys.datasafe.types.api.resource.StorageIdentifier; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; @@ -34,7 +29,6 @@ import java.io.OutputStream; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import static org.springframework.http.HttpHeaders.CONTENT_TYPE; import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE; @@ -46,7 +40,6 @@ @Slf4j @RestController @RequiredArgsConstructor -@Api(description = "Operations with private documents") public class DocumentController { private final DefaultDatasafeServices datasafeService; @@ -55,12 +48,7 @@ public class DocumentController { * Reads user's private file. */ @SneakyThrows - @GetMapping(value = "/document/{path:.*}", produces = APPLICATION_OCTET_STREAM_VALUE) - @ApiOperation("Read document from user's private space") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "Document was successfully read"), - @ApiResponse(code = 401, message = "Document not found") - }) + @GetMapping(value = "/document/{*path}", produces = APPLICATION_OCTET_STREAM_VALUE) public void readDocument(@RequestHeader String user, @RequestHeader String password, @RequestHeader(defaultValue = StorageIdentifier.DEFAULT_ID) String storageId, @@ -83,11 +71,7 @@ public void readDocument(@RequestHeader String user, * Writes file to user's private space. */ @SneakyThrows - @PutMapping(value = "/document/{path:.*}", consumes = MULTIPART_FORM_DATA_VALUE) - @ApiOperation("Write document to user's private space") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "Document was successfully written") - }) + @PutMapping(value = "/document/{*path}", consumes = MULTIPART_FORM_DATA_VALUE) public void writeDocument(@RequestHeader String user, @RequestHeader String password, @RequestHeader(defaultValue = StorageIdentifier.DEFAULT_ID) String storageId, @@ -106,16 +90,10 @@ public void writeDocument(@RequestHeader String user, /** * lists files in user's private space. */ - @GetMapping("/documents/{path:.*}") - @ApiOperation("List documents in user's private space") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "List command successfully completed"), - @ApiResponse(code = 401, message = "Unauthorised") - }) + @GetMapping("/documents/{*path}") public List listDocuments(@RequestHeader String user, @RequestHeader String password, @RequestHeader(defaultValue = StorageIdentifier.DEFAULT_ID) String storageId, - @ApiParam(defaultValue = ".") @PathVariable(required = false) String path) { UserIDAuth userIDAuth = new UserIDAuth(new UserID(user), ReadKeyPasswordHelper.getForString(password)); path = Optional.ofNullable(path) @@ -125,7 +103,7 @@ public List listDocuments(@RequestHeader String user, List documentList = datasafeService.privateService().list( ListRequest.forPrivate(userIDAuth, new StorageIdentifier(storageId), path)) .map(e -> e.getResource().asPrivate().decryptedPath().asString()) - .collect(Collectors.toList()); + .toList(); log.debug("List for path {} returned {} items", path, documentList.size()); return documentList; } catch (AmazonS3Exception e) { // for list this exception most likely means that user credentials wrong @@ -136,11 +114,7 @@ public List listDocuments(@RequestHeader String user, /** * deletes files from user's private space. */ - @DeleteMapping("/document/{path:.*}") - @ApiOperation("Delete document from user's private space") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "Document successfully deleted") - }) + @DeleteMapping("/document/{*path}") public void removeDocument(@RequestHeader String user, @RequestHeader String password, @RequestHeader(defaultValue = StorageIdentifier.DEFAULT_ID) String storageId, diff --git a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/InboxController.java b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/InboxController.java index b5aad6ef5..2967e61d8 100644 --- a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/InboxController.java +++ b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/InboxController.java @@ -11,11 +11,6 @@ import de.adorsys.datasafe.types.api.actions.WriteRequest; import de.adorsys.datasafe.types.api.resource.BasePrivateResource; import de.adorsys.datasafe.types.api.resource.PrivateResource; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; @@ -48,7 +43,6 @@ @Slf4j @RestController @RequiredArgsConstructor -@Api(description = "Operations with inbox") public class InboxController { private final DefaultDatasafeServices dataSafeService; @@ -57,12 +51,7 @@ public class InboxController { * Sends file to multiple users' INBOX. */ @SneakyThrows - @PutMapping(value = "/inbox/document/{path:.*}", consumes = MULTIPART_FORM_DATA_VALUE) - @ApiOperation("Send document to inbox") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "Document was successfully sent"), - @ApiResponse(code = 403, message = "Access denied") - }) + @PutMapping(value = "/inbox/document/{*path}", consumes = MULTIPART_FORM_DATA_VALUE) public void writeToInbox(@RequestHeader Set users, @PathVariable String path, @RequestParam("file") MultipartFile file) { @@ -78,12 +67,7 @@ public void writeToInbox(@RequestHeader Set users, * Reads file from users' INBOX. */ @SneakyThrows - @GetMapping(value = "/inbox/document/{path:.*}", produces = APPLICATION_OCTET_STREAM_VALUE) - @ApiOperation("Read document from inbox") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "Document was successfully read"), - @ApiResponse(code = 404, message = "Document not found") - }) + @GetMapping(value = "/inbox/document/{*path}", produces = APPLICATION_OCTET_STREAM_VALUE) public void readFromInbox(@RequestHeader String user, @RequestHeader String password, @PathVariable String path, @@ -103,11 +87,7 @@ public void readFromInbox(@RequestHeader String user, /** * Deletes file from users' INBOX. */ - @DeleteMapping("/inbox/document/{path:.*}") - @ApiOperation("Delete document from inbox") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "Document successfully deleted") - }) + @DeleteMapping("/inbox/document/{*path}") public void deleteFromInbox(@RequestHeader String user, @RequestHeader String password, @PathVariable String path) { @@ -121,15 +101,9 @@ public void deleteFromInbox(@RequestHeader String user, /** * list files in users' INBOX. */ - @GetMapping(value = "/inbox/documents/{path:.*}", produces = APPLICATION_JSON_VALUE) - @ApiOperation("List files in inbox") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "List command successfully completed"), - @ApiResponse(code = 401, message = "Unauthorised") - }) + @GetMapping(value = "/inbox/documents/{*path}", produces = APPLICATION_JSON_VALUE) public List listInbox(@RequestHeader String user, @RequestHeader String password, - @ApiParam(defaultValue = ".") @PathVariable(required = false) String path) { UserIDAuth userIDAuth = new UserIDAuth(new UserID(user), ReadKeyPasswordHelper.getForString(password)); path = Optional.ofNullable(path) @@ -138,7 +112,7 @@ public List listInbox(@RequestHeader String user, try { List inboxList = dataSafeService.inboxService().list(ListRequest.forDefaultPrivate(userIDAuth, path)) .map(e -> e.getResource().asPrivate().decryptedPath().asString()) - .collect(Collectors.toList()); + .toList(); log.debug("User's {} inbox contains {} items", user, inboxList.size()); return inboxList; } catch (AmazonS3Exception e) { // for list this exception most likely means that user credentials wrong diff --git a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/UserController.java b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/UserController.java index 03765e39d..5d78aece9 100644 --- a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/UserController.java +++ b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/UserController.java @@ -14,10 +14,6 @@ import de.adorsys.datasafe.rest.impl.exceptions.UserExistsException; import de.adorsys.datasafe.types.api.resource.StorageIdentifier; import de.adorsys.datasafe.types.api.types.ReadKeyPassword; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.DeleteMapping; @@ -37,7 +33,6 @@ @RestController @RequestMapping(value = "/user", produces = APPLICATION_JSON_VALUE) @RequiredArgsConstructor -@Api(description = "Create and delete users") public class UserController { private final DefaultDatasafeServices dataSafeService; @@ -56,11 +51,6 @@ public class UserController { * public-keys: ${systemRoot}/${userName}/public/keystore */ @PutMapping - @ApiOperation("Creates new user") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "User successfully created"), - @ApiResponse(code = 400, message = "User already exists") - }) public void createUser(@Validated @RequestBody UserDTO userDTO) { ReadKeyPassword readKeyPassword = ReadKeyPasswordHelper.getForString(userDTO.getPassword()); UserIDAuth auth = new UserIDAuth(new UserID(userDTO.getUserName()), readKeyPassword); @@ -71,7 +61,6 @@ public void createUser(@Validated @RequestBody UserDTO userDTO) { } @PostMapping("/password") - @ApiOperation("Change users' password") public void changePassword(@RequestHeader String user, @RequestHeader String password, @Validated @RequestBody NewPasswordDTO newPassword) { @@ -81,7 +70,6 @@ public void changePassword(@RequestHeader String user, } @GetMapping("/publicProfile") - @ApiOperation("Reads users' public profile") public UserPublicProfileDTO getPublicProfile(@RequestHeader String user, @RequestHeader String password) { ReadKeyPassword readKeyPassword = ReadKeyPasswordHelper.getForString(password); @@ -90,7 +78,6 @@ public UserPublicProfileDTO getPublicProfile(@RequestHeader String user, } @GetMapping("/privateProfile") - @ApiOperation("Reads users' private profile") public UserPrivateProfileDTO getPrivateProfile(@RequestHeader String user, @RequestHeader String password) { ReadKeyPassword readKeyPassword = ReadKeyPasswordHelper.getForString(password); @@ -99,7 +86,6 @@ public UserPrivateProfileDTO getPrivateProfile(@RequestHeader String user, } @PostMapping("/publicProfile") - @ApiOperation("Modifies users' public profile") public void updatePublicProfile(@RequestHeader String user, @RequestHeader String password, @Validated @RequestBody UserPublicProfileDTO profileDto) { @@ -109,7 +95,6 @@ public void updatePublicProfile(@RequestHeader String user, } @PostMapping("/privateProfile") - @ApiOperation("Modifies users' private profile") public void updatePrivateProfile(@RequestHeader String user, @RequestHeader String password, @Validated @RequestBody UserPrivateProfileDTO profileDto) { @@ -119,7 +104,6 @@ public void updatePrivateProfile(@RequestHeader String user, } @PostMapping("/storages") - @ApiOperation("Adds users' storage id and credentials") public void addStorageCredentials(@RequestHeader String user, @RequestHeader String password, @Validated @RequestBody StorageCredsDTO creds) { @@ -133,7 +117,6 @@ public void addStorageCredentials(@RequestHeader String user, } @DeleteMapping("/storages") - @ApiOperation("Removes users' storage id and credentials") public void removeStorageCredentials(@RequestHeader String user, @RequestHeader String password, @RequestHeader String storageId) { @@ -149,11 +132,6 @@ public void removeStorageCredentials(@RequestHeader String user, * @param password user password. */ @DeleteMapping - @ApiOperation("Deletes existing user") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "User successfully deleted"), - @ApiResponse(code = 404, message = "User does not exist") - }) public void deleteUser(@RequestHeader String user, @RequestHeader String password) { UserIDAuth auth = new UserIDAuth(new UserID(user), ReadKeyPasswordHelper.getForString(password)); diff --git a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/VersionController.java b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/VersionController.java index 645e7c110..a373e31d2 100644 --- a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/VersionController.java +++ b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/VersionController.java @@ -15,11 +15,6 @@ import de.adorsys.datasafe.types.api.resource.ResolvedResource; import de.adorsys.datasafe.types.api.resource.StorageIdentifier; import de.adorsys.datasafe.types.api.resource.Versioned; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; @@ -38,7 +33,6 @@ import java.io.OutputStream; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import static org.springframework.http.HttpHeaders.CONTENT_TYPE; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; @@ -48,7 +42,6 @@ @Slf4j @RestController @RequiredArgsConstructor -@Api(description = "Operations on private documents with enabled versioning") public class VersionController { private final VersionedDatasafeServices versionedDatasafeServices; @@ -56,12 +49,7 @@ public class VersionController { /** * lists latest versions of files in user's private space. */ - @GetMapping(value = "/versioned/{path:.*}", produces = APPLICATION_JSON_VALUE) - @ApiOperation("List latest documents in user's private space") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "List command successfully completed"), - @ApiResponse(code = 401, message = "Unauthorised") - }) + @GetMapping(value = "/versioned/{*path}", produces = APPLICATION_JSON_VALUE) public List listVersionedDocuments(@RequestHeader String user, @RequestHeader String password, @RequestHeader(defaultValue = StorageIdentifier.DEFAULT_ID) String storageId, @@ -72,7 +60,7 @@ public List listVersionedDocuments(@RequestHeader String user, List documentList = versionedDatasafeServices.latestPrivate().listWithDetails( ListRequest.forPrivate(userIDAuth, new StorageIdentifier(storageId), path)) .map(e -> e.absolute().getResource().decryptedPath().asString()) - .collect(Collectors.toList()); + .toList(); log.debug("List for path {} returned {} items", path, documentList.size()); return documentList; } catch (AmazonS3Exception e) { // for list this exception most likely means that user credentials wrong @@ -85,12 +73,7 @@ public List listVersionedDocuments(@RequestHeader String user, * reads latest version of file from user's private space. */ @SneakyThrows - @GetMapping(value = "/versioned/{path:.*}", produces = APPLICATION_OCTET_STREAM_VALUE) - @ApiOperation("Read latest document from user's private space") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "Document was successfully read"), - @ApiResponse(code = 404, message = "Document not found") - }) + @GetMapping(value = "/versioned/{*path}", produces = APPLICATION_OCTET_STREAM_VALUE) public void readVersionedDocument(@RequestHeader String user, @RequestHeader String password, @RequestHeader(defaultValue = StorageIdentifier.DEFAULT_ID) String storageId, @@ -113,11 +96,7 @@ public void readVersionedDocument(@RequestHeader String user, * writes latest version of file to user's private space. */ @SneakyThrows - @PutMapping(value = "/versioned/{path:.*}", consumes = MULTIPART_FORM_DATA_VALUE) - @ApiOperation("Write latest document to user's private space") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "Document was successfully written") - }) + @PutMapping(value = "/versioned/{*path}", consumes = MULTIPART_FORM_DATA_VALUE) public void writeVersionedDocument(@RequestHeader String user, @RequestHeader String password, @RequestHeader(defaultValue = StorageIdentifier.DEFAULT_ID) String storageId, @@ -136,11 +115,7 @@ public void writeVersionedDocument(@RequestHeader String user, /** * deletes latest version of file from user's private space. */ - @DeleteMapping("/versioned/{path:.*}") - @ApiOperation("Delete latest document from user's private space") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "Document successfully deleted") - }) + @DeleteMapping("/versioned/{*path}") public void deleteVersionedDocument(@RequestHeader String user, @RequestHeader String password, @RequestHeader(defaultValue = StorageIdentifier.DEFAULT_ID) String storageId, @@ -155,16 +130,10 @@ public void deleteVersionedDocument(@RequestHeader String user, /** * list of file versions. */ - @GetMapping(value = "/versions/list/{path:.*}", produces = APPLICATION_JSON_VALUE) - @ApiOperation("List versions of document") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "List command successfully completed"), - @ApiResponse(code = 401, message = "Unauthorised") - }) + @GetMapping(value = "/versions/list/{*path}", produces = APPLICATION_JSON_VALUE) public List versionsOf(@RequestHeader String user, @RequestHeader String password, @RequestHeader(defaultValue = StorageIdentifier.DEFAULT_ID) String storageId, - @ApiParam(defaultValue = ".") @PathVariable(required = false) String path) { UserIDAuth userIDAuth = new UserIDAuth(new UserID(user), ReadKeyPasswordHelper.getForString(password)); path = Optional.ofNullable(path) @@ -177,9 +146,11 @@ public List versionsOf(@RequestHeader String user, List, PrivateResource, DFSVersion>> versionList = versionedDatasafeServices.versionInfo() .versionsOf(request) - .collect(Collectors.toList()); + .toList(); log.debug("Versions for path {} returned {} items", path, versionList.size()); - return versionList.stream().map(a -> a.absolute().getResource().asPrivate().decryptedPath().asString()).collect(Collectors.toList()); + return versionList.stream() + .map(a -> a.absolute().getResource().asPrivate().decryptedPath().asString()) + .toList(); } } diff --git a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/dto/UserDTO.java b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/dto/UserDTO.java index 5c5607627..6b32fe697 100644 --- a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/dto/UserDTO.java +++ b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/dto/UserDTO.java @@ -1,6 +1,5 @@ package de.adorsys.datasafe.rest.impl.dto; -import io.swagger.annotations.ApiModelProperty; import jakarta.validation.constraints.NotBlank; import lombok.AllArgsConstructor; import lombok.Data; @@ -12,10 +11,8 @@ public class UserDTO { @NotBlank - @ApiModelProperty(value = "user name", position = 1) private String userName; @NotBlank - @ApiModelProperty(value = "password", position = 2) private String password; } diff --git a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/security/SecurityConfig.java b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/security/SecurityConfig.java index cc99e09ac..ed5677088 100644 --- a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/security/SecurityConfig.java +++ b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/security/SecurityConfig.java @@ -1,8 +1,11 @@ package de.adorsys.datasafe.rest.impl.security; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Scope; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; @@ -11,32 +14,28 @@ import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.DelegatingPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.firewall.HttpFirewall; import org.springframework.security.web.firewall.StrictHttpFirewall; +import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.servlet.handler.HandlerMappingIntrospector; + +import java.util.HashMap; +import java.util.Map; import static de.adorsys.datasafe.rest.impl.security.SecurityConstants.TOKEN_HEADER; +@Configuration @EnableWebSecurity @EnableMethodSecurity(securedEnabled = true) public class SecurityConfig { - private static final String[] SWAGGER_RESOURCES = { - "/v2/api-docs", - "/configuration/ui", - "/swagger-resources", - "/configuration/security", - "/swagger-ui.html", - "/webjars/**", - "/swagger-resources/configuration/ui", - "/swagger-ui.html" - }; - private final SecurityProperties securityProperties; SecurityConfig(SecurityProperties securityProperties) { @@ -44,15 +43,25 @@ public class SecurityConfig { } @Bean - public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class); + public SecurityFilterChain filterChain(HttpSecurity http, MvcRequestMatcher.Builder mvc, AuthenticationManager authenticationManager) throws Exception { + MvcRequestMatcher[] SWAGGER_RESOURCES = { + mvc.pattern("/v2/api-docs"), + mvc.pattern("/configuration/ui"), + mvc.pattern("/swagger-resources"), + mvc.pattern("/configuration/security"), + mvc.pattern("/swagger-ui.html"), + mvc.pattern("/webjars/**"), + mvc.pattern("/swagger-resources/configuration/ui"), + mvc.pattern("/swagger-ui.html") + }; + http.cors(AbstractHttpConfigurer::disable) .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(authz -> authz .requestMatchers(SWAGGER_RESOURCES).permitAll() - .requestMatchers("/static/**").permitAll() - .requestMatchers(SecurityConstants.AUTH_LOGIN_URL).permitAll() - .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() + .requestMatchers(mvc.pattern("/static/**")).permitAll() + .requestMatchers(mvc.pattern(SecurityConstants.AUTH_LOGIN_URL)).permitAll() + .requestMatchers(mvc.pattern(HttpMethod.OPTIONS, "/**")).permitAll() .anyRequest().authenticated() ) .addFilter(new JwtAuthorizationFilter(authenticationManager, securityProperties)) @@ -61,11 +70,17 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http.build(); } + @Scope("prototype") + @Bean + MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) { + return new MvcRequestMatcher.Builder(introspector); + } + @Bean public InMemoryUserDetailsManager userDetailsService(PasswordEncoder passwordEncoder) { UserDetails user = User.withDefaultPasswordEncoder() .username(securityProperties.getDefaultUser()) - .password(passwordEncoder.encode(securityProperties.getDefaultPassword())) + .password(securityProperties.getDefaultPassword()) .authorities("ROLE_USER") .build(); return new InMemoryUserDetailsManager(user); @@ -80,7 +95,9 @@ public HttpFirewall allowUrlEncodedSlashHttpFirewall() { @Bean public PasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); + Map encoders = new HashMap<>(); + encoders.put("bcrypt", new BCryptPasswordEncoder()); + return new DelegatingPasswordEncoder("bcrypt", encoders); } @Bean @@ -99,4 +116,9 @@ public CorsConfigurationSource corsConfigurationSource() { return source; } + + @Bean + public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception { + return config.getAuthenticationManager(); + } } diff --git a/datasafe-rest-impl/src/main/resources/application.properties b/datasafe-rest-impl/src/main/resources/application.properties index 622d47d5f..0c7f28841 100644 --- a/datasafe-rest-impl/src/main/resources/application.properties +++ b/datasafe-rest-impl/src/main/resources/application.properties @@ -7,6 +7,7 @@ datasafe.staticResources=${STATIC_RESOURCES} spring.servlet.multipart.max-file-size=1024MB spring.servlet.multipart.max-request-size=1024MB +server.servlet.register-default-servlet=true # Amazon datasafe.amazonAccessKeyID=${AWS_ACCESS_KEY_ID} diff --git a/datasafe-rest-impl/src/main/resources/openapi/datasafe.yml b/datasafe-rest-impl/src/main/resources/openapi/datasafe.yml new file mode 100644 index 000000000..783dfaa88 --- /dev/null +++ b/datasafe-rest-impl/src/main/resources/openapi/datasafe.yml @@ -0,0 +1,954 @@ +openapi: 3.0.1 +info: + title: Api Documentation + description: Api Documentation + termsOfService: urn:tos + contact: {} + license: + name: Apache 2.0 + url: http://www.apache.org/licenses/LICENSE-2.0 + version: "1.0" +servers: + - url: //localhost:8080/ +tags: + - name: authenticate-controller + description: Initial authentication operations + - name: document-controller + description: Operations with private documents + - name: inbox-controller + description: Operations with inbox + - name: user-controller + description: Create and delete users + - name: version-controller + description: Operations on private documents with enabled versioning +paths: + /api/authenticate: + post: + tags: + - authenticate-controller + summary: Get token for given username and password + operationId: authenticateUsingPOST + requestBody: + description: credentialsDTO + content: + application/json: + schema: + $ref: '#/components/schemas/UserDTO' + required: true + responses: + 200: + description: Successfully logged in + content: {} + 401: + description: Bad credentials + content: {} + 403: + description: Forbidden + content: {} + deprecated: false + security: + - JWT: [] + x-codegen-request-body-name: credentialsDTO + /document/{path}: + get: + tags: + - document-controller + summary: Read document from user's private space + operationId: readDocumentUsingGET + parameters: + - name: password + in: header + description: password + required: true + schema: + type: string + - name: path + in: path + description: path + required: true + schema: + type: string + - name: storageId + in: header + description: storageId + required: true + schema: + type: string + default: DEFAULT + - name: user + in: header + description: user + required: true + schema: + type: string + responses: + 200: + description: Document was successfully read + content: {} + 401: + description: Document not found + content: {} + 403: + description: Forbidden + content: {} + deprecated: false + security: + - JWT: [] + put: + tags: + - document-controller + summary: Write document to user's private space + operationId: writeDocumentUsingPUT + parameters: + - name: password + in: header + description: password + required: true + schema: + type: string + - name: path + in: path + description: path + required: true + schema: + type: string + - name: storageId + in: header + description: storageId + required: true + schema: + type: string + default: DEFAULT + - name: user + in: header + description: user + required: true + schema: + type: string + requestBody: + content: + multipart/form-data: + schema: + required: + - file + properties: + file: + type: string + description: file + format: binary + required: true + responses: + 200: + description: Document was successfully written + content: {} + 403: + description: Forbidden + content: {} + deprecated: false + security: + - JWT: [] + delete: + tags: + - document-controller + summary: Delete document from user's private space + operationId: removeDocumentUsingDELETE + parameters: + - name: password + in: header + description: password + required: true + schema: + type: string + - name: path + in: path + description: path + required: true + schema: + type: string + - name: storageId + in: header + description: storageId + required: true + schema: + type: string + default: DEFAULT + - name: user + in: header + description: user + required: true + schema: + type: string + responses: + 200: + description: Document successfully deleted + content: {} + 403: + description: Forbidden + content: {} + deprecated: false + security: + - JWT: [] + /documents/{path}: + get: + tags: + - document-controller + summary: List documents in user's private space + operationId: listDocumentsUsingGET + parameters: + - name: password + in: header + description: password + required: true + schema: + type: string + - name: path + in: path + description: path + required: true + schema: + type: string + default: "." + - name: storageId + in: header + description: storageId + required: true + schema: + type: string + default: DEFAULT + - name: user + in: header + description: user + required: true + schema: + type: string + responses: + 200: + description: List command successfully completed + content: + '*/*': + schema: + type: array + items: + type: string + 401: + description: Unauthorised + content: {} + 403: + description: Forbidden + content: {} + deprecated: false + security: + - JWT: [] + /inbox/document/{path}: + get: + tags: + - inbox-controller + summary: Read document from inbox + operationId: readFromInboxUsingGET + parameters: + - name: password + in: header + description: password + required: true + schema: + type: string + - name: path + in: path + description: path + required: true + schema: + type: string + - name: user + in: header + description: user + required: true + schema: + type: string + responses: + 200: + description: Document was successfully read + content: {} + 403: + description: Forbidden + content: {} + 404: + description: Document not found + content: {} + deprecated: false + security: + - JWT: [] + put: + tags: + - inbox-controller + summary: Send document to inbox + operationId: writeToInboxUsingPUT + parameters: + - name: path + in: path + description: path + required: true + schema: + type: string + - name: users + in: header + description: users + required: true + schema: + type: array + items: + type: string + requestBody: + content: + multipart/form-data: + schema: + required: + - file + properties: + file: + type: string + description: file + format: binary + required: true + responses: + 200: + description: Document was successfully sent + content: {} + 403: + description: Access denied + content: {} + deprecated: false + security: + - JWT: [] + delete: + tags: + - inbox-controller + summary: Delete document from inbox + operationId: deleteFromInboxUsingDELETE + parameters: + - name: password + in: header + description: password + required: true + schema: + type: string + - name: path + in: path + description: path + required: true + schema: + type: string + - name: user + in: header + description: user + required: true + schema: + type: string + responses: + 200: + description: Document successfully deleted + content: {} + 403: + description: Forbidden + content: {} + deprecated: false + security: + - JWT: [] + /inbox/documents/{path}: + get: + tags: + - inbox-controller + summary: List files in inbox + operationId: listInboxUsingGET + parameters: + - name: password + in: header + description: password + required: true + schema: + type: string + - name: path + in: path + description: path + required: true + schema: + type: string + default: "." + - name: user + in: header + description: user + required: true + schema: + type: string + responses: + 200: + description: List command successfully completed + content: + application/json: + schema: + type: array + items: + type: string + 401: + description: Unauthorised + content: {} + 403: + description: Forbidden + content: {} + deprecated: false + security: + - JWT: [] + /user: + put: + tags: + - user-controller + summary: Creates new user + operationId: createUserUsingPUT + requestBody: + description: userDTO + content: + application/json: + schema: + $ref: '#/components/schemas/UserDTO' + required: true + responses: + 200: + description: User successfully created + content: {} + 400: + description: User already exists + content: {} + 403: + description: Forbidden + content: {} + deprecated: false + security: + - JWT: [] + x-codegen-request-body-name: userDTO + delete: + tags: + - user-controller + summary: Deletes existing user + operationId: deleteUserUsingDELETE + parameters: + - name: password + in: header + description: password + required: true + schema: + type: string + - name: user + in: header + description: user + required: true + schema: + type: string + responses: + 200: + description: User successfully deleted + content: {} + 403: + description: Forbidden + content: {} + 404: + description: User does not exist + content: {} + deprecated: false + security: + - JWT: [] + /user/password: + post: + tags: + - user-controller + summary: Change users' password + operationId: changePasswordUsingPOST + parameters: + - name: password + in: header + description: password + required: true + schema: + type: string + - name: user + in: header + description: user + required: true + schema: + type: string + requestBody: + description: newPassword + content: + application/json: + schema: + $ref: '#/components/schemas/NewPasswordDTO' + required: true + responses: + 200: + description: OK + content: {} + 403: + description: Forbidden + content: {} + deprecated: false + security: + - JWT: [] + x-codegen-request-body-name: newPassword + /user/privateProfile: + get: + tags: + - user-controller + summary: Reads users' private profile + operationId: getPrivateProfileUsingGET + parameters: + - name: password + in: header + description: password + required: true + schema: + type: string + - name: user + in: header + description: user + required: true + schema: + type: string + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/UserPrivateProfileDTO' + 403: + description: Forbidden + content: {} + deprecated: false + security: + - JWT: [] + post: + tags: + - user-controller + summary: Modifies users' private profile + operationId: updatePrivateProfileUsingPOST + parameters: + - name: password + in: header + description: password + required: true + schema: + type: string + - name: user + in: header + description: user + required: true + schema: + type: string + requestBody: + description: profileDto + content: + application/json: + schema: + $ref: '#/components/schemas/UserPrivateProfileDTO' + required: true + responses: + 200: + description: OK + content: {} + 403: + description: Forbidden + content: {} + deprecated: false + security: + - JWT: [] + x-codegen-request-body-name: profileDto + /user/publicProfile: + get: + tags: + - user-controller + summary: Reads users' public profile + operationId: getPublicProfileUsingGET + parameters: + - name: password + in: header + description: password + required: true + schema: + type: string + - name: user + in: header + description: user + required: true + schema: + type: string + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/UserPublicProfileDTO' + 403: + description: Forbidden + content: {} + deprecated: false + security: + - JWT: [] + post: + tags: + - user-controller + summary: Modifies users' public profile + operationId: updatePublicProfileUsingPOST + parameters: + - name: password + in: header + description: password + required: true + schema: + type: string + - name: user + in: header + description: user + required: true + schema: + type: string + requestBody: + description: profileDto + content: + application/json: + schema: + $ref: '#/components/schemas/UserPublicProfileDTO' + required: true + responses: + 200: + description: OK + content: {} + 403: + description: Forbidden + content: {} + deprecated: false + security: + - JWT: [] + x-codegen-request-body-name: profileDto + /user/storages: + post: + tags: + - user-controller + summary: Adds users' storage id and credentials + operationId: addStorageCredentialsUsingPOST + parameters: + - name: password + in: header + description: password + required: true + schema: + type: string + - name: user + in: header + description: user + required: true + schema: + type: string + requestBody: + description: creds + content: + application/json: + schema: + $ref: '#/components/schemas/StorageCredsDTO' + required: true + responses: + 200: + description: OK + content: {} + 403: + description: Forbidden + content: {} + deprecated: false + security: + - JWT: [] + x-codegen-request-body-name: creds + delete: + tags: + - user-controller + summary: Removes users' storage id and credentials + operationId: removeStorageCredentialsUsingDELETE + parameters: + - name: password + in: header + description: password + required: true + schema: + type: string + - name: storageId + in: header + description: storageId + required: true + schema: + type: string + - name: user + in: header + description: user + required: true + schema: + type: string + responses: + 200: + description: OK + content: {} + 403: + description: Forbidden + content: {} + deprecated: false + security: + - JWT: [] + /versioned/{path}: + get: + tags: + - version-controller + summary: List latest documents in user's private space + operationId: listVersionedDocumentsUsingGET + parameters: + - name: password + in: header + description: password + required: true + schema: + type: string + - name: path + in: path + description: path + required: true + schema: + type: string + - name: storageId + in: header + description: storageId + required: true + schema: + type: string + default: DEFAULT + - name: user + in: header + description: user + required: true + schema: + type: string + responses: + 200: + description: List command successfully completed + content: + application/json: + schema: + type: array + items: + type: string + 401: + description: Unauthorised + content: {} + 403: + description: Forbidden + content: {} + deprecated: false + security: + - JWT: [] + put: + tags: + - version-controller + summary: Write latest document to user's private space + operationId: writeVersionedDocumentUsingPUT + parameters: + - name: password + in: header + description: password + required: true + schema: + type: string + - name: path + in: path + description: path + required: true + schema: + type: string + - name: storageId + in: header + description: storageId + required: true + schema: + type: string + default: DEFAULT + - name: user + in: header + description: user + required: true + schema: + type: string + requestBody: + content: + multipart/form-data: + schema: + required: + - file + properties: + file: + type: string + description: file + format: binary + required: true + responses: + 200: + description: Document was successfully written + content: {} + 403: + description: Forbidden + content: {} + deprecated: false + security: + - JWT: [] + delete: + tags: + - version-controller + summary: Delete latest document from user's private space + operationId: deleteVersionedDocumentUsingDELETE + parameters: + - name: password + in: header + description: password + required: true + schema: + type: string + - name: path + in: path + description: path + required: true + schema: + type: string + - name: storageId + in: header + description: storageId + required: true + schema: + type: string + default: DEFAULT + - name: user + in: header + description: user + required: true + schema: + type: string + responses: + 200: + description: Document successfully deleted + content: {} + 403: + description: Forbidden + content: {} + deprecated: false + security: + - JWT: [] + /versions/list/{path}: + get: + tags: + - version-controller + summary: List versions of document + operationId: versionsOfUsingGET + parameters: + - name: password + in: header + description: password + required: true + schema: + type: string + - name: path + in: path + description: path + required: true + schema: + type: string + default: "." + - name: storageId + in: header + description: storageId + required: true + schema: + type: string + default: DEFAULT + - name: user + in: header + description: user + required: true + schema: + type: string + responses: + 200: + description: List command successfully completed + content: + application/json: + schema: + type: array + items: + type: string + 401: + description: Unauthorised + content: {} + 403: + description: Forbidden + content: {} + deprecated: false + security: + - JWT: [] +components: + schemas: + NewPasswordDTO: + title: NewPasswordDTO + type: object + properties: + newPassword: + type: string + StorageCredsDTO: + title: StorageCredsDTO + type: object + properties: + password: + type: string + storageRegexMatcher: + type: string + username: + type: string + UserDTO: + title: UserDTO + type: object + properties: + userName: + type: string + description: user name + password: + type: string + description: password + UserPrivateProfileDTO: + title: UserPrivateProfileDTO + type: object + properties: + associatedResources: + type: array + items: + type: string + documentVersionStorage: + type: string + inboxWithFullAccess: + type: string + keystore: + type: string + privateStorage: + type: object + additionalProperties: + type: string + publishPublicKeysTo: + type: string + storageCredentialsKeystore: + type: string + UserPublicProfileDTO: + title: UserPublicProfileDTO + type: object + properties: + inbox: + type: string + publicKeys: + type: string diff --git a/datasafe-rest-impl/src/test/java/de/adorsys/datasafe/rest/impl/controller/AuthenticateControllerTest.java b/datasafe-rest-impl/src/test/java/de/adorsys/datasafe/rest/impl/controller/AuthenticateControllerTest.java index d8c08a3fe..a81629b90 100644 --- a/datasafe-rest-impl/src/test/java/de/adorsys/datasafe/rest/impl/controller/AuthenticateControllerTest.java +++ b/datasafe-rest-impl/src/test/java/de/adorsys/datasafe/rest/impl/controller/AuthenticateControllerTest.java @@ -82,7 +82,7 @@ void testPutDataWithToken() { String token = sendAuthenticateRequest(userDTO).getResponse().getHeader(SecurityConstants.TOKEN_HEADER); mvc.perform( - putFileBuilder("/inbox/{path}", TEST_PATH). + putFileBuilder("/inbox/document/{path}", TEST_PATH). contentType(MediaType.MULTIPART_FORM_DATA_VALUE). content("file content".getBytes()). header("users", TEST_USER). @@ -97,7 +97,7 @@ void testGetDataWithoutTokenFail() { String errorMessage = mvc .perform( - put("/inbox/{path}", TEST_PATH). + put("/inbox/document/{path}", TEST_PATH). contentType(MediaType.APPLICATION_OCTET_STREAM_VALUE). header("user", TEST_USER)) .andExpect(status().isForbidden()) diff --git a/datasafe-rest-impl/src/test/java/de/adorsys/datasafe/rest/impl/controller/TestHelper.java b/datasafe-rest-impl/src/test/java/de/adorsys/datasafe/rest/impl/controller/TestHelper.java index 0105247cb..497599cb5 100644 --- a/datasafe-rest-impl/src/test/java/de/adorsys/datasafe/rest/impl/controller/TestHelper.java +++ b/datasafe-rest-impl/src/test/java/de/adorsys/datasafe/rest/impl/controller/TestHelper.java @@ -18,7 +18,7 @@ public static MockHttpServletRequestBuilder putFileBuilder(String path, Object v "DATA".getBytes() ); - MockMultipartHttpServletRequestBuilder builder = RestDocumentationRequestBuilders.fileUpload(path, vars).file(file); + MockMultipartHttpServletRequestBuilder builder = RestDocumentationRequestBuilders.multipart(path, vars).file(file); return builder.with(request -> { request.setMethod(HttpMethod.PUT.name()); return request; diff --git a/datasafe-storage/datasafe-storage-impl-s3/pom.xml b/datasafe-storage/datasafe-storage-impl-s3/pom.xml index c4b73ac1e..9b7e7acce 100644 --- a/datasafe-storage/datasafe-storage-impl-s3/pom.xml +++ b/datasafe-storage/datasafe-storage-impl-s3/pom.xml @@ -32,6 +32,12 @@ com.amazonaws aws-java-sdk-core + + + commons-logging + commons-logging + + diff --git a/datasafe-types-api/pom.xml b/datasafe-types-api/pom.xml index 0a793d1ad..134ea2919 100644 --- a/datasafe-types-api/pom.xml +++ b/datasafe-types-api/pom.xml @@ -39,6 +39,11 @@ mockito-core test + + org.mockito + mockito-junit-jupiter + test + com.google.guava guava diff --git a/datasafe-types-api/src/test/java/de/adorsys/datasafe/types/api/shared/BaseMockitoTest.java b/datasafe-types-api/src/test/java/de/adorsys/datasafe/types/api/shared/BaseMockitoTest.java index 19835a45a..049935ab4 100644 --- a/datasafe-types-api/src/test/java/de/adorsys/datasafe/types/api/shared/BaseMockitoTest.java +++ b/datasafe-types-api/src/test/java/de/adorsys/datasafe/types/api/shared/BaseMockitoTest.java @@ -3,21 +3,22 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; /** * This class configures Mockito so that it will inject annotated mocks and display exceptions always * at correct places. * Tests that use Mockito should use this class. */ +@ExtendWith(MockitoExtension.class) public abstract class BaseMockitoTest { @BeforeEach public void setup() { System.setProperty("SECURE_LOGS", "off"); System.setProperty("SECURE_SENSITIVE", "off"); - MockitoAnnotations.initMocks(this); } @AfterEach diff --git a/pom.xml b/pom.xml index 23c48f396..c3c8b7195 100644 --- a/pom.xml +++ b/pom.xml @@ -91,7 +91,7 @@ 5.4.1 1.4.1 3.12.2 - 2.25.1 + 5.5.0 2.22.1 1.21 UTF-8 @@ -99,7 +99,7 @@ 1.18.3 0.8.10 2.5 - 1.7.25 + 2.0.7 6.5.0.Final 1.18.20.0 3.0.0 @@ -111,11 +111,10 @@ 1.0-rc4 0.21.0 3.3.0 - 5.1.8.RELEASE 3.3.1 - 1.4.199 + 2.2.220 8.0.16 - 3.6.1 + 4.23.1 6.0.11 3.1.2 1.3.1 @@ -276,6 +275,12 @@ ${mockito.version} test + + org.mockito + mockito-junit-jupiter + ${mockito.version} + test + org.testcontainers testcontainers @@ -326,7 +331,7 @@ org.springframework spring-jdbc - ${spring.jdbc} + ${spring.framework.version} com.zaxxer