Skip to content

Commit f2dc5ea

Browse files
HIA-775 Implement LAO Redaction (#763)
* HIA-775 implement LAO redaction
1 parent b16733b commit f2dc5ea

File tree

66 files changed

+840
-25
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+840
-25
lines changed

build.gradle.kts

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import org.gradle.internal.impldep.org.junit.experimental.categories.Categories.CategoryFilter.exclude
2+
13
plugins {
24
id("uk.gov.justice.hmpps.gradle-spring-boot") version "7.1.3"
35
kotlin("plugin.spring") version "2.1.10"
@@ -9,11 +11,13 @@ configurations {
911

1012
dependencies {
1113
runtimeOnly("org.flywaydb:flyway-database-postgresql")
12-
implementation("org.springframework.boot:spring-boot-starter-webflux:3.4.3")
14+
implementation("org.springframework.boot:spring-boot-starter-webflux")
1315
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.0")
1416
implementation("io.sentry:sentry-spring-boot-starter-jakarta:8.3.0")
1517
implementation("io.sentry:sentry-logback:8.3.0")
16-
implementation("org.springframework.data:spring-data-commons:3.4.3")
18+
implementation("org.springframework.data:spring-data-commons")
19+
implementation("org.springframework:spring-aop")
20+
implementation("org.aspectj:aspectjweaver")
1721
implementation("uk.gov.justice.service.hmpps:hmpps-sqs-spring-boot-starter:5.3.2") {
1822
exclude("org.springframework.security", "spring-security-config")
1923
exclude("org.springframework.security", "spring-security-core")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package uk.gov.justice.digital.hmpps.hmppsintegrationapi.common
2+
3+
interface CrnSupplier {
4+
fun getCrn(hmppsId: String): String?
5+
6+
companion object {
7+
val CRN_REGEX = "^[A-Z]\\d{6}$".toRegex()
8+
}
9+
}

src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/config/HmppsIntegrationApiExceptionHandler.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import uk.gov.justice.digital.hmpps.hmppsintegrationapi.exception.ConflictFoundE
1919
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.exception.EntityNotFoundException
2020
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.exception.ForbiddenByUpstreamServiceException
2121
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.exception.HmppsAuthFailedException
22+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.exception.LimitedAccessException
2223
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.exception.MessageFailedException
2324

2425
@RestControllerAdvice
@@ -80,7 +81,7 @@ class HmppsIntegrationApiExceptionHandler {
8081
)
8182
}
8283

83-
@ExceptionHandler(ForbiddenByUpstreamServiceException::class)
84+
@ExceptionHandler(ForbiddenByUpstreamServiceException::class, LimitedAccessException::class)
8485
fun handleAuthenticationFailedException(e: ForbiddenByUpstreamServiceException): ResponseEntity<ErrorResponse?>? {
8586
logAndCapture("Forbidden to complete action by upstream service: {}", e)
8687
return ResponseEntity

src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/RiskManagementController.kt

+3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import uk.gov.justice.digital.hmpps.hmppsintegrationapi.config.AuthorisationConf
1616
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.exception.EntityNotFoundException
1717
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.exception.ForbiddenByUpstreamServiceException
1818
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.extensions.decodeUrlCharacters
19+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess.redactor.LaoRedaction
20+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess.redactor.LaoRedaction.Mode
1921
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.RiskManagementPlan
2022
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApi
2123
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApiError
@@ -31,6 +33,7 @@ class RiskManagementController(
3133
@Autowired val getRiskManagementPlansForCrnService: GetRiskManagementPlansForCrnService,
3234
@Autowired val auditService: AuditService,
3335
) {
36+
@LaoRedaction(Mode.REJECT)
3437
@GetMapping("/v1/persons/{encodedHmppsId}/risk-management-plan")
3538
@Operation(
3639
summary = "Returns a list of Risk Management Plans created for the person with the provided HMPPS ID.",

src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/DynamicRisksController.kt

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import org.springframework.web.bind.annotation.RequestParam
1515
import org.springframework.web.bind.annotation.RestController
1616
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.exception.EntityNotFoundException
1717
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.extensions.decodeUrlCharacters
18+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess.redactor.LaoRedaction
19+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess.redactor.LaoRedaction.Mode
1820
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.DynamicRisk
1921
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApiError
2022
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.GetDynamicRisksForPersonService
@@ -29,6 +31,7 @@ class DynamicRisksController(
2931
@Autowired val getDynamicRisksForPersonService: GetDynamicRisksForPersonService,
3032
@Autowired val auditService: AuditService,
3133
) {
34+
@LaoRedaction(Mode.REDACT)
3235
@GetMapping("{encodedHmppsId}/risks/dynamic")
3336
@Operation(
3437
summary = "Returns dynamic risks associated with a person.",

src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/LicenceConditionController.kt

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import org.springframework.web.bind.annotation.RequestMapping
1313
import org.springframework.web.bind.annotation.RestController
1414
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.exception.EntityNotFoundException
1515
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.extensions.decodeUrlCharacters
16+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess.redactor.LaoRedaction
17+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess.redactor.LaoRedaction.Mode
1618
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.DataResponse
1719
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.PersonLicences
1820
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApiError
@@ -26,6 +28,7 @@ class LicenceConditionController(
2628
@Autowired val auditService: AuditService,
2729
@Autowired val getLicenceConditionService: GetLicenceConditionService,
2830
) {
31+
@LaoRedaction(Mode.REDACT)
2932
@GetMapping("{encodedHmppsId}/licences/conditions")
3033
@Operation(
3134
summary = "Returns license conditions associated with a person, sorted by createdDateTime (newest first).",

src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/MappaDetailController.kt

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import org.springframework.web.bind.annotation.RequestMapping
1414
import org.springframework.web.bind.annotation.RestController
1515
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.exception.EntityNotFoundException
1616
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.extensions.decodeUrlCharacters
17+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess.redactor.LaoRedaction
18+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess.redactor.LaoRedaction.Mode
1719
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.DataResponse
1820
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.MappaDetail
1921
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApiError
@@ -27,6 +29,7 @@ class MappaDetailController(
2729
@Autowired val getMappaDetailForPersonService: GetMappaDetailForPersonService,
2830
@Autowired val auditService: AuditService,
2931
) {
32+
@LaoRedaction(Mode.REDACT)
3033
@GetMapping("{encodedHmppsId}/risks/mappadetail")
3134
@Operation(
3235
summary = "Returns the mappa detail related to a person.",

src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/RiskSeriousHarmController.kt

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import org.springframework.web.bind.annotation.RequestMapping
1313
import org.springframework.web.bind.annotation.RestController
1414
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.exception.EntityNotFoundException
1515
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.extensions.decodeUrlCharacters
16+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess.redactor.LaoRedaction
17+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess.redactor.LaoRedaction.Mode
1618
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.DataResponse
1719
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Risks
1820
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApiError
@@ -26,6 +28,7 @@ class RiskSeriousHarmController(
2628
@Autowired val getRiskSeriousHarmForPersonService: GetRiskSeriousHarmForPersonService,
2729
@Autowired val auditService: AuditService,
2830
) {
31+
@LaoRedaction(Mode.REDACT)
2932
@GetMapping("{encodedHmppsId}/risks/serious-harm")
3033
@Operation(
3134
summary = "Returns Risk of Serious Harm (ROSH) risks associated with a person. Returns only assessments completed in the last year. This endpoint does not serve LAO (Limited Access Offender) data.",

src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/StatusInformationController.kt

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import org.springframework.web.bind.annotation.RequestParam
1515
import org.springframework.web.bind.annotation.RestController
1616
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.exception.EntityNotFoundException
1717
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.extensions.decodeUrlCharacters
18+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess.redactor.LaoRedaction
19+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess.redactor.LaoRedaction.Mode
1820
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.StatusInformation
1921
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApiError
2022
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.GetStatusInformationForPersonService
@@ -29,6 +31,7 @@ class StatusInformationController(
2931
@Autowired val getStatusInformationForPersonService: GetStatusInformationForPersonService,
3032
@Autowired val auditService: AuditService,
3133
) {
34+
@LaoRedaction(Mode.REDACT)
3235
@GetMapping("{encodedHmppsId}/status-information")
3336
@Operation(
3437
summary = "Returns the status information associated with a person.",

src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/exception/AuthorisationFailedException.kt

-7
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package uk.gov.justice.digital.hmpps.hmppsintegrationapi.exception
2+
3+
class LimitedAccessException : RuntimeException("Attempt to access a limited access case")

src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/extensions/AuthorisationFilter.kt

+10-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import org.springframework.core.annotation.Order
1313
import org.springframework.stereotype.Component
1414
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.config.AuthorisationConfig
1515
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.config.GlobalsConfig
16+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.exception.LimitedAccessException
1617
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.roleconfig.ConsumerConfig
1718
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.internal.AuthoriseConsumerService
1819
import java.io.IOException
@@ -44,7 +45,15 @@ class AuthorisationFilter(
4445

4546
val includesResult = authoriseConsumerService.doesConsumerHaveIncludesAccess(authorisationConfig.consumers[subjectDistinguishedName], requestedPath)
4647
if (includesResult) {
47-
chain.doFilter(request, response)
48+
try {
49+
chain.doFilter(request, response)
50+
} catch (e: Throwable) {
51+
if (e.cause is LimitedAccessException) {
52+
res.sendError(HttpServletResponse.SC_FORBIDDEN, e.message)
53+
} else {
54+
throw e
55+
}
56+
}
4857
return
4958
}
5059

src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/gateways/NDeliusGateway.kt

+22
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Response
1414
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Sentence
1515
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.StatusInformation
1616
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApi
17+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.ndelius.CaseAccess
1718
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.ndelius.NDeliusSupervisions
19+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.ndelius.UserAccess
1820

1921
@Component
2022
class NDeliusGateway(
@@ -162,6 +164,26 @@ class NDeliusGateway(
162164
}
163165
}
164166

167+
fun getCaseAccess(crn: String): Response<CaseAccess?> {
168+
val result =
169+
webClient.request<UserAccess>(
170+
HttpMethod.POST,
171+
"/probation-cases/access",
172+
authenticationHeader(),
173+
UpstreamApi.NDELIUS,
174+
mapOf("crns" to listOf(crn)),
175+
)
176+
return when (result) {
177+
is WebClientWrapperResponse.Success -> {
178+
Response(result.data.access.firstOrNull { it.crn == crn })
179+
}
180+
181+
is WebClientWrapperResponse.Error -> {
182+
Response(null, result.errors)
183+
}
184+
}
185+
}
186+
165187
private fun authenticationHeader(): Map<String, String> {
166188
val token = hmppsAuthGateway.getClientToken("nDelius")
167189

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess
2+
3+
import org.springframework.stereotype.Service
4+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.common.CrnSupplier
5+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.gateways.NDeliusGateway
6+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.ndelius.CaseAccess
7+
8+
interface AccessFor {
9+
fun getAccessFor(hmppsId: String): CaseAccess?
10+
}
11+
12+
@Service
13+
class GetCaseAccess(
14+
private val crnSupplier: CrnSupplier,
15+
private val deliusApi: NDeliusGateway,
16+
) : AccessFor {
17+
override fun getAccessFor(hmppsId: String): CaseAccess? = crnSupplier.getCrn(hmppsId)?.let { deliusApi.getCaseAccess(it).data }
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess
2+
3+
data class LaoContext(
4+
val crn: String,
5+
val excluded: Boolean,
6+
val restricted: Boolean,
7+
val excludedMessage: String?,
8+
val restrictedMessage: String?,
9+
) {
10+
fun isLimitedAccess() = excluded || restricted
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess.redactor
2+
3+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess.redactor.Redactor.Companion.REDACTED
4+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.DynamicRisk
5+
6+
object LaoDynamicRiskRedactor : Redactor<DynamicRisk> {
7+
override val type = DynamicRisk::class
8+
9+
override fun redact(toRedact: Any): DynamicRisk =
10+
when (toRedact) {
11+
is DynamicRisk -> toRedact.copy(notes = REDACTED)
12+
else -> throw IllegalArgumentException("${this::class.simpleName} unable to redact ${toRedact::class.simpleName}")
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess.redactor
2+
3+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess.redactor.Redactor.Companion.REDACTED
4+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.MappaDetail
5+
6+
object LaoMappaDetailRedactor : Redactor<MappaDetail> {
7+
override val type = MappaDetail::class
8+
9+
override fun redact(toRedact: Any): MappaDetail =
10+
when (toRedact) {
11+
is MappaDetail -> toRedact.copy(notes = REDACTED)
12+
else -> throw IllegalArgumentException("${this::class.simpleName} unable to redact ${toRedact::class.simpleName}")
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess.redactor
2+
3+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.PersonLicences
4+
5+
object LaoPersonLicencesRedactor : Redactor<PersonLicences> {
6+
override val type = PersonLicences::class
7+
8+
override fun redact(toRedact: Any): PersonLicences =
9+
when (toRedact) {
10+
is PersonLicences -> toRedact.copy(licences = toRedact.licences.map { it.copy(conditions = it.conditions.map { it.copy(condition = Redactor.REDACTED) }) })
11+
else -> throw IllegalArgumentException("${this::class.simpleName} unable to redact ${toRedact::class.simpleName}")
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess.redactor
2+
3+
import kotlin.reflect.KClass
4+
5+
interface Redactor<T : Any> {
6+
val type: KClass<T>
7+
8+
fun redact(toRedact: Any): T
9+
10+
companion object {
11+
const val REDACTED = "**REDACTED**"
12+
}
13+
}
14+
15+
object LaoRedactor {
16+
private val redactors =
17+
setOf(
18+
LaoPersonLicencesRedactor,
19+
LaoStatusInformationRedactor,
20+
LaoMappaDetailRedactor,
21+
LaoDynamicRiskRedactor,
22+
LaoRisksRedactor,
23+
)
24+
25+
@Suppress("UNCHECKED_CAST")
26+
fun of(any: Any): Redactor<*>? = redactors.firstOrNull { it.type == any::class }
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess.redactor
2+
3+
import org.aspectj.lang.ProceedingJoinPoint
4+
import org.aspectj.lang.annotation.Around
5+
import org.aspectj.lang.annotation.Aspect
6+
import org.springframework.context.annotation.Configuration
7+
import org.springframework.context.annotation.EnableAspectJAutoProxy
8+
import org.springframework.stereotype.Component
9+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.exception.LimitedAccessException
10+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.extensions.decodeUrlCharacters
11+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess.AccessFor
12+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess.LaoContext
13+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.limitedaccess.redactor.LaoRedaction.Mode
14+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.DataResponse
15+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.ndelius.CaseAccess
16+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.util.PaginatedResponse
17+
18+
@Configuration
19+
@EnableAspectJAutoProxy
20+
class AopConfig
21+
22+
@Aspect
23+
@Component
24+
class LaoRedactorAspect(
25+
private val loaChecker: AccessFor,
26+
) {
27+
@Around("@annotation(redaction)")
28+
fun redact(
29+
joinPoint: ProceedingJoinPoint,
30+
redaction: LaoRedaction,
31+
): Any {
32+
val hmppsId = (joinPoint.args.first() as String).decodeUrlCharacters()
33+
val laoContext = loaChecker.getAccessFor(hmppsId)?.asLaoContext()
34+
if (laoContext?.isLimitedAccess() == true && redaction.mode == Mode.REJECT) {
35+
throw LimitedAccessException()
36+
}
37+
val result = joinPoint.proceed()
38+
return if (laoContext?.isLimitedAccess() == true) {
39+
when (result) {
40+
is DataResponse<*> -> redactDataResponse(result)
41+
is PaginatedResponse<*> -> redactPaginatedResponse(result)
42+
else -> LaoRedactor.of(result)?.redact(result) ?: result
43+
}
44+
} else {
45+
result
46+
}
47+
}
48+
49+
private fun redactDataResponse(dataResponse: DataResponse<*>): DataResponse<*> = LaoRedactor.of(dataResponse.data as Any)?.redact(dataResponse.data)?.let { DataResponse(it) } ?: dataResponse
50+
51+
private fun redactPaginatedResponse(paginatedResponse: PaginatedResponse<*>): PaginatedResponse<*> {
52+
val redactor = paginatedResponse.data.firstOrNull()?.let { LaoRedactor.of(it) }
53+
return PaginatedResponse(
54+
paginatedResponse.data.map { redactor?.redact(it as Any) ?: it },
55+
paginatedResponse.pagination,
56+
)
57+
}
58+
59+
private fun CaseAccess.asLaoContext() = LaoContext(crn, userExcluded, userRestricted, exclusionMessage, restrictionMessage)
60+
}
61+
62+
@Target(AnnotationTarget.FUNCTION)
63+
@Retention(AnnotationRetention.RUNTIME)
64+
annotation class LaoRedaction(
65+
val mode: Mode = Mode.REDACT,
66+
) {
67+
enum class Mode {
68+
REDACT,
69+
REJECT,
70+
}
71+
}

0 commit comments

Comments
 (0)