Polish audit event endpoint support

Closes gh-6579
This commit is contained in:
Phillip Webb
2017-01-02 19:43:26 -08:00
parent 5b40eb48e0
commit 51762642b2
4 changed files with 43 additions and 55 deletions

View File

@@ -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.<String, Object>emptyMap());
}
}

View File

@@ -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<AuditEvent> 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<AuditEvent> 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<AuditEvent> auditEvents = this.auditEventRepository.find(principal, after,
type);
return ResponseEntity.ok(auditEvents);
Map<Object, Object> result = new LinkedHashMap<Object, Object>();
result.put("events", this.auditEventRepository.find(principal, after, type));
return ResponseEntity.ok(result);
}
}

View File

@@ -109,8 +109,7 @@ public class EndpointMvcIntegrationTests {
private final List<HttpMessageConverter<?>> converters;
public Application(
ObjectProvider<List<HttpMessageConverter<?>>> converters) {
public Application(ObjectProvider<List<HttpMessageConverter<?>>> converters) {
this.converters = converters.getIfAvailable();
}

View File

@@ -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.<String, Object>emptyMap());
}
}
}