Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PUB-1909 View Audit Logs #451

Merged
merged 9 commits into from
Dec 18, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class AuditTest {
private static final String UNAUTHORIZED_USERNAME = "unauthorized_isAuthorized";
private static final String FORBIDDEN_STATUS_CODE = "Status code does not match forbidden";
private static final String GET_AUDIT_LOG_FAILED = "Failed to retrieve audit log";
private static final String GET_ALL_AUDIT_PARAMS =
"?filterStartDate=2020-01-01T00:00:00.000Z&filterEndDate=2100-01-01T00:00:00.000Z";
private static final AuditAction AUDIT_ACTION = AuditAction.MANAGE_THIRD_PARTY_USER_VIEW;

private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
Expand Down Expand Up @@ -94,7 +96,7 @@ void testGetAllAuditLogs() throws Exception {
.contentType(MediaType.APPLICATION_JSON);
mockMvc.perform(mockHttpServletRequestBuilder2).andExpect(status().isOk());

MvcResult mvcResult = mockMvc.perform(get(ROOT_URL))
MvcResult mvcResult = mockMvc.perform(get(ROOT_URL + GET_ALL_AUDIT_PARAMS))
.andExpect(status().isOk())
.andReturn();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
Expand All @@ -21,7 +22,10 @@
import uk.gov.hmcts.reform.pip.account.management.model.AuditLog;
import uk.gov.hmcts.reform.pip.account.management.service.AuditService;
import uk.gov.hmcts.reform.pip.model.authentication.roles.IsAdmin;
import uk.gov.hmcts.reform.pip.model.enums.AuditAction;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;

import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
Expand All @@ -45,14 +49,22 @@ public AuditController(AuditService auditService) {
this.auditService = auditService;
}

@ApiResponse(responseCode = OK_ERROR_CODE, description = "All audit logs returned as a page.")
@ApiResponse(responseCode = OK_ERROR_CODE, description = "All audit logs returned as a page with filtering.")
@Operation(summary = "Get all audit logs returned as a page")
@GetMapping
public ResponseEntity<Page<AuditLog>> getAllAuditLogs(
@RequestParam(name = "pageNumber", defaultValue = "0") int pageNumber,
@RequestParam(name = "pageSize", defaultValue = "25") int pageSize) {
@RequestParam(name = "pageSize", defaultValue = "25") int pageSize,
@RequestParam(name = "email", defaultValue = "", required = false) String email,
@RequestParam(name = "userId", defaultValue = "", required = false) String userId,
@RequestParam(name = "actions", defaultValue = "", required = false) List<AuditAction> auditActions,
@RequestParam(name = "filterStartDate", defaultValue = "")
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime filterStartDate,
@RequestParam(name = "filterEndDate", defaultValue = "")
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime filterEndDate) {
Pageable pageable = PageRequest.of(pageNumber, pageSize);
return ResponseEntity.ok(auditService.getAllAuditLogs(pageable));
return ResponseEntity.ok(auditService.getAllAuditLogs(pageable, email, userId,
auditActions, filterStartDate, filterEndDate));
}

@ApiResponse(responseCode = OK_ERROR_CODE, description = "Audit log with id {id} returned.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,22 @@
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.transaction.annotation.Transactional;
import uk.gov.hmcts.reform.pip.account.management.model.AuditLog;
import uk.gov.hmcts.reform.pip.model.enums.AuditAction;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;

public interface AuditRepository extends JpaRepository<AuditLog, UUID> {

@Transactional
void deleteAllByTimestampBefore(LocalDateTime timestamp);

Page<AuditLog> findAllByOrderByTimestampDesc(Pageable pageable);
Page<AuditLog> findAllByUserEmailLikeIgnoreCaseAndUserIdLikeAndActionInAndTimestampBetweenOrderByTimestampDesc(
KianKwa marked this conversation as resolved.
Show resolved Hide resolved
String email,
String userId,
List<AuditAction> auditAction,
LocalDateTime timeStampFrom,
LocalDateTime timeStampTo,
Pageable pageable);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@
import uk.gov.hmcts.reform.pip.account.management.database.AuditRepository;
import uk.gov.hmcts.reform.pip.account.management.errorhandling.exceptions.NotFoundException;
import uk.gov.hmcts.reform.pip.account.management.model.AuditLog;
import uk.gov.hmcts.reform.pip.model.enums.AuditAction;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.UUID;

/**
Expand All @@ -33,8 +37,29 @@ public AuditService(AuditRepository auditRepository) {
* @param pageable The pageable object to query by.
* @return Returns the audit logs in a page.
*/
public Page<AuditLog> getAllAuditLogs(Pageable pageable) {
return auditRepository.findAllByOrderByTimestampDesc(pageable);
public Page<AuditLog> getAllAuditLogs(Pageable pageable, String email, String userId,
List<AuditAction> auditActions, LocalDateTime filterStartDate, LocalDateTime filterEndDate) {

// If user provenance id is supplied then find by an exact match
KianKwa marked this conversation as resolved.
Show resolved Hide resolved
String userIdToQuery = "%%";
if (!userId.isBlank()) {
userIdToQuery = userId;
}

// If user audit action is supplied then find by an exact match
List<AuditAction> auditActionsToQuery = new ArrayList<>(EnumSet.allOf(AuditAction.class));
if (!auditActions.isEmpty()) {
auditActionsToQuery = auditActions;
}

return auditRepository
.findAllByUserEmailLikeIgnoreCaseAndUserIdLikeAndActionInAndTimestampBetweenOrderByTimestampDesc(
"%" + email + "%",
userIdToQuery,
auditActionsToQuery,
filterStartDate,
filterEndDate,
pageable);
}

public AuditLog getAuditLogById(UUID id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
import uk.gov.hmcts.reform.pip.model.account.UserProvenances;
import uk.gov.hmcts.reform.pip.model.enums.AuditAction;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import static org.junit.jupiter.api.Assertions.assertEquals;
Expand All @@ -29,11 +32,16 @@ class AuditControllerTest {
private AuditController auditController;

private static final String STATUS_CODE_MATCH = "Status code responses should match";
private static final String EMAIL = "a@b.com";
private static final String USER_ID = "123";
private static final List<AuditAction> AUDIT_ACTIONS = new ArrayList<>();
private static final LocalDateTime FILTER_START_DATE = LocalDateTime.now();
private static final LocalDateTime FILTER_END_DATE = LocalDateTime.now();

@Test
void testGetAllAuditLogs() {
ResponseEntity<Page<AuditLog>> response = auditController.getAllAuditLogs(0, 25);

ResponseEntity<Page<AuditLog>> response = auditController.getAllAuditLogs(0, 25,
EMAIL, USER_ID, AUDIT_ACTIONS, FILTER_START_DATE, FILTER_END_DATE);
assertEquals(HttpStatus.OK, response.getStatusCode(), STATUS_CODE_MATCH);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import uk.gov.hmcts.reform.pip.model.enums.AuditAction;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
Expand All @@ -38,6 +39,11 @@ class AuditServiceTest {
@InjectMocks
private AuditService auditService;

private static final String EMAIL = "a@b.com";
private static final String USER_ID = "123";
private static final List<AuditAction> AUDIT_ACTIONS = new ArrayList<>();
private static final LocalDateTime FILTER_START_DATE = LocalDateTime.now();
private static final LocalDateTime FILTER_END_DATE = LocalDateTime.now();
private final AuditLog auditLogExample = new AuditLog();

@BeforeEach
Expand All @@ -48,15 +54,21 @@ void setup() {
auditLogExample.setAction(AuditAction.MANAGE_USER);
auditLogExample.setDetails("Test details for manage user");
auditLogExample.setTimestamp(LocalDateTime.now());

AUDIT_ACTIONS.add(AuditAction.ADMIN_CREATION);
}

@Test
void testGetAllAuditLogs() {
Pageable pageable = PageRequest.of(0, 25);
Page<AuditLog> page = new PageImpl<>(List.of(auditLogExample), pageable, List.of(auditLogExample).size());
when(auditRepository.findAllByOrderByTimestampDesc(pageable)).thenReturn(page);
when(auditRepository
.findAllByUserEmailLikeIgnoreCaseAndUserIdLikeAndActionInAndTimestampBetweenOrderByTimestampDesc(
"%" + EMAIL + "%", USER_ID, AUDIT_ACTIONS, FILTER_START_DATE, FILTER_END_DATE, pageable))
.thenReturn(page);

Page<AuditLog> returnedAuditLogs = auditService.getAllAuditLogs(pageable);
Page<AuditLog> returnedAuditLogs = auditService.getAllAuditLogs(pageable, EMAIL, USER_ID, AUDIT_ACTIONS,
FILTER_START_DATE, FILTER_END_DATE);

assertEquals(auditLogExample, returnedAuditLogs.getContent().get(0),
"Returned audit log does not match the expected");
Expand Down