From 7106a74212ec9b77badc1d3467a9f2e7355f5ac8 Mon Sep 17 00:00:00 2001 From: viettranx Date: Tue, 3 Mar 2026 12:10:36 +0700 Subject: [PATCH] fix(feishu): group pairing uses group-level ID instead of per-user Changed Lark group pairing to use "group:" as sender_id (matching Telegram pattern) so one approval covers the entire group. Added approvedGroups in-memory cache to avoid DB queries per message. Co-Authored-By: Claude Opus 4.6 --- internal/channels/feishu/bot_policy.go | 20 +++++++++++++------- internal/channels/feishu/feishu.go | 1 + 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/internal/channels/feishu/bot_policy.go b/internal/channels/feishu/bot_policy.go index 009df620..f343f33f 100644 --- a/internal/channels/feishu/bot_policy.go +++ b/internal/channels/feishu/bot_policy.go @@ -66,10 +66,7 @@ func (c *Channel) checkGroupPolicy(senderID, chatID string) bool { } return false case "pairing": - paired := false - if c.pairingService != nil { - paired = c.pairingService.IsPaired(senderID, c.Name()) - } + // Allowlist bypass (per-user) inAllowList := c.HasAllowList() && c.IsAllowed(senderID) inGroupAllowList := false for _, allowed := range c.groupAllowList { @@ -78,12 +75,21 @@ func (c *Channel) checkGroupPolicy(senderID, chatID string) bool { break } } - - if paired || inAllowList || inGroupAllowList { + if inAllowList || inGroupAllowList { return true } - c.sendPairingReply(senderID, chatID) + // Group-level pairing (one approval per group, matching Telegram pattern) + if _, cached := c.approvedGroups.Load(chatID); cached { + return true + } + groupSenderID := fmt.Sprintf("group:%s", chatID) + if c.pairingService != nil && c.pairingService.IsPaired(groupSenderID, c.Name()) { + c.approvedGroups.Store(chatID, true) + return true + } + + c.sendPairingReply(groupSenderID, chatID) return false default: // "open" return true diff --git a/internal/channels/feishu/feishu.go b/internal/channels/feishu/feishu.go index 23c948eb..0aab4a5b 100644 --- a/internal/channels/feishu/feishu.go +++ b/internal/channels/feishu/feishu.go @@ -39,6 +39,7 @@ type Channel struct { dedup sync.Map // message_id → struct{} pairingDebounce sync.Map // senderID → time.Time reactions sync.Map // chatID → *reactionState + approvedGroups sync.Map // chatID → true (in-memory cache for paired groups) groupAllowList []string groupHistory *channels.PendingHistory historyLimit int