mirror of
https://github.com/grafana/grafana.git
synced 2024-11-29 04:04:00 -06:00
1063 lines
33 KiB
Go
1063 lines
33 KiB
Go
package sqlstore
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
|
"github.com/grafana/grafana/pkg/services/guardian"
|
|
|
|
"github.com/grafana/grafana/pkg/bus"
|
|
"github.com/grafana/grafana/pkg/models"
|
|
|
|
. "github.com/smartystreets/goconvey/convey"
|
|
)
|
|
|
|
func TestIntegratedDashboardService(t *testing.T) {
|
|
Convey("Dashboard service integration tests", t, func() {
|
|
InitTestDB(t)
|
|
var testOrgId int64 = 1
|
|
|
|
Convey("Given saved folders and dashboards in organization A", func() {
|
|
bus.AddHandler("test", func(cmd *models.ValidateDashboardAlertsCommand) error {
|
|
return nil
|
|
})
|
|
|
|
bus.AddHandler("test", func(cmd *models.UpdateDashboardAlertsCommand) error {
|
|
return nil
|
|
})
|
|
|
|
bus.AddHandler("test", func(cmd *models.IsDashboardProvisionedQuery) error {
|
|
cmd.Result = false
|
|
return nil
|
|
})
|
|
|
|
savedFolder := saveTestFolder("Saved folder", testOrgId)
|
|
savedDashInFolder := saveTestDashboard("Saved dash in folder", testOrgId, savedFolder.Id)
|
|
saveTestDashboard("Other saved dash in folder", testOrgId, savedFolder.Id)
|
|
savedDashInGeneralFolder := saveTestDashboard("Saved dashboard in general folder", testOrgId, 0)
|
|
otherSavedFolder := saveTestFolder("Other saved folder", testOrgId)
|
|
|
|
Convey("Should return dashboard model", func() {
|
|
So(savedFolder.Title, ShouldEqual, "Saved folder")
|
|
So(savedFolder.Slug, ShouldEqual, "saved-folder")
|
|
So(savedFolder.Id, ShouldNotEqual, 0)
|
|
So(savedFolder.IsFolder, ShouldBeTrue)
|
|
So(savedFolder.FolderId, ShouldEqual, 0)
|
|
So(len(savedFolder.Uid), ShouldBeGreaterThan, 0)
|
|
|
|
So(savedDashInFolder.Title, ShouldEqual, "Saved dash in folder")
|
|
So(savedDashInFolder.Slug, ShouldEqual, "saved-dash-in-folder")
|
|
So(savedDashInFolder.Id, ShouldNotEqual, 0)
|
|
So(savedDashInFolder.IsFolder, ShouldBeFalse)
|
|
So(savedDashInFolder.FolderId, ShouldEqual, savedFolder.Id)
|
|
So(len(savedDashInFolder.Uid), ShouldBeGreaterThan, 0)
|
|
})
|
|
|
|
// Basic validation tests
|
|
|
|
Convey("When saving a dashboard with non-existing id", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: testOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": float64(123412321),
|
|
"title": "Expect error",
|
|
}),
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should result in not found error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardNotFound)
|
|
})
|
|
})
|
|
|
|
// Given other organization
|
|
|
|
Convey("Given organization B", func() {
|
|
var otherOrgId int64 = 2
|
|
|
|
Convey("When creating a dashboard with same id as dashboard in organization A", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: otherOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": savedDashInFolder.Id,
|
|
"title": "Expect error",
|
|
}),
|
|
Overwrite: false,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should result in not found error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardNotFound)
|
|
})
|
|
})
|
|
|
|
permissionScenario("Given user has permission to save", true, func(sc *dashboardPermissionScenarioContext) {
|
|
Convey("When creating a dashboard with same uid as dashboard in organization A", func() {
|
|
var otherOrgId int64 = 2
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: otherOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"uid": savedDashInFolder.Uid,
|
|
"title": "Dash with existing uid in other org",
|
|
}),
|
|
Overwrite: false,
|
|
}
|
|
|
|
res := callSaveWithResult(cmd)
|
|
|
|
Convey("It should create a new dashboard in organization B", func() {
|
|
So(res, ShouldNotBeNil)
|
|
|
|
query := models.GetDashboardQuery{OrgId: otherOrgId, Uid: savedDashInFolder.Uid}
|
|
|
|
err := bus.Dispatch(&query)
|
|
So(err, ShouldBeNil)
|
|
So(query.Result.Id, ShouldNotEqual, savedDashInFolder.Id)
|
|
So(query.Result.Id, ShouldEqual, res.Id)
|
|
So(query.Result.OrgId, ShouldEqual, otherOrgId)
|
|
So(query.Result.Uid, ShouldEqual, savedDashInFolder.Uid)
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
// Given user has no permission to save
|
|
|
|
permissionScenario("Given user has no permission to save", false, func(sc *dashboardPermissionScenarioContext) {
|
|
|
|
Convey("When creating a new dashboard in the General folder", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: testOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"title": "Dash",
|
|
}),
|
|
UserId: 10000,
|
|
Overwrite: true,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should create dashboard guardian for General Folder with correct arguments and result in access denied error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardUpdateAccessDenied)
|
|
|
|
So(sc.dashboardGuardianMock.DashId, ShouldEqual, 0)
|
|
So(sc.dashboardGuardianMock.OrgId, ShouldEqual, cmd.OrgId)
|
|
So(sc.dashboardGuardianMock.User.UserId, ShouldEqual, cmd.UserId)
|
|
})
|
|
})
|
|
|
|
Convey("When creating a new dashboard in other folder", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: testOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"title": "Dash",
|
|
}),
|
|
FolderId: otherSavedFolder.Id,
|
|
UserId: 10000,
|
|
Overwrite: true,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should create dashboard guardian for other folder with correct arguments and rsult in access denied error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardUpdateAccessDenied)
|
|
|
|
So(sc.dashboardGuardianMock.DashId, ShouldEqual, otherSavedFolder.Id)
|
|
So(sc.dashboardGuardianMock.OrgId, ShouldEqual, cmd.OrgId)
|
|
So(sc.dashboardGuardianMock.User.UserId, ShouldEqual, cmd.UserId)
|
|
})
|
|
})
|
|
|
|
Convey("When creating a new dashboard by existing title in folder", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: testOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"title": savedDashInFolder.Title,
|
|
}),
|
|
FolderId: savedFolder.Id,
|
|
UserId: 10000,
|
|
Overwrite: true,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should create dashboard guardian for folder with correct arguments and result in access denied error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardUpdateAccessDenied)
|
|
|
|
So(sc.dashboardGuardianMock.DashId, ShouldEqual, savedFolder.Id)
|
|
So(sc.dashboardGuardianMock.OrgId, ShouldEqual, cmd.OrgId)
|
|
So(sc.dashboardGuardianMock.User.UserId, ShouldEqual, cmd.UserId)
|
|
})
|
|
})
|
|
|
|
Convey("When creating a new dashboard by existing uid in folder", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: testOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"uid": savedDashInFolder.Uid,
|
|
"title": "New dash",
|
|
}),
|
|
FolderId: savedFolder.Id,
|
|
UserId: 10000,
|
|
Overwrite: true,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should create dashboard guardian for folder with correct arguments and result in access denied error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardUpdateAccessDenied)
|
|
|
|
So(sc.dashboardGuardianMock.DashId, ShouldEqual, savedFolder.Id)
|
|
So(sc.dashboardGuardianMock.OrgId, ShouldEqual, cmd.OrgId)
|
|
So(sc.dashboardGuardianMock.User.UserId, ShouldEqual, cmd.UserId)
|
|
})
|
|
})
|
|
|
|
Convey("When updating a dashboard by existing id in the General folder", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: testOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": savedDashInGeneralFolder.Id,
|
|
"title": "Dash",
|
|
}),
|
|
FolderId: savedDashInGeneralFolder.FolderId,
|
|
UserId: 10000,
|
|
Overwrite: true,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should create dashboard guardian for dashboard with correct arguments and result in access denied error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardUpdateAccessDenied)
|
|
|
|
So(sc.dashboardGuardianMock.DashId, ShouldEqual, savedDashInGeneralFolder.Id)
|
|
So(sc.dashboardGuardianMock.OrgId, ShouldEqual, cmd.OrgId)
|
|
So(sc.dashboardGuardianMock.User.UserId, ShouldEqual, cmd.UserId)
|
|
})
|
|
})
|
|
|
|
Convey("When updating a dashboard by existing id in other folder", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: testOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": savedDashInFolder.Id,
|
|
"title": "Dash",
|
|
}),
|
|
FolderId: savedDashInFolder.FolderId,
|
|
UserId: 10000,
|
|
Overwrite: true,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should create dashboard guardian for dashboard with correct arguments and result in access denied error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardUpdateAccessDenied)
|
|
|
|
So(sc.dashboardGuardianMock.DashId, ShouldEqual, savedDashInFolder.Id)
|
|
So(sc.dashboardGuardianMock.OrgId, ShouldEqual, cmd.OrgId)
|
|
So(sc.dashboardGuardianMock.User.UserId, ShouldEqual, cmd.UserId)
|
|
})
|
|
})
|
|
|
|
Convey("When moving a dashboard by existing id to other folder from General folder", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: testOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": savedDashInGeneralFolder.Id,
|
|
"title": "Dash",
|
|
}),
|
|
FolderId: otherSavedFolder.Id,
|
|
UserId: 10000,
|
|
Overwrite: true,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should create dashboard guardian for other folder with correct arguments and result in access denied error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardUpdateAccessDenied)
|
|
|
|
So(sc.dashboardGuardianMock.DashId, ShouldEqual, otherSavedFolder.Id)
|
|
So(sc.dashboardGuardianMock.OrgId, ShouldEqual, cmd.OrgId)
|
|
So(sc.dashboardGuardianMock.User.UserId, ShouldEqual, cmd.UserId)
|
|
})
|
|
})
|
|
|
|
Convey("When moving a dashboard by existing id to the General folder from other folder", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: testOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": savedDashInFolder.Id,
|
|
"title": "Dash",
|
|
}),
|
|
FolderId: 0,
|
|
UserId: 10000,
|
|
Overwrite: true,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should create dashboard guardian for General folder with correct arguments and result in access denied error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardUpdateAccessDenied)
|
|
|
|
So(sc.dashboardGuardianMock.DashId, ShouldEqual, 0)
|
|
So(sc.dashboardGuardianMock.OrgId, ShouldEqual, cmd.OrgId)
|
|
So(sc.dashboardGuardianMock.User.UserId, ShouldEqual, cmd.UserId)
|
|
})
|
|
})
|
|
|
|
Convey("When moving a dashboard by existing uid to other folder from General folder", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: testOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"uid": savedDashInGeneralFolder.Uid,
|
|
"title": "Dash",
|
|
}),
|
|
FolderId: otherSavedFolder.Id,
|
|
UserId: 10000,
|
|
Overwrite: true,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should create dashboard guardian for other folder with correct arguments and result in access denied error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardUpdateAccessDenied)
|
|
|
|
So(sc.dashboardGuardianMock.DashId, ShouldEqual, otherSavedFolder.Id)
|
|
So(sc.dashboardGuardianMock.OrgId, ShouldEqual, cmd.OrgId)
|
|
So(sc.dashboardGuardianMock.User.UserId, ShouldEqual, cmd.UserId)
|
|
})
|
|
})
|
|
|
|
Convey("When moving a dashboard by existing uid to the General folder from other folder", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: testOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"uid": savedDashInFolder.Uid,
|
|
"title": "Dash",
|
|
}),
|
|
FolderId: 0,
|
|
UserId: 10000,
|
|
Overwrite: true,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should create dashboard guardian for General folder with correct arguments and result in access denied error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardUpdateAccessDenied)
|
|
|
|
So(sc.dashboardGuardianMock.DashId, ShouldEqual, 0)
|
|
So(sc.dashboardGuardianMock.OrgId, ShouldEqual, cmd.OrgId)
|
|
So(sc.dashboardGuardianMock.User.UserId, ShouldEqual, cmd.UserId)
|
|
})
|
|
})
|
|
})
|
|
|
|
// Given user has permission to save
|
|
|
|
permissionScenario("Given user has permission to save", true, func(sc *dashboardPermissionScenarioContext) {
|
|
|
|
Convey("and overwrite flag is set to false", func() {
|
|
shouldOverwrite := false
|
|
|
|
Convey("When creating a dashboard in General folder with same name as dashboard in other folder", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: testOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": nil,
|
|
"title": savedDashInFolder.Title,
|
|
}),
|
|
FolderId: 0,
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
res := callSaveWithResult(cmd)
|
|
So(res, ShouldNotBeNil)
|
|
|
|
Convey("It should create a new dashboard", func() {
|
|
query := models.GetDashboardQuery{OrgId: cmd.OrgId, Id: res.Id}
|
|
|
|
err := bus.Dispatch(&query)
|
|
So(err, ShouldBeNil)
|
|
So(query.Result.Id, ShouldEqual, res.Id)
|
|
So(query.Result.FolderId, ShouldEqual, 0)
|
|
})
|
|
})
|
|
|
|
Convey("When creating a dashboard in other folder with same name as dashboard in General folder", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: testOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": nil,
|
|
"title": savedDashInGeneralFolder.Title,
|
|
}),
|
|
FolderId: savedFolder.Id,
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
res := callSaveWithResult(cmd)
|
|
So(res, ShouldNotBeNil)
|
|
|
|
Convey("It should create a new dashboard", func() {
|
|
So(res.Id, ShouldNotEqual, savedDashInGeneralFolder.Id)
|
|
|
|
query := models.GetDashboardQuery{OrgId: cmd.OrgId, Id: res.Id}
|
|
|
|
err := bus.Dispatch(&query)
|
|
So(err, ShouldBeNil)
|
|
So(query.Result.FolderId, ShouldEqual, savedFolder.Id)
|
|
})
|
|
})
|
|
|
|
Convey("When creating a folder with same name as dashboard in other folder", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: testOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": nil,
|
|
"title": savedDashInFolder.Title,
|
|
}),
|
|
IsFolder: true,
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
res := callSaveWithResult(cmd)
|
|
So(res, ShouldNotBeNil)
|
|
|
|
Convey("It should create a new folder", func() {
|
|
So(res.Id, ShouldNotEqual, savedDashInGeneralFolder.Id)
|
|
So(res.IsFolder, ShouldBeTrue)
|
|
|
|
query := models.GetDashboardQuery{OrgId: cmd.OrgId, Id: res.Id}
|
|
|
|
err := bus.Dispatch(&query)
|
|
So(err, ShouldBeNil)
|
|
So(query.Result.FolderId, ShouldEqual, 0)
|
|
So(query.Result.IsFolder, ShouldBeTrue)
|
|
})
|
|
})
|
|
|
|
Convey("When saving a dashboard without id and uid and unique title in folder", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: testOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"title": "Dash without id and uid",
|
|
}),
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
res := callSaveWithResult(cmd)
|
|
So(res, ShouldNotBeNil)
|
|
|
|
Convey("It should create a new dashboard", func() {
|
|
So(res.Id, ShouldBeGreaterThan, 0)
|
|
So(len(res.Uid), ShouldBeGreaterThan, 0)
|
|
query := models.GetDashboardQuery{OrgId: cmd.OrgId, Id: res.Id}
|
|
|
|
err := bus.Dispatch(&query)
|
|
So(err, ShouldBeNil)
|
|
So(query.Result.Id, ShouldEqual, res.Id)
|
|
So(query.Result.Uid, ShouldEqual, res.Uid)
|
|
})
|
|
})
|
|
|
|
Convey("When saving a dashboard when dashboard id is zero ", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: testOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": 0,
|
|
"title": "Dash with zero id",
|
|
}),
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
res := callSaveWithResult(cmd)
|
|
So(res, ShouldNotBeNil)
|
|
|
|
Convey("It should create a new dashboard", func() {
|
|
query := models.GetDashboardQuery{OrgId: cmd.OrgId, Id: res.Id}
|
|
|
|
err := bus.Dispatch(&query)
|
|
So(err, ShouldBeNil)
|
|
So(query.Result.Id, ShouldEqual, res.Id)
|
|
})
|
|
})
|
|
|
|
Convey("When saving a dashboard in non-existing folder", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: testOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"title": "Expect error",
|
|
}),
|
|
FolderId: 123412321,
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should result in folder not found error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardFolderNotFound)
|
|
})
|
|
})
|
|
|
|
Convey("When updating an existing dashboard by id without current version", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: 1,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": savedDashInGeneralFolder.Id,
|
|
"title": "test dash 23",
|
|
}),
|
|
FolderId: savedFolder.Id,
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should result in version mismatch error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardVersionMismatch)
|
|
})
|
|
})
|
|
|
|
Convey("When updating an existing dashboard by id with current version", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: 1,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": savedDashInGeneralFolder.Id,
|
|
"title": "Updated title",
|
|
"version": savedDashInGeneralFolder.Version,
|
|
}),
|
|
FolderId: savedFolder.Id,
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
res := callSaveWithResult(cmd)
|
|
So(res, ShouldNotBeNil)
|
|
|
|
Convey("It should update dashboard", func() {
|
|
query := models.GetDashboardQuery{OrgId: cmd.OrgId, Id: savedDashInGeneralFolder.Id}
|
|
|
|
err := bus.Dispatch(&query)
|
|
So(err, ShouldBeNil)
|
|
So(query.Result.Title, ShouldEqual, "Updated title")
|
|
So(query.Result.FolderId, ShouldEqual, savedFolder.Id)
|
|
So(query.Result.Version, ShouldBeGreaterThan, savedDashInGeneralFolder.Version)
|
|
})
|
|
})
|
|
|
|
Convey("When updating an existing dashboard by uid without current version", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: 1,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"uid": savedDashInFolder.Uid,
|
|
"title": "test dash 23",
|
|
}),
|
|
FolderId: 0,
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should result in version mismatch error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardVersionMismatch)
|
|
})
|
|
})
|
|
|
|
Convey("When updating an existing dashboard by uid with current version", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: 1,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"uid": savedDashInFolder.Uid,
|
|
"title": "Updated title",
|
|
"version": savedDashInFolder.Version,
|
|
}),
|
|
FolderId: 0,
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
res := callSaveWithResult(cmd)
|
|
So(res, ShouldNotBeNil)
|
|
|
|
Convey("It should update dashboard", func() {
|
|
query := models.GetDashboardQuery{OrgId: cmd.OrgId, Id: savedDashInFolder.Id}
|
|
|
|
err := bus.Dispatch(&query)
|
|
So(err, ShouldBeNil)
|
|
So(query.Result.Title, ShouldEqual, "Updated title")
|
|
So(query.Result.FolderId, ShouldEqual, 0)
|
|
So(query.Result.Version, ShouldBeGreaterThan, savedDashInFolder.Version)
|
|
})
|
|
})
|
|
|
|
Convey("When creating a dashboard with same name as dashboard in other folder", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: testOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": nil,
|
|
"title": savedDashInFolder.Title,
|
|
}),
|
|
FolderId: savedDashInFolder.FolderId,
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should result in dashboard with same name in folder error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardWithSameNameInFolderExists)
|
|
})
|
|
})
|
|
|
|
Convey("When creating a dashboard with same name as dashboard in General folder", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: testOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": nil,
|
|
"title": savedDashInGeneralFolder.Title,
|
|
}),
|
|
FolderId: savedDashInGeneralFolder.FolderId,
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should result in dashboard with same name in folder error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardWithSameNameInFolderExists)
|
|
})
|
|
})
|
|
|
|
Convey("When creating a folder with same name as existing folder", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: testOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": nil,
|
|
"title": savedFolder.Title,
|
|
}),
|
|
IsFolder: true,
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should result in dashboard with same name in folder error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardWithSameNameInFolderExists)
|
|
})
|
|
})
|
|
})
|
|
|
|
Convey("and overwrite flag is set to true", func() {
|
|
shouldOverwrite := true
|
|
|
|
Convey("When updating an existing dashboard by id without current version", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: 1,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": savedDashInGeneralFolder.Id,
|
|
"title": "Updated title",
|
|
}),
|
|
FolderId: savedFolder.Id,
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
res := callSaveWithResult(cmd)
|
|
So(res, ShouldNotBeNil)
|
|
|
|
Convey("It should update dashboard", func() {
|
|
query := models.GetDashboardQuery{OrgId: cmd.OrgId, Id: savedDashInGeneralFolder.Id}
|
|
|
|
err := bus.Dispatch(&query)
|
|
So(err, ShouldBeNil)
|
|
So(query.Result.Title, ShouldEqual, "Updated title")
|
|
So(query.Result.FolderId, ShouldEqual, savedFolder.Id)
|
|
So(query.Result.Version, ShouldBeGreaterThan, savedDashInGeneralFolder.Version)
|
|
})
|
|
})
|
|
|
|
Convey("When updating an existing dashboard by uid without current version", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: 1,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"uid": savedDashInFolder.Uid,
|
|
"title": "Updated title",
|
|
}),
|
|
FolderId: 0,
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
res := callSaveWithResult(cmd)
|
|
So(res, ShouldNotBeNil)
|
|
|
|
Convey("It should update dashboard", func() {
|
|
query := models.GetDashboardQuery{OrgId: cmd.OrgId, Id: savedDashInFolder.Id}
|
|
|
|
err := bus.Dispatch(&query)
|
|
So(err, ShouldBeNil)
|
|
So(query.Result.Title, ShouldEqual, "Updated title")
|
|
So(query.Result.FolderId, ShouldEqual, 0)
|
|
So(query.Result.Version, ShouldBeGreaterThan, savedDashInFolder.Version)
|
|
})
|
|
})
|
|
|
|
Convey("When updating uid for existing dashboard using id", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: 1,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": savedDashInFolder.Id,
|
|
"uid": "new-uid",
|
|
"title": savedDashInFolder.Title,
|
|
}),
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
res := callSaveWithResult(cmd)
|
|
|
|
Convey("It should update dashboard", func() {
|
|
So(res, ShouldNotBeNil)
|
|
So(res.Id, ShouldEqual, savedDashInFolder.Id)
|
|
So(res.Uid, ShouldEqual, "new-uid")
|
|
|
|
query := models.GetDashboardQuery{OrgId: cmd.OrgId, Id: savedDashInFolder.Id}
|
|
|
|
err := bus.Dispatch(&query)
|
|
So(err, ShouldBeNil)
|
|
So(query.Result.Uid, ShouldEqual, "new-uid")
|
|
So(query.Result.Version, ShouldBeGreaterThan, savedDashInFolder.Version)
|
|
})
|
|
})
|
|
|
|
Convey("When updating uid to an existing uid for existing dashboard using id", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: 1,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": savedDashInFolder.Id,
|
|
"uid": savedDashInGeneralFolder.Uid,
|
|
"title": savedDashInFolder.Title,
|
|
}),
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should result in same uid exists error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardWithSameUIDExists)
|
|
})
|
|
})
|
|
|
|
Convey("When creating a dashboard with same name as dashboard in other folder", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: testOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": nil,
|
|
"title": savedDashInFolder.Title,
|
|
}),
|
|
FolderId: savedDashInFolder.FolderId,
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
res := callSaveWithResult(cmd)
|
|
|
|
Convey("It should overwrite existing dashboard", func() {
|
|
So(res, ShouldNotBeNil)
|
|
So(res.Id, ShouldEqual, savedDashInFolder.Id)
|
|
So(res.Uid, ShouldEqual, savedDashInFolder.Uid)
|
|
|
|
query := models.GetDashboardQuery{OrgId: cmd.OrgId, Id: res.Id}
|
|
|
|
err := bus.Dispatch(&query)
|
|
So(err, ShouldBeNil)
|
|
So(query.Result.Id, ShouldEqual, res.Id)
|
|
So(query.Result.Uid, ShouldEqual, res.Uid)
|
|
})
|
|
})
|
|
|
|
Convey("When creating a dashboard with same name as dashboard in General folder", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: testOrgId,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": nil,
|
|
"title": savedDashInGeneralFolder.Title,
|
|
}),
|
|
FolderId: savedDashInGeneralFolder.FolderId,
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
res := callSaveWithResult(cmd)
|
|
|
|
Convey("It should overwrite existing dashboard", func() {
|
|
So(res, ShouldNotBeNil)
|
|
So(res.Id, ShouldEqual, savedDashInGeneralFolder.Id)
|
|
So(res.Uid, ShouldEqual, savedDashInGeneralFolder.Uid)
|
|
|
|
query := models.GetDashboardQuery{OrgId: cmd.OrgId, Id: res.Id}
|
|
|
|
err := bus.Dispatch(&query)
|
|
So(err, ShouldBeNil)
|
|
So(query.Result.Id, ShouldEqual, res.Id)
|
|
So(query.Result.Uid, ShouldEqual, res.Uid)
|
|
})
|
|
})
|
|
|
|
Convey("When updating existing folder to a dashboard using id", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: 1,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": savedFolder.Id,
|
|
"title": "new title",
|
|
}),
|
|
IsFolder: false,
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should result in type mismatch error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardTypeMismatch)
|
|
})
|
|
})
|
|
|
|
Convey("When updating existing dashboard to a folder using id", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: 1,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": savedDashInFolder.Id,
|
|
"title": "new folder title",
|
|
}),
|
|
IsFolder: true,
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should result in type mismatch error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardTypeMismatch)
|
|
})
|
|
})
|
|
|
|
Convey("When updating existing folder to a dashboard using uid", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: 1,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"uid": savedFolder.Uid,
|
|
"title": "new title",
|
|
}),
|
|
IsFolder: false,
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should result in type mismatch error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardTypeMismatch)
|
|
})
|
|
})
|
|
|
|
Convey("When updating existing dashboard to a folder using uid", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: 1,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"uid": savedDashInFolder.Uid,
|
|
"title": "new folder title",
|
|
}),
|
|
IsFolder: true,
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should result in type mismatch error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardTypeMismatch)
|
|
})
|
|
})
|
|
|
|
Convey("When updating existing folder to a dashboard using title", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: 1,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"title": savedFolder.Title,
|
|
}),
|
|
IsFolder: false,
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should result in dashboard with same name as folder error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardWithSameNameAsFolder)
|
|
})
|
|
})
|
|
|
|
Convey("When updating existing dashboard to a folder using title", func() {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: 1,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"title": savedDashInGeneralFolder.Title,
|
|
}),
|
|
IsFolder: true,
|
|
Overwrite: shouldOverwrite,
|
|
}
|
|
|
|
err := callSaveWithError(cmd)
|
|
|
|
Convey("It should result in folder with same name as dashboard error", func() {
|
|
So(err, ShouldNotBeNil)
|
|
So(err, ShouldEqual, models.ErrDashboardFolderWithSameNameAsDashboard)
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
type scenarioContext struct {
|
|
dashboardGuardianMock *guardian.FakeDashboardGuardian
|
|
}
|
|
|
|
type scenarioFunc func(c *scenarioContext)
|
|
|
|
func dashboardGuardianScenario(desc string, mock *guardian.FakeDashboardGuardian, fn scenarioFunc) {
|
|
Convey(desc, func() {
|
|
origNewDashboardGuardian := guardian.New
|
|
guardian.MockDashboardGuardian(mock)
|
|
|
|
sc := &scenarioContext{
|
|
dashboardGuardianMock: mock,
|
|
}
|
|
|
|
defer func() {
|
|
guardian.New = origNewDashboardGuardian
|
|
}()
|
|
|
|
fn(sc)
|
|
})
|
|
}
|
|
|
|
type dashboardPermissionScenarioContext struct {
|
|
dashboardGuardianMock *guardian.FakeDashboardGuardian
|
|
}
|
|
|
|
type dashboardPermissionScenarioFunc func(sc *dashboardPermissionScenarioContext)
|
|
|
|
func dashboardPermissionScenario(desc string, mock *guardian.FakeDashboardGuardian, fn dashboardPermissionScenarioFunc) {
|
|
Convey(desc, func() {
|
|
origNewDashboardGuardian := guardian.New
|
|
guardian.MockDashboardGuardian(mock)
|
|
|
|
sc := &dashboardPermissionScenarioContext{
|
|
dashboardGuardianMock: mock,
|
|
}
|
|
|
|
defer func() {
|
|
guardian.New = origNewDashboardGuardian
|
|
}()
|
|
|
|
fn(sc)
|
|
})
|
|
}
|
|
|
|
func permissionScenario(desc string, canSave bool, fn dashboardPermissionScenarioFunc) {
|
|
mock := &guardian.FakeDashboardGuardian{
|
|
CanSaveValue: canSave,
|
|
}
|
|
dashboardPermissionScenario(desc, mock, fn)
|
|
}
|
|
|
|
func callSaveWithResult(cmd models.SaveDashboardCommand) *models.Dashboard {
|
|
dto := toSaveDashboardDto(cmd)
|
|
res, _ := dashboards.NewService().SaveDashboard(&dto)
|
|
return res
|
|
}
|
|
|
|
func callSaveWithError(cmd models.SaveDashboardCommand) error {
|
|
dto := toSaveDashboardDto(cmd)
|
|
_, err := dashboards.NewService().SaveDashboard(&dto)
|
|
return err
|
|
}
|
|
|
|
func saveTestDashboard(title string, orgId int64, folderId int64) *models.Dashboard {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: orgId,
|
|
FolderId: folderId,
|
|
IsFolder: false,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": nil,
|
|
"title": title,
|
|
}),
|
|
}
|
|
|
|
dto := dashboards.SaveDashboardDTO{
|
|
OrgId: orgId,
|
|
Dashboard: cmd.GetDashboardModel(),
|
|
User: &models.SignedInUser{
|
|
UserId: 1,
|
|
OrgRole: models.ROLE_ADMIN,
|
|
},
|
|
}
|
|
|
|
res, err := dashboards.NewService().SaveDashboard(&dto)
|
|
So(err, ShouldBeNil)
|
|
|
|
return res
|
|
}
|
|
|
|
func saveTestFolder(title string, orgId int64) *models.Dashboard {
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: orgId,
|
|
FolderId: 0,
|
|
IsFolder: true,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": nil,
|
|
"title": title,
|
|
}),
|
|
}
|
|
|
|
dto := dashboards.SaveDashboardDTO{
|
|
OrgId: orgId,
|
|
Dashboard: cmd.GetDashboardModel(),
|
|
User: &models.SignedInUser{
|
|
UserId: 1,
|
|
OrgRole: models.ROLE_ADMIN,
|
|
},
|
|
}
|
|
|
|
res, err := dashboards.NewService().SaveDashboard(&dto)
|
|
So(err, ShouldBeNil)
|
|
|
|
return res
|
|
}
|
|
|
|
func toSaveDashboardDto(cmd models.SaveDashboardCommand) dashboards.SaveDashboardDTO {
|
|
dash := (&cmd).GetDashboardModel()
|
|
|
|
return dashboards.SaveDashboardDTO{
|
|
Dashboard: dash,
|
|
Message: cmd.Message,
|
|
OrgId: cmd.OrgId,
|
|
User: &models.SignedInUser{UserId: cmd.UserId},
|
|
Overwrite: cmd.Overwrite,
|
|
}
|
|
}
|