2018-02-26 12:12:01 -06:00
package guardian
import (
2021-09-23 10:43:32 -05:00
"context"
2020-11-19 07:47:17 -06:00
"errors"
2018-02-26 12:12:01 -06:00
"fmt"
2018-04-08 08:06:22 -05:00
"runtime"
2018-02-26 12:12:01 -06:00
"testing"
2022-06-01 13:16:26 -05:00
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
2022-10-19 08:02:15 -05:00
"github.com/grafana/grafana/pkg/infra/db/dbtest"
2020-02-29 06:35:15 -06:00
"github.com/grafana/grafana/pkg/models"
2022-06-01 13:16:26 -05:00
"github.com/grafana/grafana/pkg/services/dashboards"
2022-08-10 04:56:48 -05:00
"github.com/grafana/grafana/pkg/services/org"
2022-09-20 11:58:04 -05:00
"github.com/grafana/grafana/pkg/services/team/teamtest"
2022-08-10 04:56:48 -05:00
"github.com/grafana/grafana/pkg/services/user"
2020-11-24 05:10:32 -06:00
"github.com/grafana/grafana/pkg/setting"
2018-02-26 12:12:01 -06:00
)
2020-11-24 04:36:00 -06:00
const (
2018-04-08 08:06:22 -05: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 04:36:00 -06:00
)
var (
2022-08-10 04:56:48 -05:00
adminRole = org . RoleAdmin
editorRole = org . RoleEditor
viewerRole = org . RoleViewer
2018-04-08 08:06:22 -05:00
)
2018-02-26 12:12:01 -06:00
2018-04-08 08:06:22 -05:00
func TestGuardianAdmin ( t * testing . T ) {
2022-08-10 04:56:48 -05:00
orgRoleScenario ( "Given user has admin org role" , t , org . RoleAdmin , func ( sc * scenarioContext ) {
2020-11-24 04:36:00 -06:00
// 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 08:06:22 -05:00
} )
}
2018-02-26 12:12:01 -06:00
2018-04-08 08:06:22 -05:00
func TestGuardianEditor ( t * testing . T ) {
2022-08-10 04:56:48 -05:00
orgRoleScenario ( "Given user has editor org role" , t , org . RoleEditor , func ( sc * scenarioContext ) {
2020-11-24 04:36:00 -06:00
// 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 08:06:22 -05:00
} )
}
2018-02-26 12:12:01 -06:00
2018-04-08 08:06:22 -05:00
func TestGuardianViewer ( t * testing . T ) {
2022-08-10 04:56:48 -05:00
orgRoleScenario ( "Given user has viewer org role" , t , org . RoleViewer , func ( sc * scenarioContext ) {
2020-11-24 04:36:00 -06:00
// 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 04:10:17 -05:00
2022-08-10 04:56:48 -05:00
apiKeyScenario ( "Given api key with viewer role" , t , org . RoleViewer , func ( sc * scenarioContext ) {
2020-11-24 04:36:00 -06:00
// dashboard has default permissions
sc . defaultPermissionScenario ( VIEWER , VIEWER_ACCESS )
2018-04-08 08:06:22 -05:00
} )
}
2018-02-26 12:12:01 -06:00
2018-06-19 05:34:34 -05:00
func ( sc * scenarioContext ) defaultPermissionScenario ( pt permissionType , flag permissionFlags ) {
2018-04-08 08:06:22 -05:00
_ , callerFile , callerLine , _ := runtime . Caller ( 1 )
sc . callerFile = callerFile
sc . callerLine = callerLine
2022-07-18 08:14:58 -05:00
existingPermissions := [ ] * models . DashboardACLInfoDTO {
2020-02-29 06:35:15 -06:00
toDto ( newEditorRolePermission ( defaultDashboardID , models . PERMISSION_EDIT ) ) ,
toDto ( newViewerRolePermission ( defaultDashboardID , models . PERMISSION_VIEW ) ) ,
2018-04-08 08:06:22 -05:00
}
2018-02-26 12:12:01 -06:00
2020-11-24 04:36:00 -06: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 08:06:22 -05:00
}
2018-02-26 12:12:01 -06:00
2020-02-29 06:35:15 -06:00
func ( sc * scenarioContext ) dashboardPermissionScenario ( pt permissionType , permission models . PermissionType , flag permissionFlags ) {
2018-04-08 08:06:22 -05:00
_ , callerFile , callerLine , _ := runtime . Caller ( 1 )
sc . callerFile = callerFile
sc . callerLine = callerLine
2022-07-18 08:14:58 -05:00
var existingPermissions [ ] * models . DashboardACLInfoDTO
2018-04-08 08:06:22 -05:00
switch pt {
case USER :
2022-07-18 08:14:58 -05:00
existingPermissions = [ ] * models . DashboardACLInfoDTO { { OrgId : orgID , DashboardId : dashboardID , UserId : userID , Permission : permission } }
2018-04-08 08:06:22 -05:00
case TEAM :
2022-07-18 08:14:58 -05:00
existingPermissions = [ ] * models . DashboardACLInfoDTO { { OrgId : orgID , DashboardId : dashboardID , TeamId : teamID , Permission : permission } }
2018-04-08 08:06:22 -05:00
case EDITOR :
2022-07-18 08:14:58 -05:00
existingPermissions = [ ] * models . DashboardACLInfoDTO { { OrgId : orgID , DashboardId : dashboardID , Role : & editorRole , Permission : permission } }
2018-04-08 08:06:22 -05:00
case VIEWER :
2022-07-18 08:14:58 -05:00
existingPermissions = [ ] * models . DashboardACLInfoDTO { { OrgId : orgID , DashboardId : dashboardID , Role : & viewerRole , Permission : permission } }
2018-04-08 08:06:22 -05:00
}
2018-02-26 12:12:01 -06:00
2020-11-24 04:36:00 -06: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 08:06:22 -05:00
}
2018-02-26 12:12:01 -06:00
2020-02-29 06:35:15 -06:00
func ( sc * scenarioContext ) parentFolderPermissionScenario ( pt permissionType , permission models . PermissionType , flag permissionFlags ) {
2018-04-08 08:06:22 -05:00
_ , callerFile , callerLine , _ := runtime . Caller ( 1 )
sc . callerFile = callerFile
sc . callerLine = callerLine
2022-07-18 08:14:58 -05:00
var folderPermissionList [ ] * models . DashboardACLInfoDTO
2018-04-08 08:06:22 -05:00
switch pt {
case USER :
2022-07-18 08:14:58 -05:00
folderPermissionList = [ ] * models . DashboardACLInfoDTO { { OrgId : orgID , DashboardId : parentFolderID ,
2020-11-24 04:36:00 -06:00
UserId : userID , Permission : permission , Inherited : true } }
2018-04-08 08:06:22 -05:00
case TEAM :
2022-07-18 08:14:58 -05:00
folderPermissionList = [ ] * models . DashboardACLInfoDTO { { OrgId : orgID , DashboardId : parentFolderID , TeamId : teamID ,
2020-11-24 04:36:00 -06:00
Permission : permission , Inherited : true } }
2018-04-08 08:06:22 -05:00
case EDITOR :
2022-07-18 08:14:58 -05:00
folderPermissionList = [ ] * models . DashboardACLInfoDTO { { OrgId : orgID , DashboardId : parentFolderID ,
2020-11-24 04:36:00 -06:00
Role : & editorRole , Permission : permission , Inherited : true } }
2018-04-08 08:06:22 -05:00
case VIEWER :
2022-07-18 08:14:58 -05:00
folderPermissionList = [ ] * models . DashboardACLInfoDTO { { OrgId : orgID , DashboardId : parentFolderID ,
2020-11-24 04:36:00 -06:00
Role : & viewerRole , Permission : permission , Inherited : true } }
2018-04-08 08:06:22 -05:00
}
2018-02-26 12:12:01 -06:00
2020-11-24 04:36:00 -06: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 12:12:01 -06:00
}
2018-04-08 08:06:22 -05:00
func ( sc * scenarioContext ) verifyExpectedPermissionsFlags ( ) {
tc := fmt . Sprintf ( "should have permissions to %s" , sc . expectedFlags . String ( ) )
2020-11-24 04:36:00 -06: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 08:06:22 -05:00
var actualFlag permissionFlags
2018-02-26 12:12:01 -06:00
2018-04-08 08:06:22 -05: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 04:10:17 -05:00
if actualFlag & sc . expectedFlags != actualFlag {
2018-04-08 08:06:22 -05:00
sc . reportFailure ( tc , sc . expectedFlags . String ( ) , actualFlag . String ( ) )
}
2018-02-26 12:12:01 -06:00
2018-04-08 08:06:22 -05:00
sc . reportSuccess ( )
2018-02-26 12:12:01 -06:00
} )
}
2018-04-08 08:06:22 -05: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 04:36:00 -06:00
sc . t . Run ( tc , func ( t * testing . T ) {
2022-07-18 08:14:58 -05:00
p := [ ] * models . DashboardACL {
2020-02-29 06:35:15 -06:00
newDefaultUserPermission ( dashboardID , models . PERMISSION_VIEW ) ,
newDefaultUserPermission ( dashboardID , models . PERMISSION_ADMIN ) ,
2018-04-08 08:06:22 -05:00
}
sc . updatePermissions = p
2020-02-29 06:35:15 -06:00
_ , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , p )
2018-02-26 12:12:01 -06:00
2020-11-19 07:47:17 -06:00
if ! errors . Is ( err , ErrGuardianPermissionExists ) {
2018-04-08 08:06:22 -05:00
sc . reportFailure ( tc , ErrGuardianPermissionExists , err )
}
sc . reportSuccess ( )
2018-02-26 12:12:01 -06:00
} )
2018-04-08 08:06:22 -05:00
tc = "When updating dashboard permissions with duplicate permission for team should not be allowed"
2020-11-24 04:36:00 -06:00
sc . t . Run ( tc , func ( t * testing . T ) {
2022-07-18 08:14:58 -05:00
p := [ ] * models . DashboardACL {
2020-02-29 06:35:15 -06:00
newDefaultTeamPermission ( dashboardID , models . PERMISSION_VIEW ) ,
newDefaultTeamPermission ( dashboardID , models . PERMISSION_ADMIN ) ,
2018-04-08 08:06:22 -05:00
}
sc . updatePermissions = p
2020-02-29 06:35:15 -06:00
_ , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , p )
2020-11-19 07:47:17 -06:00
if ! errors . Is ( err , ErrGuardianPermissionExists ) {
2018-04-08 08:06:22 -05:00
sc . reportFailure ( tc , ErrGuardianPermissionExists , err )
2018-02-26 12:12:01 -06:00
}
2018-04-08 08:06:22 -05:00
sc . reportSuccess ( )
} )
tc = "When updating dashboard permissions with duplicate permission for editor role should not be allowed"
2020-11-24 04:36:00 -06:00
sc . t . Run ( tc , func ( t * testing . T ) {
2022-07-18 08:14:58 -05:00
p := [ ] * models . DashboardACL {
2020-02-29 06:35:15 -06:00
newEditorRolePermission ( dashboardID , models . PERMISSION_VIEW ) ,
newEditorRolePermission ( dashboardID , models . PERMISSION_ADMIN ) ,
2018-04-08 08:06:22 -05:00
}
sc . updatePermissions = p
2020-02-29 06:35:15 -06:00
_ , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , p )
2018-04-08 08:06:22 -05:00
2020-11-19 07:47:17 -06:00
if ! errors . Is ( err , ErrGuardianPermissionExists ) {
2018-04-08 08:06:22 -05:00
sc . reportFailure ( tc , ErrGuardianPermissionExists , err )
}
sc . reportSuccess ( )
} )
2018-02-26 12:12:01 -06:00
2018-04-08 08:06:22 -05:00
tc = "When updating dashboard permissions with duplicate permission for viewer role should not be allowed"
2020-11-24 04:36:00 -06:00
sc . t . Run ( tc , func ( t * testing . T ) {
2022-07-18 08:14:58 -05:00
p := [ ] * models . DashboardACL {
2020-02-29 06:35:15 -06:00
newViewerRolePermission ( dashboardID , models . PERMISSION_VIEW ) ,
newViewerRolePermission ( dashboardID , models . PERMISSION_ADMIN ) ,
2018-04-08 08:06:22 -05:00
}
sc . updatePermissions = p
2020-02-29 06:35:15 -06:00
_ , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , p )
2020-11-19 07:47:17 -06:00
if ! errors . Is ( err , ErrGuardianPermissionExists ) {
2018-04-08 08:06:22 -05:00
sc . reportFailure ( tc , ErrGuardianPermissionExists , err )
}
sc . reportSuccess ( )
2018-02-26 12:12:01 -06:00
} )
2018-04-08 08:06:22 -05:00
tc = "When updating dashboard permissions with duplicate permission for admin role should not be allowed"
2020-11-24 04:36:00 -06:00
sc . t . Run ( tc , func ( t * testing . T ) {
2022-07-18 08:14:58 -05:00
p := [ ] * models . DashboardACL {
2020-02-29 06:35:15 -06:00
newAdminRolePermission ( dashboardID , models . PERMISSION_ADMIN ) ,
2018-04-08 08:06:22 -05:00
}
sc . updatePermissions = p
2020-02-29 06:35:15 -06:00
_ , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , p )
2020-11-19 07:47:17 -06:00
if ! errors . Is ( err , ErrGuardianPermissionExists ) {
2018-04-08 08:06:22 -05:00
sc . reportFailure ( tc , ErrGuardianPermissionExists , err )
}
sc . reportSuccess ( )
2018-02-26 12:12:01 -06:00
} )
}
2018-04-08 08:06:22 -05:00
func ( sc * scenarioContext ) verifyUpdateDashboardPermissionsShouldBeAllowed ( pt permissionType ) {
if ! sc . expectedFlags . canAdmin ( ) {
return
}
2020-02-29 06:35:15 -06:00
for _ , p := range [ ] models . PermissionType { models . PERMISSION_ADMIN , models . PERMISSION_EDIT , models . PERMISSION_VIEW } {
2018-04-08 08:06:22 -05:00
tc := fmt . Sprintf ( "When updating dashboard permissions with %s permissions should be allowed" , p . String ( ) )
2020-11-24 04:36:00 -06:00
sc . t . Run ( tc , func ( t * testing . T ) {
2022-07-18 08:14:58 -05:00
permissionList := [ ] * models . DashboardACL { }
2018-04-08 08:06:22 -05:00
switch pt {
case USER :
2022-07-18 08:14:58 -05:00
permissionList = [ ] * models . DashboardACL {
2018-04-08 08:06:22 -05:00
newEditorRolePermission ( dashboardID , p ) ,
newViewerRolePermission ( dashboardID , p ) ,
newCustomUserPermission ( dashboardID , otherUserID , p ) ,
newDefaultTeamPermission ( dashboardID , p ) ,
}
case TEAM :
2022-07-18 08:14:58 -05:00
permissionList = [ ] * models . DashboardACL {
2018-04-08 08:06:22 -05:00
newEditorRolePermission ( dashboardID , p ) ,
newViewerRolePermission ( dashboardID , p ) ,
newDefaultUserPermission ( dashboardID , p ) ,
newCustomTeamPermission ( dashboardID , otherTeamID , p ) ,
}
case EDITOR , VIEWER :
2022-07-18 08:14:58 -05:00
permissionList = [ ] * models . DashboardACL {
2018-04-08 08:06:22 -05:00
newEditorRolePermission ( dashboardID , p ) ,
newViewerRolePermission ( dashboardID , p ) ,
newDefaultUserPermission ( dashboardID , p ) ,
newDefaultTeamPermission ( dashboardID , p ) ,
}
}
sc . updatePermissions = permissionList
2020-02-29 06:35:15 -06:00
ok , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , permissionList )
2018-04-08 08:06:22 -05: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 06:35:15 -06:00
for _ , p := range [ ] models . PermissionType { models . PERMISSION_ADMIN , models . PERMISSION_EDIT , models . PERMISSION_VIEW } {
2018-04-08 08:06:22 -05:00
tc := fmt . Sprintf ( "When updating dashboard permissions with %s permissions should NOT be allowed" , p . String ( ) )
2020-11-24 04:36:00 -06:00
sc . t . Run ( tc , func ( t * testing . T ) {
2022-07-18 08:14:58 -05:00
permissionList := [ ] * models . DashboardACL {
2018-04-08 08:06:22 -05:00
newEditorRolePermission ( dashboardID , p ) ,
newViewerRolePermission ( dashboardID , p ) ,
}
switch pt {
case USER :
2022-07-18 08:14:58 -05:00
permissionList = append ( permissionList , [ ] * models . DashboardACL {
2018-04-08 08:06:22 -05:00
newCustomUserPermission ( dashboardID , otherUserID , p ) ,
newDefaultTeamPermission ( dashboardID , p ) ,
} ... )
case TEAM :
2022-07-18 08:14:58 -05:00
permissionList = append ( permissionList , [ ] * models . DashboardACL {
2018-04-08 08:06:22 -05:00
newDefaultUserPermission ( dashboardID , p ) ,
newCustomTeamPermission ( dashboardID , otherTeamID , p ) ,
} ... )
2020-12-01 02:53:27 -06:00
default :
// TODO: Handle other cases?
2018-04-08 08:06:22 -05:00
}
sc . updatePermissions = permissionList
2020-02-29 06:35:15 -06:00
ok , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , permissionList )
2018-04-08 08:06:22 -05:00
if err != nil {
sc . reportFailure ( tc , nil , err )
}
if ok {
sc . reportFailure ( tc , true , false )
}
sc . reportSuccess ( )
} )
}
}
2020-02-29 06:35:15 -06:00
func ( sc * scenarioContext ) verifyUpdateChildDashboardPermissionsShouldBeAllowed ( pt permissionType , parentFolderPermission models . PermissionType ) {
2018-04-08 08:06:22 -05:00
if ! sc . expectedFlags . canAdmin ( ) {
return
}
2020-02-29 06:35:15 -06:00
for _ , p := range [ ] models . PermissionType { models . PERMISSION_ADMIN , models . PERMISSION_EDIT , models . PERMISSION_VIEW } {
2018-04-08 08:06:22 -05:00
tc := fmt . Sprintf ( "When updating child dashboard permissions with %s permissions should be allowed" , p . String ( ) )
2020-11-24 04:36:00 -06:00
sc . t . Run ( tc , func ( t * testing . T ) {
2022-07-18 08:14:58 -05:00
permissionList := [ ] * models . DashboardACL { }
2018-04-08 08:06:22 -05:00
switch pt {
case USER :
2022-07-18 08:14:58 -05:00
permissionList = [ ] * models . DashboardACL {
2018-04-08 08:06:22 -05:00
newEditorRolePermission ( childDashboardID , p ) ,
newViewerRolePermission ( childDashboardID , p ) ,
newCustomUserPermission ( childDashboardID , otherUserID , p ) ,
newDefaultTeamPermission ( childDashboardID , p ) ,
}
case TEAM :
2022-07-18 08:14:58 -05:00
permissionList = [ ] * models . DashboardACL {
2018-04-08 08:06:22 -05:00
newEditorRolePermission ( childDashboardID , p ) ,
newViewerRolePermission ( childDashboardID , p ) ,
newDefaultUserPermission ( childDashboardID , p ) ,
newCustomTeamPermission ( childDashboardID , otherTeamID , p ) ,
}
case EDITOR :
2022-07-18 08:14:58 -05:00
permissionList = [ ] * models . DashboardACL {
2018-04-08 08:06:22 -05: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 08:14:58 -05:00
permissionList = [ ] * models . DashboardACL {
2018-04-08 08:06:22 -05: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 06:35:15 -06:00
ok , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , permissionList )
2018-04-08 08:06:22 -05:00
if err != nil {
sc . reportFailure ( tc , nil , err )
}
if ! ok {
sc . reportFailure ( tc , false , true )
}
sc . reportSuccess ( )
} )
}
}
2020-02-29 06:35:15 -06:00
func ( sc * scenarioContext ) verifyUpdateChildDashboardPermissionsShouldNotBeAllowed ( pt permissionType , parentFolderPermission models . PermissionType ) {
2018-04-08 08:06:22 -05:00
if sc . expectedFlags . canAdmin ( ) {
return
}
2020-02-29 06:35:15 -06:00
for _ , p := range [ ] models . PermissionType { models . PERMISSION_ADMIN , models . PERMISSION_EDIT , models . PERMISSION_VIEW } {
2018-04-08 08:06:22 -05:00
tc := fmt . Sprintf ( "When updating child dashboard permissions with %s permissions should NOT be allowed" , p . String ( ) )
2020-11-24 04:36:00 -06:00
sc . t . Run ( tc , func ( t * testing . T ) {
2022-07-18 08:14:58 -05:00
permissionList := [ ] * models . DashboardACL { }
2018-04-08 08:06:22 -05:00
switch pt {
case USER :
2022-07-18 08:14:58 -05:00
permissionList = [ ] * models . DashboardACL {
2018-04-08 08:06:22 -05:00
newEditorRolePermission ( childDashboardID , p ) ,
newViewerRolePermission ( childDashboardID , p ) ,
newCustomUserPermission ( childDashboardID , otherUserID , p ) ,
newDefaultTeamPermission ( childDashboardID , p ) ,
}
case TEAM :
2022-07-18 08:14:58 -05:00
permissionList = [ ] * models . DashboardACL {
2018-04-08 08:06:22 -05:00
newEditorRolePermission ( childDashboardID , p ) ,
newViewerRolePermission ( childDashboardID , p ) ,
newDefaultUserPermission ( childDashboardID , p ) ,
newCustomTeamPermission ( childDashboardID , otherTeamID , p ) ,
}
case EDITOR :
2022-07-18 08:14:58 -05:00
permissionList = [ ] * models . DashboardACL {
2018-04-08 08:06:22 -05:00
newViewerRolePermission ( childDashboardID , p ) ,
newDefaultUserPermission ( childDashboardID , p ) ,
newDefaultTeamPermission ( childDashboardID , p ) ,
}
2020-06-01 10:11:25 -05:00
// permission to update is higher than parent folder permission
2018-04-08 08:06:22 -05:00
if p > parentFolderPermission {
permissionList = append ( permissionList , newEditorRolePermission ( childDashboardID , p ) )
}
case VIEWER :
2022-07-18 08:14:58 -05:00
permissionList = [ ] * models . DashboardACL {
2018-04-08 08:06:22 -05:00
newEditorRolePermission ( childDashboardID , p ) ,
newDefaultUserPermission ( childDashboardID , p ) ,
newDefaultTeamPermission ( childDashboardID , p ) ,
}
2020-06-01 10:11:25 -05:00
// permission to update is higher than parent folder permission
2018-04-08 08:06:22 -05:00
if p > parentFolderPermission {
permissionList = append ( permissionList , newViewerRolePermission ( childDashboardID , p ) )
}
}
sc . updatePermissions = permissionList
2020-02-29 06:35:15 -06:00
ok , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , permissionList )
2018-04-08 08:06:22 -05:00
if err != nil {
sc . reportFailure ( tc , nil , err )
}
if ok {
sc . reportFailure ( tc , true , false )
}
sc . reportSuccess ( )
} )
2018-02-26 12:12:01 -06:00
}
}
2020-02-29 06:35:15 -06:00
func ( sc * scenarioContext ) verifyUpdateChildDashboardPermissionsWithOverrideShouldBeAllowed ( pt permissionType , parentFolderPermission models . PermissionType ) {
2018-04-08 08:06:22 -05:00
if ! sc . expectedFlags . canAdmin ( ) {
return
}
2020-02-29 06:35:15 -06:00
for _ , p := range [ ] models . PermissionType { models . PERMISSION_ADMIN , models . PERMISSION_EDIT , models . PERMISSION_VIEW } {
2020-06-01 10:11:25 -05:00
// permission to update is higher than parent folder permission
2018-04-08 08:06:22 -05: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 04:36:00 -06:00
sc . t . Run ( tc , func ( t * testing . T ) {
2022-07-18 08:14:58 -05:00
permissionList := [ ] * models . DashboardACL { }
2018-04-08 08:06:22 -05:00
switch pt {
case USER :
2022-07-18 08:14:58 -05:00
permissionList = [ ] * models . DashboardACL {
2018-04-08 08:06:22 -05:00
newDefaultUserPermission ( childDashboardID , p ) ,
}
case TEAM :
2022-07-18 08:14:58 -05:00
permissionList = [ ] * models . DashboardACL {
2018-04-08 08:06:22 -05:00
newDefaultTeamPermission ( childDashboardID , p ) ,
}
case EDITOR :
2022-07-18 08:14:58 -05:00
permissionList = [ ] * models . DashboardACL {
2018-04-08 08:06:22 -05:00
newEditorRolePermission ( childDashboardID , p ) ,
}
case VIEWER :
2022-07-18 08:14:58 -05:00
permissionList = [ ] * models . DashboardACL {
2018-04-08 08:06:22 -05:00
newViewerRolePermission ( childDashboardID , p ) ,
}
}
sc . updatePermissions = permissionList
2020-02-29 06:35:15 -06:00
_ , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , permissionList )
2020-11-19 07:47:17 -06:00
if ! errors . Is ( err , ErrGuardianOverride ) {
2018-04-08 08:06:22 -05:00
sc . reportFailure ( tc , ErrGuardianOverride , err )
}
sc . reportSuccess ( )
} )
2018-02-26 12:12:01 -06:00
}
}
2020-02-29 06:35:15 -06:00
func ( sc * scenarioContext ) verifyUpdateChildDashboardPermissionsWithOverrideShouldNotBeAllowed ( pt permissionType , parentFolderPermission models . PermissionType ) {
2018-04-08 08:06:22 -05:00
if ! sc . expectedFlags . canAdmin ( ) {
return
}
2020-02-29 06:35:15 -06:00
for _ , p := range [ ] models . PermissionType { models . PERMISSION_ADMIN , models . PERMISSION_EDIT , models . PERMISSION_VIEW } {
2020-06-01 10:11:25 -05:00
// permission to update is lower than or equal to parent folder permission
2018-04-08 08:06:22 -05:00
if p <= parentFolderPermission {
continue
}
2020-11-24 04:36:00 -06: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 08:14:58 -05:00
permissionList := [ ] * models . DashboardACL { }
2018-04-08 08:06:22 -05:00
switch pt {
case USER :
2022-07-18 08:14:58 -05:00
permissionList = [ ] * models . DashboardACL {
2018-04-08 08:06:22 -05:00
newDefaultUserPermission ( childDashboardID , p ) ,
}
case TEAM :
2022-07-18 08:14:58 -05:00
permissionList = [ ] * models . DashboardACL {
2018-04-08 08:06:22 -05:00
newDefaultTeamPermission ( childDashboardID , p ) ,
}
case EDITOR :
2022-07-18 08:14:58 -05:00
permissionList = [ ] * models . DashboardACL {
2018-04-08 08:06:22 -05:00
newEditorRolePermission ( childDashboardID , p ) ,
}
case VIEWER :
2022-07-18 08:14:58 -05:00
permissionList = [ ] * models . DashboardACL {
2018-04-08 08:06:22 -05:00
newViewerRolePermission ( childDashboardID , p ) ,
}
}
2020-02-29 06:35:15 -06:00
_ , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , permissionList )
2018-04-23 12:28:54 -05:00
if err != nil {
sc . reportFailure ( tc , nil , err )
}
2018-04-08 08:06:22 -05:00
sc . updatePermissions = permissionList
2020-02-29 06:35:15 -06:00
ok , err := sc . g . CheckPermissionBeforeUpdate ( models . PERMISSION_ADMIN , permissionList )
2018-04-08 08:06:22 -05:00
if err != nil {
sc . reportFailure ( tc , nil , err )
}
if ! ok {
sc . reportFailure ( tc , false , true )
}
sc . reportSuccess ( )
} )
2018-02-26 12:12:01 -06:00
}
}
2020-11-24 05:10:32 -06:00
func TestGuardianGetHiddenACL ( t * testing . T ) {
2021-10-27 07:45:20 -05:00
t . Run ( "Get hidden ACL tests" , func ( t * testing . T ) {
2022-10-19 08:02:15 -05:00
store := dbtest . NewFakeDB ( )
2022-06-01 13:16:26 -05:00
dashSvc := dashboards . NewFakeDashboardService ( t )
2022-07-18 08:14:58 -05: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 13:16:26 -05: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 05:10:32 -06:00
cfg := setting . NewCfg ( )
cfg . HiddenUsers = map [ string ] struct { } { "user2" : { } }
2021-10-27 07:45:20 -05:00
t . Run ( "Should get hidden acl" , func ( t * testing . T ) {
2022-08-10 04:56:48 -05:00
user := & user . SignedInUser {
2022-08-11 06:28:55 -05:00
OrgID : orgID ,
UserID : 1 ,
2020-11-24 05:10:32 -06:00
Login : "user1" ,
}
2022-09-20 11:58:04 -05:00
g := newDashboardGuardian ( context . Background ( ) , dashboardID , orgID , user , store , dashSvc , & teamtest . FakeService { } )
2020-11-24 05:10:32 -06:00
hiddenACL , err := g . GetHiddenACL ( cfg )
2021-10-27 07:45:20 -05:00
require . NoError ( t , err )
2020-11-24 05:10:32 -06:00
2021-10-27 07:45:20 -05:00
require . Equal ( t , len ( hiddenACL ) , 1 )
require . Equal ( t , hiddenACL [ 0 ] . UserID , int64 ( 2 ) )
2020-11-24 05:10:32 -06:00
} )
2021-10-27 07:45:20 -05:00
t . Run ( "Grafana admin should not get hidden acl" , func ( t * testing . T ) {
2022-08-10 04:56:48 -05:00
user := & user . SignedInUser {
2022-08-11 06:28:55 -05:00
OrgID : orgID ,
UserID : 1 ,
2020-11-24 05:10:32 -06:00
Login : "user1" ,
IsGrafanaAdmin : true ,
}
2022-09-20 11:58:04 -05:00
g := newDashboardGuardian ( context . Background ( ) , dashboardID , orgID , user , store , & dashboards . FakeDashboardService { } , & teamtest . FakeService { } )
2020-11-24 05:10:32 -06:00
hiddenACL , err := g . GetHiddenACL ( cfg )
2021-10-27 07:45:20 -05:00
require . NoError ( t , err )
2020-11-24 05:10:32 -06:00
2021-10-27 07:45:20 -05:00
require . Equal ( t , len ( hiddenACL ) , 0 )
2020-11-24 05:10:32 -06:00
} )
} )
}
2021-04-28 07:42:18 -05:00
2022-07-18 08:14:58 -05:00
func TestGuardianGetACLWithoutDuplicates ( t * testing . T ) {
2021-04-28 07:42:18 -05:00
t . Run ( "Get hidden ACL tests" , func ( t * testing . T ) {
2022-10-19 08:02:15 -05:00
store := dbtest . NewFakeDB ( )
2022-06-01 13:16:26 -05:00
dashSvc := dashboards . NewFakeDashboardService ( t )
2022-07-18 08:14:58 -05: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 13:16:26 -05: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 07:42:18 -05:00
t . Run ( "Should get acl without duplicates" , func ( t * testing . T ) {
2022-08-10 04:56:48 -05:00
user := & user . SignedInUser {
2022-08-11 06:28:55 -05:00
OrgID : orgID ,
UserID : 1 ,
2021-04-28 07:42:18 -05:00
Login : "user1" ,
}
2022-09-20 11:58:04 -05:00
g := newDashboardGuardian ( context . Background ( ) , dashboardID , orgID , user , store , dashSvc , & teamtest . FakeService { } )
2021-04-28 07:42:18 -05:00
acl , err := g . GetACLWithoutDuplicates ( )
require . NoError ( t , err )
require . NotNil ( t , acl )
require . Len ( t , acl , 6 )
2022-07-18 08:14:58 -05:00
require . ElementsMatch ( t , [ ] * models . DashboardACLInfoDTO {
2021-04-28 07:42:18 -05: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 )
} )
} )
}