Skip to content

Commit

Permalink
PI-2479: Return not found when LDAP user not found
Browse files Browse the repository at this point in the history
  • Loading branch information
pmcphee77 committed Sep 17, 2024
1 parent b21ff8e commit 5aabf7f
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package uk.gov.justice.digital.hmpps.ldap

import io.opentelemetry.instrumentation.annotations.SpanAttribute
import io.opentelemetry.instrumentation.annotations.WithSpan
import org.springframework.ldap.NameNotFoundException
import org.springframework.ldap.core.AttributesMapper
import org.springframework.ldap.core.LdapTemplate
import org.springframework.ldap.query.LdapQuery
Expand All @@ -25,26 +26,32 @@ inline fun <reified T> LdapTemplate.findByUsername(@SpanAttribute username: Stri
fun LdapTemplate.findEmailByUsername(@SpanAttribute username: String) = findAttributeByUsername(username, "mail")

@WithSpan
fun LdapTemplate.findAttributeByUsername(@SpanAttribute username: String, @SpanAttribute attribute: String) = search(
query()
fun LdapTemplate.findAttributeByUsername(@SpanAttribute username: String, @SpanAttribute attribute: String) = try {
search(query()
.attributes(attribute)
.searchScope(SearchScope.ONELEVEL)
.where("objectclass").`is`("inetOrgPerson")
.and("objectclass").`is`("top")
.and("cn").`is`(username),
AttributesMapper { it[attribute]?.get()?.toString() }
).singleOrNull()
AttributesMapper { it[attribute]?.get()?.toString() }
).singleOrNull()
} catch (_: NameNotFoundException) {
throw NotFoundException("NDeliusUser of $username not found")
}

@WithSpan
fun LdapTemplate.getRoles(@SpanAttribute username: String) = search(
query()
fun LdapTemplate.getRoles(@SpanAttribute username: String) = try {
search(query()
.attributes("cn")
.base(LdapNameBuilder.newInstance().add("cn", username).build())
.searchScope(SearchScope.ONELEVEL)
.where("objectclass").`is`("NDRole")
.or("objectclass").`is`("NDRoleAssociation"),
AttributesMapper { it["cn"]?.get()?.toString() }
).filterNotNull()
AttributesMapper { it["cn"]?.get()?.toString() }
).filterNotNull()
} catch (_: NameNotFoundException) {
throw NotFoundException("NDeliusUser of $username not found")
}

@WithSpan
fun LdapTemplate.addRole(@SpanAttribute username: String, @SpanAttribute role: DeliusRole) {
Expand All @@ -56,12 +63,20 @@ fun LdapTemplate.addRole(@SpanAttribute username: String, @SpanAttribute role: D
put(listOf("NDRoleAssociation", "alias", "top").asAttribute("objectclass"))
}
val userRole = role.context(username)
rebind(userRole, null, attributes)
try {
rebind(userRole, null, attributes)
} catch (_: NameNotFoundException) {
throw NotFoundException("NDeliusUser of $username not found")
}
}

@WithSpan
fun LdapTemplate.removeRole(@SpanAttribute username: String, @SpanAttribute role: DeliusRole) =
unbind(role.context(username))
try {
unbind(role.context(username))
} catch (_: NameNotFoundException) {
throw NotFoundException("NDeliusUser of $username not found")
}

private fun DeliusRole.context(username: String? = null) =
LdapNameBuilder.newInstance()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import org.junit.jupiter.api.extension.ExtendWith
import org.mockito.Mock
import org.mockito.junit.jupiter.MockitoExtension
import org.mockito.kotlin.*
import org.springframework.ldap.NameNotFoundException
import org.springframework.ldap.core.AttributesMapper
import org.springframework.ldap.core.DirContextOperations
import org.springframework.ldap.core.LdapTemplate
import uk.gov.justice.digital.hmpps.exception.NotFoundException
import uk.gov.justice.digital.hmpps.ldap.entity.LdapUser
import javax.naming.Name
import javax.naming.directory.Attributes
import javax.naming.ldap.LdapName

Expand Down Expand Up @@ -116,4 +118,59 @@ class LdapTemplateExtensionsTest {
assertThat(it.toString(), equalTo("cn=ROLE1,cn=john-smith"))
})
}

@Test
fun `unknown username throws NotFoundException when getting roles`() {

whenever(ldapTemplate.search(any(), any<AttributesMapper<String?>>()))
.thenThrow(NameNotFoundException("No Such Object"))

assertThrows<NotFoundException> { ldapTemplate.getRoles("test") }
}

@Test
fun `unknown username throws NotFoundException finding by username`() {

whenever(ldapTemplate.search(any(), any<AttributesMapper<String?>>()))
.thenThrow(NameNotFoundException("No Such Object"))

assertThrows<NotFoundException> { ldapTemplate.findEmailByUsername("test") }
}

@Test
fun `unknown username throws NotFoundException when adding roles`() {
whenever(ldapTemplate.lookupContext(any<LdapName>()))
.thenReturn(dirContextOperations)
whenever(dirContextOperations.nameInNamespace)
.thenReturn("cn=ROLE1,cn=ndRoleCatalogue,ou=Users,dc=moj,dc=com")

whenever(ldapTemplate.rebind(any<Name>(), anyOrNull(), any<Attributes>())).thenThrow(
NameNotFoundException("No Such Object")
)
whenever(ldapTemplate.unbind(any<Name>())).thenThrow(
NameNotFoundException("No Such Object")
)

assertThrows<NotFoundException> {
ldapTemplate.addRole(
"test",
object : DeliusRole {
override val description = "Role One Description"
override val mappedRole = "MAPPED_ROLE_ONE"
override val name = "ROLE1"
}
)
}

assertThrows<NotFoundException> {
ldapTemplate.removeRole(
"test",
object : DeliusRole {
override val description = "Role One Description"
override val mappedRole = "MAPPED_ROLE_ONE"
override val name = "ROLE1"
}
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,16 @@ internal class UserIntegrationTest {
mockMvc.perform(delete("/users/test.user/roles/LHDCBT003").withToken())
.andExpect(status().isOk)
}

@Test
fun `non existent user returns not found`() {
mockMvc.perform(put("/users/nonexistent.user/roles/LHDCBT003").withToken())
.andExpect(status().isNotFound)
mockMvc
.perform(delete("/users/nonexistent.user/roles/LHDCBT003").withToken())
.andExpect(status().isNotFound)
mockMvc
.perform(get("/users/nonexistent.user/details").withToken())
.andExpect(status().isNotFound)
}
}

0 comments on commit 5aabf7f

Please sign in to comment.