fix
This commit is contained in:
parent
22cd661abb
commit
89496b3558
2 changed files with 87 additions and 11 deletions
|
|
@ -225,14 +225,14 @@ func (s *Service) UpdateUsername(ctx context.Context, userID int64, username str
|
|||
}
|
||||
}
|
||||
if self.Username == username {
|
||||
return self, nil
|
||||
return s.projectOne(ctx, self.ID, self)
|
||||
}
|
||||
u, err := s.users.UpdateUsername(ctx, self.ID, username)
|
||||
if err != nil {
|
||||
return domain.User{}, err
|
||||
}
|
||||
s.refreshCachedUsers(ctx, u)
|
||||
return u, nil
|
||||
return s.projectOne(ctx, self.ID, u)
|
||||
}
|
||||
|
||||
// UpdateProfile 修改当前用户的基础资料。未设置的字段保持原值。
|
||||
|
|
@ -264,14 +264,14 @@ func (s *Service) UpdateProfile(ctx context.Context, userID int64, update domain
|
|||
return domain.User{}, domain.ErrAboutTooLong
|
||||
}
|
||||
if firstName == self.FirstName && lastName == self.LastName && about == self.About {
|
||||
return self, nil
|
||||
return s.projectOne(ctx, self.ID, self)
|
||||
}
|
||||
u, err := s.users.UpdateProfile(ctx, self.ID, firstName, lastName, about)
|
||||
if err != nil {
|
||||
return domain.User{}, err
|
||||
}
|
||||
s.refreshCachedUsers(ctx, u)
|
||||
return u, nil
|
||||
return s.projectOne(ctx, self.ID, u)
|
||||
}
|
||||
|
||||
// UpdateLastSeen records the latest visible account activity time.
|
||||
|
|
@ -333,7 +333,7 @@ func (s *Service) GrantPremium(ctx context.Context, userID int64, months int) (d
|
|||
return domain.User{}, err
|
||||
}
|
||||
s.refreshCachedUsers(ctx, updated)
|
||||
return updated, nil
|
||||
return s.projectOne(ctx, userID, updated)
|
||||
}
|
||||
|
||||
// SetVerified 设置/取消用户认证标记。认证是账号基础事实,所有 user 投影统一消费该字段。
|
||||
|
|
@ -349,14 +349,14 @@ func (s *Service) SetVerified(ctx context.Context, userID int64, verified bool)
|
|||
return domain.User{}, domain.ErrUserNotFound
|
||||
}
|
||||
if u.Verified == verified {
|
||||
return u, nil
|
||||
return s.projectOne(ctx, userID, u)
|
||||
}
|
||||
updated, err := s.users.SetVerified(ctx, userID, verified)
|
||||
if err != nil {
|
||||
return domain.User{}, err
|
||||
}
|
||||
s.refreshCachedUsers(ctx, updated)
|
||||
return updated, nil
|
||||
return s.projectOne(ctx, userID, updated)
|
||||
}
|
||||
|
||||
// SweepExpiredPremium 清理到期会员(store 把过期行清 NULL)并失效用户缓存,
|
||||
|
|
@ -390,7 +390,7 @@ func (s *Service) UpdateEmojiStatus(ctx context.Context, userID int64, documentI
|
|||
return domain.User{}, err
|
||||
}
|
||||
s.refreshCachedUsers(ctx, u)
|
||||
return u, nil
|
||||
return s.projectOne(ctx, self.ID, u)
|
||||
}
|
||||
|
||||
// UpdateBirthday 设置/清除用户生日(account.updateBirthday)。零值 Birthday 表示清除。
|
||||
|
|
@ -411,7 +411,7 @@ func (s *Service) UpdateBirthday(ctx context.Context, userID int64, birthday dom
|
|||
return domain.User{}, err
|
||||
}
|
||||
s.refreshCachedUsers(ctx, u)
|
||||
return u, nil
|
||||
return s.projectOne(ctx, self.ID, u)
|
||||
}
|
||||
|
||||
// UpdatePersonalChannel 设置/清除资料页个人频道(account.updatePersonalChannel);
|
||||
|
|
@ -426,7 +426,7 @@ func (s *Service) UpdatePersonalChannel(ctx context.Context, userID int64, chann
|
|||
return domain.User{}, err
|
||||
}
|
||||
s.refreshCachedUsers(ctx, u)
|
||||
return u, nil
|
||||
return s.projectOne(ctx, self.ID, u)
|
||||
}
|
||||
|
||||
// UpdateColor updates the user's message accent or profile background color.
|
||||
|
|
@ -440,7 +440,7 @@ func (s *Service) UpdateColor(ctx context.Context, userID int64, forProfile bool
|
|||
return domain.User{}, err
|
||||
}
|
||||
s.refreshCachedUsers(ctx, u)
|
||||
return u, nil
|
||||
return s.projectOne(ctx, self.ID, u)
|
||||
}
|
||||
|
||||
// ResolveUsername 解析 username 到用户;调用方必须已登录。
|
||||
|
|
|
|||
|
|
@ -122,6 +122,82 @@ func TestServiceUpdateBirthday(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// fakePhotoProvider always reports the same current photo for every owner,
|
||||
// regardless of owner id — enough to prove a mutation path preserves the
|
||||
// photo instead of returning the bare, un-projected store row.
|
||||
type fakePhotoProvider struct {
|
||||
ref domain.ProfilePhotoRef
|
||||
}
|
||||
|
||||
func (f *fakePhotoProvider) CurrentProfilePhotos(ctx context.Context, ownerType domain.PeerType, ownerIDs []int64) (map[int64]domain.ProfilePhotoRef, error) {
|
||||
out := make(map[int64]domain.ProfilePhotoRef, len(ownerIDs))
|
||||
for _, id := range ownerIDs {
|
||||
out[id] = f.ref
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// TestServiceMutationsPreservePhoto guards against a class of bug where a
|
||||
// profile-mutating method returns the bare store row (users table has no
|
||||
// photo columns at all — the current avatar lives only in the profile_photos
|
||||
// association, attached via projectOne/Projector.One) instead of the
|
||||
// photo-enriched projection, causing the client to wipe its own avatar on
|
||||
// name/username/birthday/verified/color/emoji-status updates.
|
||||
func TestServiceMutationsPreservePhoto(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
store := memory.NewUserStore()
|
||||
owner, err := store.Create(ctx, domain.User{AccessHash: 1, Phone: "15550000099", FirstName: "Owner"})
|
||||
if err != nil {
|
||||
t.Fatalf("create owner: %v", err)
|
||||
}
|
||||
photos := &fakePhotoProvider{ref: domain.ProfilePhotoRef{PhotoID: 555, DCID: 2, Stripped: []byte{1, 2, 3}}}
|
||||
svc := NewService(store, WithPhotoProvider(photos))
|
||||
|
||||
assertHasPhoto := func(t *testing.T, label string, u domain.User) {
|
||||
t.Helper()
|
||||
if u.PhotoID != 555 || u.PhotoDCID != 2 {
|
||||
t.Fatalf("%s: photo = {id:%d dc:%d}, want {id:555 dc:2}", label, u.PhotoID, u.PhotoDCID)
|
||||
}
|
||||
}
|
||||
|
||||
u, err := svc.UpdateProfile(ctx, owner.ID, domain.UserProfileUpdate{FirstName: "New", HasFirstName: true})
|
||||
if err != nil {
|
||||
t.Fatalf("UpdateProfile: %v", err)
|
||||
}
|
||||
assertHasPhoto(t, "UpdateProfile", u)
|
||||
|
||||
// No-op branch (nothing actually changed) must also preserve the photo.
|
||||
u, err = svc.UpdateProfile(ctx, owner.ID, domain.UserProfileUpdate{FirstName: "New", HasFirstName: true})
|
||||
if err != nil {
|
||||
t.Fatalf("UpdateProfile no-op: %v", err)
|
||||
}
|
||||
assertHasPhoto(t, "UpdateProfile no-op", u)
|
||||
|
||||
u, err = svc.UpdateUsername(ctx, owner.ID, "ownerhandle")
|
||||
if err != nil {
|
||||
t.Fatalf("UpdateUsername: %v", err)
|
||||
}
|
||||
assertHasPhoto(t, "UpdateUsername", u)
|
||||
|
||||
u, err = svc.UpdateBirthday(ctx, owner.ID, domain.Birthday{Day: 1, Month: 1, Year: 2000})
|
||||
if err != nil {
|
||||
t.Fatalf("UpdateBirthday: %v", err)
|
||||
}
|
||||
assertHasPhoto(t, "UpdateBirthday", u)
|
||||
|
||||
u, err = svc.SetVerified(ctx, owner.ID, true)
|
||||
if err != nil {
|
||||
t.Fatalf("SetVerified: %v", err)
|
||||
}
|
||||
assertHasPhoto(t, "SetVerified", u)
|
||||
|
||||
u, err = svc.UpdateColor(ctx, owner.ID, false, domain.PeerColor{HasColor: true, Color: 3})
|
||||
if err != nil {
|
||||
t.Fatalf("UpdateColor: %v", err)
|
||||
}
|
||||
assertHasPhoto(t, "UpdateColor", u)
|
||||
}
|
||||
|
||||
func TestServiceUpdatePersonalChannel(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
store := memory.NewUserStore()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue