Skip to content

Commit

Permalink
fixup! HAI-1527 Audit logging for permission updates
Browse files Browse the repository at this point in the history
  • Loading branch information
corvidian committed Aug 31, 2023
1 parent 37cc429 commit abe60a8
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package fi.hel.haitaton.hanke.logging

import fi.hel.haitaton.hanke.application.Application
import fi.hel.haitaton.hanke.permissions.KayttajaTunniste
import fi.hel.haitaton.hanke.permissions.PermissionEntity
import fi.hel.haitaton.hanke.permissions.Permission
import fi.hel.haitaton.hanke.permissions.Role
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Propagation
Expand All @@ -12,15 +11,7 @@ import org.springframework.transaction.annotation.Transactional
class HankeKayttajaLoggingService(private val auditLogService: AuditLogService) {

@Transactional(propagation = Propagation.MANDATORY)
fun logCreate(savedApplication: Application, userId: String) {
auditLogService.create(
AuditLogService.createEntry(userId, ObjectType.APPLICATION, savedApplication)
)
}

@Transactional(propagation = Propagation.MANDATORY)
fun logUpdate(roleBefore: Role, permissionEntityAfter: PermissionEntity, userId: String) {
val permissionAfter = permissionEntityAfter.toDomain()
fun logUpdate(roleBefore: Role, permissionAfter: Permission, userId: String) {
val permissionBefore = permissionAfter.copy(role = roleBefore)

AuditLogService.updateEntry(
Expand All @@ -46,11 +37,4 @@ class HankeKayttajaLoggingService(private val auditLogService: AuditLogService)
)
?.let { auditLogService.create(it) }
}

@Transactional(propagation = Propagation.MANDATORY)
fun logDelete(applicationBefore: Application, userId: String) {
auditLogService.create(
AuditLogService.deleteEntry(userId, ObjectType.APPLICATION, applicationBefore)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class HankeKayttajaService(
if (kayttaja.permission != null) {
val roleBefore = kayttaja.permission.role.role
kayttaja.permission.role = roleRepository.findOneByRole(updates[kayttaja.id]!!)
logService.logUpdate(roleBefore, kayttaja.permission, userId)
logService.logUpdate(roleBefore, kayttaja.permission.toDomain(), userId)
} else {
val kayttajaTunnisteBefore = kayttaja.kayttajaTunniste!!.toDomain()
kayttaja.kayttajaTunniste.role = updates[kayttaja.id]!!
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package fi.hel.haitaton.hanke.factory

import fi.hel.haitaton.hanke.permissions.KayttajaTunniste
import fi.hel.haitaton.hanke.permissions.Role
import java.time.OffsetDateTime
import java.util.UUID

object KayttajaTunnisteFactory {
val TUNNISTE_ID: UUID = UUID.fromString("b514795c-d982-430a-836b-91371829db51")
const val TUNNISTE: String = "K6NqNdCJOrNRh45aCP08e9wc"
val CREATED_AT: OffsetDateTime = OffsetDateTime.parse("2023-08-31T14:25:13Z")
val SENT_AT: OffsetDateTime = OffsetDateTime.parse("2023-08-31T14:25:14Z")
val ROLE: Role = Role.KATSELUOIKEUS
val KAYTTAJA_ID: UUID = UUID.fromString("597431b3-3be1-4594-a07a-bef77c8167df")

fun create(
id: UUID = TUNNISTE_ID,
tunniste: String = TUNNISTE,
createdAt: OffsetDateTime = CREATED_AT,
sentAt: OffsetDateTime? = SENT_AT,
role: Role = ROLE,
hankeKayttajaId: UUID? = KAYTTAJA_ID,
) = KayttajaTunniste(id, tunniste, createdAt, sentAt, role, hankeKayttajaId)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package fi.hel.haitaton.hanke.factory

import fi.hel.haitaton.hanke.permissions.Permission
import fi.hel.haitaton.hanke.permissions.Role

object PermissionFactory {

const val PERMISSION_ID = 65110
const val USER_ID = "permissionUser"
const val HANKE_ID = 984141
val ROLE = Role.KATSELUOIKEUS

fun create(
id: Int = PERMISSION_ID,
userId: String = USER_ID,
hankeId: Int = HANKE_ID,
role: Role = ROLE,
) = Permission(id, userId, hankeId, role)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package fi.hel.haitaton.hanke.logging

import assertk.all
import assertk.assertThat
import assertk.assertions.contains
import assertk.assertions.isEqualTo
import assertk.assertions.isNotNull
import assertk.assertions.isNull
import fi.hel.haitaton.hanke.factory.KayttajaTunnisteFactory
import fi.hel.haitaton.hanke.factory.PermissionFactory
import fi.hel.haitaton.hanke.permissions.Role
import io.mockk.called
import io.mockk.checkUnnecessaryStub
import io.mockk.clearAllMocks
import io.mockk.confirmVerified
import io.mockk.mockk
import io.mockk.verify
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test

class HankeKayttajaLoggingServiceTest {
private val userId = "test"

private val auditLogService: AuditLogService = mockk(relaxed = true)
private val loggingService = HankeKayttajaLoggingService(auditLogService)

@BeforeEach
fun clearMocks() {
clearAllMocks()
}

@AfterEach
fun cleanUp() {
checkUnnecessaryStub()
confirmVerified(auditLogService)
}

@Nested
inner class LogPermissionUpdate {
@Test
fun `Creates audit log entry for updated permission`() {
val roleBefore = Role.KATSELUOIKEUS
val permissionAfter = PermissionFactory.create(role = Role.HANKEMUOKKAUS)

loggingService.logUpdate(roleBefore, permissionAfter, userId)

verify {
auditLogService.create(
withArg { entry ->
try {
assertThat(entry.operation).isEqualTo(Operation.UPDATE)
assertThat(entry.status).isEqualTo(Status.SUCCESS)
assertThat(entry.failureDescription).isNull()
assertThat(entry.userId).isEqualTo(userId)
assertThat(entry.userRole).isEqualTo(UserRole.USER)
assertThat(entry.objectId)
.isEqualTo(PermissionFactory.PERMISSION_ID.toString())
assertThat(entry.objectType).isEqualTo(ObjectType.PERMISSION)
assertThat(entry.objectBefore).isNotNull().all {
contains(PermissionFactory.PERMISSION_ID.toString())
contains(PermissionFactory.USER_ID)
contains(PermissionFactory.HANKE_ID.toString())
contains("KATSELUOIKEUS")
}
assertThat(entry.objectAfter).isNotNull().all {
contains(PermissionFactory.PERMISSION_ID.toString())
contains(PermissionFactory.USER_ID)
contains(PermissionFactory.HANKE_ID.toString())
contains("HANKEMUOKKAUS")
}
} catch (e: Throwable) {
println("ASDF ${e.message}")
throw e
}
}
)
}
}

@Test
fun `Doesn't create audit log entry if permission not updated`() {
val roleBefore = PermissionFactory.ROLE
val permissionAfter = PermissionFactory.create()

loggingService.logUpdate(roleBefore, permissionAfter, userId)

verify { auditLogService wasNot called }
}
}

@Nested
inner class LogTunnisteUpdate {
@Test
fun `Creates audit log entry for updated kayttajatunniste`() {
val kayttajaTunnisteBefore = KayttajaTunnisteFactory.create(sentAt = null)
val kayttajaTunnisteAfter = KayttajaTunnisteFactory.create(role = Role.HANKEMUOKKAUS)

loggingService.logUpdate(kayttajaTunnisteBefore, kayttajaTunnisteAfter, userId)

verify {
auditLogService.create(
withArg { entry ->
assertThat(entry.operation).isEqualTo(Operation.UPDATE)
assertThat(entry.status).isEqualTo(Status.SUCCESS)
assertThat(entry.failureDescription).isNull()
assertThat(entry.userId).isEqualTo(userId)
assertThat(entry.userRole).isEqualTo(UserRole.USER)
assertThat(entry.objectId)
.isEqualTo(KayttajaTunnisteFactory.TUNNISTE_ID.toString())
assertThat(entry.objectType).isEqualTo(ObjectType.KAYTTAJA_TUNNISTE)
assertThat(entry.objectBefore).isNotNull().all {
contains(KayttajaTunnisteFactory.TUNNISTE_ID.toString())
contains(KayttajaTunnisteFactory.TUNNISTE)
contains(KayttajaTunnisteFactory.CREATED_AT.toString())
contains("null")
contains(KayttajaTunnisteFactory.KAYTTAJA_ID.toString())
contains("KATSELUOIKEUS")
}
assertThat(entry.objectAfter).isNotNull().all {
contains(KayttajaTunnisteFactory.TUNNISTE_ID.toString())
contains(KayttajaTunnisteFactory.TUNNISTE)
contains(KayttajaTunnisteFactory.CREATED_AT.toString())
contains(KayttajaTunnisteFactory.SENT_AT.toString())
contains(KayttajaTunnisteFactory.KAYTTAJA_ID.toString())
contains("HANKEMUOKKAUS")
}
}
)
}
}

@Test
fun `Doesn't create audit log entry if permission not updated`() {
val kayttajaTunnisteBefore = KayttajaTunnisteFactory.create()
val kayttajaTunnisteAfter = KayttajaTunnisteFactory.create()

loggingService.logUpdate(kayttajaTunnisteBefore, kayttajaTunnisteAfter, userId)

verify { auditLogService wasNot called }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import org.junit.jupiter.api.Assertions.assertNull
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test

internal class HankeLoggingServiceTest {
class HankeLoggingServiceTest {
private val userId = "test"

private val auditLogService: AuditLogService = mockk(relaxed = true)
Expand Down Expand Up @@ -146,6 +146,7 @@ internal class HankeLoggingServiceTest {
)
}
}

@Test
fun `logUpdate doesn't create audit log entry if hanke not changed`() {
val hankeBefore = HankeFactory.create(version = 1)
Expand Down

0 comments on commit abe60a8

Please sign in to comment.