diff --git a/.github/workflows/pull-requests.yml b/.github/workflows/pull-requests.yml new file mode 100644 index 000000000..0891234c0 --- /dev/null +++ b/.github/workflows/pull-requests.yml @@ -0,0 +1,22 @@ +# Builds Pull-requests to key branches +name: Pull request CI + +on: + pull_request: + branches: + - develop + - master + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: 17 + distribution: 'adopt' + + - name: Build project and run default test suite + run: mvn clean verify -ntp diff --git a/datasafe-business/pom.xml b/datasafe-business/pom.xml index 75e561e32..54c22dbd5 100644 --- a/datasafe-business/pom.xml +++ b/datasafe-business/pom.xml @@ -168,7 +168,6 @@ org.testcontainers testcontainers - 1.11.2 org.awaitility @@ -180,7 +179,10 @@ h2 test - + + javax.xml.bind + jaxb-api + @@ -219,14 +221,19 @@ org.slf4j:slf4j-simple org.junit.jupiter:junit-jupiter-engine - org.mockito:mockito-core com.h2database:h2 + javax.xml.bind:jaxb-api:jar javax.inject:javax.inject com.amazonaws org.bouncycastle + + org.bouncycastle + org.slf4j + org.projectlombok + diff --git a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityWithConcurrencyTest.java b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityWithConcurrencyTest.java index d3909b653..7a219bf06 100644 --- a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityWithConcurrencyTest.java +++ b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/BasicFunctionalityWithConcurrencyTest.java @@ -58,7 +58,7 @@ @Slf4j class BasicFunctionalityWithConcurrencyTest extends BaseE2ETest { - private static final int TIMEOUT_S = 15; + private static final int TIMEOUT_S = 30; private static int NUMBER_OF_TEST_USERS = 3; private static int NUMBER_OF_TEST_FILES = 5; diff --git a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/KeyStoreTypeCompareTest.java b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/KeyStoreTypeCompareTest.java index 6a72fb2d4..76e75fcc4 100644 --- a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/KeyStoreTypeCompareTest.java +++ b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/KeyStoreTypeCompareTest.java @@ -16,7 +16,7 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -import org.testcontainers.shaded.org.apache.commons.lang.time.StopWatch; +import org.testcontainers.shaded.org.apache.commons.lang3.time.StopWatch; import java.io.InputStream; import java.io.OutputStream; diff --git a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/MultiDFSFunctionalityTest.java b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/MultiDFSFunctionalityTest.java index a0ec29c86..a4e5830b8 100644 --- a/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/MultiDFSFunctionalityTest.java +++ b/datasafe-business/src/test/java/de/adorsys/datasafe/business/impl/e2e/MultiDFSFunctionalityTest.java @@ -1,7 +1,6 @@ package de.adorsys.datasafe.business.impl.e2e; import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.AmazonS3Exception; import com.amazonaws.services.s3.model.S3ObjectSummary; import dagger.Lazy; import de.adorsys.datasafe.business.impl.service.DaggerDefaultDatasafeServices; @@ -95,7 +94,7 @@ class MultiDFSFunctionalityTest extends BaseMockitoTest { static void initDistributedMinios() { // Create all required minio-backed S3 buckets: Stream.of(CREDENTIALS, KEYSTORE, FILES_ONE, FILES_TWO, INBOX).forEach(it -> { - GenericContainer minio = new GenericContainer("minio/minio") + GenericContainer minio = new GenericContainer("minio/minio:RELEASE.2019-08-01T22-18-54Z") .withExposedPorts(9000) .withEnv("MINIO_ACCESS_KEY", accessKey(it)) .withEnv("MINIO_SECRET_KEY", secretKey(it)) diff --git a/datasafe-encryption/datasafe-encryption-impl/pom.xml b/datasafe-encryption/datasafe-encryption-impl/pom.xml index 6ebb0c5f0..4640cffa4 100644 --- a/datasafe-encryption/datasafe-encryption-impl/pom.xml +++ b/datasafe-encryption/datasafe-encryption-impl/pom.xml @@ -102,7 +102,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson.version} + ${jackson-databind.version} test @@ -117,6 +117,12 @@ ${jackson.version} test + + com.fasterxml.jackson.core + jackson-core + ${jackson.version} + test + diff --git a/datasafe-rest-impl/pom.xml b/datasafe-rest-impl/pom.xml index 22c64bd66..029961b5d 100644 --- a/datasafe-rest-impl/pom.xml +++ b/datasafe-rest-impl/pom.xml @@ -14,13 +14,13 @@ Spring Boot DataSafe Application - 1.8 - 2.1.5.RELEASE + 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 @@ -78,24 +83,14 @@ true - io.springfox - springfox-swagger2 - ${springfox-swagger.version} - - - io.springfox - springfox-swagger-ui - ${springfox-swagger.version} - - - com.internetitem - logback-elasticsearch-appender - 1.6 + jakarta.validation + jakarta.validation-api + ${jakarta.validation-api.varsion} com.fasterxml.jackson.core jackson-databind - ${jackson.version} + ${jackson-databind.version} com.fasterxml.jackson.core @@ -130,8 +125,8 @@ ${project.version} - mysql - mysql-connector-java + com.mysql + mysql-connector-j ${mysql.version} @@ -144,8 +139,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/DatasafeRestApplication.java b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/DatasafeRestApplication.java index 6fb6e0dc4..cf581b75a 100644 --- a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/DatasafeRestApplication.java +++ b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/DatasafeRestApplication.java @@ -10,9 +10,8 @@ import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; -@SpringBootApplication +@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class}) @EnableConfigurationProperties({DatasafeProperties.class, SecurityProperties.class}) -@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class}) public class DatasafeRestApplication { public static void main(String[] args) { 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 be61ced29..000000000 --- a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/config/MvcConfig.java +++ /dev/null @@ -1,104 +0,0 @@ -package de.adorsys.datasafe.rest.impl.config; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.MediaType; -import org.springframework.util.AntPathMatcher; -import org.springframework.util.StringUtils; -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 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() { - RequestMappingHandlerMapping handlerMapping = super.requestMappingHandlerMapping(); - 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 efadca301..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,7 @@ 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; import org.springframework.security.authentication.AuthenticationManager; @@ -22,26 +19,18 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; -import javax.servlet.http.HttpServletResponse; 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 ebe7e647f..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,7 @@ 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; import lombok.extern.slf4j.Slf4j; @@ -29,12 +25,10 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; -import javax.servlet.http.HttpServletResponse; import java.io.InputStream; 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 525a8b6d0..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,7 @@ 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; import lombok.extern.slf4j.Slf4j; @@ -29,7 +25,6 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; -import javax.servlet.http.HttpServletResponse; import java.io.InputStream; import java.io.OutputStream; import java.util.List; @@ -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/ReadKeyPasswordHelper.java b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/ReadKeyPasswordHelper.java index c0eae5298..cd5822d08 100644 --- a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/ReadKeyPasswordHelper.java +++ b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/controller/ReadKeyPasswordHelper.java @@ -1,16 +1,11 @@ package de.adorsys.datasafe.rest.impl.controller; import de.adorsys.datasafe.types.api.types.ReadKeyPassword; +import lombok.experimental.UtilityClass; -import java.util.function.Supplier; - +@UtilityClass public class ReadKeyPasswordHelper { public static ReadKeyPassword getForString(String a) { - return new ReadKeyPassword(new Supplier() { - @Override - public char[] get() { - return a.toCharArray(); - } - }); + return new ReadKeyPassword(a::toCharArray); } } 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 dc1b468d9..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,7 @@ 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; import lombok.extern.slf4j.Slf4j; @@ -33,12 +29,10 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; -import javax.servlet.http.HttpServletResponse; import java.io.InputStream; 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/NewPasswordDTO.java b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/dto/NewPasswordDTO.java index a81f1baec..dc1acf405 100644 --- a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/dto/NewPasswordDTO.java +++ b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/dto/NewPasswordDTO.java @@ -1,11 +1,10 @@ package de.adorsys.datasafe.rest.impl.dto; +import jakarta.validation.constraints.NotBlank; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotBlank; - @Data @AllArgsConstructor @NoArgsConstructor diff --git a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/dto/StorageCredsDTO.java b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/dto/StorageCredsDTO.java index 40af03488..309755492 100644 --- a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/dto/StorageCredsDTO.java +++ b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/dto/StorageCredsDTO.java @@ -1,10 +1,9 @@ package de.adorsys.datasafe.rest.impl.dto; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import lombok.Data; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; - @Data public class StorageCredsDTO { 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 11d021048..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,22 +1,18 @@ package de.adorsys.datasafe.rest.impl.dto; -import io.swagger.annotations.ApiModelProperty; +import jakarta.validation.constraints.NotBlank; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotBlank; - @Data @AllArgsConstructor @NoArgsConstructor 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/dto/UserPrivateProfileDTO.java b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/dto/UserPrivateProfileDTO.java index d2d81beac..5c00f5cb5 100644 --- a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/dto/UserPrivateProfileDTO.java +++ b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/dto/UserPrivateProfileDTO.java @@ -3,13 +3,13 @@ import de.adorsys.datasafe.directory.api.types.UserPrivateProfile; import de.adorsys.datasafe.types.api.global.Version; import de.adorsys.datasafe.types.api.resource.StorageIdentifier; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; import java.util.List; import java.util.Map; import java.util.stream.Collectors; diff --git a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/dto/UserPublicProfileDTO.java b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/dto/UserPublicProfileDTO.java index b4ea0d4b7..8cecb2057 100644 --- a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/dto/UserPublicProfileDTO.java +++ b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/dto/UserPublicProfileDTO.java @@ -2,12 +2,11 @@ import de.adorsys.datasafe.directory.api.types.UserPublicProfile; import de.adorsys.datasafe.types.api.global.Version; +import jakarta.validation.constraints.NotBlank; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotBlank; - @Data @NoArgsConstructor @AllArgsConstructor diff --git a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/security/JwtAuthorizationFilter.java b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/security/JwtAuthorizationFilter.java index a71339935..592f16087 100644 --- a/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/security/JwtAuthorizationFilter.java +++ b/datasafe-rest-impl/src/main/java/de/adorsys/datasafe/rest/impl/security/JwtAuthorizationFilter.java @@ -8,6 +8,10 @@ import io.jsonwebtoken.MalformedJwtException; import io.jsonwebtoken.UnsupportedJwtException; import io.jsonwebtoken.security.SignatureException; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -15,10 +19,6 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; import java.util.stream.Collectors; 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 475e5bfe4..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,40 +1,40 @@ package de.adorsys.datasafe.rest.impl.security; -import lombok.SneakyThrows; 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.BeanIds; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +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; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; +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 -@EnableGlobalMethodSecurity(securedEnabled = true) -public class SecurityConfig extends WebSecurityConfigurerAdapter { - - public 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" - }; +@EnableMethodSecurity(securedEnabled = true) +public class SecurityConfig { private final SecurityProperties securityProperties; @@ -42,28 +42,48 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { this.securityProperties = securityProperties; } - @Override - protected void configure(HttpSecurity http) throws Exception { - http.cors().and() - .csrf().disable() - .authorizeRequests() - .antMatchers(SWAGGER_RESOURCES).permitAll() - .antMatchers("/static/**").permitAll() - .antMatchers(SecurityConstants.AUTH_LOGIN_URL).permitAll() - .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() - .anyRequest().authenticated() - .and() - .addFilter(new JwtAuthorizationFilter(authenticationManager(), securityProperties)) - .sessionManagement() - .sessionCreationPolicy(SessionCreationPolicy.STATELESS); + @Bean + 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(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)) + .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); + + return http.build(); + } + + @Scope("prototype") + @Bean + MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) { + return new MvcRequestMatcher.Builder(introspector); } - @Override - public void configure(AuthenticationManagerBuilder auth) throws Exception { - auth.inMemoryAuthentication() - .withUser(securityProperties.getDefaultUser()) - .password(passwordEncoder().encode(securityProperties.getDefaultPassword())) - .authorities("ROLE_USER"); + @Bean + public InMemoryUserDetailsManager userDetailsService(PasswordEncoder passwordEncoder) { + UserDetails user = User.withDefaultPasswordEncoder() + .username(securityProperties.getDefaultUser()) + .password(securityProperties.getDefaultPassword()) + .authorities("ROLE_USER") + .build(); + return new InMemoryUserDetailsManager(user); } @Bean @@ -75,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 @@ -95,15 +117,8 @@ public CorsConfigurationSource corsConfigurationSource() { return source; } - @Bean(name = BeanIds.AUTHENTICATION_MANAGER) - @Override - public AuthenticationManager authenticationManagerBean() throws Exception { - return super.authenticationManagerBean(); - } - @Bean - @SneakyThrows - public JwtAuthorizationFilter jwtAuthorizationFilter() { - return new JwtAuthorizationFilter(authenticationManager(), securityProperties); + 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/logback-spring.xml b/datasafe-rest-impl/src/main/resources/logback-spring.xml index e37984bab..5aeb4eb0e 100644 --- a/datasafe-rest-impl/src/main/resources/logback-spring.xml +++ b/datasafe-rest-impl/src/main/resources/logback-spring.xml @@ -1,7 +1,6 @@ - - + @@ -9,69 +8,8 @@ - - http://aws-signing-proxy.aws-elasticsearch-proxy.svc.cluster.local:9200/_bulk - datasafe-%date{yyyy-MM-dd} - datasafe - es-logger - es-error-logger - 30000 - false - false - false - 104857600 - 3 - 30000 - 250 - false - false - 100 - - - host - ${HOSTNAME} - false - - - level - %level - - - thread - %thread - - - stacktrace - %ex - - - logger - %logger - - - -
- Content-Type - application/json -
-
-
- - - - - - - - - - %msg - - - -
\ No newline at end of file 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..b333dd7ae 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 @@ -38,13 +38,12 @@ public class AuthenticateControllerTest extends BaseDatasafeEndpointTest { @BeforeEach public void setup() { + openMocks = MockitoAnnotations.openMocks(this); when(dataSafeService.inboxService()).thenReturn(inboxService); } @Test void testAuthenticateSuccess() { - MockitoAnnotations.initMocks(this); - UserDTO userDTO = new UserDTO(); userDTO.setUserName("username"); userDTO.setPassword("password"); @@ -82,7 +81,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 +96,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-rest-impl/src/test/java/de/adorsys/datasafe/rest/impl/controller/UserControllerTest.java b/datasafe-rest-impl/src/test/java/de/adorsys/datasafe/rest/impl/controller/UserControllerTest.java index c115fccf3..6bf75ebde 100644 --- a/datasafe-rest-impl/src/test/java/de/adorsys/datasafe/rest/impl/controller/UserControllerTest.java +++ b/datasafe-rest-impl/src/test/java/de/adorsys/datasafe/rest/impl/controller/UserControllerTest.java @@ -16,6 +16,7 @@ import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; +import org.mockito.MockitoAnnotations; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler; @@ -51,6 +52,7 @@ class UserControllerTest extends BaseTokenDatasafeEndpointTest { @BeforeEach public void setup() { + openMocks = MockitoAnnotations.openMocks(this); when(dataSafeService.userProfile()).thenReturn(userProfile); gson = new Gson(); } diff --git a/datasafe-runtime-delegate/pom.xml b/datasafe-runtime-delegate/pom.xml index 8d8c11f3f..6dec41d7a 100644 --- a/datasafe-runtime-delegate/pom.xml +++ b/datasafe-runtime-delegate/pom.xml @@ -20,6 +20,10 @@ javax.inject provided + + jakarta.annotation + jakarta.annotation-api + com.squareup javapoet diff --git a/datasafe-runtime-delegate/src/main/java/de/adorsys/datasafe/runtimedelegate/RuntimeDelegateGenerator.java b/datasafe-runtime-delegate/src/main/java/de/adorsys/datasafe/runtimedelegate/RuntimeDelegateGenerator.java index de84f7b85..45df3f70c 100644 --- a/datasafe-runtime-delegate/src/main/java/de/adorsys/datasafe/runtimedelegate/RuntimeDelegateGenerator.java +++ b/datasafe-runtime-delegate/src/main/java/de/adorsys/datasafe/runtimedelegate/RuntimeDelegateGenerator.java @@ -11,8 +11,8 @@ import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; import com.squareup.javapoet.TypeVariableName; +import jakarta.annotation.Generated; -import javax.annotation.Generated; import javax.annotation.Nullable; import javax.annotation.processing.Filer; import javax.lang.model.element.ElementKind; diff --git a/datasafe-runtime-delegate/src/main/java/de/adorsys/datasafe/runtimedelegate/RuntimeDelegateProcessor.java b/datasafe-runtime-delegate/src/main/java/de/adorsys/datasafe/runtimedelegate/RuntimeDelegateProcessor.java index 11643db98..4403d5c4f 100644 --- a/datasafe-runtime-delegate/src/main/java/de/adorsys/datasafe/runtimedelegate/RuntimeDelegateProcessor.java +++ b/datasafe-runtime-delegate/src/main/java/de/adorsys/datasafe/runtimedelegate/RuntimeDelegateProcessor.java @@ -31,7 +31,7 @@ * there is nothing associated with annotated class in {@link OverridesRegistry} - it calls default implementation. */ @SupportedAnnotationTypes(ANNOTATION_CLASS) -@SupportedSourceVersion(SourceVersion.RELEASE_8) +@SupportedSourceVersion(SourceVersion.RELEASE_17) @AutoService(Processor.class) public class RuntimeDelegateProcessor extends AbstractProcessor { diff --git a/datasafe-runtime-delegate/src/test/resources/output/SimpleClassRuntimeDelegatable.java b/datasafe-runtime-delegate/src/test/resources/output/SimpleClassRuntimeDelegatable.java index 6dbdba2e3..141623da4 100644 --- a/datasafe-runtime-delegate/src/test/resources/output/SimpleClassRuntimeDelegatable.java +++ b/datasafe-runtime-delegate/src/test/resources/output/SimpleClassRuntimeDelegatable.java @@ -1,7 +1,7 @@ import de.adorsys.datasafe.types.api.context.overrides.OverridesRegistry; +import jakarta.annotation.Generated; import java.lang.Override; import java.util.function.Function; -import javax.annotation.Generated; import javax.annotation.Nullable; import javax.inject.Inject; diff --git a/datasafe-runtime-delegate/src/test/resources/output/SimpleClassWithGenericRuntimeDelegatable.java b/datasafe-runtime-delegate/src/test/resources/output/SimpleClassWithGenericRuntimeDelegatable.java index b045c7aee..568374d8e 100644 --- a/datasafe-runtime-delegate/src/test/resources/output/SimpleClassWithGenericRuntimeDelegatable.java +++ b/datasafe-runtime-delegate/src/test/resources/output/SimpleClassWithGenericRuntimeDelegatable.java @@ -1,8 +1,8 @@ import de.adorsys.datasafe.types.api.context.overrides.OverridesRegistry; +import jakarta.annotation.Generated; import java.lang.Override; import java.util.List; import java.util.function.Function; -import javax.annotation.Generated; import javax.annotation.Nullable; import javax.inject.Inject; diff --git a/datasafe-runtime-delegate/src/test/resources/output/SimpleClassWithVoidRuntimeDelegatable.java b/datasafe-runtime-delegate/src/test/resources/output/SimpleClassWithVoidRuntimeDelegatable.java index 77f34e5c9..43c954e5c 100644 --- a/datasafe-runtime-delegate/src/test/resources/output/SimpleClassWithVoidRuntimeDelegatable.java +++ b/datasafe-runtime-delegate/src/test/resources/output/SimpleClassWithVoidRuntimeDelegatable.java @@ -1,7 +1,7 @@ import de.adorsys.datasafe.types.api.context.overrides.OverridesRegistry; +import jakarta.annotation.Generated; import java.lang.Override; import java.util.function.Function; -import javax.annotation.Generated; import javax.annotation.Nullable; import javax.inject.Inject; diff --git a/datasafe-simple-adapter/datasafe-simple-adapter-api/pom.xml b/datasafe-simple-adapter/datasafe-simple-adapter-api/pom.xml index e4a7850f4..ce7de7d73 100644 --- a/datasafe-simple-adapter/datasafe-simple-adapter-api/pom.xml +++ b/datasafe-simple-adapter/datasafe-simple-adapter-api/pom.xml @@ -36,7 +36,7 @@ org.junit.jupiter junit-jupiter-api - 5.4.1 + ${jupiter.version} test
diff --git a/datasafe-simple-adapter/datasafe-simple-adapter-impl/pom.xml b/datasafe-simple-adapter/datasafe-simple-adapter-impl/pom.xml index 3f5baf778..1403a9c23 100644 --- a/datasafe-simple-adapter/datasafe-simple-adapter-impl/pom.xml +++ b/datasafe-simple-adapter/datasafe-simple-adapter-impl/pom.xml @@ -72,11 +72,6 @@ assertj-core test - - org.junit.platform - junit-platform-commons - test - diff --git a/datasafe-simple-adapter/datasafe-simple-adapter-spring/pom.xml b/datasafe-simple-adapter/datasafe-simple-adapter-spring/pom.xml index 61ef0deb5..929d787d3 100644 --- a/datasafe-simple-adapter/datasafe-simple-adapter-spring/pom.xml +++ b/datasafe-simple-adapter/datasafe-simple-adapter-spring/pom.xml @@ -74,8 +74,19 @@ org.springframework.boot spring-boot-starter-test ${spring.framework.boot.version} + + + org.springframework.boot + spring-boot-starter-logging + + test + + org.yaml + snakeyaml + 2.1 + org.junit.jupiter junit-jupiter-api @@ -117,7 +128,10 @@ ${project.version} test - + + jakarta.annotation + jakarta.annotation-api + diff --git a/datasafe-simple-adapter/datasafe-simple-adapter-spring/src/main/java/de/adorsys/datasafe/simple/adapter/spring/factory/SpringSimpleDatasafeServiceFactory.java b/datasafe-simple-adapter/datasafe-simple-adapter-spring/src/main/java/de/adorsys/datasafe/simple/adapter/spring/factory/SpringSimpleDatasafeServiceFactory.java index 064d3208a..97ecd5721 100644 --- a/datasafe-simple-adapter/datasafe-simple-adapter-spring/src/main/java/de/adorsys/datasafe/simple/adapter/spring/factory/SpringSimpleDatasafeServiceFactory.java +++ b/datasafe-simple-adapter/datasafe-simple-adapter-spring/src/main/java/de/adorsys/datasafe/simple/adapter/spring/factory/SpringSimpleDatasafeServiceFactory.java @@ -9,11 +9,10 @@ import de.adorsys.datasafe.simple.adapter.impl.SimpleDatasafeServiceImpl; import de.adorsys.datasafe.simple.adapter.impl.config.PathEncryptionConfig; import de.adorsys.datasafe.simple.adapter.spring.properties.SpringDatasafeEncryptionProperties; +import jakarta.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; -import javax.annotation.PostConstruct; - @Slf4j public class SpringSimpleDatasafeServiceFactory { diff --git a/datasafe-storage/datasafe-storage-impl-db/pom.xml b/datasafe-storage/datasafe-storage-impl-db/pom.xml index 92c3dfa08..e11d5ec26 100644 --- a/datasafe-storage/datasafe-storage-impl-db/pom.xml +++ b/datasafe-storage/datasafe-storage-impl-db/pom.xml @@ -38,6 +38,7 @@ com.google.guava guava + test org.projectlombok @@ -46,12 +47,6 @@ org.liquibase liquibase-core - - - ch.qos.logback - logback-classic - - diff --git a/datasafe-storage/datasafe-storage-impl-db/src/main/java/de/adorsys/datasafe/storage/impl/db/DatabaseStorageService.java b/datasafe-storage/datasafe-storage-impl-db/src/main/java/de/adorsys/datasafe/storage/impl/db/DatabaseStorageService.java index bb2d6de9b..45df5173e 100644 --- a/datasafe-storage/datasafe-storage-impl-db/src/main/java/de/adorsys/datasafe/storage/impl/db/DatabaseStorageService.java +++ b/datasafe-storage/datasafe-storage-impl-db/src/main/java/de/adorsys/datasafe/storage/impl/db/DatabaseStorageService.java @@ -56,7 +56,7 @@ public class DatabaseStorageService implements StorageService { @Override public boolean objectExists(AbsoluteLocation location) { ParsedLocation parsed = new ParsedLocation(location, allowedTables); - String sql = "SELECT COUNT(*) FROM " + parsed.getTableName() + " WHERE `key` = ?"; + String sql = "SELECT COUNT(*) FROM " + parsed.getTableName() + " WHERE \"key\" = ?"; return 0 != conn.jdbcTemplate(location).queryForObject(sql, Integer.class, parsed.getPathWithUser()); } @@ -64,7 +64,7 @@ public boolean objectExists(AbsoluteLocation location) { @Override public Stream> list(AbsoluteLocation location) { ParsedLocation parsed = new ParsedLocation(location, allowedTables); - String sql = "SELECT `key`,`last_modified` FROM " + parsed.getTableName() + " WHERE `key` LIKE '" + String sql = "SELECT \"key\",`last_modified` FROM " + parsed.getTableName() + " WHERE \"key\" LIKE '" + parsed.getPathWithUser() + "%'"; List> keys = conn.jdbcTemplate(location).queryForList(sql); @@ -80,7 +80,7 @@ public Stream> list(AbsoluteLocation location @Override public InputStream read(AbsoluteLocation location) { ParsedLocation parsed = new ParsedLocation(location, allowedTables); - final String sql = "SELECT value FROM " + parsed.getTableName() + " WHERE `key` = ?"; + final String sql = "SELECT \"value\" FROM " + parsed.getTableName() + " WHERE \"key\" = ?"; RowMapper rowMapper = (rs, i) -> rs.getClob("value").getAsciiStream(); List values = conn.jdbcTemplate(location).query( sql, @@ -98,7 +98,7 @@ public InputStream read(AbsoluteLocation location) { @Override public void remove(AbsoluteLocation location) { ParsedLocation parsed = new ParsedLocation(location, allowedTables); - String sql = "DELETE FROM " + parsed.getTableName() + " WHERE `key` = ?"; + String sql = "DELETE FROM " + parsed.getTableName() + " WHERE \"key\" = ?"; conn.jdbcTemplate(location).update(sql, parsed.getPathWithUser()); } @@ -138,7 +138,7 @@ private static final class PutBlobOnClose extends ByteArrayOutputStream { @Override public void close() throws IOException { - String sql = "INSERT INTO " + tableName + " (`key`, `value`) VALUES(?, ?)"; + String sql = "INSERT INTO " + tableName + " (\"key\", \"value\") VALUES(?, ?)"; KeyHolder holder = new GeneratedKeyHolder(); jdbcTemplate.update(writeData(sql), holder); super.close(); diff --git a/datasafe-storage/datasafe-storage-impl-s3/pom.xml b/datasafe-storage/datasafe-storage-impl-s3/pom.xml index c4b73ac1e..7dc009810 100644 --- a/datasafe-storage/datasafe-storage-impl-s3/pom.xml +++ b/datasafe-storage/datasafe-storage-impl-s3/pom.xml @@ -33,7 +33,10 @@ com.amazonaws aws-java-sdk-core - + + javax.xml.bind + jaxb-api + org.slf4j 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..c4544d1c7 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 @@ -13,16 +13,19 @@ */ public abstract class BaseMockitoTest { + public AutoCloseable openMocks; + @BeforeEach public void setup() { + openMocks = MockitoAnnotations.openMocks(this); System.setProperty("SECURE_LOGS", "off"); System.setProperty("SECURE_SENSITIVE", "off"); - MockitoAnnotations.initMocks(this); } @AfterEach - public void validate() { + public void validate() throws Exception { Mockito.validateMockitoUsage(); + openMocks.close(); } @AfterAll diff --git a/last-module-codecoverage-check/pom.xml b/last-module-codecoverage-check/pom.xml index 9abff3f6e..460582e2c 100644 --- a/last-module-codecoverage-check/pom.xml +++ b/last-module-codecoverage-check/pom.xml @@ -144,7 +144,7 @@ maven-resources-plugin - 2.7 + 3.3.1 package diff --git a/pom.xml b/pom.xml index 42cccbd63..a184a64bc 100644 --- a/pom.xml +++ b/pom.xml @@ -78,50 +78,50 @@ ${basedir}/../../target/jacoco.exec ${basedir}/../target/jacoco-e2e.exec - 1.8 19.2.0 - 3.7.0 - 3.1.1 - 1.18.6 - 2.8.5 - 2.24 - 27.0.1-jre + 3.11.0 + 17 + 17 + 3.6.0 + 1.18.28 + 2.8.9 + 2.46.1 + 32.1.1-jre 4.0.3 - 5.4.1 - 1.4.1 + 5.10.0 3.12.2 - 2.25.1 + 5.5.0 2.22.1 1.21 UTF-8 false - 1.8 - 1.8 - 1.11.2 - 0.8.4 + 1.18.3 + 0.8.10 2.5 - 1.7.25 + 2.0.7 6.5.0.Final - 1.18.6.0 + 1.18.20.0 3.0.0 1.0.2 - 1.11.538 + 1.12.402 3.0.0 1 1.9.0 1.0-rc4 - 0.18 - 3.1.0 - 5.1.8.RELEASE + 0.21.0 + 3.3.0 3.3.1 - 1.4.199 - 8.0.16 - 3.6.1 - 5.1.7.RELEASE - 2.1.5.RELEASE - 1.3.1 - 2.11.2 - 0.0.6 + 2.2.220 + 8.1.0 + 4.23.1 + 6.0.11 + 3.1.2 + 1.4.4 + 2.12.7 + 2.12.7.1 + 0.0.7 + 2.1.1 + 2.3.1 @@ -195,6 +195,11 @@ javax.inject ${javax-inject.version} + + jakarta.annotation + jakarta.annotation-api + ${jakarta.annotation-api.varsion} + com.squareup javapoet @@ -251,12 +256,6 @@ ${jupiter.version} test - - org.junit.platform - junit-platform-commons - ${junit.platform.version} - test - org.assertj assertj-core @@ -274,6 +273,12 @@ testcontainers ${testcontainers.version} test + + + com.fasterxml.jackson.core + jackson-annotations + + org.apache.commons @@ -313,13 +318,18 @@ org.springframework spring-jdbc - ${spring.jdbc} + ${spring.framework.version} com.zaxxer HikariCP ${hikari.cp} + + javax.xml.bind + jaxb-api + ${jaxb-api.version} + @@ -359,7 +369,24 @@ maven-surefire-plugin ${surefire.version} - ${surefireArgLine} + + ${surefireArgLine}, + --add-opens java.base/java.lang=ALL-UNNAMED, + + --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED, + --add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED, + + --add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED, + --add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED, + --add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED, + --add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED, + --add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED, + --add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED, + --add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED, + --add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED, + --add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED, + --add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED + @@ -372,7 +399,7 @@ analyze-only - true + false true javax.inject:javax.inject @@ -384,6 +411,24 @@ org.mockito:mockito-core de.adorsys:datasafe-runtime-delegate + + org.bouncycastle:bcprov-jdk15on + org.slf4j:slf4j-api:jar + org.projectlombok:lombok + de.adorsys:datasafe-business + de.adorsys:datasafe-simple-adapter-impl + de.adorsys:datasafe-types-api + de.adorsys:datasafe-storage-api + de.adorsys:datasafe-encryption-api + de.adorsys:datasafe-directory-impl + de.adorsys:datasafe-inbox-api + de.adorsys:datasafe-privatestore-api + de.adorsys:datasafe-directory-api + de.adorsys:datasafe-simple-adapter-api + com.google.guava:guava + com.google.code.gson:gson + de.adorsys.keymanagement:juggler-bouncycastle +