diff --git a/spring-boot-actuator-docs/src/restdoc/java/org/springframework/boot/actuate/hypermedia/SpringBootHypermediaApplication.java b/spring-boot-actuator-docs/src/restdoc/java/org/springframework/boot/actuate/hypermedia/SpringBootHypermediaApplication.java index 5af4a1472d..7229802deb 100644 --- a/spring-boot-actuator-docs/src/restdoc/java/org/springframework/boot/actuate/hypermedia/SpringBootHypermediaApplication.java +++ b/spring-boot-actuator-docs/src/restdoc/java/org/springframework/boot/actuate/hypermedia/SpringBootHypermediaApplication.java @@ -34,6 +34,7 @@ import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration; import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; +import org.springframework.lang.UsesJava8; // Flyway must go first @SpringBootApplication @@ -59,12 +60,16 @@ public class SpringBootHypermediaApplication implements CommandLineRunner { @Override public void run(String... args) throws Exception { - this.auditEventRepository.add(new AuditEvent(Date.from(Instant.parse( - "2016-11-01T11:00:00Z")), "user", "AUTHENTICATION_FAILURE", - Collections.emptyMap())); - this.auditEventRepository.add(new AuditEvent(Date.from(Instant.parse( - "2016-11-01T12:00:00Z")), "admin", "AUTHENTICATION_SUCCESS", - Collections.emptyMap())); + this.auditEventRepository.add( + createEvent("2016-11-01T11:00:00Z", "user", "AUTHENTICATION_FAILURE")); + this.auditEventRepository.add( + createEvent("2016-11-01T12:00:00Z", "admin", "AUTHENTICATION_SUCCESS")); + } + + @UsesJava8 + private AuditEvent createEvent(String instant, String principal, String type) { + return new AuditEvent(Date.from(Instant.parse(instant)), principal, type, + Collections.emptyMap()); } } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AuditEventsMvcEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AuditEventsMvcEndpoint.java index b441b1ca12..cffd0e8516 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AuditEventsMvcEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AuditEventsMvcEndpoint.java @@ -17,7 +17,8 @@ package org.springframework.boot.actuate.endpoint.mvc; import java.util.Date; -import java.util.List; +import java.util.LinkedHashMap; +import java.util.Map; import org.springframework.boot.actuate.audit.AuditEvent; import org.springframework.boot.actuate.audit.AuditEventRepository; @@ -34,6 +35,7 @@ import org.springframework.web.bind.annotation.ResponseBody; * {@link MvcEndpoint} to expose {@link AuditEvent}s. * * @author Vedran Pavic + * @author Phillip Webb * @since 1.5.0 */ @ConfigurationProperties(prefix = "endpoints.auditevents") @@ -47,41 +49,18 @@ public class AuditEventsMvcEndpoint extends AbstractNamedMvcEndpoint { this.auditEventRepository = auditEventRepository; } - @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE, params = { "after" }) + @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody - public ResponseEntity findByAfter( - @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssZ") Date after) { + public ResponseEntity findByPrincipalAndAfterAndType( + @RequestParam(required = false) String principal, + @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssZ") Date after, + @RequestParam(required = false) String type) { if (!isEnabled()) { return DISABLED_RESPONSE; } - List auditEvents = this.auditEventRepository.find(after); - return ResponseEntity.ok(auditEvents); - } - - @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE, - params = { "principal", "after" }) - @ResponseBody - public ResponseEntity findByPrincipalAndAfter(@RequestParam String principal, - @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssZ") Date after) { - if (!isEnabled()) { - return DISABLED_RESPONSE; - } - List auditEvents = this.auditEventRepository.find(principal, after); - return ResponseEntity.ok(auditEvents); - } - - @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE, - params = { "principal", "after", "type" }) - @ResponseBody - public ResponseEntity findByPrincipalAndAfterAndType(@RequestParam String principal, - @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssZ") Date after, - @RequestParam String type) { - if (!isEnabled()) { - return DISABLED_RESPONSE; - } - List auditEvents = this.auditEventRepository.find(principal, after, - type); - return ResponseEntity.ok(auditEvents); + Map result = new LinkedHashMap(); + result.put("events", this.auditEventRepository.find(principal, after, type)); + return ResponseEntity.ok(result); } } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointMvcIntegrationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointMvcIntegrationTests.java index e49f696b75..1e288ef615 100755 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointMvcIntegrationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointMvcIntegrationTests.java @@ -109,8 +109,7 @@ public class EndpointMvcIntegrationTests { private final List> converters; - public Application( - ObjectProvider>> converters) { + public Application(ObjectProvider>> converters) { this.converters = converters.getIfAvailable(); } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/AuditEventsMvcEndpointTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/AuditEventsMvcEndpointTests.java index de59d50df1..9873602438 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/AuditEventsMvcEndpointTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/AuditEventsMvcEndpointTests.java @@ -37,6 +37,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; @@ -55,6 +56,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. */ @SpringBootTest @RunWith(SpringRunner.class) +@TestPropertySource(properties = "management.security.enabled=false") public class AuditEventsMvcEndpointTests { @Autowired @@ -78,26 +80,27 @@ public class AuditEventsMvcEndpointTests { @Test public void invokeFilterByDateAfter() throws Exception { this.mvc.perform(get("/auditevents").param("after", "2016-11-01T13:00:00+0000")) - .andExpect(status().isOk()).andExpect(content().string("[]")); + .andExpect(status().isOk()) + .andExpect(content().string("{\"events\":[]}")); } @Test public void invokeFilterByPrincipalAndDateAfter() throws Exception { - this.mvc.perform(get("/auditevents").param("principal", "user") - .param("after", "2016-11-01T10:00:00+0000")) + this.mvc.perform(get("/auditevents").param("principal", "user").param("after", + "2016-11-01T10:00:00+0000")) .andExpect(status().isOk()) - .andExpect(content().string(containsString( - "\"principal\":\"user\",\"type\":\"login\""))) + .andExpect(content().string( + containsString("\"principal\":\"user\",\"type\":\"login\""))) .andExpect(content().string(not(containsString("admin")))); } @Test public void invokeFilterByPrincipalAndDateAfterAndType() throws Exception { this.mvc.perform(get("/auditevents").param("principal", "admin") - .param("after", "2016-11-01T10:00:00+0000") - .param("type", "logout")).andExpect(status().isOk()) - .andExpect(content().string(containsString( - "\"principal\":\"admin\",\"type\":\"logout\""))) + .param("after", "2016-11-01T10:00:00+0000").param("type", "logout")) + .andExpect(status().isOk()) + .andExpect(content().string( + containsString("\"principal\":\"admin\",\"type\":\"logout\""))) .andExpect(content().string(not(containsString("login")))); } @@ -111,15 +114,17 @@ public class AuditEventsMvcEndpointTests { @Bean public AuditEventRepository auditEventsRepository() { AuditEventRepository repository = new InMemoryAuditEventRepository(3); - repository.add(new AuditEvent(Date.from(Instant.parse( - "2016-11-01T11:00:00Z")), "admin", "login", Collections.emptyMap())); - repository.add(new AuditEvent(Date.from(Instant.parse( - "2016-11-01T12:00:00Z")), "admin", "logout", Collections.emptyMap())); - repository.add(new AuditEvent(Date.from(Instant.parse( - "2016-11-01T12:00:00Z")), "user", "login", Collections.emptyMap())); + repository.add(createEvent("2016-11-01T11:00:00Z", "admin", "login")); + repository.add(createEvent("2016-11-01T12:00:00Z", "admin", "logout")); + repository.add(createEvent("2016-11-01T12:00:00Z", "user", "login")); return repository; } + private AuditEvent createEvent(String instant, String principal, String type) { + return new AuditEvent(Date.from(Instant.parse(instant)), principal, type, + Collections.emptyMap()); + } + } }