From 058e3ffc21fac5c319df9dce17f88e8fc361e30f Mon Sep 17 00:00:00 2001 From: Serge Zaitsev Date: Fri, 4 Feb 2022 13:41:15 +0100 Subject: [PATCH] Chore: Remove bus from Alerting API (#44894) * assign handlers to httpserver * turn sqlstore mock in to a pointer * add search service interface * fix tests for alerting and other apis * once again, make linter happy --- pkg/api/admin_users_test.go | 8 +- pkg/api/alerting.go | 76 ++--- pkg/api/alerting_test.go | 154 +++++----- pkg/api/api.go | 28 +- pkg/api/http_server.go | 2 +- pkg/api/team_test.go | 2 +- pkg/api/user_token_test.go | 6 +- pkg/services/search/service.go | 5 + pkg/services/sqlstore/mockstore/mockstore.go | 283 ++++++++++--------- 9 files changed, 274 insertions(+), 290 deletions(-) diff --git a/pkg/api/admin_users_test.go b/pkg/api/admin_users_test.go index e79320ee2d0..7e3fca4b436 100644 --- a/pkg/api/admin_users_test.go +++ b/pkg/api/admin_users_test.go @@ -35,7 +35,7 @@ func TestAdminAPIEndpoint(t *testing.T) { updateCmd := dtos.AdminUpdateUserPermissionsForm{ IsGrafanaAdmin: false, } - mock := mockstore.SQLStoreMock{ + mock := &mockstore.SQLStoreMock{ ExpectedError: models.ErrLastGrafanaAdmin, } putAdminScenario(t, "When calling PUT on", "/api/admin/users/1/permissions", @@ -60,7 +60,7 @@ func TestAdminAPIEndpoint(t *testing.T) { }) t.Run("When a server admin attempts to logout a non-existing user from all devices", func(t *testing.T) { - mock := mockstore.SQLStoreMock{ + mock := &mockstore.SQLStoreMock{ ExpectedError: models.ErrUserNotFound, } adminLogoutUserScenario(t, "Should return not found when calling POST on", "/api/admin/users/200/logout", @@ -72,7 +72,7 @@ func TestAdminAPIEndpoint(t *testing.T) { t.Run("When a server admin attempts to revoke an auth token for a non-existing user", func(t *testing.T) { cmd := models.RevokeAuthTokenCmd{AuthTokenId: 2} - mock := mockstore.SQLStoreMock{ + mock := &mockstore.SQLStoreMock{ ExpectedError: models.ErrUserNotFound, } adminRevokeUserAuthTokenScenario(t, "Should return not found when calling POST on", @@ -83,7 +83,7 @@ func TestAdminAPIEndpoint(t *testing.T) { }) t.Run("When a server admin gets auth tokens for a non-existing user", func(t *testing.T) { - mock := mockstore.SQLStoreMock{ + mock := &mockstore.SQLStoreMock{ ExpectedError: models.ErrUserNotFound, } adminGetUserAuthTokensScenario(t, "Should return not found when calling GET on", diff --git a/pkg/api/alerting.go b/pkg/api/alerting.go index 9162f30c72d..23efe48f686 100644 --- a/pkg/api/alerting.go +++ b/pkg/api/alerting.go @@ -20,7 +20,7 @@ import ( "github.com/grafana/grafana/pkg/web" ) -func ValidateOrgAlert(c *models.ReqContext) { +func (hs *HTTPServer) ValidateOrgAlert(c *models.ReqContext) { id, err := strconv.ParseInt(web.Params(c.Req)[":alertId"], 10, 64) if err != nil { c.JsonApiErr(http.StatusBadRequest, "alertId is invalid", nil) @@ -28,7 +28,7 @@ func ValidateOrgAlert(c *models.ReqContext) { } query := models.GetAlertByIdQuery{Id: id} - if err := bus.Dispatch(c.Req.Context(), &query); err != nil { + if err := hs.SQLStore.GetAlertById(c.Req.Context(), &query); err != nil { c.JsonApiErr(404, "Alert not found", nil) return } @@ -39,7 +39,7 @@ func ValidateOrgAlert(c *models.ReqContext) { } } -func GetAlertStatesForDashboard(c *models.ReqContext) response.Response { +func (hs *HTTPServer) GetAlertStatesForDashboard(c *models.ReqContext) response.Response { dashboardID := c.QueryInt64("dashboardId") if dashboardID == 0 { @@ -51,7 +51,7 @@ func GetAlertStatesForDashboard(c *models.ReqContext) response.Response { DashboardId: c.QueryInt64("dashboardId"), } - if err := bus.Dispatch(c.Req.Context(), &query); err != nil { + if err := hs.SQLStore.GetAlertStatesForDashboard(c.Req.Context(), &query); err != nil { return response.Error(500, "Failed to fetch alert states", err) } @@ -59,7 +59,7 @@ func GetAlertStatesForDashboard(c *models.ReqContext) response.Response { } // GET /api/alerts -func GetAlerts(c *models.ReqContext) response.Response { +func (hs *HTTPServer) GetAlerts(c *models.ReqContext) response.Response { dashboardQuery := c.Query("dashboardQuery") dashboardTags := c.QueryStrings("dashboardTag") stringDashboardIDs := c.QueryStrings("dashboardId") @@ -94,7 +94,7 @@ func GetAlerts(c *models.ReqContext) response.Response { Permission: models.PERMISSION_VIEW, } - err := bus.Dispatch(c.Req.Context(), &searchQuery) + err := hs.SearchService.SearchHandler(c.Req.Context(), &searchQuery) if err != nil { return response.Error(500, "List alerts failed", err) } @@ -125,7 +125,7 @@ func GetAlerts(c *models.ReqContext) response.Response { query.State = states } - if err := bus.Dispatch(c.Req.Context(), &query); err != nil { + if err := hs.SQLStore.HandleAlertsQuery(c.Req.Context(), &query); err != nil { return response.Error(500, "List alerts failed", err) } @@ -181,21 +181,21 @@ func (hs *HTTPServer) AlertTest(c *models.ReqContext) response.Response { } // GET /api/alerts/:id -func GetAlert(c *models.ReqContext) response.Response { +func (hs *HTTPServer) GetAlert(c *models.ReqContext) response.Response { id, err := strconv.ParseInt(web.Params(c.Req)[":alertId"], 10, 64) if err != nil { return response.Error(http.StatusBadRequest, "alertId is invalid", err) } query := models.GetAlertByIdQuery{Id: id} - if err := bus.Dispatch(c.Req.Context(), &query); err != nil { + if err := hs.SQLStore.GetAlertById(c.Req.Context(), &query); err != nil { return response.Error(500, "List alerts failed", err) } return response.JSON(200, &query.Result) } -func GetAlertNotifiers(ngalertEnabled bool) func(*models.ReqContext) response.Response { +func (hs *HTTPServer) GetAlertNotifiers(ngalertEnabled bool) func(*models.ReqContext) response.Response { return func(_ *models.ReqContext) response.Response { if ngalertEnabled { return response.JSON(200, notifier.GetAvailableNotifiers()) @@ -206,8 +206,8 @@ func GetAlertNotifiers(ngalertEnabled bool) func(*models.ReqContext) response.Re } } -func GetAlertNotificationLookup(c *models.ReqContext) response.Response { - alertNotifications, err := getAlertNotificationsInternal(c) +func (hs *HTTPServer) GetAlertNotificationLookup(c *models.ReqContext) response.Response { + alertNotifications, err := hs.getAlertNotificationsInternal(c) if err != nil { return response.Error(500, "Failed to get alert notifications", err) } @@ -221,8 +221,8 @@ func GetAlertNotificationLookup(c *models.ReqContext) response.Response { return response.JSON(200, result) } -func GetAlertNotifications(c *models.ReqContext) response.Response { - alertNotifications, err := getAlertNotificationsInternal(c) +func (hs *HTTPServer) GetAlertNotifications(c *models.ReqContext) response.Response { + alertNotifications, err := hs.getAlertNotificationsInternal(c) if err != nil { return response.Error(500, "Failed to get alert notifications", err) } @@ -236,17 +236,17 @@ func GetAlertNotifications(c *models.ReqContext) response.Response { return response.JSON(200, result) } -func getAlertNotificationsInternal(c *models.ReqContext) ([]*models.AlertNotification, error) { +func (hs *HTTPServer) getAlertNotificationsInternal(c *models.ReqContext) ([]*models.AlertNotification, error) { query := &models.GetAllAlertNotificationsQuery{OrgId: c.OrgId} - if err := bus.Dispatch(c.Req.Context(), query); err != nil { + if err := hs.SQLStore.GetAllAlertNotifications(c.Req.Context(), query); err != nil { return nil, err } return query.Result, nil } -func GetAlertNotificationByID(c *models.ReqContext) response.Response { +func (hs *HTTPServer) GetAlertNotificationByID(c *models.ReqContext) response.Response { notificationId, err := strconv.ParseInt(web.Params(c.Req)[":notificationId"], 10, 64) if err != nil { return response.Error(http.StatusBadRequest, "notificationId is invalid", err) @@ -260,7 +260,7 @@ func GetAlertNotificationByID(c *models.ReqContext) response.Response { return response.Error(404, "Alert notification not found", nil) } - if err := bus.Dispatch(c.Req.Context(), query); err != nil { + if err := hs.SQLStore.GetAlertNotifications(c.Req.Context(), query); err != nil { return response.Error(500, "Failed to get alert notifications", err) } @@ -271,7 +271,7 @@ func GetAlertNotificationByID(c *models.ReqContext) response.Response { return response.JSON(200, dtos.NewAlertNotification(query.Result)) } -func GetAlertNotificationByUID(c *models.ReqContext) response.Response { +func (hs *HTTPServer) GetAlertNotificationByUID(c *models.ReqContext) response.Response { query := &models.GetAlertNotificationsWithUidQuery{ OrgId: c.OrgId, Uid: web.Params(c.Req)[":uid"], @@ -281,7 +281,7 @@ func GetAlertNotificationByUID(c *models.ReqContext) response.Response { return response.Error(404, "Alert notification not found", nil) } - if err := bus.Dispatch(c.Req.Context(), query); err != nil { + if err := hs.SQLStore.GetAlertNotificationsWithUid(c.Req.Context(), query); err != nil { return response.Error(500, "Failed to get alert notifications", err) } @@ -292,14 +292,14 @@ func GetAlertNotificationByUID(c *models.ReqContext) response.Response { return response.JSON(200, dtos.NewAlertNotification(query.Result)) } -func CreateAlertNotification(c *models.ReqContext) response.Response { +func (hs *HTTPServer) CreateAlertNotification(c *models.ReqContext) response.Response { cmd := models.CreateAlertNotificationCommand{} if err := web.Bind(c.Req, &cmd); err != nil { return response.Error(http.StatusBadRequest, "bad request data", err) } cmd.OrgId = c.OrgId - if err := bus.Dispatch(c.Req.Context(), &cmd); err != nil { + if err := hs.SQLStore.CreateAlertNotificationCommand(c.Req.Context(), &cmd); err != nil { if errors.Is(err, models.ErrAlertNotificationWithSameNameExists) || errors.Is(err, models.ErrAlertNotificationWithSameUIDExists) { return response.Error(409, "Failed to create alert notification", err) } @@ -325,7 +325,7 @@ func (hs *HTTPServer) UpdateAlertNotification(c *models.ReqContext) response.Res return response.Error(500, "Failed to update alert notification", err) } - if err := bus.Dispatch(c.Req.Context(), &cmd); err != nil { + if err := hs.SQLStore.UpdateAlertNotification(c.Req.Context(), &cmd); err != nil { if errors.Is(err, models.ErrAlertNotificationNotFound) { return response.Error(404, err.Error(), err) } @@ -341,7 +341,7 @@ func (hs *HTTPServer) UpdateAlertNotification(c *models.ReqContext) response.Res Id: cmd.Id, } - if err := bus.Dispatch(c.Req.Context(), &query); err != nil { + if err := hs.SQLStore.GetAlertNotifications(c.Req.Context(), &query); err != nil { return response.Error(500, "Failed to get alert notification", err) } @@ -361,7 +361,7 @@ func (hs *HTTPServer) UpdateAlertNotificationByUID(c *models.ReqContext) respons return response.Error(500, "Failed to update alert notification", err) } - if err := bus.Dispatch(c.Req.Context(), &cmd); err != nil { + if err := hs.SQLStore.UpdateAlertNotificationWithUid(c.Req.Context(), &cmd); err != nil { if errors.Is(err, models.ErrAlertNotificationNotFound) { return response.Error(404, err.Error(), nil) } @@ -373,7 +373,7 @@ func (hs *HTTPServer) UpdateAlertNotificationByUID(c *models.ReqContext) respons Uid: cmd.Uid, } - if err := bus.Dispatch(c.Req.Context(), &query); err != nil { + if err := hs.SQLStore.GetAlertNotificationsWithUid(c.Req.Context(), &query); err != nil { return response.Error(500, "Failed to get alert notification", err) } @@ -390,7 +390,7 @@ func (hs *HTTPServer) fillWithSecureSettingsData(ctx context.Context, cmd *model Id: cmd.Id, } - if err := bus.Dispatch(ctx, query); err != nil { + if err := hs.SQLStore.GetAlertNotifications(ctx, query); err != nil { return err } @@ -418,7 +418,7 @@ func (hs *HTTPServer) fillWithSecureSettingsDataByUID(ctx context.Context, cmd * Uid: cmd.Uid, } - if err := bus.Dispatch(ctx, query); err != nil { + if err := hs.SQLStore.GetAlertNotificationsWithUid(ctx, query); err != nil { return err } @@ -436,7 +436,7 @@ func (hs *HTTPServer) fillWithSecureSettingsDataByUID(ctx context.Context, cmd * return nil } -func DeleteAlertNotification(c *models.ReqContext) response.Response { +func (hs *HTTPServer) DeleteAlertNotification(c *models.ReqContext) response.Response { notificationId, err := strconv.ParseInt(web.Params(c.Req)[":notificationId"], 10, 64) if err != nil { return response.Error(http.StatusBadRequest, "notificationId is invalid", err) @@ -447,7 +447,7 @@ func DeleteAlertNotification(c *models.ReqContext) response.Response { Id: notificationId, } - if err := bus.Dispatch(c.Req.Context(), &cmd); err != nil { + if err := hs.SQLStore.DeleteAlertNotification(c.Req.Context(), &cmd); err != nil { if errors.Is(err, models.ErrAlertNotificationNotFound) { return response.Error(404, err.Error(), nil) } @@ -457,13 +457,13 @@ func DeleteAlertNotification(c *models.ReqContext) response.Response { return response.Success("Notification deleted") } -func DeleteAlertNotificationByUID(c *models.ReqContext) response.Response { +func (hs *HTTPServer) DeleteAlertNotificationByUID(c *models.ReqContext) response.Response { cmd := models.DeleteAlertNotificationWithUidCommand{ OrgId: c.OrgId, Uid: web.Params(c.Req)[":uid"], } - if err := bus.Dispatch(c.Req.Context(), &cmd); err != nil { + if err := hs.SQLStore.DeleteAlertNotificationWithUid(c.Req.Context(), &cmd); err != nil { if errors.Is(err, models.ErrAlertNotificationNotFound) { return response.Error(404, err.Error(), nil) } @@ -477,7 +477,7 @@ func DeleteAlertNotificationByUID(c *models.ReqContext) response.Response { } // POST /api/alert-notifications/test -func NotificationTest(c *models.ReqContext) response.Response { +func (hs *HTTPServer) NotificationTest(c *models.ReqContext) response.Response { dto := dtos.NotificationTestCommand{} if err := web.Bind(c.Req, &dto); err != nil { return response.Error(http.StatusBadRequest, "bad request data", err) @@ -507,7 +507,7 @@ func NotificationTest(c *models.ReqContext) response.Response { } // POST /api/alerts/:alertId/pause -func PauseAlert(c *models.ReqContext) response.Response { +func (hs *HTTPServer) PauseAlert(c *models.ReqContext) response.Response { dto := dtos.PauseAlertCommand{} if err := web.Bind(c.Req, &dto); err != nil { return response.Error(http.StatusBadRequest, "bad request data", err) @@ -520,7 +520,7 @@ func PauseAlert(c *models.ReqContext) response.Response { result["alertId"] = alertID query := models.GetAlertByIdQuery{Id: alertID} - if err := bus.Dispatch(c.Req.Context(), &query); err != nil { + if err := hs.SQLStore.GetAlertById(c.Req.Context(), &query); err != nil { return response.Error(500, "Get Alert failed", err) } @@ -550,7 +550,7 @@ func PauseAlert(c *models.ReqContext) response.Response { Paused: dto.Paused, } - if err := bus.Dispatch(c.Req.Context(), &cmd); err != nil { + if err := hs.SQLStore.PauseAlert(c.Req.Context(), &cmd); err != nil { return response.Error(500, "", err) } @@ -567,7 +567,7 @@ func PauseAlert(c *models.ReqContext) response.Response { } // POST /api/admin/pause-all-alerts -func PauseAllAlerts(c *models.ReqContext) response.Response { +func (hs *HTTPServer) PauseAllAlerts(c *models.ReqContext) response.Response { dto := dtos.PauseAllAlertsCommand{} if err := web.Bind(c.Req, &dto); err != nil { return response.Error(http.StatusBadRequest, "bad request data", err) @@ -576,7 +576,7 @@ func PauseAllAlerts(c *models.ReqContext) response.Response { Paused: dto.Paused, } - if err := bus.Dispatch(c.Req.Context(), &updateCmd); err != nil { + if err := hs.SQLStore.PauseAllAlerts(c.Req.Context(), &updateCmd); err != nil { return response.Error(500, "Failed to pause alerts", err) } diff --git a/pkg/api/alerting_test.go b/pkg/api/alerting_test.go index 1a7caf1e65d..b484c8337ca 100644 --- a/pkg/api/alerting_test.go +++ b/pkg/api/alerting_test.go @@ -17,44 +17,55 @@ import ( "github.com/stretchr/testify/require" ) +var ( + viewerRole = models.ROLE_VIEWER + editorRole = models.ROLE_EDITOR +) + type setUpConf struct { aclMockResp []*models.DashboardAclInfoDTO } -func TestAlertingAPIEndpoint(t *testing.T) { +type mockSearchService struct{ ExpectedResult search.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 setUp(confs ...setUpConf) *HTTPServer { singleAlert := &models.Alert{Id: 1, DashboardId: 1, Name: "singlealert"} - viewerRole := models.ROLE_VIEWER - editorRole := models.ROLE_EDITOR + store := mockstore.NewSQLStoreMock() + hs := &HTTPServer{SQLStore: store, SearchService: &mockSearchService{}} + store.ExpectedAlert = singleAlert - setUp := func(confs ...setUpConf) { - bus.AddHandler("test", func(ctx context.Context, query *models.GetAlertByIdQuery) error { - query.Result = singleAlert - return nil - }) - - aclMockResp := []*models.DashboardAclInfoDTO{} - for _, c := range confs { - if c.aclMockResp != nil { - aclMockResp = c.aclMockResp - } + aclMockResp := []*models.DashboardAclInfoDTO{} + for _, c := range confs { + if c.aclMockResp != nil { + aclMockResp = c.aclMockResp } - bus.AddHandler("test", func(ctx context.Context, query *models.GetDashboardAclInfoListQuery) error { - query.Result = aclMockResp - return nil - }) - - bus.AddHandler("test", func(ctx context.Context, query *models.GetTeamsByUserQuery) error { - query.Result = []*models.TeamDTO{} - return nil - }) } + bus.AddHandler("test", func(ctx context.Context, query *models.GetDashboardAclInfoListQuery) error { + query.Result = aclMockResp + return nil + }) + bus.AddHandler("test", func(ctx context.Context, query *models.GetTeamsByUserQuery) error { + query.Result = []*models.TeamDTO{} + return nil + }) + return hs +} + +func TestAlertingAPIEndpoint(t *testing.T) { t.Run("When user is editor and not in the ACL", func(t *testing.T) { + hs := setUp() cmd := dtos.PauseAlertCommand{ AlertId: 1, Paused: true, } - postAlertScenario(t, "When calling POST on", "/api/alerts/1/pause", "/api/alerts/:alertId/pause", + postAlertScenario(t, hs, "When calling POST on", "/api/alerts/1/pause", "/api/alerts/:alertId/pause", models.ROLE_EDITOR, cmd, func(sc *scenarioContext) { setUp() @@ -64,11 +75,12 @@ func TestAlertingAPIEndpoint(t *testing.T) { }) t.Run("When user is editor and dashboard has default ACL", func(t *testing.T) { + hs := setUp() cmd := dtos.PauseAlertCommand{ AlertId: 1, Paused: true, } - postAlertScenario(t, "When calling POST on", "/api/alerts/1/pause", "/api/alerts/:alertId/pause", + postAlertScenario(t, hs, "When calling POST on", "/api/alerts/1/pause", "/api/alerts/:alertId/pause", models.ROLE_EDITOR, cmd, func(sc *scenarioContext) { setUp(setUpConf{ aclMockResp: []*models.DashboardAclInfoDTO{ @@ -82,76 +94,38 @@ func TestAlertingAPIEndpoint(t *testing.T) { }) }) - mock := mockstore.NewSQLStoreMock() - loggedInUserScenarioWithRole(t, "When calling GET on", "GET", "/api/alerts?dashboardId=1", "/api/alerts", - models.ROLE_EDITOR, func(sc *scenarioContext) { - setUp() - - var searchQuery *search.Query - bus.AddHandler("test", func(ctx context.Context, query *search.Query) error { - searchQuery = query - return nil - }) - - var getAlertsQuery *models.GetAlertsQuery - bus.AddHandler("test", func(ctx context.Context, query *models.GetAlertsQuery) error { - getAlertsQuery = query - return nil - }) - - sc.handlerFunc = GetAlerts - sc.fakeReqWithParams("GET", sc.url, map[string]string{}).exec() - - require.Nil(t, searchQuery) - assert.NotNil(t, getAlertsQuery) - }, mock) - - 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) { - setUp() - - var searchQuery *search.Query - bus.AddHandler("test", func(ctx context.Context, query *search.Query) error { - searchQuery = query - query.Result = search.HitList{ + t.Run("When calling GET", func(t *testing.T) { + hs := setUp() + 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}, } - return nil - }) - var getAlertsQuery *models.GetAlertsQuery - bus.AddHandler("test", func(ctx context.Context, query *models.GetAlertsQuery) error { - getAlertsQuery = query - return nil - }) + sc.handlerFunc = hs.GetAlerts + sc.fakeReqWithParams("GET", sc.url, map[string]string{}).exec() - sc.handlerFunc = GetAlerts - sc.fakeReqWithParams("GET", sc.url, map[string]string{}).exec() + getAlertsQuery := hs.SQLStore.(*mockstore.SQLStoreMock).LastGetAlertsQuery - require.NotNil(t, searchQuery) - assert.Equal(t, int64(1), searchQuery.DashboardIds[0]) - assert.Equal(t, int64(2), searchQuery.DashboardIds[1]) - assert.Equal(t, int64(3), searchQuery.FolderIds[0]) - assert.Equal(t, "abc", searchQuery.Tags[0]) - assert.Equal(t, "dbQuery", searchQuery.Title) + require.NotNil(t, getAlertsQuery) + assert.Equal(t, int64(1), getAlertsQuery.DashboardIDs[0]) + assert.Equal(t, int64(2), getAlertsQuery.DashboardIDs[1]) + assert.Equal(t, int64(5), getAlertsQuery.Limit) + assert.Equal(t, "alertQuery", getAlertsQuery.Query) + }, hs.SQLStore) + }) - require.NotNil(t, getAlertsQuery) - assert.Equal(t, int64(1), getAlertsQuery.DashboardIDs[0]) - assert.Equal(t, int64(2), getAlertsQuery.DashboardIDs[1]) - assert.Equal(t, int64(5), getAlertsQuery.Limit) - assert.Equal(t, "alertQuery", getAlertsQuery.Query) - }, mock) - - loggedInUserScenarioWithRole(t, "When calling GET on", "GET", "/api/alert-notifications/1", - "/alert-notifications/:notificationId", models.ROLE_ADMIN, func(sc *scenarioContext) { - setUp() - - sc.handlerFunc = GetAlertNotificationByID - sc.fakeReqWithParams("GET", sc.url, map[string]string{}).exec() - assert.Equal(t, 404, sc.resp.Code) - }, mock) + t.Run("When calling GET on alert-notifications", func(t *testing.T) { + hs := setUp() + loggedInUserScenarioWithRole(t, "When calling GET on", "GET", "/api/alert-notifications/1", + "/alert-notifications/:notificationId", models.ROLE_ADMIN, func(sc *scenarioContext) { + sc.handlerFunc = hs.GetAlertNotificationByID + sc.fakeReqWithParams("GET", sc.url, map[string]string{}).exec() + assert.Equal(t, 404, sc.resp.Code) + }, hs.SQLStore) + }) } func callPauseAlert(sc *scenarioContext) { @@ -162,7 +136,7 @@ func callPauseAlert(sc *scenarioContext) { sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec() } -func postAlertScenario(t *testing.T, desc string, url string, routePattern string, role models.RoleType, +func postAlertScenario(t *testing.T, hs *HTTPServer, desc string, url string, routePattern string, role models.RoleType, cmd dtos.PauseAlertCommand, fn scenarioFunc) { t.Run(fmt.Sprintf("%s %s", desc, url), func(t *testing.T) { defer bus.ClearBusHandlers() @@ -175,7 +149,7 @@ func postAlertScenario(t *testing.T, desc string, url string, routePattern strin sc.context.OrgId = testOrgID sc.context.OrgRole = role - return PauseAlert(c) + return hs.PauseAlert(c) }) sc.m.Post(routePattern, sc.defaultHandler) diff --git a/pkg/api/api.go b/pkg/api/api.go index d25e0a44dfc..41cf0eee227 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -383,31 +383,31 @@ func (hs *HTTPServer) registerRoutes() { apiRoute.Group("/alerts", func(alertsRoute routing.RouteRegister) { alertsRoute.Post("/test", routing.Wrap(hs.AlertTest)) - alertsRoute.Post("/:alertId/pause", reqEditorRole, routing.Wrap(PauseAlert)) - alertsRoute.Get("/:alertId", ValidateOrgAlert, routing.Wrap(GetAlert)) - alertsRoute.Get("/", routing.Wrap(GetAlerts)) - alertsRoute.Get("/states-for-dashboard", routing.Wrap(GetAlertStatesForDashboard)) + alertsRoute.Post("/:alertId/pause", reqEditorRole, routing.Wrap(hs.PauseAlert)) + alertsRoute.Get("/:alertId", hs.ValidateOrgAlert, routing.Wrap(hs.GetAlert)) + alertsRoute.Get("/", routing.Wrap(hs.GetAlerts)) + alertsRoute.Get("/states-for-dashboard", routing.Wrap(hs.GetAlertStatesForDashboard)) }) apiRoute.Get("/alert-notifiers", reqEditorRole, routing.Wrap( - GetAlertNotifiers(hs.Cfg.UnifiedAlerting.IsEnabled())), + hs.GetAlertNotifiers(hs.Cfg.UnifiedAlerting.IsEnabled())), ) apiRoute.Group("/alert-notifications", func(alertNotifications routing.RouteRegister) { - alertNotifications.Get("/", routing.Wrap(GetAlertNotifications)) - alertNotifications.Post("/test", routing.Wrap(NotificationTest)) - alertNotifications.Post("/", routing.Wrap(CreateAlertNotification)) + alertNotifications.Get("/", routing.Wrap(hs.GetAlertNotifications)) + alertNotifications.Post("/test", routing.Wrap(hs.NotificationTest)) + alertNotifications.Post("/", routing.Wrap(hs.CreateAlertNotification)) alertNotifications.Put("/:notificationId", routing.Wrap(hs.UpdateAlertNotification)) - alertNotifications.Get("/:notificationId", routing.Wrap(GetAlertNotificationByID)) - alertNotifications.Delete("/:notificationId", routing.Wrap(DeleteAlertNotification)) - alertNotifications.Get("/uid/:uid", routing.Wrap(GetAlertNotificationByUID)) + alertNotifications.Get("/:notificationId", routing.Wrap(hs.GetAlertNotificationByID)) + alertNotifications.Delete("/:notificationId", routing.Wrap(hs.DeleteAlertNotification)) + alertNotifications.Get("/uid/:uid", routing.Wrap(hs.GetAlertNotificationByUID)) alertNotifications.Put("/uid/:uid", routing.Wrap(hs.UpdateAlertNotificationByUID)) - alertNotifications.Delete("/uid/:uid", routing.Wrap(DeleteAlertNotificationByUID)) + alertNotifications.Delete("/uid/:uid", routing.Wrap(hs.DeleteAlertNotificationByUID)) }, reqEditorRole) // alert notifications without requirement of user to be org editor apiRoute.Group("/alert-notifications", func(orgRoute routing.RouteRegister) { - orgRoute.Get("/lookup", routing.Wrap(GetAlertNotificationLookup)) + orgRoute.Get("/lookup", routing.Wrap(hs.GetAlertNotificationLookup)) }) apiRoute.Get("/annotations", routing.Wrap(GetAnnotations)) @@ -464,7 +464,7 @@ func (hs *HTTPServer) registerRoutes() { adminRoute.Get("/settings/features", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionSettingsRead)), hs.Features.HandleGetSettings) } adminRoute.Get("/stats", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionServerStatsRead)), routing.Wrap(AdminGetStats)) - adminRoute.Post("/pause-all-alerts", reqGrafanaAdmin, routing.Wrap(PauseAllAlerts)) + adminRoute.Post("/pause-all-alerts", reqGrafanaAdmin, routing.Wrap(hs.PauseAllAlerts)) if hs.ThumbService != nil { adminRoute.Post("/crawler/start", reqGrafanaAdmin, routing.Wrap(hs.ThumbService.StartCrawler)) diff --git a/pkg/api/http_server.go b/pkg/api/http_server.go index 73012c9ffa0..b0bf64917b2 100644 --- a/pkg/api/http_server.go +++ b/pkg/api/http_server.go @@ -100,7 +100,7 @@ type HTTPServer struct { pluginDashboardManager plugins.PluginDashboardManager pluginStaticRouteResolver plugins.StaticRouteResolver pluginErrorResolver plugins.ErrorResolver - SearchService *search.SearchService + SearchService search.Service ShortURLService shorturls.Service QueryHistoryService queryhistory.Service Live *live.GrafanaLive diff --git a/pkg/api/team_test.go b/pkg/api/team_test.go index 5f6803edc2e..2f5f997da21 100644 --- a/pkg/api/team_test.go +++ b/pkg/api/team_test.go @@ -35,7 +35,7 @@ func TestTeamAPIEndpoint(t *testing.T) { t.Run("Given two teams", func(t *testing.T) { hs := setupSimpleHTTPServer(nil) hs.SQLStore = sqlstore.InitTestDB(t) - mock := mockstore.SQLStoreMock{} + mock := &mockstore.SQLStoreMock{} loggedInUserScenario(t, "When calling GET on", "/api/teams/search", "/api/teams/search", func(sc *scenarioContext) { _, err := hs.SQLStore.CreateTeam("team1", "", 1) require.NoError(t, err) diff --git a/pkg/api/user_token_test.go b/pkg/api/user_token_test.go index 68c523c4777..37766385f13 100644 --- a/pkg/api/user_token_test.go +++ b/pkg/api/user_token_test.go @@ -29,7 +29,7 @@ func TestUserTokenAPIEndpoint(t *testing.T) { }) t.Run("When current user gets auth tokens for a non-existing user", func(t *testing.T) { - mock := mockstore.SQLStoreMock{ + mock := &mockstore.SQLStoreMock{ ExpectedUser: &models.User{Id: 200}, ExpectedError: models.ErrUserNotFound, } @@ -40,7 +40,7 @@ func TestUserTokenAPIEndpoint(t *testing.T) { }) t.Run("When logging out an existing user from all devices", func(t *testing.T) { - mock := mockstore.SQLStoreMock{ + mock := &mockstore.SQLStoreMock{ ExpectedUser: &models.User{Id: 200}, } logoutUserFromAllDevicesInternalScenario(t, "Should be successful", 1, func(sc *scenarioContext) { @@ -61,7 +61,7 @@ func TestUserTokenAPIEndpoint(t *testing.T) { t.Run("When revoke an auth token for a user", func(t *testing.T) { cmd := models.RevokeAuthTokenCmd{AuthTokenId: 2} token := &models.UserToken{Id: 1} - mock := mockstore.SQLStoreMock{ + mock := &mockstore.SQLStoreMock{ ExpectedUser: &models.User{Id: 200}, } diff --git a/pkg/services/search/service.go b/pkg/services/search/service.go index 77bf654f02c..4a8b9f2b956 100644 --- a/pkg/services/search/service.go +++ b/pkg/services/search/service.go @@ -59,6 +59,11 @@ type FindPersistedDashboardsQuery struct { Result HitList } +type Service interface { + SearchHandler(context.Context, *Query) error + SortOptions() []SortOption +} + type SearchService struct { Bus bus.Bus Cfg *setting.Cfg diff --git a/pkg/services/sqlstore/mockstore/mockstore.go b/pkg/services/sqlstore/mockstore/mockstore.go index 827e94d56e2..74bedabe415 100644 --- a/pkg/services/sqlstore/mockstore/mockstore.go +++ b/pkg/services/sqlstore/mockstore/mockstore.go @@ -9,8 +9,11 @@ import ( ) type SQLStoreMock struct { + LastGetAlertsQuery *models.GetAlertsQuery + ExpectedUser *models.User ExpectedDatasource *models.DataSource + ExpectedAlert *models.Alert ExpectedError error } @@ -18,152 +21,152 @@ func NewSQLStoreMock() *SQLStoreMock { return &SQLStoreMock{} } -func (m SQLStoreMock) DeleteExpiredSnapshots(ctx context.Context, cmd *models.DeleteExpiredSnapshotsCommand) error { +func (m *SQLStoreMock) DeleteExpiredSnapshots(ctx context.Context, cmd *models.DeleteExpiredSnapshotsCommand) error { return m.ExpectedError } -func (m SQLStoreMock) CreateDashboardSnapshot(ctx context.Context, cmd *models.CreateDashboardSnapshotCommand) error { +func (m *SQLStoreMock) CreateDashboardSnapshot(ctx context.Context, cmd *models.CreateDashboardSnapshotCommand) error { return m.ExpectedError } -func (m SQLStoreMock) DeleteDashboardSnapshot(ctx context.Context, cmd *models.DeleteDashboardSnapshotCommand) error { +func (m *SQLStoreMock) DeleteDashboardSnapshot(ctx context.Context, cmd *models.DeleteDashboardSnapshotCommand) error { return m.ExpectedError } -func (m SQLStoreMock) GetDashboardSnapshot(query *models.GetDashboardSnapshotQuery) error { +func (m *SQLStoreMock) GetDashboardSnapshot(query *models.GetDashboardSnapshotQuery) error { return m.ExpectedError } -func (m SQLStoreMock) HasEditPermissionInFolders(ctx context.Context, query *models.HasEditPermissionInFoldersQuery) error { +func (m *SQLStoreMock) HasEditPermissionInFolders(ctx context.Context, query *models.HasEditPermissionInFoldersQuery) error { return m.ExpectedError } -func (m SQLStoreMock) SearchDashboardSnapshots(query *models.GetDashboardSnapshotsQuery) error { +func (m *SQLStoreMock) SearchDashboardSnapshots(query *models.GetDashboardSnapshotsQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetOrgByName(name string) (*models.Org, error) { +func (m *SQLStoreMock) GetOrgByName(name string) (*models.Org, error) { return nil, m.ExpectedError } -func (m SQLStoreMock) CreateOrgWithMember(name string, userID int64) (models.Org, error) { +func (m *SQLStoreMock) CreateOrgWithMember(name string, userID int64) (models.Org, error) { return models.Org{}, nil } -func (m SQLStoreMock) UpdateOrg(ctx context.Context, cmd *models.UpdateOrgCommand) error { +func (m *SQLStoreMock) UpdateOrg(ctx context.Context, cmd *models.UpdateOrgCommand) error { return m.ExpectedError } -func (m SQLStoreMock) UpdateOrgAddress(ctx context.Context, cmd *models.UpdateOrgAddressCommand) error { +func (m *SQLStoreMock) UpdateOrgAddress(ctx context.Context, cmd *models.UpdateOrgAddressCommand) error { return m.ExpectedError } -func (m SQLStoreMock) DeleteOrg(ctx context.Context, cmd *models.DeleteOrgCommand) error { +func (m *SQLStoreMock) DeleteOrg(ctx context.Context, cmd *models.DeleteOrgCommand) error { return m.ExpectedError } -func (m SQLStoreMock) GetProvisionedDataByDashboardID(dashboardID int64) (*models.DashboardProvisioning, error) { +func (m *SQLStoreMock) GetProvisionedDataByDashboardID(dashboardID int64) (*models.DashboardProvisioning, error) { return nil, m.ExpectedError } -func (m SQLStoreMock) GetProvisionedDataByDashboardUID(orgID int64, dashboardUID string) (*models.DashboardProvisioning, error) { +func (m *SQLStoreMock) GetProvisionedDataByDashboardUID(orgID int64, dashboardUID string) (*models.DashboardProvisioning, error) { return nil, m.ExpectedError } -func (m SQLStoreMock) SaveProvisionedDashboard(cmd models.SaveDashboardCommand, provisioning *models.DashboardProvisioning) (*models.Dashboard, error) { +func (m *SQLStoreMock) SaveProvisionedDashboard(cmd models.SaveDashboardCommand, provisioning *models.DashboardProvisioning) (*models.Dashboard, error) { return nil, m.ExpectedError } -func (m SQLStoreMock) GetProvisionedDashboardData(name string) ([]*models.DashboardProvisioning, error) { +func (m *SQLStoreMock) GetProvisionedDashboardData(name string) ([]*models.DashboardProvisioning, error) { return nil, m.ExpectedError } -func (m SQLStoreMock) DeleteOrphanedProvisionedDashboards(ctx context.Context, cmd *models.DeleteOrphanedProvisionedDashboardsCommand) error { +func (m *SQLStoreMock) DeleteOrphanedProvisionedDashboards(ctx context.Context, cmd *models.DeleteOrphanedProvisionedDashboardsCommand) error { return m.ExpectedError } -func (m SQLStoreMock) CreateLoginAttempt(ctx context.Context, cmd *models.CreateLoginAttemptCommand) error { +func (m *SQLStoreMock) CreateLoginAttempt(ctx context.Context, cmd *models.CreateLoginAttemptCommand) error { return m.ExpectedError } -func (m SQLStoreMock) DeleteOldLoginAttempts(ctx context.Context, cmd *models.DeleteOldLoginAttemptsCommand) error { +func (m *SQLStoreMock) DeleteOldLoginAttempts(ctx context.Context, cmd *models.DeleteOldLoginAttemptsCommand) error { return m.ExpectedError } -func (m SQLStoreMock) CloneUserToServiceAccount(ctx context.Context, siUser *models.SignedInUser) (*models.User, error) { +func (m *SQLStoreMock) CloneUserToServiceAccount(ctx context.Context, siUser *models.SignedInUser) (*models.User, error) { return nil, m.ExpectedError } -func (m SQLStoreMock) CreateServiceAccountForApikey(ctx context.Context, orgId int64, keyname string, role models.RoleType) (*models.User, error) { +func (m *SQLStoreMock) CreateServiceAccountForApikey(ctx context.Context, orgId int64, keyname string, role models.RoleType) (*models.User, error) { return nil, m.ExpectedError } -func (m SQLStoreMock) CreateUser(ctx context.Context, cmd models.CreateUserCommand) (*models.User, error) { +func (m *SQLStoreMock) CreateUser(ctx context.Context, cmd models.CreateUserCommand) (*models.User, error) { return nil, m.ExpectedError } -func (m SQLStoreMock) GetUserById(ctx context.Context, query *models.GetUserByIdQuery) error { +func (m *SQLStoreMock) GetUserById(ctx context.Context, query *models.GetUserByIdQuery) error { query.Result = m.ExpectedUser return m.ExpectedError } -func (m SQLStoreMock) GetUserByLogin(ctx context.Context, query *models.GetUserByLoginQuery) error { +func (m *SQLStoreMock) GetUserByLogin(ctx context.Context, query *models.GetUserByLoginQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetUserByEmail(ctx context.Context, query *models.GetUserByEmailQuery) error { +func (m *SQLStoreMock) GetUserByEmail(ctx context.Context, query *models.GetUserByEmailQuery) error { return m.ExpectedError } -func (m SQLStoreMock) UpdateUser(ctx context.Context, cmd *models.UpdateUserCommand) error { +func (m *SQLStoreMock) UpdateUser(ctx context.Context, cmd *models.UpdateUserCommand) error { return m.ExpectedError } -func (m SQLStoreMock) ChangeUserPassword(ctx context.Context, cmd *models.ChangeUserPasswordCommand) error { +func (m *SQLStoreMock) ChangeUserPassword(ctx context.Context, cmd *models.ChangeUserPasswordCommand) error { return m.ExpectedError } -func (m SQLStoreMock) UpdateUserLastSeenAt(ctx context.Context, cmd *models.UpdateUserLastSeenAtCommand) error { +func (m *SQLStoreMock) UpdateUserLastSeenAt(ctx context.Context, cmd *models.UpdateUserLastSeenAtCommand) error { return m.ExpectedError } -func (m SQLStoreMock) SetUsingOrg(ctx context.Context, cmd *models.SetUsingOrgCommand) error { +func (m *SQLStoreMock) SetUsingOrg(ctx context.Context, cmd *models.SetUsingOrgCommand) error { return m.ExpectedError } -func (m SQLStoreMock) GetUserProfile(ctx context.Context, query *models.GetUserProfileQuery) error { +func (m *SQLStoreMock) GetUserProfile(ctx context.Context, query *models.GetUserProfileQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetUserOrgList(ctx context.Context, query *models.GetUserOrgListQuery) error { +func (m *SQLStoreMock) GetUserOrgList(ctx context.Context, query *models.GetUserOrgListQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetSignedInUserWithCacheCtx(ctx context.Context, query *models.GetSignedInUserQuery) error { +func (m *SQLStoreMock) GetSignedInUserWithCacheCtx(ctx context.Context, query *models.GetSignedInUserQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetSignedInUser(ctx context.Context, query *models.GetSignedInUserQuery) error { +func (m *SQLStoreMock) GetSignedInUser(ctx context.Context, query *models.GetSignedInUserQuery) error { return m.ExpectedError } -func (m SQLStoreMock) BatchDisableUsers(ctx context.Context, cmd *models.BatchDisableUsersCommand) error { +func (m *SQLStoreMock) BatchDisableUsers(ctx context.Context, cmd *models.BatchDisableUsersCommand) error { return m.ExpectedError } -func (m SQLStoreMock) DeleteUser(ctx context.Context, cmd *models.DeleteUserCommand) error { +func (m *SQLStoreMock) DeleteUser(ctx context.Context, cmd *models.DeleteUserCommand) error { return m.ExpectedError } -func (m SQLStoreMock) UpdateUserPermissions(userID int64, isAdmin bool) error { +func (m *SQLStoreMock) UpdateUserPermissions(userID int64, isAdmin bool) error { return m.ExpectedError } -func (m SQLStoreMock) SetUserHelpFlag(ctx context.Context, cmd *models.SetUserHelpFlagCommand) error { +func (m *SQLStoreMock) SetUserHelpFlag(ctx context.Context, cmd *models.SetUserHelpFlagCommand) error { return m.ExpectedError } -func (m SQLStoreMock) CreateTeam(name string, email string, orgID int64) (models.Team, error) { +func (m *SQLStoreMock) CreateTeam(name string, email string, orgID int64) (models.Team, error) { return models.Team{ Name: name, Email: email, @@ -171,411 +174,413 @@ func (m SQLStoreMock) CreateTeam(name string, email string, orgID int64) (models }, nil } -func (m SQLStoreMock) UpdateTeam(ctx context.Context, cmd *models.UpdateTeamCommand) error { +func (m *SQLStoreMock) UpdateTeam(ctx context.Context, cmd *models.UpdateTeamCommand) error { return m.ExpectedError } -func (m SQLStoreMock) DeleteTeam(ctx context.Context, cmd *models.DeleteTeamCommand) error { +func (m *SQLStoreMock) DeleteTeam(ctx context.Context, cmd *models.DeleteTeamCommand) error { return m.ExpectedError } -func (m SQLStoreMock) SearchTeams(ctx context.Context, query *models.SearchTeamsQuery) error { +func (m *SQLStoreMock) SearchTeams(ctx context.Context, query *models.SearchTeamsQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetTeamById(ctx context.Context, query *models.GetTeamByIdQuery) error { +func (m *SQLStoreMock) GetTeamById(ctx context.Context, query *models.GetTeamByIdQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetTeamsByUser(ctx context.Context, query *models.GetTeamsByUserQuery) error { +func (m *SQLStoreMock) GetTeamsByUser(ctx context.Context, query *models.GetTeamsByUserQuery) error { return m.ExpectedError } -func (m SQLStoreMock) AddTeamMember(userID int64, orgID int64, teamID int64, isExternal bool, permission models.PermissionType) error { +func (m *SQLStoreMock) AddTeamMember(userID int64, orgID int64, teamID int64, isExternal bool, permission models.PermissionType) error { return m.ExpectedError } -func (m SQLStoreMock) UpdateTeamMember(ctx context.Context, cmd *models.UpdateTeamMemberCommand) error { +func (m *SQLStoreMock) UpdateTeamMember(ctx context.Context, cmd *models.UpdateTeamMemberCommand) error { return m.ExpectedError } -func (m SQLStoreMock) IsTeamMember(orgId int64, teamId int64, userId int64) (bool, error) { +func (m *SQLStoreMock) IsTeamMember(orgId int64, teamId int64, userId int64) (bool, error) { return false, nil } -func (m SQLStoreMock) RemoveTeamMember(ctx context.Context, cmd *models.RemoveTeamMemberCommand) error { +func (m *SQLStoreMock) RemoveTeamMember(ctx context.Context, cmd *models.RemoveTeamMemberCommand) error { return m.ExpectedError } -func (m SQLStoreMock) GetTeamMembers(ctx context.Context, query *models.GetTeamMembersQuery) error { +func (m *SQLStoreMock) GetTeamMembers(ctx context.Context, query *models.GetTeamMembersQuery) error { return m.ExpectedError } -func (m SQLStoreMock) NewSession(ctx context.Context) *sqlstore.DBSession { +func (m *SQLStoreMock) NewSession(ctx context.Context) *sqlstore.DBSession { return nil } -func (m SQLStoreMock) WithDbSession(ctx context.Context, callback sqlstore.DBTransactionFunc) error { +func (m *SQLStoreMock) WithDbSession(ctx context.Context, callback sqlstore.DBTransactionFunc) error { return m.ExpectedError } -func (m SQLStoreMock) GetPreferencesWithDefaults(ctx context.Context, query *models.GetPreferencesWithDefaultsQuery) error { +func (m *SQLStoreMock) GetPreferencesWithDefaults(ctx context.Context, query *models.GetPreferencesWithDefaultsQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetPreferences(ctx context.Context, query *models.GetPreferencesQuery) error { +func (m *SQLStoreMock) GetPreferences(ctx context.Context, query *models.GetPreferencesQuery) error { return m.ExpectedError } -func (m SQLStoreMock) SavePreferences(ctx context.Context, cmd *models.SavePreferencesCommand) error { +func (m *SQLStoreMock) SavePreferences(ctx context.Context, cmd *models.SavePreferencesCommand) error { return m.ExpectedError } -func (m SQLStoreMock) GetPluginSettings(ctx context.Context, orgID int64) ([]*models.PluginSettingInfoDTO, error) { +func (m *SQLStoreMock) GetPluginSettings(ctx context.Context, orgID int64) ([]*models.PluginSettingInfoDTO, error) { return nil, m.ExpectedError } -func (m SQLStoreMock) GetPluginSettingById(ctx context.Context, query *models.GetPluginSettingByIdQuery) error { +func (m *SQLStoreMock) GetPluginSettingById(ctx context.Context, query *models.GetPluginSettingByIdQuery) error { return m.ExpectedError } -func (m SQLStoreMock) UpdatePluginSetting(ctx context.Context, cmd *models.UpdatePluginSettingCmd) error { +func (m *SQLStoreMock) UpdatePluginSetting(ctx context.Context, cmd *models.UpdatePluginSettingCmd) error { return m.ExpectedError } -func (m SQLStoreMock) UpdatePluginSettingVersion(ctx context.Context, cmd *models.UpdatePluginSettingVersionCmd) error { +func (m *SQLStoreMock) UpdatePluginSettingVersion(ctx context.Context, cmd *models.UpdatePluginSettingVersionCmd) error { return m.ExpectedError } -func (m SQLStoreMock) IsStarredByUserCtx(ctx context.Context, query *models.IsStarredByUserQuery) error { +func (m *SQLStoreMock) IsStarredByUserCtx(ctx context.Context, query *models.IsStarredByUserQuery) error { return m.ExpectedError } -func (m SQLStoreMock) StarDashboard(ctx context.Context, cmd *models.StarDashboardCommand) error { +func (m *SQLStoreMock) StarDashboard(ctx context.Context, cmd *models.StarDashboardCommand) error { return m.ExpectedError } -func (m SQLStoreMock) UnstarDashboard(ctx context.Context, cmd *models.UnstarDashboardCommand) error { +func (m *SQLStoreMock) UnstarDashboard(ctx context.Context, cmd *models.UnstarDashboardCommand) error { return m.ExpectedError } -func (m SQLStoreMock) GetUserStars(ctx context.Context, query *models.GetUserStarsQuery) error { +func (m *SQLStoreMock) GetUserStars(ctx context.Context, query *models.GetUserStarsQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetOrgQuotaByTarget(ctx context.Context, query *models.GetOrgQuotaByTargetQuery) error { +func (m *SQLStoreMock) GetOrgQuotaByTarget(ctx context.Context, query *models.GetOrgQuotaByTargetQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetOrgQuotas(ctx context.Context, query *models.GetOrgQuotasQuery) error { +func (m *SQLStoreMock) GetOrgQuotas(ctx context.Context, query *models.GetOrgQuotasQuery) error { return m.ExpectedError } -func (m SQLStoreMock) UpdateOrgQuota(ctx context.Context, cmd *models.UpdateOrgQuotaCmd) error { +func (m *SQLStoreMock) UpdateOrgQuota(ctx context.Context, cmd *models.UpdateOrgQuotaCmd) error { return m.ExpectedError } -func (m SQLStoreMock) GetUserQuotaByTarget(ctx context.Context, query *models.GetUserQuotaByTargetQuery) error { +func (m *SQLStoreMock) GetUserQuotaByTarget(ctx context.Context, query *models.GetUserQuotaByTargetQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetUserQuotas(ctx context.Context, query *models.GetUserQuotasQuery) error { +func (m *SQLStoreMock) GetUserQuotas(ctx context.Context, query *models.GetUserQuotasQuery) error { return m.ExpectedError } -func (m SQLStoreMock) UpdateUserQuota(ctx context.Context, cmd *models.UpdateUserQuotaCmd) error { +func (m *SQLStoreMock) UpdateUserQuota(ctx context.Context, cmd *models.UpdateUserQuotaCmd) error { return m.ExpectedError } -func (m SQLStoreMock) GetGlobalQuotaByTarget(ctx context.Context, query *models.GetGlobalQuotaByTargetQuery) error { +func (m *SQLStoreMock) GetGlobalQuotaByTarget(ctx context.Context, query *models.GetGlobalQuotaByTargetQuery) error { return m.ExpectedError } -func (m SQLStoreMock) WithTransactionalDbSession(ctx context.Context, callback sqlstore.DBTransactionFunc) error { +func (m *SQLStoreMock) WithTransactionalDbSession(ctx context.Context, callback sqlstore.DBTransactionFunc) error { return m.ExpectedError } -func (m SQLStoreMock) InTransaction(ctx context.Context, fn func(ctx context.Context) error) error { +func (m *SQLStoreMock) InTransaction(ctx context.Context, fn func(ctx context.Context) error) error { return m.ExpectedError } -func (m SQLStoreMock) GetDashboardVersion(ctx context.Context, query *models.GetDashboardVersionQuery) error { +func (m *SQLStoreMock) GetDashboardVersion(ctx context.Context, query *models.GetDashboardVersionQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetDashboardVersions(ctx context.Context, query *models.GetDashboardVersionsQuery) error { +func (m *SQLStoreMock) GetDashboardVersions(ctx context.Context, query *models.GetDashboardVersionsQuery) error { return m.ExpectedError } -func (m SQLStoreMock) DeleteExpiredVersions(ctx context.Context, cmd *models.DeleteExpiredVersionsCommand) error { +func (m *SQLStoreMock) DeleteExpiredVersions(ctx context.Context, cmd *models.DeleteExpiredVersionsCommand) error { return m.ExpectedError } -func (m SQLStoreMock) UpdateDashboardACL(ctx context.Context, dashboardID int64, items []*models.DashboardAcl) error { +func (m *SQLStoreMock) UpdateDashboardACL(ctx context.Context, dashboardID int64, items []*models.DashboardAcl) error { return m.ExpectedError } -func (m SQLStoreMock) UpdateDashboardACLCtx(ctx context.Context, dashboardID int64, items []*models.DashboardAcl) error { +func (m *SQLStoreMock) UpdateDashboardACLCtx(ctx context.Context, dashboardID int64, items []*models.DashboardAcl) error { return m.ExpectedError } -func (m SQLStoreMock) GetDashboardAclInfoList(ctx context.Context, query *models.GetDashboardAclInfoListQuery) error { +func (m *SQLStoreMock) GetDashboardAclInfoList(ctx context.Context, query *models.GetDashboardAclInfoListQuery) error { return m.ExpectedError } -func (m SQLStoreMock) CreatePlaylist(ctx context.Context, cmd *models.CreatePlaylistCommand) error { +func (m *SQLStoreMock) CreatePlaylist(ctx context.Context, cmd *models.CreatePlaylistCommand) error { return m.ExpectedError } -func (m SQLStoreMock) UpdatePlaylist(ctx context.Context, cmd *models.UpdatePlaylistCommand) error { +func (m *SQLStoreMock) UpdatePlaylist(ctx context.Context, cmd *models.UpdatePlaylistCommand) error { return m.ExpectedError } -func (m SQLStoreMock) GetPlaylist(ctx context.Context, query *models.GetPlaylistByIdQuery) error { +func (m *SQLStoreMock) GetPlaylist(ctx context.Context, query *models.GetPlaylistByIdQuery) error { return m.ExpectedError } -func (m SQLStoreMock) DeletePlaylist(ctx context.Context, cmd *models.DeletePlaylistCommand) error { +func (m *SQLStoreMock) DeletePlaylist(ctx context.Context, cmd *models.DeletePlaylistCommand) error { return m.ExpectedError } -func (m SQLStoreMock) SearchPlaylists(ctx context.Context, query *models.GetPlaylistsQuery) error { +func (m *SQLStoreMock) SearchPlaylists(ctx context.Context, query *models.GetPlaylistsQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetPlaylistItem(ctx context.Context, query *models.GetPlaylistItemsByIdQuery) error { +func (m *SQLStoreMock) GetPlaylistItem(ctx context.Context, query *models.GetPlaylistItemsByIdQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetAlertById(ctx context.Context, query *models.GetAlertByIdQuery) error { +func (m *SQLStoreMock) GetAlertById(ctx context.Context, query *models.GetAlertByIdQuery) error { + query.Result = m.ExpectedAlert return m.ExpectedError } -func (m SQLStoreMock) GetAllAlertQueryHandler(ctx context.Context, query *models.GetAllAlertsQuery) error { +func (m *SQLStoreMock) GetAllAlertQueryHandler(ctx context.Context, query *models.GetAllAlertsQuery) error { return m.ExpectedError } -func (m SQLStoreMock) HandleAlertsQuery(ctx context.Context, query *models.GetAlertsQuery) error { +func (m *SQLStoreMock) HandleAlertsQuery(ctx context.Context, query *models.GetAlertsQuery) error { + m.LastGetAlertsQuery = query return m.ExpectedError } -func (m SQLStoreMock) SaveAlerts(ctx context.Context, dashID int64, alerts []*models.Alert) error { +func (m *SQLStoreMock) SaveAlerts(ctx context.Context, dashID int64, alerts []*models.Alert) error { return m.ExpectedError } -func (m SQLStoreMock) SetAlertState(ctx context.Context, cmd *models.SetAlertStateCommand) error { +func (m *SQLStoreMock) SetAlertState(ctx context.Context, cmd *models.SetAlertStateCommand) error { return m.ExpectedError } -func (m SQLStoreMock) PauseAlert(ctx context.Context, cmd *models.PauseAlertCommand) error { +func (m *SQLStoreMock) PauseAlert(ctx context.Context, cmd *models.PauseAlertCommand) error { return m.ExpectedError } -func (m SQLStoreMock) PauseAllAlerts(ctx context.Context, cmd *models.PauseAllAlertCommand) error { +func (m *SQLStoreMock) PauseAllAlerts(ctx context.Context, cmd *models.PauseAllAlertCommand) error { return m.ExpectedError } -func (m SQLStoreMock) GetAlertStatesForDashboard(ctx context.Context, query *models.GetAlertStatesForDashboardQuery) error { +func (m *SQLStoreMock) GetAlertStatesForDashboard(ctx context.Context, query *models.GetAlertStatesForDashboardQuery) error { return m.ExpectedError } -func (m SQLStoreMock) AddOrgUser(ctx context.Context, cmd *models.AddOrgUserCommand) error { +func (m *SQLStoreMock) AddOrgUser(ctx context.Context, cmd *models.AddOrgUserCommand) error { return m.ExpectedError } -func (m SQLStoreMock) UpdateOrgUser(ctx context.Context, cmd *models.UpdateOrgUserCommand) error { +func (m *SQLStoreMock) UpdateOrgUser(ctx context.Context, cmd *models.UpdateOrgUserCommand) error { return m.ExpectedError } -func (m SQLStoreMock) GetOrgUsers(ctx context.Context, query *models.GetOrgUsersQuery) error { +func (m *SQLStoreMock) GetOrgUsers(ctx context.Context, query *models.GetOrgUsersQuery) error { return m.ExpectedError } -func (m SQLStoreMock) SearchOrgUsers(ctx context.Context, query *models.SearchOrgUsersQuery) error { +func (m *SQLStoreMock) SearchOrgUsers(ctx context.Context, query *models.SearchOrgUsersQuery) error { return m.ExpectedError } -func (m SQLStoreMock) RemoveOrgUser(ctx context.Context, cmd *models.RemoveOrgUserCommand) error { +func (m *SQLStoreMock) RemoveOrgUser(ctx context.Context, cmd *models.RemoveOrgUserCommand) error { return m.ExpectedError } -func (m SQLStoreMock) SaveDashboard(cmd models.SaveDashboardCommand) (*models.Dashboard, error) { +func (m *SQLStoreMock) SaveDashboard(cmd models.SaveDashboardCommand) (*models.Dashboard, error) { return nil, m.ExpectedError } -func (m SQLStoreMock) GetDashboard(id int64, orgID int64, uid string, slug string) (*models.Dashboard, error) { +func (m *SQLStoreMock) GetDashboard(id int64, orgID int64, uid string, slug string) (*models.Dashboard, error) { return nil, m.ExpectedError } -func (m SQLStoreMock) GetFolderByTitle(orgID int64, title string) (*models.Dashboard, error) { +func (m *SQLStoreMock) GetFolderByTitle(orgID int64, title string) (*models.Dashboard, error) { return nil, m.ExpectedError } -func (m SQLStoreMock) SearchDashboards(ctx context.Context, query *search.FindPersistedDashboardsQuery) error { +func (m *SQLStoreMock) SearchDashboards(ctx context.Context, query *search.FindPersistedDashboardsQuery) error { return m.ExpectedError } -func (m SQLStoreMock) DeleteDashboard(ctx context.Context, cmd *models.DeleteDashboardCommand) error { +func (m *SQLStoreMock) DeleteDashboard(ctx context.Context, cmd *models.DeleteDashboardCommand) error { return m.ExpectedError } -func (m SQLStoreMock) GetDashboards(ctx context.Context, query *models.GetDashboardsQuery) error { +func (m *SQLStoreMock) GetDashboards(ctx context.Context, query *models.GetDashboardsQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetDashboardUIDById(ctx context.Context, query *models.GetDashboardRefByIdQuery) error { +func (m *SQLStoreMock) GetDashboardUIDById(ctx context.Context, query *models.GetDashboardRefByIdQuery) error { return m.ExpectedError } -func (m SQLStoreMock) ValidateDashboardBeforeSave(dashboard *models.Dashboard, overwrite bool) (bool, error) { +func (m *SQLStoreMock) ValidateDashboardBeforeSave(dashboard *models.Dashboard, overwrite bool) (bool, error) { return false, nil } -func (m SQLStoreMock) GetDataSource(ctx context.Context, query *models.GetDataSourceQuery) error { +func (m *SQLStoreMock) GetDataSource(ctx context.Context, query *models.GetDataSourceQuery) error { query.Result = m.ExpectedDatasource return m.ExpectedError } -func (m SQLStoreMock) GetDataSources(ctx context.Context, query *models.GetDataSourcesQuery) error { +func (m *SQLStoreMock) GetDataSources(ctx context.Context, query *models.GetDataSourcesQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetDataSourcesByType(ctx context.Context, query *models.GetDataSourcesByTypeQuery) error { +func (m *SQLStoreMock) GetDataSourcesByType(ctx context.Context, query *models.GetDataSourcesByTypeQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetDefaultDataSource(ctx context.Context, query *models.GetDefaultDataSourceQuery) error { +func (m *SQLStoreMock) GetDefaultDataSource(ctx context.Context, query *models.GetDefaultDataSourceQuery) error { return m.ExpectedError } -func (m SQLStoreMock) DeleteDataSource(ctx context.Context, cmd *models.DeleteDataSourceCommand) error { +func (m *SQLStoreMock) DeleteDataSource(ctx context.Context, cmd *models.DeleteDataSourceCommand) error { return m.ExpectedError } -func (m SQLStoreMock) AddDataSource(ctx context.Context, cmd *models.AddDataSourceCommand) error { +func (m *SQLStoreMock) AddDataSource(ctx context.Context, cmd *models.AddDataSourceCommand) error { return m.ExpectedError } -func (m SQLStoreMock) UpdateDataSource(ctx context.Context, cmd *models.UpdateDataSourceCommand) error { +func (m *SQLStoreMock) UpdateDataSource(ctx context.Context, cmd *models.UpdateDataSourceCommand) error { return m.ExpectedError } -func (m SQLStoreMock) Migrate() error { +func (m *SQLStoreMock) Migrate() error { return m.ExpectedError } -func (m SQLStoreMock) Sync() error { +func (m *SQLStoreMock) Sync() error { return m.ExpectedError } -func (m SQLStoreMock) Reset() error { +func (m *SQLStoreMock) Reset() error { return m.ExpectedError } -func (m SQLStoreMock) Quote(value string) string { +func (m *SQLStoreMock) Quote(value string) string { return "" } -func (m SQLStoreMock) DeleteAlertNotification(ctx context.Context, cmd *models.DeleteAlertNotificationCommand) error { +func (m *SQLStoreMock) DeleteAlertNotification(ctx context.Context, cmd *models.DeleteAlertNotificationCommand) error { return m.ExpectedError } -func (m SQLStoreMock) DeleteAlertNotificationWithUid(ctx context.Context, cmd *models.DeleteAlertNotificationWithUidCommand) error { +func (m *SQLStoreMock) DeleteAlertNotificationWithUid(ctx context.Context, cmd *models.DeleteAlertNotificationWithUidCommand) error { return m.ExpectedError } -func (m SQLStoreMock) GetAlertNotifications(ctx context.Context, query *models.GetAlertNotificationsQuery) error { +func (m *SQLStoreMock) GetAlertNotifications(ctx context.Context, query *models.GetAlertNotificationsQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetAlertNotificationUidWithId(ctx context.Context, query *models.GetAlertNotificationUidQuery) error { +func (m *SQLStoreMock) GetAlertNotificationUidWithId(ctx context.Context, query *models.GetAlertNotificationUidQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetAlertNotificationsWithUid(ctx context.Context, query *models.GetAlertNotificationsWithUidQuery) error { +func (m *SQLStoreMock) GetAlertNotificationsWithUid(ctx context.Context, query *models.GetAlertNotificationsWithUidQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetAllAlertNotifications(ctx context.Context, query *models.GetAllAlertNotificationsQuery) error { +func (m *SQLStoreMock) GetAllAlertNotifications(ctx context.Context, query *models.GetAllAlertNotificationsQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetAlertNotificationsWithUidToSend(ctx context.Context, query *models.GetAlertNotificationsWithUidToSendQuery) error { +func (m *SQLStoreMock) GetAlertNotificationsWithUidToSend(ctx context.Context, query *models.GetAlertNotificationsWithUidToSendQuery) error { return m.ExpectedError } -func (m SQLStoreMock) CreateAlertNotificationCommand(ctx context.Context, cmd *models.CreateAlertNotificationCommand) error { +func (m *SQLStoreMock) CreateAlertNotificationCommand(ctx context.Context, cmd *models.CreateAlertNotificationCommand) error { return m.ExpectedError } -func (m SQLStoreMock) UpdateAlertNotification(ctx context.Context, cmd *models.UpdateAlertNotificationCommand) error { +func (m *SQLStoreMock) UpdateAlertNotification(ctx context.Context, cmd *models.UpdateAlertNotificationCommand) error { return m.ExpectedError } -func (m SQLStoreMock) UpdateAlertNotificationWithUid(ctx context.Context, cmd *models.UpdateAlertNotificationWithUidCommand) error { +func (m *SQLStoreMock) UpdateAlertNotificationWithUid(ctx context.Context, cmd *models.UpdateAlertNotificationWithUidCommand) error { return m.ExpectedError } -func (m SQLStoreMock) SetAlertNotificationStateToCompleteCommand(ctx context.Context, cmd *models.SetAlertNotificationStateToCompleteCommand) error { +func (m *SQLStoreMock) SetAlertNotificationStateToCompleteCommand(ctx context.Context, cmd *models.SetAlertNotificationStateToCompleteCommand) error { return m.ExpectedError } -func (m SQLStoreMock) SetAlertNotificationStateToPendingCommand(ctx context.Context, cmd *models.SetAlertNotificationStateToPendingCommand) error { +func (m *SQLStoreMock) SetAlertNotificationStateToPendingCommand(ctx context.Context, cmd *models.SetAlertNotificationStateToPendingCommand) error { return m.ExpectedError } -func (m SQLStoreMock) GetOrCreateAlertNotificationState(ctx context.Context, cmd *models.GetOrCreateNotificationStateQuery) error { +func (m *SQLStoreMock) GetOrCreateAlertNotificationState(ctx context.Context, cmd *models.GetOrCreateNotificationStateQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetAPIKeys(ctx context.Context, query *models.GetApiKeysQuery) error { +func (m *SQLStoreMock) GetAPIKeys(ctx context.Context, query *models.GetApiKeysQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetNonServiceAccountAPIKeys(ctx context.Context) []*models.ApiKey { +func (m *SQLStoreMock) GetNonServiceAccountAPIKeys(ctx context.Context) []*models.ApiKey { return nil } -func (m SQLStoreMock) DeleteApiKey(ctx context.Context, cmd *models.DeleteApiKeyCommand) error { +func (m *SQLStoreMock) DeleteApiKey(ctx context.Context, cmd *models.DeleteApiKeyCommand) error { return m.ExpectedError } -func (m SQLStoreMock) AddAPIKey(ctx context.Context, cmd *models.AddApiKeyCommand) error { +func (m *SQLStoreMock) AddAPIKey(ctx context.Context, cmd *models.AddApiKeyCommand) error { return m.ExpectedError } -func (m SQLStoreMock) UpdateApikeyServiceAccount(ctx context.Context, apikeyId int64, saccountId int64) error { +func (m *SQLStoreMock) UpdateApikeyServiceAccount(ctx context.Context, apikeyId int64, saccountId int64) error { return m.ExpectedError } -func (m SQLStoreMock) GetApiKeyById(ctx context.Context, query *models.GetApiKeyByIdQuery) error { +func (m *SQLStoreMock) GetApiKeyById(ctx context.Context, query *models.GetApiKeyByIdQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetApiKeyByName(ctx context.Context, query *models.GetApiKeyByNameQuery) error { +func (m *SQLStoreMock) GetApiKeyByName(ctx context.Context, query *models.GetApiKeyByNameQuery) error { return m.ExpectedError } -func (m SQLStoreMock) UpdateTempUserStatus(ctx context.Context, cmd *models.UpdateTempUserStatusCommand) error { +func (m *SQLStoreMock) UpdateTempUserStatus(ctx context.Context, cmd *models.UpdateTempUserStatusCommand) error { return m.ExpectedError } -func (m SQLStoreMock) CreateTempUser(ctx context.Context, cmd *models.CreateTempUserCommand) error { +func (m *SQLStoreMock) CreateTempUser(ctx context.Context, cmd *models.CreateTempUserCommand) error { return m.ExpectedError } -func (m SQLStoreMock) UpdateTempUserWithEmailSent(ctx context.Context, cmd *models.UpdateTempUserWithEmailSentCommand) error { +func (m *SQLStoreMock) UpdateTempUserWithEmailSent(ctx context.Context, cmd *models.UpdateTempUserWithEmailSentCommand) error { return m.ExpectedError } -func (m SQLStoreMock) GetTempUsersQuery(ctx context.Context, query *models.GetTempUsersQuery) error { +func (m *SQLStoreMock) GetTempUsersQuery(ctx context.Context, query *models.GetTempUsersQuery) error { return m.ExpectedError } -func (m SQLStoreMock) GetTempUserByCode(ctx context.Context, query *models.GetTempUserByCodeQuery) error { +func (m *SQLStoreMock) GetTempUserByCode(ctx context.Context, query *models.GetTempUserByCodeQuery) error { return m.ExpectedError } -func (m SQLStoreMock) ExpireOldUserInvites(ctx context.Context, cmd *models.ExpireTempUsersCommand) error { +func (m *SQLStoreMock) ExpireOldUserInvites(ctx context.Context, cmd *models.ExpireTempUsersCommand) error { return m.ExpectedError }