use of reactor.core.publisher.Mono in project spring-security by spring-projects.
the class CurrentSecurityContextArgumentResolverTests method resolveArgumentWithCustomSecurityContext.
@Test
public void resolveArgumentWithCustomSecurityContext() {
MethodParameter parameter = ResolvableMethod.on(getClass()).named("customSecurityContext").build().arg(Mono.class, SecurityContext.class);
Authentication auth = buildAuthenticationWithPrincipal("hello");
Context context = ReactiveSecurityContextHolder.withSecurityContext(Mono.just(new CustomSecurityContext(auth)));
Mono<Object> argument = this.resolver.resolveArgument(parameter, this.bindingContext, this.exchange);
CustomSecurityContext securityContext = (CustomSecurityContext) argument.subscriberContext(context).cast(Mono.class).block().block();
assertThat(securityContext.getAuthentication()).isSameAs(auth);
ReactiveSecurityContextHolder.clearContext();
}
use of reactor.core.publisher.Mono in project spring-security by spring-projects.
the class CurrentSecurityContextArgumentResolverTests method resolveArgumentWithAuthentication1.
@Test
public void resolveArgumentWithAuthentication1() {
MethodParameter parameter = ResolvableMethod.on(getClass()).named("securityContextWithAuthentication").build().arg(Mono.class, Authentication.class);
Authentication auth = buildAuthenticationWithPrincipal("authentication1");
Context context = ReactiveSecurityContextHolder.withAuthentication(auth);
Mono<Object> argument = this.resolver.resolveArgument(parameter, this.bindingContext, this.exchange);
Mono<Authentication> auth1 = (Mono<Authentication>) argument.subscriberContext(context).block();
assertThat(auth1.block()).isSameAs(auth);
ReactiveSecurityContextHolder.clearContext();
}
use of reactor.core.publisher.Mono in project spring-security by spring-projects.
the class CurrentSecurityContextArgumentResolverTests method resolveArgumentWithSecurityContext.
@Test
public void resolveArgumentWithSecurityContext() {
MethodParameter parameter = ResolvableMethod.on(getClass()).named("securityContext").build().arg(Mono.class, SecurityContext.class);
Authentication auth = buildAuthenticationWithPrincipal("hello");
Context context = ReactiveSecurityContextHolder.withAuthentication(auth);
Mono<Object> argument = this.resolver.resolveArgument(parameter, this.bindingContext, this.exchange);
SecurityContext securityContext = (SecurityContext) argument.subscriberContext(context).cast(Mono.class).block().block();
assertThat(securityContext.getAuthentication()).isSameAs(auth);
ReactiveSecurityContextHolder.clearContext();
}
use of reactor.core.publisher.Mono in project spring-security by spring-projects.
the class CurrentSecurityContextArgumentResolverTests method metaAnnotationWhenCurrentSecurityWithErrorOnInvalidTypeThenInjectSecurityContext.
@Test
public void metaAnnotationWhenCurrentSecurityWithErrorOnInvalidTypeThenInjectSecurityContext() {
MethodParameter parameter = ResolvableMethod.on(getClass()).named("currentSecurityWithErrorOnInvalidType").build().arg(Mono.class, SecurityContext.class);
Authentication auth = buildAuthenticationWithPrincipal("current_security_with_error_on_invalid_type");
Context context = ReactiveSecurityContextHolder.withAuthentication(auth);
Mono<Object> argument = this.resolver.resolveArgument(parameter, this.bindingContext, this.exchange);
SecurityContext securityContext = (SecurityContext) argument.subscriberContext(context).cast(Mono.class).block().block();
assertThat(securityContext.getAuthentication()).isSameAs(auth);
ReactiveSecurityContextHolder.clearContext();
}
use of reactor.core.publisher.Mono in project spring-security by spring-projects.
the class PrePostAdviceReactiveMethodInterceptor method invoke.
@Override
public Object invoke(final MethodInvocation invocation) {
Method method = invocation.getMethod();
Class<?> returnType = method.getReturnType();
boolean isSuspendingFunction = KotlinDetector.isSuspendingFunction(method);
boolean hasFlowReturnType = COROUTINES_FLOW_CLASS_NAME.equals(new MethodParameter(method, RETURN_TYPE_METHOD_PARAMETER_INDEX).getParameterType().getName());
boolean hasReactiveReturnType = Publisher.class.isAssignableFrom(returnType) || isSuspendingFunction || hasFlowReturnType;
Assert.state(hasReactiveReturnType, () -> "The returnType " + returnType + " on " + method + " must return an instance of org.reactivestreams.Publisher " + "(i.e. Mono / Flux) or the function must be a Kotlin coroutine " + "function in order to support Reactor Context");
Class<?> targetClass = invocation.getThis().getClass();
Collection<ConfigAttribute> attributes = this.attributeSource.getAttributes(method, targetClass);
PreInvocationAttribute preAttr = findPreInvocationAttribute(attributes);
// @formatter:off
Mono<Authentication> toInvoke = ReactiveSecurityContextHolder.getContext().map(SecurityContext::getAuthentication).defaultIfEmpty(this.anonymous).filter((auth) -> this.preInvocationAdvice.before(auth, invocation, preAttr)).switchIfEmpty(Mono.defer(() -> Mono.error(new AccessDeniedException("Denied"))));
// @formatter:on
PostInvocationAttribute attr = findPostInvocationAttribute(attributes);
if (Mono.class.isAssignableFrom(returnType)) {
return toInvoke.flatMap((auth) -> PrePostAdviceReactiveMethodInterceptor.<Mono<?>>proceed(invocation).map((r) -> (attr != null) ? this.postAdvice.after(auth, invocation, attr, r) : r));
}
if (Flux.class.isAssignableFrom(returnType)) {
return toInvoke.flatMapMany((auth) -> PrePostAdviceReactiveMethodInterceptor.<Flux<?>>proceed(invocation).map((r) -> (attr != null) ? this.postAdvice.after(auth, invocation, attr, r) : r));
}
if (hasFlowReturnType) {
Flux<?> response;
if (isSuspendingFunction) {
response = toInvoke.flatMapMany((auth) -> Flux.from(CoroutinesUtils.invokeSuspendingFunction(invocation.getMethod(), invocation.getThis(), invocation.getArguments())).map((r) -> (attr != null) ? this.postAdvice.after(auth, invocation, attr, r) : r));
} else {
ReactiveAdapter adapter = ReactiveAdapterRegistry.getSharedInstance().getAdapter(returnType);
Assert.state(adapter != null, () -> "The returnType " + returnType + " on " + method + " must have a org.springframework.core.ReactiveAdapter registered");
response = toInvoke.flatMapMany((auth) -> Flux.from(adapter.toPublisher(PrePostAdviceReactiveMethodInterceptor.flowProceed(invocation))).map((r) -> (attr != null) ? this.postAdvice.after(auth, invocation, attr, r) : r));
}
return KotlinDelegate.asFlow(response);
}
if (isSuspendingFunction) {
Mono<?> response = toInvoke.flatMap((auth) -> Mono.from(CoroutinesUtils.invokeSuspendingFunction(invocation.getMethod(), invocation.getThis(), invocation.getArguments())).map((r) -> (attr != null) ? this.postAdvice.after(auth, invocation, attr, r) : r));
return KotlinDelegate.awaitSingleOrNull(response, invocation.getArguments()[invocation.getArguments().length - 1]);
}
return toInvoke.flatMapMany((auth) -> Flux.from(PrePostAdviceReactiveMethodInterceptor.<Publisher<?>>proceed(invocation)).map((r) -> (attr != null) ? this.postAdvice.after(auth, invocation, attr, r) : r));
}
Aggregations