pull/11812/merge
Phillip Webb 7 years ago
parent 00d9dbe4ce
commit 7d5e41f7dc

@ -37,9 +37,9 @@ public interface OperationParameter {
Class<?> getType(); Class<?> getType();
/** /**
* Return if the parameter accepts null values. * Return if the parameter is mandatory (does not accept null values).
* @return if the parameter is nullable * @return if the parameter is mandatory
*/ */
boolean isNullable(); boolean isMandatory();
} }

@ -40,6 +40,15 @@ public interface OperationParameters extends Iterable<OperationParameter> {
*/ */
int getParameterCount(); int getParameterCount();
/**
* Return if any of the contained parameters are
* {@link OperationParameter#isMandatory() mandatory}.
* @return if any parameters are mandatory
*/
default boolean hasMandatoryParameter() {
return stream().anyMatch(OperationParameter::isMandatory);
}
/** /**
* Return the parameter at the specified index. * Return the parameter at the specified index.
* @param index the parameter index * @param index the parameter index

@ -54,8 +54,8 @@ class OperationMethodParameter implements OperationParameter {
} }
@Override @Override
public boolean isNullable() { public boolean isMandatory() {
return !ObjectUtils.isEmpty(this.parameter.getAnnotationsByType(Nullable.class)); return ObjectUtils.isEmpty(this.parameter.getAnnotationsByType(Nullable.class));
} }
@Override @Override

@ -85,8 +85,8 @@ public class ReflectiveOperationInvoker implements OperationInvoker {
private boolean isMissing(Map<String, Object> arguments, private boolean isMissing(Map<String, Object> arguments,
OperationParameter parameter) { OperationParameter parameter) {
if (parameter.isNullable()) { if (!parameter.isMandatory()) {
return false; return true;
} }
return arguments.get(parameter.getName()) == null; return arguments.get(parameter.getName()) == null;
} }

@ -17,6 +17,7 @@
package org.springframework.boot.actuate.endpoint.invoker.cache; package org.springframework.boot.actuate.endpoint.invoker.cache;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import org.springframework.boot.actuate.endpoint.invoke.OperationInvoker; import org.springframework.boot.actuate.endpoint.invoke.OperationInvoker;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -74,11 +75,7 @@ public class CachingOperationInvoker implements OperationInvoker {
private boolean hasArgument(Map<String, Object> arguments) { private boolean hasArgument(Map<String, Object> arguments) {
if (!ObjectUtils.isEmpty(arguments)) { if (!ObjectUtils.isEmpty(arguments)) {
for (Object value : arguments.values()) { return arguments.values().stream().anyMatch(Objects::nonNull);
if (value != null) {
return true;
}
}
} }
return false; return false;
} }

@ -21,7 +21,6 @@ import java.util.function.Function;
import org.springframework.boot.actuate.endpoint.OperationType; import org.springframework.boot.actuate.endpoint.OperationType;
import org.springframework.boot.actuate.endpoint.invoke.OperationInvoker; import org.springframework.boot.actuate.endpoint.invoke.OperationInvoker;
import org.springframework.boot.actuate.endpoint.invoke.OperationInvokerAdvisor; import org.springframework.boot.actuate.endpoint.invoke.OperationInvokerAdvisor;
import org.springframework.boot.actuate.endpoint.invoke.OperationParameter;
import org.springframework.boot.actuate.endpoint.invoke.OperationParameters; import org.springframework.boot.actuate.endpoint.invoke.OperationParameters;
/** /**
@ -41,7 +40,7 @@ public class CachingOperationInvokerAdvisor implements OperationInvokerAdvisor {
@Override @Override
public OperationInvoker apply(String endpointId, OperationType operationType, public OperationInvoker apply(String endpointId, OperationType operationType,
OperationParameters parameters, OperationInvoker invoker) { OperationParameters parameters, OperationInvoker invoker) {
if (operationType == OperationType.READ && !hasMandatoryParameter(parameters)) { if (operationType == OperationType.READ && !parameters.hasMandatoryParameter()) {
Long timeToLive = this.endpointIdTimeToLive.apply(endpointId); Long timeToLive = this.endpointIdTimeToLive.apply(endpointId);
if (timeToLive != null && timeToLive > 0) { if (timeToLive != null && timeToLive > 0) {
return new CachingOperationInvoker(invoker, timeToLive); return new CachingOperationInvoker(invoker, timeToLive);
@ -50,13 +49,4 @@ public class CachingOperationInvokerAdvisor implements OperationInvokerAdvisor {
return invoker; return invoker;
} }
private boolean hasMandatoryParameter(OperationParameters parameters) {
for (OperationParameter parameter : parameters) {
if (!parameter.isNullable()) {
return true;
}
}
return false;
}
} }

@ -50,17 +50,17 @@ public class OperationMethodParameterTests {
} }
@Test @Test
public void isNullableWhenNoAnnotationShouldReturnFalse() { public void isMandatoryWhenNoAnnotationShouldReturnTrue() {
OperationMethodParameter parameter = new OperationMethodParameter("name", OperationMethodParameter parameter = new OperationMethodParameter("name",
this.method.getParameters()[0]); this.method.getParameters()[0]);
assertThat(parameter.isNullable()).isFalse(); assertThat(parameter.isMandatory()).isTrue();
} }
@Test @Test
public void isNullableWhenNullableAnnotationShouldReturnTrue() { public void isMandatoryWhenNullableAnnotationShouldReturnFalse() {
OperationMethodParameter parameter = new OperationMethodParameter("name", OperationMethodParameter parameter = new OperationMethodParameter("name",
this.method.getParameters()[1]); this.method.getParameters()[1]);
assertThat(parameter.isNullable()).isTrue(); assertThat(parameter.isMandatory()).isFalse();
} }
void example(String one, @Nullable String two) { void example(String one, @Nullable String two) {

@ -87,10 +87,14 @@ public class SecurityAutoConfigurationTests {
@Test @Test
public void testDefaultFilterOrderWithSecurityAdapter() { public void testDefaultFilterOrderWithSecurityAdapter() {
this.contextRunner.withConfiguration(AutoConfigurations.of(WebSecurity.class, SecurityFilterAutoConfiguration.class)) this.contextRunner.withConfiguration(AutoConfigurations.of(WebSecurity.class,
.run(context -> assertThat(context.getBean("securityFilterChainRegistration", SecurityFilterAutoConfiguration.class)).run(
DelegatingFilterProxyRegistrationBean.class).getOrder()).isEqualTo( context -> assertThat(context
FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER - 100)); .getBean("securityFilterChainRegistration",
DelegatingFilterProxyRegistrationBean.class)
.getOrder()).isEqualTo(
FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER
- 100));
} }
@Test @Test
@ -115,30 +119,41 @@ public class SecurityAutoConfigurationTests {
@Test @Test
public void defaultAuthenticationEventPublisherIsConditionalOnMissingBean() { public void defaultAuthenticationEventPublisherIsConditionalOnMissingBean() {
this.contextRunner.withUserConfiguration(AuthenticationEventPublisherConfiguration.class).run(context -> { this.contextRunner
assertThat(context.getBean(AuthenticationEventPublisher.class)) .withUserConfiguration(AuthenticationEventPublisherConfiguration.class)
.isInstanceOf(AuthenticationEventPublisherConfiguration.TestAuthenticationEventPublisher.class); .run(context -> {
}); assertThat(context.getBean(AuthenticationEventPublisher.class))
.isInstanceOf(
AuthenticationEventPublisherConfiguration.TestAuthenticationEventPublisher.class);
});
} }
@Test @Test
public void testDefaultFilterOrder() { public void testDefaultFilterOrder() {
this.contextRunner.withConfiguration(AutoConfigurations.of(SecurityFilterAutoConfiguration.class)).run(context -> { this.contextRunner
assertThat(context.getBean("securityFilterChainRegistration", .withConfiguration(
DelegatingFilterProxyRegistrationBean.class).getOrder()).isEqualTo( AutoConfigurations.of(SecurityFilterAutoConfiguration.class))
FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER - 100); .run(context -> {
}); assertThat(context
.getBean("securityFilterChainRegistration",
DelegatingFilterProxyRegistrationBean.class)
.getOrder()).isEqualTo(
FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER
- 100);
});
} }
@Test @Test
public void testCustomFilterOrder() { public void testCustomFilterOrder() {
this.contextRunner.withConfiguration(AutoConfigurations.of(SecurityFilterAutoConfiguration.class)) this.contextRunner
.withPropertyValues("spring.security.filter.order:12345") .withConfiguration(
.run(context -> { AutoConfigurations.of(SecurityFilterAutoConfiguration.class))
assertThat(context.getBean("securityFilterChainRegistration", .withPropertyValues("spring.security.filter.order:12345").run(context -> {
DelegatingFilterProxyRegistrationBean.class).getOrder()).isEqualTo( assertThat(context
12345); .getBean("securityFilterChainRegistration",
}); DelegatingFilterProxyRegistrationBean.class)
.getOrder()).isEqualTo(12345);
});
} }
@Test @Test
@ -153,60 +168,75 @@ public class SecurityAutoConfigurationTests {
@Test @Test
public void defaultUserNotCreatedIfAuthenticationManagerBeanPresent() { public void defaultUserNotCreatedIfAuthenticationManagerBeanPresent() {
this.contextRunner.withUserConfiguration(TestAuthenticationManagerConfiguration.class).run(context -> { this.contextRunner
AuthenticationManager manager = context.getBean(AuthenticationManager.class); .withUserConfiguration(TestAuthenticationManagerConfiguration.class)
assertThat(manager).isEqualTo(context.getBean( .run(context -> {
TestAuthenticationManagerConfiguration.class).authenticationManager); AuthenticationManager manager = context
assertThat(this.outputCapture.toString()) .getBean(AuthenticationManager.class);
.doesNotContain("Using generated security password: "); assertThat(manager).isEqualTo(context.getBean(
TestingAuthenticationToken token = new TestingAuthenticationToken("foo", "bar"); TestAuthenticationManagerConfiguration.class).authenticationManager);
assertThat(manager.authenticate(token)).isNotNull(); assertThat(this.outputCapture.toString())
}); .doesNotContain("Using generated security password: ");
TestingAuthenticationToken token = new TestingAuthenticationToken(
"foo", "bar");
assertThat(manager.authenticate(token)).isNotNull();
});
} }
@Test @Test
public void defaultUserNotCreatedIfUserDetailsServiceBeanPresent() { public void defaultUserNotCreatedIfUserDetailsServiceBeanPresent() {
this.contextRunner.withUserConfiguration(TestUserDetailsServiceConfiguration.class).run(context -> { this.contextRunner
UserDetailsService userDetailsService = context .withUserConfiguration(TestUserDetailsServiceConfiguration.class)
.getBean(UserDetailsService.class); .run(context -> {
assertThat(this.outputCapture.toString()) UserDetailsService userDetailsService = context
.doesNotContain("Using default security password: "); .getBean(UserDetailsService.class);
assertThat(userDetailsService.loadUserByUsername("foo")).isNotNull(); assertThat(this.outputCapture.toString())
}); .doesNotContain("Using default security password: ");
assertThat(userDetailsService.loadUserByUsername("foo")).isNotNull();
});
} }
@Test @Test
public void defaultUserNotCreatedIfAuthenticationProviderBeanPresent() { public void defaultUserNotCreatedIfAuthenticationProviderBeanPresent() {
this.contextRunner.withUserConfiguration(TestAuthenticationProviderConfiguration.class).run(context -> { this.contextRunner
AuthenticationProvider provider = context .withUserConfiguration(TestAuthenticationProviderConfiguration.class)
.getBean(AuthenticationProvider.class); .run(context -> {
assertThat(this.outputCapture.toString()) AuthenticationProvider provider = context
.doesNotContain("Using default security password: "); .getBean(AuthenticationProvider.class);
TestingAuthenticationToken token = new TestingAuthenticationToken("foo", "bar"); assertThat(this.outputCapture.toString())
assertThat(provider.authenticate(token)).isNotNull(); .doesNotContain("Using default security password: ");
}); TestingAuthenticationToken token = new TestingAuthenticationToken(
"foo", "bar");
assertThat(provider.authenticate(token)).isNotNull();
});
} }
@Test @Test
public void testJpaCoexistsHappily() { public void testJpaCoexistsHappily() {
this.contextRunner.withPropertyValues("spring.datasource.url:jdbc:hsqldb:mem:testsecdb", this.contextRunner
.withPropertyValues("spring.datasource.url:jdbc:hsqldb:mem:testsecdb",
"spring.datasource.initialization-mode:never") "spring.datasource.initialization-mode:never")
.withUserConfiguration(EntityConfiguration.class) .withUserConfiguration(EntityConfiguration.class)
.withConfiguration(AutoConfigurations.of(HibernateJpaAutoConfiguration.class, DataSourceAutoConfiguration.class)) .withConfiguration(
.run(context -> assertThat(context.getBean(JpaTransactionManager.class)).isNotNull()); AutoConfigurations.of(HibernateJpaAutoConfiguration.class,
DataSourceAutoConfiguration.class))
.run(context -> assertThat(context.getBean(JpaTransactionManager.class))
.isNotNull());
// This can fail if security @Conditionals force early instantiation of the // This can fail if security @Conditionals force early instantiation of the
// HibernateJpaAutoConfiguration (e.g. the EntityManagerFactory is not found) // HibernateJpaAutoConfiguration (e.g. the EntityManagerFactory is not found)
} }
@Test @Test
public void testSecurityEvaluationContextExtensionSupport() { public void testSecurityEvaluationContextExtensionSupport() {
this.contextRunner.run(context -> this.contextRunner.run(context -> assertThat(context)
assertThat(context).getBean(SecurityEvaluationContextExtension.class).isNotNull()); .getBean(SecurityEvaluationContextExtension.class).isNotNull());
} }
@Test @Test
public void defaultFilterDispatcherTypes() { public void defaultFilterDispatcherTypes() {
this.contextRunner.withConfiguration(AutoConfigurations.of(SecurityFilterAutoConfiguration.class)) this.contextRunner
.withConfiguration(
AutoConfigurations.of(SecurityFilterAutoConfiguration.class))
.run(context -> { .run(context -> {
DelegatingFilterProxyRegistrationBean bean = context.getBean( DelegatingFilterProxyRegistrationBean bean = context.getBean(
"securityFilterChainRegistration", "securityFilterChainRegistration",
@ -216,13 +246,16 @@ public class SecurityAutoConfigurationTests {
.getField(bean, "dispatcherTypes"); .getField(bean, "dispatcherTypes");
assertThat(dispatcherTypes).containsOnly(DispatcherType.ASYNC, assertThat(dispatcherTypes).containsOnly(DispatcherType.ASYNC,
DispatcherType.ERROR, DispatcherType.REQUEST); DispatcherType.ERROR, DispatcherType.REQUEST);
}); });
} }
@Test @Test
public void customFilterDispatcherTypes() { public void customFilterDispatcherTypes() {
this.contextRunner.withPropertyValues("spring.security.filter.dispatcher-types:INCLUDE,ERROR") this.contextRunner
.withConfiguration(AutoConfigurations.of(SecurityFilterAutoConfiguration.class)) .withPropertyValues(
"spring.security.filter.dispatcher-types:INCLUDE,ERROR")
.withConfiguration(
AutoConfigurations.of(SecurityFilterAutoConfiguration.class))
.run(context -> { .run(context -> {
DelegatingFilterProxyRegistrationBean bean = context.getBean( DelegatingFilterProxyRegistrationBean bean = context.getBean(
"securityFilterChainRegistration", "securityFilterChainRegistration",
@ -257,10 +290,13 @@ public class SecurityAutoConfigurationTests {
} }
@Override @Override
public void publishAuthenticationFailure(AuthenticationException exception, Authentication authentication) { public void publishAuthenticationFailure(AuthenticationException exception,
Authentication authentication) {
} }
} }
} }
@Configuration @Configuration

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2017 the original author or authors. * Copyright 2012-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

Loading…
Cancel
Save