From 0d5a6c21946f5dc1fbe3cc94312941e58e3f6105 Mon Sep 17 00:00:00 2001 From: ying-jeanne <74549700+ying-jeanne@users.noreply.github.com> Date: Mon, 21 Mar 2022 16:54:30 +0100 Subject: [PATCH] remove bus from search and avoid import cycle (#46789) * fix the import cicle * fix some unittest * fix removal bus from search --- pkg/api/alerting.go | 4 +- pkg/api/alerting_test.go | 10 ++-- pkg/api/docs/definitions/search.go | 4 +- .../search/hits.go => models/search.go} | 40 ++++++++++++++- .../database/database_dashboard_test.go | 31 ++++++----- .../database/database_folder_test.go | 29 +++++------ pkg/services/search/service.go | 51 +++++++------------ pkg/services/search/service_test.go | 37 +++++--------- pkg/services/search/sorting.go | 28 +++------- pkg/services/sqlstore/dashboard.go | 21 ++++---- pkg/services/sqlstore/mockstore/mockstore.go | 13 +++-- pkg/services/sqlstore/store.go | 3 +- .../api/dashboards/api_dashboards_test.go | 3 +- 13 files changed, 137 insertions(+), 137 deletions(-) rename pkg/{services/search/hits.go => models/search.go} (63%) diff --git a/pkg/api/alerting.go b/pkg/api/alerting.go index 15414b6269d..4b58ace4bce 100644 --- a/pkg/api/alerting.go +++ b/pkg/api/alerting.go @@ -89,7 +89,7 @@ func (hs *HTTPServer) GetAlerts(c *models.ReqContext) response.Response { Limit: 1000, OrgId: c.OrgId, DashboardIds: dashboardIDs, - Type: string(search.DashHitDB), + Type: string(models.DashHitDB), FolderIds: folderIDs, Permission: models.PERMISSION_VIEW, } @@ -100,7 +100,7 @@ func (hs *HTTPServer) GetAlerts(c *models.ReqContext) response.Response { } for _, d := range searchQuery.Result { - if d.Type == search.DashHitDB && d.ID > 0 { + if d.Type == models.DashHitDB && d.ID > 0 { dashboardIDs = append(dashboardIDs, d.ID) } } diff --git a/pkg/api/alerting_test.go b/pkg/api/alerting_test.go index 952c97a9e30..1f09ca06a19 100644 --- a/pkg/api/alerting_test.go +++ b/pkg/api/alerting_test.go @@ -27,13 +27,13 @@ type setUpConf struct { aclMockResp []*models.DashboardAclInfoDTO } -type mockSearchService struct{ ExpectedResult search.HitList } +type mockSearchService struct{ ExpectedResult models.HitList } func (mss *mockSearchService) SearchHandler(_ context.Context, q *search.Query) error { q.Result = mss.ExpectedResult return nil } -func (mss *mockSearchService) SortOptions() []search.SortOption { return nil } +func (mss *mockSearchService) SortOptions() []models.SortOption { return nil } func setUp(confs ...setUpConf) *HTTPServer { singleAlert := &models.Alert{Id: 1, DashboardId: 1, Name: "singlealert"} @@ -94,9 +94,9 @@ func TestAlertingAPIEndpoint(t *testing.T) { loggedInUserScenarioWithRole(t, "When calling GET on", "GET", "/api/alerts?dashboardId=1&dashboardId=2&folderId=3&dashboardTag=abc&dashboardQuery=dbQuery&limit=5&query=alertQuery", "/api/alerts", models.ROLE_EDITOR, func(sc *scenarioContext) { - hs.SearchService.(*mockSearchService).ExpectedResult = search.HitList{ - &search.Hit{ID: 1}, - &search.Hit{ID: 2}, + hs.SearchService.(*mockSearchService).ExpectedResult = models.HitList{ + &models.Hit{ID: 1}, + &models.Hit{ID: 2}, } sc.handlerFunc = hs.GetAlerts diff --git a/pkg/api/docs/definitions/search.go b/pkg/api/docs/definitions/search.go index a76acd39be6..1e3ffd29731 100644 --- a/pkg/api/docs/definitions/search.go +++ b/pkg/api/docs/definitions/search.go @@ -1,6 +1,6 @@ package definitions -import "github.com/grafana/grafana/pkg/services/search" +import "github.com/grafana/grafana/pkg/models" // swagger:route GET /search/sorting search searchSorting // @@ -75,7 +75,7 @@ type SearchParameters struct { // swagger:response searchResponse type SearchResponse struct { // in: body - Body search.HitList `json:"body"` + Body models.HitList `json:"body"` } // swagger:response searchSortingResponse diff --git a/pkg/services/search/hits.go b/pkg/models/search.go similarity index 63% rename from pkg/services/search/hits.go rename to pkg/models/search.go index fbc9a473f8d..2bc351678e7 100644 --- a/pkg/services/search/hits.go +++ b/pkg/models/search.go @@ -1,6 +1,42 @@ -package search +package models -import "strings" +import ( + "strings" + + "github.com/grafana/grafana/pkg/services/sqlstore/searchstore" +) + +type SortOption struct { + Name string + DisplayName string + Description string + Index int + MetaName string + Filter []SortOptionFilter +} + +type SortOptionFilter interface { + searchstore.FilterOrderBy +} + +type FindPersistedDashboardsQuery struct { + Title string + OrgId int64 + SignedInUser *SignedInUser + IsStarred bool + DashboardIds []int64 + Type string + FolderIds []int64 + Tags []string + Limit int64 + Page int64 + Permission PermissionType + Sort SortOption + + Filters []interface{} + + Result HitList +} type HitType string diff --git a/pkg/services/dashboards/database/database_dashboard_test.go b/pkg/services/dashboards/database/database_dashboard_test.go index 7524d84b70f..90518f6a2f9 100644 --- a/pkg/services/dashboards/database/database_dashboard_test.go +++ b/pkg/services/dashboards/database/database_dashboard_test.go @@ -16,7 +16,6 @@ import ( "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/models" - "github.com/grafana/grafana/pkg/services/search" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore/searchstore" "github.com/grafana/grafana/pkg/setting" @@ -211,7 +210,7 @@ func TestDashboardDataAccess(t *testing.T) { err := sqlStore.DeleteDashboard(context.Background(), deleteCmd) require.NoError(t, err) - query := search.FindPersistedDashboardsQuery{ + query := models.FindPersistedDashboardsQuery{ OrgId: 1, FolderIds: []int64{savedFolder.Id}, SignedInUser: &models.SignedInUser{}, @@ -278,7 +277,7 @@ func TestDashboardDataAccess(t *testing.T) { t.Run("Should be able to search for dashboard folder", func(t *testing.T) { setup() - query := search.FindPersistedDashboardsQuery{ + query := models.FindPersistedDashboardsQuery{ Title: "1 test dash folder", OrgId: 1, SignedInUser: &models.SignedInUser{OrgId: 1, OrgRole: models.ROLE_EDITOR}, @@ -289,14 +288,14 @@ func TestDashboardDataAccess(t *testing.T) { require.Equal(t, len(query.Result), 1) hit := query.Result[0] - require.Equal(t, hit.Type, search.DashHitFolder) + require.Equal(t, hit.Type, models.DashHitFolder) require.Equal(t, hit.URL, fmt.Sprintf("/dashboards/f/%s/%s", savedFolder.Uid, savedFolder.Slug)) require.Equal(t, hit.FolderTitle, "") }) t.Run("Should be able to limit search", func(t *testing.T) { setup() - query := search.FindPersistedDashboardsQuery{ + query := models.FindPersistedDashboardsQuery{ OrgId: 1, Limit: 1, SignedInUser: &models.SignedInUser{OrgId: 1, OrgRole: models.ROLE_EDITOR}, @@ -311,7 +310,7 @@ func TestDashboardDataAccess(t *testing.T) { t.Run("Should be able to search beyond limit using paging", func(t *testing.T) { setup() - query := search.FindPersistedDashboardsQuery{ + query := models.FindPersistedDashboardsQuery{ OrgId: 1, Limit: 1, Page: 2, @@ -327,7 +326,7 @@ func TestDashboardDataAccess(t *testing.T) { t.Run("Should be able to filter by tag and type", func(t *testing.T) { setup() - query := search.FindPersistedDashboardsQuery{ + query := models.FindPersistedDashboardsQuery{ OrgId: 1, Type: "dash-db", Tags: []string{"prod"}, @@ -343,7 +342,7 @@ func TestDashboardDataAccess(t *testing.T) { t.Run("Should be able to search for a dashboard folder's children", func(t *testing.T) { setup() - query := search.FindPersistedDashboardsQuery{ + query := models.FindPersistedDashboardsQuery{ OrgId: 1, FolderIds: []int64{savedFolder.Id}, SignedInUser: &models.SignedInUser{OrgId: 1, OrgRole: models.ROLE_EDITOR}, @@ -364,7 +363,7 @@ func TestDashboardDataAccess(t *testing.T) { t.Run("Should be able to search for dashboard by dashboard ids", func(t *testing.T) { setup() - query := search.FindPersistedDashboardsQuery{ + query := models.FindPersistedDashboardsQuery{ DashboardIds: []int64{savedDash.Id, savedDash2.Id}, SignedInUser: &models.SignedInUser{OrgId: 1, OrgRole: models.ROLE_EDITOR}, } @@ -396,7 +395,7 @@ func TestDashboardDataAccess(t *testing.T) { }) require.NoError(t, err) - query := search.FindPersistedDashboardsQuery{ + query := models.FindPersistedDashboardsQuery{ SignedInUser: &models.SignedInUser{UserId: 10, OrgId: 1, OrgRole: models.ROLE_EDITOR}, IsStarred: true, } @@ -435,7 +434,7 @@ func TestDashboard_SortingOptions(t *testing.T) { dashA := insertTestDashboard(t, dashboardStore, "Alfa", 1, 0, false) assert.NotZero(t, dashA.Id) assert.Less(t, dashB.Id, dashA.Id) - qNoSort := &search.FindPersistedDashboardsQuery{ + qNoSort := &models.FindPersistedDashboardsQuery{ SignedInUser: &models.SignedInUser{OrgId: 1, UserId: 1, OrgRole: models.ROLE_ADMIN}, } dashboards, err := sqlStore.FindDashboards(context.Background(), qNoSort) @@ -444,10 +443,10 @@ func TestDashboard_SortingOptions(t *testing.T) { assert.Equal(t, dashA.Id, dashboards[0].ID) assert.Equal(t, dashB.Id, dashboards[1].ID) - qSort := &search.FindPersistedDashboardsQuery{ + qSort := &models.FindPersistedDashboardsQuery{ SignedInUser: &models.SignedInUser{OrgId: 1, UserId: 1, OrgRole: models.ROLE_ADMIN}, - Sort: search.SortOption{ - Filter: []search.SortOptionFilter{ + Sort: models.SortOption{ + Filter: []models.SortOptionFilter{ searchstore.TitleSorter{Descending: true}, }, }, @@ -465,14 +464,14 @@ func TestDashboard_Filter(t *testing.T) { dashboardStore := ProvideDashboardStore(sqlStore) insertTestDashboard(t, dashboardStore, "Alfa", 1, 0, false) dashB := insertTestDashboard(t, dashboardStore, "Beta", 1, 0, false) - qNoFilter := &search.FindPersistedDashboardsQuery{ + qNoFilter := &models.FindPersistedDashboardsQuery{ SignedInUser: &models.SignedInUser{OrgId: 1, UserId: 1, OrgRole: models.ROLE_ADMIN}, } dashboards, err := sqlStore.FindDashboards(context.Background(), qNoFilter) require.NoError(t, err) require.Len(t, dashboards, 2) - qFilter := &search.FindPersistedDashboardsQuery{ + qFilter := &models.FindPersistedDashboardsQuery{ SignedInUser: &models.SignedInUser{OrgId: 1, UserId: 1, OrgRole: models.ROLE_ADMIN}, Filters: []interface{}{ searchstore.TitleFilter{ diff --git a/pkg/services/dashboards/database/database_folder_test.go b/pkg/services/dashboards/database/database_folder_test.go index 73960834774..34a8f674add 100644 --- a/pkg/services/dashboards/database/database_folder_test.go +++ b/pkg/services/dashboards/database/database_folder_test.go @@ -11,7 +11,6 @@ import ( "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/models" - "github.com/grafana/grafana/pkg/services/search" "github.com/grafana/grafana/pkg/services/sqlstore" ) @@ -37,7 +36,7 @@ func TestDashboardFolderDataAccess(t *testing.T) { t.Run("and no acls are set", func(t *testing.T) { t.Run("should return all dashboards", func(t *testing.T) { - query := &search.FindPersistedDashboardsQuery{ + query := &models.FindPersistedDashboardsQuery{ SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER}, OrgId: 1, DashboardIds: []int64{folder.Id, dashInRoot.Id}, @@ -61,7 +60,7 @@ func TestDashboardFolderDataAccess(t *testing.T) { require.NoError(t, err) t.Run("should not return folder", func(t *testing.T) { - query := &search.FindPersistedDashboardsQuery{ + query := &models.FindPersistedDashboardsQuery{ SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER}, OrgId: 1, DashboardIds: []int64{folder.Id, dashInRoot.Id}, } @@ -79,7 +78,7 @@ func TestDashboardFolderDataAccess(t *testing.T) { require.NoError(t, err) t.Run("should be able to access folder", func(t *testing.T) { - query := &search.FindPersistedDashboardsQuery{ + query := &models.FindPersistedDashboardsQuery{ SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER}, OrgId: 1, DashboardIds: []int64{folder.Id, dashInRoot.Id}, @@ -94,7 +93,7 @@ func TestDashboardFolderDataAccess(t *testing.T) { t.Run("when the user is an admin", func(t *testing.T) { t.Run("should be able to access folder", func(t *testing.T) { - query := &search.FindPersistedDashboardsQuery{ + query := &models.FindPersistedDashboardsQuery{ SignedInUser: &models.SignedInUser{ UserId: currentUser.Id, OrgId: 1, @@ -122,7 +121,7 @@ func TestDashboardFolderDataAccess(t *testing.T) { require.NoError(t, err) t.Run("should not return folder or child", func(t *testing.T) { - query := &search.FindPersistedDashboardsQuery{ + query := &models.FindPersistedDashboardsQuery{ SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER}, OrgId: 1, DashboardIds: []int64{folder.Id, childDash.Id, dashInRoot.Id}, } err := sqlStore.SearchDashboards(context.Background(), query) @@ -138,7 +137,7 @@ func TestDashboardFolderDataAccess(t *testing.T) { require.NoError(t, err) t.Run("should be able to search for child dashboard but not folder", func(t *testing.T) { - query := &search.FindPersistedDashboardsQuery{SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER}, OrgId: 1, DashboardIds: []int64{folder.Id, childDash.Id, dashInRoot.Id}} + query := &models.FindPersistedDashboardsQuery{SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER}, OrgId: 1, DashboardIds: []int64{folder.Id, childDash.Id, dashInRoot.Id}} err := sqlStore.SearchDashboards(context.Background(), query) require.NoError(t, err) require.Equal(t, len(query.Result), 2) @@ -149,7 +148,7 @@ func TestDashboardFolderDataAccess(t *testing.T) { t.Run("when the user is an admin", func(t *testing.T) { t.Run("should be able to search for child dash and folder", func(t *testing.T) { - query := &search.FindPersistedDashboardsQuery{ + query := &models.FindPersistedDashboardsQuery{ SignedInUser: &models.SignedInUser{ UserId: currentUser.Id, OrgId: 1, @@ -190,7 +189,7 @@ func TestDashboardFolderDataAccess(t *testing.T) { setup2() t.Run("and one folder is expanded, the other collapsed", func(t *testing.T) { t.Run("should return dashboards in root and expanded folder", func(t *testing.T) { - query := &search.FindPersistedDashboardsQuery{ + query := &models.FindPersistedDashboardsQuery{ FolderIds: []int64{ rootFolderId, folder1.Id}, SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER, @@ -218,7 +217,7 @@ func TestDashboardFolderDataAccess(t *testing.T) { moveDashboard(t, dashboardStore, 1, childDash2.Data, folder1.Id) t.Run("should not return folder with acl or its children", func(t *testing.T) { - query := &search.FindPersistedDashboardsQuery{ + query := &models.FindPersistedDashboardsQuery{ SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER}, OrgId: 1, DashboardIds: []int64{folder1.Id, childDash1.Id, childDash2.Id, dashInRoot.Id}, @@ -234,7 +233,7 @@ func TestDashboardFolderDataAccess(t *testing.T) { moveDashboard(t, dashboardStore, 1, childDash1.Data, folder2.Id) t.Run("should return folder without acl and its children", func(t *testing.T) { - query := &search.FindPersistedDashboardsQuery{ + query := &models.FindPersistedDashboardsQuery{ SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER}, OrgId: 1, DashboardIds: []int64{folder2.Id, childDash1.Id, childDash2.Id, dashInRoot.Id}, @@ -258,7 +257,7 @@ func TestDashboardFolderDataAccess(t *testing.T) { moveDashboard(t, dashboardStore, 1, childDash1.Data, folder2.Id) t.Run("should return folder without acl but not the dashboard with acl", func(t *testing.T) { - query := &search.FindPersistedDashboardsQuery{ + query := &models.FindPersistedDashboardsQuery{ SignedInUser: &models.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: models.ROLE_VIEWER}, OrgId: 1, DashboardIds: []int64{folder2.Id, childDash1.Id, childDash2.Id, dashInRoot.Id}, @@ -295,7 +294,7 @@ func TestDashboardFolderDataAccess(t *testing.T) { setup3() t.Run("Admin users", func(t *testing.T) { t.Run("Should have write access to all dashboard folders in their org", func(t *testing.T) { - query := search.FindPersistedDashboardsQuery{ + query := models.FindPersistedDashboardsQuery{ OrgId: 1, SignedInUser: &models.SignedInUser{UserId: adminUser.Id, OrgRole: models.ROLE_ADMIN, OrgId: 1}, Permission: models.PERMISSION_VIEW, @@ -348,7 +347,7 @@ func TestDashboardFolderDataAccess(t *testing.T) { }) t.Run("Editor users", func(t *testing.T) { - query := search.FindPersistedDashboardsQuery{ + query := models.FindPersistedDashboardsQuery{ OrgId: 1, SignedInUser: &models.SignedInUser{UserId: editorUser.Id, OrgRole: models.ROLE_EDITOR, OrgId: 1}, Permission: models.PERMISSION_EDIT, @@ -414,7 +413,7 @@ func TestDashboardFolderDataAccess(t *testing.T) { }) t.Run("Viewer users", func(t *testing.T) { - query := search.FindPersistedDashboardsQuery{ + query := models.FindPersistedDashboardsQuery{ OrgId: 1, SignedInUser: &models.SignedInUser{UserId: viewerUser.Id, OrgRole: models.ROLE_VIEWER, OrgId: 1}, Permission: models.PERMISSION_EDIT, diff --git a/pkg/services/search/service.go b/pkg/services/search/service.go index 4a8b9f2b956..d8b3eb2e95a 100644 --- a/pkg/services/search/service.go +++ b/pkg/services/search/service.go @@ -4,20 +4,22 @@ import ( "context" "sort" + "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/models" ) -func ProvideService(cfg *setting.Cfg, bus bus.Bus) *SearchService { +func ProvideService(cfg *setting.Cfg, bus bus.Bus, sqlstore *sqlstore.SQLStore) *SearchService { s := &SearchService{ Cfg: cfg, Bus: bus, - sortOptions: map[string]SortOption{ + sortOptions: map[string]models.SortOption{ SortAlphaAsc.Name: SortAlphaAsc, SortAlphaDesc.Name: SortAlphaDesc, }, + sqlstore: sqlstore, } s.Bus.AddHandler(s.SearchHandler) return s @@ -37,41 +39,23 @@ type Query struct { Permission models.PermissionType Sort string - Result HitList -} - -type FindPersistedDashboardsQuery struct { - Title string - OrgId int64 - SignedInUser *models.SignedInUser - IsStarred bool - DashboardIds []int64 - Type string - FolderIds []int64 - Tags []string - Limit int64 - Page int64 - Permission models.PermissionType - Sort SortOption - - Filters []interface{} - - Result HitList + Result models.HitList } type Service interface { SearchHandler(context.Context, *Query) error - SortOptions() []SortOption + SortOptions() []models.SortOption } type SearchService struct { Bus bus.Bus Cfg *setting.Cfg - sortOptions map[string]SortOption + sortOptions map[string]models.SortOption + sqlstore sqlstore.Store } func (s *SearchService) SearchHandler(ctx context.Context, query *Query) error { - dashboardQuery := FindPersistedDashboardsQuery{ + dashboardQuery := models.FindPersistedDashboardsQuery{ Title: query.Title, SignedInUser: query.SignedInUser, IsStarred: query.IsStarred, @@ -88,7 +72,7 @@ func (s *SearchService) SearchHandler(ctx context.Context, query *Query) error { dashboardQuery.Sort = sortOpt } - if err := bus.Dispatch(ctx, &dashboardQuery); err != nil { + if err := s.sqlstore.SearchDashboards(ctx, &dashboardQuery); err != nil { return err } @@ -97,7 +81,7 @@ func (s *SearchService) SearchHandler(ctx context.Context, query *Query) error { hits = sortedHits(hits) } - if err := setStarredDashboards(ctx, query.SignedInUser.UserId, hits); err != nil { + if err := s.setStarredDashboards(ctx, query.SignedInUser.UserId, hits); err != nil { return err } @@ -106,8 +90,8 @@ func (s *SearchService) SearchHandler(ctx context.Context, query *Query) error { return nil } -func sortedHits(unsorted HitList) HitList { - hits := make(HitList, 0) +func sortedHits(unsorted models.HitList) models.HitList { + hits := make(models.HitList, 0) hits = append(hits, unsorted...) sort.Sort(hits) @@ -119,17 +103,18 @@ func sortedHits(unsorted HitList) HitList { return hits } -func setStarredDashboards(ctx context.Context, userID int64, hits []*Hit) error { +func (s *SearchService) setStarredDashboards(ctx context.Context, userID int64, hits []*models.Hit) error { query := models.GetUserStarsQuery{ UserId: userID, } - if err := bus.Dispatch(ctx, &query); err != nil { + err := s.sqlstore.GetUserStars(ctx, &query) + if err != nil { return err } - + iuserstars := query.Result for _, dashboard := range hits { - if _, ok := query.Result[dashboard.ID]; ok { + if _, ok := iuserstars[dashboard.ID]; ok { dashboard.IsStarred = true } } diff --git a/pkg/services/search/service_test.go b/pkg/services/search/service_test.go index 0f00565e1b1..9a86f3dbf3d 100644 --- a/pkg/services/search/service_test.go +++ b/pkg/services/search/service_test.go @@ -4,35 +4,26 @@ import ( "context" "testing" - "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/sqlstore/mockstore" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestSearch_SortedResults(t *testing.T) { - bus.AddHandler("test", func(_ context.Context, query *FindPersistedDashboardsQuery) error { - query.Result = HitList{ - &Hit{ID: 16, Title: "CCAA", Type: "dash-db", Tags: []string{"BB", "AA"}}, - &Hit{ID: 10, Title: "AABB", Type: "dash-db", Tags: []string{"CC", "AA"}}, - &Hit{ID: 15, Title: "BBAA", Type: "dash-db", Tags: []string{"EE", "AA", "BB"}}, - &Hit{ID: 25, Title: "bbAAa", Type: "dash-db", Tags: []string{"EE", "AA", "BB"}}, - &Hit{ID: 17, Title: "FOLDER", Type: "dash-folder"}, - } - return nil - }) - - bus.AddHandler("test", func(_ context.Context, query *models.GetUserStarsQuery) error { - query.Result = map[int64]bool{10: true, 12: true} - return nil - }) - - bus.AddHandler("test", func(_ context.Context, query *models.GetSignedInUserQuery) error { - query.Result = &models.SignedInUser{IsGrafanaAdmin: true} - return nil - }) - - svc := &SearchService{} + ms := mockstore.NewSQLStoreMock() + ms.ExpectedPersistedDashboards = models.HitList{ + &models.Hit{ID: 16, Title: "CCAA", Type: "dash-db", Tags: []string{"BB", "AA"}}, + &models.Hit{ID: 10, Title: "AABB", Type: "dash-db", Tags: []string{"CC", "AA"}}, + &models.Hit{ID: 15, Title: "BBAA", Type: "dash-db", Tags: []string{"EE", "AA", "BB"}}, + &models.Hit{ID: 25, Title: "bbAAa", Type: "dash-db", Tags: []string{"EE", "AA", "BB"}}, + &models.Hit{ID: 17, Title: "FOLDER", Type: "dash-folder"}, + } + ms.ExpectedSignedInUser = &models.SignedInUser{IsGrafanaAdmin: true} + ms.ExpectedUserStars = map[int64]bool{10: true, 12: true} + svc := &SearchService{ + sqlstore: ms, + } query := &Query{ Limit: 2000, diff --git a/pkg/services/search/sorting.go b/pkg/services/search/sorting.go index 3df9fc7894e..25658d0b2f9 100644 --- a/pkg/services/search/sorting.go +++ b/pkg/services/search/sorting.go @@ -3,51 +3,39 @@ package search import ( "sort" + "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/sqlstore/searchstore" ) var ( - SortAlphaAsc = SortOption{ + SortAlphaAsc = models.SortOption{ Name: "alpha-asc", DisplayName: "Alphabetically (A–Z)", Description: "Sort results in an alphabetically ascending order", Index: 0, - Filter: []SortOptionFilter{ + Filter: []models.SortOptionFilter{ searchstore.TitleSorter{}, }, } - SortAlphaDesc = SortOption{ + SortAlphaDesc = models.SortOption{ Name: "alpha-desc", DisplayName: "Alphabetically (Z–A)", Description: "Sort results in an alphabetically descending order", Index: 0, - Filter: []SortOptionFilter{ + Filter: []models.SortOptionFilter{ searchstore.TitleSorter{Descending: true}, }, } ) -type SortOption struct { - Name string - DisplayName string - Description string - Index int - MetaName string - Filter []SortOptionFilter -} - -type SortOptionFilter interface { - searchstore.FilterOrderBy -} - // RegisterSortOption allows for hooking in more search options from // other services. -func (s *SearchService) RegisterSortOption(option SortOption) { +func (s *SearchService) RegisterSortOption(option models.SortOption) { s.sortOptions[option.Name] = option } -func (s *SearchService) SortOptions() []SortOption { - opts := make([]SortOption, 0, len(s.sortOptions)) +func (s *SearchService) SortOptions() []models.SortOption { + opts := make([]models.SortOption, 0, len(s.sortOptions)) for _, o := range s.sortOptions { opts = append(opts, o) } diff --git a/pkg/services/sqlstore/dashboard.go b/pkg/services/sqlstore/dashboard.go index 88f56f346cc..a1f7fe210bb 100644 --- a/pkg/services/sqlstore/dashboard.go +++ b/pkg/services/sqlstore/dashboard.go @@ -13,7 +13,6 @@ import ( ac "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/featuremgmt" - "github.com/grafana/grafana/pkg/services/search" "github.com/grafana/grafana/pkg/services/sqlstore/permissions" "github.com/grafana/grafana/pkg/services/sqlstore/searchstore" "github.com/grafana/grafana/pkg/util" @@ -82,7 +81,7 @@ type DashboardSearchProjection struct { SortMeta int64 } -func (ss *SQLStore) FindDashboards(ctx context.Context, query *search.FindPersistedDashboardsQuery) ([]DashboardSearchProjection, error) { +func (ss *SQLStore) FindDashboards(ctx context.Context, query *models.FindPersistedDashboardsQuery) ([]DashboardSearchProjection, error) { filters := []interface{}{ permissions.DashboardPermissionFilter{ OrgRole: query.SignedInUser.OrgRole, @@ -162,7 +161,7 @@ func (ss *SQLStore) FindDashboards(ctx context.Context, query *search.FindPersis return res, nil } -func (ss *SQLStore) SearchDashboards(ctx context.Context, query *search.FindPersistedDashboardsQuery) error { +func (ss *SQLStore) SearchDashboards(ctx context.Context, query *models.FindPersistedDashboardsQuery) error { res, err := ss.FindDashboards(ctx, query) if err != nil { return err @@ -173,25 +172,25 @@ func (ss *SQLStore) SearchDashboards(ctx context.Context, query *search.FindPers return nil } -func getHitType(item DashboardSearchProjection) search.HitType { - var hitType search.HitType +func getHitType(item DashboardSearchProjection) models.HitType { + var hitType models.HitType if item.IsFolder { - hitType = search.DashHitFolder + hitType = models.DashHitFolder } else { - hitType = search.DashHitDB + hitType = models.DashHitDB } return hitType } -func makeQueryResult(query *search.FindPersistedDashboardsQuery, res []DashboardSearchProjection) { - query.Result = make([]*search.Hit, 0) - hits := make(map[int64]*search.Hit) +func makeQueryResult(query *models.FindPersistedDashboardsQuery, res []DashboardSearchProjection) { + query.Result = make([]*models.Hit, 0) + hits := make(map[int64]*models.Hit) for _, item := range res { hit, exists := hits[item.ID] if !exists { - hit = &search.Hit{ + hit = &models.Hit{ ID: item.ID, UID: item.UID, Title: item.Title, diff --git a/pkg/services/sqlstore/mockstore/mockstore.go b/pkg/services/sqlstore/mockstore/mockstore.go index baff080ba55..db6b4278211 100644 --- a/pkg/services/sqlstore/mockstore/mockstore.go +++ b/pkg/services/sqlstore/mockstore/mockstore.go @@ -4,7 +4,6 @@ import ( "context" "github.com/grafana/grafana/pkg/models" - "github.com/grafana/grafana/pkg/services/search" "github.com/grafana/grafana/pkg/services/sqlstore" ) @@ -38,8 +37,10 @@ type SQLStoreMock struct { ExpectedDataSources []*models.DataSource ExpectedDataSourcesAccessStats []*models.DataSourceAccessStats ExpectedNotifierUsageStats []*models.NotifierUsageStats - - ExpectedError error + ExpectedPersistedDashboards models.HitList + ExpectedSignedInUser *models.SignedInUser + ExpectedUserStars map[int64]bool + ExpectedError error } func NewSQLStoreMock() *SQLStoreMock { @@ -179,10 +180,12 @@ func (m *SQLStoreMock) GetUserOrgList(ctx context.Context, query *models.GetUser } func (m *SQLStoreMock) GetSignedInUserWithCacheCtx(ctx context.Context, query *models.GetSignedInUserQuery) error { + query.Result = m.ExpectedSignedInUser return m.ExpectedError } func (m *SQLStoreMock) GetSignedInUser(ctx context.Context, query *models.GetSignedInUserQuery) error { + query.Result = m.ExpectedSignedInUser return m.ExpectedError } @@ -322,6 +325,7 @@ func (m *SQLStoreMock) UnstarDashboard(ctx context.Context, cmd *models.UnstarDa } func (m *SQLStoreMock) GetUserStars(ctx context.Context, query *models.GetUserStarsQuery) error { + query.Result = m.ExpectedUserStars return m.ExpectedError } @@ -469,7 +473,8 @@ func (m *SQLStoreMock) GetDashboard(ctx context.Context, query *models.GetDashbo return m.ExpectedError } -func (m SQLStoreMock) SearchDashboards(ctx context.Context, query *search.FindPersistedDashboardsQuery) error { +func (m SQLStoreMock) SearchDashboards(ctx context.Context, query *models.FindPersistedDashboardsQuery) error { + query.Result = m.ExpectedPersistedDashboards return m.ExpectedError } diff --git a/pkg/services/sqlstore/store.go b/pkg/services/sqlstore/store.go index cdd6b50e58a..2256495cf38 100644 --- a/pkg/services/sqlstore/store.go +++ b/pkg/services/sqlstore/store.go @@ -4,7 +4,6 @@ import ( "context" "github.com/grafana/grafana/pkg/models" - "github.com/grafana/grafana/pkg/services/search" ) type Store interface { @@ -105,7 +104,7 @@ type Store interface { RemoveOrgUser(ctx context.Context, cmd *models.RemoveOrgUserCommand) error GetDashboard(ctx context.Context, query *models.GetDashboardQuery) error GetDashboardTags(ctx context.Context, query *models.GetDashboardTagsQuery) error - SearchDashboards(ctx context.Context, query *search.FindPersistedDashboardsQuery) error + SearchDashboards(ctx context.Context, query *models.FindPersistedDashboardsQuery) error DeleteDashboard(ctx context.Context, cmd *models.DeleteDashboardCommand) error GetDashboards(ctx context.Context, query *models.GetDashboardsQuery) error GetDashboardUIDById(ctx context.Context, query *models.GetDashboardRefByIdQuery) error diff --git a/pkg/tests/api/dashboards/api_dashboards_test.go b/pkg/tests/api/dashboards/api_dashboards_test.go index 2e41d0d974f..9292002ee36 100644 --- a/pkg/tests/api/dashboards/api_dashboards_test.go +++ b/pkg/tests/api/dashboards/api_dashboards_test.go @@ -16,7 +16,6 @@ import ( "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/dashboardimport" "github.com/grafana/grafana/pkg/services/plugindashboards" - "github.com/grafana/grafana/pkg/services/search" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/tests/testinfra" "github.com/stretchr/testify/assert" @@ -147,7 +146,7 @@ providers: }) b, err := ioutil.ReadAll(resp.Body) require.NoError(t, err) - dashboardList := &search.HitList{} + dashboardList := &models.HitList{} err = json.Unmarshal(b, dashboardList) require.NoError(t, err) assert.Equal(t, 1, dashboardList.Len())