diff --git a/pkg/api/dashboard_snapshot.go b/pkg/api/dashboard_snapshot.go index b2161db9327..79ae82d3930 100644 --- a/pkg/api/dashboard_snapshot.go +++ b/pkg/api/dashboard_snapshot.go @@ -13,6 +13,7 @@ import ( "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/infra/metrics" "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/dashboardsnapshots" "github.com/grafana/grafana/pkg/services/guardian" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/util" @@ -39,7 +40,7 @@ type CreateExternalSnapshotResponse struct { DeleteUrl string `json:"deleteUrl"` } -func createExternalDashboardSnapshot(cmd models.CreateDashboardSnapshotCommand) (*CreateExternalSnapshotResponse, error) { +func createExternalDashboardSnapshot(cmd dashboardsnapshots.CreateDashboardSnapshotCommand) (*CreateExternalSnapshotResponse, error) { var createSnapshotResponse CreateExternalSnapshotResponse message := map[string]interface{}{ "name": cmd.Name, @@ -77,7 +78,7 @@ func createExternalDashboardSnapshot(cmd models.CreateDashboardSnapshotCommand) // POST /api/snapshots func (hs *HTTPServer) CreateDashboardSnapshot(c *models.ReqContext) response.Response { - cmd := models.CreateDashboardSnapshotCommand{} + cmd := dashboardsnapshots.CreateDashboardSnapshotCommand{} if err := web.Bind(c.Req, &cmd); err != nil { return response.Error(http.StatusBadRequest, "bad request data", err) } @@ -156,7 +157,7 @@ func (hs *HTTPServer) GetDashboardSnapshot(c *models.ReqContext) response.Respon return response.Error(404, "Snapshot not found", nil) } - query := &models.GetDashboardSnapshotQuery{Key: key} + query := &dashboardsnapshots.GetDashboardSnapshotQuery{Key: key} err := hs.dashboardsnapshotsService.GetDashboardSnapshot(c.Req.Context(), query) if err != nil { @@ -224,7 +225,7 @@ func (hs *HTTPServer) DeleteDashboardSnapshotByDeleteKey(c *models.ReqContext) r return response.Error(404, "Snapshot not found", nil) } - query := &models.GetDashboardSnapshotQuery{DeleteKey: key} + query := &dashboardsnapshots.GetDashboardSnapshotQuery{DeleteKey: key} err := hs.dashboardsnapshotsService.GetDashboardSnapshot(c.Req.Context(), query) if err != nil { return response.Error(500, "Failed to get dashboard snapshot", err) @@ -237,7 +238,7 @@ func (hs *HTTPServer) DeleteDashboardSnapshotByDeleteKey(c *models.ReqContext) r } } - cmd := &models.DeleteDashboardSnapshotCommand{DeleteKey: query.Result.DeleteKey} + cmd := &dashboardsnapshots.DeleteDashboardSnapshotCommand{DeleteKey: query.Result.DeleteKey} if err := hs.dashboardsnapshotsService.DeleteDashboardSnapshot(c.Req.Context(), cmd); err != nil { return response.Error(500, "Failed to delete dashboard snapshot", err) @@ -256,7 +257,7 @@ func (hs *HTTPServer) DeleteDashboardSnapshot(c *models.ReqContext) response.Res return response.Error(404, "Snapshot not found", nil) } - query := &models.GetDashboardSnapshotQuery{Key: key} + query := &dashboardsnapshots.GetDashboardSnapshotQuery{Key: key} err := hs.dashboardsnapshotsService.GetDashboardSnapshot(c.Req.Context(), query) if err != nil { @@ -286,7 +287,7 @@ func (hs *HTTPServer) DeleteDashboardSnapshot(c *models.ReqContext) response.Res } } - cmd := &models.DeleteDashboardSnapshotCommand{DeleteKey: query.Result.DeleteKey} + cmd := &dashboardsnapshots.DeleteDashboardSnapshotCommand{DeleteKey: query.Result.DeleteKey} if err := hs.dashboardsnapshotsService.DeleteDashboardSnapshot(c.Req.Context(), cmd); err != nil { return response.Error(500, "Failed to delete dashboard snapshot", err) @@ -307,7 +308,7 @@ func (hs *HTTPServer) SearchDashboardSnapshots(c *models.ReqContext) response.Re limit = 1000 } - searchQuery := models.GetDashboardSnapshotsQuery{ + searchQuery := dashboardsnapshots.GetDashboardSnapshotsQuery{ Name: query, Limit: limit, OrgId: c.OrgId, @@ -319,9 +320,9 @@ func (hs *HTTPServer) SearchDashboardSnapshots(c *models.ReqContext) response.Re return response.Error(500, "Search failed", err) } - dtos := make([]*models.DashboardSnapshotDTO, len(searchQuery.Result)) + dtos := make([]*dashboardsnapshots.DashboardSnapshotDTO, len(searchQuery.Result)) for i, snapshot := range searchQuery.Result { - dtos[i] = &models.DashboardSnapshotDTO{ + dtos[i] = &dashboardsnapshots.DashboardSnapshotDTO{ Id: snapshot.Id, Name: snapshot.Name, Key: snapshot.Key, diff --git a/pkg/api/dashboard_snapshot_test.go b/pkg/api/dashboard_snapshot_test.go index 4634b9e68e9..5c09202cb09 100644 --- a/pkg/api/dashboard_snapshot_test.go +++ b/pkg/api/dashboard_snapshot_test.go @@ -15,7 +15,7 @@ import ( "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/dashboards" - dashboardsnapshots "github.com/grafana/grafana/pkg/services/dashboardsnapshots/service" + "github.com/grafana/grafana/pkg/services/dashboardsnapshots" "github.com/grafana/grafana/pkg/services/guardian" "github.com/grafana/grafana/pkg/services/sqlstore/mockstore" ) @@ -29,42 +29,52 @@ func TestDashboardSnapshotAPIEndpoint_singleSnapshot(t *testing.T) { return s } + sqlmock := mockstore.NewSQLStoreMock() + sqlmock.ExpectedTeamsByUser = []*models.TeamDTO{} jsonModel, err := simplejson.NewJson([]byte(`{"id":100}`)) require.NoError(t, err) - sqlmock := mockstore.NewSQLStoreMock() - dashSvc := &dashboards.FakeDashboardService{} - dashSvc.On("GetDashboardAclInfoList", mock.Anything, mock.AnythingOfType("*models.GetDashboardAclInfoListQuery")).Return(nil) - dashSnapSvc := dashboardsnapshots.ProvideService(sqlmock, nil) - hs := &HTTPServer{dashboardsnapshotsService: dashSnapSvc} - - setUpSnapshotTest := func(t *testing.T) *models.DashboardSnapshot { + setUpSnapshotTest := func(t *testing.T, userId int64, deleteUrl string) dashboardsnapshots.Service { t.Helper() - mockSnapshotResult := &models.DashboardSnapshot{ - Id: 1, - Key: "12345", - DeleteKey: "54321", - Dashboard: jsonModel, - Expires: time.Now().Add(time.Duration(1000) * time.Second), - UserId: 999999, - External: true, - } - sqlmock.ExpectedDashboardSnapshot = mockSnapshotResult - sqlmock.ExpectedTeamsByUser = []*models.TeamDTO{} - return mockSnapshotResult + dashSnapSvc := dashboardsnapshots.NewMockService(t) + dashSnapSvc.On("DeleteDashboardSnapshot", mock.Anything, mock.AnythingOfType("*dashboardsnapshots.DeleteDashboardSnapshotCommand")).Return(nil).Maybe() + dashSnapSvc.On("GetDashboardSnapshot", mock.Anything, mock.AnythingOfType("*dashboardsnapshots.GetDashboardSnapshotQuery")).Run(func(args mock.Arguments) { + q := args.Get(1).(*dashboardsnapshots.GetDashboardSnapshotQuery) + res := &dashboardsnapshots.DashboardSnapshot{ + Id: 1, + Key: "12345", + DeleteKey: "54321", + Dashboard: jsonModel, + Expires: time.Now().Add(time.Duration(1000) * time.Second), + UserId: 999999, + } + if userId != 0 { + res.UserId = userId + } + if deleteUrl != "" { + res.External = true + res.ExternalDeleteUrl = deleteUrl + } + q.Result = res + }).Return(nil) + dashSnapSvc.On("DeleteDashboardSnapshot", mock.Anything, mock.AnythingOfType("*dashboardsnapshots.DeleteDashboardSnapshotCommand")).Return(nil).Maybe() + return dashSnapSvc } t.Run("When user has editor role and is not in the ACL", func(t *testing.T) { loggedInUserScenarioWithRole(t, "Should not be able to delete snapshot when calling DELETE on", "DELETE", "/api/snapshots/12345", "/api/snapshots/:key", models.ROLE_EDITOR, func(sc *scenarioContext) { var externalRequest *http.Request - mockSnapshotResult := setUpSnapshotTest(t) ts := setupRemoteServer(func(rw http.ResponseWriter, req *http.Request) { externalRequest = req }) - mockSnapshotResult.ExternalDeleteUrl = ts.URL + hs := &HTTPServer{dashboardsnapshotsService: setUpSnapshotTest(t, 0, ts.URL)} sc.handlerFunc = hs.DeleteDashboardSnapshot + + dashSvc := dashboards.NewFakeDashboardService(t) + dashSvc.On("GetDashboardAclInfoList", mock.Anything, mock.AnythingOfType("*models.GetDashboardAclInfoListQuery")).Return(nil).Maybe() + guardian.InitLegacyGuardian(sc.sqlStore, dashSvc) sc.fakeReqWithParams("DELETE", sc.url, map[string]string{"key": "12345"}).exec() @@ -76,15 +86,13 @@ func TestDashboardSnapshotAPIEndpoint_singleSnapshot(t *testing.T) { t.Run("When user is anonymous", func(t *testing.T) { anonymousUserScenario(t, "Should be able to delete a snapshot when calling GET on", "GET", "/api/snapshots-delete/12345", "/api/snapshots-delete/:deleteKey", func(sc *scenarioContext) { - mockSnapshotResult := setUpSnapshotTest(t) - var externalRequest *http.Request ts := setupRemoteServer(func(rw http.ResponseWriter, req *http.Request) { rw.WriteHeader(200) externalRequest = req }) + hs := &HTTPServer{dashboardsnapshotsService: setUpSnapshotTest(t, 0, ts.URL)} - mockSnapshotResult.ExternalDeleteUrl = ts.URL sc.handlerFunc = hs.DeleteDashboardSnapshotByDeleteKey sc.fakeReqWithParams("GET", sc.url, map[string]string{"deleteKey": "12345"}).exec() @@ -113,14 +121,13 @@ func TestDashboardSnapshotAPIEndpoint_singleSnapshot(t *testing.T) { loggedInUserScenarioWithRole(t, "Should be able to delete a snapshot when calling DELETE on", "DELETE", "/api/snapshots/12345", "/api/snapshots/:key", models.ROLE_EDITOR, func(sc *scenarioContext) { - mockSnapshotResult := setUpSnapshotTest(t) guardian.InitLegacyGuardian(sc.sqlStore, dashSvc) var externalRequest *http.Request ts := setupRemoteServer(func(rw http.ResponseWriter, req *http.Request) { rw.WriteHeader(200) externalRequest = req }) - mockSnapshotResult.ExternalDeleteUrl = ts.URL + hs := &HTTPServer{dashboardsnapshotsService: setUpSnapshotTest(t, 0, ts.URL)} sc.handlerFunc = hs.DeleteDashboardSnapshot sc.fakeReqWithParams("DELETE", sc.url, map[string]string{"key": "12345"}).exec() @@ -138,9 +145,8 @@ func TestDashboardSnapshotAPIEndpoint_singleSnapshot(t *testing.T) { t.Run("When user is editor and creator of the snapshot", func(t *testing.T) { loggedInUserScenarioWithRole(t, "Should be able to delete a snapshot when calling DELETE on", "DELETE", "/api/snapshots/12345", "/api/snapshots/:key", models.ROLE_EDITOR, func(sc *scenarioContext) { - mockSnapshotResult := setUpSnapshotTest(t) - mockSnapshotResult.UserId = testUserID - mockSnapshotResult.External = false + d := setUpSnapshotTest(t, testUserID, "") + hs := &HTTPServer{dashboardsnapshotsService: d} sc.handlerFunc = hs.DeleteDashboardSnapshot sc.fakeReqWithParams("DELETE", sc.url, map[string]string{"key": "12345"}).exec() @@ -158,16 +164,12 @@ func TestDashboardSnapshotAPIEndpoint_singleSnapshot(t *testing.T) { loggedInUserScenarioWithRole(t, "Should gracefully delete local snapshot when remote snapshot has already been removed when calling DELETE on", "DELETE", "/api/snapshots/12345", "/api/snapshots/:key", models.ROLE_EDITOR, func(sc *scenarioContext) { - mockSnapshotResult := setUpSnapshotTest(t) - mockSnapshotResult.UserId = testUserID - var writeErr error ts := setupRemoteServer(func(rw http.ResponseWriter, req *http.Request) { rw.WriteHeader(500) _, writeErr = rw.Write([]byte(`{"message":"Failed to get dashboard snapshot"}`)) }) - - mockSnapshotResult.ExternalDeleteUrl = ts.URL + hs := &HTTPServer{dashboardsnapshotsService: setUpSnapshotTest(t, testUserID, ts.URL)} sc.handlerFunc = hs.DeleteDashboardSnapshot sc.fakeReqWithParams("DELETE", sc.url, map[string]string{"key": "12345"}).exec() @@ -183,17 +185,12 @@ func TestDashboardSnapshotAPIEndpoint_singleSnapshot(t *testing.T) { loggedInUserScenarioWithRole(t, "Should fail to delete local snapshot when an unexpected 500 error occurs when calling DELETE on", "DELETE", "/api/snapshots/12345", "/api/snapshots/:key", models.ROLE_EDITOR, func(sc *scenarioContext) { - mockSnapshotResult := setUpSnapshotTest(t) - mockSnapshotResult.UserId = testUserID - var writeErr error ts := setupRemoteServer(func(rw http.ResponseWriter, req *http.Request) { rw.WriteHeader(500) _, writeErr = rw.Write([]byte(`{"message":"Unexpected"}`)) }) - - t.Log("Setting external delete URL", "url", ts.URL) - mockSnapshotResult.ExternalDeleteUrl = ts.URL + hs := &HTTPServer{dashboardsnapshotsService: setUpSnapshotTest(t, testUserID, ts.URL)} sc.handlerFunc = hs.DeleteDashboardSnapshot sc.fakeReqWithParams("DELETE", sc.url, map[string]string{"key": "12345"}).exec() @@ -204,14 +201,10 @@ func TestDashboardSnapshotAPIEndpoint_singleSnapshot(t *testing.T) { loggedInUserScenarioWithRole(t, "Should fail to delete local snapshot when an unexpected remote error occurs when calling DELETE on", "DELETE", "/api/snapshots/12345", "/api/snapshots/:key", models.ROLE_EDITOR, func(sc *scenarioContext) { - mockSnapshotResult := setUpSnapshotTest(t) - mockSnapshotResult.UserId = testUserID - ts := setupRemoteServer(func(rw http.ResponseWriter, req *http.Request) { rw.WriteHeader(404) }) - - mockSnapshotResult.ExternalDeleteUrl = ts.URL + hs := &HTTPServer{dashboardsnapshotsService: setUpSnapshotTest(t, testUserID, ts.URL)} sc.handlerFunc = hs.DeleteDashboardSnapshot sc.fakeReqWithParams("DELETE", sc.url, map[string]string{"key": "12345"}).exec() @@ -220,8 +213,7 @@ func TestDashboardSnapshotAPIEndpoint_singleSnapshot(t *testing.T) { loggedInUserScenarioWithRole(t, "Should be able to read a snapshot's unencrypted data when calling GET on", "GET", "/api/snapshots/12345", "/api/snapshots/:key", models.ROLE_EDITOR, func(sc *scenarioContext) { - setUpSnapshotTest(t) - + hs := &HTTPServer{dashboardsnapshotsService: setUpSnapshotTest(t, 0, "")} sc.handlerFunc = hs.GetDashboardSnapshot sc.fakeReqWithParams("GET", sc.url, map[string]string{"key": "12345"}).exec() diff --git a/pkg/api/docs/definitions/snapshot.go b/pkg/api/docs/definitions/snapshot.go index 95d78e1ce80..62cd890fc3a 100644 --- a/pkg/api/docs/definitions/snapshot.go +++ b/pkg/api/docs/definitions/snapshot.go @@ -1,7 +1,7 @@ package definitions import ( - "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/dashboardsnapshots" ) // swagger:route POST /snapshots snapshots createSnapshot @@ -68,7 +68,7 @@ import ( type CreateSnapshotParams struct { // in:body // required:true - Body models.CreateDashboardSnapshotCommand `json:"body"` + Body dashboardsnapshots.CreateDashboardSnapshotCommand `json:"body"` } // swagger:parameters getSnapshots @@ -118,7 +118,7 @@ type CreateSnapshotResponse struct { // swagger:response getSnapshotsResponse type GetSnapshotsResponse struct { // in:body - Body []*models.DashboardSnapshotDTO `json:"body"` + Body []*dashboardsnapshots.DashboardSnapshotDTO `json:"body"` } // swagger:response snapshotResponse diff --git a/pkg/services/cleanup/cleanup.go b/pkg/services/cleanup/cleanup.go index 6a9d9ab3f40..a495c902bf3 100644 --- a/pkg/services/cleanup/cleanup.go +++ b/pkg/services/cleanup/cleanup.go @@ -139,7 +139,7 @@ func (srv *CleanUpService) shouldCleanupTempFile(filemtime time.Time, now time.T } func (srv *CleanUpService) deleteExpiredSnapshots(ctx context.Context) { - cmd := models.DeleteExpiredSnapshotsCommand{} + cmd := dashboardsnapshots.DeleteExpiredSnapshotsCommand{} if err := srv.dashboardSnapshotService.DeleteExpiredSnapshots(ctx, &cmd); err != nil { srv.log.Error("Failed to delete expired snapshots", "error", err.Error()) } else { diff --git a/pkg/services/dashboardsnapshots/database/database.go b/pkg/services/dashboardsnapshots/database/database.go index 89b44438324..8732802d737 100644 --- a/pkg/services/dashboardsnapshots/database/database.go +++ b/pkg/services/dashboardsnapshots/database/database.go @@ -28,7 +28,7 @@ func ProvideStore(db db.DB) *DashboardSnapshotStore { // DeleteExpiredSnapshots removes snapshots with old expiry dates. // SnapShotRemoveExpired is deprecated and should be removed in the future. // Snapshot expiry is decided by the user when they share the snapshot. -func (d *DashboardSnapshotStore) DeleteExpiredSnapshots(ctx context.Context, cmd *models.DeleteExpiredSnapshotsCommand) error { +func (d *DashboardSnapshotStore) DeleteExpiredSnapshots(ctx context.Context, cmd *dashboardsnapshots.DeleteExpiredSnapshotsCommand) error { return d.store.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error { if !setting.SnapShotRemoveExpired { d.log.Warn("[Deprecated] The snapshot_remove_expired setting is outdated. Please remove from your config.") @@ -46,15 +46,14 @@ func (d *DashboardSnapshotStore) DeleteExpiredSnapshots(ctx context.Context, cmd }) } -func (d *DashboardSnapshotStore) CreateDashboardSnapshot(ctx context.Context, cmd *models.CreateDashboardSnapshotCommand) error { +func (d *DashboardSnapshotStore) CreateDashboardSnapshot(ctx context.Context, cmd *dashboardsnapshots.CreateDashboardSnapshotCommand) error { return d.store.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error { - // never var expires = time.Now().Add(time.Hour * 24 * 365 * 50) if cmd.Expires > 0 { expires = time.Now().Add(time.Second * time.Duration(cmd.Expires)) } - snapshot := &models.DashboardSnapshot{ + snapshot := &dashboardsnapshots.DashboardSnapshot{ Name: cmd.Name, Key: cmd.Key, DeleteKey: cmd.DeleteKey, @@ -76,7 +75,7 @@ func (d *DashboardSnapshotStore) CreateDashboardSnapshot(ctx context.Context, cm }) } -func (d *DashboardSnapshotStore) DeleteDashboardSnapshot(ctx context.Context, cmd *models.DeleteDashboardSnapshotCommand) error { +func (d *DashboardSnapshotStore) DeleteDashboardSnapshot(ctx context.Context, cmd *dashboardsnapshots.DeleteDashboardSnapshotCommand) error { return d.store.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error { var rawSQL = "DELETE FROM dashboard_snapshot WHERE delete_key=?" _, err := sess.Exec(rawSQL, cmd.DeleteKey) @@ -84,10 +83,10 @@ func (d *DashboardSnapshotStore) DeleteDashboardSnapshot(ctx context.Context, cm }) } -func (d *DashboardSnapshotStore) GetDashboardSnapshot(ctx context.Context, query *models.GetDashboardSnapshotQuery) error { - return d.store.WithDbSession(ctx, func(dbSess *sqlstore.DBSession) error { - snapshot := models.DashboardSnapshot{Key: query.Key, DeleteKey: query.DeleteKey} - has, err := dbSess.Get(&snapshot) +func (d *DashboardSnapshotStore) GetDashboardSnapshot(ctx context.Context, query *dashboardsnapshots.GetDashboardSnapshotQuery) error { + return d.store.WithDbSession(ctx, func(sess *sqlstore.DBSession) error { + snapshot := dashboardsnapshots.DashboardSnapshot{Key: query.Key, DeleteKey: query.DeleteKey} + has, err := sess.Get(&snapshot) if err != nil { return err @@ -102,9 +101,9 @@ func (d *DashboardSnapshotStore) GetDashboardSnapshot(ctx context.Context, query // SearchDashboardSnapshots returns a list of all snapshots for admins // for other roles, it returns snapshots created by the user -func (d *DashboardSnapshotStore) SearchDashboardSnapshots(ctx context.Context, query *models.GetDashboardSnapshotsQuery) error { +func (d *DashboardSnapshotStore) SearchDashboardSnapshots(ctx context.Context, query *dashboardsnapshots.GetDashboardSnapshotsQuery) error { return d.store.WithDbSession(ctx, func(sess *sqlstore.DBSession) error { - var snapshots = make(models.DashboardSnapshotsList, 0) + var snapshots = make(dashboardsnapshots.DashboardSnapshotsList, 0) if query.Limit > 0 { sess.Limit(query.Limit) } diff --git a/pkg/services/dashboardsnapshots/database/database_test.go b/pkg/services/dashboardsnapshots/database/database_test.go index e4cd112ada7..bf1af16a1a5 100644 --- a/pkg/services/dashboardsnapshots/database/database_test.go +++ b/pkg/services/dashboardsnapshots/database/database_test.go @@ -10,6 +10,7 @@ import ( "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/dashboardsnapshots" "github.com/grafana/grafana/pkg/services/secrets" "github.com/grafana/grafana/pkg/services/secrets/fakes" "github.com/grafana/grafana/pkg/services/sqlstore" @@ -38,7 +39,7 @@ func TestIntegrationDashboardSnapshotDBAccess(t *testing.T) { encryptedDashboard, err := secretsService.Encrypt(context.Background(), rawDashboard, secrets.WithoutScope()) require.NoError(t, err) - cmd := models.CreateDashboardSnapshotCommand{ + cmd := dashboardsnapshots.CreateDashboardSnapshotCommand{ Key: "hej", DashboardEncrypted: encryptedDashboard, UserId: 1000, @@ -49,7 +50,7 @@ func TestIntegrationDashboardSnapshotDBAccess(t *testing.T) { require.NoError(t, err) t.Run("Should be able to get snapshot by key", func(t *testing.T) { - query := models.GetDashboardSnapshotQuery{Key: "hej"} + query := dashboardsnapshots.GetDashboardSnapshotQuery{Key: "hej"} err := dashStore.GetDashboardSnapshot(context.Background(), &query) require.NoError(t, err) @@ -68,7 +69,7 @@ func TestIntegrationDashboardSnapshotDBAccess(t *testing.T) { }) t.Run("And the user has the admin role", func(t *testing.T) { - query := models.GetDashboardSnapshotsQuery{ + query := dashboardsnapshots.GetDashboardSnapshotsQuery{ OrgId: 1, SignedInUser: &models.SignedInUser{OrgRole: models.ROLE_ADMIN}, } @@ -82,7 +83,7 @@ func TestIntegrationDashboardSnapshotDBAccess(t *testing.T) { }) t.Run("And the user has the editor role and has created a snapshot", func(t *testing.T) { - query := models.GetDashboardSnapshotsQuery{ + query := dashboardsnapshots.GetDashboardSnapshotsQuery{ OrgId: 1, SignedInUser: &models.SignedInUser{OrgRole: models.ROLE_EDITOR, UserId: 1000}, } @@ -96,7 +97,7 @@ func TestIntegrationDashboardSnapshotDBAccess(t *testing.T) { }) t.Run("And the user has the editor role and has not created any snapshot", func(t *testing.T) { - query := models.GetDashboardSnapshotsQuery{ + query := dashboardsnapshots.GetDashboardSnapshotsQuery{ OrgId: 1, SignedInUser: &models.SignedInUser{OrgRole: models.ROLE_EDITOR, UserId: 2}, } @@ -110,7 +111,7 @@ func TestIntegrationDashboardSnapshotDBAccess(t *testing.T) { }) t.Run("And the user is anonymous", func(t *testing.T) { - cmd := models.CreateDashboardSnapshotCommand{ + cmd := dashboardsnapshots.CreateDashboardSnapshotCommand{ Key: "strangesnapshotwithuserid0", DeleteKey: "adeletekey", Dashboard: simplejson.NewFromAny(map[string]interface{}{ @@ -123,7 +124,7 @@ func TestIntegrationDashboardSnapshotDBAccess(t *testing.T) { require.NoError(t, err) t.Run("Should not return any snapshots", func(t *testing.T) { - query := models.GetDashboardSnapshotsQuery{ + query := dashboardsnapshots.GetDashboardSnapshotsQuery{ OrgId: 1, SignedInUser: &models.SignedInUser{OrgRole: models.ROLE_EDITOR, IsAnonymous: true, UserId: 0}, } @@ -161,10 +162,10 @@ func TestIntegrationDeleteExpiredSnapshots(t *testing.T) { createTestSnapshot(t, dashStore, "key2", -1200) createTestSnapshot(t, dashStore, "key3", -1200) - err := dashStore.DeleteExpiredSnapshots(context.Background(), &models.DeleteExpiredSnapshotsCommand{}) + err := dashStore.DeleteExpiredSnapshots(context.Background(), &dashboardsnapshots.DeleteExpiredSnapshotsCommand{}) require.NoError(t, err) - query := models.GetDashboardSnapshotsQuery{ + query := dashboardsnapshots.GetDashboardSnapshotsQuery{ OrgId: 1, SignedInUser: &models.SignedInUser{OrgRole: models.ROLE_ADMIN}, } @@ -174,10 +175,10 @@ func TestIntegrationDeleteExpiredSnapshots(t *testing.T) { assert.Len(t, query.Result, 1) assert.Equal(t, nonExpiredSnapshot.Key, query.Result[0].Key) - err = dashStore.DeleteExpiredSnapshots(context.Background(), &models.DeleteExpiredSnapshotsCommand{}) + err = dashStore.DeleteExpiredSnapshots(context.Background(), &dashboardsnapshots.DeleteExpiredSnapshotsCommand{}) require.NoError(t, err) - query = models.GetDashboardSnapshotsQuery{ + query = dashboardsnapshots.GetDashboardSnapshotsQuery{ OrgId: 1, SignedInUser: &models.SignedInUser{OrgRole: models.ROLE_ADMIN}, } @@ -189,8 +190,8 @@ func TestIntegrationDeleteExpiredSnapshots(t *testing.T) { }) } -func createTestSnapshot(t *testing.T, dashStore *DashboardSnapshotStore, key string, expires int64) *models.DashboardSnapshot { - cmd := models.CreateDashboardSnapshotCommand{ +func createTestSnapshot(t *testing.T, dashStore *DashboardSnapshotStore, key string, expires int64) *dashboardsnapshots.DashboardSnapshot { + cmd := dashboardsnapshots.CreateDashboardSnapshotCommand{ Key: key, DeleteKey: "delete" + key, Dashboard: simplejson.NewFromAny(map[string]interface{}{ diff --git a/pkg/models/dashboard_snapshot.go b/pkg/services/dashboardsnapshots/models.go similarity index 96% rename from pkg/models/dashboard_snapshot.go rename to pkg/services/dashboardsnapshots/models.go index c86fe395d70..4feb21596ce 100644 --- a/pkg/models/dashboard_snapshot.go +++ b/pkg/services/dashboardsnapshots/models.go @@ -1,9 +1,10 @@ -package models +package dashboardsnapshots import ( "time" "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/models" ) // DashboardSnapshot model @@ -101,7 +102,7 @@ type GetDashboardSnapshotsQuery struct { Name string Limit int OrgId int64 - SignedInUser *SignedInUser + SignedInUser *models.SignedInUser Result DashboardSnapshotsList } diff --git a/pkg/services/dashboardsnapshots/service.go b/pkg/services/dashboardsnapshots/service.go index 5fc6f4eaf22..dd63c6476d9 100644 --- a/pkg/services/dashboardsnapshots/service.go +++ b/pkg/services/dashboardsnapshots/service.go @@ -2,14 +2,13 @@ package dashboardsnapshots import ( "context" - - "github.com/grafana/grafana/pkg/models" ) +//go:generate mockery --name Service --structname MockService --inpackage --filename service_mock.go type Service interface { - CreateDashboardSnapshot(context.Context, *models.CreateDashboardSnapshotCommand) error - DeleteDashboardSnapshot(context.Context, *models.DeleteDashboardSnapshotCommand) error - DeleteExpiredSnapshots(context.Context, *models.DeleteExpiredSnapshotsCommand) error - GetDashboardSnapshot(context.Context, *models.GetDashboardSnapshotQuery) error - SearchDashboardSnapshots(context.Context, *models.GetDashboardSnapshotsQuery) error + CreateDashboardSnapshot(context.Context, *CreateDashboardSnapshotCommand) error + DeleteDashboardSnapshot(context.Context, *DeleteDashboardSnapshotCommand) error + DeleteExpiredSnapshots(context.Context, *DeleteExpiredSnapshotsCommand) error + GetDashboardSnapshot(context.Context, *GetDashboardSnapshotQuery) error + SearchDashboardSnapshots(context.Context, *GetDashboardSnapshotsQuery) error } diff --git a/pkg/services/dashboardsnapshots/service/service.go b/pkg/services/dashboardsnapshots/service/service.go index a16d5665e81..4a8b26cae87 100644 --- a/pkg/services/dashboardsnapshots/service/service.go +++ b/pkg/services/dashboardsnapshots/service/service.go @@ -4,7 +4,6 @@ import ( "context" "github.com/grafana/grafana/pkg/components/simplejson" - "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/dashboardsnapshots" "github.com/grafana/grafana/pkg/services/secrets" ) @@ -26,7 +25,7 @@ func ProvideService(store dashboardsnapshots.Store, secretsService secrets.Servi return s } -func (s *ServiceImpl) CreateDashboardSnapshot(ctx context.Context, cmd *models.CreateDashboardSnapshotCommand) error { +func (s *ServiceImpl) CreateDashboardSnapshot(ctx context.Context, cmd *dashboardsnapshots.CreateDashboardSnapshotCommand) error { marshalledData, err := cmd.Dashboard.Encode() if err != nil { return err @@ -42,7 +41,7 @@ func (s *ServiceImpl) CreateDashboardSnapshot(ctx context.Context, cmd *models.C return s.store.CreateDashboardSnapshot(ctx, cmd) } -func (s *ServiceImpl) GetDashboardSnapshot(ctx context.Context, query *models.GetDashboardSnapshotQuery) error { +func (s *ServiceImpl) GetDashboardSnapshot(ctx context.Context, query *dashboardsnapshots.GetDashboardSnapshotQuery) error { err := s.store.GetDashboardSnapshot(ctx, query) if err != nil { return err @@ -65,14 +64,14 @@ func (s *ServiceImpl) GetDashboardSnapshot(ctx context.Context, query *models.Ge return err } -func (s *ServiceImpl) DeleteDashboardSnapshot(ctx context.Context, cmd *models.DeleteDashboardSnapshotCommand) error { +func (s *ServiceImpl) DeleteDashboardSnapshot(ctx context.Context, cmd *dashboardsnapshots.DeleteDashboardSnapshotCommand) error { return s.store.DeleteDashboardSnapshot(ctx, cmd) } -func (s *ServiceImpl) SearchDashboardSnapshots(ctx context.Context, query *models.GetDashboardSnapshotsQuery) error { +func (s *ServiceImpl) SearchDashboardSnapshots(ctx context.Context, query *dashboardsnapshots.GetDashboardSnapshotsQuery) error { return s.store.SearchDashboardSnapshots(ctx, query) } -func (s *ServiceImpl) DeleteExpiredSnapshots(ctx context.Context, cmd *models.DeleteExpiredSnapshotsCommand) error { +func (s *ServiceImpl) DeleteExpiredSnapshots(ctx context.Context, cmd *dashboardsnapshots.DeleteExpiredSnapshotsCommand) error { return s.store.DeleteExpiredSnapshots(ctx, cmd) } diff --git a/pkg/services/dashboardsnapshots/service/service_test.go b/pkg/services/dashboardsnapshots/service/service_test.go index ab9053bca12..58c5f589488 100644 --- a/pkg/services/dashboardsnapshots/service/service_test.go +++ b/pkg/services/dashboardsnapshots/service/service_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/require" "github.com/grafana/grafana/pkg/components/simplejson" - "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/dashboardsnapshots" dashsnapdb "github.com/grafana/grafana/pkg/services/dashboardsnapshots/database" "github.com/grafana/grafana/pkg/services/secrets/database" secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager" @@ -36,7 +36,7 @@ func TestDashboardSnapshotsService(t *testing.T) { t.Run("create dashboard snapshot should encrypt the dashboard", func(t *testing.T) { ctx := context.Background() - cmd := models.CreateDashboardSnapshotCommand{ + cmd := dashboardsnapshots.CreateDashboardSnapshotCommand{ Key: dashboardKey, DeleteKey: dashboardKey, Dashboard: dashboard, @@ -54,7 +54,7 @@ func TestDashboardSnapshotsService(t *testing.T) { t.Run("get dashboard snapshot should return the dashboard decrypted", func(t *testing.T) { ctx := context.Background() - query := models.GetDashboardSnapshotQuery{ + query := dashboardsnapshots.GetDashboardSnapshotQuery{ Key: dashboardKey, DeleteKey: dashboardKey, } diff --git a/pkg/services/dashboardsnapshots/service_mock.go b/pkg/services/dashboardsnapshots/service_mock.go new file mode 100644 index 00000000000..efca62367bf --- /dev/null +++ b/pkg/services/dashboardsnapshots/service_mock.go @@ -0,0 +1,95 @@ +// Code generated by mockery v2.12.2. DO NOT EDIT. + +package dashboardsnapshots + +import ( + context "context" + testing "testing" + + mock "github.com/stretchr/testify/mock" +) + +// MockService is an autogenerated mock type for the Service type +type MockService struct { + mock.Mock +} + +// CreateDashboardSnapshot provides a mock function with given fields: _a0, _a1 +func (_m *MockService) CreateDashboardSnapshot(_a0 context.Context, _a1 *CreateDashboardSnapshotCommand) error { + ret := _m.Called(_a0, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *CreateDashboardSnapshotCommand) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DeleteDashboardSnapshot provides a mock function with given fields: _a0, _a1 +func (_m *MockService) DeleteDashboardSnapshot(_a0 context.Context, _a1 *DeleteDashboardSnapshotCommand) error { + ret := _m.Called(_a0, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *DeleteDashboardSnapshotCommand) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DeleteExpiredSnapshots provides a mock function with given fields: _a0, _a1 +func (_m *MockService) DeleteExpiredSnapshots(_a0 context.Context, _a1 *DeleteExpiredSnapshotsCommand) error { + ret := _m.Called(_a0, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *DeleteExpiredSnapshotsCommand) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// GetDashboardSnapshot provides a mock function with given fields: _a0, _a1 +func (_m *MockService) GetDashboardSnapshot(_a0 context.Context, _a1 *GetDashboardSnapshotQuery) error { + ret := _m.Called(_a0, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *GetDashboardSnapshotQuery) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// SearchDashboardSnapshots provides a mock function with given fields: _a0, _a1 +func (_m *MockService) SearchDashboardSnapshots(_a0 context.Context, _a1 *GetDashboardSnapshotsQuery) error { + ret := _m.Called(_a0, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *GetDashboardSnapshotsQuery) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// NewMockService creates a new instance of MockService. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations. +func NewMockService(t testing.TB) *MockService { + mock := &MockService{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/services/dashboardsnapshots/store.go b/pkg/services/dashboardsnapshots/store.go index ca2144cba56..392c21f795d 100644 --- a/pkg/services/dashboardsnapshots/store.go +++ b/pkg/services/dashboardsnapshots/store.go @@ -2,14 +2,12 @@ package dashboardsnapshots import ( "context" - - "github.com/grafana/grafana/pkg/models" ) type Store interface { - CreateDashboardSnapshot(context.Context, *models.CreateDashboardSnapshotCommand) error - DeleteDashboardSnapshot(context.Context, *models.DeleteDashboardSnapshotCommand) error - DeleteExpiredSnapshots(context.Context, *models.DeleteExpiredSnapshotsCommand) error - GetDashboardSnapshot(context.Context, *models.GetDashboardSnapshotQuery) error - SearchDashboardSnapshots(context.Context, *models.GetDashboardSnapshotsQuery) error + CreateDashboardSnapshot(context.Context, *CreateDashboardSnapshotCommand) error + DeleteDashboardSnapshot(context.Context, *DeleteDashboardSnapshotCommand) error + DeleteExpiredSnapshots(context.Context, *DeleteExpiredSnapshotsCommand) error + GetDashboardSnapshot(context.Context, *GetDashboardSnapshotQuery) error + SearchDashboardSnapshots(context.Context, *GetDashboardSnapshotsQuery) error } diff --git a/pkg/services/sqlstore/mockstore/mockstore.go b/pkg/services/sqlstore/mockstore/mockstore.go index e68bc681ff5..e29509e5af2 100644 --- a/pkg/services/sqlstore/mockstore/mockstore.go +++ b/pkg/services/sqlstore/mockstore/mockstore.go @@ -24,7 +24,6 @@ type SQLStoreMock struct { ExpectedDashboardAclInfoList []*models.DashboardAclInfoDTO ExpectedUserOrgList []*models.UserOrgDTO ExpectedOrgListResponse OrgListResponse - ExpectedDashboardSnapshot *models.DashboardSnapshot ExpectedTeamsByUser []*models.TeamDTO ExpectedSearchOrgList []*models.OrgDTO ExpectedSearchUsers models.SearchUserQueryResult @@ -73,31 +72,10 @@ func (m *SQLStoreMock) GetSystemStats(ctx context.Context, query *models.GetSyst return m.ExpectedError } -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 { - return m.ExpectedError -} - -func (m *SQLStoreMock) DeleteDashboardSnapshot(ctx context.Context, cmd *models.DeleteDashboardSnapshotCommand) error { - return m.ExpectedError -} - -func (m *SQLStoreMock) GetDashboardSnapshot(ctx context.Context, query *models.GetDashboardSnapshotQuery) error { - query.Result = m.ExpectedDashboardSnapshot - return m.ExpectedError -} - func (m *SQLStoreMock) HasEditPermissionInFolders(ctx context.Context, query *models.HasEditPermissionInFoldersQuery) error { return m.ExpectedError } -func (m *SQLStoreMock) SearchDashboardSnapshots(ctx context.Context, query *models.GetDashboardSnapshotsQuery) error { - return m.ExpectedError -} - func (m *SQLStoreMock) GetOrgById(ctx context.Context, cmd *models.GetOrgByIdQuery) error { return m.ExpectedError }