Update logic for create/update dashboard, validation and plugin dashboard links (#10809)

* enables overwrite if dashboard allready exist in folder

* dashboard: Don't allow creating a folder named General

* dashboards: update logic for save/update dashboard

No id and uid creates a new dashboard/folder.
No id and uid, with an existing title in folder allows overwrite
  of dashboard.
Id without uid, allows update of existing dashboard/folder without
  overwrite.
Uid without id allows update of existing dashboard/folder without
  overwrite.
Id without uid, with an existing title in folder allows overwrite
  of dashboard/folder and updated will have the uid of overwritten.
Uid without id, with an existing title in folder allows overwrite
  of dashboard/folder and new will have the same uid as provided.
Trying to change an existing folder to a dashboard yields error.
Trying to change an existing dashboard to a folder yields error.

* dashboards: include folder id when confirmed to save with overwrite

* dashboards: fixes due to new url structure

Return importedUrl property in response to importing dashboards and
getting plugin dashboards and use this for redirects/links in the
frontend.
This commit is contained in:
Marcus Efraimsson
2018-02-08 12:48:38 +01:00
committed by Torkel Ödegaard
parent fc05fc42c9
commit 0e8377a9f4
10 changed files with 520 additions and 336 deletions
+90 -59
View File
@@ -32,47 +32,36 @@ func SaveDashboard(cmd *m.SaveDashboardCommand) error {
return inTransaction(func(sess *DBSession) error {
dash := cmd.GetDashboardModel()
// try get existing dashboard
var existing m.Dashboard
if err := getExistingDashboardForUpdate(sess, dash, cmd); err != nil {
return err
}
if dash.Id != 0 {
dashWithIdExists, err := sess.Where("id=? AND org_id=?", dash.Id, dash.OrgId).Get(&existing)
if err != nil {
return err
}
if !dashWithIdExists {
return m.ErrDashboardNotFound
}
var existingByTitleAndFolder m.Dashboard
// check for is someone else has written in between
if dash.Version != existing.Version {
if cmd.Overwrite {
dash.Version = existing.Version
} else {
return m.ErrDashboardVersionMismatch
dashWithTitleAndFolderExists, err := sess.Where("org_id=? AND slug=? AND (is_folder=? OR folder_id=?)", dash.OrgId, dash.Slug, dialect.BooleanStr(true), dash.FolderId).Get(&existingByTitleAndFolder)
if err != nil {
return err
}
if dashWithTitleAndFolderExists {
if dash.Id != existingByTitleAndFolder.Id {
if existingByTitleAndFolder.IsFolder && !cmd.IsFolder {
return m.ErrDashboardWithSameNameAsFolder
}
}
// do not allow plugin dashboard updates without overwrite flag
if existing.PluginId != "" && cmd.Overwrite == false {
return m.UpdatePluginDashboardError{PluginId: existing.PluginId}
}
} else if dash.Uid != "" {
var sameUid m.Dashboard
sameUidExists, err := sess.Where("org_id=? AND uid=?", dash.OrgId, dash.Uid).Get(&sameUid)
if err != nil {
return err
}
if !existingByTitleAndFolder.IsFolder && cmd.IsFolder {
return m.ErrDashboardFolderWithSameNameAsDashboard
}
if sameUidExists {
// another dashboard with same uid
if dash.Id != sameUid.Id {
if cmd.Overwrite {
dash.Id = sameUid.Id
dash.Version = sameUid.Version
} else {
return m.ErrDashboardWithSameUIDExists
if cmd.Overwrite {
dash.Id = existingByTitleAndFolder.Id
dash.Version = existingByTitleAndFolder.Version
if dash.Uid == "" {
dash.Uid = existingByTitleAndFolder.Uid
}
} else {
return m.ErrDashboardWithSameNameInFolderExists
}
}
}
@@ -86,11 +75,6 @@ func SaveDashboard(cmd *m.SaveDashboardCommand) error {
dash.Data.Set("uid", uid)
}
err := guaranteeDashboardNameIsUniqueInFolder(sess, dash)
if err != nil {
return err
}
err = setHasAcl(sess, dash)
if err != nil {
return err
@@ -162,6 +146,72 @@ func SaveDashboard(cmd *m.SaveDashboardCommand) error {
})
}
func getExistingDashboardForUpdate(sess *DBSession, dash *m.Dashboard, cmd *m.SaveDashboardCommand) (err error) {
dashWithIdExists := false
var existingById m.Dashboard
if dash.Id > 0 {
dashWithIdExists, err = sess.Where("id=? AND org_id=?", dash.Id, dash.OrgId).Get(&existingById)
if err != nil {
return err
}
if !dashWithIdExists {
return m.ErrDashboardNotFound
}
if dash.Uid == "" {
dash.Uid = existingById.Uid
}
}
dashWithUidExists := false
var existingByUid m.Dashboard
if dash.Uid != "" {
dashWithUidExists, err = sess.Where("org_id=? AND uid=?", dash.OrgId, dash.Uid).Get(&existingByUid)
if err != nil {
return err
}
}
if !dashWithIdExists && !dashWithUidExists {
return nil
}
if dashWithIdExists && dashWithUidExists && existingById.Id != existingByUid.Id {
return m.ErrDashboardWithSameUIDExists
}
existing := existingById
if !dashWithIdExists && dashWithUidExists {
dash.Id = existingByUid.Id
existing = existingByUid
}
if (existing.IsFolder && !cmd.IsFolder) ||
(!existing.IsFolder && cmd.IsFolder) {
return m.ErrDashboardTypeMismatch
}
// check for is someone else has written in between
if dash.Version != existing.Version {
if cmd.Overwrite {
dash.Version = existing.Version
} else {
return m.ErrDashboardVersionMismatch
}
}
// do not allow plugin dashboard updates without overwrite flag
if existing.PluginId != "" && cmd.Overwrite == false {
return m.UpdatePluginDashboardError{PluginId: existing.PluginId}
}
return nil
}
func generateNewDashboardUid(sess *DBSession, orgId int64) (string, error) {
for i := 0; i < 3; i++ {
uid := generateNewUid()
@@ -179,23 +229,6 @@ func generateNewDashboardUid(sess *DBSession, orgId int64) (string, error) {
return "", m.ErrDashboardFailedGenerateUniqueUid
}
func guaranteeDashboardNameIsUniqueInFolder(sess *DBSession, dash *m.Dashboard) error {
var sameNameInFolder m.Dashboard
sameNameInFolderExist, err := sess.Where("org_id=? AND title=? AND folder_id = ? AND uid <> ?",
dash.OrgId, dash.Title, dash.FolderId, dash.Uid).
Get(&sameNameInFolder)
if err != nil {
return err
}
if sameNameInFolderExist {
return m.ErrDashboardWithSameNameInFolderExists
}
return nil
}
func setHasAcl(sess *DBSession, dash *m.Dashboard) error {
// check if parent has acl
if dash.FolderId > 0 {
@@ -518,9 +551,7 @@ func GetDashboardPermissionsForUser(query *m.GetDashboardPermissionsForUserQuery
params = append(params, query.UserId)
params = append(params, dialect.BooleanStr(false))
x.ShowSQL(true)
err := x.Sql(sql, params...).Find(&query.Result)
x.ShowSQL(false)
for _, p := range query.Result {
p.PermissionName = p.Permission.String()
+378 -246
View File
@@ -100,7 +100,7 @@ func TestDashboardDataAccess(t *testing.T) {
So(err, ShouldBeNil)
})
Convey("Should return error if no dashboard is updated", func() {
Convey("Should return not found error if no dashboard is found for update", func() {
cmd := m.SaveDashboardCommand{
OrgId: 1,
Overwrite: true,
@@ -112,7 +112,7 @@ func TestDashboardDataAccess(t *testing.T) {
}
err := SaveDashboard(&cmd)
So(err, ShouldNotBeNil)
So(err, ShouldEqual, m.ErrDashboardNotFound)
})
Convey("Should not be able to overwrite dashboard in another org", func() {
@@ -130,7 +130,382 @@ func TestDashboardDataAccess(t *testing.T) {
}
err := SaveDashboard(&cmd)
So(err, ShouldNotBeNil)
So(err, ShouldEqual, m.ErrDashboardNotFound)
})
Convey("Should be able to save dashboards with same name in different folders", func() {
firstSaveCmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": nil,
"title": "test dash folder and title",
"tags": []interface{}{},
"uid": "randomHash",
}),
FolderId: 3,
}
err := SaveDashboard(&firstSaveCmd)
So(err, ShouldBeNil)
secondSaveCmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": nil,
"title": "test dash folder and title",
"tags": []interface{}{},
"uid": "moreRandomHash",
}),
FolderId: 1,
}
err = SaveDashboard(&secondSaveCmd)
So(err, ShouldBeNil)
So(firstSaveCmd.Result.Id, ShouldNotEqual, secondSaveCmd.Result.Id)
})
Convey("Should be able to overwrite dashboard in same folder using title", func() {
insertTestDashboard("Dash", 1, 0, false, "prod", "webapp")
folder := insertTestDashboard("Folder", 1, 0, true, "prod", "webapp")
dashInFolder := insertTestDashboard("Dash", 1, folder.Id, false, "prod", "webapp")
cmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"title": "Dash",
}),
FolderId: folder.Id,
Overwrite: true,
}
err := SaveDashboard(&cmd)
So(err, ShouldBeNil)
So(cmd.Result.Id, ShouldEqual, dashInFolder.Id)
So(cmd.Result.Uid, ShouldEqual, dashInFolder.Uid)
})
Convey("Should be able to overwrite dashboard in General folder using title", func() {
dashInGeneral := insertTestDashboard("Dash", 1, 0, false, "prod", "webapp")
folder := insertTestDashboard("Folder", 1, 0, true, "prod", "webapp")
insertTestDashboard("Dash", 1, folder.Id, false, "prod", "webapp")
cmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"title": "Dash",
}),
FolderId: 0,
Overwrite: true,
}
err := SaveDashboard(&cmd)
So(err, ShouldBeNil)
So(cmd.Result.Id, ShouldEqual, dashInGeneral.Id)
So(cmd.Result.Uid, ShouldEqual, dashInGeneral.Uid)
})
Convey("Should not be able to overwrite folder with dashboard in general folder using title", func() {
cmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"title": savedFolder.Title,
}),
FolderId: 0,
IsFolder: false,
Overwrite: true,
}
err := SaveDashboard(&cmd)
So(err, ShouldEqual, m.ErrDashboardWithSameNameAsFolder)
})
Convey("Should not be able to overwrite folder with dashboard in folder using title", func() {
cmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"title": savedFolder.Title,
}),
FolderId: savedFolder.Id,
IsFolder: false,
Overwrite: true,
}
err := SaveDashboard(&cmd)
So(err, ShouldEqual, m.ErrDashboardWithSameNameAsFolder)
})
Convey("Should not be able to overwrite folder with dashboard using id", func() {
cmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": savedFolder.Id,
"title": "new title",
}),
IsFolder: false,
Overwrite: true,
}
err := SaveDashboard(&cmd)
So(err, ShouldEqual, m.ErrDashboardTypeMismatch)
})
Convey("Should not be able to overwrite dashboard with folder using id", func() {
cmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": savedDash.Id,
"title": "new folder title",
}),
IsFolder: true,
Overwrite: true,
}
err := SaveDashboard(&cmd)
So(err, ShouldEqual, m.ErrDashboardTypeMismatch)
})
Convey("Should not be able to overwrite folder with dashboard using uid", func() {
cmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"uid": savedFolder.Uid,
"title": "new title",
}),
IsFolder: false,
Overwrite: true,
}
err := SaveDashboard(&cmd)
So(err, ShouldEqual, m.ErrDashboardTypeMismatch)
})
Convey("Should not be able to overwrite dashboard with folder using uid", func() {
cmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"uid": savedDash.Uid,
"title": "new folder title",
}),
IsFolder: true,
Overwrite: true,
}
err := SaveDashboard(&cmd)
So(err, ShouldEqual, m.ErrDashboardTypeMismatch)
})
Convey("Should not be able to save dashboard with same name in the same folder without overwrite", func() {
firstSaveCmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": nil,
"title": "test dash folder and title",
"tags": []interface{}{},
"uid": "randomHash",
}),
FolderId: 3,
}
err := SaveDashboard(&firstSaveCmd)
So(err, ShouldBeNil)
secondSaveCmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": nil,
"title": "test dash folder and title",
"tags": []interface{}{},
"uid": "moreRandomHash",
}),
FolderId: 3,
}
err = SaveDashboard(&secondSaveCmd)
So(err, ShouldEqual, m.ErrDashboardWithSameNameInFolderExists)
})
Convey("Should be able to save and update dashboard using same uid", func() {
cmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": nil,
"uid": "dsfalkjngailuedt",
"title": "test dash 23",
}),
}
err := SaveDashboard(&cmd)
So(err, ShouldBeNil)
err = SaveDashboard(&cmd)
So(err, ShouldBeNil)
})
Convey("Should be able to update dashboard using uid", func() {
cmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"uid": savedDash.Uid,
"title": "new title",
}),
FolderId: 0,
Overwrite: true,
}
err := SaveDashboard(&cmd)
So(err, ShouldBeNil)
Convey("Should be able to get updated dashboard by uid", func() {
query := m.GetDashboardQuery{
Uid: savedDash.Uid,
OrgId: 1,
}
err := GetDashboard(&query)
So(err, ShouldBeNil)
So(query.Result.Id, ShouldEqual, savedDash.Id)
So(query.Result.Title, ShouldEqual, "new title")
So(query.Result.FolderId, ShouldEqual, 0)
})
})
Convey("Should be able to update dashboard with the same title and folder id", func() {
cmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"uid": "randomHash",
"title": "folderId",
"style": "light",
"tags": []interface{}{},
}),
FolderId: 2,
}
err := SaveDashboard(&cmd)
So(err, ShouldBeNil)
So(cmd.Result.FolderId, ShouldEqual, 2)
cmd = m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": cmd.Result.Id,
"uid": "randomHash",
"title": "folderId",
"style": "dark",
"version": cmd.Result.Version,
"tags": []interface{}{},
}),
FolderId: 2,
}
err = SaveDashboard(&cmd)
So(err, ShouldBeNil)
})
Convey("Should be able to update using uid without id and overwrite", func() {
cmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"uid": savedDash.Uid,
"title": "folderId",
"version": savedDash.Version,
"tags": []interface{}{},
}),
FolderId: savedDash.FolderId,
}
err := SaveDashboard(&cmd)
So(err, ShouldBeNil)
})
Convey("Should retry generation of uid once if it fails.", func() {
timesCalled := 0
generateNewUid = func() string {
timesCalled += 1
if timesCalled <= 2 {
return savedDash.Uid
} else {
return util.GenerateShortUid()
}
}
cmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"title": "new dash 12334",
"tags": []interface{}{},
}),
}
err := SaveDashboard(&cmd)
So(err, ShouldBeNil)
generateNewUid = util.GenerateShortUid
})
Convey("Should be able to update dashboard by id and remove folderId", func() {
cmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": savedDash.Id,
"title": "folderId",
"tags": []interface{}{},
}),
Overwrite: true,
FolderId: 2,
}
err := SaveDashboard(&cmd)
So(err, ShouldBeNil)
So(cmd.Result.FolderId, ShouldEqual, 2)
cmd = m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": savedDash.Id,
"title": "folderId",
"tags": []interface{}{},
}),
FolderId: 0,
Overwrite: true,
}
err = SaveDashboard(&cmd)
So(err, ShouldBeNil)
query := m.GetDashboardQuery{
Id: savedDash.Id,
OrgId: 1,
}
err = GetDashboard(&query)
So(err, ShouldBeNil)
So(query.Result.FolderId, ShouldEqual, 0)
})
Convey("Should be able to delete a dashboard folder and its children", func() {
deleteCmd := &m.DeleteDashboardCommand{Id: savedFolder.Id}
err := DeleteDashboard(deleteCmd)
So(err, ShouldBeNil)
query := search.FindPersistedDashboardsQuery{
OrgId: 1,
FolderIds: []int64{savedFolder.Id},
SignedInUser: &m.SignedInUser{},
}
err = SearchDashboards(&query)
So(err, ShouldBeNil)
So(len(query.Result), ShouldEqual, 0)
})
Convey("Should be able to get dashboard tags", func() {
query := m.GetDashboardTagsQuery{OrgId: 1}
err := GetDashboardTags(&query)
So(err, ShouldBeNil)
So(len(query.Result), ShouldEqual, 2)
})
Convey("Should be able to search for dashboard folder", func() {
@@ -188,249 +563,6 @@ func TestDashboardDataAccess(t *testing.T) {
hit2 := query.Result[1]
So(len(hit2.Tags), ShouldEqual, 1)
})
Convey("DashboardIds that does not exists should not cause errors", func() {
query := search.FindPersistedDashboardsQuery{
DashboardIds: []int64{1000},
SignedInUser: &m.SignedInUser{OrgId: 1},
}
err := SearchDashboards(&query)
So(err, ShouldBeNil)
So(len(query.Result), ShouldEqual, 0)
})
})
Convey("Should be able to save dashboards with same name in different folders", func() {
firstSaveCmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": nil,
"title": "test dash folder and title",
"tags": []interface{}{},
"uid": "randomHash",
}),
FolderId: 3,
}
err := SaveDashboard(&firstSaveCmd)
So(err, ShouldBeNil)
secondSaveCmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": nil,
"title": "test dash folder and title",
"tags": []interface{}{},
"uid": "moreRandomHash",
}),
FolderId: 1,
}
err = SaveDashboard(&secondSaveCmd)
So(err, ShouldBeNil)
})
Convey("Should not be able to save dashboard with same name in the same folder", func() {
firstSaveCmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": nil,
"title": "test dash folder and title",
"tags": []interface{}{},
"uid": "randomHash",
}),
FolderId: 3,
}
err := SaveDashboard(&firstSaveCmd)
So(err, ShouldBeNil)
secondSaveCmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": nil,
"title": "test dash folder and title",
"tags": []interface{}{},
"uid": "moreRandomHash",
}),
FolderId: 3,
}
err = SaveDashboard(&secondSaveCmd)
So(err, ShouldEqual, m.ErrDashboardWithSameNameInFolderExists)
})
Convey("Should not be able to save dashboard with same uid", func() {
cmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": nil,
"title": "test dash 23",
"uid": "dsfalkjngailuedt",
}),
}
err := SaveDashboard(&cmd)
So(err, ShouldBeNil)
err = SaveDashboard(&cmd)
So(err, ShouldNotBeNil)
})
Convey("Should be able to update dashboard with the same title and folder id", func() {
cmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"uid": "randomHash",
"title": "folderId",
"style": "light",
"tags": []interface{}{},
}),
FolderId: 2,
}
err := SaveDashboard(&cmd)
So(err, ShouldBeNil)
So(cmd.Result.FolderId, ShouldEqual, 2)
cmd = m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": cmd.Result.Id,
"uid": "randomHash",
"title": "folderId",
"style": "dark",
"version": cmd.Result.Version,
"tags": []interface{}{},
}),
FolderId: 2,
}
err = SaveDashboard(&cmd)
So(err, ShouldBeNil)
})
Convey("Should not be able to update using just uid", func() {
cmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"uid": savedDash.Uid,
"title": "folderId",
"version": savedDash.Version,
"tags": []interface{}{},
}),
FolderId: savedDash.FolderId,
}
err := SaveDashboard(&cmd)
So(err, ShouldEqual, m.ErrDashboardWithSameUIDExists)
})
Convey("Should be able to update using just uid with overwrite", func() {
cmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"uid": savedDash.Uid,
"title": "folderId",
"version": savedDash.Version,
"tags": []interface{}{},
}),
FolderId: savedDash.FolderId,
Overwrite: true,
}
err := SaveDashboard(&cmd)
So(err, ShouldBeNil)
})
Convey("Should retry generation of uid once if it fails.", func() {
timesCalled := 0
generateNewUid = func() string {
timesCalled += 1
if timesCalled <= 2 {
return savedDash.Uid
} else {
return util.GenerateShortUid()
}
}
cmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"title": "new dash 12334",
"tags": []interface{}{},
}),
}
err := SaveDashboard(&cmd)
So(err, ShouldBeNil)
generateNewUid = util.GenerateShortUid
})
Convey("Should be able to update dashboard and remove folderId", func() {
cmd := m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": 1,
"title": "folderId",
"tags": []interface{}{},
}),
Overwrite: true,
FolderId: 2,
}
err := SaveDashboard(&cmd)
So(err, ShouldBeNil)
So(cmd.Result.FolderId, ShouldEqual, 2)
cmd = m.SaveDashboardCommand{
OrgId: 1,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": 1,
"title": "folderId",
"tags": []interface{}{},
}),
FolderId: 0,
Overwrite: true,
}
err = SaveDashboard(&cmd)
So(err, ShouldBeNil)
query := m.GetDashboardQuery{
Slug: cmd.Result.Slug,
OrgId: 1,
}
err = GetDashboard(&query)
So(err, ShouldBeNil)
So(query.Result.FolderId, ShouldEqual, 0)
})
Convey("Should be able to delete a dashboard folder and its children", func() {
deleteCmd := &m.DeleteDashboardCommand{Id: savedFolder.Id}
err := DeleteDashboard(deleteCmd)
So(err, ShouldBeNil)
query := search.FindPersistedDashboardsQuery{
OrgId: 1,
FolderIds: []int64{savedFolder.Id},
SignedInUser: &m.SignedInUser{},
}
err = SearchDashboards(&query)
So(err, ShouldBeNil)
So(len(query.Result), ShouldEqual, 0)
})
Convey("Should be able to get dashboard tags", func() {
query := m.GetDashboardTagsQuery{OrgId: 1}
err := GetDashboardTags(&query)
So(err, ShouldBeNil)
So(len(query.Result), ShouldEqual, 2)
})
Convey("Given two dashboards, one is starred dashboard by user 10, other starred by user 1", func() {