Skip to content

Commit

Permalink
Merge pull request #19895 from geoand/#19878
Browse files Browse the repository at this point in the history
Ensure that eager security handling works in native mode
  • Loading branch information
geoand authored Sep 6, 2021
2 parents a5a2777 + 690210e commit 717df52
Showing 7 changed files with 114 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -10,11 +10,11 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.ws.rs.Priorities;
@@ -41,13 +41,13 @@
import org.jboss.resteasy.reactive.common.model.ResourceDynamicFeature;
import org.jboss.resteasy.reactive.common.model.ResourceFeature;
import org.jboss.resteasy.reactive.common.model.ResourceInterceptors;
import org.jboss.resteasy.reactive.common.model.ResourceMethod;
import org.jboss.resteasy.reactive.common.model.ResourceReader;
import org.jboss.resteasy.reactive.common.model.ResourceWriter;
import org.jboss.resteasy.reactive.common.processor.AdditionalReaderWriter;
import org.jboss.resteasy.reactive.common.processor.AdditionalReaders;
import org.jboss.resteasy.reactive.common.processor.AdditionalWriters;
import org.jboss.resteasy.reactive.common.processor.DefaultProducesHandler;
import org.jboss.resteasy.reactive.common.processor.EndpointIndexer;
import org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames;
import org.jboss.resteasy.reactive.common.processor.scanning.ApplicationScanningResult;
import org.jboss.resteasy.reactive.common.processor.scanning.ResourceScanningResult;
@@ -335,7 +335,7 @@ public void setupEndpoints(Capabilities capabilities, BeanArchiveIndexBuildItem

QuarkusServerEndpointIndexer.Builder serverEndpointIndexerBuilder = new QuarkusServerEndpointIndexer.Builder()
.addMethodScanners(
methodScanners.stream().map(MethodScannerBuildItem::getMethodScanner).collect(Collectors.toList()))
methodScanners.stream().map(MethodScannerBuildItem::getMethodScanner).collect(toList()))
.setIndex(index)
.setFactoryCreator(new QuarkusFactoryCreator(recorder, beanContainerBuildItem.getValue()))
.setEndpointInvokerFactory(new QuarkusInvokerFactory(generatedClassBuildItemBuildProducer, recorder))
@@ -353,13 +353,20 @@ public void setupEndpoints(Capabilities capabilities, BeanArchiveIndexBuildItem
.setClassLevelExceptionMappers(
classLevelExceptionMappers.isPresent() ? classLevelExceptionMappers.get().getMappers()
: Collections.emptyMap())
.setResourceMethodCallback(new Consumer<Map.Entry<MethodInfo, ResourceMethod>>() {
.setResourceMethodCallback(new Consumer<>() {
@Override
public void accept(Map.Entry<MethodInfo, ResourceMethod> entry) {
MethodInfo method = entry.getKey();
public void accept(EndpointIndexer.ResourceMethodCallbackData entry) {
MethodInfo method = entry.getMethodInfo();
String source = ResteasyReactiveProcessor.class.getSimpleName() + " > " + method.declaringClass()
+ "[" + method + "]";

ClassInfo classInfoWithSecurity = consumeStandardSecurityAnnotations(method,
entry.getActualEndpointInfo(), index, c -> c);
if (classInfoWithSecurity != null) {
reflectiveClass.produce(new ReflectiveClassBuildItem(false, true, false,
entry.getActualEndpointInfo().name().toString()));
}

reflectiveHierarchy.produce(new ReflectiveHierarchyBuildItem.Builder()
.type(method.returnType())
.index(index)
@@ -648,21 +655,29 @@ MethodScannerBuildItem integrateEagerSecurity(Capabilities capabilities, Combine
@Override
public List<HandlerChainCustomizer> scan(MethodInfo method, ClassInfo actualEndpointClass,
Map<String, Object> methodContext) {
if (SecurityTransformerUtils.hasStandardSecurityAnnotation(method)) {
return Collections.singletonList(new EagerSecurityHandler.Customizer());
}
ClassInfo c = actualEndpointClass;
while (c.superName() != null) {
if (SecurityTransformerUtils.hasStandardSecurityAnnotation(c)) {
return Collections.singletonList(new EagerSecurityHandler.Customizer());
}
c = index.getClassByName(c.superName());
}
return Collections.emptyList();
return Objects.requireNonNullElse(
consumeStandardSecurityAnnotations(method, actualEndpointClass, index,
(c) -> Collections.singletonList(new EagerSecurityHandler.Customizer())),
Collections.emptyList());
}
});
}

private <T> T consumeStandardSecurityAnnotations(MethodInfo methodInfo, ClassInfo classInfo, IndexView index,
Function<ClassInfo, T> function) {
if (SecurityTransformerUtils.hasStandardSecurityAnnotation(methodInfo)) {
return function.apply(methodInfo.declaringClass());
}
ClassInfo c = classInfo;
while (c.superName() != null) {
if (SecurityTransformerUtils.hasStandardSecurityAnnotation(c)) {
return function.apply(c);
}
c = index.getClassByName(c.superName());
}
return null;
}

private Optional<String> getAppPath(Optional<String> newPropertyValue) {
Optional<String> legacyProperty = ConfigProvider.getConfig().getOptionalValue("quarkus.rest.path", String.class);
if (legacyProperty.isPresent()) {
Original file line number Diff line number Diff line change
@@ -177,7 +177,7 @@ public abstract class EndpointIndexer<T extends EndpointIndexer<T, PARAM, METHOD
private final BlockingDefault defaultBlocking;
private final Map<DotName, Map<String, String>> classLevelExceptionMappers;
private final Function<String, BeanFactory<Object>> factoryCreator;
private final Consumer<Map.Entry<MethodInfo, ResourceMethod>> resourceMethodCallback;
private final Consumer<ResourceMethodCallbackData> resourceMethodCallback;

protected EndpointIndexer(Builder<T, ?, METHOD> builder) {
this.index = builder.index;
@@ -549,7 +549,7 @@ private ResourceMethod createResourceMethod(ClassInfo currentClassInfo, ClassInf

handleAdditionalMethodProcessing((METHOD) method, currentClassInfo, currentMethodInfo);
if (resourceMethodCallback != null) {
resourceMethodCallback.accept(new AbstractMap.SimpleEntry<>(currentMethodInfo, method));
resourceMethodCallback.accept(new ResourceMethodCallbackData(currentMethodInfo, actualEndpointInfo, method));
}
return method;
} catch (Exception e) {
@@ -1144,7 +1144,7 @@ public static abstract class Builder<T extends EndpointIndexer<T, ?, METHOD>, B
private AdditionalWriters additionalWriters;
private boolean hasRuntimeConverters;
private Map<DotName, Map<String, String>> classLevelExceptionMappers;
private Consumer<Map.Entry<MethodInfo, ResourceMethod>> resourceMethodCallback;
private Consumer<ResourceMethodCallbackData> resourceMethodCallback;

public B setDefaultBlocking(BlockingDefault defaultBlocking) {
this.defaultBlocking = defaultBlocking;
@@ -1206,12 +1206,36 @@ public B setClassLevelExceptionMappers(Map<DotName, Map<String, String>> classLe
return (B) this;
}

public B setResourceMethodCallback(Consumer<Map.Entry<MethodInfo, ResourceMethod>> resourceMethodCallback) {
public B setResourceMethodCallback(Consumer<ResourceMethodCallbackData> resourceMethodCallback) {
this.resourceMethodCallback = resourceMethodCallback;
return (B) this;
}

public abstract T build();
}

public static class ResourceMethodCallbackData {
private final MethodInfo methodInfo;
private final ClassInfo actualEndpointInfo;
private final ResourceMethod resourceMethod;

public ResourceMethodCallbackData(MethodInfo methodInfo, ClassInfo actualEndpointInfo, ResourceMethod resourceMethod) {
this.methodInfo = methodInfo;
this.actualEndpointInfo = actualEndpointInfo;
this.resourceMethod = resourceMethod;
}

public MethodInfo getMethodInfo() {
return methodInfo;
}

public ClassInfo getActualEndpointInfo() {
return actualEndpointInfo;
}

public ResourceMethod getResourceMethod() {
return resourceMethod;
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package io.quarkus.it.keycloak;

public class HelloResource extends HelloResourceBase implements IHelloResource {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.quarkus.it.keycloak;

import javax.annotation.security.RolesAllowed;

@RolesAllowed("user")
public class HelloResourceBase {

public String hello() {
return "hello";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.quarkus.it.keycloak;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/hello")
public interface IHelloResource {

@GET
@Produces(MediaType.TEXT_PLAIN)
String hello();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.quarkus.it.keycloak;

import io.quarkus.test.junit.QuarkusIntegrationTest;

@QuarkusIntegrationTest
public class HelloResourceIT extends HelloResourceTest {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.quarkus.it.keycloak;

import static io.restassured.RestAssured.when;

import org.junit.jupiter.api.Test;

import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest
public class HelloResourceTest {

@Test
public void testHelloEndpoint() {
when().get("/hello")
.then()
.statusCode(401);
}
}

0 comments on commit 717df52

Please sign in to comment.