feat(audit): emit USER_CREATED when admin creates a new user
Adds USER_CREATED, USER_DELETED, GROUP_MEMBERSHIP_CHANGED to AuditKind. Injects AuditService into UserService; changes createUserOrUpdate to accept actorId and emits logAfterCommit(USER_CREATED) only on the new-user branch. Updates UserController to resolve and pass actorId. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -26,7 +26,16 @@ public enum AuditKind {
|
||||
COMMENT_ADDED,
|
||||
|
||||
/** Payload: {@code {"commentId": "uuid", "mentionedUserId": "uuid"}} */
|
||||
MENTION_CREATED;
|
||||
MENTION_CREATED,
|
||||
|
||||
/** Payload: {@code {"userId": "uuid", "email": "addr"}} */
|
||||
USER_CREATED,
|
||||
|
||||
/** Payload: {@code {"userId": "uuid", "email": "addr"}} */
|
||||
USER_DELETED,
|
||||
|
||||
/** Payload: {@code {"userId": "uuid", "email": "addr", "addedGroups": ["Admin"], "removedGroups": []}} */
|
||||
GROUP_MEMBERSHIP_CHANGED;
|
||||
|
||||
public static final Set<AuditKind> ROLLUP_ELIGIBLE = Set.of(
|
||||
TEXT_SAVED, FILE_UPLOADED, ANNOTATION_CREATED,
|
||||
|
||||
@@ -78,8 +78,10 @@ public class UserController {
|
||||
|
||||
@PostMapping("/users")
|
||||
@RequirePermission(Permission.ADMIN_USER)
|
||||
public ResponseEntity<AppUser> createUser(@Valid @RequestBody CreateUserRequest request) {
|
||||
return ResponseEntity.ok(userService.createUserOrUpdate(request));
|
||||
public ResponseEntity<AppUser> createUser(Authentication authentication,
|
||||
@Valid @RequestBody CreateUserRequest request) {
|
||||
AppUser actor = userService.findByEmail(authentication.getName());
|
||||
return ResponseEntity.ok(userService.createUserOrUpdate(actor.getId(), request));
|
||||
}
|
||||
|
||||
@PutMapping("/users/{id}")
|
||||
|
||||
@@ -3,6 +3,8 @@ package org.raddatz.familienarchiv.service;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.raddatz.familienarchiv.audit.AuditKind;
|
||||
import org.raddatz.familienarchiv.audit.AuditService;
|
||||
import org.raddatz.familienarchiv.dto.AdminUpdateUserRequest;
|
||||
import org.raddatz.familienarchiv.dto.ChangePasswordDTO;
|
||||
import org.raddatz.familienarchiv.dto.CreateUserRequest;
|
||||
@@ -21,6 +23,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
@@ -33,9 +36,10 @@ public class UserService {
|
||||
private final AppUserRepository userRepository;
|
||||
private final UserGroupRepository groupRepository;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final AuditService auditService;
|
||||
|
||||
@Transactional
|
||||
public AppUser createUserOrUpdate(CreateUserRequest request) {
|
||||
public AppUser createUserOrUpdate(UUID actorId, CreateUserRequest request) {
|
||||
log.info("Creating or updating user: {}", request.getEmail());
|
||||
|
||||
Set<UserGroup> groups = new HashSet<>();
|
||||
@@ -45,10 +49,12 @@ public class UserService {
|
||||
|
||||
Optional<AppUser> existingUser = userRepository.findByEmail(request.getEmail());
|
||||
AppUser user;
|
||||
boolean isNew;
|
||||
|
||||
if (existingUser.isPresent()) {
|
||||
log.info("User exists, updating: {}", request.getEmail());
|
||||
user = existingUser.get().updateFromRequest(request, passwordEncoder, groups);
|
||||
isNew = false;
|
||||
} else {
|
||||
log.info("Creating new user: {}", request.getEmail());
|
||||
user = AppUser.builder()
|
||||
@@ -61,9 +67,15 @@ public class UserService {
|
||||
.contact(request.getContact())
|
||||
.enabled(true)
|
||||
.build();
|
||||
isNew = true;
|
||||
}
|
||||
|
||||
return userRepository.save(user);
|
||||
AppUser saved = userRepository.save(user);
|
||||
if (isNew) {
|
||||
auditService.logAfterCommit(AuditKind.USER_CREATED, actorId, null,
|
||||
Map.of("userId", saved.getId().toString(), "email", saved.getEmail()));
|
||||
}
|
||||
return saved;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
||||
Reference in New Issue
Block a user