Skip to content

Commit

Permalink
Merge pull request #39259 from PierreAdam/issue/39227
Browse files Browse the repository at this point in the history
Add handling of the annotation @PermissionsAllowed on methods or class for OpenAPI
  • Loading branch information
phillip-kruger authored Mar 7, 2024
2 parents dc10a9d + d7d2e08 commit 8ae9c71
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
import io.quarkus.runtime.LaunchMode;
import io.quarkus.runtime.util.ClassPathUtils;
import io.quarkus.security.Authenticated;
import io.quarkus.security.PermissionsAllowed;
import io.quarkus.smallrye.openapi.OpenApiFilter;
import io.quarkus.smallrye.openapi.common.deployment.SmallRyeOpenApiConfig;
import io.quarkus.smallrye.openapi.deployment.filter.AutoRolesAllowedFilter;
Expand Down Expand Up @@ -565,6 +566,9 @@ private OASFilter getAutoRolesAllowedFilter(
Map<String, List<String>> rolesAllowedMethodReferences = getRolesAllowedMethodReferences(
apiFilteredIndexViewBuildItem);

getPermissionsAllowedMethodReferences(apiFilteredIndexViewBuildItem)
.forEach(k -> rolesAllowedMethodReferences.putIfAbsent(k, List.of()));

List<String> authenticatedMethodReferences = getAuthenticatedMethodReferences(
apiFilteredIndexViewBuildItem);

Expand Down Expand Up @@ -630,6 +634,17 @@ private Map<String, List<String>> getRolesAllowedMethodReferences(OpenApiFiltere
}));
}

private List<String> getPermissionsAllowedMethodReferences(
OpenApiFilteredIndexViewBuildItem indexViewBuildItem) {
return indexViewBuildItem.getIndex()
.getAnnotations(DotName.createSimple(PermissionsAllowed.class))
.stream()
.flatMap(SmallRyeOpenApiProcessor::getMethods)
.map(e -> JandexUtil.createUniqueMethodReference(e.getKey().declaringClass(), e.getKey()))
.distinct()
.toList();
}

private List<String> getAuthenticatedMethodReferences(OpenApiFilteredIndexViewBuildItem indexViewBuildItem) {
return indexViewBuildItem.getIndex()
.getAnnotations(DotName.createSimple(Authenticated.class.getName()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ class AutoSecurityRolesAllowedTestCase {
static QuarkusUnitTest runner = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar
.addClasses(ResourceBean.class, OpenApiResourceSecuredAtClassLevel.class,
OpenApiResourceSecuredAtMethodLevel.class, OpenApiResourceSecuredAtMethodLevel2.class)
OpenApiResourceSecuredAtClassLevel2.class, OpenApiResourceSecuredAtMethodLevel.class,
OpenApiResourceSecuredAtMethodLevel2.class)
.addAsResource(
new StringAsset("quarkus.smallrye-openapi.security-scheme=jwt\n"
+ "quarkus.smallrye-openapi.security-scheme-name=JWTCompanyAuthentication\n"
Expand Down Expand Up @@ -71,6 +72,7 @@ void testAutoSecurityRequirement() {
.body("paths.'/resource2/test-security/methodLevel/public'.get.security", nullValue())
.body("paths.'/resource2/test-security/annotated/documented'.get.security", defaultSecurity)
.body("paths.'/resource2/test-security/methodLevel/3'.get.security", defaultSecurity)
.body("paths.'/resource2/test-security/methodLevel/4'.get.security", defaultSecurity)
.and()
// OpenApiResourceSecuredAtClassLevel
.body("paths.'/resource2/test-security/classLevel/1'.get.security", defaultSecurity)
Expand All @@ -79,7 +81,10 @@ void testAutoSecurityRequirement() {
.body("paths.'/resource2/test-security/classLevel/4'.get.security", defaultSecurity)
.and()
// OpenApiResourceSecuredAtMethodLevel2
.body("paths.'/resource3/test-security/annotated'.get.security", schemeArray("AtClassLevel"));
.body("paths.'/resource3/test-security/annotated'.get.security", schemeArray("AtClassLevel"))
.and()
// OpenApiResourceSecuredAtClassLevel2
.body("paths.'/resource3/test-security/classLevel-2/1'.get.security", defaultSecurity);
}

@Test
Expand Down Expand Up @@ -153,7 +158,19 @@ void testOpenAPIAnnotations() {
Matchers.equalTo("Who are you?"))
.and()
.body("paths.'/resource2/test-security/methodLevel/3'.get.responses.403.description",
Matchers.equalTo("You cannot do that."));
Matchers.equalTo("You cannot do that."))
.and()
.body("paths.'/resource2/test-security/methodLevel/4'.get.responses.401.description",
Matchers.equalTo("Not Authorized"))
.and()
.body("paths.'/resource2/test-security/methodLevel/4'.get.responses.403.description",
Matchers.equalTo("Not Allowed"))
.and()
.body("paths.'/resource3/test-security/classLevel-2/1'.get.responses.401.description",
Matchers.equalTo("Not Authorized"))
.and()
.body("paths.'/resource3/test-security/classLevel-2/1'.get.responses.403.description",
Matchers.equalTo("Not Allowed"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.quarkus.smallrye.openapi.test.jaxrs;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

import org.eclipse.microprofile.openapi.annotations.servers.Server;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;

import io.quarkus.security.PermissionsAllowed;

@Path("/resource3")
@Tag(name = "test")
@Server(url = "serverUrl")
@PermissionsAllowed("secure:read")
public class OpenApiResourceSecuredAtClassLevel2 {

@SuppressWarnings("unused")
private ResourceBean resourceBean;

@GET
@Path("/test-security/classLevel-2/1")
public String secureEndpoint1() {
return "secret";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import org.eclipse.microprofile.openapi.annotations.servers.Server;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;

import io.quarkus.security.PermissionsAllowed;

@Path("/resource2")
@Tag(name = "test")
@Server(url = "serverUrl")
Expand Down Expand Up @@ -76,4 +78,11 @@ public String secureEndpoint3() {
return "secret";
}

@GET
@Path("/test-security/methodLevel/4")
@PermissionsAllowed("secure:read")
public String secureEndpoint5() {
return "secret";
}

}

0 comments on commit 8ae9c71

Please sign in to comment.