diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-mongo/build.gradle b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-mongo/build.gradle new file mode 100644 index 00000000000..5ef53bdca3d --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-mongo/build.gradle @@ -0,0 +1,20 @@ +plugins { + id "java" + id "org.springframework.boot.conventions" +} + +description = "Spring Boot Session WebFlux MongoDB smoke test" + +dependencies { + implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-security")) + implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-webflux")) + + runtimeOnly(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-data-mongodb-reactive")) + runtimeOnly("org.springframework.session:spring-session-data-mongodb") + + testImplementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-test")) + testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support")) + testImplementation("org.testcontainers:mongodb") + testImplementation("org.testcontainers:testcontainers") + testImplementation("org.testcontainers:junit-jupiter") +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux/src/main/java/smoketest/session/HelloRestController.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-mongo/src/main/java/smoketest/session/HelloRestController.java similarity index 94% rename from spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux/src/main/java/smoketest/session/HelloRestController.java rename to spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-mongo/src/main/java/smoketest/session/HelloRestController.java index 93701349b1d..ddf78a81c44 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux/src/main/java/smoketest/session/HelloRestController.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-mongo/src/main/java/smoketest/session/HelloRestController.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux/src/main/java/smoketest/session/SampleSessionWebFluxApplication.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-mongo/src/main/java/smoketest/session/SampleSessionWebFluxMongoApplication.java similarity index 89% rename from spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux/src/main/java/smoketest/session/SampleSessionWebFluxApplication.java rename to spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-mongo/src/main/java/smoketest/session/SampleSessionWebFluxMongoApplication.java index cdd226272e1..405e9a85e29 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux/src/main/java/smoketest/session/SampleSessionWebFluxApplication.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-mongo/src/main/java/smoketest/session/SampleSessionWebFluxMongoApplication.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,10 +24,10 @@ import org.springframework.security.web.server.SecurityWebFilterChain; import org.springframework.security.web.server.context.WebSessionServerSecurityContextRepository; @SpringBootApplication -public class SampleSessionWebFluxApplication { +public class SampleSessionWebFluxMongoApplication { public static void main(String[] args) { - SpringApplication.run(SampleSessionWebFluxApplication.class); + SpringApplication.run(SampleSessionWebFluxMongoApplication.class); } @Bean diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux/src/main/resources/application.properties b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-mongo/src/main/resources/application.properties similarity index 64% rename from spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux/src/main/resources/application.properties rename to spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-mongo/src/main/resources/application.properties index c2627bb342c..e548561d4a9 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux/src/main/resources/application.properties +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-mongo/src/main/resources/application.properties @@ -1,3 +1,2 @@ spring.security.user.name=user spring.security.user.password=password -spring.mongodb.embedded.version=3.5.5 diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-mongo/src/test/java/smoketest/session/SampleSessionWebFluxMongoApplicationTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-mongo/src/test/java/smoketest/session/SampleSessionWebFluxMongoApplicationTests.java new file mode 100644 index 00000000000..07f26347717 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-mongo/src/test/java/smoketest/session/SampleSessionWebFluxMongoApplicationTests.java @@ -0,0 +1,90 @@ +/* + * Copyright 2012-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package smoketest.session; + +import java.time.Duration; +import java.util.Base64; + +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.MongoDBContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import reactor.util.function.Tuples; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.testsupport.testcontainers.DockerImageNames; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.http.HttpStatus; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.springframework.web.reactive.function.client.WebClient; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Integration tests for {@link SampleSessionWebFluxMongoApplication}. + * + * @author Vedran Pavic + * @author Scott Frederick + */ +@SpringBootTest(properties = "spring.session.timeout:10", webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@Testcontainers(disabledWithoutDocker = true) +class SampleSessionWebFluxMongoApplicationTests { + + @Container + private static final MongoDBContainer mongo = new MongoDBContainer(DockerImageNames.mongo()).withStartupAttempts(3) + .withStartupTimeout(Duration.ofMinutes(2)); + + @LocalServerPort + private int port; + + @Autowired + private WebClient.Builder webClientBuilder; + + @DynamicPropertySource + static void applicationProperties(DynamicPropertyRegistry registry) { + registry.add("spring.data.mongodb.uri", mongo::getReplicaSetUrl); + } + + @Test + void userDefinedMappingsSecureByDefault() { + WebClient client = this.webClientBuilder.baseUrl("http://localhost:" + this.port + "/").build(); + client.get().header("Authorization", getBasicAuth()).exchangeToMono((response) -> { + assertThat(response.statusCode()).isEqualTo(HttpStatus.OK); + return response.bodyToMono(String.class) + .map((sessionId) -> Tuples.of(response.cookies().getFirst("SESSION").getValue(), sessionId)); + }).flatMap((tuple) -> { + String sessionCookie = tuple.getT1(); + return client.get().cookie("SESSION", sessionCookie).exchangeToMono((response) -> { + assertThat(response.statusCode()).isEqualTo(HttpStatus.OK); + return response.bodyToMono(String.class) + .doOnNext((sessionId) -> assertThat(sessionId).isEqualTo(tuple.getT2())) + .thenReturn(sessionCookie); + }); + }).delayElement(Duration.ofSeconds(10)) + .flatMap((sessionCookie) -> client.get().cookie("SESSION", sessionCookie).exchangeToMono((response) -> { + assertThat(response.statusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); + return response.releaseBody(); + })).block(Duration.ofSeconds(30)); + } + + private String getBasicAuth() { + return "Basic " + Base64.getEncoder().encodeToString("user:password".getBytes()); + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-redis/build.gradle b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-redis/build.gradle new file mode 100644 index 00000000000..488e0342466 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-redis/build.gradle @@ -0,0 +1,19 @@ +plugins { + id "java" + id "org.springframework.boot.conventions" +} + +description = "Spring Boot Session WebFlux Redis smoke test" + +dependencies { + implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-security")) + implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-webflux")) + + runtimeOnly(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-data-redis-reactive")) + runtimeOnly("org.springframework.session:spring-session-data-redis") + + testImplementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-test")) + testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support")) + testImplementation("org.testcontainers:testcontainers") + testImplementation("org.testcontainers:junit-jupiter") +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-redis/src/main/java/smoketest/session/HelloRestController.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-redis/src/main/java/smoketest/session/HelloRestController.java new file mode 100644 index 00000000000..ddf78a81c44 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-redis/src/main/java/smoketest/session/HelloRestController.java @@ -0,0 +1,31 @@ +/* + * Copyright 2012-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package smoketest.session; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.WebSession; + +@RestController +public class HelloRestController { + + @GetMapping("/") + String sessionId(WebSession session) { + return session.getId(); + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-redis/src/main/java/smoketest/session/SampleSessionWebFluxRedisApplication.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-redis/src/main/java/smoketest/session/SampleSessionWebFluxRedisApplication.java new file mode 100644 index 00000000000..4ebfaf48b86 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-redis/src/main/java/smoketest/session/SampleSessionWebFluxRedisApplication.java @@ -0,0 +1,48 @@ +/* + * Copyright 2012-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package smoketest.session; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.web.server.SecurityWebFilterChain; +import org.springframework.security.web.server.context.WebSessionServerSecurityContextRepository; + +@SpringBootApplication +public class SampleSessionWebFluxRedisApplication { + + public static void main(String[] args) { + SpringApplication.run(SampleSessionWebFluxRedisApplication.class); + } + + @Bean + public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { + // @formatter:off + return http + .authorizeExchange() + .anyExchange().authenticated() + .and() + .httpBasic().securityContextRepository(new WebSessionServerSecurityContextRepository()) + .and() + .formLogin() + .and() + .build(); + // @formatter:on + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-redis/src/main/resources/application.properties b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-redis/src/main/resources/application.properties new file mode 100644 index 00000000000..e548561d4a9 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-redis/src/main/resources/application.properties @@ -0,0 +1,2 @@ +spring.security.user.name=user +spring.security.user.password=password diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux/src/test/java/smoketest/session/SampleSessionWebFluxApplicationTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-redis/src/test/java/smoketest/session/SampleSessionWebFluxRedisApplicationTests.java similarity index 76% rename from spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux/src/test/java/smoketest/session/SampleSessionWebFluxApplicationTests.java rename to spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-redis/src/test/java/smoketest/session/SampleSessionWebFluxRedisApplicationTests.java index 66db6ac92ed..4f50256a772 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux/src/test/java/smoketest/session/SampleSessionWebFluxApplicationTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux-redis/src/test/java/smoketest/session/SampleSessionWebFluxRedisApplicationTests.java @@ -20,27 +20,33 @@ import java.time.Duration; import java.util.Base64; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.OS; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; import reactor.util.function.Tuples; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.testsupport.junit.DisabledOnOs; +import org.springframework.boot.testsupport.testcontainers.RedisContainer; import org.springframework.boot.web.server.LocalServerPort; import org.springframework.http.HttpStatus; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; import org.springframework.web.reactive.function.client.WebClient; import static org.assertj.core.api.Assertions.assertThat; /** - * Integration tests for {@link SampleSessionWebFluxApplication}. + * Integration tests for {@link SampleSessionWebFluxRedisApplication}. * * @author Vedran Pavic + * @author Scott Frederick */ @SpringBootTest(properties = "spring.session.timeout:10", webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@DisabledOnOs(os = OS.LINUX, architecture = "aarch64", - disabledReason = "Embedded Mongo doesn't support Linux aarch64, see https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo/issues/379") -class SampleSessionWebFluxApplicationTests { +@Testcontainers(disabledWithoutDocker = true) +class SampleSessionWebFluxRedisApplicationTests { + + @Container + private static final RedisContainer redis = new RedisContainer(); @LocalServerPort private int port; @@ -48,6 +54,12 @@ class SampleSessionWebFluxApplicationTests { @Autowired private WebClient.Builder webClientBuilder; + @DynamicPropertySource + static void applicationProperties(DynamicPropertyRegistry registry) { + registry.add("spring.redis.host", redis::getHost); + registry.add("spring.redis.port", redis::getFirstMappedPort); + } + @Test void userDefinedMappingsSecureByDefault() { WebClient client = this.webClientBuilder.baseUrl("http://localhost:" + this.port + "/").build(); diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux/build.gradle b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux/build.gradle deleted file mode 100644 index 34a18993ffc..00000000000 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-session-webflux/build.gradle +++ /dev/null @@ -1,28 +0,0 @@ -plugins { - id "java" - id "org.springframework.boot.conventions" -} - -description = "Spring Boot Session WebFlux smoke test" - -def sessionStores = [ - "mongodb": [ - project(":spring-boot-project:spring-boot-starters:spring-boot-starter-data-mongodb-reactive"), - "de.flapdoodle.embed:de.flapdoodle.embed.mongo", - "org.springframework.session:spring-session-data-mongodb" - ], - "redis": [ - project(":spring-boot-project:spring-boot-starters:spring-boot-starter-data-redis-reactive"), - "org.springframework.session:spring-session-data-redis" - ] -] - -dependencies { - implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-security")) - implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-webflux")) - - sessionStores[project.findProperty("sessionStore") ?: "mongodb"].each { runtimeOnly it } - - testImplementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-test")) - testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support")) -}