From 77affcfb4faff070d44b2520eb710a2e91e6de9c Mon Sep 17 00:00:00 2001 From: Marcel Date: Sun, 26 Apr 2026 15:05:09 +0200 Subject: [PATCH] =?UTF-8?q?test(audit):=20integration=20test=20=E2=80=94?= =?UTF-8?q?=20create=20+=20delete=20user=20produces=20ordered=20audit=20en?= =?UTF-8?q?tries?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Creates a real actor user first (needed for audit_log FK constraint), then creates and deletes a target user, asserts USER_DELETED is newest and USER_CREATED is second via findRecentUserManagementEvents. Co-Authored-By: Claude Sonnet 4.6 --- .../UserManagementAuditIntegrationTest.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 backend/src/test/java/org/raddatz/familienarchiv/audit/UserManagementAuditIntegrationTest.java diff --git a/backend/src/test/java/org/raddatz/familienarchiv/audit/UserManagementAuditIntegrationTest.java b/backend/src/test/java/org/raddatz/familienarchiv/audit/UserManagementAuditIntegrationTest.java new file mode 100644 index 00000000..1437bc83 --- /dev/null +++ b/backend/src/test/java/org/raddatz/familienarchiv/audit/UserManagementAuditIntegrationTest.java @@ -0,0 +1,75 @@ +package org.raddatz.familienarchiv.audit; + +import org.junit.jupiter.api.Test; +import org.raddatz.familienarchiv.PostgresContainerConfig; +import org.raddatz.familienarchiv.dto.CreateUserRequest; +import org.raddatz.familienarchiv.model.AppUser; +import org.raddatz.familienarchiv.repository.AppUserRepository; +import org.raddatz.familienarchiv.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.transaction.support.TransactionTemplate; +import software.amazon.awssdk.services.s3.S3Client; + +import java.util.List; +import java.util.UUID; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) +@ActiveProfiles("test") +@Import(PostgresContainerConfig.class) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) +class UserManagementAuditIntegrationTest { + + @MockitoBean S3Client s3Client; + @Autowired UserService userService; + @Autowired AppUserRepository userRepository; + @Autowired AuditLogRepository auditLogRepository; + @Autowired AuditLogQueryService auditLogQueryService; + @Autowired TransactionTemplate transactionTemplate; + + @Test + void createAndDeleteUser_producesOrderedAuditEntries() { + // Create the actor (admin) user directly — bypasses audit logging so no FK issue + CreateUserRequest adminReq = new CreateUserRequest(); + adminReq.setEmail("admin@test.example.com"); + adminReq.setInitialPassword("admin-secret"); + AppUser actor = transactionTemplate.execute(status -> + userService.createUserOrUpdate(null, adminReq)); + UUID actorId = actor.getId(); + + // The admin creation is logged with null actorId — clear to start with a clean slate + await().atMost(5, SECONDS).until(() -> auditLogRepository.count() > 0); + transactionTemplate.execute(status -> { auditLogRepository.deleteAll(); return null; }); + + // Create the target user — should emit USER_CREATED + CreateUserRequest req = new CreateUserRequest(); + req.setEmail("audit-test@example.com"); + req.setInitialPassword("secret"); + transactionTemplate.execute(status -> { + userService.createUserOrUpdate(actorId, req); + return null; + }); + await().atMost(5, SECONDS).until(() -> auditLogRepository.count() > 0); + + // Delete the target user — should emit USER_DELETED + AppUser created = userRepository.findByEmail("audit-test@example.com").orElseThrow(); + transactionTemplate.execute(status -> { + userService.deleteUser(actorId, created.getId()); + return null; + }); + await().atMost(5, SECONDS).until(() -> auditLogRepository.count() >= 2); + + List events = auditLogQueryService.findRecentUserManagementEvents(10); + assertThat(events).hasSize(2); + assertThat(events.get(0).getKind()).isEqualTo(AuditKind.USER_DELETED); + assertThat(events.get(1).getKind()).isEqualTo(AuditKind.USER_CREATED); + } +}