add test security attribute type handling
* added an attribute type enum which converts the `String` `value` into various types of objects * use the converter when setting up the security identity for tests * added some documentation about how to use `@SecurityAttribute` inside the `@TestSecurity` annotation Signed-off-by:Nathan Erwin <nathan.d.erwin@gmail.com>
This commit is contained in:
parent
016bfb50c3
commit
bc206d7449
|
@ -93,6 +93,24 @@ identity to be present.
|
|||
|
||||
See xref:security-oidc-bearer-token-authentication.adoc#integration-testing-security-annotation[OpenID Connect Bearer Token Integration testing], xref:security-oidc-code-flow-authentication.adoc#integration-testing-security-annotation[OpenID Connect Authorization Code Flow Integration testing] and xref:security-jwt.adoc#integration-testing-security-annotation[SmallRye JWT Integration testing] for more details about testing the endpoint code which depends on the injected `JsonWebToken`.
|
||||
|
||||
Additionally, you can specify attributes for the identity, perhaps custom items that were added with identity augmentation:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Inject
|
||||
SecurityIdentity identity;
|
||||
|
||||
@Test
|
||||
@TestSecurity(user = "testUser", "roles = {"admin, "user"}, attributes = {
|
||||
@SecurityAttribute(key = "answer", value = "42", type = AttributeType.LONG) }
|
||||
void someTestMethod() {
|
||||
Long answer = identity.<Long>getAttribute("answer");
|
||||
...
|
||||
}
|
||||
----
|
||||
|
||||
This will run the test with an identity with an attribute of type `Long` named `answer`.
|
||||
|
||||
[WARNING]
|
||||
====
|
||||
The feature is only available for `@QuarkusTest` and will **not** work on a `@QuarkusIntegrationTest`.
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package io.quarkus.it.resteasy.elytron;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
@ -13,6 +16,7 @@ import org.junit.jupiter.params.provider.MethodSource;
|
|||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import io.quarkus.test.junit.QuarkusTest;
|
||||
import io.quarkus.test.security.AttributeType;
|
||||
import io.quarkus.test.security.SecurityAttribute;
|
||||
import io.quarkus.test.security.TestSecurity;
|
||||
|
||||
|
@ -94,6 +98,50 @@ class TestSecurityTestCase {
|
|||
.body(is("foo=bar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestSecurity(user = "testUser", roles = "user", attributes = {
|
||||
@SecurityAttribute(key = "foo", value = "9223372036854775807", type = AttributeType.LONG) })
|
||||
void testLongAttributes() {
|
||||
given()
|
||||
.when()
|
||||
.get("/attributes")
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.body(is("foo=" + Long.MAX_VALUE));
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestSecurity(user = "testUser", roles = "user", attributes = {
|
||||
@SecurityAttribute(key = "foo", value = "[\"A\",\"B\",\"C\"]", type = AttributeType.JSON_ARRAY) })
|
||||
void testJsonArrayAttributes() {
|
||||
given()
|
||||
.when()
|
||||
.get("/attributes")
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.body(is("foo=[\"A\",\"B\",\"C\"]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestSecurity(user = "testUser", roles = "user", attributes = {
|
||||
@SecurityAttribute(key = "foo", value = "\"A\",\"B\",\"C\"", type = AttributeType.STRING_SET) })
|
||||
void testStringSetAttributes() {
|
||||
given()
|
||||
.when()
|
||||
.get("/attributes")
|
||||
.then()
|
||||
.statusCode(200)
|
||||
.body(startsWith("foo=["))
|
||||
.and()
|
||||
.body(endsWith("]"))
|
||||
.and()
|
||||
.body(containsString("\"A\""))
|
||||
.and()
|
||||
.body(containsString("\"B\""))
|
||||
.and()
|
||||
.body(containsString("\"C\""));
|
||||
}
|
||||
|
||||
static Stream<Arguments> arrayParams() {
|
||||
return Stream.of(
|
||||
arguments(new int[] { 1, 2 }, new String[] { "hello", "world" }));
|
||||
|
|
|
@ -32,6 +32,12 @@
|
|||
<artifactId>junit-jupiter</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-jsonp</artifactId>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
package io.quarkus.test.security;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.json.Json;
|
||||
import jakarta.json.JsonReader;
|
||||
|
||||
public enum AttributeType {
|
||||
LONG {
|
||||
@Override
|
||||
Object convert(String value) {
|
||||
return Long.valueOf(value);
|
||||
}
|
||||
},
|
||||
INTEGER {
|
||||
@Override
|
||||
Object convert(String value) {
|
||||
return Integer.valueOf(value);
|
||||
}
|
||||
},
|
||||
BOOLEAN {
|
||||
@Override
|
||||
Object convert(String value) {
|
||||
return Boolean.valueOf(value);
|
||||
}
|
||||
},
|
||||
STRING {
|
||||
@Override
|
||||
Object convert(String value) {
|
||||
return value;
|
||||
}
|
||||
},
|
||||
STRING_SET {
|
||||
/**
|
||||
* Returns a Set of String values, parsed from the given value.
|
||||
*
|
||||
* @param value a comma separated list of values
|
||||
*/
|
||||
@Override
|
||||
Object convert(String value) {
|
||||
return Set.of(value.split(","));
|
||||
}
|
||||
},
|
||||
JSON_ARRAY {
|
||||
@Override
|
||||
Object convert(String value) {
|
||||
try (JsonReader reader = Json.createReader(new StringReader(value))) {
|
||||
return reader.readArray();
|
||||
}
|
||||
}
|
||||
},
|
||||
JSON_OBJECT {
|
||||
@Override
|
||||
Object convert(String value) {
|
||||
try (JsonReader reader = Json.createReader(new StringReader(value))) {
|
||||
return reader.readObject();
|
||||
}
|
||||
}
|
||||
},
|
||||
DEFAULT {
|
||||
@Override
|
||||
Object convert(String value) {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
abstract Object convert(String value);
|
||||
}
|
|
@ -60,7 +60,7 @@ public class QuarkusSecurityTestExtension implements QuarkusTestBeforeEachCallba
|
|||
|
||||
if (testSecurity.attributes() != null) {
|
||||
user.addAttributes(Arrays.stream(testSecurity.attributes())
|
||||
.collect(Collectors.toMap(s -> s.key(), s -> s.value())));
|
||||
.collect(Collectors.toMap(s -> s.key(), s -> s.type().convert(s.value()))));
|
||||
}
|
||||
|
||||
SecurityIdentity userIdentity = augment(user.build(), allAnnotations);
|
||||
|
|
|
@ -10,4 +10,6 @@ public @interface SecurityAttribute {
|
|||
String key();
|
||||
|
||||
String value();
|
||||
|
||||
AttributeType type() default AttributeType.DEFAULT;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue