package useCases import ( "RenewCMS/internal/domain/audit" "RenewCMS/internal/domain/user" "context" "strings" "unicode/utf8" ) const maxDisplayNameRunes = 60 type UpdateUserProfileUseCase struct { userRepository user.Repository recorder audit.Recorder } func NewUpdateUserProfileUseCase(userRepository user.Repository, recorder audit.Recorder) *UpdateUserProfileUseCase { return &UpdateUserProfileUseCase{userRepository, recorder} } func (u *UpdateUserProfileUseCase) UpdateDisplayName(ctx context.Context, userId uint32, displayName string) (user.User, error) { before, err := u.userRepository.Get(userId) if err != nil { return user.User{}, err } event := audit.NewEvent(audit.ActionUserUpdateProfile, audit.CategoryUsers) event.Target = userTarget(before) trimmed := strings.TrimSpace(displayName) if utf8.RuneCountInString(trimmed) > maxDisplayNameRunes { recordFailure(ctx, u.recorder, event, user.ErrInvalidDisplayName) return user.User{}, user.ErrInvalidDisplayName } updated, err := u.userRepository.UpdateDisplayName(userId, trimmed) if err != nil { recordFailure(ctx, u.recorder, event, err) return user.User{}, err } if updated.DisplayName != before.DisplayName { event.Target = userTarget(updated) event.Changes = []audit.Change{audit.TextChange(audit.FieldDisplayName, before.DisplayName, updated.DisplayName)} u.recorder.Record(ctx, event) } return updated, nil } func userTarget(u user.User) audit.Target { return audit.NewTarget(audit.TargetUser, u.ID, audit.UserActor(u).Name) }