81 lines
3.4 KiB
Go
81 lines
3.4 KiB
Go
package rpc
|
||
|
||
import (
|
||
"context"
|
||
"testing"
|
||
|
||
"github.com/gotd/td/clock"
|
||
"go.uber.org/zap/zaptest"
|
||
|
||
appchannels "telesrv/internal/app/channels"
|
||
"telesrv/internal/domain"
|
||
"telesrv/internal/store/memory"
|
||
)
|
||
|
||
// privacyBotResolver 让指定 user 成为 bot_chat_history=false 的隐私 bot(命令/@/回复以外的群消息不可见)。
|
||
type privacyBotResolver map[int64]bool
|
||
|
||
func (p privacyBotResolver) BotInfo(_ context.Context, botUserID int64) (domain.BotProfile, bool, error) {
|
||
if _, ok := p[botUserID]; !ok {
|
||
return domain.BotProfile{}, false, nil
|
||
}
|
||
return domain.BotProfile{BotUserID: botUserID, ChatHistory: false}, true, nil
|
||
}
|
||
|
||
// TestChannelMessageFanoutSkipsPrivacyBotOnlinePush 回归:在线 privacy bot 不得经实时 fanout 收到群里
|
||
// 的纯文本消息。修复前 channelFanoutRecipients 按「在线活跃成员」重算 recipients,会把 send 时已按
|
||
// SkipDeliveryUserIDs 排除的 bot 加回 → 在线 bot 实时收到全部群聊内容(持久 history/difference 已正确
|
||
// 隐藏,仅此直接推送泄漏内容)。修复后 fanout build 对被 skip 的 viewer 返回 nil,不推送。
|
||
func TestChannelMessageFanoutSkipsPrivacyBotOnlinePush(t *testing.T) {
|
||
ctx := context.Background()
|
||
channelStore := memory.NewChannelStore()
|
||
bots := privacyBotResolver{1003: true}
|
||
channelService := appchannels.NewService(channelStore, appchannels.WithBotProfileResolver(bots))
|
||
created, err := channelService.CreateMegagroupFromCreateChat(ctx, 1001, domain.CreateChannelRequest{
|
||
Title: "Privacy",
|
||
MemberUserIDs: []int64{1002, 1003},
|
||
Date: 10,
|
||
})
|
||
if err != nil {
|
||
t.Fatalf("create channel: %v", err)
|
||
}
|
||
|
||
// 纯文本消息:privacy bot 1003 不可见 → SendMessage 把它放进 SkipDeliveryUserIDs、排除出 Recipients。
|
||
res, err := channelService.SendMessage(ctx, 1001, domain.SendChannelMessageRequest{
|
||
ChannelID: created.Channel.ID,
|
||
RandomID: 2001,
|
||
Message: "plain group chatter",
|
||
Date: 11,
|
||
})
|
||
if err != nil {
|
||
t.Fatalf("send: %v", err)
|
||
}
|
||
if !fanoutHasID(res.SkipDeliveryUserIDs, 1003) {
|
||
t.Fatalf("res.SkipDeliveryUserIDs = %v, want privacy bot 1003 excluded at send", res.SkipDeliveryUserIDs)
|
||
}
|
||
if fanoutHasID(res.Recipients, 1003) {
|
||
t.Fatalf("res.Recipients = %v, privacy bot 1003 must not be a delivery recipient", res.Recipients)
|
||
}
|
||
|
||
// 两成员都在线;channelFanoutRecipients 据此把 1003 当在线活跃成员加回 recipients。
|
||
sessions := &captureSessions{
|
||
channelMembers: map[int64][]int64{created.Channel.ID: {1002, 1003}},
|
||
}
|
||
r := New(Config{}, Deps{Channels: channelService, Sessions: sessions}, zaptest.NewLogger(t), clock.System)
|
||
|
||
// 复核前置:修复前后 channelFanoutRecipients 都会把 1003 列进 recipients(在线活跃成员),
|
||
// 漏洞/修复的差异在 build 是否对它返回 nil。
|
||
got := r.channelFanoutRecipients(ctx, channelFanoutMembers, created.Channel.ID, res.Recipients)
|
||
if !fanoutHasID(got, 1003) {
|
||
t.Fatalf("channelFanoutRecipients = %v, 期望在线活跃成员 1003 仍被列入(否则测不到 build 跳过)", got)
|
||
}
|
||
|
||
r.enqueueChannelMessageFanout(ctx, 1001, res, nil)
|
||
pushed := sessions.pushedUserIDs()
|
||
if !fanoutHasID(pushed, 1002) {
|
||
t.Fatalf("fanout pushed = %v, want human member 1002 to receive online push", pushed)
|
||
}
|
||
if fanoutHasID(pushed, 1003) {
|
||
t.Fatalf("fanout pushed = %v, online privacy bot 1003 must NOT receive plain-message push (privacy leak)", pushed)
|
||
}
|
||
}
|