diff --git a/pkg/services/dashboards/database/database.go b/pkg/services/dashboards/database/database.go index 734a0cbcdc8..016cf4afcb3 100644 --- a/pkg/services/dashboards/database/database.go +++ b/pkg/services/dashboards/database/database.go @@ -715,6 +715,7 @@ func (d *DashboardStore) deleteDashboard(cmd *models.DeleteDashboardCommand, ses deletes := []string{ "DELETE FROM dashboard_tag WHERE dashboard_id = ? ", "DELETE FROM star WHERE dashboard_id = ? ", + "DELETE FROM dashboard_public WHERE dashboard_uid = (SELECT uid FROM dashboard WHERE id = ?)", "DELETE FROM dashboard WHERE id = ?", "DELETE FROM playlist_item WHERE type = 'dashboard_by_id' AND value = ?", "DELETE FROM dashboard_version WHERE dashboard_id = ?", @@ -763,6 +764,7 @@ func (d *DashboardStore) deleteDashboard(cmd *models.DeleteDashboardCommand, ses "DELETE FROM annotation WHERE dashboard_id IN (SELECT id FROM dashboard WHERE org_id = ? AND folder_id = ?)", "DELETE FROM dashboard_provisioning WHERE dashboard_id IN (SELECT id FROM dashboard WHERE org_id = ? AND folder_id = ?)", "DELETE FROM dashboard_acl WHERE dashboard_id IN (SELECT id FROM dashboard WHERE org_id = ? AND folder_id = ?)", + "DELETE FROM dashboard_public WHERE dashboard_uid IN (SELECT uid FROM dashboard WHERE org_id = ? AND folder_id = ?)", } for _, sql := range childrenDeletes { _, err := sess.Exec(sql, dashboard.OrgId, dashboard.Id) diff --git a/pkg/services/dashboards/database/database_test.go b/pkg/services/dashboards/database/database_test.go index 6ec292b2946..9f001c106b7 100644 --- a/pkg/services/dashboards/database/database_test.go +++ b/pkg/services/dashboards/database/database_test.go @@ -16,6 +16,8 @@ import ( "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/org" + "github.com/grafana/grafana/pkg/services/publicdashboards/database" + publicDashboardModels "github.com/grafana/grafana/pkg/services/publicdashboards/models" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore/searchstore" "github.com/grafana/grafana/pkg/services/star" @@ -34,6 +36,7 @@ func TestIntegrationDashboardDataAccess(t *testing.T) { var savedFolder, savedDash, savedDash2 *models.Dashboard var dashboardStore *DashboardStore var starService star.Service + var publicDashboardStore *database.PublicDashboardStoreImpl setup := func() { sqlStore, cfg = db.InitTestDBwithCfg(t) @@ -44,6 +47,8 @@ func TestIntegrationDashboardDataAccess(t *testing.T) { insertTestDashboard(t, dashboardStore, "test dash 45", 1, savedFolder.Id, false, "prod") savedDash2 = insertTestDashboard(t, dashboardStore, "test dash 67", 1, 0, false, "prod") insertTestRule(t, sqlStore, savedFolder.OrgId, savedFolder.Uid) + + publicDashboardStore = database.ProvideStore(sqlStore) } t.Run("Should return dashboard model", func(t *testing.T) { @@ -235,6 +240,78 @@ func TestIntegrationDashboardDataAccess(t *testing.T) { require.True(t, errors.Is(err, dashboards.ErrFolderContainsAlertRules)) }) + t.Run("Should be able to delete dashboard and related public dashboard", func(t *testing.T) { + setup() + + uid, _ := publicDashboardStore.GenerateNewPublicDashboardUid(context.Background()) + cmd := publicDashboardModels.SavePublicDashboardConfigCommand{ + PublicDashboard: publicDashboardModels.PublicDashboard{ + Uid: uid, + DashboardUid: savedDash.Uid, + OrgId: savedDash.OrgId, + IsEnabled: true, + TimeSettings: &publicDashboardModels.TimeSettings{}, + CreatedBy: 1, + CreatedAt: time.Now(), + AccessToken: "an-access-token", + }, + } + err := publicDashboardStore.SavePublicDashboardConfig(context.Background(), cmd) + require.NoError(t, err) + pubdashConfig, _, _ := publicDashboardStore.GetPublicDashboard(context.Background(), "an-access-token") + require.NotNil(t, pubdashConfig) + + deleteCmd := &models.DeleteDashboardCommand{Id: savedDash.Id, OrgId: savedDash.OrgId} + err = dashboardStore.DeleteDashboard(context.Background(), deleteCmd) + require.NoError(t, err) + + query := models.GetDashboardQuery{Uid: savedDash.Uid, OrgId: savedDash.OrgId} + dash, getErr := dashboardStore.GetDashboard(context.Background(), &query) + require.Equal(t, getErr, dashboards.ErrDashboardNotFound) + assert.Nil(t, dash) + + pubdashConfig, _, err = publicDashboardStore.GetPublicDashboard(context.Background(), "an-access-token") + require.Equal(t, err, publicDashboardModels.ErrPublicDashboardNotFound) + require.Nil(t, pubdashConfig) + }) + + t.Run("Should be able to delete a dashboard folder, with its dashboard and related public dashboard", func(t *testing.T) { + setup() + + uid, _ := publicDashboardStore.GenerateNewPublicDashboardUid(context.Background()) + cmd := publicDashboardModels.SavePublicDashboardConfigCommand{ + PublicDashboard: publicDashboardModels.PublicDashboard{ + Uid: uid, + DashboardUid: savedDash.Uid, + OrgId: savedDash.OrgId, + IsEnabled: true, + TimeSettings: &publicDashboardModels.TimeSettings{}, + CreatedBy: 1, + CreatedAt: time.Now(), + AccessToken: "an-access-token", + }, + } + err := publicDashboardStore.SavePublicDashboardConfig(context.Background(), cmd) + require.NoError(t, err) + pubdashConfig, _, _ := publicDashboardStore.GetPublicDashboard(context.Background(), "an-access-token") + require.NotNil(t, pubdashConfig) + + deleteCmd := &models.DeleteDashboardCommand{Id: savedFolder.Id, ForceDeleteFolderRules: true} + err = dashboardStore.DeleteDashboard(context.Background(), deleteCmd) + require.NoError(t, err) + + query := models.GetDashboardsQuery{ + DashboardIds: []int64{savedFolder.Id, savedDash.Id}, + } + err = dashboardStore.GetDashboards(context.Background(), &query) + require.NoError(t, err) + require.Equal(t, len(query.Result), 0) + + pubdashConfig, _, err = publicDashboardStore.GetPublicDashboard(context.Background(), "an-access-token") + require.Equal(t, err, publicDashboardModels.ErrPublicDashboardNotFound) + require.Nil(t, pubdashConfig) + }) + t.Run("Should be able to delete a dashboard folder and its children if force delete rules is enabled", func(t *testing.T) { setup() deleteCmd := &models.DeleteDashboardCommand{Id: savedFolder.Id, ForceDeleteFolderRules: true}