refactor(audit): extract createUserForBootstrap() to make null actorId contract explicit

createUserOrUpdate(UUID actorId, ...) is always called from the controller with
a real authenticated actor. createUserForBootstrap() handles seeding/test setup
without emitting an audit event, making the two contracts unambiguous.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-26 17:39:09 +02:00
parent 1dd6e054fc
commit 6d9910b805
2 changed files with 48 additions and 0 deletions

View File

@@ -80,6 +80,34 @@ public class UserService {
return saved;
}
@Transactional
public AppUser createUserForBootstrap(CreateUserRequest request) {
log.info("Bootstrap user creation (no audit): {}", request.getEmail());
Set<UserGroup> groups = new HashSet<>();
if (request.getGroupIds() != null && !request.getGroupIds().isEmpty()) {
groups.addAll(groupRepository.findAllById(request.getGroupIds()));
}
Optional<AppUser> existingUser = userRepository.findByEmail(request.getEmail());
if (existingUser.isPresent()) {
AppUser updated = existingUser.get().updateFromRequest(request, passwordEncoder, groups);
return userRepository.save(updated);
}
AppUser user = AppUser.builder()
.email(request.getEmail())
.password(passwordEncoder.encode(request.getInitialPassword()))
.groups(groups)
.firstName(request.getFirstName())
.lastName(request.getLastName())
.birthDate(request.getBirthDate())
.contact(request.getContact())
.enabled(true)
.build();
return userRepository.save(user);
}
@Transactional
public AppUser createUser(String email, String rawPassword, String firstName, String lastName, Set<UUID> groupIds) {
userRepository.findByEmail(email).ifPresent(existing -> {

View File

@@ -837,6 +837,26 @@ class UserServiceTest {
verify(auditService, never()).logAfterCommit(any(), any(), any(), any());
}
// ─── createUserForBootstrap ───────────────────────────────────────────────
@Test
void createUserForBootstrap_createsUserWithoutAuditEvent() {
CreateUserRequest req = new CreateUserRequest();
req.setEmail("bootstrap@example.com");
req.setInitialPassword("secret");
req.setGroupIds(List.of());
when(userRepository.findByEmail("bootstrap@example.com")).thenReturn(Optional.empty());
when(passwordEncoder.encode("secret")).thenReturn("encoded");
AppUser saved = AppUser.builder().id(UUID.randomUUID()).email("bootstrap@example.com").build();
when(userRepository.save(any())).thenReturn(saved);
AppUser result = userService.createUserForBootstrap(req);
assertThat(result).isEqualTo(saved);
verify(auditService, never()).logAfterCommit(any(), any(), any(), any());
}
// ─── createGroup ──────────────────────────────────────────────────────────
@Test