Skip to content

Commit

Permalink
make composite authentication provider synthetic
Browse files Browse the repository at this point in the history
  • Loading branch information
rmanibus committed Sep 14, 2024
1 parent 62bba62 commit 56acf4b
Show file tree
Hide file tree
Showing 17 changed files with 272 additions and 176 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.quarkiverse.openapi.generator.deployment;

import io.quarkus.builder.item.MultiBuildItem;

public final class AuthProviderBuildItem extends MultiBuildItem {

AuthProviderBuildItem(String openApiSpecId, String name) {
this.openApiSpecId = openApiSpecId;
this.name = name;
}

final String openApiSpecId;
final String name;

public String getOpenApiSpecId() {
return openApiSpecId;
}

public String getName() {
return name;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@
import java.util.stream.Collectors;

import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.inject.Instance;

import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.ClassType;
import org.jboss.jandex.DotName;
import org.jboss.jandex.ParameterizedType;

import io.quarkiverse.openapi.generator.*;
import io.quarkiverse.openapi.generator.markers.*;
import io.quarkiverse.openapi.generator.providers.*;
import io.quarkiverse.openapi.generator.providers.OAuth2AuthenticationProvider.OidcClientRequestFilterDelegate;
import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
import io.quarkus.arc.deployment.SyntheticBeanBuildItem;
import io.quarkus.deployment.Capabilities;
import io.quarkus.deployment.Capability;
Expand All @@ -38,122 +43,165 @@ FeatureBuildItem feature() {
return new FeatureBuildItem(FEATURE);
}

@BuildStep
void additionalBean(
Capabilities capabilities,
BuildProducer<AdditionalBeanBuildItem> additionalBeanBuildItem) {
if (capabilities.isPresent(Capability.REST_CLIENT_REACTIVE)) {
additionalBeanBuildItem.produce(
AdditionalBeanBuildItem.builder().addBeanClass(ReactiveOidcClientRequestFilterDelegate.class)
.setDefaultScope(DotName.createSimple(Dependent.class))
.setUnremovable()
.build());
} else {
additionalBeanBuildItem.produce(
AdditionalBeanBuildItem.builder().addBeanClass(ClassicOidcClientRequestFilterDelegate.class)
.setDefaultScope(DotName.createSimple(Dependent.class))
.setUnremovable()
.build());
}
}

@BuildStep
@Record(ExecutionTime.STATIC_INIT)
void produceCompositeProviders(AuthenticationRecorder recorder,
List<AuthProviderBuildItem> authProviders,
BuildProducer<SyntheticBeanBuildItem> beanProducer) {
Map<String, List<AuthProviderBuildItem>> providersBySpec = authProviders.stream()
.collect(Collectors.groupingBy(AuthProviderBuildItem::getOpenApiSpecId));
providersBySpec.forEach((openApiSpecId, providers) -> {
beanProducer.produce(SyntheticBeanBuildItem.configure(CompositeAuthenticationProvider.class)
.scope(Dependent.class)
.addQualifier()
.annotation(Authentication.class)
.addValue("openApiSpecId", openApiSpecId)
.done()
.addInjectionPoint(
ParameterizedType.create(Instance.class, ClassType.create(AuthProvider.class)),
AnnotationInstance.builder(Authentication.class)
.add("openApiSpecId", openApiSpecId)
.build())
.createWith(recorder.recordCompositeProvider(openApiSpecId))
.done());

});
}

@BuildStep
@Record(ExecutionTime.STATIC_INIT)
void produceOauthAuthentication(CombinedIndexBuildItem beanArchiveBuildItem,
Capabilities capabilities,
BuildProducer<SyntheticBeanBuildItem> producer,
BuildProducer<AuthProviderBuildItem> authenticationProviders,
BuildProducer<SyntheticBeanBuildItem> beanProducer,
AuthenticationRecorder recorder) {
Collection<AnnotationInstance> authenticationMarkers = beanArchiveBuildItem.getIndex()
.getAnnotations(OAUTH_AUTHENTICATION_MARKER);

Map<String, List<AnnotationInstance>> operationsBySpec = getOperationsBySpec(beanArchiveBuildItem);

for (AnnotationInstance authenticationMarker : authenticationMarkers) {

String name = authenticationMarker.value("name").asString();
String openApiSpecId = authenticationMarker.value("openApiSpecId").asString();

List<OperationAuthInfo> operations = getOperations(operationsBySpec, openApiSpecId, name);

producer.produce(SyntheticBeanBuildItem.configure(OAuth2AuthenticationProvider.class)
authenticationProviders.produce(new AuthProviderBuildItem(openApiSpecId, name));
beanProducer.produce(SyntheticBeanBuildItem.configure(AuthProvider.class)
.scope(Dependent.class)
.addQualifier()
.annotation(Authentication.class)
.addValue("name", name)
.addValue("openApiSpecId", openApiSpecId)
.done()
.runtimeValue(recorder.recordOauthAuthProvider(
.addInjectionPoint(ClassType.create(OidcClientRequestFilterDelegate.class),
AnnotationInstance.builder(OidcClient.class)
.add("name", sanitizeAuthName(name))
.build())
.createWith(recorder.recordOauthAuthProvider(
sanitizeAuthName(name),
openApiSpecId,
capabilities.isPresent(Capability.REST_CLIENT_REACTIVE)
? recorder.recordReactiveDelegate(sanitizeAuthName(name))
: recorder.recordClassicDelegate(sanitizeAuthName(name)),
operations))
.unremovable()
.done());
}

}

@BuildStep
@Record(ExecutionTime.STATIC_INIT)
void produceBasicAuthentication(CombinedIndexBuildItem beanArchiveBuildItem,
BuildProducer<SyntheticBeanBuildItem> producer,
BuildProducer<AuthProviderBuildItem> authenticationProviders,
BuildProducer<SyntheticBeanBuildItem> beanProducer,
AuthenticationRecorder recorder) {

Collection<AnnotationInstance> authenticationMarkers = beanArchiveBuildItem.getIndex()
.getAnnotations(BASIC_AUTHENTICATION_MARKER);

Map<String, List<AnnotationInstance>> operationsBySpec = getOperationsBySpec(beanArchiveBuildItem);

for (AnnotationInstance authenticationMarker : authenticationMarkers) {
String name = authenticationMarker.value("name").asString();
String openApiSpecId = authenticationMarker.value("openApiSpecId").asString();

List<OperationAuthInfo> operations = getOperations(operationsBySpec, openApiSpecId, name);

producer.produce(SyntheticBeanBuildItem.configure(BasicAuthenticationProvider.class)
authenticationProviders.produce(new AuthProviderBuildItem(openApiSpecId, name));

beanProducer.produce(SyntheticBeanBuildItem.configure(AuthProvider.class)
.scope(Dependent.class)
.addQualifier()
.annotation(Authentication.class)
.addValue("name", name)
.addValue("openApiSpecId", openApiSpecId)
.done()
.createWith(recorder.recordBasicAuthProvider(
sanitizeAuthName(name),
openApiSpecId,
operations))
.unremovable()
.done());
}

}

@BuildStep
@Record(ExecutionTime.STATIC_INIT)
void produceBearerAuthentication(CombinedIndexBuildItem beanArchiveBuildItem,
BuildProducer<SyntheticBeanBuildItem> producer,
BuildProducer<AuthProviderBuildItem> authenticationProviders,
BuildProducer<SyntheticBeanBuildItem> beanProducer,
AuthenticationRecorder recorder) {

Collection<AnnotationInstance> authenticationMarkers = beanArchiveBuildItem.getIndex()
.getAnnotations(BEARER_AUTHENTICATION_MARKER);

Map<String, List<AnnotationInstance>> operationsBySpec = getOperationsBySpec(beanArchiveBuildItem);

for (AnnotationInstance authenticationMarker : authenticationMarkers) {
String name = authenticationMarker.value("name").asString();
String scheme = authenticationMarker.value("scheme").asString();
String openApiSpecId = authenticationMarker.value("openApiSpecId").asString();

List<OperationAuthInfo> operations = getOperations(operationsBySpec, openApiSpecId, name);

producer.produce(SyntheticBeanBuildItem.configure(BearerAuthenticationProvider.class)
authenticationProviders.produce(new AuthProviderBuildItem(openApiSpecId, name));
beanProducer.produce(SyntheticBeanBuildItem.configure(AuthProvider.class)
.scope(Dependent.class)
.addQualifier()
.annotation(Authentication.class)
.addValue("name", name)
.addValue("openApiSpecId", openApiSpecId)
.done()
.createWith(recorder.recordBearerAuthProvider(
sanitizeAuthName(name),
scheme,
openApiSpecId,
operations))
.unremovable()
.done());
}

}
}

@BuildStep
@Record(ExecutionTime.STATIC_INIT)
void produceApiKeyAuthentication(CombinedIndexBuildItem beanArchiveBuildItem,
BuildProducer<SyntheticBeanBuildItem> producer,
BuildProducer<AuthProviderBuildItem> authenticationProviders,
BuildProducer<SyntheticBeanBuildItem> beanProducer,
AuthenticationRecorder recorder) {

Collection<AnnotationInstance> authenticationMarkers = beanArchiveBuildItem.getIndex()
.getAnnotations(API_KEY_AUTHENTICATION_MARKER);

Map<String, List<AnnotationInstance>> operationsBySpec = getOperationsBySpec(beanArchiveBuildItem);

for (AnnotationInstance authenticationMarker : authenticationMarkers) {
String name = authenticationMarker.value("name").asString();
String openApiSpecId = authenticationMarker.value("openApiSpecId").asString();
Expand All @@ -162,11 +210,12 @@ void produceApiKeyAuthentication(CombinedIndexBuildItem beanArchiveBuildItem,

List<OperationAuthInfo> operations = getOperations(operationsBySpec, openApiSpecId, name);

producer.produce(SyntheticBeanBuildItem.configure(ApiKeyAuthenticationProvider.class)
authenticationProviders.produce(new AuthProviderBuildItem(openApiSpecId, name));

beanProducer.produce(SyntheticBeanBuildItem.configure(AuthProvider.class)
.scope(Dependent.class)
.addQualifier()
.annotation(Authentication.class)
.addValue("name", name)
.addValue("openApiSpecId", openApiSpecId)
.done()
.createWith(recorder.recordApiKeyAuthProvider(
Expand All @@ -175,6 +224,7 @@ void produceApiKeyAuthentication(CombinedIndexBuildItem beanArchiveBuildItem,
apiKeyIn,
apiKeyName,
operations))
.unremovable()
.done());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,48 +19,14 @@ package {apiPackage}.auth;
@io.quarkiverse.openapi.generator.markers.ApiKeyAuthenticationMarker(name="{auth.name}", openApiSpecId="{quarkus-generator.openApiSpecId}", apiKeyIn=io.quarkiverse.openapi.generator.providers.ApiKeyIn.cookie, apiKeyName="{auth.keyParamName}")
{/if}
{/for}
public class CompositeAuthenticationProvider extends io.quarkiverse.openapi.generator.providers.AbstractCompositeAuthenticationProvider {
public class CompositeAuthenticationProvider implements jakarta.ws.rs.client.ClientRequestFilter {



@jakarta.inject.Inject
io.quarkiverse.openapi.generator.OpenApiGeneratorConfig generatorConfig;

{#for auth in oauthMethods.orEmpty}
@jakarta.inject.Inject
@io.quarkiverse.openapi.generator.Authentication(name="{auth.name}", openApiSpecId="{configKey}")
io.quarkiverse.openapi.generator.providers.OAuth2AuthenticationProvider oAuth2Provider{auth_index};
{/for}

{#for auth in httpBasicMethods.orEmpty}
@io.quarkiverse.openapi.generator.Authentication(name="{auth.name}", openApiSpecId="{quarkus-generator.openApiSpecId}")
io.quarkiverse.openapi.generator.providers.BasicAuthenticationProvider basicAuthProvider{auth_index};
{/for}

{#for auth in httpBearerMethods.orEmpty}
@io.quarkiverse.openapi.generator.Authentication(name="{auth.name}", openApiSpecId="{quarkus-generator.openApiSpecId}")
io.quarkiverse.openapi.generator.providers.BearerAuthenticationProvider bearerProvider{auth_index};
{/for}

{#for auth in apiKeyMethods.orEmpty}
@io.quarkiverse.openapi.generator.Authentication(name="{auth.name}", openApiSpecId="{quarkus-generator.openApiSpecId}")
io.quarkiverse.openapi.generator.providers.ApiKeyAuthenticationProvider apiKeyQueryProvider{auth_index};
{/for}

@io.quarkiverse.openapi.generator.Authentication(openApiSpecId="{configKey}")
io.quarkiverse.openapi.generator.providers.CompositeAuthenticationProvider compositeProvider;

@jakarta.annotation.PostConstruct
public void init() {
{#for auth in httpBasicMethods.orEmpty}
this.addAuthenticationProvider(basicAuthProvider{auth_index});
{/for}
{#for auth in oauthMethods.orEmpty}
this.addAuthenticationProvider(oAuth2Provider{auth_index});
{/for}
{#for auth in httpBearerMethods.orEmpty}
this.addAuthenticationProvider(bearerProvider{auth_index});
{/for}
{#for auth in apiKeyMethods.orEmpty}
this.addAuthenticationProvider(apiKeyQueryProvider{auth_index});
{/for}
}
@java.lang.Override
public void filter(jakarta.ws.rs.client.ClientRequestContext context) throws java.io.IOException {
compositeProvider.filter(context);
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package {apiPackage}.auth;
public class AuthenticationPropagationHeadersFactory extends io.quarkiverse.openapi.generator.providers.AbstractAuthenticationPropagationHeadersFactory {

@jakarta.inject.Inject
public AuthenticationPropagationHeadersFactory(CompositeAuthenticationProvider compositeProvider, io.quarkiverse.openapi.generator.OpenApiGeneratorConfig generatorConfig, io.quarkiverse.openapi.generator.providers.HeadersProvider headersProvider) {
public AuthenticationPropagationHeadersFactory(@io.quarkiverse.openapi.generator.Authentication(openApiSpecId="{configKey}") io.quarkiverse.openapi.generator.providers.CompositeAuthenticationProvider compositeProvider, io.quarkiverse.openapi.generator.OpenApiGeneratorConfig generatorConfig, io.quarkiverse.openapi.generator.providers.HeadersProvider headersProvider) {
super(compositeProvider, generatorConfig, headersProvider);
}

Expand Down
Loading

0 comments on commit 56acf4b

Please sign in to comment.