Skip to content

Commit

Permalink
PI-2603 Update LAO endpoints to use staff code
Browse files Browse the repository at this point in the history
  • Loading branch information
marcus-bcl committed Oct 24, 2024
1 parent 40cc317 commit 0a4e56a
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import uk.gov.justice.digital.hmpps.entity.LimitedAccessPerson
import uk.gov.justice.digital.hmpps.entity.LimitedAccessUser
import uk.gov.justice.digital.hmpps.entity.Restriction
import uk.gov.justice.digital.hmpps.integrations.delius.person.Person
import uk.gov.justice.digital.hmpps.integrations.delius.provider.StaffWithUser
import uk.gov.justice.digital.hmpps.user.AuditUser
import java.time.LocalDateTime

Expand All @@ -13,19 +14,20 @@ object LimitedAccessGenerator {
val RESTRICTION = generateRestriction(endDateTime = LocalDateTime.now().plusHours(1))

fun generateExclusion(
user: AuditUser = UserGenerator.LIMITED_ACCESS_USER,
user: LimitedAccessUser = UserGenerator.LIMITED_ACCESS_USER.limitedAccess(),
person: Person = PersonGenerator.EXCLUSION,
endDateTime: LocalDateTime? = null,
id: Long = IdGenerator.getAndIncrement()
) = Exclusion(person.limitedAccess(), user.limitedAccess(), endDateTime, id)
) = Exclusion(person.limitedAccess(), user, endDateTime, id)

fun generateRestriction(
user: AuditUser = UserGenerator.AUDIT_USER,
user: LimitedAccessUser = StaffGenerator.STAFF_WITH_USER.limitedAccess(),
person: Person = PersonGenerator.RESTRICTION,
endDateTime: LocalDateTime? = null,
id: Long = IdGenerator.getAndIncrement()
) = Restriction(person.limitedAccess(), user.limitedAccess(), endDateTime, id)
) = Restriction(person.limitedAccess(), user, endDateTime, id)

