Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
anthony-britton-moj authored Apr 3, 2024
1 parent 6fca0b1 commit 27e7dfe
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ abstract class AuditableService(private val auditedInteractionService: AuditedIn
protected fun <T> audit(
interactionCode: InteractionCode,
dateTime: ZonedDateTime = ZonedDateTime.now(),
username: String? = null,
params: AuditedInteraction.Parameters = AuditedInteraction.Parameters(),
code: (AuditedInteraction.Parameters) -> T
): T {
Expand All @@ -17,15 +18,17 @@ abstract class AuditableService(private val auditedInteractionService: AuditedIn
interactionCode,
params,
AuditedInteraction.Outcome.SUCCESS,
dateTime
dateTime,
username
)
return result
} catch (e: Exception) {
auditedInteractionService.createAuditedInteraction(
interactionCode,
params,
AuditedInteraction.Outcome.FAIL,
dateTime
dateTime,
username
)
throw e
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,34 @@ import uk.gov.justice.digital.hmpps.audit.repository.AuditedInteractionRepositor
import uk.gov.justice.digital.hmpps.audit.repository.BusinessInteractionRepository
import uk.gov.justice.digital.hmpps.audit.repository.getByCode
import uk.gov.justice.digital.hmpps.security.ServiceContext
import uk.gov.justice.digital.hmpps.user.AuditUserService
import java.time.ZonedDateTime

@Service
class AuditedInteractionService(
private val businessInteractionRepository: BusinessInteractionRepository,
private val auditedInteractionRepository: AuditedInteractionRepository
private val auditedInteractionRepository: AuditedInteractionRepository,
private val auditUserService: AuditUserService
) {
@Async
@Transactional(propagation = Propagation.REQUIRES_NEW)
fun createAuditedInteraction(
interactionCode: InteractionCode,
params: AuditedInteraction.Parameters,
outcome: AuditedInteraction.Outcome,
dateTime: ZonedDateTime
dateTime: ZonedDateTime,
username: String?
) {
ServiceContext.servicePrincipal()!!.let {
val bi = businessInteractionRepository.getByCode(interactionCode.code)
auditedInteractionRepository.save(
AuditedInteraction(
businessInteractionId = bi.id,
userId = it.userId,
dateTime = dateTime,
parameters = params,
outcome = outcome
)
val bi = businessInteractionRepository.getByCode(interactionCode.code)
auditedInteractionRepository.save(
AuditedInteraction(
businessInteractionId = bi.id,
userId = username?.let { auditUserService.findUser(it) }?.id
?: ServiceContext.servicePrincipal()!!.userId,
dateTime = dateTime,
parameters = params,
outcome = outcome
)
}
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import org.mockito.InjectMocks
import org.mockito.Mock
import org.mockito.junit.jupiter.MockitoExtension
import org.mockito.kotlin.any
import org.mockito.kotlin.anyOrNull
import org.mockito.kotlin.eq
import org.mockito.kotlin.verify
import uk.gov.justice.digital.hmpps.audit.BusinessInteractionCode
Expand All @@ -32,7 +33,8 @@ class AuditableServiceTest {
eq(BusinessInteractionCode.TEST_BI_CODE),
eq(AuditedInteraction.Parameters(mutableMapOf("field" to "value"))),
eq(AuditedInteraction.Outcome.SUCCESS),
any()
any(),
anyOrNull()
)
}

Expand All @@ -46,7 +48,8 @@ class AuditableServiceTest {
eq(BusinessInteractionCode.TEST_BI_CODE),
eq(AuditedInteraction.Parameters(mutableMapOf("field" to "value"))),
eq(AuditedInteraction.Outcome.FAIL),
any()
any(),
anyOrNull()
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ class AuditedInteractionServiceTest {
BusinessInteractionCode.TEST_BI_CODE,
parameters,
AuditedInteraction.Outcome.SUCCESS,
dateTime
dateTime,
null
)
val aiCaptor = ArgumentCaptor.forClass(AuditedInteraction::class.java)
verify(auditedInteractionRepository, Mockito.times(1)).save(aiCaptor.capture())
Expand All @@ -95,11 +96,44 @@ class AuditedInteractionServiceTest {
BusinessInteractionCode.TEST_BI_CODE,
parameters,
AuditedInteraction.Outcome.SUCCESS,
ZonedDateTime.now()
ZonedDateTime.now(),
null
)
}
}

@Test
fun `create audited interaction with username override`() {
setupUser()
val anotherUser = AuditUser(99, "AnotherUser")
whenever(auditUserService.findUser(anotherUser.username)).thenReturn(anotherUser)

val bi = BusinessInteraction(1, BusinessInteractionCode.TEST_BI_CODE.code, ZonedDateTime.now())
whenever(businessInteractionRepository.findByCode(eq(BusinessInteractionCode.TEST_BI_CODE.code), any()))
.thenReturn(bi)

val parameters = AuditedInteraction.Parameters(
Pair("key", "value")
)
val dateTime = ZonedDateTime.now()
auditedInteractionService.createAuditedInteraction(
BusinessInteractionCode.TEST_BI_CODE,
parameters,
AuditedInteraction.Outcome.SUCCESS,
dateTime,
anotherUser.username
)
val aiCaptor = ArgumentCaptor.forClass(AuditedInteraction::class.java)
verify(auditedInteractionRepository, Mockito.times(1)).save(aiCaptor.capture())
val saved = aiCaptor.value

assertThat(saved.businessInteractionId, equalTo(1))
assertThat(saved.outcome, equalTo(AuditedInteraction.Outcome.SUCCESS))
assertThat(saved.userId, equalTo(anotherUser.id))
assertThat(saved.parameters, equalTo(parameters))
assertThat(saved.dateTime, equalTo(dateTime))
}

@Test
fun `test audit interaction class`() {
val dateTime = ZonedDateTime.now()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class ContactServiceTest {
assertThat(it.notes, equalTo("Some notes"))
assertThat(it.externalReference, equalTo("urn"))
})
verify(auditedInteractionService).createAuditedInteraction(eq(ADD_CONTACT), any(), any(), any())
verify(auditedInteractionService).createAuditedInteraction(eq(ADD_CONTACT), any(), any(), any(), anyOrNull())
}

@Test
Expand All @@ -102,7 +102,7 @@ class ContactServiceTest {
createContact()

verify(contactRepository, never()).save(any())
verify(auditedInteractionService, never()).createAuditedInteraction(any(), any(), any(), any())
verify(auditedInteractionService, never()).createAuditedInteraction(any(), any(), any(), any(), anyOrNull())
verify(telemetryService).trackEvent("ContactAlreadyExists", mapOf("urn" to "urn"), mapOf())
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class DataLoader(
}

override fun onApplicationEvent(are: ApplicationReadyEvent) {
auditUserRepository.save(UserGenerator.SEARCH_USER)
BusinessInteractionCode.entries.forEach {
bir.save(
BusinessInteraction(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ import uk.gov.justice.digital.hmpps.user.AuditUser

object UserGenerator {
val AUDIT_USER = AuditUser(IdGenerator.getAndIncrement(), "ProbationSearchAndDelius")
val SEARCH_USER = AuditUser(IdGenerator.getAndIncrement(), "SearchUser")
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
import uk.gov.justice.digital.hmpps.audit.entity.AuditedInteraction
import uk.gov.justice.digital.hmpps.audit.repository.AuditedInteractionRepository
import uk.gov.justice.digital.hmpps.data.generator.UserGenerator
import uk.gov.justice.digital.hmpps.service.ContactSearchAuditRequest
import uk.gov.justice.digital.hmpps.service.ContactSearchRequest
import uk.gov.justice.digital.hmpps.service.PageRequest
Expand Down Expand Up @@ -54,6 +55,7 @@ internal class IntegrationTest {
.withJson(
ContactSearchAuditRequest(
ContactSearchRequest(crn, query, true),
"SearchUser",
PageRequest(page, pageSize, sort, direction),
dateTime
)
Expand All @@ -64,13 +66,14 @@ internal class IntegrationTest {
verify(air, timeout(2000)).save(audit.capture())

val saved = audit.firstValue
assertThat(saved.userId, equalTo(UserGenerator.SEARCH_USER.id))
assertThat(saved.parameters["crn"], equalTo(crn))
assertThat(saved.parameters["query"], equalTo(query))
assertThat(saved.parameters["matchAllTerms"], equalTo(true))
assertThat(saved.parameters["page"], equalTo(page))
assertThat(saved.parameters["pageSize"], equalTo(pageSize))
assertThat(saved.parameters["sort"], equalTo(sort))
assertThat(saved.parameters["direction"], equalTo(direction))
assertThat(saved.parameters["sortedBy"], equalTo(sort))
assertThat(saved.parameters["sortDirection"], equalTo(direction))
assertThat(saved.dateTime, isCloseTo(dateTime))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import uk.gov.justice.digital.hmpps.integrations.delius.audit.BusinessInteractio
import java.time.ZonedDateTime

@Service
class SearchAuditService(auditedInteractionService: AuditedInteractionService) :
AuditableService(auditedInteractionService) {
class SearchAuditService(
auditedInteractionService: AuditedInteractionService
) : AuditableService(auditedInteractionService) {
fun auditContactSearch(auditRequest: ContactSearchAuditRequest) =
audit(BusinessInteractionCode.SEARCH_CONTACTS, auditRequest.dateTime) { audit ->
audit(BusinessInteractionCode.SEARCH_CONTACTS, auditRequest.dateTime, auditRequest.username) { audit ->
with(auditRequest.search) {
audit["crn"] = crn
query?.also { audit["query"] = it }
Expand All @@ -19,14 +20,15 @@ class SearchAuditService(auditedInteractionService: AuditedInteractionService) :
with(auditRequest.pagination) {
audit["page"] = page
audit["pageSize"] = pageSize
sort?.also { audit["sort"] = it }
direction?.also { audit["direction"] = it }
sort?.also { audit["sortedBy"] = it }
direction?.also { audit["sortDirection"] = it }
}
}
}

data class ContactSearchAuditRequest(
val search: ContactSearchRequest,
val username: String,
val pagination: PageRequest,
val dateTime: ZonedDateTime
)
Expand Down

0 comments on commit 27e7dfe

Please sign in to comment.