mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-23 08:56:42 +08:00
fix: unable to get owner in chat and search (#17244)
### Summary As title
This commit is contained in:
@@ -54,8 +54,8 @@ func (dao *ChatDAO) ListByTenantID(tenantID string, status string) ([]*entity.Ch
|
||||
}
|
||||
|
||||
// ListByTenantIDs list chats by tenant IDs with pagination and filtering
|
||||
func (dao *ChatDAO) ListByTenantIDs(tenantIDs []string, userID string, page, pageSize int, orderby string, desc bool, keywords string) ([]*entity.Chat, int64, error) {
|
||||
var chats []*entity.Chat
|
||||
func (dao *ChatDAO) ListByTenantIDs(tenantIDs []string, userID string, page, pageSize int, orderby string, desc bool, keywords string) ([]*entity.ChatListItem, int64, error) {
|
||||
var chats []*entity.ChatListItem
|
||||
var total int64
|
||||
|
||||
// Build query with join to user table for nickname and avatar
|
||||
@@ -93,11 +93,11 @@ func (dao *ChatDAO) ListByTenantIDs(tenantIDs []string, userID string, page, pag
|
||||
// Apply pagination
|
||||
if page > 0 && pageSize > 0 {
|
||||
offset := (page - 1) * pageSize
|
||||
if err := query.Offset(offset).Limit(pageSize).Find(&chats).Error; err != nil {
|
||||
if err := query.Offset(offset).Limit(pageSize).Scan(&chats).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
} else {
|
||||
if err := query.Find(&chats).Error; err != nil {
|
||||
if err := query.Scan(&chats).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
}
|
||||
@@ -106,8 +106,8 @@ func (dao *ChatDAO) ListByTenantIDs(tenantIDs []string, userID string, page, pag
|
||||
}
|
||||
|
||||
// ListByOwnerIDs list chats by owner IDs with filtering (manual pagination)
|
||||
func (dao *ChatDAO) ListByOwnerIDs(ownerIDs []string, userID string, orderby string, desc bool, keywords string) ([]*entity.Chat, int64, error) {
|
||||
var chats []*entity.Chat
|
||||
func (dao *ChatDAO) ListByOwnerIDs(ownerIDs []string, userID string, orderby string, desc bool, keywords string) ([]*entity.ChatListItem, int64, error) {
|
||||
var chats []*entity.ChatListItem
|
||||
|
||||
// Build query with join to user table
|
||||
query := DB.Model(&entity.Chat{}).
|
||||
@@ -135,7 +135,7 @@ func (dao *ChatDAO) ListByOwnerIDs(ownerIDs []string, userID string, orderby str
|
||||
query = query.Order(orderby + " " + orderDirection)
|
||||
|
||||
// Get all matching records
|
||||
if err := query.Find(&chats).Error; err != nil {
|
||||
if err := query.Scan(&chats).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
|
||||
@@ -45,8 +45,8 @@ type SearchDetailRow struct {
|
||||
}
|
||||
|
||||
// ListByTenantIDs list searches by tenant IDs with pagination and filtering
|
||||
func (dao *SearchDAO) ListByTenantIDs(tenantIDs []string, userID string, page, pageSize int, orderby string, desc bool, keywords string) ([]*entity.Search, int64, error) {
|
||||
var searches []*entity.Search
|
||||
func (dao *SearchDAO) ListByTenantIDs(tenantIDs []string, userID string, page, pageSize int, orderby string, desc bool, keywords string) ([]*entity.SearchListItem, int64, error) {
|
||||
var searches []*entity.SearchListItem
|
||||
var total int64
|
||||
|
||||
// Build query with join to user table for nickname and avatar
|
||||
@@ -84,11 +84,11 @@ func (dao *SearchDAO) ListByTenantIDs(tenantIDs []string, userID string, page, p
|
||||
// Apply pagination
|
||||
if page > 0 && pageSize > 0 {
|
||||
offset := (page - 1) * pageSize
|
||||
if err := query.Offset(offset).Limit(pageSize).Find(&searches).Error; err != nil {
|
||||
if err := query.Offset(offset).Limit(pageSize).Scan(&searches).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
} else {
|
||||
if err := query.Find(&searches).Error; err != nil {
|
||||
if err := query.Scan(&searches).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
}
|
||||
@@ -97,8 +97,8 @@ func (dao *SearchDAO) ListByTenantIDs(tenantIDs []string, userID string, page, p
|
||||
}
|
||||
|
||||
// ListByOwnerIDs list searches by owner IDs with filtering (manual pagination)
|
||||
func (dao *SearchDAO) ListByOwnerIDs(ownerIDs []string, userID string, orderby string, desc bool, keywords string) ([]*entity.Search, int64, error) {
|
||||
var searches []*entity.Search
|
||||
func (dao *SearchDAO) ListByOwnerIDs(ownerIDs []string, userID string, orderby string, desc bool, keywords string) ([]*entity.SearchListItem, int64, error) {
|
||||
var searches []*entity.SearchListItem
|
||||
|
||||
// Build query with join to user table
|
||||
query := DB.Model(&entity.Search{}).
|
||||
@@ -126,7 +126,7 @@ func (dao *SearchDAO) ListByOwnerIDs(ownerIDs []string, userID string, orderby s
|
||||
query = query.Order(orderby + " " + orderDirection)
|
||||
|
||||
// Get all matching records
|
||||
if err := query.Find(&searches).Error; err != nil {
|
||||
if err := query.Scan(&searches).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,13 @@ func (Chat) TableName() string {
|
||||
return "dialog"
|
||||
}
|
||||
|
||||
// ChatListItem represents a chat list row with owner profile fields.
|
||||
type ChatListItem struct {
|
||||
Chat
|
||||
Nickname *string `gorm:"column:nickname" json:"nickname,omitempty"`
|
||||
TenantAvatar *string `gorm:"column:tenant_avatar" json:"tenant_avatar,omitempty"`
|
||||
}
|
||||
|
||||
// Conversation conversation model
|
||||
type ChatSession struct {
|
||||
ID string `gorm:"column:id;primaryKey;size:32" json:"id"`
|
||||
|
||||
@@ -33,3 +33,10 @@ type Search struct {
|
||||
func (Search) TableName() string {
|
||||
return "search"
|
||||
}
|
||||
|
||||
// SearchListItem represents a search list row with owner profile fields.
|
||||
type SearchListItem struct {
|
||||
Search
|
||||
Nickname *string `gorm:"column:nickname" json:"nickname,omitempty"`
|
||||
TenantAvatar *string `gorm:"column:tenant_avatar" json:"tenant_avatar,omitempty"`
|
||||
}
|
||||
|
||||
@@ -102,8 +102,10 @@ func (h *ChatHandler) ListChats(c *gin.Context) {
|
||||
desc = descStr != "false"
|
||||
}
|
||||
|
||||
ownerIDs := getOwnerIDs(c)
|
||||
|
||||
// List chats - default to valid status "1" (same as Python StatusEnum.VALID.value)
|
||||
result, err := h.chatService.ListChats(userID, "1", keywords, page, pageSize, orderby, desc)
|
||||
result, err := h.chatService.ListChats(userID, "1", keywords, page, pageSize, orderby, desc, ownerIDs)
|
||||
if err != nil {
|
||||
common.ResponseWithHttpCodeData(c, http.StatusInternalServerError, 500, nil, err.Error())
|
||||
return
|
||||
|
||||
@@ -124,7 +124,7 @@ func MCPListDatasets(ds *dataset.DatasetService, userID string, page, pageSize i
|
||||
// MCPListChats wraps ChatService.ListChats for the MCP tool handler,
|
||||
// converting the typed response into a generic []map[string]interface{}.
|
||||
func MCPListChats(cs *service.ChatService, userID string, page, pageSize int, orderby string, desc bool) ([]map[string]interface{}, int64, error) {
|
||||
resp, err := cs.ListChats(userID, "1", "", page, pageSize, orderby, desc)
|
||||
resp, err := cs.ListChats(userID, "1", "", page, pageSize, orderby, desc, nil)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ func (h *SearchHandler) SetCompletionDependencies(streamLLM *service.ModelProvid
|
||||
h.askService = askService
|
||||
}
|
||||
|
||||
func getSearchOwnerIDs(c *gin.Context) []string {
|
||||
func getOwnerIDs(c *gin.Context) []string {
|
||||
values := c.QueryArray("owner_ids")
|
||||
if len(values) == 0 {
|
||||
values = c.QueryArray("owner_id")
|
||||
@@ -114,7 +114,7 @@ func (h *SearchHandler) ListSearches(c *gin.Context) {
|
||||
desc = descStr != "false"
|
||||
}
|
||||
|
||||
ownerIDs := getSearchOwnerIDs(c)
|
||||
ownerIDs := getOwnerIDs(c)
|
||||
|
||||
// Keep body parsing as a compatibility fallback for existing callers that
|
||||
// send owner_ids in a GET body. Python reads owner_ids from the query.
|
||||
|
||||
@@ -65,8 +65,10 @@ func NewChatService() *ChatService {
|
||||
// ChatWithKBNames chat with knowledge base names
|
||||
type ChatWithKBNames struct {
|
||||
*entity.Chat
|
||||
KBNames []string `json:"kb_names"`
|
||||
DatasetIDs []string `json:"dataset_ids"`
|
||||
KBNames []string `json:"kb_names"`
|
||||
DatasetIDs []string `json:"dataset_ids"`
|
||||
Nickname string `json:"nickname"`
|
||||
TenantAvatar *string `json:"tenant_avatar,omitempty"`
|
||||
}
|
||||
|
||||
// ListChatsResponse list chats response
|
||||
@@ -76,18 +78,53 @@ type ListChatsResponse struct {
|
||||
}
|
||||
|
||||
// ListChats list chats for a user
|
||||
func (s *ChatService) ListChats(userID, status, keywords string, page, pageSize int, orderBy string, desc bool) (*ListChatsResponse, error) {
|
||||
chats, total, err := s.chatDAO.ListByTenantIDs(
|
||||
nil,
|
||||
userID,
|
||||
page,
|
||||
pageSize,
|
||||
orderBy,
|
||||
desc,
|
||||
keywords,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func (s *ChatService) ListChats(userID, status, keywords string, page, pageSize int, orderBy string, desc bool, ownerIDs []string) (*ListChatsResponse, error) {
|
||||
var chats []*entity.ChatListItem
|
||||
var total int64
|
||||
var err error
|
||||
|
||||
if len(ownerIDs) == 0 {
|
||||
chats, total, err = s.chatDAO.ListByTenantIDs(
|
||||
nil,
|
||||
userID,
|
||||
page,
|
||||
pageSize,
|
||||
orderBy,
|
||||
desc,
|
||||
keywords,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
filterOwnerIDs, err := s.filterAccessibleChatOwnerIDs(userID, ownerIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(filterOwnerIDs) == 0 {
|
||||
return &ListChatsResponse{
|
||||
Total: 0,
|
||||
Chats: []*ChatWithKBNames{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
chats, total, err = s.chatDAO.ListByOwnerIDs(filterOwnerIDs, userID, orderBy, desc, keywords)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if page > 0 && pageSize > 0 {
|
||||
start := (page - 1) * pageSize
|
||||
end := start + pageSize
|
||||
if start < int(total) {
|
||||
if end > int(total) {
|
||||
end = int(total)
|
||||
}
|
||||
chats = chats[start:end]
|
||||
} else {
|
||||
chats = []*entity.ChatListItem{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Enrich with knowledge base names
|
||||
@@ -95,9 +132,11 @@ func (s *ChatService) ListChats(userID, status, keywords string, page, pageSize
|
||||
for _, chat := range chats {
|
||||
kbNames, datasetIDs := s.getDatasetNamesAndIDs(chat.KBIDs)
|
||||
chatsWithKBNames = append(chatsWithKBNames, &ChatWithKBNames{
|
||||
Chat: chat,
|
||||
KBNames: kbNames,
|
||||
DatasetIDs: datasetIDs,
|
||||
Chat: &chat.Chat,
|
||||
KBNames: kbNames,
|
||||
DatasetIDs: datasetIDs,
|
||||
Nickname: ownerNickname(chat.Nickname, chat.TenantID),
|
||||
TenantAvatar: chat.TenantAvatar,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -107,6 +146,46 @@ func (s *ChatService) ListChats(userID, status, keywords string, page, pageSize
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *ChatService) filterAccessibleChatOwnerIDs(userID string, ownerIDs []string) ([]string, error) {
|
||||
tenantIDs, err := s.userTenantDAO.GetTenantIDsByUserID(userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
allowed := map[string]struct{}{userID: {}}
|
||||
for _, tenantID := range tenantIDs {
|
||||
tenantID = strings.TrimSpace(tenantID)
|
||||
if tenantID != "" {
|
||||
allowed[tenantID] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
filtered := make([]string, 0, len(ownerIDs))
|
||||
seen := make(map[string]struct{}, len(ownerIDs))
|
||||
for _, ownerID := range ownerIDs {
|
||||
ownerID = strings.TrimSpace(ownerID)
|
||||
if ownerID == "" {
|
||||
continue
|
||||
}
|
||||
if _, ok := allowed[ownerID]; !ok {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[ownerID]; ok {
|
||||
continue
|
||||
}
|
||||
seen[ownerID] = struct{}{}
|
||||
filtered = append(filtered, ownerID)
|
||||
}
|
||||
return filtered, nil
|
||||
}
|
||||
|
||||
func ownerNickname(nickname *string, tenantID string) string {
|
||||
if nickname != nil && strings.TrimSpace(*nickname) != "" {
|
||||
return *nickname
|
||||
}
|
||||
return tenantID
|
||||
}
|
||||
|
||||
type CreateChatRequest struct {
|
||||
Name string
|
||||
DatasetIDs []string `json:"dataset_ids"`
|
||||
|
||||
@@ -82,7 +82,7 @@ func TestChatServiceListChatsDefaultReturnsAllWithCorrectTotal(t *testing.T) {
|
||||
createChatListTestChat(t, db, "chat-3", "user-1", "list_test_2")
|
||||
|
||||
svc := NewChatService()
|
||||
result, err := svc.ListChats("user-1", "1", "", 0, 0, "create_time", true)
|
||||
result, err := svc.ListChats("user-1", "1", "", 0, 0, "create_time", true, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("ListChats failed: %v", err)
|
||||
}
|
||||
@@ -92,6 +92,50 @@ func TestChatServiceListChatsDefaultReturnsAllWithCorrectTotal(t *testing.T) {
|
||||
if len(result.Chats) != 3 {
|
||||
t.Fatalf("expected 3 chats, got %d", len(result.Chats))
|
||||
}
|
||||
if result.Chats[0].Nickname != "tester" {
|
||||
t.Fatalf("expected nickname tester, got %q", result.Chats[0].Nickname)
|
||||
}
|
||||
}
|
||||
|
||||
func TestChatServiceListChatsFiltersByOwnerIDs(t *testing.T) {
|
||||
db := setupChatListTestDB(t)
|
||||
|
||||
if err := db.Create(&entity.User{
|
||||
ID: "tenant-2",
|
||||
Nickname: "team owner",
|
||||
Email: "tenant-2@test.com",
|
||||
Status: sptr("1"),
|
||||
}).Error; err != nil {
|
||||
t.Fatalf("failed to create tenant user: %v", err)
|
||||
}
|
||||
if err := db.Create(&entity.UserTenant{
|
||||
ID: "rel-1",
|
||||
UserID: "user-1",
|
||||
TenantID: "tenant-2",
|
||||
Role: "normal",
|
||||
InvitedBy: "tenant-2",
|
||||
Status: sptr("1"),
|
||||
}).Error; err != nil {
|
||||
t.Fatalf("failed to create user tenant relation: %v", err)
|
||||
}
|
||||
|
||||
createChatListTestChat(t, db, "chat-own", "user-1", "own_chat")
|
||||
createChatListTestChat(t, db, "chat-team", "tenant-2", "team_chat")
|
||||
|
||||
svc := NewChatService()
|
||||
result, err := svc.ListChats("user-1", "1", "", 0, 0, "create_time", true, []string{"tenant-2"})
|
||||
if err != nil {
|
||||
t.Fatalf("ListChats failed: %v", err)
|
||||
}
|
||||
if result.Total != 1 || len(result.Chats) != 1 {
|
||||
t.Fatalf("expected one filtered chat, got total=%d len=%d", result.Total, len(result.Chats))
|
||||
}
|
||||
if result.Chats[0].TenantID != "tenant-2" {
|
||||
t.Fatalf("expected tenant-2 chat, got tenant %q", result.Chats[0].TenantID)
|
||||
}
|
||||
if result.Chats[0].Nickname != "team owner" {
|
||||
t.Fatalf("expected nickname team owner, got %q", result.Chats[0].Nickname)
|
||||
}
|
||||
}
|
||||
|
||||
func TestChatServiceListChatsKeywordFiltersCorrectly(t *testing.T) {
|
||||
@@ -102,7 +146,7 @@ func TestChatServiceListChatsKeywordFiltersCorrectly(t *testing.T) {
|
||||
|
||||
svc := NewChatService()
|
||||
|
||||
exactResult, err := svc.ListChats("user-1", "1", "list_keyword_1", 0, 0, "create_time", true)
|
||||
exactResult, err := svc.ListChats("user-1", "1", "list_keyword_1", 0, 0, "create_time", true, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("ListChats keyword exact failed: %v", err)
|
||||
}
|
||||
@@ -113,7 +157,7 @@ func TestChatServiceListChatsKeywordFiltersCorrectly(t *testing.T) {
|
||||
t.Fatalf("expected chat name 'list_keyword_1', got %+v", exactResult.Chats[0].Name)
|
||||
}
|
||||
|
||||
unknownResult, err := svc.ListChats("user-1", "1", "unknown_keyword", 0, 0, "create_time", true)
|
||||
unknownResult, err := svc.ListChats("user-1", "1", "unknown_keyword", 0, 0, "create_time", true, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("ListChats unknown keyword failed: %v", err)
|
||||
}
|
||||
@@ -121,7 +165,7 @@ func TestChatServiceListChatsKeywordFiltersCorrectly(t *testing.T) {
|
||||
t.Fatalf("expected 0 chats for unknown keyword, got %d", len(unknownResult.Chats))
|
||||
}
|
||||
|
||||
partialResult, err := svc.ListChats("user-1", "1", "list_keyword", 0, 0, "create_time", true)
|
||||
partialResult, err := svc.ListChats("user-1", "1", "list_keyword", 0, 0, "create_time", true, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("ListChats partial keyword failed: %v", err)
|
||||
}
|
||||
@@ -138,7 +182,7 @@ func TestChatServiceListChatsPagination(t *testing.T) {
|
||||
|
||||
svc := NewChatService()
|
||||
|
||||
page1, err := svc.ListChats("user-1", "1", "", 1, 2, "create_time", true)
|
||||
page1, err := svc.ListChats("user-1", "1", "", 1, 2, "create_time", true, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("ListChats page 1 failed: %v", err)
|
||||
}
|
||||
@@ -149,7 +193,7 @@ func TestChatServiceListChatsPagination(t *testing.T) {
|
||||
t.Fatalf("expected total=5, got %d", page1.Total)
|
||||
}
|
||||
|
||||
page3, err := svc.ListChats("user-1", "1", "", 3, 2, "create_time", true)
|
||||
page3, err := svc.ListChats("user-1", "1", "", 3, 2, "create_time", true, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("ListChats page 3 failed: %v", err)
|
||||
}
|
||||
@@ -167,7 +211,7 @@ func TestChatServiceListChatsExcludesDeletedChats(t *testing.T) {
|
||||
db.Model(&entity.Chat{}).Where("id = ?", "chat-2").Update("status", invalidStatus)
|
||||
|
||||
svc := NewChatService()
|
||||
result, err := svc.ListChats("user-1", "1", "", 0, 0, "create_time", true)
|
||||
result, err := svc.ListChats("user-1", "1", "", 0, 0, "create_time", true, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("ListChats failed: %v", err)
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ type SearchShareDetail struct {
|
||||
|
||||
// ListSearches list search apps with advanced filtering (equivalent to list_search_app)
|
||||
func (s *SearchService) ListSearches(userID string, keywords string, page, pageSize int, orderby string, desc bool, ownerIDs []string) (*ListSearchAppsResponse, error) {
|
||||
var searches []*entity.Search
|
||||
var searches []*entity.SearchListItem
|
||||
var total int64
|
||||
var err error
|
||||
|
||||
@@ -115,7 +115,7 @@ func (s *SearchService) ListSearches(userID string, keywords string, page, pageS
|
||||
}
|
||||
searches = searches[start:end]
|
||||
} else {
|
||||
searches = []*entity.Search{}
|
||||
searches = []*entity.SearchListItem{}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -166,7 +166,7 @@ func (s *SearchService) filterAccessibleSearchOwnerIDs(userID string, ownerIDs [
|
||||
}
|
||||
|
||||
// toSearchAppResponse converts search model to response format
|
||||
func (s *SearchService) toSearchAppResponse(search *entity.Search) map[string]interface{} {
|
||||
func (s *SearchService) toSearchAppResponse(search *entity.SearchListItem) map[string]interface{} {
|
||||
result := map[string]interface{}{
|
||||
"id": search.ID,
|
||||
"tenant_id": search.TenantID,
|
||||
@@ -177,16 +177,15 @@ func (s *SearchService) toSearchAppResponse(search *entity.Search) map[string]in
|
||||
"create_time": search.CreateTime,
|
||||
"update_time": search.UpdateTime,
|
||||
"search_config": map[string]interface{}(search.SearchConfig),
|
||||
"nickname": ownerNickname(search.Nickname, search.TenantID),
|
||||
}
|
||||
|
||||
if search.Avatar != nil {
|
||||
result["avatar"] = *search.Avatar
|
||||
}
|
||||
|
||||
// Add joined fields from user table
|
||||
// Note: These fields are populated by the DAO query with Select clause
|
||||
// but GORM will map them to the model's embedded fields if available
|
||||
// We need to handle the extra fields manually
|
||||
if search.TenantAvatar != nil {
|
||||
result["tenant_avatar"] = *search.TenantAvatar
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -33,6 +33,22 @@ func setupSearchServiceTestDB(t *testing.T) {
|
||||
pushServiceDB(t, db)
|
||||
}
|
||||
|
||||
func createSearchServiceTestSearch(t *testing.T, id, tenantID, name string) {
|
||||
t.Helper()
|
||||
|
||||
status := string(entity.StatusValid)
|
||||
if err := dao.DB.Create(&entity.Search{
|
||||
ID: id,
|
||||
TenantID: tenantID,
|
||||
Name: name,
|
||||
CreatedBy: tenantID,
|
||||
SearchConfig: entity.JSONMap{},
|
||||
Status: &status,
|
||||
}).Error; err != nil {
|
||||
t.Fatalf("failed to create search: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSearchServiceCreateRejectsEmptyName(t *testing.T) {
|
||||
setupSearchServiceTestDB(t)
|
||||
|
||||
@@ -106,3 +122,44 @@ func TestSearchServiceCreateAndUpdateRoundTrip(t *testing.T) {
|
||||
t.Fatalf("expected persisted name, got %q", persisted.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSearchServiceListSearchesReturnsOwnerDisplayFields(t *testing.T) {
|
||||
setupSearchServiceTestDB(t)
|
||||
|
||||
if err := dao.DB.Create(&entity.User{
|
||||
ID: "user-1",
|
||||
Nickname: "search owner",
|
||||
Status: sptr("1"),
|
||||
}).Error; err != nil {
|
||||
t.Fatalf("failed to create user: %v", err)
|
||||
}
|
||||
createSearchServiceTestSearch(t, "search-1", "user-1", "Search One")
|
||||
|
||||
result, err := NewSearchService().ListSearches("user-1", "", 0, 0, "create_time", true, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("ListSearches failed: %v", err)
|
||||
}
|
||||
if result.Total != 1 || len(result.SearchApps) != 1 {
|
||||
t.Fatalf("expected one search app, got total=%d len=%d", result.Total, len(result.SearchApps))
|
||||
}
|
||||
if got, want := result.SearchApps[0]["nickname"], "search owner"; got != want {
|
||||
t.Fatalf("nickname = %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSearchServiceListSearchesNicknameFallsBackToTenantID(t *testing.T) {
|
||||
setupSearchServiceTestDB(t)
|
||||
|
||||
createSearchServiceTestSearch(t, "search-1", "user-1", "Search One")
|
||||
|
||||
result, err := NewSearchService().ListSearches("user-1", "", 0, 0, "create_time", true, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("ListSearches failed: %v", err)
|
||||
}
|
||||
if result.Total != 1 || len(result.SearchApps) != 1 {
|
||||
t.Fatalf("expected one search app, got total=%d len=%d", result.Total, len(result.SearchApps))
|
||||
}
|
||||
if got, want := result.SearchApps[0]["nickname"], "user-1"; got != want {
|
||||
t.Fatalf("nickname = %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user