Close profile identity and avatar loop

This commit is contained in:
IanShaw027
2026-04-21 00:11:03 +08:00
parent f73117f9b1
commit 9204145746
14 changed files with 801 additions and 35 deletions

View File

@@ -65,6 +65,8 @@ type UserRepository interface {
List(ctx context.Context, params pagination.PaginationParams) ([]User, *pagination.PaginationResult, error)
ListWithFilters(ctx context.Context, params pagination.PaginationParams, filters UserListFilters) ([]User, *pagination.PaginationResult, error)
GetLatestUsedAtByUserIDs(ctx context.Context, userIDs []int64) (map[int64]*time.Time, error)
GetLatestUsedAtByUserID(ctx context.Context, userID int64) (*time.Time, error)
UpdateBalance(ctx context.Context, id int64, amount float64) error
DeductBalance(ctx context.Context, id int64, amount float64) error
@@ -159,6 +161,33 @@ type userAuthIdentityReader interface {
ListUserAuthIdentities(ctx context.Context, userID int64) ([]UserAuthIdentityRecord, error)
}
type emailAuthIdentitySynchronizer interface {
EnsureEmailAuthIdentity(ctx context.Context, userID int64, email string) error
ReplaceEmailAuthIdentity(ctx context.Context, userID int64, oldEmail, newEmail string) error
}
func ensureEmailAuthIdentitySync(ctx context.Context, repo UserRepository, userID int64, email string) error {
syncer, ok := repo.(emailAuthIdentitySynchronizer)
if !ok {
return nil
}
return syncer.EnsureEmailAuthIdentity(ctx, userID, email)
}
func replaceEmailAuthIdentitySync(ctx context.Context, repo UserRepository, userID int64, oldEmail, newEmail string) error {
oldNormalized := strings.ToLower(strings.TrimSpace(oldEmail))
newNormalized := strings.ToLower(strings.TrimSpace(newEmail))
if oldNormalized == newNormalized {
return nil
}
syncer, ok := repo.(emailAuthIdentitySynchronizer)
if !ok {
return nil
}
return syncer.ReplaceEmailAuthIdentity(ctx, userID, oldEmail, newEmail)
}
// ChangePasswordRequest 修改密码请求
type ChangePasswordRequest struct {
CurrentPassword string `json:"current_password"`
@@ -252,6 +281,7 @@ func (s *UserService) UpdateProfile(ctx context.Context, userID int64, req Updat
return nil, fmt.Errorf("get user: %w", err)
}
oldConcurrency := user.Concurrency
oldEmail := user.Email
// 更新字段
if req.Email != nil {
@@ -271,24 +301,11 @@ func (s *UserService) UpdateProfile(ctx context.Context, userID int64, req Updat
}
if req.AvatarURL != nil {
avatarValue := strings.TrimSpace(*req.AvatarURL)
switch {
case avatarValue == "":
if err := s.userRepo.DeleteUserAvatar(ctx, userID); err != nil {
return nil, fmt.Errorf("delete avatar: %w", err)
}
applyUserAvatar(user, nil)
default:
avatarInput, err := normalizeUserAvatarInput(avatarValue)
if err != nil {
return nil, err
}
avatar, err := s.userRepo.UpsertUserAvatar(ctx, userID, avatarInput)
if err != nil {
return nil, fmt.Errorf("upsert avatar: %w", err)
}
applyUserAvatar(user, avatar)
avatar, err := s.SetAvatar(ctx, userID, *req.AvatarURL)
if err != nil {
return nil, err
}
applyUserAvatar(user, avatar)
}
if req.Concurrency != nil {
@@ -309,6 +326,9 @@ func (s *UserService) UpdateProfile(ctx context.Context, userID int64, req Updat
if err := s.userRepo.Update(ctx, user); err != nil {
return nil, fmt.Errorf("update user: %w", err)
}
if err := replaceEmailAuthIdentitySync(ctx, s.userRepo, user.ID, oldEmail, user.Email); err != nil {
return nil, fmt.Errorf("sync email auth identity: %w", err)
}
if s.authCacheInvalidator != nil && user.Concurrency != oldConcurrency {
s.authCacheInvalidator.InvalidateAuthCacheByUserID(ctx, userID)
}
@@ -316,6 +336,27 @@ func (s *UserService) UpdateProfile(ctx context.Context, userID int64, req Updat
return user, nil
}
func (s *UserService) SetAvatar(ctx context.Context, userID int64, raw string) (*UserAvatar, error) {
avatarValue := strings.TrimSpace(raw)
if avatarValue == "" {
if err := s.userRepo.DeleteUserAvatar(ctx, userID); err != nil {
return nil, fmt.Errorf("delete avatar: %w", err)
}
return nil, nil
}
avatarInput, err := normalizeUserAvatarInput(avatarValue)
if err != nil {
return nil, err
}
avatar, err := s.userRepo.UpsertUserAvatar(ctx, userID, avatarInput)
if err != nil {
return nil, fmt.Errorf("upsert avatar: %w", err)
}
return avatar, nil
}
func applyUserAvatar(user *User, avatar *UserAvatar) {
if user == nil {
return