Skip to content

Commit 269de67

Browse files
Cleanup Authorisation Filter to only call doFilter in a single place (#769)
* Add test for current covered case of Limited access. * Catch other case of limited access requests being made. * Move different authorisation methods to own functions.
1 parent d2313db commit 269de67

File tree

2 files changed

+48
-10
lines changed

2 files changed

+48
-10
lines changed

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

+21-10
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,30 @@ class AuthorisationFilter(
4343
val authoriseConsumerService = AuthoriseConsumerService()
4444
val requestedPath = req.requestURI
4545

46-
val includesResult = authoriseConsumerService.doesConsumerHaveIncludesAccess(authorisationConfig.consumers[subjectDistinguishedName], requestedPath)
47-
if (includesResult) {
46+
if (authorisedThroughIncludes(authoriseConsumerService, subjectDistinguishedName, requestedPath) ||
47+
authorisedThroughRole(authoriseConsumerService, subjectDistinguishedName, requestedPath)
48+
) {
4849
try {
4950
chain.doFilter(request, response)
5051
} catch (e: Throwable) {
51-
if (e.cause is LimitedAccessException) {
52-
res.sendError(HttpServletResponse.SC_FORBIDDEN, e.message)
52+
val cause = e.cause
53+
if (cause is LimitedAccessException) {
54+
res.sendError(HttpServletResponse.SC_FORBIDDEN, cause.message)
5355
} else {
5456
throw e
5557
}
5658
}
5759
return
60+
} else {
61+
res.sendError(HttpServletResponse.SC_FORBIDDEN, "Unable to authorise $requestedPath for $subjectDistinguishedName")
5862
}
63+
}
5964

65+
private fun authorisedThroughRole(
66+
authoriseConsumerService: AuthoriseConsumerService,
67+
subjectDistinguishedName: String?,
68+
requestedPath: String,
69+
): Boolean {
6070
val consumerConfig: ConsumerConfig? = authorisationConfig.consumers[subjectDistinguishedName]
6171
val consumersRoles = consumerConfig?.roles
6272
val rolesInclude =
@@ -67,11 +77,12 @@ class AuthorisationFilter(
6777
}
6878
val roleResult =
6979
authoriseConsumerService.doesConsumerHaveRoleAccess(rolesInclude, requestedPath)
70-
if (!roleResult) {
71-
res.sendError(HttpServletResponse.SC_FORBIDDEN, "Unable to authorise $requestedPath for $subjectDistinguishedName")
72-
return
73-
}
74-
75-
chain.doFilter(request, response)
80+
return roleResult
7681
}
82+
83+
private fun authorisedThroughIncludes(
84+
authoriseConsumerService: AuthoriseConsumerService,
85+
subjectDistinguishedName: String?,
86+
requestedPath: String,
87+
) = authoriseConsumerService.doesConsumerHaveIncludesAccess(authorisationConfig.consumers[subjectDistinguishedName], requestedPath)
7788
}

src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/extensions/AuthorisationFilterTest.kt

+27
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package uk.gov.justice.digital.hmpps.hmppsintegrationapi.extensions
22

33
import jakarta.servlet.FilterChain
4+
import jakarta.servlet.ServletException
45
import jakarta.servlet.http.HttpServletRequest
56
import jakarta.servlet.http.HttpServletResponse
67
import org.junit.jupiter.api.BeforeEach
@@ -12,6 +13,7 @@ import org.mockito.kotlin.reset
1213
import org.mockito.kotlin.whenever
1314
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.config.AuthorisationConfig
1415
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.config.GlobalsConfig
16+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.exception.LimitedAccessException
1517
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.roleconfig.ConsumerConfig
1618
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.roleconfig.ConsumerFilters
1719
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.roleconfig.Role
@@ -91,4 +93,29 @@ class AuthorisationFilterTest {
9193

9294
verify(mockResponse, times(1)).sendError(403, "No subject-distinguished-name header provided for authorisation")
9395
}
96+
97+
@Test
98+
fun `Forbidden if limited access caused by error for path not found in roles, but found in includes`() {
99+
val authorisationConfig = AuthorisationConfig()
100+
authorisationConfig.consumers = mapOf(exampleConsumer to ConsumerConfig(include = listOf(examplePath), filters = ConsumerFilters(prisons = null), roles = listOf()))
101+
val invalidRoleConfig = GlobalsConfig(roles = mapOf(roleName to Role(include = emptyList())))
102+
val authorisationFilter = AuthorisationFilter(authorisationConfig, invalidRoleConfig)
103+
whenever(mockChain.doFilter(mockRequest, mockResponse)).thenThrow(ServletException(LimitedAccessException()))
104+
105+
authorisationFilter.doFilter(mockRequest, mockResponse, mockChain)
106+
107+
verify(mockResponse, times(1)).sendError(403, "Attempt to access a limited access case")
108+
}
109+
110+
@Test
111+
fun `Forbidden if limited access caused by error for path found in roles (but not in includes)`() {
112+
val authorisationConfig = AuthorisationConfig()
113+
authorisationConfig.consumers = mapOf(exampleConsumer to ConsumerConfig(include = emptyList(), filters = ConsumerFilters(prisons = null), roles = exampleRoles))
114+
val authorisationFilter = AuthorisationFilter(authorisationConfig, exampleGlobalsConfig)
115+
whenever(mockChain.doFilter(mockRequest, mockResponse)).thenThrow(ServletException(LimitedAccessException()))
116+
117+
authorisationFilter.doFilter(mockRequest, mockResponse, mockChain)
118+
119+
verify(mockResponse, times(1)).sendError(403, "Attempt to access a limited access case")
120+
}
94121
}

0 commit comments

Comments
 (0)