2021-09-01 09:38:56 -05:00
//go:build integration
2021-03-17 10:06:10 -05:00
// +build integration
package dashboards
import (
2021-11-03 08:10:39 -05:00
"context"
2021-03-17 10:06:10 -05:00
"testing"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/dashboards"
"github.com/grafana/grafana/pkg/services/guardian"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/models"
)
const testOrgID int64 = 1
func TestIntegratedDashboardService ( t * testing . T ) {
t . Run ( "Given saved folders and dashboards in organization A" , func ( t * testing . T ) {
origUpdateAlerting := UpdateAlerting
t . Cleanup ( func ( ) {
UpdateAlerting = origUpdateAlerting
} )
2021-11-03 08:10:39 -05:00
UpdateAlerting = func ( ctx context . Context , store dashboards . Store , orgID int64 , dashboard * models . Dashboard , user * models . SignedInUser ) error {
2021-03-17 10:06:10 -05:00
return nil
}
// Basic validation tests
permissionScenario ( t , "When saving a dashboard with non-existing id" , true ,
func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : float64 ( 123412321 ) ,
"title" : "Expect error" ,
} ) ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
assert . Equal ( t , models . ErrDashboardNotFound , err )
} )
// Given other organization
t . Run ( "Given organization B" , func ( t * testing . T ) {
const otherOrgId int64 = 2
permissionScenario ( t , "When creating a dashboard with same id as dashboard in organization A" ,
true , func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : otherOrgId ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : sc . savedDashInFolder . Id ,
"title" : "Expect error" ,
} ) ,
Overwrite : false ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
assert . Equal ( t , models . ErrDashboardNotFound , err )
} )
permissionScenario ( t , "When creating a dashboard with same uid as dashboard in organization A, it should create a new dashboard in org B" ,
true , func ( t * testing . T , sc * permissionScenarioContext ) {
const otherOrgId int64 = 2
cmd := models . SaveDashboardCommand {
OrgId : otherOrgId ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"uid" : sc . savedDashInFolder . Uid ,
"title" : "Dash with existing uid in other org" ,
} ) ,
Overwrite : false ,
}
res := callSaveWithResult ( t , cmd , sc . sqlStore )
require . NotNil ( t , res )
dash , err := sc . sqlStore . GetDashboard ( 0 , otherOrgId , sc . savedDashInFolder . Uid , "" )
require . NoError ( t , err )
assert . NotEqual ( t , sc . savedDashInFolder . Id , dash . Id )
assert . Equal ( t , res . Id , dash . Id )
assert . Equal ( t , otherOrgId , dash . OrgId )
assert . Equal ( t , sc . savedDashInFolder . Uid , dash . Uid )
} )
} )
t . Run ( "Given user has no permission to save" , func ( t * testing . T ) {
const canSave = false
permissionScenario ( t , "When creating a new dashboard in the General folder" , canSave ,
func ( t * testing . T , sc * permissionScenarioContext ) {
sqlStore := sqlstore . InitTestDB ( t )
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"title" : "Dash" ,
} ) ,
UserId : 10000 ,
Overwrite : true ,
}
err := callSaveWithError ( cmd , sqlStore )
assert . Equal ( t , models . ErrDashboardUpdateAccessDenied , err )
assert . Equal ( t , int64 ( 0 ) , sc . dashboardGuardianMock . DashId )
assert . Equal ( t , cmd . OrgId , sc . dashboardGuardianMock . OrgId )
assert . Equal ( t , cmd . UserId , sc . dashboardGuardianMock . User . UserId )
} )
permissionScenario ( t , "When creating a new dashboard in other folder, it should create dashboard guardian for other folder with correct arguments and rsult in access denied error" ,
canSave , func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"title" : "Dash" ,
} ) ,
FolderId : sc . otherSavedFolder . Id ,
UserId : 10000 ,
Overwrite : true ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
require . Equal ( t , models . ErrDashboardUpdateAccessDenied , err )
assert . Equal ( t , sc . otherSavedFolder . Id , sc . dashboardGuardianMock . DashId )
assert . Equal ( t , cmd . OrgId , sc . dashboardGuardianMock . OrgId )
assert . Equal ( t , cmd . UserId , sc . dashboardGuardianMock . User . UserId )
} )
permissionScenario ( t , "When creating a new dashboard by existing title in folder, it should create dashboard guardian for folder with correct arguments and result in access denied error" ,
canSave , func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"title" : sc . savedDashInFolder . Title ,
} ) ,
FolderId : sc . savedFolder . Id ,
UserId : 10000 ,
Overwrite : true ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
require . Equal ( t , models . ErrDashboardUpdateAccessDenied , err )
assert . Equal ( t , sc . savedFolder . Id , sc . dashboardGuardianMock . DashId )
assert . Equal ( t , cmd . OrgId , sc . dashboardGuardianMock . OrgId )
assert . Equal ( t , cmd . UserId , sc . dashboardGuardianMock . User . UserId )
} )
permissionScenario ( t , "When creating a new dashboard by existing UID in folder, it should create dashboard guardian for folder with correct arguments and result in access denied error" ,
canSave , func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"uid" : sc . savedDashInFolder . Uid ,
"title" : "New dash" ,
} ) ,
FolderId : sc . savedFolder . Id ,
UserId : 10000 ,
Overwrite : true ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
require . Equal ( t , models . ErrDashboardUpdateAccessDenied , err )
assert . Equal ( t , sc . savedFolder . Id , sc . dashboardGuardianMock . DashId )
assert . Equal ( t , cmd . OrgId , sc . dashboardGuardianMock . OrgId )
assert . Equal ( t , cmd . UserId , sc . dashboardGuardianMock . User . UserId )
} )
permissionScenario ( t , "When updating a dashboard by existing id in the General folder, it should create dashboard guardian for dashboard with correct arguments and result in access denied error" ,
canSave , func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : sc . savedDashInGeneralFolder . Id ,
"title" : "Dash" ,
} ) ,
FolderId : sc . savedDashInGeneralFolder . FolderId ,
UserId : 10000 ,
Overwrite : true ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
assert . Equal ( t , models . ErrDashboardUpdateAccessDenied , err )
assert . Equal ( t , sc . savedDashInGeneralFolder . Id , sc . dashboardGuardianMock . DashId )
assert . Equal ( t , cmd . OrgId , sc . dashboardGuardianMock . OrgId )
assert . Equal ( t , cmd . UserId , sc . dashboardGuardianMock . User . UserId )
} )
permissionScenario ( t , "When updating a dashboard by existing id in other folder, it should create dashboard guardian for dashboard with correct arguments and result in access denied error" ,
canSave , func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : sc . savedDashInFolder . Id ,
"title" : "Dash" ,
} ) ,
FolderId : sc . savedDashInFolder . FolderId ,
UserId : 10000 ,
Overwrite : true ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
require . Equal ( t , models . ErrDashboardUpdateAccessDenied , err )
assert . Equal ( t , sc . savedDashInFolder . Id , sc . dashboardGuardianMock . DashId )
assert . Equal ( t , cmd . OrgId , sc . dashboardGuardianMock . OrgId )
assert . Equal ( t , cmd . UserId , sc . dashboardGuardianMock . User . UserId )
} )
permissionScenario ( t , "When moving a dashboard by existing ID to other folder from General folder, it should create dashboard guardian for other folder with correct arguments and result in access denied error" ,
canSave , func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : sc . savedDashInGeneralFolder . Id ,
"title" : "Dash" ,
} ) ,
FolderId : sc . otherSavedFolder . Id ,
UserId : 10000 ,
Overwrite : true ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
require . Equal ( t , models . ErrDashboardUpdateAccessDenied , err )
assert . Equal ( t , sc . otherSavedFolder . Id , sc . dashboardGuardianMock . DashId )
assert . Equal ( t , cmd . OrgId , sc . dashboardGuardianMock . OrgId )
assert . Equal ( t , cmd . UserId , sc . dashboardGuardianMock . User . UserId )
} )
permissionScenario ( t , "When moving a dashboard by existing id to the General folder from other folder, it should create dashboard guardian for General folder with correct arguments and result in access denied error" ,
canSave , func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : sc . savedDashInFolder . Id ,
"title" : "Dash" ,
} ) ,
FolderId : 0 ,
UserId : 10000 ,
Overwrite : true ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
assert . Equal ( t , models . ErrDashboardUpdateAccessDenied , err )
assert . Equal ( t , int64 ( 0 ) , sc . dashboardGuardianMock . DashId )
assert . Equal ( t , cmd . OrgId , sc . dashboardGuardianMock . OrgId )
assert . Equal ( t , cmd . UserId , sc . dashboardGuardianMock . User . UserId )
} )
permissionScenario ( t , "When moving a dashboard by existing uid to other folder from General folder, it should create dashboard guardian for other folder with correct arguments and result in access denied error" ,
canSave , func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"uid" : sc . savedDashInGeneralFolder . Uid ,
"title" : "Dash" ,
} ) ,
FolderId : sc . otherSavedFolder . Id ,
UserId : 10000 ,
Overwrite : true ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
require . Equal ( t , models . ErrDashboardUpdateAccessDenied , err )
assert . Equal ( t , sc . otherSavedFolder . Id , sc . dashboardGuardianMock . DashId )
assert . Equal ( t , cmd . OrgId , sc . dashboardGuardianMock . OrgId )
assert . Equal ( t , cmd . UserId , sc . dashboardGuardianMock . User . UserId )
} )
permissionScenario ( t , "When moving a dashboard by existing UID to the General folder from other folder, it should create dashboard guardian for General folder with correct arguments and result in access denied error" ,
canSave , func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"uid" : sc . savedDashInFolder . Uid ,
"title" : "Dash" ,
} ) ,
FolderId : 0 ,
UserId : 10000 ,
Overwrite : true ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
require . Equal ( t , models . ErrDashboardUpdateAccessDenied , err )
assert . Equal ( t , int64 ( 0 ) , sc . dashboardGuardianMock . DashId )
assert . Equal ( t , cmd . OrgId , sc . dashboardGuardianMock . OrgId )
assert . Equal ( t , cmd . UserId , sc . dashboardGuardianMock . User . UserId )
} )
} )
t . Run ( "Given user has permission to save" , func ( t * testing . T ) {
const canSave = true
t . Run ( "and overwrite flag is set to false" , func ( t * testing . T ) {
const shouldOverwrite = false
permissionScenario ( t , "When creating a dashboard in General folder with same name as dashboard in other folder" ,
canSave , func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : nil ,
"title" : sc . savedDashInFolder . Title ,
} ) ,
FolderId : 0 ,
Overwrite : shouldOverwrite ,
}
res := callSaveWithResult ( t , cmd , sc . sqlStore )
require . NotNil ( t , res )
dash , err := sc . sqlStore . GetDashboard ( res . Id , cmd . OrgId , "" , "" )
require . NoError ( t , err )
assert . Equal ( t , res . Id , dash . Id )
assert . Equal ( t , int64 ( 0 ) , dash . FolderId )
} )
permissionScenario ( t , "When creating a dashboard in other folder with same name as dashboard in General folder" ,
canSave , func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : nil ,
"title" : sc . savedDashInGeneralFolder . Title ,
} ) ,
FolderId : sc . savedFolder . Id ,
Overwrite : shouldOverwrite ,
}
res := callSaveWithResult ( t , cmd , sc . sqlStore )
require . NotNil ( t , res )
assert . NotEqual ( t , sc . savedDashInGeneralFolder . Id , res . Id )
dash , err := sc . sqlStore . GetDashboard ( res . Id , cmd . OrgId , "" , "" )
require . NoError ( t , err )
assert . Equal ( t , sc . savedFolder . Id , dash . FolderId )
} )
permissionScenario ( t , "When creating a folder with same name as dashboard in other folder" ,
canSave , func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : nil ,
"title" : sc . savedDashInFolder . Title ,
} ) ,
IsFolder : true ,
Overwrite : shouldOverwrite ,
}
res := callSaveWithResult ( t , cmd , sc . sqlStore )
require . NotNil ( t , res )
assert . NotEqual ( t , sc . savedDashInGeneralFolder . Id , res . Id )
assert . True ( t , res . IsFolder )
dash , err := sc . sqlStore . GetDashboard ( res . Id , cmd . OrgId , "" , "" )
require . NoError ( t , err )
assert . Equal ( t , int64 ( 0 ) , dash . FolderId )
assert . True ( t , dash . IsFolder )
} )
permissionScenario ( t , "When saving a dashboard without id and uid and unique title in folder" ,
canSave , func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"title" : "Dash without id and uid" ,
} ) ,
Overwrite : shouldOverwrite ,
}
res := callSaveWithResult ( t , cmd , sc . sqlStore )
require . NotNil ( t , res )
assert . Greater ( t , res . Id , int64 ( 0 ) )
assert . NotEmpty ( t , res . Uid )
dash , err := sc . sqlStore . GetDashboard ( res . Id , cmd . OrgId , "" , "" )
require . NoError ( t , err )
assert . Equal ( t , res . Id , dash . Id )
assert . Equal ( t , res . Uid , dash . Uid )
} )
permissionScenario ( t , "When saving a dashboard when dashboard id is zero " , canSave ,
func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : 0 ,
"title" : "Dash with zero id" ,
} ) ,
Overwrite : shouldOverwrite ,
}
res := callSaveWithResult ( t , cmd , sc . sqlStore )
require . NotNil ( t , res )
dash , err := sc . sqlStore . GetDashboard ( res . Id , cmd . OrgId , "" , "" )
require . NoError ( t , err )
assert . Equal ( t , res . Id , dash . Id )
} )
permissionScenario ( t , "When saving a dashboard in non-existing folder" , canSave ,
func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"title" : "Expect error" ,
} ) ,
FolderId : 123412321 ,
Overwrite : shouldOverwrite ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
assert . Equal ( t , models . ErrDashboardFolderNotFound , err )
} )
permissionScenario ( t , "When updating an existing dashboard by id without current version" , canSave ,
func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : 1 ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : sc . savedDashInGeneralFolder . Id ,
"title" : "test dash 23" ,
} ) ,
FolderId : sc . savedFolder . Id ,
Overwrite : shouldOverwrite ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
assert . Equal ( t , models . ErrDashboardVersionMismatch , err )
} )
permissionScenario ( t , "When updating an existing dashboard by id with current version" , canSave ,
func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : 1 ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : sc . savedDashInGeneralFolder . Id ,
"title" : "Updated title" ,
"version" : sc . savedDashInGeneralFolder . Version ,
} ) ,
FolderId : sc . savedFolder . Id ,
Overwrite : shouldOverwrite ,
}
res := callSaveWithResult ( t , cmd , sc . sqlStore )
require . NotNil ( t , res )
dash , err := sc . sqlStore . GetDashboard ( sc . savedDashInGeneralFolder . Id , cmd . OrgId , "" , "" )
require . NoError ( t , err )
assert . Equal ( t , "Updated title" , dash . Title )
assert . Equal ( t , sc . savedFolder . Id , dash . FolderId )
assert . Greater ( t , dash . Version , sc . savedDashInGeneralFolder . Version )
} )
permissionScenario ( t , "When updating an existing dashboard by uid without current version" , canSave ,
func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : 1 ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"uid" : sc . savedDashInFolder . Uid ,
"title" : "test dash 23" ,
} ) ,
FolderId : 0 ,
Overwrite : shouldOverwrite ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
assert . Equal ( t , models . ErrDashboardVersionMismatch , err )
} )
permissionScenario ( t , "When updating an existing dashboard by uid with current version" , canSave ,
func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : 1 ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"uid" : sc . savedDashInFolder . Uid ,
"title" : "Updated title" ,
"version" : sc . savedDashInFolder . Version ,
} ) ,
FolderId : 0 ,
Overwrite : shouldOverwrite ,
}
res := callSaveWithResult ( t , cmd , sc . sqlStore )
require . NotNil ( t , res )
dash , err := sc . sqlStore . GetDashboard ( sc . savedDashInFolder . Id , cmd . OrgId , "" , "" )
require . NoError ( t , err )
assert . Equal ( t , "Updated title" , dash . Title )
assert . Equal ( t , int64 ( 0 ) , dash . FolderId )
assert . Greater ( t , dash . Version , sc . savedDashInFolder . Version )
} )
permissionScenario ( t , "When creating a dashboard with same name as dashboard in other folder" ,
canSave , func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : nil ,
"title" : sc . savedDashInFolder . Title ,
} ) ,
FolderId : sc . savedDashInFolder . FolderId ,
Overwrite : shouldOverwrite ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
assert . Equal ( t , models . ErrDashboardWithSameNameInFolderExists , err )
} )
permissionScenario ( t , "When creating a dashboard with same name as dashboard in General folder" ,
canSave , func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : nil ,
"title" : sc . savedDashInGeneralFolder . Title ,
} ) ,
FolderId : sc . savedDashInGeneralFolder . FolderId ,
Overwrite : shouldOverwrite ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
assert . Equal ( t , models . ErrDashboardWithSameNameInFolderExists , err )
} )
permissionScenario ( t , "When creating a folder with same name as existing folder" , canSave ,
func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : nil ,
"title" : sc . savedFolder . Title ,
} ) ,
IsFolder : true ,
Overwrite : shouldOverwrite ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
assert . Equal ( t , models . ErrDashboardWithSameNameInFolderExists , err )
} )
} )
t . Run ( "and overwrite flag is set to true" , func ( t * testing . T ) {
const shouldOverwrite = true
permissionScenario ( t , "When updating an existing dashboard by id without current version" , canSave ,
func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : 1 ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : sc . savedDashInGeneralFolder . Id ,
"title" : "Updated title" ,
} ) ,
FolderId : sc . savedFolder . Id ,
Overwrite : shouldOverwrite ,
}
res := callSaveWithResult ( t , cmd , sc . sqlStore )
require . NotNil ( t , res )
dash , err := sc . sqlStore . GetDashboard ( sc . savedDashInGeneralFolder . Id , cmd . OrgId , "" , "" )
require . NoError ( t , err )
assert . Equal ( t , "Updated title" , dash . Title )
assert . Equal ( t , sc . savedFolder . Id , dash . FolderId )
assert . Greater ( t , dash . Version , sc . savedDashInGeneralFolder . Version )
} )
permissionScenario ( t , "When updating an existing dashboard by uid without current version" , canSave ,
func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : 1 ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"uid" : sc . savedDashInFolder . Uid ,
"title" : "Updated title" ,
} ) ,
FolderId : 0 ,
Overwrite : shouldOverwrite ,
}
res := callSaveWithResult ( t , cmd , sc . sqlStore )
require . NotNil ( t , res )
dash , err := sc . sqlStore . GetDashboard ( sc . savedDashInFolder . Id , cmd . OrgId , "" , "" )
require . NoError ( t , err )
assert . Equal ( t , "Updated title" , dash . Title )
assert . Equal ( t , int64 ( 0 ) , dash . FolderId )
assert . Greater ( t , dash . Version , sc . savedDashInFolder . Version )
} )
permissionScenario ( t , "When updating uid for existing dashboard using id" , canSave ,
func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : 1 ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : sc . savedDashInFolder . Id ,
"uid" : "new-uid" ,
"title" : sc . savedDashInFolder . Title ,
} ) ,
Overwrite : shouldOverwrite ,
}
res := callSaveWithResult ( t , cmd , sc . sqlStore )
require . NotNil ( t , res )
assert . Equal ( t , sc . savedDashInFolder . Id , res . Id )
assert . Equal ( t , "new-uid" , res . Uid )
dash , err := sc . sqlStore . GetDashboard ( sc . savedDashInFolder . Id , cmd . OrgId , "" , "" )
require . NoError ( t , err )
assert . Equal ( t , "new-uid" , dash . Uid )
assert . Greater ( t , dash . Version , sc . savedDashInFolder . Version )
} )
permissionScenario ( t , "When updating uid to an existing uid for existing dashboard using id" , canSave ,
func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : 1 ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : sc . savedDashInFolder . Id ,
"uid" : sc . savedDashInGeneralFolder . Uid ,
"title" : sc . savedDashInFolder . Title ,
} ) ,
Overwrite : shouldOverwrite ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
assert . Equal ( t , models . ErrDashboardWithSameUIDExists , err )
} )
permissionScenario ( t , "When creating a dashboard with same name as dashboard in other folder" , canSave ,
func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : nil ,
"title" : sc . savedDashInFolder . Title ,
} ) ,
FolderId : sc . savedDashInFolder . FolderId ,
Overwrite : shouldOverwrite ,
}
res := callSaveWithResult ( t , cmd , sc . sqlStore )
require . NotNil ( t , res )
assert . Equal ( t , sc . savedDashInFolder . Id , res . Id )
assert . Equal ( t , sc . savedDashInFolder . Uid , res . Uid )
dash , err := sc . sqlStore . GetDashboard ( res . Id , cmd . OrgId , "" , "" )
require . NoError ( t , err )
assert . Equal ( t , res . Id , dash . Id )
assert . Equal ( t , res . Uid , dash . Uid )
} )
permissionScenario ( t , "When creating a dashboard with same name as dashboard in General folder" , canSave ,
func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : testOrgID ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : nil ,
"title" : sc . savedDashInGeneralFolder . Title ,
} ) ,
FolderId : sc . savedDashInGeneralFolder . FolderId ,
Overwrite : shouldOverwrite ,
}
res := callSaveWithResult ( t , cmd , sc . sqlStore )
require . NotNil ( t , res )
assert . Equal ( t , sc . savedDashInGeneralFolder . Id , res . Id )
assert . Equal ( t , sc . savedDashInGeneralFolder . Uid , res . Uid )
dash , err := sc . sqlStore . GetDashboard ( res . Id , cmd . OrgId , "" , "" )
require . NoError ( t , err )
assert . Equal ( t , res . Id , dash . Id )
assert . Equal ( t , res . Uid , dash . Uid )
} )
permissionScenario ( t , "When updating existing folder to a dashboard using id" , canSave ,
func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : 1 ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : sc . savedFolder . Id ,
"title" : "new title" ,
} ) ,
IsFolder : false ,
Overwrite : shouldOverwrite ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
assert . Equal ( t , models . ErrDashboardTypeMismatch , err )
} )
permissionScenario ( t , "When updating existing dashboard to a folder using id" , canSave ,
func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : 1 ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : sc . savedDashInFolder . Id ,
"title" : "new folder title" ,
} ) ,
IsFolder : true ,
Overwrite : shouldOverwrite ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
assert . Equal ( t , models . ErrDashboardTypeMismatch , err )
} )
permissionScenario ( t , "When updating existing folder to a dashboard using uid" , canSave ,
func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : 1 ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"uid" : sc . savedFolder . Uid ,
"title" : "new title" ,
} ) ,
IsFolder : false ,
Overwrite : shouldOverwrite ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
assert . Equal ( t , models . ErrDashboardTypeMismatch , err )
} )
permissionScenario ( t , "When updating existing dashboard to a folder using uid" , canSave ,
func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : 1 ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"uid" : sc . savedDashInFolder . Uid ,
"title" : "new folder title" ,
} ) ,
IsFolder : true ,
Overwrite : shouldOverwrite ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
assert . Equal ( t , models . ErrDashboardTypeMismatch , err )
} )
permissionScenario ( t , "When updating existing folder to a dashboard using title" , canSave ,
func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : 1 ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"title" : sc . savedFolder . Title ,
} ) ,
IsFolder : false ,
Overwrite : shouldOverwrite ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
assert . Equal ( t , models . ErrDashboardWithSameNameAsFolder , err )
} )
permissionScenario ( t , "When updating existing dashboard to a folder using title" , canSave ,
func ( t * testing . T , sc * permissionScenarioContext ) {
cmd := models . SaveDashboardCommand {
OrgId : 1 ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"title" : sc . savedDashInGeneralFolder . Title ,
} ) ,
IsFolder : true ,
Overwrite : shouldOverwrite ,
}
err := callSaveWithError ( cmd , sc . sqlStore )
assert . Equal ( t , models . ErrDashboardFolderWithSameNameAsDashboard , err )
} )
} )
} )
} )
}
type permissionScenarioContext struct {
dashboardGuardianMock * guardian . FakeDashboardGuardian
sqlStore * sqlstore . SQLStore
savedFolder * models . Dashboard
savedDashInFolder * models . Dashboard
otherSavedFolder * models . Dashboard
savedDashInGeneralFolder * models . Dashboard
}
type permissionScenarioFunc func ( t * testing . T , sc * permissionScenarioContext )
func permissionScenario ( t * testing . T , desc string , canSave bool , fn permissionScenarioFunc ) {
t . Helper ( )
mock := & guardian . FakeDashboardGuardian {
CanSaveValue : canSave ,
}
t . Run ( desc , func ( t * testing . T ) {
sqlStore := sqlstore . InitTestDB ( t )
savedFolder := saveTestFolder ( t , "Saved folder" , testOrgID , sqlStore )
savedDashInFolder := saveTestDashboard ( t , "Saved dash in folder" , testOrgID , savedFolder . Id , sqlStore )
saveTestDashboard ( t , "Other saved dash in folder" , testOrgID , savedFolder . Id , sqlStore )
savedDashInGeneralFolder := saveTestDashboard ( t , "Saved dashboard in general folder" , testOrgID , 0 , sqlStore )
otherSavedFolder := saveTestFolder ( t , "Other saved folder" , testOrgID , sqlStore )
require . Equal ( t , "Saved folder" , savedFolder . Title )
require . Equal ( t , "saved-folder" , savedFolder . Slug )
require . NotEqual ( t , int64 ( 0 ) , savedFolder . Id )
require . True ( t , savedFolder . IsFolder )
require . Equal ( t , int64 ( 0 ) , savedFolder . FolderId )
require . NotEmpty ( t , savedFolder . Uid )
require . Equal ( t , "Saved dash in folder" , savedDashInFolder . Title )
require . Equal ( t , "saved-dash-in-folder" , savedDashInFolder . Slug )
require . NotEqual ( t , int64 ( 0 ) , savedDashInFolder . Id )
require . False ( t , savedDashInFolder . IsFolder )
require . Equal ( t , savedFolder . Id , savedDashInFolder . FolderId )
require . NotEmpty ( t , savedDashInFolder . Uid )
origNewDashboardGuardian := guardian . New
t . Cleanup ( func ( ) {
guardian . New = origNewDashboardGuardian
} )
guardian . MockDashboardGuardian ( mock )
sc := & permissionScenarioContext {
dashboardGuardianMock : mock ,
sqlStore : sqlStore ,
savedDashInFolder : savedDashInFolder ,
otherSavedFolder : otherSavedFolder ,
savedDashInGeneralFolder : savedDashInGeneralFolder ,
savedFolder : savedFolder ,
}
fn ( t , sc )
} )
}
func callSaveWithResult ( t * testing . T , cmd models . SaveDashboardCommand , sqlStore * sqlstore . SQLStore ) * models . Dashboard {
t . Helper ( )
dto := toSaveDashboardDto ( cmd )
2021-11-03 08:10:39 -05:00
res , err := NewService ( sqlStore ) . SaveDashboard ( context . Background ( ) , & dto , false )
2021-03-17 10:06:10 -05:00
require . NoError ( t , err )
return res
}
func callSaveWithError ( cmd models . SaveDashboardCommand , sqlStore * sqlstore . SQLStore ) error {
dto := toSaveDashboardDto ( cmd )
2021-11-03 08:10:39 -05:00
_ , err := NewService ( sqlStore ) . SaveDashboard ( context . Background ( ) , & dto , false )
2021-03-17 10:06:10 -05:00
return err
}
func saveTestDashboard ( t * testing . T , title string , orgID , folderID int64 , sqlStore * sqlstore . SQLStore ) * models . Dashboard {
t . Helper ( )
cmd := models . SaveDashboardCommand {
OrgId : orgID ,
FolderId : folderID ,
IsFolder : false ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : nil ,
"title" : title ,
} ) ,
}
dto := SaveDashboardDTO {
OrgId : orgID ,
Dashboard : cmd . GetDashboardModel ( ) ,
User : & models . SignedInUser {
UserId : 1 ,
OrgRole : models . ROLE_ADMIN ,
} ,
}
2021-11-03 08:10:39 -05:00
res , err := NewService ( sqlStore ) . SaveDashboard ( context . Background ( ) , & dto , false )
2021-03-17 10:06:10 -05:00
require . NoError ( t , err )
return res
}
func saveTestFolder ( t * testing . T , title string , orgID int64 , sqlStore * sqlstore . SQLStore ) * models . Dashboard {
t . Helper ( )
cmd := models . SaveDashboardCommand {
OrgId : orgID ,
FolderId : 0 ,
IsFolder : true ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"id" : nil ,
"title" : title ,
} ) ,
}
dto := SaveDashboardDTO {
OrgId : orgID ,
Dashboard : cmd . GetDashboardModel ( ) ,
User : & models . SignedInUser {
UserId : 1 ,
OrgRole : models . ROLE_ADMIN ,
} ,
}
2021-11-03 08:10:39 -05:00
res , err := NewService ( sqlStore ) . SaveDashboard ( context . Background ( ) , & dto , false )
2021-03-17 10:06:10 -05:00
require . NoError ( t , err )
return res
}
func toSaveDashboardDto ( cmd models . SaveDashboardCommand ) SaveDashboardDTO {
dash := ( & cmd ) . GetDashboardModel ( )
return SaveDashboardDTO {
Dashboard : dash ,
Message : cmd . Message ,
OrgId : cmd . OrgId ,
User : & models . SignedInUser { UserId : cmd . UserId } ,
Overwrite : cmd . Overwrite ,
}
}