From f0421ed08ea9bde31bd11c44ef15ded87f30474f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agn=C3=A8s=20Toulet?= <35176601+AgnesToulet@users.noreply.github.com> Date: Fri, 6 Nov 2020 09:02:31 +0100 Subject: [PATCH] Dashboards / Folders: delete related data (permissions, stars, tags, versions, annotations) when deleting a dashboard or a folder (#28826) * Dashboard: delete related data when deleting a dashboard or a folder * fix migrations order * apply PR feedback --- pkg/services/sqlstore/dashboard.go | 22 ++++++++++++++++--- pkg/services/sqlstore/dashboard_test.go | 8 +++++++ .../sqlstore/migrations/dashboard_acl.go | 3 +++ .../sqlstore/migrations/dashboard_mig.go | 6 +++++ 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/pkg/services/sqlstore/dashboard.go b/pkg/services/sqlstore/dashboard.go index d3b71d5ff83..1215936bbf8 100644 --- a/pkg/services/sqlstore/dashboard.go +++ b/pkg/services/sqlstore/dashboard.go @@ -374,16 +374,16 @@ func deleteDashboard(cmd *models.DeleteDashboardCommand, sess *DBSession) error "DELETE FROM dashboard_version WHERE dashboard_id = ?", "DELETE FROM annotation WHERE dashboard_id = ?", "DELETE FROM dashboard_provisioning WHERE dashboard_id = ?", + "DELETE FROM dashboard_acl WHERE dashboard_id = ?", } if dashboard.IsFolder { - deletes = append(deletes, "DELETE FROM dashboard_provisioning WHERE dashboard_id in (select id from dashboard where folder_id = ?)") deletes = append(deletes, "DELETE FROM dashboard WHERE folder_id = ?") dashIds := []struct { Id int64 }{} - err := sess.SQL("select id from dashboard where folder_id = ?", dashboard.Id).Find(&dashIds) + err := sess.SQL("SELECT id FROM dashboard WHERE folder_id = ?", dashboard.Id).Find(&dashIds) if err != nil { return err } @@ -393,6 +393,23 @@ func deleteDashboard(cmd *models.DeleteDashboardCommand, sess *DBSession) error return err } } + + if len(dashIds) > 0 { + childrenDeletes := []string{ + "DELETE FROM dashboard_tag WHERE dashboard_id IN (SELECT id FROM dashboard WHERE org_id = ? AND folder_id = ?)", + "DELETE FROM star WHERE dashboard_id IN (SELECT id FROM dashboard WHERE org_id = ? AND folder_id = ?)", + "DELETE FROM dashboard_version WHERE dashboard_id IN (SELECT id FROM dashboard WHERE org_id = ? AND folder_id = ?)", + "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 = ?)", + } + for _, sql := range childrenDeletes { + _, err := sess.Exec(sql, dashboard.OrgId, dashboard.Id) + if err != nil { + return err + } + } + } } if err := deleteAlertDefinition(dashboard.Id, sess); err != nil { @@ -401,7 +418,6 @@ func deleteDashboard(cmd *models.DeleteDashboardCommand, sess *DBSession) error for _, sql := range deletes { _, err := sess.Exec(sql, dashboard.Id) - if err != nil { return err } diff --git a/pkg/services/sqlstore/dashboard_test.go b/pkg/services/sqlstore/dashboard_test.go index c448cc8e281..99467814287 100644 --- a/pkg/services/sqlstore/dashboard_test.go +++ b/pkg/services/sqlstore/dashboard_test.go @@ -201,6 +201,14 @@ func TestDashboardDataAccess(t *testing.T) { So(query.Result.Updated.IsZero(), ShouldBeFalse) }) + Convey("Should be able to delete empty folder", func() { + emptyFolder := insertTestDashboard("2 test dash folder", 1, 0, true, "prod", "webapp") + + deleteCmd := &models.DeleteDashboardCommand{Id: emptyFolder.Id} + err := DeleteDashboard(deleteCmd) + So(err, ShouldBeNil) + }) + Convey("Should be able to delete a dashboard folder and its children", func() { deleteCmd := &models.DeleteDashboardCommand{Id: savedFolder.Id} err := DeleteDashboard(deleteCmd) diff --git a/pkg/services/sqlstore/migrations/dashboard_acl.go b/pkg/services/sqlstore/migrations/dashboard_acl.go index 32e4aec6d4a..983191c04d1 100644 --- a/pkg/services/sqlstore/migrations/dashboard_acl.go +++ b/pkg/services/sqlstore/migrations/dashboard_acl.go @@ -46,4 +46,7 @@ INSERT INTO dashboard_acl ` mg.AddMigration("save default acl rules in dashboard_acl table", NewRawSqlMigration(rawSQL)) + + mg.AddMigration("delete acl rules for deleted dashboards and folders", NewRawSqlMigration( + "DELETE FROM dashboard_acl WHERE dashboard_id NOT IN (SELECT id FROM dashboard) AND dashboard_id != -1")) } diff --git a/pkg/services/sqlstore/migrations/dashboard_mig.go b/pkg/services/sqlstore/migrations/dashboard_mig.go index 6af020770ab..03d4c016975 100644 --- a/pkg/services/sqlstore/migrations/dashboard_mig.go +++ b/pkg/services/sqlstore/migrations/dashboard_mig.go @@ -219,4 +219,10 @@ func addDashboardMigration(mg *Migrator) { Cols: []string{"title"}, Type: IndexType, })) + + mg.AddMigration("delete tags for deleted dashboards", NewRawSqlMigration( + "DELETE FROM dashboard_tag WHERE dashboard_id NOT IN (SELECT id FROM dashboard)")) + + mg.AddMigration("delete stars for deleted dashboards", NewRawSqlMigration( + "DELETE FROM star WHERE dashboard_id NOT IN (SELECT id FROM dashboard)")) }