Commit c3b7764b authored by Phillip Webb's avatar Phillip Webb

Polish

parent fe8e8df7
......@@ -121,7 +121,8 @@ public class EndpointWebMvcChildContextConfiguration {
@Bean
public ManagementErrorEndpoint errorEndpoint(ServerProperties serverProperties,
final ErrorAttributes errorAttributes) {
return new ManagementErrorEndpoint(serverProperties.getError().getPath(), errorAttributes);
return new ManagementErrorEndpoint(serverProperties.getError().getPath(),
errorAttributes);
}
/**
......
......@@ -32,6 +32,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
public class EndpointMvcAdapter implements MvcEndpoint {
private final Endpoint<?> delegate;
private String path;
/**
......@@ -59,16 +60,16 @@ public class EndpointMvcAdapter implements MvcEndpoint {
@Override
public String getPath() {
return this.path != null ? this.path : "/" + this.delegate.getId();
return (this.path != null ? this.path : "/" + this.delegate.getId());
}
public void setPath(String path) {
if (!path.startsWith("/")) {
path = "/" + path;
}
while (path.endsWith("/")) {
path = path.substring(0, path.length() - 1);
}
if (!path.startsWith("/")) {
path = "/" + path;
}
this.path = path;
}
......
......@@ -134,9 +134,8 @@ public class HealthMvcEndpoint implements MvcEndpoint, EnvironmentAware {
public Object invoke(Principal principal) {
if (!this.delegate.isEnabled()) {
// Shouldn't happen because the request mapping should not be registered
return new ResponseEntity<Map<String, String>>(
Collections.singletonMap("message", "This endpoint is disabled"),
HttpStatus.NOT_FOUND);
return new ResponseEntity<Map<String, String>>(Collections.singletonMap(
"message", "This endpoint is disabled"), HttpStatus.NOT_FOUND);
}
Health health = getHealth(principal);
HttpStatus status = getStatus(health);
......@@ -187,21 +186,24 @@ public class HealthMvcEndpoint implements MvcEndpoint, EnvironmentAware {
if (principal == null || principal.getClass().getName().contains("Anonymous")) {
return false;
}
if (!ClassUtils.isPresent("org.springframework.security.core.Authentication",
null) || !(principal instanceof Authentication)) {
return false;
}
String role = this.roleResolver.getProperty("role", "ROLE_ADMIN");
Authentication authentication = (Authentication) principal;
for (GrantedAuthority authority : authentication.getAuthorities()) {
String name = authority.getAuthority();
if (role.equals(name) || ("ROLE_" + role).equals(name)) {
return true;
if (isSpringSecurityAuthentication(principal)) {
Authentication authentication = (Authentication) principal;
String role = this.roleResolver.getProperty("role", "ROLE_ADMIN");
for (GrantedAuthority authority : authentication.getAuthorities()) {
String name = authority.getAuthority();
if (role.equals(name) || ("ROLE_" + role).equals(name)) {
return true;
}
}
}
return false;
}
private boolean isSpringSecurityAuthentication(Principal principal) {
return ClassUtils.isPresent("org.springframework.security.core.Authentication",
null) && (principal instanceof Authentication);
}
private boolean isUnrestricted() {
Boolean sensitive = this.propertyResolver.getProperty("sensitive", Boolean.class);
return !this.secure && !Boolean.TRUE.equals(sensitive);
......@@ -209,16 +211,16 @@ public class HealthMvcEndpoint implements MvcEndpoint, EnvironmentAware {
@Override
public String getPath() {
return this.path != null ? this.path : "/" + this.delegate.getId();
return (this.path != null ? this.path : "/" + this.delegate.getId());
}
public void setPath(String path) {
if (!path.startsWith("/")) {
path = "/" + path;
}
while (path.endsWith("/")) {
path = path.substring(0, path.length() - 1);
}
if (!path.startsWith("/")) {
path = "/" + path;
}
this.path = path;
}
......
......@@ -58,14 +58,13 @@ public class MvcEndpoints implements ApplicationContextAware, InitializingBean {
this.endpoints.addAll(existing);
this.customTypes = findEndpointClasses(existing);
@SuppressWarnings("rawtypes")
Collection<Endpoint> delegates = BeanFactoryUtils
.beansOfTypeIncludingAncestors(this.applicationContext, Endpoint.class)
.values();
Collection<Endpoint> delegates = BeanFactoryUtils.beansOfTypeIncludingAncestors(
this.applicationContext, Endpoint.class).values();
for (Endpoint<?> endpoint : delegates) {
if (isGenericEndpoint(endpoint.getClass()) && endpoint.isEnabled()) {
EndpointMvcAdapter adapter = new EndpointMvcAdapter(endpoint);
String path = this.applicationContext.getEnvironment()
.getProperty("endpoints." + endpoint.getId() + ".path");
String path = this.applicationContext.getEnvironment().getProperty(
"endpoints." + endpoint.getId() + ".path");
if (path != null) {
adapter.setPath(path);
}
......
......@@ -98,10 +98,10 @@ public class HealthMvcEndpointTests {
@Test
@SuppressWarnings("unchecked")
public void customMapping() {
given(this.endpoint.invoke())
.willReturn(new Health.Builder().status("OK").build());
this.mvc.setStatusMapping(
Collections.singletonMap("OK", HttpStatus.INTERNAL_SERVER_ERROR));
given(this.endpoint.invoke()).willReturn(
new Health.Builder().status("OK").build());
this.mvc.setStatusMapping(Collections.singletonMap("OK",
HttpStatus.INTERNAL_SERVER_ERROR));
Object result = this.mvc.invoke(null);
assertTrue(result instanceof ResponseEntity);
ResponseEntity<Health> response = (ResponseEntity<Health>) result;
......@@ -112,8 +112,8 @@ public class HealthMvcEndpointTests {
@Test
@SuppressWarnings("unchecked")
public void customMappingWithRelaxedName() {
given(this.endpoint.invoke())
.willReturn(new Health.Builder().outOfService().build());
given(this.endpoint.invoke()).willReturn(
new Health.Builder().outOfService().build());
this.mvc.setStatusMapping(Collections.singletonMap("out-of-service",
HttpStatus.INTERNAL_SERVER_ERROR));
Object result = this.mvc.invoke(null);
......@@ -125,8 +125,8 @@ public class HealthMvcEndpointTests {
@Test
public void secureEvenWhenNotSensitive() {
given(this.endpoint.invoke())
.willReturn(new Health.Builder().up().withDetail("foo", "bar").build());
given(this.endpoint.invoke()).willReturn(
new Health.Builder().up().withDetail("foo", "bar").build());
given(this.endpoint.isSensitive()).willReturn(false);
Object result = this.mvc.invoke(this.admin);
assertTrue(result instanceof Health);
......@@ -136,8 +136,8 @@ public class HealthMvcEndpointTests {
@Test
public void secureNonAdmin() {
given(this.endpoint.invoke())
.willReturn(new Health.Builder().up().withDetail("foo", "bar").build());
given(this.endpoint.invoke()).willReturn(
new Health.Builder().up().withDetail("foo", "bar").build());
Object result = this.mvc.invoke(this.user);
assertTrue(result instanceof Health);
assertTrue(((Health) result).getStatus() == Status.UP);
......@@ -148,8 +148,8 @@ public class HealthMvcEndpointTests {
public void healthIsCached() {
given(this.endpoint.getTimeToLive()).willReturn(10000L);
given(this.endpoint.isSensitive()).willReturn(true);
given(this.endpoint.invoke())
.willReturn(new Health.Builder().up().withDetail("foo", "bar").build());
given(this.endpoint.invoke()).willReturn(
new Health.Builder().up().withDetail("foo", "bar").build());
Object result = this.mvc.invoke(this.admin);
assertTrue(result instanceof Health);
Health health = (Health) result;
......@@ -170,8 +170,8 @@ public class HealthMvcEndpointTests {
public void unsecureAnonymousAccessUnrestricted() {
this.mvc = new HealthMvcEndpoint(this.endpoint, false);
this.mvc.setEnvironment(this.environment);
given(this.endpoint.invoke())
.willReturn(new Health.Builder().up().withDetail("foo", "bar").build());
given(this.endpoint.invoke()).willReturn(
new Health.Builder().up().withDetail("foo", "bar").build());
Object result = this.mvc.invoke(null);
assertTrue(result instanceof Health);
assertTrue(((Health) result).getStatus() == Status.UP);
......@@ -181,8 +181,8 @@ public class HealthMvcEndpointTests {
@Test
public void unsensitiveAnonymousAccessRestricted() {
this.environment.getPropertySources().addLast(NON_SENSITIVE);
given(this.endpoint.invoke())
.willReturn(new Health.Builder().up().withDetail("foo", "bar").build());
given(this.endpoint.invoke()).willReturn(
new Health.Builder().up().withDetail("foo", "bar").build());
Object result = this.mvc.invoke(null);
assertTrue(result instanceof Health);
assertTrue(((Health) result).getStatus() == Status.UP);
......@@ -194,8 +194,8 @@ public class HealthMvcEndpointTests {
this.mvc = new HealthMvcEndpoint(this.endpoint, false);
this.mvc.setEnvironment(this.environment);
this.environment.getPropertySources().addLast(NON_SENSITIVE);
given(this.endpoint.invoke())
.willReturn(new Health.Builder().up().withDetail("foo", "bar").build());
given(this.endpoint.invoke()).willReturn(
new Health.Builder().up().withDetail("foo", "bar").build());
Object result = this.mvc.invoke(null);
assertTrue(result instanceof Health);
assertTrue(((Health) result).getStatus() == Status.UP);
......@@ -205,8 +205,8 @@ public class HealthMvcEndpointTests {
@Test
public void noCachingWhenTimeToLiveIsZero() {
given(this.endpoint.getTimeToLive()).willReturn(0L);
given(this.endpoint.invoke())
.willReturn(new Health.Builder().up().withDetail("foo", "bar").build());
given(this.endpoint.invoke()).willReturn(
new Health.Builder().up().withDetail("foo", "bar").build());
Object result = this.mvc.invoke(null);
assertTrue(result instanceof Health);
assertTrue(((Health) result).getStatus() == Status.UP);
......@@ -221,8 +221,8 @@ public class HealthMvcEndpointTests {
public void newValueIsReturnedOnceTtlExpires() throws InterruptedException {
given(this.endpoint.getTimeToLive()).willReturn(50L);
given(this.endpoint.isSensitive()).willReturn(false);
given(this.endpoint.invoke())
.willReturn(new Health.Builder().up().withDetail("foo", "bar").build());
given(this.endpoint.invoke()).willReturn(
new Health.Builder().up().withDetail("foo", "bar").build());
Object result = this.mvc.invoke(null);
assertTrue(result instanceof Health);
assertTrue(((Health) result).getStatus() == Status.UP);
......
......@@ -182,8 +182,8 @@ public class MvcEndpointIntegrationTests {
EnvironmentTestUtils.addEnvironment(this.context,
"spring.jackson.serialization.indent-output:true");
MockMvc mockMvc = createMockMvc();
mockMvc.perform(get("/beans"))
.andExpect(content().string(startsWith("{" + LINE_SEPARATOR)));
mockMvc.perform(get("/beans")).andExpect(
content().string(startsWith("{" + LINE_SEPARATOR)));
}
private MockMvc createMockMvc() {
......@@ -205,8 +205,8 @@ public class MvcEndpointIntegrationTests {
}
@ImportAutoConfiguration({ JacksonAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class, EndpointAutoConfiguration.class,
EndpointWebMvcAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
EndpointAutoConfiguration.class, EndpointWebMvcAutoConfiguration.class,
ManagementServerPropertiesAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, WebMvcAutoConfiguration.class })
static class DefaultConfiguration {
......@@ -224,8 +224,8 @@ public class MvcEndpointIntegrationTests {
@ImportAutoConfiguration({ HypermediaAutoConfiguration.class,
RepositoryRestMvcAutoConfiguration.class, JacksonAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class, EndpointAutoConfiguration.class,
EndpointWebMvcAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
EndpointAutoConfiguration.class, EndpointWebMvcAutoConfiguration.class,
ManagementServerPropertiesAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, WebMvcAutoConfiguration.class })
static class SpringDataRestConfiguration {
......
......@@ -65,15 +65,15 @@ public class MvcEndpointsTests {
@Test
public void changesPath() throws Exception {
EnvironmentTestUtils.addEnvironment(this.context,
"endpoints.test.path=/foo/bar/");
EnvironmentTestUtils
.addEnvironment(this.context, "endpoints.test.path=/foo/bar/");
this.context.getDefaultListableBeanFactory().registerSingleton("endpoint",
new TestEndpoint());
this.endpoints.setApplicationContext(this.context);
this.endpoints.afterPropertiesSet();
assertEquals(1, this.endpoints.getEndpoints().size());
assertEquals("/foo/bar",
this.endpoints.getEndpoints().iterator().next().getPath());
assertEquals("/foo/bar", this.endpoints.getEndpoints().iterator().next()
.getPath());
}
protected static class TestEndpoint extends AbstractEndpoint<String> {
......
......@@ -99,8 +99,8 @@ public class DataSourceHealthIndicatorTests {
public void connectionClosed() throws Exception {
DataSource dataSource = mock(DataSource.class);
Connection connection = mock(Connection.class);
given(connection.getMetaData())
.willReturn(this.dataSource.getConnection().getMetaData());
given(connection.getMetaData()).willReturn(
this.dataSource.getConnection().getMetaData());
given(dataSource.getConnection()).willReturn(connection);
this.indicator.setDataSource(dataSource);
Health health = this.indicator.health();
......
......@@ -88,7 +88,8 @@ public class VelocityAutoConfiguration {
factory.setResourceLoaderPath(this.properties.getResourceLoaderPath());
factory.setPreferFileSystemAccess(this.properties.isPreferFileSystemAccess());
Properties velocityProperties = new Properties();
velocityProperties.setProperty("input.encoding", this.properties.getCharsetName());
velocityProperties.setProperty("input.encoding",
this.properties.getCharsetName());
velocityProperties.putAll(this.properties.getProperties());
factory.setVelocityProperties(velocityProperties);
}
......
spring.thymeleaf.cache=true
\ No newline at end of file
spring.thymeleaf.cache=true
......@@ -513,23 +513,21 @@ your application might already use `/info` for another purpose. You can use the
The `application.properties` example above will change the endpoint from `/{id}` to
`/manage/{id}` (e.g. `/manage/info`).
You can also change the "id" of an endpoint (using
`endpoints.{name}.id`) which then changes the default resource path
for the MVC endpoint. Legal endpoint ids are composed only of
alphanumeric characters (because they can be exposed in a number of
places, including JMX object names, where special characters are
forbidden). The MVC path can be changed separately by configuring
`endpoints.{name}.path`, and there is no validation on those values
(so you can use anything that is legel in a URL path). For example, to
change the location of the `/health` endpoint to `/ping/me` you can
set `endpoints.health.path=/ping/me`.
TIP: If you provide a custom `MvcEndpoint` remember to include a
settable `path` property, and default it to `/{id}` if you want your
code to behave like the standard MVC endpoints. (Take a look at the
`HealthMvcEndpoint` to see how you might do that.) If your custom
endpoint is an `Endpoint` (not an `MvcEndpoint`) then Spring Boot will
take care of the path for you.
You can also change the "`id`" of an endpoint (using `endpoints.{name}.id`) which then
changes the default resource path for the MVC endpoint. Legal endpoint ids are composed
only of alphanumeric characters (because they can be exposed in a number of places,
including JMX object names, where special characters are forbidden). The MVC path can be
changed separately by configuring `endpoints.{name}.path`, and there is no validation on
those values (so you can use anything that is legel in a URL path). For example, to change
the location of the `/health` endpoint to `/ping/me` you can set
`endpoints.health.path=/ping/me`.
TIP: If you provide a custom `MvcEndpoint` remember to include a settable `path` property,
and default it to `/{id}` if you want your code to behave like the standard MVC endpoints.
(Take a look at the `HealthMvcEndpoint` to see how you might do that.) If your custom
endpoint is an `Endpoint` (not an `MvcEndpoint`) then Spring Boot will take care of the
path for you.
[[production-ready-customizing-management-server-port]]
......@@ -1073,10 +1071,11 @@ values for specific `MetricWriters` can be set as
`spring.metrics.export.triggers.<name>.*` where `<name>` is a bean name (or pattern for
matching bean names).
WARNING: The automatic export of metrics is disabled if you switch off the
default `MetricRepository` (e.g. by using Dropwizard metrics). You can get back the
same functionality be declaring a bean of your own of type `MetricReader` and
declaring it to be `@ExportMetricReader`.
WARNING: The automatic export of metrics is disabled if you switch off the default
`MetricRepository` (e.g. by using Dropwizard metrics). You can get back the same
functionality be declaring a bean of your own of type `MetricReader` and declaring it to
be `@ExportMetricReader`.
[[production-ready-metric-writers-export-to-redis]]
......
......@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.secure.sso;
import org.springframework.boot.SpringApplication;
......@@ -23,7 +24,7 @@ import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth
* After you launch the app it should prompt you for login with github. As long as it runs
* on port 8080 on localhost it should work. Use an incognito window for testing
* (otherwise you might find you are already authenticated).
*
*
* @author Dave Syer
*/
@SpringBootApplication
......
......@@ -7,8 +7,7 @@
href="webjars/bootstrap/3.0.3/css/bootstrap.min.css" />
</head>
<body>
<script type="text/javascript"
src="webjars/jquery/2.0.3/jquery.min.js"></script>
<script type="text/javascript" src="webjars/jquery/2.0.3/jquery.min.js"></script>
<div id="navbar" class="navbar navbar-default" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse"
......@@ -17,8 +16,8 @@
class="icon-bar"></span>
</button>
<a class="navbar-brand"
href="https://github.com/spring-projects/spring-boot"> Spring Boot
</a>
href="https://github.com/spring-projects/spring-boot"> Spring
Boot </a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
......@@ -30,8 +29,9 @@
<h1>Home</h1>
<p>Some static content</p>
<p>
<a class="btn btn-lg btn-primary" href="#navbar" role="button">Go &raquo;</a>
</p>
<a class="btn btn-lg btn-primary" href="#navbar" role="button">Go
&raquo;</a>
</p>
</div>
<script type="text/javascript"
src="webjars/bootstrap/3.0.3/js/bootstrap.min.js"></script>
......
/*
* Copyright 2012-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.secure.sso;
import org.junit.Before;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment