diff --git a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/tenant/HibernateCurrentTenantIdentifierResolver.java b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/tenant/HibernateCurrentTenantIdentifierResolver.java index c7b2fdf6389db..1989224a06406 100644 --- a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/tenant/HibernateCurrentTenantIdentifierResolver.java +++ b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/tenant/HibernateCurrentTenantIdentifierResolver.java @@ -50,6 +50,19 @@ public boolean validateExistingCurrentSessions() { return false; } + @Override + public boolean isRoot(String tenantId) { + // Make sure that we're in a request + if (!Arc.container().requestContext().isActive()) { + return false; + } + TenantResolver resolver = tenantResolver(persistenceUnitName); + if (resolver == null) { + return false; + } + return resolver.isRoot(tenantId); + } + private static TenantResolver tenantResolver(String persistenceUnitName) { InjectableInstance instance = PersistenceUnitUtil.legacySingleExtensionInstanceForPersistenceUnit( TenantResolver.class, persistenceUnitName); diff --git a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/tenant/TenantResolver.java b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/tenant/TenantResolver.java index 3e628625c5c00..976f6100930d9 100644 --- a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/tenant/TenantResolver.java +++ b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/tenant/TenantResolver.java @@ -23,4 +23,14 @@ public interface TenantResolver { */ String resolveTenantId(); + /** + * Does the given tenant id represent a "root" tenant with access to all partitions? + * + * @param tenantId a tenant id produced by {@link #resolveTenantId()} + * + * @return true is this is root tenant + */ + default boolean isRoot(String tenantId) { + return false; + } } diff --git a/integration-tests/hibernate-orm-tenancy/discriminator/src/main/java/io/quarkus/it/hibernate/multitenancy/fruit/CustomTenantResolver.java b/integration-tests/hibernate-orm-tenancy/discriminator/src/main/java/io/quarkus/it/hibernate/multitenancy/fruit/CustomTenantResolver.java index 424bb8087c0c3..6b6b65a23f472 100644 --- a/integration-tests/hibernate-orm-tenancy/discriminator/src/main/java/io/quarkus/it/hibernate/multitenancy/fruit/CustomTenantResolver.java +++ b/integration-tests/hibernate-orm-tenancy/discriminator/src/main/java/io/quarkus/it/hibernate/multitenancy/fruit/CustomTenantResolver.java @@ -29,6 +29,8 @@ public String resolveTenantId() { final String tenantId; if (path.startsWith("/mycompany")) { tenantId = "mycompany"; + } else if (path.startsWith("/global")) { + tenantId = "global"; } else { tenantId = getDefaultTenantId(); } @@ -36,4 +38,8 @@ public String resolveTenantId() { return tenantId; } + @Override + public boolean isRoot(String tenantId) { + return "global".equals(tenantId); + } } diff --git a/integration-tests/hibernate-orm-tenancy/discriminator/src/test/java/io/quarkus/it/hibernate/multitenancy/fruit/HibernateTenancyFunctionalityTest.java b/integration-tests/hibernate-orm-tenancy/discriminator/src/test/java/io/quarkus/it/hibernate/multitenancy/fruit/HibernateTenancyFunctionalityTest.java index 6d3090f0d0208..ba4556fc144a0 100644 --- a/integration-tests/hibernate-orm-tenancy/discriminator/src/test/java/io/quarkus/it/hibernate/multitenancy/fruit/HibernateTenancyFunctionalityTest.java +++ b/integration-tests/hibernate-orm-tenancy/discriminator/src/test/java/io/quarkus/it/hibernate/multitenancy/fruit/HibernateTenancyFunctionalityTest.java @@ -4,10 +4,13 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.arrayWithSize; +import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; +import java.util.Arrays; + import jakarta.ws.rs.core.Response.Status; import org.junit.jupiter.api.BeforeEach; @@ -147,6 +150,18 @@ public void testUpdateFruitDefaultTenant() throws Exception { } + @Test + public void testGetFruitsTenantRoot() throws Exception { + + // Get all tenant fruits + Fruit[] fruits = given().when().get("/global/fruits").then().assertThat() + .statusCode(is(Status.OK.getStatusCode())).extract() + .as(Fruit[].class); + assertThat(fruits, arrayWithSize(6)); + assertThat(Arrays.asList(fruits), hasItems(new Fruit(4, "Avocado"), new Fruit(1, "Cherry"))); + + } + private Fruit findByName(String tenantPath, String name) { Response response = given().when().get(tenantPath + "/fruitsFindBy?type=name&value={name}", name); if (response.getStatusCode() == Status.OK.getStatusCode()) {