2017-06-12 08:48:55 -05:00
package api
import (
"encoding/json"
2018-02-19 04:12:56 -06:00
"fmt"
2017-06-12 08:48:55 -05:00
"testing"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/bus"
2017-06-12 16:05:32 -05:00
"github.com/grafana/grafana/pkg/components/simplejson"
2020-03-04 05:57:20 -06:00
"github.com/grafana/grafana/pkg/models"
2018-10-13 00:53:28 -05:00
"github.com/grafana/grafana/pkg/services/alerting"
2017-12-12 09:15:24 -06:00
"github.com/grafana/grafana/pkg/services/dashboards"
2019-04-30 06:32:18 -05:00
"github.com/grafana/grafana/pkg/services/provisioning"
2017-12-15 07:19:49 -06:00
"github.com/grafana/grafana/pkg/setting"
2017-06-12 08:48:55 -05:00
. "github.com/smartystreets/goconvey/convey"
)
2018-02-19 04:12:56 -06:00
// This tests three main scenarios.
// If a user has access to execute an action on a dashboard:
// 1. and the dashboard is in a folder which does not have an acl
// 2. and the dashboard is in a folder which does have an acl
// 3. Post dashboard response tests
2018-01-30 07:09:30 -06:00
2017-06-12 08:48:55 -05:00
func TestDashboardApiEndpoint ( t * testing . T ) {
Convey ( "Given a dashboard with a parent folder which does not have an acl" , t , func ( ) {
2020-03-04 05:57:20 -06:00
fakeDash := models . NewDashboard ( "Child dash" )
2017-06-17 17:24:38 -05:00
fakeDash . Id = 1
2017-06-23 15:00:26 -05:00
fakeDash . FolderId = 1
2017-06-12 08:48:55 -05:00
fakeDash . HasAcl = false
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetDashboardsBySlugQuery ) error {
dashboards := [ ] * models . Dashboard { fakeDash }
2018-01-31 09:51:06 -06:00
query . Result = dashboards
return nil
} )
2020-03-04 05:57:20 -06:00
var getDashboardQueries [ ] * models . GetDashboardQuery
2018-01-29 14:23:07 -06:00
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetDashboardQuery ) error {
2017-06-12 08:48:55 -05:00
query . Result = fakeDash
2018-01-29 14:23:07 -06:00
getDashboardQueries = append ( getDashboardQueries , query )
2017-06-12 08:48:55 -05:00
return nil
} )
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetProvisionedDashboardDataByIdQuery ) error {
2019-04-30 06:32:18 -05:00
query . Result = nil
2018-04-10 03:48:10 -05:00
return nil
} )
2020-03-04 05:57:20 -06:00
viewerRole := models . ROLE_VIEWER
editorRole := models . ROLE_EDITOR
2017-06-22 16:43:55 -05:00
2020-03-04 05:57:20 -06:00
aclMockResp := [ ] * models . DashboardAclInfoDTO {
{ Role : & viewerRole , Permission : models . PERMISSION_VIEW } ,
{ Role : & editorRole , Permission : models . PERMISSION_EDIT } ,
2017-06-22 16:43:55 -05:00
}
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetDashboardAclInfoListQuery ) error {
2017-06-19 14:22:42 -05:00
query . Result = aclMockResp
return nil
} )
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetTeamsByUserQuery ) error {
query . Result = [ ] * models . TeamDTO { }
2017-06-22 16:43:55 -05:00
return nil
} )
2018-01-30 07:09:30 -06:00
// This tests two scenarios:
// 1. user is an org viewer
// 2. user is an org editor
2017-06-12 08:48:55 -05:00
Convey ( "When user is an Org Viewer" , func ( ) {
2020-03-04 05:57:20 -06:00
role := models . ROLE_VIEWER
2017-06-12 08:48:55 -05:00
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/db/child-dash" , "/api/dashboards/db/:slug" , role , func ( sc * scenarioContext ) {
2017-06-12 16:05:32 -05:00
dash := GetDashboardShouldReturn200 ( sc )
2017-06-12 08:48:55 -05:00
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by slug" , func ( ) {
So ( getDashboardQueries [ 0 ] . Slug , ShouldEqual , "child-dash" )
} )
2017-06-12 08:48:55 -05:00
Convey ( "Should not be able to edit or save dashboard" , func ( ) {
So ( dash . Meta . CanEdit , ShouldBeFalse )
So ( dash . Meta . CanSave , ShouldBeFalse )
2017-06-22 17:34:19 -05:00
So ( dash . Meta . CanAdmin , ShouldBeFalse )
2017-06-12 08:48:55 -05:00
} )
} )
2017-06-12 16:05:32 -05:00
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/uid/abcdefghi" , "/api/dashboards/uid/:uid" , role , func ( sc * scenarioContext ) {
2017-06-12 16:05:32 -05:00
dash := GetDashboardShouldReturn200 ( sc )
2017-06-12 08:48:55 -05:00
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by uid" , func ( ) {
So ( getDashboardQueries [ 0 ] . Uid , ShouldEqual , "abcdefghi" )
} )
2017-06-12 08:48:55 -05:00
Convey ( "Should not be able to edit or save dashboard" , func ( ) {
So ( dash . Meta . CanEdit , ShouldBeFalse )
So ( dash . Meta . CanSave , ShouldBeFalse )
2017-06-22 17:34:19 -05:00
So ( dash . Meta . CanAdmin , ShouldBeFalse )
2017-06-12 08:48:55 -05:00
} )
} )
2017-06-12 16:05:32 -05:00
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling DELETE on" , "DELETE" , "/api/dashboards/db/child-dash" , "/api/dashboards/db/:slug" , role , func ( sc * scenarioContext ) {
2019-04-10 06:29:10 -05:00
CallDeleteDashboardBySlug ( sc )
2017-06-12 16:05:32 -05:00
So ( sc . resp . Code , ShouldEqual , 403 )
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by slug" , func ( ) {
So ( getDashboardQueries [ 0 ] . Slug , ShouldEqual , "child-dash" )
} )
2017-06-12 16:05:32 -05:00
} )
2018-01-31 09:46:31 -06:00
loggedInUserScenarioWithRole ( "When calling DELETE on" , "DELETE" , "/api/dashboards/uid/abcdefghi" , "/api/dashboards/uid/:uid" , role , func ( sc * scenarioContext ) {
2018-03-22 06:37:35 -05:00
CallDeleteDashboardByUID ( sc )
2018-01-31 09:46:31 -06:00
So ( sc . resp . Code , ShouldEqual , 403 )
Convey ( "Should lookup dashboard by uid" , func ( ) {
So ( getDashboardQueries [ 0 ] . Uid , ShouldEqual , "abcdefghi" )
} )
2017-06-12 16:05:32 -05:00
} )
2017-06-13 17:28:34 -05:00
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/id/2/versions/1" , "/api/dashboards/id/:dashboardId/versions/:id" , role , func ( sc * scenarioContext ) {
CallGetDashboardVersion ( sc )
So ( sc . resp . Code , ShouldEqual , 403 )
} )
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/id/2/versions" , "/api/dashboards/id/:dashboardId/versions" , role , func ( sc * scenarioContext ) {
CallGetDashboardVersions ( sc )
So ( sc . resp . Code , ShouldEqual , 403 )
} )
2017-06-12 08:48:55 -05:00
} )
Convey ( "When user is an Org Editor" , func ( ) {
2020-03-04 05:57:20 -06:00
role := models . ROLE_EDITOR
2017-06-12 08:48:55 -05:00
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/db/child-dash" , "/api/dashboards/db/:slug" , role , func ( sc * scenarioContext ) {
2017-06-12 16:05:32 -05:00
dash := GetDashboardShouldReturn200 ( sc )
2017-06-12 08:48:55 -05:00
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by slug" , func ( ) {
So ( getDashboardQueries [ 0 ] . Slug , ShouldEqual , "child-dash" )
} )
2017-06-12 08:48:55 -05:00
Convey ( "Should be able to edit or save dashboard" , func ( ) {
So ( dash . Meta . CanEdit , ShouldBeTrue )
So ( dash . Meta . CanSave , ShouldBeTrue )
2017-06-22 17:34:19 -05:00
So ( dash . Meta . CanAdmin , ShouldBeFalse )
2017-06-12 08:48:55 -05:00
} )
} )
2017-06-12 16:05:32 -05:00
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/uid/abcdefghi" , "/api/dashboards/uid/:uid" , role , func ( sc * scenarioContext ) {
2017-06-12 16:05:32 -05:00
dash := GetDashboardShouldReturn200 ( sc )
2017-06-12 08:48:55 -05:00
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by uid" , func ( ) {
So ( getDashboardQueries [ 0 ] . Uid , ShouldEqual , "abcdefghi" )
} )
2017-06-12 08:48:55 -05:00
Convey ( "Should be able to edit or save dashboard" , func ( ) {
So ( dash . Meta . CanEdit , ShouldBeTrue )
So ( dash . Meta . CanSave , ShouldBeTrue )
2017-06-22 17:34:19 -05:00
So ( dash . Meta . CanAdmin , ShouldBeFalse )
2017-06-12 08:48:55 -05:00
} )
} )
2017-06-12 16:05:32 -05:00
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling DELETE on" , "DELETE" , "/api/dashboards/db/child-dash" , "/api/dashboards/db/:slug" , role , func ( sc * scenarioContext ) {
2019-04-10 06:29:10 -05:00
CallDeleteDashboardBySlug ( sc )
2017-06-12 16:05:32 -05:00
So ( sc . resp . Code , ShouldEqual , 200 )
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by slug" , func ( ) {
So ( getDashboardQueries [ 0 ] . Slug , ShouldEqual , "child-dash" )
} )
2017-06-12 16:05:32 -05:00
} )
2018-01-31 09:46:31 -06:00
loggedInUserScenarioWithRole ( "When calling DELETE on" , "DELETE" , "/api/dashboards/uid/abcdefghi" , "/api/dashboards/uid/:uid" , role , func ( sc * scenarioContext ) {
2018-03-22 06:37:35 -05:00
CallDeleteDashboardByUID ( sc )
2018-01-31 09:46:31 -06:00
So ( sc . resp . Code , ShouldEqual , 200 )
Convey ( "Should lookup dashboard by uid" , func ( ) {
So ( getDashboardQueries [ 0 ] . Uid , ShouldEqual , "abcdefghi" )
} )
2017-06-12 16:05:32 -05:00
} )
2017-06-13 17:28:34 -05:00
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/id/2/versions/1" , "/api/dashboards/id/:dashboardId/versions/:id" , role , func ( sc * scenarioContext ) {
CallGetDashboardVersion ( sc )
So ( sc . resp . Code , ShouldEqual , 200 )
} )
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/id/2/versions" , "/api/dashboards/id/:dashboardId/versions" , role , func ( sc * scenarioContext ) {
CallGetDashboardVersions ( sc )
So ( sc . resp . Code , ShouldEqual , 200 )
} )
2017-06-12 08:48:55 -05:00
} )
} )
Convey ( "Given a dashboard with a parent folder which has an acl" , t , func ( ) {
2020-03-04 05:57:20 -06:00
fakeDash := models . NewDashboard ( "Child dash" )
2017-06-17 17:24:38 -05:00
fakeDash . Id = 1
2017-06-23 15:00:26 -05:00
fakeDash . FolderId = 1
2017-06-12 08:48:55 -05:00
fakeDash . HasAcl = true
2017-12-15 07:19:49 -06:00
setting . ViewersCanEdit = false
2017-06-12 08:48:55 -05:00
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetProvisionedDashboardDataByIdQuery ) error {
2019-04-30 06:32:18 -05:00
query . Result = nil
2018-04-10 03:48:10 -05:00
return nil
} )
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetDashboardsBySlugQuery ) error {
dashboards := [ ] * models . Dashboard { fakeDash }
2018-01-31 09:51:06 -06:00
query . Result = dashboards
return nil
} )
2020-03-04 05:57:20 -06:00
aclMockResp := [ ] * models . DashboardAclInfoDTO {
2017-06-19 14:22:42 -05:00
{
DashboardId : 1 ,
2020-03-04 05:57:20 -06:00
Permission : models . PERMISSION_EDIT ,
2017-06-19 14:22:42 -05:00
UserId : 200 ,
} ,
}
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetDashboardAclInfoListQuery ) error {
2017-06-19 14:22:42 -05:00
query . Result = aclMockResp
return nil
} )
2020-03-04 05:57:20 -06:00
var getDashboardQueries [ ] * models . GetDashboardQuery
2018-01-29 14:23:07 -06:00
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetDashboardQuery ) error {
2017-06-12 08:48:55 -05:00
query . Result = fakeDash
2018-01-29 14:23:07 -06:00
getDashboardQueries = append ( getDashboardQueries , query )
2017-06-12 08:48:55 -05:00
return nil
} )
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetTeamsByUserQuery ) error {
query . Result = [ ] * models . TeamDTO { }
2017-06-12 08:48:55 -05:00
return nil
} )
2019-04-30 06:32:18 -05:00
hs := & HTTPServer {
Cfg : setting . NewCfg ( ) ,
}
2018-01-30 07:09:30 -06:00
// This tests six scenarios:
// 1. user is an org viewer AND has no permissions for this dashboard
// 2. user is an org editor AND has no permissions for this dashboard
// 3. user is an org viewer AND has been granted edit permission for the dashboard
// 4. user is an org viewer AND all viewers have edit permission for this dashboard
// 5. user is an org viewer AND has been granted an admin permission
// 6. user is an org editor AND has been granted a view permission
2017-06-12 08:48:55 -05:00
Convey ( "When user is an Org Viewer and has no permissions for this dashboard" , func ( ) {
2020-03-04 05:57:20 -06:00
role := models . ROLE_VIEWER
2017-06-12 08:48:55 -05:00
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/db/child-dash" , "/api/dashboards/db/:slug" , role , func ( sc * scenarioContext ) {
2019-04-30 06:32:18 -05:00
sc . handlerFunc = hs . GetDashboard
2017-06-12 08:48:55 -05:00
sc . fakeReqWithParams ( "GET" , sc . url , map [ string ] string { } ) . exec ( )
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by slug" , func ( ) {
So ( getDashboardQueries [ 0 ] . Slug , ShouldEqual , "child-dash" )
} )
2017-06-12 08:48:55 -05:00
Convey ( "Should be denied access" , func ( ) {
So ( sc . resp . Code , ShouldEqual , 403 )
} )
} )
2017-06-12 16:05:32 -05:00
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/uid/abcdefghi" , "/api/dashboards/uid/:uid" , role , func ( sc * scenarioContext ) {
2019-04-30 06:32:18 -05:00
sc . handlerFunc = hs . GetDashboard
2017-06-12 08:48:55 -05:00
sc . fakeReqWithParams ( "GET" , sc . url , map [ string ] string { } ) . exec ( )
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by uid" , func ( ) {
So ( getDashboardQueries [ 0 ] . Uid , ShouldEqual , "abcdefghi" )
} )
2017-06-12 08:48:55 -05:00
Convey ( "Should be denied access" , func ( ) {
So ( sc . resp . Code , ShouldEqual , 403 )
} )
} )
2017-06-12 16:05:32 -05:00
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling DELETE on" , "DELETE" , "/api/dashboards/db/child-dash" , "/api/dashboards/db/:slug" , role , func ( sc * scenarioContext ) {
2019-04-10 06:29:10 -05:00
CallDeleteDashboardBySlug ( sc )
2017-06-12 16:05:32 -05:00
So ( sc . resp . Code , ShouldEqual , 403 )
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by slug" , func ( ) {
So ( getDashboardQueries [ 0 ] . Slug , ShouldEqual , "child-dash" )
} )
2017-06-12 16:05:32 -05:00
} )
2018-01-31 09:46:31 -06:00
loggedInUserScenarioWithRole ( "When calling DELETE on" , "DELETE" , "/api/dashboards/uid/abcdefghi" , "/api/dashboards/uid/:uid" , role , func ( sc * scenarioContext ) {
2018-03-22 06:37:35 -05:00
CallDeleteDashboardByUID ( sc )
2018-01-31 09:46:31 -06:00
So ( sc . resp . Code , ShouldEqual , 403 )
Convey ( "Should lookup dashboard by uid" , func ( ) {
So ( getDashboardQueries [ 0 ] . Uid , ShouldEqual , "abcdefghi" )
} )
2017-06-12 16:05:32 -05:00
} )
2017-06-13 17:28:34 -05:00
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/id/2/versions/1" , "/api/dashboards/id/:dashboardId/versions/:id" , role , func ( sc * scenarioContext ) {
CallGetDashboardVersion ( sc )
So ( sc . resp . Code , ShouldEqual , 403 )
} )
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/id/2/versions" , "/api/dashboards/id/:dashboardId/versions" , role , func ( sc * scenarioContext ) {
CallGetDashboardVersions ( sc )
So ( sc . resp . Code , ShouldEqual , 403 )
} )
2017-06-12 08:48:55 -05:00
} )
Convey ( "When user is an Org Editor and has no permissions for this dashboard" , func ( ) {
2020-03-04 05:57:20 -06:00
role := models . ROLE_EDITOR
2017-06-12 16:05:32 -05:00
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/db/child-dash" , "/api/dashboards/db/:slug" , role , func ( sc * scenarioContext ) {
2019-04-30 06:32:18 -05:00
sc . handlerFunc = hs . GetDashboard
2017-06-12 08:48:55 -05:00
sc . fakeReqWithParams ( "GET" , sc . url , map [ string ] string { } ) . exec ( )
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by slug" , func ( ) {
So ( getDashboardQueries [ 0 ] . Slug , ShouldEqual , "child-dash" )
} )
2017-06-12 08:48:55 -05:00
Convey ( "Should be denied access" , func ( ) {
So ( sc . resp . Code , ShouldEqual , 403 )
} )
} )
2017-06-12 16:05:32 -05:00
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/uid/abcdefghi" , "/api/dashboards/uid/:uid" , role , func ( sc * scenarioContext ) {
2019-04-30 06:32:18 -05:00
sc . handlerFunc = hs . GetDashboard
2017-06-12 08:48:55 -05:00
sc . fakeReqWithParams ( "GET" , sc . url , map [ string ] string { } ) . exec ( )
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by uid" , func ( ) {
So ( getDashboardQueries [ 0 ] . Uid , ShouldEqual , "abcdefghi" )
} )
2017-06-12 08:48:55 -05:00
Convey ( "Should be denied access" , func ( ) {
So ( sc . resp . Code , ShouldEqual , 403 )
} )
} )
2017-06-12 16:05:32 -05:00
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling DELETE on" , "DELETE" , "/api/dashboards/db/child-dash" , "/api/dashboards/db/:slug" , role , func ( sc * scenarioContext ) {
2019-04-10 06:29:10 -05:00
CallDeleteDashboardBySlug ( sc )
2017-06-12 16:05:32 -05:00
So ( sc . resp . Code , ShouldEqual , 403 )
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by slug" , func ( ) {
So ( getDashboardQueries [ 0 ] . Slug , ShouldEqual , "child-dash" )
} )
2017-06-12 16:05:32 -05:00
} )
2018-01-31 09:46:31 -06:00
loggedInUserScenarioWithRole ( "When calling DELETE on" , "DELETE" , "/api/dashboards/uid/abcdefghi" , "/api/dashboards/uid/:uid" , role , func ( sc * scenarioContext ) {
2018-03-22 06:37:35 -05:00
CallDeleteDashboardByUID ( sc )
2018-01-31 09:46:31 -06:00
So ( sc . resp . Code , ShouldEqual , 403 )
Convey ( "Should lookup dashboard by uid" , func ( ) {
So ( getDashboardQueries [ 0 ] . Uid , ShouldEqual , "abcdefghi" )
} )
2017-06-12 16:05:32 -05:00
} )
2017-06-13 17:28:34 -05:00
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/id/2/versions/1" , "/api/dashboards/id/:dashboardId/versions/:id" , role , func ( sc * scenarioContext ) {
CallGetDashboardVersion ( sc )
So ( sc . resp . Code , ShouldEqual , 403 )
} )
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/id/2/versions" , "/api/dashboards/id/:dashboardId/versions" , role , func ( sc * scenarioContext ) {
CallGetDashboardVersions ( sc )
So ( sc . resp . Code , ShouldEqual , 403 )
} )
2017-06-12 08:48:55 -05:00
} )
Convey ( "When user is an Org Viewer but has an edit permission" , func ( ) {
2020-03-04 05:57:20 -06:00
role := models . ROLE_VIEWER
2017-06-12 16:05:32 -05:00
2020-03-04 05:57:20 -06:00
mockResult := [ ] * models . DashboardAclInfoDTO {
{ OrgId : 1 , DashboardId : 2 , UserId : 1 , Permission : models . PERMISSION_EDIT } ,
2017-06-12 08:48:55 -05:00
}
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetDashboardAclInfoListQuery ) error {
2017-06-12 08:48:55 -05:00
query . Result = mockResult
return nil
} )
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/db/child-dash" , "/api/dashboards/db/:slug" , role , func ( sc * scenarioContext ) {
2017-06-12 16:05:32 -05:00
dash := GetDashboardShouldReturn200 ( sc )
2017-06-12 08:48:55 -05:00
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by slug" , func ( ) {
So ( getDashboardQueries [ 0 ] . Slug , ShouldEqual , "child-dash" )
} )
2017-06-12 08:48:55 -05:00
Convey ( "Should be able to get dashboard with edit rights" , func ( ) {
So ( dash . Meta . CanEdit , ShouldBeTrue )
So ( dash . Meta . CanSave , ShouldBeTrue )
2017-06-22 17:34:19 -05:00
So ( dash . Meta . CanAdmin , ShouldBeFalse )
} )
} )
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/uid/abcdefghi" , "/api/dashboards/uid/:uid" , role , func ( sc * scenarioContext ) {
dash := GetDashboardShouldReturn200 ( sc )
Convey ( "Should lookup dashboard by uid" , func ( ) {
So ( getDashboardQueries [ 0 ] . Uid , ShouldEqual , "abcdefghi" )
} )
2017-06-12 08:48:55 -05:00
Convey ( "Should be able to get dashboard with edit rights" , func ( ) {
So ( dash . Meta . CanEdit , ShouldBeTrue )
So ( dash . Meta . CanSave , ShouldBeTrue )
2017-06-22 17:34:19 -05:00
So ( dash . Meta . CanAdmin , ShouldBeFalse )
} )
} )
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling DELETE on" , "DELETE" , "/api/dashboards/db/child-dash" , "/api/dashboards/db/:slug" , role , func ( sc * scenarioContext ) {
2019-04-10 06:29:10 -05:00
CallDeleteDashboardBySlug ( sc )
2017-06-22 17:34:19 -05:00
So ( sc . resp . Code , ShouldEqual , 200 )
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by slug" , func ( ) {
So ( getDashboardQueries [ 0 ] . Slug , ShouldEqual , "child-dash" )
} )
2017-06-22 17:34:19 -05:00
} )
2018-01-31 09:46:31 -06:00
loggedInUserScenarioWithRole ( "When calling DELETE on" , "DELETE" , "/api/dashboards/uid/abcdefghi" , "/api/dashboards/uid/:uid" , role , func ( sc * scenarioContext ) {
2018-03-22 06:37:35 -05:00
CallDeleteDashboardByUID ( sc )
2018-01-31 09:46:31 -06:00
So ( sc . resp . Code , ShouldEqual , 200 )
Convey ( "Should lookup dashboard by uid" , func ( ) {
So ( getDashboardQueries [ 0 ] . Uid , ShouldEqual , "abcdefghi" )
} )
2017-06-22 17:34:19 -05:00
} )
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/id/2/versions/1" , "/api/dashboards/id/:dashboardId/versions/:id" , role , func ( sc * scenarioContext ) {
CallGetDashboardVersion ( sc )
So ( sc . resp . Code , ShouldEqual , 200 )
} )
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/id/2/versions" , "/api/dashboards/id/:dashboardId/versions" , role , func ( sc * scenarioContext ) {
CallGetDashboardVersions ( sc )
So ( sc . resp . Code , ShouldEqual , 200 )
} )
} )
2017-12-15 07:19:49 -06:00
Convey ( "When user is an Org Viewer and viewers can edit" , func ( ) {
2020-03-04 05:57:20 -06:00
role := models . ROLE_VIEWER
2017-12-15 07:19:49 -06:00
setting . ViewersCanEdit = true
2020-03-04 05:57:20 -06:00
mockResult := [ ] * models . DashboardAclInfoDTO {
{ OrgId : 1 , DashboardId : 2 , UserId : 1 , Permission : models . PERMISSION_VIEW } ,
2017-12-15 07:19:49 -06:00
}
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetDashboardAclInfoListQuery ) error {
2017-12-15 07:19:49 -06:00
query . Result = mockResult
return nil
} )
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/db/child-dash" , "/api/dashboards/db/:slug" , role , func ( sc * scenarioContext ) {
2017-12-15 07:19:49 -06:00
dash := GetDashboardShouldReturn200 ( sc )
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by slug" , func ( ) {
So ( getDashboardQueries [ 0 ] . Slug , ShouldEqual , "child-dash" )
} )
2017-12-15 07:19:49 -06:00
Convey ( "Should be able to get dashboard with edit rights but can save should be false" , func ( ) {
So ( dash . Meta . CanEdit , ShouldBeTrue )
So ( dash . Meta . CanSave , ShouldBeFalse )
So ( dash . Meta . CanAdmin , ShouldBeFalse )
} )
} )
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/uid/abcdefghi" , "/api/dashboards/uid/:uid" , role , func ( sc * scenarioContext ) {
2017-12-15 07:19:49 -06:00
dash := GetDashboardShouldReturn200 ( sc )
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by uid" , func ( ) {
So ( getDashboardQueries [ 0 ] . Uid , ShouldEqual , "abcdefghi" )
} )
2017-12-15 07:19:49 -06:00
Convey ( "Should be able to get dashboard with edit rights but can save should be false" , func ( ) {
So ( dash . Meta . CanEdit , ShouldBeTrue )
So ( dash . Meta . CanSave , ShouldBeFalse )
So ( dash . Meta . CanAdmin , ShouldBeFalse )
} )
} )
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling DELETE on" , "DELETE" , "/api/dashboards/db/child-dash" , "/api/dashboards/db/:slug" , role , func ( sc * scenarioContext ) {
2019-04-10 06:29:10 -05:00
CallDeleteDashboardBySlug ( sc )
2017-12-15 07:19:49 -06:00
So ( sc . resp . Code , ShouldEqual , 403 )
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by slug" , func ( ) {
So ( getDashboardQueries [ 0 ] . Slug , ShouldEqual , "child-dash" )
} )
2017-12-15 07:19:49 -06:00
} )
2018-01-31 09:46:31 -06:00
loggedInUserScenarioWithRole ( "When calling DELETE on" , "DELETE" , "/api/dashboards/uid/abcdefghi" , "/api/dashboards/uid/:uid" , role , func ( sc * scenarioContext ) {
2018-03-22 06:37:35 -05:00
CallDeleteDashboardByUID ( sc )
2018-01-31 09:46:31 -06:00
So ( sc . resp . Code , ShouldEqual , 403 )
Convey ( "Should lookup dashboard by uid" , func ( ) {
So ( getDashboardQueries [ 0 ] . Uid , ShouldEqual , "abcdefghi" )
} )
2017-12-15 07:19:49 -06:00
} )
} )
2017-06-22 17:34:19 -05:00
Convey ( "When user is an Org Viewer but has an admin permission" , func ( ) {
2020-03-04 05:57:20 -06:00
role := models . ROLE_VIEWER
2017-06-22 17:34:19 -05:00
2020-03-04 05:57:20 -06:00
mockResult := [ ] * models . DashboardAclInfoDTO {
{ OrgId : 1 , DashboardId : 2 , UserId : 1 , Permission : models . PERMISSION_ADMIN } ,
2017-06-22 17:34:19 -05:00
}
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetDashboardAclInfoListQuery ) error {
2017-06-22 17:34:19 -05:00
query . Result = mockResult
return nil
} )
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/db/child-dash" , "/api/dashboards/db/:slug" , role , func ( sc * scenarioContext ) {
2017-06-22 17:34:19 -05:00
dash := GetDashboardShouldReturn200 ( sc )
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by slug" , func ( ) {
So ( getDashboardQueries [ 0 ] . Slug , ShouldEqual , "child-dash" )
} )
2017-06-22 17:34:19 -05:00
Convey ( "Should be able to get dashboard with edit rights" , func ( ) {
So ( dash . Meta . CanEdit , ShouldBeTrue )
So ( dash . Meta . CanSave , ShouldBeTrue )
So ( dash . Meta . CanAdmin , ShouldBeTrue )
2017-06-12 08:48:55 -05:00
} )
} )
2017-06-12 16:05:32 -05:00
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/uid/abcdefghi" , "/api/dashboards/uid/:uid" , role , func ( sc * scenarioContext ) {
2017-06-22 17:34:19 -05:00
dash := GetDashboardShouldReturn200 ( sc )
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by uid" , func ( ) {
So ( getDashboardQueries [ 0 ] . Uid , ShouldEqual , "abcdefghi" )
} )
2017-06-22 17:34:19 -05:00
Convey ( "Should be able to get dashboard with edit rights" , func ( ) {
So ( dash . Meta . CanEdit , ShouldBeTrue )
So ( dash . Meta . CanSave , ShouldBeTrue )
So ( dash . Meta . CanAdmin , ShouldBeTrue )
2017-06-12 08:48:55 -05:00
} )
} )
2017-06-12 16:05:32 -05:00
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling DELETE on" , "DELETE" , "/api/dashboards/db/child-dash" , "/api/dashboards/db/:slug" , role , func ( sc * scenarioContext ) {
2019-04-10 06:29:10 -05:00
CallDeleteDashboardBySlug ( sc )
2017-06-12 16:05:32 -05:00
So ( sc . resp . Code , ShouldEqual , 200 )
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by slug" , func ( ) {
So ( getDashboardQueries [ 0 ] . Slug , ShouldEqual , "child-dash" )
} )
2017-06-12 16:05:32 -05:00
} )
2018-01-31 09:46:31 -06:00
loggedInUserScenarioWithRole ( "When calling DELETE on" , "DELETE" , "/api/dashboards/uid/abcdefghi" , "/api/dashboards/uid/:uid" , role , func ( sc * scenarioContext ) {
2018-03-22 06:37:35 -05:00
CallDeleteDashboardByUID ( sc )
2018-01-31 09:46:31 -06:00
So ( sc . resp . Code , ShouldEqual , 200 )
Convey ( "Should lookup dashboard by uid" , func ( ) {
So ( getDashboardQueries [ 0 ] . Uid , ShouldEqual , "abcdefghi" )
} )
2017-06-12 16:05:32 -05:00
} )
2017-06-13 17:28:34 -05:00
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/id/2/versions/1" , "/api/dashboards/id/:dashboardId/versions/:id" , role , func ( sc * scenarioContext ) {
CallGetDashboardVersion ( sc )
So ( sc . resp . Code , ShouldEqual , 200 )
} )
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/id/2/versions" , "/api/dashboards/id/:dashboardId/versions" , role , func ( sc * scenarioContext ) {
CallGetDashboardVersions ( sc )
So ( sc . resp . Code , ShouldEqual , 200 )
} )
2017-06-12 08:48:55 -05:00
} )
Convey ( "When user is an Org Editor but has a view permission" , func ( ) {
2020-03-04 05:57:20 -06:00
role := models . ROLE_EDITOR
2017-06-12 16:05:32 -05:00
2020-03-04 05:57:20 -06:00
mockResult := [ ] * models . DashboardAclInfoDTO {
{ OrgId : 1 , DashboardId : 2 , UserId : 1 , Permission : models . PERMISSION_VIEW } ,
2017-06-12 08:48:55 -05:00
}
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetDashboardAclInfoListQuery ) error {
2017-06-12 08:48:55 -05:00
query . Result = mockResult
return nil
} )
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/db/child-dash" , "/api/dashboards/db/:slug" , role , func ( sc * scenarioContext ) {
2017-06-12 16:05:32 -05:00
dash := GetDashboardShouldReturn200 ( sc )
2017-06-12 08:48:55 -05:00
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by slug" , func ( ) {
So ( getDashboardQueries [ 0 ] . Slug , ShouldEqual , "child-dash" )
} )
Convey ( "Should not be able to edit or save dashboard" , func ( ) {
So ( dash . Meta . CanEdit , ShouldBeFalse )
So ( dash . Meta . CanSave , ShouldBeFalse )
} )
} )
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/uid/abcdefghi" , "/api/dashboards/uid/:uid" , role , func ( sc * scenarioContext ) {
2017-06-12 16:05:32 -05:00
dash := GetDashboardShouldReturn200 ( sc )
2017-06-12 08:48:55 -05:00
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by uid" , func ( ) {
So ( getDashboardQueries [ 0 ] . Uid , ShouldEqual , "abcdefghi" )
} )
2017-06-12 08:48:55 -05:00
Convey ( "Should not be able to edit or save dashboard" , func ( ) {
So ( dash . Meta . CanEdit , ShouldBeFalse )
So ( dash . Meta . CanSave , ShouldBeFalse )
} )
} )
2017-06-12 16:05:32 -05:00
2018-01-29 14:23:07 -06:00
loggedInUserScenarioWithRole ( "When calling DELETE on" , "DELETE" , "/api/dashboards/db/child-dash" , "/api/dashboards/db/:slug" , role , func ( sc * scenarioContext ) {
2019-04-10 06:29:10 -05:00
CallDeleteDashboardBySlug ( sc )
2017-06-12 16:05:32 -05:00
So ( sc . resp . Code , ShouldEqual , 403 )
2018-01-29 14:23:07 -06:00
Convey ( "Should lookup dashboard by slug" , func ( ) {
So ( getDashboardQueries [ 0 ] . Slug , ShouldEqual , "child-dash" )
} )
2017-06-12 16:05:32 -05:00
} )
2018-01-31 09:46:31 -06:00
loggedInUserScenarioWithRole ( "When calling DELETE on" , "DELETE" , "/api/dashboards/uid/abcdefghi" , "/api/dashboards/uid/:uid" , role , func ( sc * scenarioContext ) {
2018-03-22 06:37:35 -05:00
CallDeleteDashboardByUID ( sc )
2018-01-31 09:46:31 -06:00
So ( sc . resp . Code , ShouldEqual , 403 )
Convey ( "Should lookup dashboard by uid" , func ( ) {
So ( getDashboardQueries [ 0 ] . Uid , ShouldEqual , "abcdefghi" )
} )
2017-06-12 16:05:32 -05:00
} )
2017-06-13 17:28:34 -05:00
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/id/2/versions/1" , "/api/dashboards/id/:dashboardId/versions/:id" , role , func ( sc * scenarioContext ) {
CallGetDashboardVersion ( sc )
So ( sc . resp . Code , ShouldEqual , 403 )
} )
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/id/2/versions" , "/api/dashboards/id/:dashboardId/versions" , role , func ( sc * scenarioContext ) {
CallGetDashboardVersions ( sc )
So ( sc . resp . Code , ShouldEqual , 403 )
} )
2017-06-12 08:48:55 -05:00
} )
} )
2018-01-31 09:51:06 -06:00
Convey ( "Given two dashboards with the same title in different folders" , t , func ( ) {
2020-03-04 05:57:20 -06:00
dashOne := models . NewDashboard ( "dash" )
2018-01-31 09:51:06 -06:00
dashOne . Id = 2
dashOne . FolderId = 1
dashOne . HasAcl = false
2020-03-04 05:57:20 -06:00
dashTwo := models . NewDashboard ( "dash" )
2018-01-31 09:51:06 -06:00
dashTwo . Id = 4
dashTwo . FolderId = 3
dashTwo . HasAcl = false
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetProvisionedDashboardDataByIdQuery ) error {
2019-04-30 06:32:18 -05:00
query . Result = nil
2018-04-10 03:48:10 -05:00
return nil
} )
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetDashboardsBySlugQuery ) error {
dashboards := [ ] * models . Dashboard { dashOne , dashTwo }
2018-01-31 09:51:06 -06:00
query . Result = dashboards
return nil
} )
2020-03-04 05:57:20 -06:00
role := models . ROLE_EDITOR
2018-01-31 09:51:06 -06:00
loggedInUserScenarioWithRole ( "When calling DELETE on" , "DELETE" , "/api/dashboards/db/dash" , "/api/dashboards/db/:slug" , role , func ( sc * scenarioContext ) {
2019-04-10 06:29:10 -05:00
CallDeleteDashboardBySlug ( sc )
2018-01-31 09:51:06 -06:00
Convey ( "Should result in 412 Precondition failed" , func ( ) {
So ( sc . resp . Code , ShouldEqual , 412 )
2018-03-22 16:13:46 -05:00
result := sc . ToJSON ( )
2018-01-31 09:51:06 -06:00
So ( result . Get ( "status" ) . MustString ( ) , ShouldEqual , "multiple-slugs-exists" )
2020-03-04 05:57:20 -06:00
So ( result . Get ( "message" ) . MustString ( ) , ShouldEqual , models . ErrDashboardsWithSameSlugExists . Error ( ) )
2018-01-31 09:51:06 -06:00
} )
} )
} )
2018-02-19 04:12:56 -06:00
Convey ( "Post dashboard response tests" , t , func ( ) {
// This tests that a valid request returns correct response
Convey ( "Given a correct request for creating a dashboard" , func ( ) {
2020-03-04 05:57:20 -06:00
cmd := models . SaveDashboardCommand {
2018-02-19 04:12:56 -06:00
OrgId : 1 ,
UserId : 5 ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"title" : "Dash" ,
} ) ,
Overwrite : true ,
FolderId : 3 ,
IsFolder : false ,
Message : "msg" ,
}
mock := & dashboards . FakeDashboardService {
2020-03-04 05:57:20 -06:00
SaveDashboardResult : & models . Dashboard {
2018-02-19 04:12:56 -06:00
Id : 2 ,
Uid : "uid" ,
Title : "Dash" ,
Slug : "dash" ,
Version : 2 ,
} ,
}
postDashboardScenario ( "When calling POST on" , "/api/dashboards" , "/api/dashboards" , mock , cmd , func ( sc * scenarioContext ) {
CallPostDashboardShouldReturnSuccess ( sc )
Convey ( "It should call dashboard service with correct data" , func ( ) {
dto := mock . SavedDashboards [ 0 ]
So ( dto . OrgId , ShouldEqual , cmd . OrgId )
So ( dto . User . UserId , ShouldEqual , cmd . UserId )
So ( dto . Dashboard . FolderId , ShouldEqual , 3 )
So ( dto . Dashboard . Title , ShouldEqual , "Dash" )
So ( dto . Overwrite , ShouldBeTrue )
So ( dto . Message , ShouldEqual , "msg" )
} )
Convey ( "It should return correct response data" , func ( ) {
2018-03-22 16:13:46 -05:00
result := sc . ToJSON ( )
2018-02-19 04:12:56 -06:00
So ( result . Get ( "status" ) . MustString ( ) , ShouldEqual , "success" )
So ( result . Get ( "id" ) . MustInt64 ( ) , ShouldEqual , 2 )
So ( result . Get ( "uid" ) . MustString ( ) , ShouldEqual , "uid" )
So ( result . Get ( "slug" ) . MustString ( ) , ShouldEqual , "dash" )
So ( result . Get ( "url" ) . MustString ( ) , ShouldEqual , "/d/uid/dash" )
} )
} )
} )
// This tests that invalid requests returns expected error responses
Convey ( "Given incorrect requests for creating a dashboard" , func ( ) {
testCases := [ ] struct {
SaveError error
ExpectedStatusCode int
} {
2020-03-04 05:57:20 -06:00
{ SaveError : models . ErrDashboardNotFound , ExpectedStatusCode : 404 } ,
{ SaveError : models . ErrFolderNotFound , ExpectedStatusCode : 400 } ,
{ SaveError : models . ErrDashboardWithSameUIDExists , ExpectedStatusCode : 400 } ,
{ SaveError : models . ErrDashboardWithSameNameInFolderExists , ExpectedStatusCode : 412 } ,
{ SaveError : models . ErrDashboardVersionMismatch , ExpectedStatusCode : 412 } ,
{ SaveError : models . ErrDashboardTitleEmpty , ExpectedStatusCode : 400 } ,
{ SaveError : models . ErrDashboardFolderCannotHaveParent , ExpectedStatusCode : 400 } ,
2018-10-13 00:53:28 -05:00
{ SaveError : alerting . ValidationError { Reason : "Mu" } , ExpectedStatusCode : 422 } ,
2020-03-04 05:57:20 -06:00
{ SaveError : models . ErrDashboardFailedGenerateUniqueUid , ExpectedStatusCode : 500 } ,
{ SaveError : models . ErrDashboardTypeMismatch , ExpectedStatusCode : 400 } ,
{ SaveError : models . ErrDashboardFolderWithSameNameAsDashboard , ExpectedStatusCode : 400 } ,
{ SaveError : models . ErrDashboardWithSameNameAsFolder , ExpectedStatusCode : 400 } ,
{ SaveError : models . ErrDashboardFolderNameExists , ExpectedStatusCode : 400 } ,
{ SaveError : models . ErrDashboardUpdateAccessDenied , ExpectedStatusCode : 403 } ,
{ SaveError : models . ErrDashboardInvalidUid , ExpectedStatusCode : 400 } ,
{ SaveError : models . ErrDashboardUidToLong , ExpectedStatusCode : 400 } ,
{ SaveError : models . ErrDashboardCannotSaveProvisionedDashboard , ExpectedStatusCode : 400 } ,
{ SaveError : models . UpdatePluginDashboardError { PluginId : "plug" } , ExpectedStatusCode : 412 } ,
2018-02-19 04:12:56 -06:00
}
2020-03-04 05:57:20 -06:00
cmd := models . SaveDashboardCommand {
2018-02-19 04:12:56 -06:00
OrgId : 1 ,
Dashboard : simplejson . NewFromAny ( map [ string ] interface { } {
"title" : "" ,
} ) ,
}
for _ , tc := range testCases {
mock := & dashboards . FakeDashboardService {
SaveDashboardError : tc . SaveError ,
}
postDashboardScenario ( fmt . Sprintf ( "Expect '%s' error when calling POST on" , tc . SaveError . Error ( ) ) , "/api/dashboards" , "/api/dashboards" , mock , cmd , func ( sc * scenarioContext ) {
CallPostDashboard ( sc )
So ( sc . resp . Code , ShouldEqual , tc . ExpectedStatusCode )
} )
}
} )
} )
2018-02-27 10:53:30 -06:00
Convey ( "Given two dashboards being compared" , t , func ( ) {
2020-03-04 05:57:20 -06:00
mockResult := [ ] * models . DashboardAclInfoDTO { }
bus . AddHandler ( "test" , func ( query * models . GetDashboardAclInfoListQuery ) error {
2018-02-27 10:53:30 -06:00
query . Result = mockResult
return nil
} )
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetProvisionedDashboardDataByIdQuery ) error {
2019-04-30 06:32:18 -05:00
query . Result = nil
2018-04-10 03:48:10 -05:00
return nil
} )
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetDashboardVersionQuery ) error {
query . Result = & models . DashboardVersion {
2018-02-27 10:53:30 -06:00
Data : simplejson . NewFromAny ( map [ string ] interface { } {
"title" : "Dash" + string ( query . DashboardId ) ,
} ) ,
}
return nil
} )
cmd := dtos . CalculateDiffOptions {
Base : dtos . CalculateDiffTarget {
DashboardId : 1 ,
Version : 1 ,
} ,
New : dtos . CalculateDiffTarget {
DashboardId : 2 ,
Version : 2 ,
} ,
DiffType : "basic" ,
}
Convey ( "when user does not have permission" , func ( ) {
2020-03-04 05:57:20 -06:00
role := models . ROLE_VIEWER
2018-02-27 10:53:30 -06:00
postDiffScenario ( "When calling POST on" , "/api/dashboards/calculate-diff" , "/api/dashboards/calculate-diff" , cmd , role , func ( sc * scenarioContext ) {
CallPostDashboard ( sc )
So ( sc . resp . Code , ShouldEqual , 403 )
} )
} )
Convey ( "when user does have permission" , func ( ) {
2020-03-04 05:57:20 -06:00
role := models . ROLE_ADMIN
2018-02-27 10:53:30 -06:00
postDiffScenario ( "When calling POST on" , "/api/dashboards/calculate-diff" , "/api/dashboards/calculate-diff" , cmd , role , func ( sc * scenarioContext ) {
CallPostDashboard ( sc )
So ( sc . resp . Code , ShouldEqual , 200 )
} )
} )
} )
2019-03-06 07:38:40 -06:00
Convey ( "Given dashboard in folder being restored should restore to folder" , t , func ( ) {
2020-03-04 05:57:20 -06:00
fakeDash := models . NewDashboard ( "Child dash" )
2019-03-06 07:38:40 -06:00
fakeDash . Id = 2
fakeDash . FolderId = 1
fakeDash . HasAcl = false
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetDashboardQuery ) error {
2019-03-06 07:38:40 -06:00
query . Result = fakeDash
return nil
} )
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetDashboardVersionQuery ) error {
query . Result = & models . DashboardVersion {
2019-03-06 07:38:40 -06:00
DashboardId : 2 ,
Version : 1 ,
Data : fakeDash . Data ,
}
return nil
} )
mock := & dashboards . FakeDashboardService {
2020-03-04 05:57:20 -06:00
SaveDashboardResult : & models . Dashboard {
2019-03-06 07:38:40 -06:00
Id : 2 ,
Uid : "uid" ,
Title : "Dash" ,
Slug : "dash" ,
Version : 1 ,
} ,
}
cmd := dtos . RestoreDashboardVersionCommand {
Version : 1 ,
}
restoreDashboardVersionScenario ( "When calling POST on" , "/api/dashboards/id/1/restore" , "/api/dashboards/id/:dashboardId/restore" , mock , cmd , func ( sc * scenarioContext ) {
CallRestoreDashboardVersion ( sc )
So ( sc . resp . Code , ShouldEqual , 200 )
dto := mock . SavedDashboards [ 0 ]
So ( dto . Dashboard . FolderId , ShouldEqual , 1 )
So ( dto . Dashboard . Title , ShouldEqual , "Child dash" )
So ( dto . Message , ShouldEqual , "Restored from version 1" )
} )
} )
Convey ( "Given dashboard in general folder being restored should restore to general folder" , t , func ( ) {
2020-03-04 05:57:20 -06:00
fakeDash := models . NewDashboard ( "Child dash" )
2019-03-06 07:38:40 -06:00
fakeDash . Id = 2
fakeDash . HasAcl = false
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetDashboardQuery ) error {
2019-03-06 07:38:40 -06:00
query . Result = fakeDash
return nil
} )
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetDashboardVersionQuery ) error {
query . Result = & models . DashboardVersion {
2019-03-06 07:38:40 -06:00
DashboardId : 2 ,
Version : 1 ,
Data : fakeDash . Data ,
}
return nil
} )
mock := & dashboards . FakeDashboardService {
2020-03-04 05:57:20 -06:00
SaveDashboardResult : & models . Dashboard {
2019-03-06 07:38:40 -06:00
Id : 2 ,
Uid : "uid" ,
Title : "Dash" ,
Slug : "dash" ,
Version : 1 ,
} ,
}
cmd := dtos . RestoreDashboardVersionCommand {
Version : 1 ,
}
restoreDashboardVersionScenario ( "When calling POST on" , "/api/dashboards/id/1/restore" , "/api/dashboards/id/:dashboardId/restore" , mock , cmd , func ( sc * scenarioContext ) {
CallRestoreDashboardVersion ( sc )
So ( sc . resp . Code , ShouldEqual , 200 )
dto := mock . SavedDashboards [ 0 ]
So ( dto . Dashboard . FolderId , ShouldEqual , 0 )
So ( dto . Dashboard . Title , ShouldEqual , "Child dash" )
So ( dto . Message , ShouldEqual , "Restored from version 1" )
} )
} )
2019-04-10 06:29:10 -05:00
Convey ( "Given provisioned dashboard" , t , func ( ) {
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetDashboardsBySlugQuery ) error {
query . Result = [ ] * models . Dashboard { { } }
2019-04-10 06:29:10 -05:00
return nil
} )
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetDashboardQuery ) error {
query . Result = & models . Dashboard { Id : 1 , Data : & simplejson . Json { } }
2019-04-10 06:29:10 -05:00
return nil
} )
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetProvisionedDashboardDataByIdQuery ) error {
query . Result = & models . DashboardProvisioning { ExternalId : "/tmp/grafana/dashboards/test/dashboard1.json" }
2019-04-10 06:29:10 -05:00
return nil
} )
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetDashboardAclInfoListQuery ) error {
query . Result = [ ] * models . DashboardAclInfoDTO {
{ OrgId : TestOrgID , DashboardId : 1 , UserId : TestUserID , Permission : models . PERMISSION_EDIT } ,
2019-04-10 06:29:10 -05:00
}
return nil
} )
2020-03-04 05:57:20 -06:00
loggedInUserScenarioWithRole ( "When calling DELETE on" , "DELETE" , "/api/dashboards/db/dash" , "/api/dashboards/db/:slug" , models . ROLE_EDITOR , func ( sc * scenarioContext ) {
2019-04-10 06:29:10 -05:00
CallDeleteDashboardBySlug ( sc )
Convey ( "Should result in 400" , func ( ) {
So ( sc . resp . Code , ShouldEqual , 400 )
result := sc . ToJSON ( )
2020-03-04 05:57:20 -06:00
So ( result . Get ( "error" ) . MustString ( ) , ShouldEqual , models . ErrDashboardCannotDeleteProvisionedDashboard . Error ( ) )
2019-04-10 06:29:10 -05:00
} )
} )
2020-03-04 05:57:20 -06:00
loggedInUserScenarioWithRole ( "When calling DELETE on" , "DELETE" , "/api/dashboards/db/abcdefghi" , "/api/dashboards/db/:uid" , models . ROLE_EDITOR , func ( sc * scenarioContext ) {
2019-04-10 06:29:10 -05:00
CallDeleteDashboardByUID ( sc )
Convey ( "Should result in 400" , func ( ) {
So ( sc . resp . Code , ShouldEqual , 400 )
result := sc . ToJSON ( )
2020-03-04 05:57:20 -06:00
So ( result . Get ( "error" ) . MustString ( ) , ShouldEqual , models . ErrDashboardCannotDeleteProvisionedDashboard . Error ( ) )
2019-04-10 06:29:10 -05:00
} )
} )
2019-04-30 06:32:18 -05:00
2020-03-04 05:57:20 -06:00
loggedInUserScenarioWithRole ( "When calling GET on" , "GET" , "/api/dashboards/uid/dash" , "/api/dashboards/uid/:uid" , models . ROLE_EDITOR , func ( sc * scenarioContext ) {
2019-04-30 06:32:18 -05:00
mock := provisioning . NewProvisioningServiceMock ( )
mock . GetDashboardProvisionerResolvedPathFunc = func ( name string ) string {
return "/tmp/grafana/dashboards"
}
dash := GetDashboardShouldReturn200WithConfig ( sc , mock )
Convey ( "Should return relative path to provisioning file" , func ( ) {
So ( dash . Meta . ProvisionedExternalId , ShouldEqual , "test/dashboard1.json" )
} )
} )
2019-10-31 08:27:31 -05:00
2020-03-04 05:57:20 -06:00
loggedInUserScenarioWithRole ( "When allowUiUpdates is true and calling GET on" , "GET" , "/api/dashboards/uid/dash" , "/api/dashboards/uid/:uid" , models . ROLE_EDITOR , func ( sc * scenarioContext ) {
2019-10-31 08:27:31 -05:00
mock := provisioning . NewProvisioningServiceMock ( )
mock . GetDashboardProvisionerResolvedPathFunc = func ( name string ) string {
return "/tmp/grafana/dashboards"
}
mock . GetAllowUiUpdatesFromConfigFunc = func ( name string ) bool {
return true
}
hs := & HTTPServer {
Cfg : setting . NewCfg ( ) ,
ProvisioningService : mock ,
}
CallGetDashboard ( sc , hs )
So ( sc . resp . Code , ShouldEqual , 200 )
dash := dtos . DashboardFullWithMeta { }
err := json . NewDecoder ( sc . resp . Body ) . Decode ( & dash )
So ( err , ShouldBeNil )
Convey ( "Should have metadata that says Provisioned is false" , func ( ) {
So ( dash . Meta . Provisioned , ShouldEqual , false )
} )
} )
2019-04-10 06:29:10 -05:00
} )
2017-06-12 08:48:55 -05:00
}
2017-06-12 16:05:32 -05:00
2020-03-25 08:14:24 -05:00
func GetDashboardShouldReturn200WithConfig ( sc * scenarioContext , provisioningService provisioning . ProvisioningService ) dtos .
DashboardFullWithMeta {
2019-04-30 06:32:18 -05:00
if provisioningService == nil {
provisioningService = provisioning . NewProvisioningServiceMock ( )
}
hs := & HTTPServer {
Cfg : setting . NewCfg ( ) ,
ProvisioningService : provisioningService ,
}
CallGetDashboard ( sc , hs )
2017-06-12 16:05:32 -05:00
So ( sc . resp . Code , ShouldEqual , 200 )
dash := dtos . DashboardFullWithMeta { }
err := json . NewDecoder ( sc . resp . Body ) . Decode ( & dash )
So ( err , ShouldBeNil )
return dash
}
2019-04-30 06:32:18 -05:00
func GetDashboardShouldReturn200 ( sc * scenarioContext ) dtos . DashboardFullWithMeta {
return GetDashboardShouldReturn200WithConfig ( sc , nil )
}
func CallGetDashboard ( sc * scenarioContext , hs * HTTPServer ) {
sc . handlerFunc = hs . GetDashboard
2018-01-29 06:51:01 -06:00
sc . fakeReqWithParams ( "GET" , sc . url , map [ string ] string { } ) . exec ( )
}
2017-06-13 17:28:34 -05:00
func CallGetDashboardVersion ( sc * scenarioContext ) {
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetDashboardVersionQuery ) error {
query . Result = & models . DashboardVersion { }
2017-06-13 17:28:34 -05:00
return nil
} )
sc . handlerFunc = GetDashboardVersion
sc . fakeReqWithParams ( "GET" , sc . url , map [ string ] string { } ) . exec ( )
}
func CallGetDashboardVersions ( sc * scenarioContext ) {
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( query * models . GetDashboardVersionsQuery ) error {
query . Result = [ ] * models . DashboardVersionDTO { }
2017-06-13 17:28:34 -05:00
return nil
} )
sc . handlerFunc = GetDashboardVersions
sc . fakeReqWithParams ( "GET" , sc . url , map [ string ] string { } ) . exec ( )
}
2019-04-10 06:29:10 -05:00
func CallDeleteDashboardBySlug ( sc * scenarioContext ) {
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( cmd * models . DeleteDashboardCommand ) error {
2017-06-12 16:05:32 -05:00
return nil
} )
2019-04-10 06:29:10 -05:00
sc . handlerFunc = DeleteDashboardBySlug
2017-06-12 16:05:32 -05:00
sc . fakeReqWithParams ( "DELETE" , sc . url , map [ string ] string { } ) . exec ( )
}
2018-03-22 06:37:35 -05:00
func CallDeleteDashboardByUID ( sc * scenarioContext ) {
2020-03-04 05:57:20 -06:00
bus . AddHandler ( "test" , func ( cmd * models . DeleteDashboardCommand ) error {
2018-01-31 09:46:31 -06:00
return nil
} )
2018-03-22 06:37:35 -05:00
sc . handlerFunc = DeleteDashboardByUID
2018-01-31 09:46:31 -06:00
sc . fakeReqWithParams ( "DELETE" , sc . url , map [ string ] string { } ) . exec ( )
}
2017-06-12 16:05:32 -05:00
func CallPostDashboard ( sc * scenarioContext ) {
sc . fakeReqWithParams ( "POST" , sc . url , map [ string ] string { } ) . exec ( )
}
2019-03-06 07:38:40 -06:00
func CallRestoreDashboardVersion ( sc * scenarioContext ) {
sc . fakeReqWithParams ( "POST" , sc . url , map [ string ] string { } ) . exec ( )
}
2018-01-30 16:37:54 -06:00
func CallPostDashboardShouldReturnSuccess ( sc * scenarioContext ) {
CallPostDashboard ( sc )
So ( sc . resp . Code , ShouldEqual , 200 )
}
2019-10-31 08:27:31 -05:00
func ( m mockDashboardProvisioningService ) DeleteProvisionedDashboard ( dashboardId int64 , orgId int64 ) error {
panic ( "implement me" )
}
2020-03-04 05:57:20 -06:00
func postDashboardScenario ( desc string , url string , routePattern string , mock * dashboards . FakeDashboardService , cmd models . SaveDashboardCommand , fn scenarioFunc ) {
2017-06-12 16:05:32 -05:00
Convey ( desc + " " + url , func ( ) {
defer bus . ClearBusHandlers ( )
2019-02-11 14:12:01 -06:00
hs := HTTPServer {
2019-10-31 08:27:31 -05:00
Bus : bus . GetBus ( ) ,
Cfg : setting . NewCfg ( ) ,
ProvisioningService : provisioning . NewProvisioningServiceMock ( ) ,
2019-02-11 14:12:01 -06:00
}
2018-01-30 06:17:48 -06:00
sc := setupScenarioContext ( url )
2020-03-04 05:57:20 -06:00
sc . defaultHandler = Wrap ( func ( c * models . ReqContext ) Response {
2017-06-12 16:05:32 -05:00
sc . context = c
2020-03-04 05:57:20 -06:00
sc . context . SignedInUser = & models . SignedInUser { OrgId : cmd . OrgId , UserId : cmd . UserId }
2017-06-12 16:05:32 -05:00
2019-02-11 14:12:01 -06:00
return hs . PostDashboard ( c , cmd )
2017-06-12 16:05:32 -05:00
} )
2018-02-19 04:12:56 -06:00
origNewDashboardService := dashboards . NewService
dashboards . MockDashboardService ( mock )
2017-12-12 09:15:24 -06:00
2019-10-31 08:27:31 -05:00
origProvisioningService := dashboards . NewProvisioningService
dashboards . NewProvisioningService = func ( ) dashboards . DashboardProvisioningService {
return mockDashboardProvisioningService { }
}
2017-06-12 16:05:32 -05:00
sc . m . Post ( routePattern , sc . defaultHandler )
2018-02-19 04:12:56 -06:00
defer func ( ) {
dashboards . NewService = origNewDashboardService
2019-10-31 08:27:31 -05:00
dashboards . NewProvisioningService = origProvisioningService
2018-02-19 04:12:56 -06:00
} ( )
2017-06-12 16:05:32 -05:00
fn ( sc )
} )
}
2018-01-29 12:27:53 -06:00
2020-03-04 05:57:20 -06:00
func postDiffScenario ( desc string , url string , routePattern string , cmd dtos . CalculateDiffOptions , role models . RoleType , fn scenarioFunc ) {
2018-02-27 10:53:30 -06:00
Convey ( desc + " " + url , func ( ) {
defer bus . ClearBusHandlers ( )
sc := setupScenarioContext ( url )
2020-03-04 05:57:20 -06:00
sc . defaultHandler = Wrap ( func ( c * models . ReqContext ) Response {
2018-02-27 10:53:30 -06:00
sc . context = c
2020-03-04 05:57:20 -06:00
sc . context . SignedInUser = & models . SignedInUser {
2018-02-27 10:53:30 -06:00
OrgId : TestOrgID ,
UserId : TestUserID ,
}
sc . context . OrgRole = role
return CalculateDashboardDiff ( c , cmd )
} )
sc . m . Post ( routePattern , sc . defaultHandler )
fn ( sc )
} )
}
2019-03-06 07:38:40 -06:00
func restoreDashboardVersionScenario ( desc string , url string , routePattern string , mock * dashboards . FakeDashboardService , cmd dtos . RestoreDashboardVersionCommand , fn scenarioFunc ) {
Convey ( desc + " " + url , func ( ) {
defer bus . ClearBusHandlers ( )
hs := HTTPServer {
2019-10-31 08:27:31 -05:00
Cfg : setting . NewCfg ( ) ,
Bus : bus . GetBus ( ) ,
ProvisioningService : provisioning . NewProvisioningServiceMock ( ) ,
2019-03-06 07:38:40 -06:00
}
sc := setupScenarioContext ( url )
2020-03-04 05:57:20 -06:00
sc . defaultHandler = Wrap ( func ( c * models . ReqContext ) Response {
2019-03-06 07:38:40 -06:00
sc . context = c
2020-03-04 05:57:20 -06:00
sc . context . SignedInUser = & models . SignedInUser {
2019-03-06 07:38:40 -06:00
OrgId : TestOrgID ,
UserId : TestUserID ,
}
2020-03-04 05:57:20 -06:00
sc . context . OrgRole = models . ROLE_ADMIN
2019-03-06 07:38:40 -06:00
return hs . RestoreDashboardVersion ( c , cmd )
} )
2019-10-31 08:27:31 -05:00
origProvisioningService := dashboards . NewProvisioningService
dashboards . NewProvisioningService = func ( ) dashboards . DashboardProvisioningService {
return mockDashboardProvisioningService { }
}
2019-03-06 07:38:40 -06:00
origNewDashboardService := dashboards . NewService
dashboards . MockDashboardService ( mock )
sc . m . Post ( routePattern , sc . defaultHandler )
defer func ( ) {
dashboards . NewService = origNewDashboardService
2019-10-31 08:27:31 -05:00
dashboards . NewProvisioningService = origProvisioningService
2019-03-06 07:38:40 -06:00
} ( )
fn ( sc )
} )
}
2018-03-22 16:13:46 -05:00
func ( sc * scenarioContext ) ToJSON ( ) * simplejson . Json {
2018-01-29 12:27:53 -06:00
var result * simplejson . Json
err := json . NewDecoder ( sc . resp . Body ) . Decode ( & result )
So ( err , ShouldBeNil )
return result
}
2019-10-31 08:27:31 -05:00
type mockDashboardProvisioningService struct {
}
2020-03-04 05:57:20 -06:00
func ( m mockDashboardProvisioningService ) SaveProvisionedDashboard ( dto * dashboards . SaveDashboardDTO , provisioning * models . DashboardProvisioning ) ( * models . Dashboard , error ) {
2019-10-31 08:27:31 -05:00
panic ( "implement me" )
}
2020-03-04 05:57:20 -06:00
func ( m mockDashboardProvisioningService ) SaveFolderForProvisionedDashboards ( * dashboards . SaveDashboardDTO ) ( * models . Dashboard , error ) {
2019-10-31 08:27:31 -05:00
panic ( "implement me" )
}
2020-03-04 05:57:20 -06:00
func ( m mockDashboardProvisioningService ) GetProvisionedDashboardData ( name string ) ( [ ] * models . DashboardProvisioning , error ) {
2019-10-31 08:27:31 -05:00
panic ( "implement me" )
}
2020-03-04 05:57:20 -06:00
func ( mock mockDashboardProvisioningService ) GetProvisionedDashboardDataByDashboardId ( dashboardId int64 ) ( * models . DashboardProvisioning , error ) {
return & models . DashboardProvisioning { } , nil
2019-10-31 08:27:31 -05:00
}
func ( m mockDashboardProvisioningService ) UnprovisionDashboard ( dashboardId int64 ) error {
panic ( "implement me" )
}