feat(audit): track user management events in audit log (#336) #337

Merged
marcel merged 14 commits from feat/issue-336-audit-user-management into main 2026-04-26 19:42:00 +02:00
2 changed files with 10 additions and 5 deletions
Showing only changes of commit 23cff1cdd7 - Show all commits

View File

@@ -5,4 +5,5 @@ import org.springframework.data.jpa.repository.JpaRepository;
import java.util.UUID;
public interface AuditLogRepository extends JpaRepository<AuditLog, UUID> {
boolean existsByKind(AuditKind kind);
}

View File

@@ -1,5 +1,6 @@
package org.raddatz.familienarchiv.audit;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.raddatz.familienarchiv.PostgresContainerConfig;
import org.raddatz.familienarchiv.dto.CreateUserRequest;
@@ -9,7 +10,6 @@ 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;
@@ -25,7 +25,6 @@ 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;
@@ -35,6 +34,11 @@ class UserManagementAuditIntegrationTest {
@Autowired AuditLogQueryService auditLogQueryService;
@Autowired TransactionTemplate transactionTemplate;
@BeforeEach
void clearAuditLog() {
transactionTemplate.execute(status -> { auditLogRepository.deleteAll(); return null; });
}
@Test
void createAndDeleteUser_producesOrderedAuditEntries() {
// Create the actor (admin) user directly — bypasses audit logging so no FK issue
@@ -46,7 +50,7 @@ class UserManagementAuditIntegrationTest {
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);
await().atMost(5, SECONDS).until(() -> auditLogRepository.existsByKind(AuditKind.USER_CREATED));
transactionTemplate.execute(status -> { auditLogRepository.deleteAll(); return null; });
// Create the target user — should emit USER_CREATED
@@ -57,7 +61,7 @@ class UserManagementAuditIntegrationTest {
userService.createUserOrUpdate(actorId, req);
return null;
});
await().atMost(5, SECONDS).until(() -> auditLogRepository.count() > 0);
await().atMost(5, SECONDS).until(() -> auditLogRepository.existsByKind(AuditKind.USER_CREATED));
// Delete the target user — should emit USER_DELETED
AppUser created = userRepository.findByEmail("audit-test@example.com").orElseThrow();
@@ -65,7 +69,7 @@ class UserManagementAuditIntegrationTest {
userService.deleteUser(actorId, created.getId());
return null;
});
await().atMost(5, SECONDS).until(() -> auditLogRepository.count() >= 2);
await().atMost(5, SECONDS).until(() -> auditLogRepository.existsByKind(AuditKind.USER_DELETED));
List<AuditLog> events = auditLogQueryService.findRecentUserManagementEvents(10);
assertThat(events).hasSize(2);