From 1532a3a60210108300434bd8dc557fec1b00e5c5 Mon Sep 17 00:00:00 2001 From: Fouad Almalki Date: Thu, 30 May 2024 03:29:30 +0300 Subject: [PATCH] Support specifying multiple tenants in @TenantFeature --- .../oidc/deployment/OidcBuildStep.java | 17 -------- .../java/io/quarkus/oidc/TenantFeature.java | 36 ++--------------- .../oidc/runtime/TenantFeatureFinder.java | 39 ++++++++++++++----- 3 files changed, 32 insertions(+), 60 deletions(-) diff --git a/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/OidcBuildStep.java b/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/OidcBuildStep.java index 43a5a696d8cc2..dc9a8081e5506 100644 --- a/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/OidcBuildStep.java +++ b/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/OidcBuildStep.java @@ -10,8 +10,6 @@ import static org.jboss.jandex.AnnotationTarget.Kind.METHOD; import java.util.List; -import java.util.Map; -import java.util.Set; import java.util.function.BooleanSupplier; import jakarta.inject.Singleton; @@ -29,13 +27,11 @@ import io.quarkus.arc.deployment.BeanDiscoveryFinishedBuildItem; import io.quarkus.arc.deployment.BeanRegistrationPhaseBuildItem; import io.quarkus.arc.deployment.InjectionPointTransformerBuildItem; -import io.quarkus.arc.deployment.QualifierRegistrarBuildItem; import io.quarkus.arc.deployment.SyntheticBeanBuildItem; import io.quarkus.arc.processor.Annotations; import io.quarkus.arc.processor.DotNames; import io.quarkus.arc.processor.InjectionPointInfo; import io.quarkus.arc.processor.InjectionPointsTransformer; -import io.quarkus.arc.processor.QualifierRegistrar; import io.quarkus.deployment.Capabilities; import io.quarkus.deployment.Capability; import io.quarkus.deployment.Feature; @@ -156,19 +152,6 @@ ExtensionSslNativeSupportBuildItem enableSslInNative() { return new ExtensionSslNativeSupportBuildItem(Feature.OIDC); } - @BuildStep - QualifierRegistrarBuildItem addQualifiers() { - // this seems to be necessary; I think it's because sometimes we only access beans - // annotated with @TenantFeature programmatically and no injection point is annotated with it - // TODO: drop @TenantFeature qualifier when 'TenantFeatureFinder' stop using this annotation as a qualifier - return new QualifierRegistrarBuildItem(new QualifierRegistrar() { - @Override - public Map> getAdditionalQualifiers() { - return Map.of(TENANT_FEATURE_NAME, Set.of()); - } - }); - } - @BuildStep InjectionPointTransformerBuildItem makeTenantIdentityProviderInjectionPointsNamed() { // @Tenant annotation cannot be a qualifier as it is used on resource methods and lead to illegal states diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/TenantFeature.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/TenantFeature.java index 34126a84f21ad..9813ca93db8e5 100644 --- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/TenantFeature.java +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/TenantFeature.java @@ -10,45 +10,15 @@ import java.lang.annotation.Retention; import java.lang.annotation.Target; -import jakarta.enterprise.util.AnnotationLiteral; -import jakarta.inject.Qualifier; - /** - * Qualifier used to specify which named tenant is associated with one or more OIDC feature. + * Annotation used to specify which named tenants are associated with an OIDC feature. */ @Target({ METHOD, FIELD, PARAMETER, TYPE }) @Retention(RUNTIME) @Documented -@Qualifier public @interface TenantFeature { /** - * Identifies an OIDC tenant to which a given feature applies. + * Identifies one or more OIDC tenants to which a given feature applies. */ - String value(); - - /** - * Supports inline instantiation of the {@link TenantFeature} qualifier. - */ - final class TenantFeatureLiteral extends AnnotationLiteral implements TenantFeature { - - private final String value; - - private TenantFeatureLiteral(String value) { - this.value = value; - } - - @Override - public String value() { - return value; - } - - @Override - public String toString() { - return "TenantFeatureLiteral [value=" + value + "]"; - } - - public static TenantFeature of(String value) { - return new TenantFeatureLiteral(value); - } - } + String[] value(); } diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/TenantFeatureFinder.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/TenantFeatureFinder.java index 11a918f6dd5ba..d39baf402d40c 100644 --- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/TenantFeatureFinder.java +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/TenantFeatureFinder.java @@ -1,17 +1,18 @@ package io.quarkus.oidc.runtime; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import jakarta.enterprise.inject.Default; import io.quarkus.arc.Arc; import io.quarkus.arc.ArcContainer; +import io.quarkus.arc.ClientProxy; import io.quarkus.arc.InstanceHandle; import io.quarkus.oidc.OIDCException; import io.quarkus.oidc.OidcTenantConfig; import io.quarkus.oidc.TenantFeature; -import io.quarkus.oidc.TenantFeature.TenantFeatureLiteral; import io.quarkus.oidc.TokenCustomizer; public class TenantFeatureFinder { @@ -35,9 +36,17 @@ public static TokenCustomizer find(OidcTenantConfig oidcConfig) { throw new OIDCException("Unable to find TokenCustomizer " + customizerName); } } else if (oidcConfig.tenantId.isPresent()) { - return container - .instance(TokenCustomizer.class, TenantFeature.TenantFeatureLiteral.of(oidcConfig.tenantId.get())) - .get(); + String tenantId = oidcConfig.tenantId.get(); + List list = findTenantFeaturesByTenantId(TokenCustomizer.class, tenantId); + if (!list.isEmpty()) { + if (list.size() >= 2) { + throw new OIDCException( + "Found multiple TokenCustomizers that are annotated with @TenantFeature that has tenantId (" + + tenantId + ")"); + } + return list.get(0); + } + } } return null; @@ -51,16 +60,26 @@ public static List find(OidcTenantConfig oidcTenantConfig, Class tenan tenantsValidators.add(instance.get()); } } - for (var instance : Arc.container().listAll(tenantFeatureClass, - TenantFeatureLiteral.of(oidcTenantConfig.tenantId.get()))) { - if (instance.isAvailable()) { - tenantsValidators.add(instance.get()); - } - } + tenantsValidators.addAll(findTenantFeaturesByTenantId(tenantFeatureClass, oidcTenantConfig.tenantId.get())); if (!tenantsValidators.isEmpty()) { return List.copyOf(tenantsValidators); } } return List.of(); } + + private static List findTenantFeaturesByTenantId(Class tenantFeatureClass, String tenantId) { + ArcContainer container = Arc.container(); + if (container != null) { + List list = new ArrayList<>(); + for (T tenantFeature : container.listAll(tenantFeatureClass).stream().map(InstanceHandle::get).toList()) { + TenantFeature annotation = ClientProxy.unwrap(tenantFeature).getClass().getAnnotation(TenantFeature.class); + if (annotation != null && Arrays.asList(annotation.value()).contains(tenantId)) { + list.add(tenantFeature); + } + } + return list; + } + return List.of(); + } }