feat(search): scope message recency

This commit is contained in:
2026-06-07 07:22:42 +08:00
parent 4bde740c80
commit 112ae43955
8 changed files with 101 additions and 10 deletions
+10
View File
@@ -33,6 +33,7 @@ type RepoSearchFilter struct {
Private *bool
EnforceInboxAccess bool
AccessibleInboxIDs []uint
MessageCreatedAfter *time.Time
DateFrom *time.Time
DateTo *time.Time
SortBy string
@@ -107,6 +108,7 @@ func searchFilterToRepo(f *search.SearchFilter) *RepoSearchFilter {
Private: f.Private,
EnforceInboxAccess: f.EnforceInboxAccess,
AccessibleInboxIDs: append([]uint(nil), f.AccessibleInboxIDs...),
MessageCreatedAfter: f.MessageCreatedAfter,
DateFrom: f.DateFrom,
DateTo: f.DateTo,
SortBy: f.SortBy,
@@ -207,6 +209,7 @@ func (r *SearchRepo) searchMessagesInternal(ctx context.Context, accountID uint,
var total int64
q := r.db.WithContext(ctx).Model(&model.Message{}).Where("account_id = ?", accountID)
q = applyMessageRecentBase(q, filter)
// Text search on message content — ILIKE or pg_trgm fuzzy match
if query != "" {
@@ -515,6 +518,13 @@ func applySearchInboxAccess(q *gorm.DB, filter *RepoSearchFilter) *gorm.DB {
return q.Where("inbox_id IN ?", filter.AccessibleInboxIDs)
}
func applyMessageRecentBase(q *gorm.DB, filter *RepoSearchFilter) *gorm.DB {
if filter == nil || filter.MessageCreatedAfter == nil {
return q
}
return q.Where("created_at >= ?", *filter.MessageCreatedAfter)
}
func searchInboxIDAllowed(filter *RepoSearchFilter, inboxID uint) bool {
if filter == nil || !filter.EnforceInboxAccess {
return true
+22
View File
@@ -4,6 +4,7 @@ import (
"context"
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -245,6 +246,27 @@ func TestSearchRepo_SearchMessages_InaccessibleInboxParamFallsBackToAccessibleBa
assert.Equal(t, visibleMsg.ID, results[0].ID)
}
func TestSearchRepo_SearchMessages_MessageBaseExcludesOldMessages(t *testing.T) {
db := setupTestDB(t)
repo := NewSearchRepo(db)
account := createTestAccountForSearch(t, db)
conv := createTestConversationForSearch(t, db, account.ID, "open", "")
cutoff := time.Date(2026, 3, 7, 12, 0, 0, 0, time.UTC)
recentMsg := createTestMessageForSearch(t, db, account.ID, conv.ID, "recent message", "incoming")
require.NoError(t, db.Model(recentMsg).Update("created_at", cutoff.Add(time.Hour)).Error)
oldMsg := createTestMessageForSearch(t, db, account.ID, conv.ID, "old message", "incoming")
require.NoError(t, db.Model(oldMsg).Update("created_at", cutoff.Add(-time.Hour)).Error)
filter := &search.SearchFilter{Page: 1, PerPage: 25, MessageCreatedAfter: &cutoff}
results, total, err := repo.SearchMessages(context.Background(), account.ID, "", filter)
require.NoError(t, err)
assert.Equal(t, int64(1), total)
require.Len(t, results, 1)
assert.Equal(t, recentMsg.ID, results[0].ID)
}
// ========== SearchConversations DB tests (PG only for ILIKE) ==========
func TestSearchRepo_SearchConversations_EmptyQuery(t *testing.T) {