Skip to content

Commit

Permalink
Support specifying multiple tenants in @TenantFeature
Browse files Browse the repository at this point in the history
  • Loading branch information
Eng-Fouad committed May 30, 2024
1 parent 7fb79c0 commit 1532a3a
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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<DotName, Set<String>> 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<TenantFeature> 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();
}
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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<TokenCustomizer> 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;
Expand All @@ -51,16 +60,26 @@ public static <T> List<T> find(OidcTenantConfig oidcTenantConfig, Class<T> 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 <T> List<T> findTenantFeaturesByTenantId(Class<T> tenantFeatureClass, String tenantId) {
ArcContainer container = Arc.container();
if (container != null) {
List<T> 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();
}
}

0 comments on commit 1532a3a

Please sign in to comment.