Close profile identity and avatar loop
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user