fix: persist group nickname for legacy groups
This commit is contained in:
@@ -4723,6 +4723,12 @@ func serveIMGroupMyProfile(wrt http.ResponseWriter, req *http.Request, topic str
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, err := store.GroupBusiness.UpdateMember(principal.TenantID, topic, principal.Uid, types.GroupMemberPatch{Nickname: &nickname, Version: body.Version}); err != nil {
|
if _, err := store.GroupBusiness.UpdateMember(principal.TenantID, topic, principal.Uid, types.GroupMemberPatch{Nickname: &nickname, Version: body.Version}); err != nil {
|
||||||
|
if errors.Is(err, types.ErrNotFound) {
|
||||||
|
logs.Warn.Printf("group[%s]: member profile saved to subscription only; business member row missing for user %s", topic, principal.Uid.UserId())
|
||||||
|
dispatchIMGroupEvents(principal.TenantID)
|
||||||
|
writeIMSuccess(wrt, req, map[string]any{"nickname": nickname, "version": currentVersion + 1, "updated_at": updatedAt.Format(time.RFC3339Nano)})
|
||||||
|
return
|
||||||
|
}
|
||||||
if rollbackErr := store.Subs.Update(principal.TenantID, topic, principal.Uid, map[string]any{"Private": selfSub.Private}); rollbackErr != nil {
|
if rollbackErr := store.Subs.Update(principal.TenantID, topic, principal.Uid, map[string]any{"Private": selfSub.Private}); rollbackErr != nil {
|
||||||
logs.Warn.Printf("group[%s]: failed to roll back member profile: %v", topic, rollbackErr)
|
logs.Warn.Printf("group[%s]: failed to roll back member profile: %v", topic, rollbackErr)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -334,6 +334,7 @@ type testGroupBusinessStore struct {
|
|||||||
updatedSettings types.GroupSettingsPatch
|
updatedSettings types.GroupSettingsPatch
|
||||||
updatedMembers []types.GroupMemberPatch
|
updatedMembers []types.GroupMemberPatch
|
||||||
updatedRoleMode types.AccessMode
|
updatedRoleMode types.AccessMode
|
||||||
|
updateMemberErr error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *testGroupBusinessStore) CreateGroup(_ types.TenantID, _ *types.Topic, _ types.Uid, _ any,
|
func (s *testGroupBusinessStore) CreateGroup(_ types.TenantID, _ *types.Topic, _ types.Uid, _ any,
|
||||||
@@ -388,6 +389,9 @@ func (s *testGroupBusinessStore) ListMembers(_ types.TenantID, _ string, _ types
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *testGroupBusinessStore) UpdateMember(_ types.TenantID, topic string, uid types.Uid, patch types.GroupMemberPatch) (*types.GroupMember, error) {
|
func (s *testGroupBusinessStore) UpdateMember(_ types.TenantID, topic string, uid types.Uid, patch types.GroupMemberPatch) (*types.GroupMember, error) {
|
||||||
|
if s.updateMemberErr != nil {
|
||||||
|
return nil, s.updateMemberErr
|
||||||
|
}
|
||||||
s.updatedMembers = append(s.updatedMembers, patch)
|
s.updatedMembers = append(s.updatedMembers, patch)
|
||||||
return &types.GroupMember{Topic: topic, UserID: uid, Role: defaultStringPtr(patch.Role, types.GroupMemberRoleMember), MemberStatus: types.GroupMemberStatusActive, Version: 2}, nil
|
return &types.GroupMember{Topic: topic, UserID: uid, Role: defaultStringPtr(patch.Role, types.GroupMemberRoleMember), MemberStatus: types.GroupMemberStatusActive, Version: 2}, nil
|
||||||
}
|
}
|
||||||
@@ -3780,6 +3784,57 @@ func TestServeIMGroupDetailPatchSettingsProfileAndLeave(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestServeIMGroupMyProfileKeepsSubscriptionNicknameWhenBusinessMemberMissing(t *testing.T) {
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
expectIMBearer(t, ctrl, "token-1", 7, 42)
|
||||||
|
oldSubs := store.Subs
|
||||||
|
oldGroupBusiness := store.GroupBusiness
|
||||||
|
subs := mock_store.NewMockSubsPersistenceInterface(ctrl)
|
||||||
|
store.Subs = subs
|
||||||
|
store.GroupBusiness = &testGroupBusinessStore{updateMemberErr: types.ErrNotFound}
|
||||||
|
defer func() {
|
||||||
|
store.Subs = oldSubs
|
||||||
|
store.GroupBusiness = oldGroupBusiness
|
||||||
|
}()
|
||||||
|
|
||||||
|
selfSub := &types.Subscription{
|
||||||
|
TenantID: 7,
|
||||||
|
User: types.Uid(42).String(),
|
||||||
|
Topic: "grpAlpha",
|
||||||
|
ModeWant: types.ModeCFull,
|
||||||
|
ModeGiven: types.ModeCFull,
|
||||||
|
Private: map[string]any{"comment": "", "profile_version": 1},
|
||||||
|
}
|
||||||
|
var savedPrivate map[string]any
|
||||||
|
subs.EXPECT().Get(types.TenantID(7), "grpAlpha", types.Uid(42), false).Return(selfSub, nil)
|
||||||
|
subs.EXPECT().Update(types.TenantID(7), "grpAlpha", types.Uid(42), gomock.Any()).DoAndReturn(
|
||||||
|
func(_ types.TenantID, _ string, _ types.Uid, update map[string]any) error {
|
||||||
|
private, ok := update["Private"].(map[string]any)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("Private update missing: %#v", update)
|
||||||
|
}
|
||||||
|
savedPrivate = private
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
req := httptest.NewRequest(http.MethodPut, "/v1/im/groups/grpAlpha/members/me/profile", bytes.NewBufferString(`{"nickname":"Coffee 备注","version":1}`))
|
||||||
|
req.Header.Set("Authorization", "Bearer token-1")
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
serveIMGroupResource(rec, req)
|
||||||
|
|
||||||
|
if rec.Code != http.StatusOK {
|
||||||
|
t.Fatalf("profile status: got %d body=%s", rec.Code, rec.Body.String())
|
||||||
|
}
|
||||||
|
if savedPrivate["nickname"] != "Coffee 备注" || savedPrivate["profile_version"] != 2 {
|
||||||
|
t.Fatalf("subscription private not saved: %#v", savedPrivate)
|
||||||
|
}
|
||||||
|
if data := decodeIMHTTPResponse(t, rec).Data.(map[string]any); data["nickname"] != "Coffee 备注" || data["version"].(float64) != 2 {
|
||||||
|
t.Fatalf("unexpected profile response: %#v", data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestServeIMGroupLeave(t *testing.T) {
|
func TestServeIMGroupLeave(t *testing.T) {
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|||||||
Reference in New Issue
Block a user