2018-02-26 19:12:01 +01:00
package guardian
import (
2021-09-23 17:43:32 +02:00
"context"
2020-11-19 14:47:17 +01:00
"errors"
2018-02-26 19:12:01 +01:00
"fmt"
2018-04-08 15:06:22 +02:00
"runtime"
2018-02-26 19:12:01 +01:00
"testing"
2022-06-01 14:16:26 -04:00
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
2020-02-29 13:35:15 +01:00
"github.com/grafana/grafana/pkg/models"
2022-06-01 14:16:26 -04:00
"github.com/grafana/grafana/pkg/services/dashboards"
2022-03-21 10:49:49 +01:00
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
2020-11-24 12:10:32 +01:00
"github.com/grafana/grafana/pkg/setting"
2018-02-26 19:12:01 +01:00
)
2020-11-24 11:36:00 +01:00
const (
2018-04-08 15:06:22 +02:00
orgID = int64 ( 1 )
defaultDashboardID = int64 ( - 1 )
dashboardID = int64 ( 1 )
parentFolderID = int64 ( 2 )
childDashboardID = int64 ( 3 )
userID = int64 ( 1 )
otherUserID = int64 ( 2 )
teamID = int64 ( 1 )
otherTeamID = int64 ( 2 )
2020-11-24 11:36:00 +01:00
)
var (
adminRole = models . ROLE_ADMIN
editorRole = models . ROLE_EDITOR
viewerRole = models . ROLE_VIEWER
2018-04-08 15:06:22 +02:00
)
2018-02-26 19:12:01 +01:00
2018-04-08 15:06:22 +02:00
func TestGuardianAdmin ( t * testing . T ) {
2020-11-24 11:36:00 +01:00
orgRoleScenario ( "Given user has admin org role" , t , models . ROLE_ADMIN , func ( sc * scenarioContext ) {
// dashboard has default permissions
sc . defaultPermissionScenario ( USER , FULL_ACCESS )
// dashboard has user with permission
sc . dashboardPermissionScenario ( USER , models . PERMISSION_ADMIN , FULL_ACCESS )
sc . dashboardPermissionScenario ( USER , models . PERMISSION_EDIT , FULL_ACCESS )
sc . dashboardPermissionScenario ( USER , models . PERMISSION_VIEW , FULL_ACCESS )
// dashboard has team with permission
sc . dashboardPermissionScenario ( TEAM , models . PERMISSION_ADMIN , FULL_ACCESS )
sc . dashboardPermissionScenario ( TEAM , models . PERMISSION_EDIT , FULL_ACCESS )
sc . dashboardPermissionScenario ( TEAM , models . PERMISSION_VIEW , FULL_ACCESS )
// dashboard has editor role with permission
sc . dashboardPermissionScenario ( EDITOR , models . PERMISSION_ADMIN , FULL_ACCESS )
sc . dashboardPermissionScenario ( EDITOR , models . PERMISSION_EDIT , FULL_ACCESS )
sc . dashboardPermissionScenario ( EDITOR , models . PERMISSION_VIEW , FULL_ACCESS )
// dashboard has viewer role with permission
sc . dashboardPermissionScenario ( VIEWER , models . PERMISSION_ADMIN , FULL_ACCESS )
sc . dashboardPermissionScenario ( VIEWER , models . PERMISSION_EDIT , FULL_ACCESS )
sc . dashboardPermissionScenario ( VIEWER , models . PERMISSION_VIEW , FULL_ACCESS )
// parent folder has user with permission
sc . parentFolderPermissionScenario ( USER , models . PERMISSION_ADMIN , FULL_ACCESS )
sc . parentFolderPermissionScenario ( USER , models . PERMISSION_EDIT , FULL_ACCESS )
sc . parentFolderPermissionScenario ( USER , models . PERMISSION_VIEW , FULL_ACCESS )
// parent folder has team with permission
sc . parentFolderPermissionScenario ( TEAM , models . PERMISSION_ADMIN , FULL_ACCESS )
sc . parentFolderPermissionScenario ( TEAM , models . PERMISSION_EDIT , FULL_ACCESS )
sc . parentFolderPermissionScenario ( TEAM , models . PERMISSION_VIEW , FULL_ACCESS )
// parent folder has editor role with permission
sc . parentFolderPermissionScenario ( EDITOR , models . PERMISSION_ADMIN , FULL_ACCESS )
sc . parentFolderPermissionScenario ( EDITOR , models . PERMISSION_EDIT , FULL_ACCESS )
sc . parentFolderPermissionScenario ( EDITOR , models . PERMISSION_VIEW , FULL_ACCESS )
// parent folder has viewer role with permission
sc . parentFolderPermissionScenario ( VIEWER , models . PERMISSION_ADMIN , FULL_ACCESS )
sc . parentFolderPermissionScenario ( VIEWER , models . PERMISSION_EDIT , FULL_ACCESS )
sc . parentFolderPermissionScenario ( VIEWER , models . PERMISSION_VIEW , FULL_ACCESS )
2018-04-08 15:06:22 +02:00
})
}
2018-02-26 19:12:01 +01:00
2018-04-08 15:06:22 +02:00
func TestGuardianEditor ( t * testing . T ) {
2020-11-24 11:36:00 +01:00
orgRoleScenario ( "Given user has editor org role" , t , models . ROLE_EDITOR , func ( sc * scenarioContext ) {
// dashboard has default permissions
sc . defaultPermissionScenario ( USER , EDITOR_ACCESS )
// dashboard has user with permission
sc . dashboardPermissionScenario ( USER , models . PERMISSION_ADMIN , FULL_ACCESS )
sc . dashboardPermissionScenario ( USER , models . PERMISSION_EDIT , EDITOR_ACCESS )
sc . dashboardPermissionScenario ( USER , models . PERMISSION_VIEW , CAN_VIEW )
// dashboard has team with permission
sc . dashboardPermissionScenario ( TEAM , models . PERMISSION_ADMIN , FULL_ACCESS )
sc . dashboardPermissionScenario ( TEAM , models . PERMISSION_EDIT , EDITOR_ACCESS )
sc . dashboardPermissionScenario ( TEAM , models . PERMISSION_VIEW , CAN_VIEW )
// dashboard has editor role with permission
sc . dashboardPermissionScenario ( EDITOR , models . PERMISSION_ADMIN , FULL_ACCESS )
sc . dashboardPermissionScenario ( EDITOR , models . PERMISSION_EDIT , EDITOR_ACCESS )
sc . dashboardPermissionScenario ( EDITOR , models . PERMISSION_VIEW , VIEWER_ACCESS )
// dashboard has viewer role with permission
sc . dashboardPermissionScenario ( VIEWER , models . PERMISSION_ADMIN , NO_ACCESS )
sc . dashboardPermissionScenario ( VIEWER , models . PERMISSION_EDIT , NO_ACCESS )
sc . dashboardPermissionScenario ( VIEWER , models . PERMISSION_VIEW , NO_ACCESS )
// parent folder has user with permission
sc . parentFolderPermissionScenario ( USER , models . PERMISSION_ADMIN , FULL_ACCESS )
sc . parentFolderPermissionScenario ( USER , models . PERMISSION_EDIT , EDITOR_ACCESS )
sc . parentFolderPermissionScenario ( USER , models . PERMISSION_VIEW , VIEWER_ACCESS )
// parent folder has team with permission
sc . parentFolderPermissionScenario ( TEAM , models . PERMISSION_ADMIN , FULL_ACCESS )
sc . parentFolderPermissionScenario ( TEAM , models . PERMISSION_EDIT , EDITOR_ACCESS )
sc . parentFolderPermissionScenario ( TEAM , models . PERMISSION_VIEW , VIEWER_ACCESS )
// parent folder has editor role with permission
sc . parentFolderPermissionScenario ( EDITOR , models . PERMISSION_ADMIN , FULL_ACCESS )
sc . parentFolderPermissionScenario ( EDITOR , models . PERMISSION_EDIT , EDITOR_ACCESS )
sc . parentFolderPermissionScenario ( EDITOR , models . PERMISSION_VIEW , VIEWER_ACCESS )
// parent folder has viewer role with permission
sc . parentFolderPermissionScenario ( VIEWER , models . PERMISSION_ADMIN , NO_ACCESS )
sc . parentFolderPermissionScenario ( VIEWER , models . PERMISSION_EDIT , NO_ACCESS )
sc . parentFolderPermissionScenario ( VIEWER , models . PERMISSION_VIEW , NO_ACCESS )
2018-04-08 15:06:22 +02:00
})
}
2018-02-26 19:12:01 +01:00
2018-04-08 15:06:22 +02:00
func TestGuardianViewer ( t * testing . T ) {
2020-11-24 11:36:00 +01:00
orgRoleScenario ( "Given user has viewer org role" , t , models . ROLE_VIEWER , func ( sc * scenarioContext ) {
// dashboard has default permissions
sc . defaultPermissionScenario ( USER , VIEWER_ACCESS )
// dashboard has user with permission
sc . dashboardPermissionScenario ( USER , models . PERMISSION_ADMIN , FULL_ACCESS )
sc . dashboardPermissionScenario ( USER , models . PERMISSION_EDIT , EDITOR_ACCESS )
sc . dashboardPermissionScenario ( USER , models . PERMISSION_VIEW , VIEWER_ACCESS )
// dashboard has team with permission
sc . dashboardPermissionScenario ( TEAM , models . PERMISSION_ADMIN , FULL_ACCESS )
sc . dashboardPermissionScenario ( TEAM , models . PERMISSION_EDIT , EDITOR_ACCESS )
sc . dashboardPermissionScenario ( TEAM , models . PERMISSION_VIEW , VIEWER_ACCESS )
// dashboard has editor role with permission
sc . dashboardPermissionScenario ( EDITOR , models . PERMISSION_ADMIN , NO_ACCESS )
sc . dashboardPermissionScenario ( EDITOR , models . PERMISSION_EDIT , NO_ACCESS )
sc . dashboardPermissionScenario ( EDITOR , models . PERMISSION_VIEW , NO_ACCESS )
// dashboard has viewer role with permission
sc . dashboardPermissionScenario ( VIEWER , models . PERMISSION_ADMIN , FULL_ACCESS )
sc . dashboardPermissionScenario ( VIEWER , models . PERMISSION_EDIT , EDITOR_ACCESS )
sc . dashboardPermissionScenario ( VIEWER , models . PERMISSION_VIEW , VIEWER_ACCESS )
// parent folder has user with permission
sc . parentFolderPermissionScenario ( USER , models . PERMISSION_ADMIN , FULL_ACCESS )
sc . parentFolderPermissionScenario ( USER , models . PERMISSION_EDIT , EDITOR_ACCESS )
sc . parentFolderPermissionScenario ( USER , models . PERMISSION_VIEW , VIEWER_ACCESS )
// parent folder has team with permission
sc . parentFolderPermissionScenario ( TEAM , models . PERMISSION_ADMIN , FULL_ACCESS )
sc . parentFolderPermissionScenario ( TEAM , models . PERMISSION_EDIT , EDITOR_ACCESS )
sc . parentFolderPermissionScenario ( TEAM , models . PERMISSION_VIEW , VIEWER_ACCESS )
// parent folder has editor role with permission
sc . parentFolderPermissionScenario ( EDITOR , models . PERMISSION_ADMIN , NO_ACCESS )
sc . parentFolderPermissionScenario ( EDITOR , models . PERMISSION_EDIT , NO_ACCESS )
sc . parentFolderPermissionScenario ( EDITOR , models . PERMISSION_VIEW , NO_ACCESS )
// parent folder has viewer role with permission
sc . parentFolderPermissionScenario ( VIEWER , models . PERMISSION_ADMIN , FULL_ACCESS )
sc . parentFolderPermissionScenario ( VIEWER , models . PERMISSION_EDIT , EDITOR_ACCESS )
sc . parentFolderPermissionScenario ( VIEWER , models . PERMISSION_VIEW , VIEWER_ACCESS )
})
2018-06-19 11:10:17 +02:00
2020-11-24 11:36:00 +01:00
apiKeyScenario ( "Given api key with viewer role" , t , models . ROLE_VIEWER , func ( sc * scenarioContext ) {
// dashboard has default permissions
sc . defaultPermissionScenario ( VIEWER , VIEWER_ACCESS )
2018-04-08 15:06:22 +02:00
})
}
2018-02-26 19:12:01 +01:00
2018-06-19 12:34:34 +02:00
func ( sc * scenarioContext ) defaultPermissionScenario ( pt permissionType , flag permissionFlags ) {
2018-04-08 15:06:22 +02:00
_ , callerFile , callerLine , _ := runtime . Caller ( 1 )
sc . callerFile = callerFile
sc . callerLine = callerLine
2022-07-18 15:14:58 +02:00
existingPermissions := [] * models . DashboardACLInfoDTO {
2020-02-29 13:35:15 +01:00
toDto ( newEditorRolePermission ( defaultDashboardID , models . PERMISSION_EDIT )),
toDto ( newViewerRolePermission ( defaultDashboardID , models . PERMISSION_VIEW )),
2018-04-08 15:06:22 +02:00
}
2018-02-26 19:12:01 +01:00
2020-11-24 11:36:00 +01:00
permissionScenario ( "and existing permissions are the default permissions (everyone with editor role can edit, everyone with viewer role can view)" ,
dashboardID , sc , existingPermissions , func ( sc * scenarioContext ) {
sc . expectedFlags = flag
sc . verifyExpectedPermissionsFlags ()
sc . verifyDuplicatePermissionsShouldNotBeAllowed ()
sc . verifyUpdateDashboardPermissionsShouldBeAllowed ( pt )
sc . verifyUpdateDashboardPermissionsShouldNotBeAllowed ( pt )
})
2018-04-08 15:06:22 +02:00
}
2018-02-26 19:12:01 +01:00
2020-02-29 13:35:15 +01:00
func ( sc * scenarioContext ) dashboardPermissionScenario ( pt permissionType , permission models . PermissionType , flag permissionFlags ) {
2018-04-08 15:06:22 +02:00
_ , callerFile , callerLine , _ := runtime . Caller ( 1 )
sc . callerFile = callerFile
sc . callerLine = callerLine
2022-07-18 15:14:58 +02:00
var existingPermissions [] * models . DashboardACLInfoDTO
2018-04-08 15:06:22 +02:00
switch pt {
case USER :
2022-07-18 15:14:58 +02:00
existingPermissions = [] * models . DashboardACLInfoDTO {{ OrgId : orgID , DashboardId : dashboardID , UserId : userID , Permission : permission }}
2018-04-08 15:06:22 +02:00
case TEAM :
2022-07-18 15:14:58 +02:00
existingPermissions = [] * models . DashboardACLInfoDTO {{ OrgId : orgID , DashboardId : dashboardID , TeamId : teamID , Permission : permission }}
2018-04-08 15:06:22 +02:00
case EDITOR :
2022-07-18 15:14:58 +02:00
existingPermissions = [] * models . DashboardACLInfoDTO {{ OrgId : orgID , DashboardId : dashboardID , Role : & editorRole , Permission : permission }}
2018-04-08 15:06:22 +02:00
case VIEWER :
2022-07-18 15:14:58 +02:00
existingPermissions = [] * models . DashboardACLInfoDTO {{ OrgId : orgID , DashboardId : dashboardID , Role : & viewerRole , Permission : permission }}
2018-04-08 15:06:22 +02:00
}
2018-02-26 19:12:01 +01:00
2020-11-24 11:36:00 +01:00
permissionScenario ( fmt . Sprintf ( "and %s has permission to %s dashboard" , pt . String (), permission . String ()),
dashboardID , sc , existingPermissions , func ( sc * scenarioContext ) {
sc . expectedFlags = flag
sc . verifyExpectedPermissionsFlags ()
sc . verifyDuplicatePermissionsShouldNotBeAllowed ()
sc . verifyUpdateDashboardPermissionsShouldBeAllowed ( pt )
sc . verifyUpdateDashboardPermissionsShouldNotBeAllowed ( pt )
})
2018-04-08 15:06:22 +02:00
}
2018-02-26 19:12:01 +01:00
2020-02-29 13:35:15 +01:00
func ( sc * scenarioContext ) parentFolderPermissionScenario ( pt permissionType , permission models . PermissionType , flag permissionFlags ) {
2018-04-08 15:06:22 +02:00
_ , callerFile , callerLine , _ := runtime . Caller ( 1 )
sc . callerFile = callerFile
sc . callerLine = callerLine
2022-07-18 15:14:58 +02:00
var folderPermissionList [] * models . DashboardACLInfoDTO
2018-04-08 15:06:22 +02:00
switch pt {
case USER :
2022-07-18 15:14:58 +02:00
folderPermissionList = [] * models . DashboardACLInfoDTO {{ OrgId : orgID , DashboardId : parentFolderID ,
2020-11-24 11:36:00 +01:00
UserId : userID , Permission : permission , Inherited : true }}
2018-04-08 15:06:22 +02:00
case TEAM :
2022-07-18 15:14:58 +02:00
folderPermissionList = [] * models . DashboardACLInfoDTO {{ OrgId : orgID , DashboardId : parentFolderID , TeamId : teamID ,
2020-11-24 11:36:00 +01:00
Permission : permission , Inherited : true }}
2018-04-08 15:06:22 +02:00
case EDITOR :
2022-07-18 15:14:58 +02:00
folderPermissionList = [] * models . DashboardACLInfoDTO {{ OrgId : orgID , DashboardId : parentFolderID ,
2020-11-24 11:36:00 +01:00
Role : & editorRole , Permission : permission , Inherited : true }}
2018-04-08 15:06:22 +02:00
case VIEWER :
2022-07-18 15:14:58 +02:00
folderPermissionList = [] * models . DashboardACLInfoDTO {{ OrgId : orgID , DashboardId : parentFolderID ,
2020-11-24 11:36:00 +01:00
Role : & viewerRole , Permission : permission , Inherited : true }}
2018-04-08 15:06:22 +02:00
}
2018-02-26 19:12:01 +01:00
2020-11-24 11:36:00 +01:00
permissionScenario ( fmt . Sprintf ( "and parent folder has %s with permission to %s" , pt . String (), permission . String ()),
childDashboardID , sc , folderPermissionList , func ( sc * scenarioContext ) {
sc . expectedFlags = flag
sc . verifyExpectedPermissionsFlags ()
sc . verifyDuplicatePermissionsShouldNotBeAllowed ()
sc . verifyUpdateChildDashboardPermissionsShouldBeAllowed ( pt , permission )
sc . verifyUpdateChildDashboardPermissionsShouldNotBeAllowed ( pt , permission )
sc . verifyUpdateChildDashboardPermissionsWithOverrideShouldBeAllowed ( pt , permission )
sc . verifyUpdateChildDashboardPermissionsWithOverrideShouldNotBeAllowed ( pt , permission )
})
2018-02-26 19:12:01 +01:00
}
2018-04-08 15:06:22 +02:00
func ( sc * scenarioContext ) verifyExpectedPermissionsFlags () {
tc := fmt . Sprintf ( "should have permissions to %s" , sc . expectedFlags . String ())
2020-11-24 11:36:00 +01:00
sc . t . Run ( tc , func ( t * testing . T ) {
canAdmin , err := sc . g . CanAdmin ()
require . NoError ( t , err )
canEdit , err := sc . g . CanEdit ()
require . NoError ( t , err )
canSave , err := sc . g . CanSave ()
require . NoError ( t , err )
canView , err := sc . g . CanView ()
require . NoError ( t , err )
2018-04-08 15:06:22 +02:00
var actualFlag permissionFlags
2018-02-26 19:12:01 +01:00
2018-04-08 15:06:22 +02:00
if canAdmin {
actualFlag |= CAN_ADMIN
}
if canEdit {
actualFlag |= CAN_EDIT
}
if canSave {
actualFlag |= CAN_SAVE
}
if canView {
actualFlag |= CAN_VIEW
}
if actualFlag . noAccess () {
actualFlag = NO_ACCESS
}
2018-06-19 11:10:17 +02:00
if actualFlag & sc . expectedFlags != actualFlag {
2018-04-08 15:06:22 +02:00
sc . reportFailure ( tc , sc . expectedFlags . String (), actualFlag . String ())
}
2018-02-26 19:12:01 +01:00
2018-04-08 15:06:22 +02:00
sc . reportSuccess ()
2018-02-26 19:12:01 +01:00
})
}
2018-04-08 15:06:22 +02:00
func ( sc * scenarioContext ) verifyDuplicatePermissionsShouldNotBeAllowed () {
if ! sc . expectedFlags . canAdmin () {
return
}
tc := "When updating dashboard permissions with duplicate permission for user should not be allowed"
2020-11-24 11:36:00 +01:00
sc . t . Run ( tc , func ( t * testing . T ) {
2022-07-18 15:14:58 +02:00
p := [] * models . DashboardACL {
2020-02-29 13:35:15 +01:00
newDefaultUserPermission ( dashboardID , models . PERMISSION_VIEW ),
newDefaultUserPermission ( dashboardID , models . PERMISSION_ADMIN ),
2018-04-08 15:06:22 +02:00
}
sc . updatePermissions = p
2020-02-29 13:35:15 +01:00
_ , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , p )
2018-02-26 19:12:01 +01:00
2020-11-19 14:47:17 +01:00
if ! errors . Is ( err , ErrGuardianPermissionExists ) {
2018-04-08 15:06:22 +02:00
sc . reportFailure ( tc , ErrGuardianPermissionExists , err )
}
sc . reportSuccess ()
2018-02-26 19:12:01 +01:00
})
2018-04-08 15:06:22 +02:00
tc = "When updating dashboard permissions with duplicate permission for team should not be allowed"
2020-11-24 11:36:00 +01:00
sc . t . Run ( tc , func ( t * testing . T ) {
2022-07-18 15:14:58 +02:00
p := [] * models . DashboardACL {
2020-02-29 13:35:15 +01:00
newDefaultTeamPermission ( dashboardID , models . PERMISSION_VIEW ),
newDefaultTeamPermission ( dashboardID , models . PERMISSION_ADMIN ),
2018-04-08 15:06:22 +02:00
}
sc . updatePermissions = p
2020-02-29 13:35:15 +01:00
_ , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , p )
2020-11-19 14:47:17 +01:00
if ! errors . Is ( err , ErrGuardianPermissionExists ) {
2018-04-08 15:06:22 +02:00
sc . reportFailure ( tc , ErrGuardianPermissionExists , err )
2018-02-26 19:12:01 +01:00
}
2018-04-08 15:06:22 +02:00
sc . reportSuccess ()
})
tc = "When updating dashboard permissions with duplicate permission for editor role should not be allowed"
2020-11-24 11:36:00 +01:00
sc . t . Run ( tc , func ( t * testing . T ) {
2022-07-18 15:14:58 +02:00
p := [] * models . DashboardACL {
2020-02-29 13:35:15 +01:00
newEditorRolePermission ( dashboardID , models . PERMISSION_VIEW ),
newEditorRolePermission ( dashboardID , models . PERMISSION_ADMIN ),
2018-04-08 15:06:22 +02:00
}
sc . updatePermissions = p
2020-02-29 13:35:15 +01:00
_ , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , p )
2018-04-08 15:06:22 +02:00
2020-11-19 14:47:17 +01:00
if ! errors . Is ( err , ErrGuardianPermissionExists ) {
2018-04-08 15:06:22 +02:00
sc . reportFailure ( tc , ErrGuardianPermissionExists , err )
}
sc . reportSuccess ()
})
2018-02-26 19:12:01 +01:00
2018-04-08 15:06:22 +02:00
tc = "When updating dashboard permissions with duplicate permission for viewer role should not be allowed"
2020-11-24 11:36:00 +01:00
sc . t . Run ( tc , func ( t * testing . T ) {
2022-07-18 15:14:58 +02:00
p := [] * models . DashboardACL {
2020-02-29 13:35:15 +01:00
newViewerRolePermission ( dashboardID , models . PERMISSION_VIEW ),
newViewerRolePermission ( dashboardID , models . PERMISSION_ADMIN ),
2018-04-08 15:06:22 +02:00
}
sc . updatePermissions = p
2020-02-29 13:35:15 +01:00
_ , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , p )
2020-11-19 14:47:17 +01:00
if ! errors . Is ( err , ErrGuardianPermissionExists ) {
2018-04-08 15:06:22 +02:00
sc . reportFailure ( tc , ErrGuardianPermissionExists , err )
}
sc . reportSuccess ()
2018-02-26 19:12:01 +01:00
})
2018-04-08 15:06:22 +02:00
tc = "When updating dashboard permissions with duplicate permission for admin role should not be allowed"
2020-11-24 11:36:00 +01:00
sc . t . Run ( tc , func ( t * testing . T ) {
2022-07-18 15:14:58 +02:00
p := [] * models . DashboardACL {
2020-02-29 13:35:15 +01:00
newAdminRolePermission ( dashboardID , models . PERMISSION_ADMIN ),
2018-04-08 15:06:22 +02:00
}
sc . updatePermissions = p
2020-02-29 13:35:15 +01:00
_ , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , p )
2020-11-19 14:47:17 +01:00
if ! errors . Is ( err , ErrGuardianPermissionExists ) {
2018-04-08 15:06:22 +02:00
sc . reportFailure ( tc , ErrGuardianPermissionExists , err )
}
sc . reportSuccess ()
2018-02-26 19:12:01 +01:00
})
}
2018-04-08 15:06:22 +02:00
func ( sc * scenarioContext ) verifyUpdateDashboardPermissionsShouldBeAllowed ( pt permissionType ) {
if ! sc . expectedFlags . canAdmin () {
return
}
2020-02-29 13:35:15 +01:00
for _ , p := range [] models . PermissionType { models . PERMISSION_ADMIN , models . PERMISSION_EDIT , models . PERMISSION_VIEW } {
2018-04-08 15:06:22 +02:00
tc := fmt . Sprintf ( "When updating dashboard permissions with %s permissions should be allowed" , p . String ())
2020-11-24 11:36:00 +01:00
sc . t . Run ( tc , func ( t * testing . T ) {
2022-07-18 15:14:58 +02:00
permissionList := [] * models . DashboardACL {}
2018-04-08 15:06:22 +02:00
switch pt {
case USER :
2022-07-18 15:14:58 +02:00
permissionList = [] * models . DashboardACL {
2018-04-08 15:06:22 +02:00
newEditorRolePermission ( dashboardID , p ),
newViewerRolePermission ( dashboardID , p ),
newCustomUserPermission ( dashboardID , otherUserID , p ),
newDefaultTeamPermission ( dashboardID , p ),
}
case TEAM :
2022-07-18 15:14:58 +02:00
permissionList = [] * models . DashboardACL {
2018-04-08 15:06:22 +02:00
newEditorRolePermission ( dashboardID , p ),
newViewerRolePermission ( dashboardID , p ),
newDefaultUserPermission ( dashboardID , p ),
newCustomTeamPermission ( dashboardID , otherTeamID , p ),
}
case EDITOR , VIEWER :
2022-07-18 15:14:58 +02:00
permissionList = [] * models . DashboardACL {
2018-04-08 15:06:22 +02:00
newEditorRolePermission ( dashboardID , p ),
newViewerRolePermission ( dashboardID , p ),
newDefaultUserPermission ( dashboardID , p ),
newDefaultTeamPermission ( dashboardID , p ),
}
}
sc . updatePermissions = permissionList
2020-02-29 13:35:15 +01:00
ok , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , permissionList )
2018-04-08 15:06:22 +02:00
if err != nil {
sc . reportFailure ( tc , nil , err )
}
if ! ok {
sc . reportFailure ( tc , false , true )
}
sc . reportSuccess ()
})
}
}
func ( sc * scenarioContext ) verifyUpdateDashboardPermissionsShouldNotBeAllowed ( pt permissionType ) {
if sc . expectedFlags . canAdmin () {
return
}
2020-02-29 13:35:15 +01:00
for _ , p := range [] models . PermissionType { models . PERMISSION_ADMIN , models . PERMISSION_EDIT , models . PERMISSION_VIEW } {
2018-04-08 15:06:22 +02:00
tc := fmt . Sprintf ( "When updating dashboard permissions with %s permissions should NOT be allowed" , p . String ())
2020-11-24 11:36:00 +01:00
sc . t . Run ( tc , func ( t * testing . T ) {
2022-07-18 15:14:58 +02:00
permissionList := [] * models . DashboardACL {
2018-04-08 15:06:22 +02:00
newEditorRolePermission ( dashboardID , p ),
newViewerRolePermission ( dashboardID , p ),
}
switch pt {
case USER :
2022-07-18 15:14:58 +02:00
permissionList = append ( permissionList , [] * models . DashboardACL {
2018-04-08 15:06:22 +02:00
newCustomUserPermission ( dashboardID , otherUserID , p ),
newDefaultTeamPermission ( dashboardID , p ),
} ... )
case TEAM :
2022-07-18 15:14:58 +02:00
permissionList = append ( permissionList , [] * models . DashboardACL {
2018-04-08 15:06:22 +02:00
newDefaultUserPermission ( dashboardID , p ),
newCustomTeamPermission ( dashboardID , otherTeamID , p ),
} ... )
2020-12-01 09:53:27 +01:00
default :
// TODO: Handle other cases?
2018-04-08 15:06:22 +02:00
}
sc . updatePermissions = permissionList
2020-02-29 13:35:15 +01:00
ok , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , permissionList )
2018-04-08 15:06:22 +02:00
if err != nil {
sc . reportFailure ( tc , nil , err )
}
if ok {
sc . reportFailure ( tc , true , false )
}
sc . reportSuccess ()
})
}
}
2020-02-29 13:35:15 +01:00
func ( sc * scenarioContext ) verifyUpdateChildDashboardPermissionsShouldBeAllowed ( pt permissionType , parentFolderPermission models . PermissionType ) {
2018-04-08 15:06:22 +02:00
if ! sc . expectedFlags . canAdmin () {
return
}
2020-02-29 13:35:15 +01:00
for _ , p := range [] models . PermissionType { models . PERMISSION_ADMIN , models . PERMISSION_EDIT , models . PERMISSION_VIEW } {
2018-04-08 15:06:22 +02:00
tc := fmt . Sprintf ( "When updating child dashboard permissions with %s permissions should be allowed" , p . String ())
2020-11-24 11:36:00 +01:00
sc . t . Run ( tc , func ( t * testing . T ) {
2022-07-18 15:14:58 +02:00
permissionList := [] * models . DashboardACL {}
2018-04-08 15:06:22 +02:00
switch pt {
case USER :
2022-07-18 15:14:58 +02:00
permissionList = [] * models . DashboardACL {
2018-04-08 15:06:22 +02:00
newEditorRolePermission ( childDashboardID , p ),
newViewerRolePermission ( childDashboardID , p ),
newCustomUserPermission ( childDashboardID , otherUserID , p ),
newDefaultTeamPermission ( childDashboardID , p ),
}
case TEAM :
2022-07-18 15:14:58 +02:00
permissionList = [] * models . DashboardACL {
2018-04-08 15:06:22 +02:00
newEditorRolePermission ( childDashboardID , p ),
newViewerRolePermission ( childDashboardID , p ),
newDefaultUserPermission ( childDashboardID , p ),
newCustomTeamPermission ( childDashboardID , otherTeamID , p ),
}
case EDITOR :
2022-07-18 15:14:58 +02:00
permissionList = [] * models . DashboardACL {
2018-04-08 15:06:22 +02:00
newViewerRolePermission ( childDashboardID , p ),
newDefaultUserPermission ( childDashboardID , p ),
newDefaultTeamPermission ( childDashboardID , p ),
}
// permission to update is higher than parent folder permission
if p > parentFolderPermission {
permissionList = append ( permissionList , newEditorRolePermission ( childDashboardID , p ))
}
case VIEWER :
2022-07-18 15:14:58 +02:00
permissionList = [] * models . DashboardACL {
2018-04-08 15:06:22 +02:00
newEditorRolePermission ( childDashboardID , p ),
newDefaultUserPermission ( childDashboardID , p ),
newDefaultTeamPermission ( childDashboardID , p ),
}
// permission to update is higher than parent folder permission
if p > parentFolderPermission {
permissionList = append ( permissionList , newViewerRolePermission ( childDashboardID , p ))
}
}
sc . updatePermissions = permissionList
2020-02-29 13:35:15 +01:00
ok , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , permissionList )
2018-04-08 15:06:22 +02:00
if err != nil {
sc . reportFailure ( tc , nil , err )
}
if ! ok {
sc . reportFailure ( tc , false , true )
}
sc . reportSuccess ()
})
}
}
2020-02-29 13:35:15 +01:00
func ( sc * scenarioContext ) verifyUpdateChildDashboardPermissionsShouldNotBeAllowed ( pt permissionType , parentFolderPermission models . PermissionType ) {
2018-04-08 15:06:22 +02:00
if sc . expectedFlags . canAdmin () {
return
}
2020-02-29 13:35:15 +01:00
for _ , p := range [] models . PermissionType { models . PERMISSION_ADMIN , models . PERMISSION_EDIT , models . PERMISSION_VIEW } {
2018-04-08 15:06:22 +02:00
tc := fmt . Sprintf ( "When updating child dashboard permissions with %s permissions should NOT be allowed" , p . String ())
2020-11-24 11:36:00 +01:00
sc . t . Run ( tc , func ( t * testing . T ) {
2022-07-18 15:14:58 +02:00
permissionList := [] * models . DashboardACL {}
2018-04-08 15:06:22 +02:00
switch pt {
case USER :
2022-07-18 15:14:58 +02:00
permissionList = [] * models . DashboardACL {
2018-04-08 15:06:22 +02:00
newEditorRolePermission ( childDashboardID , p ),
newViewerRolePermission ( childDashboardID , p ),
newCustomUserPermission ( childDashboardID , otherUserID , p ),
newDefaultTeamPermission ( childDashboardID , p ),
}
case TEAM :
2022-07-18 15:14:58 +02:00
permissionList = [] * models . DashboardACL {
2018-04-08 15:06:22 +02:00
newEditorRolePermission ( childDashboardID , p ),
newViewerRolePermission ( childDashboardID , p ),
newDefaultUserPermission ( childDashboardID , p ),
newCustomTeamPermission ( childDashboardID , otherTeamID , p ),
}
case EDITOR :
2022-07-18 15:14:58 +02:00
permissionList = [] * models . DashboardACL {
2018-04-08 15:06:22 +02:00
newViewerRolePermission ( childDashboardID , p ),
newDefaultUserPermission ( childDashboardID , p ),
newDefaultTeamPermission ( childDashboardID , p ),
}
2020-06-01 17:11:25 +02:00
// permission to update is higher than parent folder permission
2018-04-08 15:06:22 +02:00
if p > parentFolderPermission {
permissionList = append ( permissionList , newEditorRolePermission ( childDashboardID , p ))
}
case VIEWER :
2022-07-18 15:14:58 +02:00
permissionList = [] * models . DashboardACL {
2018-04-08 15:06:22 +02:00
newEditorRolePermission ( childDashboardID , p ),
newDefaultUserPermission ( childDashboardID , p ),
newDefaultTeamPermission ( childDashboardID , p ),
}
2020-06-01 17:11:25 +02:00
// permission to update is higher than parent folder permission
2018-04-08 15:06:22 +02:00
if p > parentFolderPermission {
permissionList = append ( permissionList , newViewerRolePermission ( childDashboardID , p ))
}
}
sc . updatePermissions = permissionList
2020-02-29 13:35:15 +01:00
ok , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , permissionList )
2018-04-08 15:06:22 +02:00
if err != nil {
sc . reportFailure ( tc , nil , err )
}
if ok {
sc . reportFailure ( tc , true , false )
}
sc . reportSuccess ()
})
2018-02-26 19:12:01 +01:00
}
}
2020-02-29 13:35:15 +01:00
func ( sc * scenarioContext ) verifyUpdateChildDashboardPermissionsWithOverrideShouldBeAllowed ( pt permissionType , parentFolderPermission models . PermissionType ) {
2018-04-08 15:06:22 +02:00
if ! sc . expectedFlags . canAdmin () {
return
}
2020-02-29 13:35:15 +01:00
for _ , p := range [] models . PermissionType { models . PERMISSION_ADMIN , models . PERMISSION_EDIT , models . PERMISSION_VIEW } {
2020-06-01 17:11:25 +02:00
// permission to update is higher than parent folder permission
2018-04-08 15:06:22 +02:00
if p > parentFolderPermission {
continue
}
tc := fmt . Sprintf ( "When updating child dashboard permissions overriding parent %s permission with %s permission should NOT be allowed" , pt . String (), p . String ())
2020-11-24 11:36:00 +01:00
sc . t . Run ( tc , func ( t * testing . T ) {
2022-07-18 15:14:58 +02:00
permissionList := [] * models . DashboardACL {}
2018-04-08 15:06:22 +02:00
switch pt {
case USER :
2022-07-18 15:14:58 +02:00
permissionList = [] * models . DashboardACL {
2018-04-08 15:06:22 +02:00
newDefaultUserPermission ( childDashboardID , p ),
}
case TEAM :
2022-07-18 15:14:58 +02:00
permissionList = [] * models . DashboardACL {
2018-04-08 15:06:22 +02:00
newDefaultTeamPermission ( childDashboardID , p ),
}
case EDITOR :
2022-07-18 15:14:58 +02:00
permissionList = [] * models . DashboardACL {
2018-04-08 15:06:22 +02:00
newEditorRolePermission ( childDashboardID , p ),
}
case VIEWER :
2022-07-18 15:14:58 +02:00
permissionList = [] * models . DashboardACL {
2018-04-08 15:06:22 +02:00
newViewerRolePermission ( childDashboardID , p ),
}
}
sc . updatePermissions = permissionList
2020-02-29 13:35:15 +01:00
_ , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , permissionList )
2020-11-19 14:47:17 +01:00
if ! errors . Is ( err , ErrGuardianOverride ) {
2018-04-08 15:06:22 +02:00
sc . reportFailure ( tc , ErrGuardianOverride , err )
}
sc . reportSuccess ()
})
2018-02-26 19:12:01 +01:00
}
}
2020-02-29 13:35:15 +01:00
func ( sc * scenarioContext ) verifyUpdateChildDashboardPermissionsWithOverrideShouldNotBeAllowed ( pt permissionType , parentFolderPermission models . PermissionType ) {
2018-04-08 15:06:22 +02:00
if ! sc . expectedFlags . canAdmin () {
return
}
2020-02-29 13:35:15 +01:00
for _ , p := range [] models . PermissionType { models . PERMISSION_ADMIN , models . PERMISSION_EDIT , models . PERMISSION_VIEW } {
2020-06-01 17:11:25 +02:00
// permission to update is lower than or equal to parent folder permission
2018-04-08 15:06:22 +02:00
if p <= parentFolderPermission {
continue
}
2020-11-24 11:36:00 +01:00
tc := fmt . Sprintf (
"When updating child dashboard permissions overriding parent %s permission with %s permission should be allowed" ,
pt . String (), p . String (),
)
sc . t . Run ( tc , func ( t * testing . T ) {
2022-07-18 15:14:58 +02:00
permissionList := [] * models . DashboardACL {}
2018-04-08 15:06:22 +02:00
switch pt {
case USER :
2022-07-18 15:14:58 +02:00
permissionList = [] * models . DashboardACL {
2018-04-08 15:06:22 +02:00
newDefaultUserPermission ( childDashboardID , p ),
}
case TEAM :
2022-07-18 15:14:58 +02:00
permissionList = [] * models . DashboardACL {
2018-04-08 15:06:22 +02:00
newDefaultTeamPermission ( childDashboardID , p ),
}
case EDITOR :
2022-07-18 15:14:58 +02:00
permissionList = [] * models . DashboardACL {
2018-04-08 15:06:22 +02:00
newEditorRolePermission ( childDashboardID , p ),
}
case VIEWER :
2022-07-18 15:14:58 +02:00
permissionList = [] * models . DashboardACL {
2018-04-08 15:06:22 +02:00
newViewerRolePermission ( childDashboardID , p ),
}
}
2020-02-29 13:35:15 +01:00
_ , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , permissionList )
2018-04-23 19:28:54 +02:00
if err != nil {
sc . reportFailure ( tc , nil , err )
}
2018-04-08 15:06:22 +02:00
sc . updatePermissions = permissionList
2020-02-29 13:35:15 +01:00
ok , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , permissionList )
2018-04-08 15:06:22 +02:00
if err != nil {
sc . reportFailure ( tc , nil , err )
}
if ! ok {
sc . reportFailure ( tc , false , true )
}
sc . reportSuccess ()
})
2018-02-26 19:12:01 +01:00
}
}
2020-11-24 12:10:32 +01:00
func TestGuardianGetHiddenACL ( t * testing . T ) {
2021-10-27 14:45:20 +02:00
t . Run ( "Get hidden ACL tests" , func ( t * testing . T ) {
2022-03-21 10:49:49 +01:00
store := mockstore . NewSQLStoreMock ()
2022-06-01 14:16:26 -04:00
dashSvc := dashboards . NewFakeDashboardService ( t )
2022-07-18 15:14:58 +02:00
dashSvc . On ( "GetDashboardACLInfoList" , mock . Anything , mock . AnythingOfType ( "*models.GetDashboardACLInfoListQuery" )). Run ( func ( args mock . Arguments ) {
q := args . Get ( 1 ).( * models . GetDashboardACLInfoListQuery )
q . Result = [] * models . DashboardACLInfoDTO {
2022-06-01 14:16:26 -04:00
{ Inherited : false , UserId : 1 , UserLogin : "user1" , Permission : models . PERMISSION_EDIT },
{ Inherited : false , UserId : 2 , UserLogin : "user2" , Permission : models . PERMISSION_ADMIN },
{ Inherited : true , UserId : 3 , UserLogin : "user3" , Permission : models . PERMISSION_VIEW },
}
}). Return ( nil )
2020-11-24 12:10:32 +01:00
cfg := setting . NewCfg ()
cfg . HiddenUsers = map [ string ] struct {}{ "user2" : {}}
2021-10-27 14:45:20 +02:00
t . Run ( "Should get hidden acl" , func ( t * testing . T ) {
2020-11-24 12:10:32 +01:00
user := & models . SignedInUser {
OrgId : orgID ,
UserId : 1 ,
Login : "user1" ,
}
2022-06-01 14:16:26 -04:00
g := newDashboardGuardian ( context . Background (), dashboardID , orgID , user , store , dashSvc )
2020-11-24 12:10:32 +01:00
hiddenACL , err := g . GetHiddenACL ( cfg )
2021-10-27 14:45:20 +02:00
require . NoError ( t , err )
2020-11-24 12:10:32 +01:00
2021-10-27 14:45:20 +02:00
require . Equal ( t , len ( hiddenACL ), 1 )
require . Equal ( t , hiddenACL [ 0 ]. UserID , int64 ( 2 ))
2020-11-24 12:10:32 +01:00
})
2021-10-27 14:45:20 +02:00
t . Run ( "Grafana admin should not get hidden acl" , func ( t * testing . T ) {
2020-11-24 12:10:32 +01:00
user := & models . SignedInUser {
OrgId : orgID ,
UserId : 1 ,
Login : "user1" ,
IsGrafanaAdmin : true ,
}
2022-06-01 14:16:26 -04:00
g := newDashboardGuardian ( context . Background (), dashboardID , orgID , user , store , & dashboards . FakeDashboardService {})
2020-11-24 12:10:32 +01:00
hiddenACL , err := g . GetHiddenACL ( cfg )
2021-10-27 14:45:20 +02:00
require . NoError ( t , err )
2020-11-24 12:10:32 +01:00
2021-10-27 14:45:20 +02:00
require . Equal ( t , len ( hiddenACL ), 0 )
2020-11-24 12:10:32 +01:00
})
})
}
2021-04-28 14:42:18 +02:00
2022-07-18 15:14:58 +02:00
func TestGuardianGetACLWithoutDuplicates ( t * testing . T ) {
2021-04-28 14:42:18 +02:00
t . Run ( "Get hidden ACL tests" , func ( t * testing . T ) {
2022-03-21 10:49:49 +01:00
store := mockstore . NewSQLStoreMock ()
2022-06-01 14:16:26 -04:00
dashSvc := dashboards . NewFakeDashboardService ( t )
2022-07-18 15:14:58 +02:00
dashSvc . On ( "GetDashboardACLInfoList" , mock . Anything , mock . AnythingOfType ( "*models.GetDashboardACLInfoListQuery" )). Run ( func ( args mock . Arguments ) {
q := args . Get ( 1 ).( * models . GetDashboardACLInfoListQuery )
q . Result = [] * models . DashboardACLInfoDTO {
2022-06-01 14:16:26 -04:00
{ Inherited : true , UserId : 3 , UserLogin : "user3" , Permission : models . PERMISSION_EDIT },
{ Inherited : false , UserId : 3 , UserLogin : "user3" , Permission : models . PERMISSION_VIEW },
{ Inherited : false , UserId : 2 , UserLogin : "user2" , Permission : models . PERMISSION_ADMIN },
{ Inherited : true , UserId : 4 , UserLogin : "user4" , Permission : models . PERMISSION_ADMIN },
{ Inherited : false , UserId : 4 , UserLogin : "user4" , Permission : models . PERMISSION_ADMIN },
{ Inherited : false , UserId : 5 , UserLogin : "user5" , Permission : models . PERMISSION_EDIT },
{ Inherited : true , UserId : 6 , UserLogin : "user6" , Permission : models . PERMISSION_VIEW },
{ Inherited : false , UserId : 6 , UserLogin : "user6" , Permission : models . PERMISSION_EDIT },
}
}). Return ( nil )
2021-04-28 14:42:18 +02:00
t . Run ( "Should get acl without duplicates" , func ( t * testing . T ) {
user := & models . SignedInUser {
OrgId : orgID ,
UserId : 1 ,
Login : "user1" ,
}
2022-06-01 14:16:26 -04:00
g := newDashboardGuardian ( context . Background (), dashboardID , orgID , user , store , dashSvc )
2021-04-28 14:42:18 +02:00
acl , err := g . GetACLWithoutDuplicates ()
require . NoError ( t , err )
require . NotNil ( t , acl )
require . Len ( t , acl , 6 )
2022-07-18 15:14:58 +02:00
require . ElementsMatch ( t , [] * models . DashboardACLInfoDTO {
2021-04-28 14:42:18 +02:00
{ Inherited : true , UserId : 3 , UserLogin : "user3" , Permission : models . PERMISSION_EDIT },
{ Inherited : true , UserId : 4 , UserLogin : "user4" , Permission : models . PERMISSION_ADMIN },
{ Inherited : true , UserId : 6 , UserLogin : "user6" , Permission : models . PERMISSION_VIEW },
{ Inherited : false , UserId : 2 , UserLogin : "user2" , Permission : models . PERMISSION_ADMIN },
{ Inherited : false , UserId : 5 , UserLogin : "user5" , Permission : models . PERMISSION_EDIT },
{ Inherited : false , UserId : 6 , UserLogin : "user6" , Permission : models . PERMISSION_EDIT },
}, acl )
})
})
}