fix: sync public channel preview updates

This commit is contained in:
iamxvbaba 2026-07-24 14:50:17 +08:00
parent 2289a31f46
commit b4aaf57d6b
27 changed files with 877 additions and 128 deletions

View file

@ -2295,6 +2295,21 @@ func (s *Service) FilterActiveMemberIDs(ctx context.Context, channelID int64, us
return s.channels.FilterActiveChannelMemberIDs(ctx, channelID, candidates)
}
// FilterMessageAudienceIDs keeps active members and currently authorized
// public-preview viewers from a bounded online candidate set. The store performs
// one batched authoritative check per bounded chunk so runtime session indexes
// never become an access-control source of truth.
func (s *Service) FilterMessageAudienceIDs(ctx context.Context, channelID int64, userIDs []int64) ([]int64, error) {
if s == nil || s.channels == nil || channelID == 0 {
return nil, domain.ErrChannelInvalid
}
candidates := uniqueNonZero(userIDs)
if len(candidates) == 0 {
return nil, nil
}
return s.channels.FilterChannelMessageAudienceIDs(ctx, channelID, candidates)
}
// GetDifference returns channel-scoped pts difference.
func (s *Service) GetDifference(ctx context.Context, userID int64, req domain.ChannelDifferenceRequest) (domain.ChannelDifference, error) {
if s == nil || s.channels == nil || userID == 0 || req.ChannelID == 0 {

View file

@ -3014,12 +3014,37 @@ func TestPublicChannelPreviewAllowsNonMemberHistory(t *testing.T) {
if err != nil {
t.Fatalf("non-member GetDifference public preview: %v", err)
}
if !diff.Final || diff.Pts != sent.Event.Pts || len(diff.Events) != 0 || len(diff.NewMessages) != 0 || len(diff.OtherUpdates) != 0 {
t.Fatalf("preview diff = %+v, want empty public preview difference at current pts", diff)
if !diff.Final || diff.Pts != sent.Event.Pts || len(diff.Events) != 1 || len(diff.NewMessages) != 1 || len(diff.OtherUpdates) != 0 {
t.Fatalf("preview diff = %+v, want one public preview message at current pts", diff)
}
if diff.NewMessages[0].ID != sent.Message.ID || diff.NewMessages[0].Body != sent.Message.Body {
t.Fatalf("preview diff message = %+v, want sent public post %+v", diff.NewMessages[0], sent.Message)
}
if diff.Dialog.UnreadCount != 0 || diff.Dialog.ReadInboxMaxID < sent.Message.ID {
t.Fatalf("preview diff dialog = %+v, want read-only public preview dialog", diff.Dialog)
}
audience, err := service.FilterMessageAudienceIDs(ctx, public.ID, []int64{viewerID, ownerID, viewerID})
if err != nil || len(audience) != 2 {
t.Fatalf("public message audience = %v err %v, want owner and preview viewer", audience, err)
}
if _, err := service.JoinChannel(ctx, viewerID, public.ID, 21); err != nil {
t.Fatalf("JoinChannel public preview viewer: %v", err)
}
if _, err := service.LeaveChannel(ctx, viewerID, public.ID, 22); err != nil {
t.Fatalf("LeaveChannel public preview viewer: %v", err)
}
filtered, err := service.GetDifference(ctx, viewerID, domain.ChannelDifferenceRequest{
ChannelID: public.ID,
Pts: sent.Event.Pts,
Limit: 10,
})
if err != nil {
t.Fatalf("preview difference across participant events: %v", err)
}
if !filtered.Final || filtered.Pts != sent.Event.Pts || len(filtered.Events) != 0 ||
len(filtered.NewMessages) != 0 || len(filtered.OtherUpdates) != 0 {
t.Fatalf("difference after transient participant changes = %+v, want unchanged PTS", filtered)
}
private, err := service.CreateChannel(ctx, ownerID, domain.CreateChannelRequest{
Title: "Private Preview",
@ -3047,6 +3072,9 @@ func TestPublicChannelPreviewAllowsNonMemberHistory(t *testing.T) {
if _, err := service.GetDifference(ctx, viewerID, domain.ChannelDifferenceRequest{ChannelID: public.ID, Pts: created.Event.Pts, Limit: 10}); !errors.Is(err, domain.ErrChannelUserBanned) {
t.Fatalf("banned public preview GetDifference err = %v, want ErrChannelUserBanned", err)
}
if audience, err := service.FilterMessageAudienceIDs(ctx, public.ID, []int64{viewerID}); err != nil || len(audience) != 0 {
t.Fatalf("banned public message audience = %v err %v, want empty", audience, err)
}
}
func TestChannelDifferenceStartsAtMemberAvailableMinPts(t *testing.T) {