H-388: tighten contact inbox conversation scope (#68)

Co-authored-by: Rogee <rogee@ipao.vip>
This commit is contained in:
Rogee
2026-08-21 13:19:12 +08:00
committed by GitHub
co-authored by rogee
parent a0a6c338f5
commit 40ab664b08
2 changed files with 37 additions and 2 deletions
@@ -197,8 +197,8 @@ func (r *ConversationRepo) FindByContactInbox(ctx context.Context, accountID, co
var conversations []model.Conversation
var total int64
query := r.db.WithContext(ctx).Model(&model.Conversation{}).
Where("account_id = ? AND (contact_inbox_id = ? OR (contact_inbox_id IS NULL AND contact_id = ? AND inbox_id = ? AND ?))",
accountID, contactInboxID, contactID, inboxID, includeLegacy)
Where("account_id = ? AND contact_id = ? AND inbox_id = ? AND (contact_inbox_id = ? OR (contact_inbox_id IS NULL AND ?))",
accountID, contactID, inboxID, contactInboxID, includeLegacy)
if err := query.Count(&total).Error; err != nil {
return nil, 0, err
}
@@ -85,6 +85,41 @@ func TestConversationRepo_FindByContactInboxIncludesLegacyOnlyWhenAllowed(t *tes
assert.Equal(t, owned.ID, conversations[0].ID)
}
func TestConversationRepo_FindByContactInboxRejectsMismatchedConversationIdentity(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)
account := &model.Account{Name: "Widget identity scope account", Active: true}
require.NoError(t, db.Create(account).Error)
inbox := &model.Inbox{AccountID: account.ID, Name: "Widget", ChannelType: "web_widget"}
require.NoError(t, db.Create(inbox).Error)
otherInbox := &model.Inbox{AccountID: account.ID, Name: "Other widget", ChannelType: "web_widget"}
require.NoError(t, db.Create(otherInbox).Error)
contact := &model.Contact{AccountID: account.ID, Name: "Visitor"}
require.NoError(t, db.Create(contact).Error)
otherContact := &model.Contact{AccountID: account.ID, Name: "Other visitor"}
require.NoError(t, db.Create(otherContact).Error)
contactInbox := &model.ContactInbox{ContactID: contact.ID, InboxID: inbox.ID, PubsubToken: "scope-token"}
require.NoError(t, db.Create(contactInbox).Error)
owned := createTestConversation(t, db, account.ID, inbox.ID, contact.ID, "open")
wrongContact := createTestConversation(t, db, account.ID, inbox.ID, otherContact.ID, "open")
wrongInbox := createTestConversation(t, db, account.ID, otherInbox.ID, contact.ID, "open")
for _, conversation := range []*model.Conversation{owned, wrongContact, wrongInbox} {
require.NoError(t, db.Model(conversation).Update("contact_inbox_id", contactInbox.ID).Error)
}
conversations, total, err := repo.FindByContactInbox(context.Background(), account.ID, contact.ID, inbox.ID, contactInbox.ID, false, 0, 10)
require.NoError(t, err)
require.Equal(t, int64(1), total)
require.Len(t, conversations, 1)
assert.Equal(t, owned.ID, conversations[0].ID)
latest, _, err := repo.FindByContactInbox(context.Background(), account.ID, contact.ID, inbox.ID, contactInbox.ID, false, 0, 1)
require.NoError(t, err)
require.Len(t, latest, 1)
assert.Equal(t, owned.ID, latest[0].ID)
}
func TestConversationRepo_FindByAccountAndID(t *testing.T) {
db := setupTestDB(t)
repo := NewConversationRepo(db)