From 98e81ecbc6221a0681233779fa88fd544acbe390 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Vav=C5=99=C3=ADk?= Date: Sun, 28 May 2023 21:24:23 +0200 Subject: [PATCH] Security JPA Reactive - fix non-unique ex (cherry picked from commit 08c152def361fe8f96d72286e255cc7365807281) --- .../PanacheEntitiesConfigurationTest.java | 42 ++++++++++++++++ .../security/jpa/reactive/UserResource.java | 49 +++++++++++++++++++ .../resources/multiple-entities/import.sql | 10 ++-- .../runtime/JpaReactiveIdentityProvider.java | 2 +- .../JpaReactiveTrustedIdentityProvider.java | 2 +- 5 files changed, 98 insertions(+), 7 deletions(-) create mode 100644 extensions/security-jpa-reactive/deployment/src/test/java/io/quarkus/security/jpa/reactive/UserResource.java diff --git a/extensions/security-jpa-reactive/deployment/src/test/java/io/quarkus/security/jpa/reactive/PanacheEntitiesConfigurationTest.java b/extensions/security-jpa-reactive/deployment/src/test/java/io/quarkus/security/jpa/reactive/PanacheEntitiesConfigurationTest.java index 58755e00cac1c..e393f804d4bd3 100644 --- a/extensions/security-jpa-reactive/deployment/src/test/java/io/quarkus/security/jpa/reactive/PanacheEntitiesConfigurationTest.java +++ b/extensions/security-jpa-reactive/deployment/src/test/java/io/quarkus/security/jpa/reactive/PanacheEntitiesConfigurationTest.java @@ -1,18 +1,60 @@ package io.quarkus.security.jpa.reactive; +import static org.hamcrest.Matchers.is; + +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import io.quarkus.test.QuarkusUnitTest; +import io.restassured.RestAssured; +import io.restassured.response.ValidatableResponse; public class PanacheEntitiesConfigurationTest extends JpaSecurityRealmTest { + private static final String DUPLICATE_USERNAME = "merlin"; + @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() .withApplicationRoot((jar) -> jar .addClasses(testClasses) .addClass(PanacheUserEntity.class) .addClass(PanacheRoleEntity.class) + .addClass(UserResource.class) .addAsResource("multiple-entities/import.sql", "import.sql") .addAsResource("multiple-entities/application.properties", "application.properties")); + @Test + void duplicateUsernameTest() { + // duplicate username must lead to 401 + RestAssured.enableLoggingOfRequestAndResponseIfValidationFails(); + + // no user -> unauthenticated + getUsername().statusCode(401); + createUser(); + // one user + getUsername().statusCode(200).body(is(DUPLICATE_USERNAME)); + createUser(); + // two users -> NonUniqueResultException -> 401 + getUsername().statusCode(401); + } + + private static void createUser() { + RestAssured + .given() + .auth().preemptive().basic("user", "user") + .body(DUPLICATE_USERNAME) + .post("/jaxrs-secured/user") + .then() + .statusCode(201); + } + + private static ValidatableResponse getUsername() { + return RestAssured + .given() + .auth().preemptive().basic(DUPLICATE_USERNAME, DUPLICATE_USERNAME) + .body(DUPLICATE_USERNAME) + .get("/jaxrs-secured/user") + .then(); + } + } diff --git a/extensions/security-jpa-reactive/deployment/src/test/java/io/quarkus/security/jpa/reactive/UserResource.java b/extensions/security-jpa-reactive/deployment/src/test/java/io/quarkus/security/jpa/reactive/UserResource.java new file mode 100644 index 0000000000000..f901a7b13ff24 --- /dev/null +++ b/extensions/security-jpa-reactive/deployment/src/test/java/io/quarkus/security/jpa/reactive/UserResource.java @@ -0,0 +1,49 @@ +package io.quarkus.security.jpa.reactive; + +import static java.util.Objects.requireNonNull; + +import java.util.List; + +import jakarta.annotation.security.RolesAllowed; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.SecurityContext; + +import io.quarkus.hibernate.reactive.panache.common.WithTransaction; +import io.smallrye.mutiny.Uni; + +@RolesAllowed("user") +@Path("/user") +public class UserResource { + + @WithTransaction + @POST + public Uni createUser(String username) { + if (username == null || username.isBlank()) { + throw new IllegalStateException("Invalid username"); + } + + // create new user with role 'user' and do not validate whether username is unique + return PanacheRoleEntity + . find("role", "user") + .singleResult() + .flatMap(userRole -> { + PanacheUserEntity user = new PanacheUserEntity(); + user.name = username; + user.pass = username; + user.roles = List.of(userRole); + return user.persist(); + }) + .map(user -> Response.created(null).build()); + } + + @GET + public Uni getUsername(@Context SecurityContext sec) { + var principal = requireNonNull(sec.getUserPrincipal()); + return Uni.createFrom().item(principal.getName()); + } + +} diff --git a/extensions/security-jpa-reactive/deployment/src/test/resources/multiple-entities/import.sql b/extensions/security-jpa-reactive/deployment/src/test/resources/multiple-entities/import.sql index c66a7a488b249..475210c9cc382 100644 --- a/extensions/security-jpa-reactive/deployment/src/test/resources/multiple-entities/import.sql +++ b/extensions/security-jpa-reactive/deployment/src/test/resources/multiple-entities/import.sql @@ -1,9 +1,9 @@ -INSERT INTO test_user (id, username, password) VALUES (1, 'admin', 'admin'); -INSERT INTO test_user (id, username, password) VALUES (2, 'user','user'); -INSERT INTO test_user (id, username, password) VALUES (3, 'noRoleUser','noRoleUser'); +INSERT INTO test_user (id, username, password) VALUES (-1, 'admin', 'admin'); +INSERT INTO test_user (id, username, password) VALUES (-2, 'user','user'); +INSERT INTO test_user (id, username, password) VALUES (-3, 'noRoleUser','noRoleUser'); INSERT INTO test_role (id, role_name) VALUES (1, 'admin'); INSERT INTO test_role (id, role_name) VALUES (2, 'user'); -INSERT INTO test_user_role (user_id, role_id) VALUES (1, 1); -INSERT INTO test_user_role (user_id, role_id) VALUES (2, 2); +INSERT INTO test_user_role (user_id, role_id) VALUES (-1, 1); +INSERT INTO test_user_role (user_id, role_id) VALUES (-2, 2); diff --git a/extensions/security-jpa-reactive/runtime/src/main/java/io/quarkus/security/jpa/reactive/runtime/JpaReactiveIdentityProvider.java b/extensions/security-jpa-reactive/runtime/src/main/java/io/quarkus/security/jpa/reactive/runtime/JpaReactiveIdentityProvider.java index b4b2a74ce7453..96da9cb2970a7 100644 --- a/extensions/security-jpa-reactive/runtime/src/main/java/io/quarkus/security/jpa/reactive/runtime/JpaReactiveIdentityProvider.java +++ b/extensions/security-jpa-reactive/runtime/src/main/java/io/quarkus/security/jpa/reactive/runtime/JpaReactiveIdentityProvider.java @@ -4,9 +4,9 @@ import java.util.function.Predicate; import jakarta.inject.Inject; +import jakarta.persistence.NonUniqueResultException; import org.hibernate.FlushMode; -import org.hibernate.NonUniqueResultException; import org.hibernate.reactive.mutiny.Mutiny; import org.jboss.logging.Logger; diff --git a/extensions/security-jpa-reactive/runtime/src/main/java/io/quarkus/security/jpa/reactive/runtime/JpaReactiveTrustedIdentityProvider.java b/extensions/security-jpa-reactive/runtime/src/main/java/io/quarkus/security/jpa/reactive/runtime/JpaReactiveTrustedIdentityProvider.java index d5625d2232e3e..54bfef704f49b 100644 --- a/extensions/security-jpa-reactive/runtime/src/main/java/io/quarkus/security/jpa/reactive/runtime/JpaReactiveTrustedIdentityProvider.java +++ b/extensions/security-jpa-reactive/runtime/src/main/java/io/quarkus/security/jpa/reactive/runtime/JpaReactiveTrustedIdentityProvider.java @@ -4,9 +4,9 @@ import java.util.function.Predicate; import jakarta.inject.Inject; +import jakarta.persistence.NonUniqueResultException; import org.hibernate.FlushMode; -import org.hibernate.NonUniqueResultException; import org.hibernate.reactive.mutiny.Mutiny; import org.jboss.logging.Logger;