diff --git a/spring-graphql/src/main/java/org/springframework/graphql/data/method/annotation/support/AuthenticationPrincipalArgumentResolver.java b/spring-graphql/src/main/java/org/springframework/graphql/data/method/annotation/support/AuthenticationPrincipalArgumentResolver.java index 73ed6179..3f1a8bcb 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/data/method/annotation/support/AuthenticationPrincipalArgumentResolver.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/data/method/annotation/support/AuthenticationPrincipalArgumentResolver.java @@ -15,10 +15,13 @@ */ package org.springframework.graphql.data.method.annotation.support; +import java.lang.annotation.Annotation; + import graphql.schema.DataFetchingEnvironment; import org.reactivestreams.Publisher; +import reactor.core.publisher.Mono; + import org.springframework.core.MethodParameter; -import org.springframework.core.ResolvableType; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.expression.BeanResolver; import org.springframework.expression.Expression; @@ -35,13 +38,11 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; -import reactor.core.publisher.Mono; - -import java.lang.annotation.Annotation; /** - * Resolver to obtain {@link Authentication#getPrincipal()} from Spring Security context via - * {@link SecurityContext#getAuthentication()} for parameters annotated with {@link AuthenticationPrincipal}. + * Resolver to obtain {@link Authentication#getPrincipal()} from Spring Security + * context via {@link SecurityContext#getAuthentication()} for parameters + * annotated with {@link AuthenticationPrincipal}. * *

The resolver checks both ThreadLocal context via {@link SecurityContextHolder} * for Spring MVC applications, and {@link ReactiveSecurityContextHolder} for @@ -52,10 +53,11 @@ import java.lang.annotation.Annotation; */ public class AuthenticationPrincipalArgumentResolver implements HandlerMethodArgumentResolver { - private ExpressionParser parser = new SpelExpressionParser(); + private final ExpressionParser parser = new SpelExpressionParser(); private final BeanResolver beanResolver; + /** * Creates a new instance. * @param beanResolver the {@link BeanResolver} used for resolving beans in SpEL expressions. Cannot be null. @@ -65,37 +67,60 @@ public class AuthenticationPrincipalArgumentResolver implements HandlerMethodArg this.beanResolver = beanResolver; } + @Override public boolean supportsParameter(MethodParameter parameter) { - return findMethodAnnotation(AuthenticationPrincipal.class, parameter) != null; + return findMethodAnnotation(parameter) != null; + } + + /** + * Obtains the {@link AuthenticationPrincipal} annotation which can be + * directly on the {@link MethodParameter} or on a custom annotation that + * is meta-annotated with it. + */ + @Nullable + private static AuthenticationPrincipal findMethodAnnotation(MethodParameter parameter) { + AuthenticationPrincipal annotation = parameter.getParameterAnnotation(AuthenticationPrincipal.class); + if (annotation != null) { + return annotation; + } + Annotation[] annotationsToSearch = parameter.getParameterAnnotations(); + for (Annotation toSearch : annotationsToSearch) { + annotation = AnnotationUtils.findAnnotation(toSearch.annotationType(), AuthenticationPrincipal.class); + if (annotation != null) { + return annotation; + } + } + return null; } @Override public Object resolveArgument(MethodParameter parameter, DataFetchingEnvironment environment) throws Exception { - return getCurrentAuthentication().map(Authentication::getPrincipal) - .flatMap((principal) -> Mono.justOrEmpty(resolvePrincipal(parameter, principal))) - .transform((argument) -> { - boolean isParameterPublisher = isParameterMonoAssignable(parameter); - return isParameterPublisher ? Mono.just(argument) : argument; - }); + return getCurrentAuthentication() + .flatMap(auth -> Mono.justOrEmpty(resolvePrincipal(parameter, auth.getPrincipal()))) + .transform((argument) -> isParameterMonoAssignable(parameter) ? Mono.just(argument) : argument); + } + + private static boolean isParameterMonoAssignable(MethodParameter parameter) { + Class type = parameter.getParameterType(); + return (Publisher.class.equals(type) || Mono.class.equals(type)); } private Mono getCurrentAuthentication() { - SecurityContext securityContext = SecurityContextHolder.getContext(); - return Mono.justOrEmpty(securityContext.getAuthentication()) + return Mono.justOrEmpty(SecurityContextHolder.getContext().getAuthentication()) .switchIfEmpty(ReactiveSecurityContextHolder.getContext().map(SecurityContext::getAuthentication)); } @Nullable private Object resolvePrincipal(MethodParameter parameter, Object principal) { - AuthenticationPrincipal annotation = findMethodAnnotation(AuthenticationPrincipal.class, parameter); - String expressionToParse = annotation.expression(); - if (StringUtils.hasLength(expressionToParse)) { + AuthenticationPrincipal annotation = findMethodAnnotation(parameter); + String expressionValue = annotation.expression(); + if (StringUtils.hasLength(expressionValue)) { StandardEvaluationContext context = new StandardEvaluationContext(); context.setRootObject(principal); context.setVariable("this", principal); context.setBeanResolver(this.beanResolver); - Expression expression = this.parser.parseExpression(expressionToParse); + Expression expression = this.parser.parseExpression(expressionValue); principal = expression.getValue(context); } if (isInvalidType(parameter, principal)) { @@ -113,9 +138,8 @@ public class AuthenticationPrincipalArgumentResolver implements HandlerMethodArg } Class typeToCheck = parameter.getParameterType(); if (isParameterMonoAssignable(parameter)) { - ResolvableType resolvableType = ResolvableType.forMethodParameter(parameter); - Class genericType = resolvableType.resolveGeneric(0); - if (genericType == null) { + Class genericType = parameter.nested().getNestedParameterType(); + if (genericType.equals(Object.class)) { return false; } typeToCheck = genericType; @@ -123,31 +147,4 @@ public class AuthenticationPrincipalArgumentResolver implements HandlerMethodArg return !ClassUtils.isAssignable(typeToCheck, principal.getClass()); } - private boolean isParameterMonoAssignable(MethodParameter parameter) { - return Publisher.class.equals(parameter.getParameterType()) || - Mono.class.equals(parameter.getParameterType()); - } - - /** - * Obtains the specified {@link Annotation} on the specified {@link MethodParameter}. - * @param annotationClass the class of the {@link Annotation} to find on the - * {@link MethodParameter} - * @param parameter the {@link MethodParameter} to search for an {@link Annotation} - * @return the {@link Annotation} that was found or null. - */ - @Nullable - private T findMethodAnnotation(Class annotationClass, MethodParameter parameter) { - T annotation = parameter.getParameterAnnotation(annotationClass); - if (annotation != null) { - return annotation; - } - Annotation[] annotationsToSearch = parameter.getParameterAnnotations(); - for (Annotation toSearch : annotationsToSearch) { - annotation = AnnotationUtils.findAnnotation(toSearch.annotationType(), annotationClass); - if (annotation != null) { - return annotation; - } - } - return null; - } } diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/AuthenticationPrincipalArgumentResolverTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/AuthenticationPrincipalArgumentResolverTests.java index 51dde89d..fb0536d1 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/AuthenticationPrincipalArgumentResolverTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/data/method/annotation/support/AuthenticationPrincipalArgumentResolverTests.java @@ -15,10 +15,18 @@ */ package org.springframework.graphql.data.method.annotation.support; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Method; +import java.util.function.Function; + import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.reactivestreams.Publisher; +import reactor.core.publisher.Mono; +import reactor.test.publisher.TestPublisher; +import reactor.util.context.Context; + import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.core.MethodParameter; import org.springframework.core.ResolvableType; @@ -36,14 +44,6 @@ import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Controller; import org.springframework.util.ClassUtils; -import reactor.core.publisher.Mono; -import reactor.test.publisher.TestPublisher; -import reactor.util.context.Context; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.reflect.Method; -import java.util.function.Function; import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; @@ -55,73 +55,76 @@ import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; */ class AuthenticationPrincipalArgumentResolverTests { - private final static Class MONO_USER_DETAILS_CLASS = ResolvableType.forClassWithGenerics(Mono.class, UserDetails.class).getRawClass(); + private final static Class STRING_CLASS = String.class; private final static Class USER_DETAILS_CLASS = UserDetails.class; - private final static Class STRING_CLASS = String.class; + private final static Class MONO_USER_DETAILS_CLASS = + ResolvableType.forClassWithGenerics(Mono.class, UserDetails.class).getRawClass(); - private final static Class MONO_STRING_CLASS = ResolvableType.forClassWithGenerics(Mono.class, String.class).getRawClass(); + private final static Class MONO_STRING_CLASS = + ResolvableType.forClassWithGenerics(Mono.class, String.class).getRawClass(); - private final static Class PUBLISHER_USER_DETAILS_CLASS = ResolvableType.forClassWithGenerics(Publisher.class, UserDetails.class).getRawClass(); + private final static Class PUBLISHER_USER_DETAILS_CLASS = + ResolvableType.forClassWithGenerics(Publisher.class, UserDetails.class).getRawClass(); - private final static Class TESTPUBLISHER_USER_DETAILS_CLASS = ResolvableType.forClassWithGenerics(TestPublisher.class, UserDetails.class).getRawClass(); + private final static Class TESTPUBLISHER_USER_DETAILS_CLASS = + ResolvableType.forClassWithGenerics(TestPublisher.class, UserDetails.class).getRawClass(); - private AuthenticationPrincipalArgumentResolver resolver; - @BeforeEach - void setup() { - this.resolver = new AuthenticationPrincipalArgumentResolver((beanName, context) -> new PrincipalConverter()); - } + private final AuthenticationPrincipalArgumentResolver resolver = + new AuthenticationPrincipalArgumentResolver((beanName, context) -> new PrincipalConverter()); + @AfterEach void cleanup() { SecurityContextHolder.clearContext(); } + @Test - void supportsParameterWhenNoAnnotation() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "noParameter", USER_DETAILS_CLASS); - assertThat(this.resolver.supportsParameter(methodParameter)).isFalse(); + void supportsParameterWhenNoAnnotation() { + MethodParameter parameter = firstParameter(UserController.class, "noParameter", USER_DETAILS_CLASS); + assertThat(this.resolver.supportsParameter(parameter)).isFalse(); } @Test - void supportsParameterWhenWrongAnnotation() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "argument", USER_DETAILS_CLASS); - assertThat(this.resolver.supportsParameter(methodParameter)).isFalse(); + void supportsParameterWhenWrongAnnotation() { + MethodParameter parameter = firstParameter(UserController.class, "argument", USER_DETAILS_CLASS); + assertThat(this.resolver.supportsParameter(parameter)).isFalse(); } @Test - void supportsParameterWhenCurrentUser() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "currentUser", USER_DETAILS_CLASS); - assertThat(this.resolver.supportsParameter(methodParameter)).isTrue(); + void supportsParameterWhenCurrentUser() { + MethodParameter parameter = firstParameter(UserController.class, "currentUser", USER_DETAILS_CLASS); + assertThat(this.resolver.supportsParameter(parameter)).isTrue(); } @Test - void supportsParameterWhenAuthenticationPrincipal() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "userDetails", USER_DETAILS_CLASS); - assertThat(this.resolver.supportsParameter(methodParameter)).isTrue(); + void supportsParameterWhenAuthenticationPrincipal() { + MethodParameter parameter = firstParameter(UserController.class, "userDetails", USER_DETAILS_CLASS); + assertThat(this.resolver.supportsParameter(parameter)).isTrue(); } @Test void resolveArgumentWhenAuthenticationPrincipal() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "userDetails", USER_DETAILS_CLASS); - Mono userDetails = (Mono) this.resolver.resolveArgument(methodParameter, null); - assertThat(userDetails.contextWrite(authenticationContext()).block().getUsername()).isEqualTo("user"); + MethodParameter parameter = firstParameter(UserController.class, "userDetails", USER_DETAILS_CLASS); + Mono details = (Mono) this.resolver.resolveArgument(parameter, null); + assertThat(details.contextWrite(authenticationContext()).block().getUsername()).isEqualTo("user"); } @Test void resolveArgumentWhenCurrentUser() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "currentUser", USER_DETAILS_CLASS); - Mono userDetails = (Mono) this.resolver.resolveArgument(methodParameter, null); - assertThat(userDetails.contextWrite(authenticationContext()).block().getUsername()).isEqualTo("user"); + MethodParameter parameter = firstParameter(UserController.class, "currentUser", USER_DETAILS_CLASS); + Mono details = (Mono) this.resolver.resolveArgument(parameter, null); + assertThat(details.contextWrite(authenticationContext()).block().getUsername()).isEqualTo("user"); } @Test void resolveArgumentWhenNoSecurityContext() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "currentUser", USER_DETAILS_CLASS); - Mono userDetails = (Mono) this.resolver.resolveArgument(methodParameter, null); - assertThat(userDetails.block()).isNull(); + MethodParameter parameter = firstParameter(UserController.class, "currentUser", USER_DETAILS_CLASS); + Mono details = (Mono) this.resolver.resolveArgument(parameter, null); + assertThat(details.block()).isNull(); } @Test @@ -129,83 +132,83 @@ class AuthenticationPrincipalArgumentResolverTests { SecurityContext context = SecurityContextHolder.createEmptyContext(); context.setAuthentication(usernamePasswordAuthentication()); SecurityContextHolder.setContext(context); - MethodParameter methodParameter = firstMethodParameter(UserController.class, "currentUser", USER_DETAILS_CLASS); - Mono userDetails = (Mono) this.resolver.resolveArgument(methodParameter, null); - assertThat(userDetails.contextWrite(authenticationContext()).block().getUsername()).isEqualTo("user"); + MethodParameter parameter = firstParameter(UserController.class, "currentUser", USER_DETAILS_CLASS); + Mono details = (Mono) this.resolver.resolveArgument(parameter, null); + assertThat(details.contextWrite(authenticationContext()).block().getUsername()).isEqualTo("user"); } @Test void resolveArgumentWhenAuthenticationPrincipalUsername() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "username", STRING_CLASS); - Mono userDetails = (Mono) this.resolver.resolveArgument(methodParameter, null); - assertThat(userDetails.contextWrite(authenticationContext()).block()).isEqualTo("user"); + MethodParameter parameter = firstParameter(UserController.class, "username", STRING_CLASS); + Mono details = (Mono) this.resolver.resolveArgument(parameter, null); + assertThat(details.contextWrite(authenticationContext()).block()).isEqualTo("user"); } @Test void resolveArgumentWhenBeanName() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "beanName", USER_DETAILS_CLASS); - Mono userDetails = (Mono) this.resolver.resolveArgument(methodParameter, null); - assertThat(userDetails.contextWrite(authenticationContext()).block().getUsername()).isEqualTo("user"); + MethodParameter parameter = firstParameter(UserController.class, "beanName", USER_DETAILS_CLASS); + Mono details = (Mono) this.resolver.resolveArgument(parameter, null); + assertThat(details.contextWrite(authenticationContext()).block().getUsername()).isEqualTo("user"); } @Test void resolveArgumentWhenErrorOnInvalidType() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "errorOnInvalidType", String.class); - Mono userDetails = (Mono) this.resolver.resolveArgument(methodParameter, null); + MethodParameter parameter = firstParameter(UserController.class, "errorOnInvalidType", String.class); + Mono details = (Mono) this.resolver.resolveArgument(parameter, null); assertThatExceptionOfType(ClassCastException.class) - .isThrownBy(() -> userDetails.contextWrite(authenticationContext()).block()); + .isThrownBy(() -> details.contextWrite(authenticationContext()).block()); } @Test void resolveArgumentWhenInvalidType() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "invalidType", STRING_CLASS); - Mono> userDetails = (Mono>) this.resolver.resolveArgument(methodParameter, null); - assertThat(userDetails.flatMap(u -> u).contextWrite(authenticationContext()).block()).isNull(); + MethodParameter parameter = firstParameter(UserController.class, "invalidType", STRING_CLASS); + Mono> details = (Mono>) this.resolver.resolveArgument(parameter, null); + assertThat(details.flatMap(u -> u).contextWrite(authenticationContext()).block()).isNull(); } @Test - void supportsParameterWhenMonoNoAnnotation() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "noParameter", MONO_USER_DETAILS_CLASS); - assertThat(this.resolver.supportsParameter(methodParameter)).isFalse(); + void supportsParameterWhenMonoNoAnnotation() { + MethodParameter parameter = firstParameter(UserController.class, "noParameter", MONO_USER_DETAILS_CLASS); + assertThat(this.resolver.supportsParameter(parameter)).isFalse(); } @Test - void supportsParameterWhenMonoWrongAnnotation() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "argument", MONO_USER_DETAILS_CLASS); - assertThat(this.resolver.supportsParameter(methodParameter)).isFalse(); + void supportsParameterWhenMonoWrongAnnotation() { + MethodParameter parameter = firstParameter(UserController.class, "argument", MONO_USER_DETAILS_CLASS); + assertThat(this.resolver.supportsParameter(parameter)).isFalse(); } @Test - void supportsParameterWhenMonoCurrentUser() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "currentUser", MONO_USER_DETAILS_CLASS); - assertThat(this.resolver.supportsParameter(methodParameter)).isTrue(); + void supportsParameterWhenMonoCurrentUser() { + MethodParameter parameter = firstParameter(UserController.class, "currentUser", MONO_USER_DETAILS_CLASS); + assertThat(this.resolver.supportsParameter(parameter)).isTrue(); } @Test - void supportsParameterWhenMonoAuthenticationPrincipal() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "userDetails", MONO_USER_DETAILS_CLASS); - assertThat(this.resolver.supportsParameter(methodParameter)).isTrue(); + void supportsParameterWhenMonoAuthenticationPrincipal() { + MethodParameter parameter = firstParameter(UserController.class, "userDetails", MONO_USER_DETAILS_CLASS); + assertThat(this.resolver.supportsParameter(parameter)).isTrue(); } @Test void resolveArgumentWhenMonoAuthenticationPrincipal() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "userDetails", MONO_USER_DETAILS_CLASS); - Mono> userDetails = (Mono>) this.resolver.resolveArgument(methodParameter, null); - assertThat(userDetails.block().contextWrite(authenticationContext()).block().getUsername()).isEqualTo("user"); + MethodParameter parameter = firstParameter(UserController.class, "userDetails", MONO_USER_DETAILS_CLASS); + Mono> details = (Mono>) this.resolver.resolveArgument(parameter, null); + assertThat(details.block().contextWrite(authenticationContext()).block().getUsername()).isEqualTo("user"); } @Test void resolveArgumentWhenMonoCurrentUser() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "currentUser", MONO_USER_DETAILS_CLASS); - Mono> userDetails = (Mono>) this.resolver.resolveArgument(methodParameter, null); - assertThat(userDetails.block().contextWrite(authenticationContext()).block().getUsername()).isEqualTo("user"); + MethodParameter parameter = firstParameter(UserController.class, "currentUser", MONO_USER_DETAILS_CLASS); + Mono> details = (Mono>) this.resolver.resolveArgument(parameter, null); + assertThat(details.block().contextWrite(authenticationContext()).block().getUsername()).isEqualTo("user"); } @Test void resolveArgumentWhenMonoNoSecurityContext() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "currentUser", MONO_USER_DETAILS_CLASS); - Mono> userDetails = (Mono>) this.resolver.resolveArgument(methodParameter, null); - assertThat(userDetails.block().block()).isNull(); + MethodParameter parameter = firstParameter(UserController.class, "currentUser", MONO_USER_DETAILS_CLASS); + Mono> details = (Mono>) this.resolver.resolveArgument(parameter, null); + assertThat(details.block().block()).isNull(); } @Test @@ -213,71 +216,71 @@ class AuthenticationPrincipalArgumentResolverTests { SecurityContext context = SecurityContextHolder.createEmptyContext(); context.setAuthentication(usernamePasswordAuthentication()); SecurityContextHolder.setContext(context); - MethodParameter methodParameter = firstMethodParameter(UserController.class, "currentUser", MONO_USER_DETAILS_CLASS); - Mono> userDetails = (Mono>) this.resolver.resolveArgument(methodParameter, null); - assertThat(userDetails.block().contextWrite(authenticationContext()).block().getUsername()).isEqualTo("user"); + MethodParameter parameter = firstParameter(UserController.class, "currentUser", MONO_USER_DETAILS_CLASS); + Mono> details = (Mono>) this.resolver.resolveArgument(parameter, null); + assertThat(details.block().contextWrite(authenticationContext()).block().getUsername()).isEqualTo("user"); } @Test void resolveArgumentWhenMonoAuthenticationPrincipalUsername() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "username", MONO_STRING_CLASS); - Mono> userDetails = (Mono>) this.resolver.resolveArgument(methodParameter, null); - assertThat(userDetails.block().contextWrite(authenticationContext()).block()).isEqualTo("user"); + MethodParameter parameter = firstParameter(UserController.class, "username", MONO_STRING_CLASS); + Mono> details = (Mono>) this.resolver.resolveArgument(parameter, null); + assertThat(details.block().contextWrite(authenticationContext()).block()).isEqualTo("user"); } @Test void resolveArgumentWhenMonoBeanName() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "beanName", MONO_USER_DETAILS_CLASS); - Mono> userDetails = (Mono>) this.resolver.resolveArgument(methodParameter, null); - assertThat(userDetails.flatMap(u -> u).contextWrite(authenticationContext()).block().getUsername()).isEqualTo("user"); + MethodParameter parameter = firstParameter(UserController.class, "beanName", MONO_USER_DETAILS_CLASS); + Mono> details = (Mono>) this.resolver.resolveArgument(parameter, null); + assertThat(details.flatMap(u -> u).contextWrite(authenticationContext()).block().getUsername()).isEqualTo("user"); } @Test void resolveArgumentWhenMonoErrorOnInvalidType() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "errorOnInvalidType", MONO_STRING_CLASS); - Mono> userDetails = (Mono>) this.resolver.resolveArgument(methodParameter, null); + MethodParameter parameter = firstParameter(UserController.class, "errorOnInvalidType", MONO_STRING_CLASS); + Mono> details = (Mono>) this.resolver.resolveArgument(parameter, null); assertThatExceptionOfType(ClassCastException.class) - .isThrownBy(() -> userDetails.flatMap(u -> u).contextWrite(authenticationContext()).block()); + .isThrownBy(() -> details.flatMap(u -> u).contextWrite(authenticationContext()).block()); } @Test void resolveArgumentWhenMonoInvalidType() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "invalidType", MONO_STRING_CLASS); - Mono> userDetails = (Mono>) this.resolver.resolveArgument(methodParameter, null); - assertThat(userDetails.flatMap(u -> u).contextWrite(authenticationContext()).block()).isNull(); + MethodParameter parameter = firstParameter(UserController.class, "invalidType", MONO_STRING_CLASS); + Mono> details = (Mono>) this.resolver.resolveArgument(parameter, null); + assertThat(details.flatMap(u -> u).contextWrite(authenticationContext()).block()).isNull(); } @Test void resolveArgumentWhenPublisher() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "publisher", PUBLISHER_USER_DETAILS_CLASS); - Mono> userDetails = (Mono>) this.resolver.resolveArgument(methodParameter, null); - assertThat(userDetails.block().contextWrite(authenticationContext()).block().getUsername()).isEqualTo("user"); + MethodParameter parameter = firstParameter(UserController.class, "publisher", PUBLISHER_USER_DETAILS_CLASS); + Mono> details = (Mono>) this.resolver.resolveArgument(parameter, null); + assertThat(details.block().contextWrite(authenticationContext()).block().getUsername()).isEqualTo("user"); } @Test void resolveArgumentWhenTestPublisherThenEmptyMono() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "publisher", TESTPUBLISHER_USER_DETAILS_CLASS); - Mono> userDetails = (Mono>) this.resolver.resolveArgument(methodParameter, null); - assertThat(userDetails.contextWrite(authenticationContext()).block()).isNull(); + MethodParameter parameter = firstParameter(UserController.class, "publisher", TESTPUBLISHER_USER_DETAILS_CLASS); + Mono> details = (Mono>) this.resolver.resolveArgument(parameter, null); + assertThat(details.contextWrite(authenticationContext()).block()).isNull(); } @Test void resolveArgumentWhenTestPublisherAndErrorOnInvalidType() throws Exception { - MethodParameter methodParameter = firstMethodParameter(UserController.class, "errorOnInvalidType", TESTPUBLISHER_USER_DETAILS_CLASS); - Mono> userDetails = (Mono>) this.resolver.resolveArgument(methodParameter, null); + MethodParameter parameter = firstParameter(UserController.class, "errorOnInvalidType", TESTPUBLISHER_USER_DETAILS_CLASS); + Mono> details = (Mono>) this.resolver.resolveArgument(parameter, null); assertThatExceptionOfType(ClassCastException.class) - .isThrownBy(() -> userDetails.flatMap(u -> u).contextWrite(authenticationContext()).block()); + .isThrownBy(() -> details.flatMap(u -> u).contextWrite(authenticationContext()).block()); } - private MethodParameter firstMethodParameter(Class clazz, String methodName, Class... paramTypes) { + private MethodParameter firstParameter(Class clazz, String methodName, Class... paramTypes) { Method method = ClassUtils.getMethod(clazz, methodName, paramTypes); return methodParam(method, 0); } private MethodParameter methodParam(Method method, int index) { - MethodParameter methodParameter = new SynthesizingMethodParameter(method, index); - methodParameter.initParameterNameDiscovery(new DefaultParameterNameDiscoverer()); - return methodParameter; + MethodParameter parameter = new SynthesizingMethodParameter(method, index); + parameter.initParameterNameDiscovery(new DefaultParameterNameDiscoverer()); + return parameter; } private static Function authenticationContext() { @@ -285,8 +288,8 @@ class AuthenticationPrincipalArgumentResolverTests { } private static Authentication usernamePasswordAuthentication() { - UserDetails userDetails = userDetails(); - return new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities()); + UserDetails details = userDetails(); + return new UsernamePasswordAuthenticationToken(details, details.getPassword(), details.getAuthorities()); } private static UserDetails userDetails() { @@ -299,6 +302,7 @@ class AuthenticationPrincipalArgumentResolverTests { } } + @Controller static class UserController { @@ -328,7 +332,9 @@ class AuthenticationPrincipalArgumentResolverTests { } @QueryMapping - public UserDetails beanName(@AuthenticationPrincipal(expression = "@bean.convert(#this)") UserDetails userDetails) { + public UserDetails beanName( + @AuthenticationPrincipal(expression = "@bean.convert(#this)") UserDetails userDetails) { + return userDetails; } @@ -368,17 +374,23 @@ class AuthenticationPrincipalArgumentResolverTests { } @QueryMapping - public Mono beanName(@AuthenticationPrincipal(expression = "@bean.convert(#this)") Mono userDetails) { + public Mono beanName( + @AuthenticationPrincipal(expression = "@bean.convert(#this)") Mono userDetails) { + return userDetails; } @QueryMapping - public Mono errorOnInvalidType(@AuthenticationPrincipal(errorOnInvalidType = true) Mono userDetails) { + public Mono errorOnInvalidType( + @AuthenticationPrincipal(errorOnInvalidType = true) Mono userDetails) { + return userDetails; } @QueryMapping - public Publisher errorOnInvalidType(@AuthenticationPrincipal(errorOnInvalidType = true) TestPublisher userDetails) { + public Publisher errorOnInvalidType( + @AuthenticationPrincipal(errorOnInvalidType = true) TestPublisher userDetails) { + return userDetails; } @@ -398,8 +410,10 @@ class AuthenticationPrincipalArgumentResolverTests { } } + @AuthenticationPrincipal @Retention(RetentionPolicy.RUNTIME) public @interface CurrentUser { } + } \ No newline at end of file