private fun Person.limitedAccess() = LimitedAccessPerson(crn, exclusionMessage, restrictionMessage, id)
private fun AuditUser.limitedAccess() = LimitedAccessUser(username, id)
private fun StaffWithUser.limitedAccess() = LimitedAccessUser(user!!.username, user!!.id)
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ import uk.gov.justice.digital.hmpps.api.model.CaseAccess
import uk.gov.justice.digital.hmpps.api.model.CaseAccessList
import uk.gov.justice.digital.hmpps.api.model.User
import uk.gov.justice.digital.hmpps.api.model.UserAccess
import uk.gov.justice.digital.hmpps.data.generator.LimitedAccessGenerator
import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator
import uk.gov.justice.digital.hmpps.data.generator.StaffGenerator
import uk.gov.justice.digital.hmpps.data.generator.UserGenerator
import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.andExpectJson
import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.contentAsJson
Expand All @@ -39,7 +41,7 @@ class UserIntegrationTest {
@Test
fun `limited access controls are correctly returned`() {
val result = mockMvc.perform(
post("/users/limited-access?username=${UserGenerator.LIMITED_ACCESS_USER.username}")
post("/users/limited-access?username=${LimitedAccessGenerator.EXCLUSION.user.username}")
.withToken()
.withJson(
listOf(
Expand Down Expand Up @@ -100,7 +102,7 @@ class UserIntegrationTest {
@Test
fun `limited access controls do not prevent legitimate access`() {
val result = mockMvc.perform(
post("/users/limited-access?username=${UserGenerator.AUDIT_USER.username}")
post("/users/limited-access?username=${LimitedAccessGenerator.RESTRICTION.user.username}")
.withToken()
.withJson(
listOf(
Expand Down Expand Up @@ -131,25 +133,31 @@ class UserIntegrationTest {
.andExpectJson(
CaseAccessList(
crn = PersonGenerator.RESTRICTION_EXCLUSION.crn,
excludedFrom = listOf(User(UserGenerator.LIMITED_ACCESS_USER.username)),
restrictedTo = listOf(User(UserGenerator.AUDIT_USER.username)),
excludedFrom = listOf(User(UserGenerator.LIMITED_ACCESS_USER.username, null)),
restrictedTo = listOf(
User(
StaffGenerator.STAFF_WITH_USER.user!!.username,
StaffGenerator.STAFF_WITH_USER.code
)
),
exclusionMessage = PersonGenerator.RESTRICTION_EXCLUSION.exclusionMessage,
restrictionMessage = PersonGenerator.RESTRICTION_EXCLUSION.restrictionMessage,
)
)
}

@Test
fun `get all access limitations filtered by username`() {
fun `get all access limitations filtered by staff code`() {
val staff = StaffGenerator.STAFF_WITH_USER
mockMvc.perform(
post("/person/${PersonGenerator.RESTRICTION_EXCLUSION.crn}/limited-access")
.withToken()
.withJson(listOf(UserGenerator.AUDIT_USER.username))
.withJson(listOf(staff.code))
).andExpectJson(
CaseAccessList(
crn = PersonGenerator.RESTRICTION_EXCLUSION.crn,
excludedFrom = emptyList(),
restrictedTo = listOf(User(UserGenerator.AUDIT_USER.username)),
restrictedTo = listOf(User(staff.user!!.username, staff.code)),
exclusionMessage = PersonGenerator.RESTRICTION_EXCLUSION.exclusionMessage,
restrictionMessage = PersonGenerator.RESTRICTION_EXCLUSION.restrictionMessage,
)
Expand All @@ -158,7 +166,7 @@ class UserIntegrationTest {
mockMvc.perform(
post("/person/${PersonGenerator.RESTRICTION_EXCLUSION.crn}/limited-access")
.withToken()
.withJson(listOf("SomeOtherUsername"))
.withJson(listOf("OTHER"))
).andExpectJson(
CaseAccessList(
crn = PersonGenerator.RESTRICTION_EXCLUSION.crn,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ data class Name(
data class Event(val number: String, val manager: Manager? = null)
data class Sentence(val type: String, val date: LocalDate, val length: String)

data class User(val username: String)
data class User(val username: String, val staffCode: String?)

data class StaffMember(
val code: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,13 @@ import io.swagger.v3.oas.annotations.Operation
import jakarta.validation.constraints.Size
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.web.bind.annotation.*
import uk.gov.justice.digital.hmpps.api.model.User
import uk.gov.justice.digital.hmpps.service.LdapService
import uk.gov.justice.digital.hmpps.service.UserAccessService
import uk.gov.justice.digital.hmpps.service.UserService

@RestController
class UserResource(
private val userAccessService: UserAccessService,
private val userService: UserService,
private val ldapService: LdapService,
) {

@PreAuthorize("hasRole('PROBATION_API__WORKFORCE_ALLOCATIONS__CASE_DETAIL')")
Expand All @@ -37,7 +34,7 @@ class UserResource(

@GetMapping("/users")
@Operation(summary = "Returns all users with the Delius `MAABT001` role")
fun allUsers() = ldapService.findAllUsersWithRole().map { User(it) }
fun allUsers() = userService.findAllUsersWithRole()

@GetMapping("/person/{crn}/limited-access/all")
@Operation(summary = "Returns all limited access information (restrictions and exclusions) for a Delius CRN")
Expand All @@ -47,7 +44,7 @@ class UserResource(
@Operation(summary = "Returns limited access information (restrictions and exclusions) for a Delius CRN, given a list of staff codes")
fun allAccessLimitationsForCrnAndUserList(
@PathVariable crn: String,
@Size(min = 0, max = 500, message = "Please provide up to 500 usernames to filter by")
@RequestBody(required = false) usernames: List<String>? = null,
) = userService.getAllAccessLimitations(crn, usernames)
@Size(min = 0, max = 500, message = "Please provide up to 500 staff codes to filter by")
@RequestBody(required = false) staffCodes: List<String>? = null,
) = userService.getAllAccessLimitations(crn, staffCodes)
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ interface StaffRepository : JpaRepository<StaffRecord, Long> {
@Query("select s from StaffWithUser s where upper(s.user.username) = upper(:username)")
fun findStaffWithUserByUsername(username: String): StaffWithUser?

@EntityGraph(attributePaths = ["user"])
@Query("select s from StaffWithUser s where upper(s.user.username) in :usernamesUppercase")
fun findStaffForUsernamesIn(
usernames: List<String>,
usernamesUppercase: List<String> = usernames.map { it.uppercase() }
): List<StaffWithUser>

@EntityGraph(attributePaths = ["grade.dataset"])
fun findByCode(code: String): Staff?

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ class LdapService(private val ldapTemplate: LdapTemplate) {
.associate { it.username to it.email }

@WithSpan
fun findAllUsersWithRole(role: String = "MAABT001"): List<String> = ldapTemplate.search(LdapQueryBuilder.query()
fun findAllUsersWithRole(role: String): List<String> = ldapTemplate.search(
LdapQueryBuilder.query()
.attributes("entryDN")
.searchScope(SearchScope.SUBTREE)
.where("cn").`is`(role)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,39 @@ import uk.gov.justice.digital.hmpps.api.model.CaseAccessList
import uk.gov.justice.digital.hmpps.api.model.User
import uk.gov.justice.digital.hmpps.exception.NotFoundException
import uk.gov.justice.digital.hmpps.integrations.delius.person.PersonRepository
import uk.gov.justice.digital.hmpps.integrations.delius.provider.StaffRepository
import uk.gov.justice.digital.hmpps.integrations.delius.user.ExclusionRepository
import uk.gov.justice.digital.hmpps.integrations.delius.user.RestrictionRepository

@Service
class UserService(
private val personRepository: PersonRepository,
private val exclusionRepository: ExclusionRepository,
private val restrictionRepository: RestrictionRepository
private val restrictionRepository: RestrictionRepository,
private val staffRepository: StaffRepository,
private val ldapService: LdapService,
) {
fun getAllAccessLimitations(crn: String, usernamesFilter: List<String>? = null): CaseAccessList {
fun getAllAccessLimitations(crn: String, staffCodesFilter: List<String>? = null): CaseAccessList {
val person = personRepository.findByCrnAndSoftDeletedFalse(crn) ?: throw NotFoundException("Person", "crn", crn)
val exclusions = exclusionRepository.findByPersonId(person.id).map { it.user.username }
val restrictions = restrictionRepository.findByPersonId(person.id).map { it.user.username }
val staffCodes = staffRepository.findStaffForUsernamesIn(exclusions + restrictions)
.associate { it.user?.username to it.code }
return CaseAccessList(
crn = crn,
exclusionMessage = person.exclusionMessage,
restrictionMessage = person.restrictionMessage,
excludedFrom = exclusionRepository.findByPersonId(person.id).map { it.user.username }
.filter { usernamesFilter == null || it in usernamesFilter }
.map { User(it) },
restrictedTo = restrictionRepository.findByPersonId(person.id).map { it.user.username }
.filter { usernamesFilter == null || it in usernamesFilter }
.map { User(it) },
excludedFrom = exclusions.map { User(it, staffCodes[it]) }
.filter { staffCodesFilter == null || it.staffCode in staffCodesFilter },
restrictedTo = restrictions.map { User(it, staffCodes[it]) }
.filter { staffCodesFilter == null || it.staffCode in staffCodesFilter },
)
}

fun findAllUsersWithRole(role: String = "MAABT001"): List<User> {
val usernames = ldapService.findAllUsersWithRole(role)
val staff = staffRepository.findStaffForUsernamesIn(usernames)
return staff.map { User(it.user!!.username, it.code) }
}
}

0 comments on commit 0a4e56a

Please sign in to comment.