From d52a321ca1cb149b75f9dd8727db083a509e01ac Mon Sep 17 00:00:00 2001 From: HellySamael Date: Sat, 14 Sep 2024 20:11:23 +0200 Subject: [PATCH] :arrow_up: upgrade spring dependencies and adapt code --- server/build.gradle.kts | 1 - server/zally-core/build.gradle.kts | 3 +- server/zally-server/build.gradle.kts | 13 +++--- .../zally/apireview/ApiDefinitionReader.kt | 2 +- .../org/zalando/zally/apireview/ApiReview.kt | 23 ++++------ .../zally/apireview/ApiReviewRepository.kt | 4 +- .../apireview/ApiViolationsController.kt | 2 +- .../zalando/zally/apireview/RuleViolation.kt | 16 +++---- .../configuration/NoSecurityConfiguration.kt | 23 ++++++---- .../zally/configuration/OAuthConfiguration.kt | 42 ++++++++++--------- .../zally/exception/ExceptionHandling.kt | 12 +++--- .../statistic/ReviewStatisticsController.kt | 4 +- .../src/main/resources/application-dev.yml | 8 ++-- .../src/main/resources/application.yml | 2 +- .../zally/apireview/RestCorsWithOAuthTest.kt | 9 ++-- .../zally/configuration/PathMatchersTest.kt | 2 +- .../org/zalando/zally/util/JadlerUtil.kt | 4 +- 17 files changed, 88 insertions(+), 82 deletions(-) diff --git a/server/build.gradle.kts b/server/build.gradle.kts index 94412b34f..97e7a3433 100644 --- a/server/build.gradle.kts +++ b/server/build.gradle.kts @@ -161,7 +161,6 @@ subprojects { implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.1") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.14.1") implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.1") - implementation("org.yaml:snakeyaml:1.33") testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.9.1") testImplementation("com.jayway.jsonpath:json-path-assert:2.7.0") diff --git a/server/zally-core/build.gradle.kts b/server/zally-core/build.gradle.kts index 4372f8f0a..bdc1cd19b 100644 --- a/server/zally-core/build.gradle.kts +++ b/server/zally-core/build.gradle.kts @@ -2,7 +2,8 @@ dependencies { kapt("com.google.auto.service:auto-service:1.0.1") api(project(":zally-rule-api")) - api("io.swagger.parser.v3:swagger-parser:2.1.12") + api("io.swagger.parser.v3:swagger-parser:2.1.16") + api("com.sun.mail:mailapi:1.6.2") api("io.github.config4k:config4k:0.5.0") implementation("com.google.auto.service:auto-service:1.0.1") diff --git a/server/zally-server/build.gradle.kts b/server/zally-server/build.gradle.kts index c4ac2f124..801316b2e 100644 --- a/server/zally-server/build.gradle.kts +++ b/server/zally-server/build.gradle.kts @@ -9,7 +9,7 @@ plugins { kotlin("plugin.spring") version kotlinVersion kotlin("plugin.allopen") version kotlinVersion - id("org.springframework.boot") version "2.7.7" + id("org.springframework.boot") version "3.3.3" } apply(plugin = "io.spring.dependency-management") @@ -28,14 +28,13 @@ dependencies { } implementation("org.flywaydb:flyway-core:9.11.0") implementation("org.hsqldb:hsqldb:2.7.1") - implementation("org.postgresql:postgresql:42.5.1") - implementation("org.hibernate:hibernate-core") - implementation("org.jadira.usertype:usertype.core:7.0.0.CR1") { - exclude("org.hibernate", "hibernate-entitymanager") - } + implementation("org.postgresql:postgresql:42.7.2") + implementation("org.hibernate.orm:hibernate-core") + implementation("org.zalando.stups:stups-spring-oauth2-server:1.0.24") implementation("org.zalando:problem:0.27.1") - implementation("org.zalando:problem-spring-web:0.27.0") + implementation("org.zalando:jackson-datatype-problem:0.27.1") + implementation("org.zalando:problem-spring-web:0.29.1") implementation("org.zalando:twintip-spring-web:1.2.0") testImplementation(project(":zally-test")) diff --git a/server/zally-server/src/main/kotlin/org/zalando/zally/apireview/ApiDefinitionReader.kt b/server/zally-server/src/main/kotlin/org/zalando/zally/apireview/ApiDefinitionReader.kt index b19980407..62d399a76 100644 --- a/server/zally-server/src/main/kotlin/org/zalando/zally/apireview/ApiDefinitionReader.kt +++ b/server/zally-server/src/main/kotlin/org/zalando/zally/apireview/ApiDefinitionReader.kt @@ -43,7 +43,7 @@ class ApiDefinitionReader(private val client: RestTemplate) { } catch (exception: HttpClientErrorException) { throw InaccessibleResourceUrlException( "${exception.message} while retrieving api definition url", - exception.statusCode + HttpStatus.valueOf(exception.statusCode.value()) ) } catch (exception: ResourceAccessException) { throw InaccessibleResourceUrlException( diff --git a/server/zally-server/src/main/kotlin/org/zalando/zally/apireview/ApiReview.kt b/server/zally-server/src/main/kotlin/org/zalando/zally/apireview/ApiReview.kt index 7fb0d46ef..d408411ea 100644 --- a/server/zally-server/src/main/kotlin/org/zalando/zally/apireview/ApiReview.kt +++ b/server/zally-server/src/main/kotlin/org/zalando/zally/apireview/ApiReview.kt @@ -1,7 +1,13 @@ package org.zalando.zally.apireview -import org.hibernate.annotations.Parameter -import org.hibernate.annotations.Type +import jakarta.persistence.CascadeType +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.FetchType +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import jakarta.persistence.OneToMany import org.zalando.zally.core.Result import org.zalando.zally.dto.ApiDefinitionRequest import org.zalando.zally.rule.api.Severity @@ -11,14 +17,6 @@ import java.time.LocalDate import java.time.OffsetDateTime import java.time.ZoneOffset import java.util.UUID -import javax.persistence.CascadeType -import javax.persistence.Column -import javax.persistence.Entity -import javax.persistence.FetchType -import javax.persistence.GeneratedValue -import javax.persistence.GenerationType -import javax.persistence.Id -import javax.persistence.OneToMany @Suppress("unused") @Entity @@ -29,10 +27,7 @@ class ApiReview( violations: List = emptyList(), val name: String? = OpenApiHelper.extractApiName(apiDefinition), val apiId: String? = OpenApiHelper.extractApiId(apiDefinition), - @Type( - type = "org.jadira.usertype.dateandtime.threeten.PersistentOffsetDateTime", - parameters = [Parameter(name = "javaZone", value = "UTC")] - ) + @Column(nullable = false) val created: OffsetDateTime = Instant.now().atOffset(ZoneOffset.UTC), @Column(nullable = false) diff --git a/server/zally-server/src/main/kotlin/org/zalando/zally/apireview/ApiReviewRepository.kt b/server/zally-server/src/main/kotlin/org/zalando/zally/apireview/ApiReviewRepository.kt index fac4fb471..c5a3c3b2f 100644 --- a/server/zally-server/src/main/kotlin/org/zalando/zally/apireview/ApiReviewRepository.kt +++ b/server/zally-server/src/main/kotlin/org/zalando/zally/apireview/ApiReviewRepository.kt @@ -14,14 +14,14 @@ interface ApiReviewRepository : CrudRepository { SELECT new org.zalando.zally.statistic.ReviewStatistics( COUNT(r) AS totalReviews, COUNT(DISTINCT r.name) AS totalReviewDeduplicated, - COALESCE(SUM(CASE WHEN r.isSuccessfulProcessed = 'True' THEN 1 ELSE 0 END),0) AS successfulReviews, + COALESCE(SUM(CASE WHEN r.isSuccessfulProcessed = true THEN 1 ELSE 0 END),0) AS successfulReviews, COALESCE(SUM(r.numberOfEndpoints),0) AS numberOfEndpoints, COALESCE(SUM(r.mustViolations),0) AS mustViolations, COALESCE(SUM(r.shouldViolations),0) AS shouldViolations, COALESCE(SUM(r.mayViolations),0) AS mayViolations, COALESCE(SUM(r.hintViolations),0) AS hintViolations) FROM org.zalando.zally.apireview.ApiReview r - WHERE day >= :from AND day <= :to AND user_agent LIKE :userAgent + WHERE day >= :from AND day <= :to AND userAgent LIKE :userAgent """ ) fun getReviewStatistics( diff --git a/server/zally-server/src/main/kotlin/org/zalando/zally/apireview/ApiViolationsController.kt b/server/zally-server/src/main/kotlin/org/zalando/zally/apireview/ApiViolationsController.kt index e41fee73f..89c2c1b4c 100644 --- a/server/zally-server/src/main/kotlin/org/zalando/zally/apireview/ApiViolationsController.kt +++ b/server/zally-server/src/main/kotlin/org/zalando/zally/apireview/ApiViolationsController.kt @@ -62,7 +62,7 @@ class ApiViolationsController( @ResponseBody @GetMapping("/api-violations/{externalId}") fun getExistingViolationResponse( - @PathVariable(value = "externalId") externalId: UUID + @PathVariable externalId: UUID ): ApiDefinitionResponse { val review = apiReviewRepository.findByExternalId(externalId) ?: throw ApiReviewNotFoundException() diff --git a/server/zally-server/src/main/kotlin/org/zalando/zally/apireview/RuleViolation.kt b/server/zally-server/src/main/kotlin/org/zalando/zally/apireview/RuleViolation.kt index 70074aa86..fc39b7ced 100644 --- a/server/zally-server/src/main/kotlin/org/zalando/zally/apireview/RuleViolation.kt +++ b/server/zally-server/src/main/kotlin/org/zalando/zally/apireview/RuleViolation.kt @@ -1,17 +1,17 @@ package org.zalando.zally.apireview import com.fasterxml.jackson.annotation.JsonIgnore +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.EnumType +import jakarta.persistence.Enumerated +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import jakarta.persistence.ManyToOne import org.zalando.zally.core.Result import org.zalando.zally.rule.api.Severity import java.io.Serializable -import javax.persistence.Column -import javax.persistence.Entity -import javax.persistence.EnumType -import javax.persistence.Enumerated -import javax.persistence.GeneratedValue -import javax.persistence.GenerationType -import javax.persistence.Id -import javax.persistence.ManyToOne @Entity class RuleViolation( diff --git a/server/zally-server/src/main/kotlin/org/zalando/zally/configuration/NoSecurityConfiguration.kt b/server/zally-server/src/main/kotlin/org/zalando/zally/configuration/NoSecurityConfiguration.kt index 5238d1349..58d78b722 100644 --- a/server/zally-server/src/main/kotlin/org/zalando/zally/configuration/NoSecurityConfiguration.kt +++ b/server/zally-server/src/main/kotlin/org/zalando/zally/configuration/NoSecurityConfiguration.kt @@ -1,18 +1,27 @@ package org.zalando.zally.configuration +import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.context.annotation.Profile import org.springframework.security.config.annotation.web.builders.HttpSecurity -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity +import org.springframework.security.web.SecurityFilterChain @Profile("dev", "test") @Configuration -class NoSecurityConfiguration : WebSecurityConfigurerAdapter() { +@EnableWebSecurity +class NoSecurityConfiguration { - @Throws(Exception::class) - override fun configure(http: HttpSecurity) { - http.httpBasic().disable() - .csrf().disable() - .authorizeRequests().antMatchers("/**").permitAll() + @Bean + fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { + http + .httpBasic { basic -> basic.disable() } + .csrf { csrf -> csrf.disable() } + .authorizeHttpRequests { requests -> + requests + .requestMatchers("/**").permitAll() + } + + return http.build() } } diff --git a/server/zally-server/src/main/kotlin/org/zalando/zally/configuration/OAuthConfiguration.kt b/server/zally-server/src/main/kotlin/org/zalando/zally/configuration/OAuthConfiguration.kt index 2c9277597..7f394b2f6 100644 --- a/server/zally-server/src/main/kotlin/org/zalando/zally/configuration/OAuthConfiguration.kt +++ b/server/zally-server/src/main/kotlin/org/zalando/zally/configuration/OAuthConfiguration.kt @@ -37,28 +37,30 @@ class OAuthConfiguration : ResourceServerConfigurerAdapter() { @Throws(Exception::class) override fun configure(http: HttpSecurity) { http - .httpBasic().disable() - .requestMatchers().antMatchers("/**") - .and() - .sessionManagement() - .sessionCreationPolicy(SessionCreationPolicy.NEVER) - .and() - .authorizeRequests() - .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() - .regexMatchers("/health/?").permitAll() - .regexMatchers( - "/metrics/?(\\?.*)?", - "/api-violations/?([a-z0-9-]+/?)?(\\?)?", - "/supported-rules/?(\\?.*)?", - "/review-statistics/?(\\?.*)?" - ) - .access("#oauth2.hasScope('uid')") - .antMatchers("**").denyAll() + .authorizeHttpRequests { it.requestMatchers("/**") } + .httpBasic { it.disable() } + .sessionManagement { + it.sessionCreationPolicy(SessionCreationPolicy.NEVER) + } + .authorizeHttpRequests { + it.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() + .requestMatchers("/health/?").permitAll() + .requestMatchers( + "/metrics/?(\\?.*)?", + "/api-violations/?([a-z0-9-]+/?)?(\\?)?", + "/supported-rules/?(\\?.*)?", + "/review-statistics/?(\\?.*)?" + ) + .hasAuthority("SCOPE_uid") + .anyRequest().denyAll() + } http - .exceptionHandling() - .authenticationEntryPoint(problemSupport) - .accessDeniedHandler(problemSupport) + .exceptionHandling { handling -> + handling + .authenticationEntryPoint(problemSupport) + .accessDeniedHandler(problemSupport) + } } @Bean diff --git a/server/zally-server/src/main/kotlin/org/zalando/zally/exception/ExceptionHandling.kt b/server/zally-server/src/main/kotlin/org/zalando/zally/exception/ExceptionHandling.kt index caed4afb3..b7517faca 100644 --- a/server/zally-server/src/main/kotlin/org/zalando/zally/exception/ExceptionHandling.kt +++ b/server/zally-server/src/main/kotlin/org/zalando/zally/exception/ExceptionHandling.kt @@ -12,7 +12,7 @@ import org.zalando.problem.spring.web.advice.SpringAdviceTrait @ControllerAdvice class ExceptionHandling : ProblemHandling, SpringAdviceTrait { - @ExceptionHandler + @ExceptionHandler(MissingApiDefinitionException::class) fun handleMissingApiDefinitionException( exception: MissingApiDefinitionException, request: NativeWebRequest @@ -20,7 +20,7 @@ class ExceptionHandling : ProblemHandling, SpringAdviceTrait { return create(HttpStatus.BAD_REQUEST, exception, request) } - @ExceptionHandler + @ExceptionHandler(InaccessibleResourceUrlException::class) fun handleUnaccessibleResourceUrlException( exception: InaccessibleResourceUrlException, request: NativeWebRequest @@ -28,16 +28,16 @@ class ExceptionHandling : ProblemHandling, SpringAdviceTrait { return create(exception.httpStatus, exception, request) } - @ExceptionHandler - fun handleUnsufficientTimeIntervalParameterException( + @ExceptionHandler(InsufficientTimeIntervalParameterException::class) + fun handleInsufficientTimeIntervalParameterException( exception: InsufficientTimeIntervalParameterException, request: NativeWebRequest ): ResponseEntity { return create(HttpStatus.BAD_REQUEST, exception, request) } - @ExceptionHandler - fun handleUnsufficientTimeIntervalParameterException( + @ExceptionHandler(TimeParameterIsInTheFutureException::class) + fun handleTimeParameterIsInTheFutureException( exception: TimeParameterIsInTheFutureException, request: NativeWebRequest ): ResponseEntity { diff --git a/server/zally-server/src/main/kotlin/org/zalando/zally/statistic/ReviewStatisticsController.kt b/server/zally-server/src/main/kotlin/org/zalando/zally/statistic/ReviewStatisticsController.kt index e164f63e4..cc06072b6 100644 --- a/server/zally-server/src/main/kotlin/org/zalando/zally/statistic/ReviewStatisticsController.kt +++ b/server/zally-server/src/main/kotlin/org/zalando/zally/statistic/ReviewStatisticsController.kt @@ -21,10 +21,10 @@ class ReviewStatisticsController(private val apiReviewRepository: ApiReviewRepos @ResponseBody @GetMapping("/review-statistics") fun retrieveReviewStatistics( - @RequestParam(value = "from", required = false) + @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) from: LocalDate?, - @RequestParam(value = "to", required = false) + @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) to: LocalDate?, @RequestParam(value = "user_agent", required = false) userAgent: String? diff --git a/server/zally-server/src/main/resources/application-dev.yml b/server/zally-server/src/main/resources/application-dev.yml index 43ab6f28e..4424c6576 100644 --- a/server/zally-server/src/main/resources/application-dev.yml +++ b/server/zally-server/src/main/resources/application-dev.yml @@ -1,9 +1,6 @@ + endpoints: - enabled: false - health: - enabled: true metrics: - enabled: true sensitive: false spring: @@ -28,3 +25,6 @@ zally: deprecatedCliAgents: unirest-java/1.3.11,Zally-CLI/1.0 TOKEN_INFO_URI: https://auth.example.com/oauth2/tokeninfo +management.endpoints.enabled-by-default: false +management.endpoint.health.enabled: true +management.endpoint.metrics.enabled: true diff --git a/server/zally-server/src/main/resources/application.yml b/server/zally-server/src/main/resources/application.yml index f31d1cd5d..8424c9234 100644 --- a/server/zally-server/src/main/resources/application.yml +++ b/server/zally-server/src/main/resources/application.yml @@ -43,5 +43,5 @@ zally: releasesPage: https://github.com/zalando/zally/releases deprecatedCliAgents: unirest-java/1.3.11,Zally-CLI/1.0 --- -spring.profiles: local +spring.config.activate.on-profile: local TOKEN_INFO_URI: https://auth.example.com/oauth2/tokeninfo diff --git a/server/zally-server/src/test/kotlin/org/zalando/zally/apireview/RestCorsWithOAuthTest.kt b/server/zally-server/src/test/kotlin/org/zalando/zally/apireview/RestCorsWithOAuthTest.kt index a4c0c43cb..7453e02e4 100644 --- a/server/zally-server/src/test/kotlin/org/zalando/zally/apireview/RestCorsWithOAuthTest.kt +++ b/server/zally-server/src/test/kotlin/org/zalando/zally/apireview/RestCorsWithOAuthTest.kt @@ -4,6 +4,7 @@ import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.springframework.http.HttpMethod import org.springframework.http.HttpStatus +import org.springframework.http.HttpStatusCode import org.springframework.http.RequestEntity import org.springframework.test.context.ActiveProfiles @@ -12,12 +13,12 @@ class RestCorsWithOAuthTest : RestApiBaseTest() { @Test fun shouldSupportCorsWhenOAuthIsEnabledOnAllResources() { - assertThat(optionsRequest(RestApiBaseTest.API_VIOLATIONS_URL)).isEqualTo(HttpStatus.OK) - assertThat(optionsRequest(RestApiBaseTest.SUPPORTED_RULES_URL)).isEqualTo(HttpStatus.OK) - assertThat(optionsRequest(RestApiBaseTest.REVIEW_STATISTICS_URL)).isEqualTo(HttpStatus.OK) + assertThat(optionsRequest(API_VIOLATIONS_URL)).isEqualTo(HttpStatus.OK) + assertThat(optionsRequest(SUPPORTED_RULES_URL)).isEqualTo(HttpStatus.OK) + assertThat(optionsRequest(REVIEW_STATISTICS_URL)).isEqualTo(HttpStatus.OK) } - private fun optionsRequest(url: String): HttpStatus { + private fun optionsRequest(url: String): HttpStatusCode { return restTemplate.exchange(url, HttpMethod.OPTIONS, RequestEntity.EMPTY, String::class.java).statusCode } } diff --git a/server/zally-server/src/test/kotlin/org/zalando/zally/configuration/PathMatchersTest.kt b/server/zally-server/src/test/kotlin/org/zalando/zally/configuration/PathMatchersTest.kt index 3307a0e6c..db3505b31 100644 --- a/server/zally-server/src/test/kotlin/org/zalando/zally/configuration/PathMatchersTest.kt +++ b/server/zally-server/src/test/kotlin/org/zalando/zally/configuration/PathMatchersTest.kt @@ -1,5 +1,6 @@ package org.zalando.zally.configuration +import jakarta.servlet.http.HttpServletRequest import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test @@ -7,7 +8,6 @@ import org.mockito.Mockito import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher import org.springframework.security.web.util.matcher.AntPathRequestMatcher import org.springframework.security.web.util.matcher.RegexRequestMatcher -import javax.servlet.http.HttpServletRequest /** * This serves as a reminder/documentation of how the matchers do work. diff --git a/server/zally-server/src/test/kotlin/org/zalando/zally/util/JadlerUtil.kt b/server/zally-server/src/test/kotlin/org/zalando/zally/util/JadlerUtil.kt index 57b109241..c7db79f2d 100644 --- a/server/zally-server/src/test/kotlin/org/zalando/zally/util/JadlerUtil.kt +++ b/server/zally-server/src/test/kotlin/org/zalando/zally/util/JadlerUtil.kt @@ -24,7 +24,7 @@ object JadlerUtil { val url = String.format("http://localhost:%d/%s", port(), resourceName) onRequest() - .havingMethodEqualTo(GET.name) + .havingMethodEqualTo(GET.name()) .havingPathEqualTo("/$resourceName") .respond() .withStatus(status) @@ -39,7 +39,7 @@ object JadlerUtil { val url = "http://localhost:" + port() + remotePath onRequest() - .havingMethodEqualTo(GET.name) + .havingMethodEqualTo(GET.name()) .havingPathEqualTo(remotePath) .respond() .withStatus(NOT_FOUND.value())