You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

391 lines
10 KiB

package database
import (
"context"
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/sqlstore"
)
type setUserResourcePermissionsTest struct {
desc string
orgID int64
userID int64
actions []string
resource string
resourceID string
seeds []accesscontrol.SetResourcePermissionsCommand
}
func TestAccessControlStore_SetUserResourcePermissions(t *testing.T) {
tests := []setUserResourcePermissionsTest{
{
desc: "should set resource permission for user",
userID: 1,
actions: []string{"datasources:query"},
resource: "datasources",
resourceID: "1",
},
{
desc: "should remove resource permission for user",
orgID: 1,
userID: 1,
actions: []string{},
resource: "datasources",
resourceID: "1",
seeds: []accesscontrol.SetResourcePermissionsCommand{
{
Actions: []string{"datasources:query"},
Resource: "datasources",
ResourceID: "1",
},
},
},
{
desc: "should add new resource permission for user",
orgID: 1,
userID: 1,
actions: []string{"datasources:query", "datasources:write"},
resource: "datasources",
resourceID: "1",
seeds: []accesscontrol.SetResourcePermissionsCommand{
{
Actions: []string{"datasources:write"},
Resource: "datasources",
ResourceID: "1",
},
},
},
}
for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
store, _ := setupTestEnv(t)
for _, s := range test.seeds {
_, err := store.SetUserResourcePermissions(context.Background(), test.orgID, test.userID, s)
require.NoError(t, err)
}
added, err := store.SetUserResourcePermissions(context.Background(), test.userID, test.userID, accesscontrol.SetResourcePermissionsCommand{
Actions: test.actions,
Resource: test.resource,
ResourceID: test.resourceID,
})
require.NoError(t, err)
assert.Len(t, added, len(test.actions))
for _, p := range added {
assert.Equal(t, getResourceScope(test.resource, test.resourceID), p.Scope)
}
})
}
}
type setTeamResourcePermissionsTest struct {
desc string
orgID int64
teamID int64
actions []string
resource string
resourceID string
seeds []accesscontrol.SetResourcePermissionsCommand
}
func TestAccessControlStore_SetTeamResourcePermissions(t *testing.T) {
tests := []setTeamResourcePermissionsTest{
{
desc: "should add new resource permission for team",
orgID: 1,
teamID: 1,
actions: []string{"datasources:query"},
resource: "datasources",
resourceID: "1",
},
{
desc: "should add new resource permission when others exist",
orgID: 1,
teamID: 1,
actions: []string{"datasources:query", "datasources:write"},
resource: "datasources",
resourceID: "1",
seeds: []accesscontrol.SetResourcePermissionsCommand{
{
Actions: []string{"datasources:query"},
Resource: "datasources",
ResourceID: "1",
},
},
},
{
desc: "should remove permissions for team",
orgID: 1,
teamID: 1,
actions: []string{},
resource: "datasources",
resourceID: "1",
seeds: []accesscontrol.SetResourcePermissionsCommand{
{
Actions: []string{"datasources:query"},
Resource: "datasources",
ResourceID: "1",
},
},
},
}
for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
store, _ := setupTestEnv(t)
for _, s := range test.seeds {
_, err := store.SetTeamResourcePermissions(context.Background(), test.orgID, test.teamID, s)
require.NoError(t, err)
}
added, err := store.SetTeamResourcePermissions(context.Background(), test.orgID, test.teamID, accesscontrol.SetResourcePermissionsCommand{
Actions: test.actions,
Resource: test.resource,
ResourceID: test.resourceID,
})
require.NoError(t, err)
assert.Len(t, added, len(test.actions))
for _, p := range added {
assert.Equal(t, getResourceScope(test.resource, test.resourceID), p.Scope)
}
})
}
}
type setBuiltinResourcePermissionsTest struct {
desc string
orgID int64
builtinRole string
actions []string
resource string
resourceID string
seeds []accesscontrol.SetResourcePermissionsCommand
}
func TestAccessControlStore_SetBuiltinResourcePermissions(t *testing.T) {
tests := []setBuiltinResourcePermissionsTest{
{
desc: "should add new resource permission for builtin role",
orgID: 1,
builtinRole: "Viewer",
actions: []string{"datasources:query"},
resource: "datasources",
resourceID: "1",
},
{
desc: "should add new resource permission when others exist",
orgID: 1,
builtinRole: "Viewer",
actions: []string{"datasources:query", "datasources:write"},
resource: "datasources",
resourceID: "1",
seeds: []accesscontrol.SetResourcePermissionsCommand{
{
Actions: []string{"datasources:query"},
Resource: "datasources",
ResourceID: "1",
},
},
},
{
desc: "should remove permissions for builtin role",
orgID: 1,
builtinRole: "Viewer",
actions: []string{},
resource: "datasources",
resourceID: "1",
seeds: []accesscontrol.SetResourcePermissionsCommand{
{
Actions: []string{"datasources:query"},
Resource: "datasources",
ResourceID: "1",
},
},
},
}
for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
store, _ := setupTestEnv(t)
for _, s := range test.seeds {
_, err := store.SetBuiltinResourcePermissions(context.Background(), test.orgID, test.builtinRole, s)
require.NoError(t, err)
}
added, err := store.SetBuiltinResourcePermissions(context.Background(), test.orgID, test.builtinRole, accesscontrol.SetResourcePermissionsCommand{
Actions: test.actions,
Resource: test.resource,
ResourceID: test.resourceID,
})
require.NoError(t, err)
assert.Len(t, added, len(test.actions))
for _, p := range added {
assert.Equal(t, getResourceScope(test.resource, test.resourceID), p.Scope)
}
})
}
}
type resourcePermission struct {
resource string
resourceID string
}
type removeResourcePermissionTest struct {
desc string
add resourcePermission
remove resourcePermission
expectedErr error
}
func TestAccessControlStore_RemoveResourcePermission(t *testing.T) {
tests := []removeResourcePermissionTest{
{
desc: "should remove resource permission",
add: resourcePermission{
resource: "datasources",
resourceID: "1",
},
remove: resourcePermission{
resource: "datasources",
resourceID: "1",
},
expectedErr: nil,
},
{
desc: "should return nil when permission does not exist",
add: resourcePermission{
resource: "datasources",
resourceID: "1",
},
remove: resourcePermission{
resource: "datasources",
resourceID: "2",
},
expectedErr: nil,
},
}
for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
store, sql := setupTestEnv(t)
user, err := sql.CreateUser(context.Background(), models.CreateUserCommand{
Login: "user",
OrgId: 1,
})
require.NoError(t, err)
// Seed with permission
seeded, err := store.SetUserResourcePermissions(context.Background(), user.OrgId, user.Id, accesscontrol.SetResourcePermissionsCommand{
Actions: []string{"datasources:query"},
Resource: test.add.resource,
ResourceID: test.add.resourceID,
})
require.NoError(t, err)
err = store.RemoveResourcePermission(context.Background(), user.OrgId, accesscontrol.RemoveResourcePermissionCommand{
Actions: []string{"datasources:query"},
Resource: test.remove.resource,
ResourceID: test.remove.resourceID,
PermissionID: seeded[0].ID,
})
if test.expectedErr != nil {
assert.ErrorIs(t, err, test.expectedErr)
} else {
permissions, err := store.GetResourcesPermissions(context.Background(), user.OrgId, accesscontrol.GetResourcesPermissionsQuery{
Actions: []string{"datasources:query"},
Resource: test.add.resource,
ResourceIDs: []string{test.add.resourceID},
})
assert.NoError(t, err)
if test.add.resourceID != test.remove.resourceID {
assert.Len(t, permissions, 1)
} else {
assert.Len(t, permissions, 0)
}
}
})
}
}
type getResourcesPermissionsTest struct {
desc string
numUsers int
actions []string
resource string
resourceIDs []string
}
func TestAccessControlStore_GetResourcesPermissions(t *testing.T) {
tests := []getResourcesPermissionsTest{
{
desc: "should return permissions for all resource ids",
numUsers: 3,
actions: []string{"datasources:query"},
resource: "datasources",
resourceIDs: []string{"1", "2"},
},
}
for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
store, sql := setupTestEnv(t)
for _, id := range test.resourceIDs {
seedResourcePermissions(t, store, sql, test.actions, test.resource, id, test.numUsers)
}
permissions, err := store.GetResourcesPermissions(context.Background(), 1, accesscontrol.GetResourcesPermissionsQuery{
Actions: test.actions,
Resource: test.resource,
ResourceIDs: test.resourceIDs,
})
require.NoError(t, err)
expectedLen := test.numUsers * len(test.resourceIDs)
assert.Len(t, permissions, expectedLen)
})
}
}
func seedResourcePermissions(t *testing.T, store *AccessControlStore, sql *sqlstore.SQLStore, actions []string, resource, resourceID string, numUsers int) {
t.Helper()
for i := 0; i < numUsers; i++ {
org, _ := sql.GetOrgByName("test")
if org == nil {
addedOrg, err := sql.CreateOrgWithMember("test", int64(i))
require.NoError(t, err)
org = &addedOrg
}
u, err := sql.CreateUser(context.Background(), models.CreateUserCommand{
Login: fmt.Sprintf("user:%s%d", resourceID, i),
OrgId: org.Id,
})
require.NoError(t, err)
_, err = store.SetUserResourcePermissions(context.Background(), 1, u.Id, accesscontrol.SetResourcePermissionsCommand{
Actions: actions,
Resource: resource,
ResourceID: resourceID,
})
require.NoError(t, err)
}
}