feat(API): optional display name on users

This commit is contained in:
fsylvain committed 2026-09-29 06:52:58 +02:00
1 parent 792aba433d
commit 7aae704d0a
22 files changed
+1051 -40

No files matched your search

+2
View File
@@ -13,6 +13,7 @@ var ErrVerificationCodeExpired = errors.New("verification code expired")
var ErrAlreadyVerified = errors.New("user already verified")
var ErrInvalidPasswordResetCode = errors.New("invalid password reset code")
var ErrPasswordResetCodeExpired = errors.New("password reset code expired")
var ErrInvalidDisplayName = errors.New("invalid display name")
type User struct {
ID uint32 `json:"id"`
@@ -20,6 +21,7 @@ type User struct {
Password string `json:"password"`
PasswordResetCode string `json:"password_reset_code"`
Email string `json:"email"`
DisplayName string `json:"display_name"`
IsVerified bool `json:"is_verified"`
VerificationCode string `json:"verification_code"`
VerificationExpiration time.Time `json:"verification_expiration"`
@@ -14,4 +14,5 @@ type Repository interface {
UpdatePasswordResetCode(userId uint32, code string, expiration time.Time) (User, error)
ClearVerificationCode(userId uint32) (User, error)
ResetPassword(userId uint32, hashedPassword string) (User, error)
UpdateDisplayName(userId uint32, displayName string) (User, error)
}
@@ -26,6 +26,7 @@ func UserToDomain(m models.User) user.User {
Password: m.Password,
PasswordResetCode: nullableStringToDomain(m.PasswordResetCode),
Email: m.Email,
DisplayName: m.DisplayName,
IsVerified: m.IsVerified,
VerificationCode: nullableStringToDomain(m.VerificationCode),
VerificationExpiration: m.VerificationExpiration,
@@ -42,6 +43,7 @@ func UserToModel(a user.User) models.User {
Password: a.Password,
PasswordResetCode: DomainToNullableString(a.PasswordResetCode),
Email: a.Email,
DisplayName: a.DisplayName,
IsVerified: a.IsVerified,
VerificationCode: DomainToNullableString(a.VerificationCode),
VerificationExpiration: a.VerificationExpiration,
@@ -10,6 +10,7 @@ type User struct {
Password string `gorm:"not null"`
PasswordResetCode *string `gorm:"unique"`
Email string `gorm:"unique;not null"`
DisplayName string `gorm:"not null;default:''"`
IsVerified bool `gorm:"default=false;not null"`
VerificationCode *string `gorm:"unique"`
VerificationExpiration time.Time
@@ -169,4 +169,20 @@ func (u *UserRepository) ResetPassword(userId uint32, hashedPassword string) (do
return mappers.UserToDomain(localUser), nil
}
func (u *UserRepository) UpdateDisplayName(userId uint32, displayName string) (domainUser.User, error) {
var localUser entity.User
err := u.db.Model(&entity.User{}).First(&localUser, userId).Error
if err != nil {
return domainUser.User{}, mapNotFoundErr(err, domainUser.ErrUserNotFound)
}
localUser.DisplayName = displayName
err = u.db.Save(&localUser).Error
if err != nil {
return domainUser.User{}, err
}
return mappers.UserToDomain(localUser), nil
}
var _ domainUser.Repository = &UserRepository{}
@@ -0,0 +1,25 @@
package useCases
import (
"RenewCMS/internal/domain/user"
"strings"
"unicode/utf8"
)
const maxDisplayNameRunes = 60
type UpdateUserProfileUseCase struct {
userRepository user.Repository
}
func NewUpdateUserProfileUseCase(userRepository user.Repository) *UpdateUserProfileUseCase {
return &UpdateUserProfileUseCase{userRepository}
}
func (u *UpdateUserProfileUseCase) UpdateDisplayName(userId uint32, displayName string) (user.User, error) {
trimmed := strings.TrimSpace(displayName)
if utf8.RuneCountInString(trimmed) > maxDisplayNameRunes {
return user.User{}, user.ErrInvalidDisplayName
}
return u.userRepository.UpdateDisplayName(userId, trimmed)
}