RBAC: Move resource permissions store to service package (#53815)

* Rename file to store

* Move resource permission specific database functions to
resourcepermissions package

* Wire: Remove interface bind

* RBAC: Remove injection of resourcepermission Store

* RBAC: Export store constructor

* Tests: Use resource permission package to initiate store used in tests

* RBAC: Remove internal types package and move to resourcepermissions
package

* RBAC: Run database tests as itegration tests
This commit is contained in:
Karl Persson
2022-08-18 09:43:45 +02:00
committed by GitHub
parent 83f8da2e02
commit 1b933ff3ed
18 changed files with 177 additions and 185 deletions

View File

@@ -380,7 +380,7 @@ func setupHTTPServerWithCfgDb(
require.NoError(t, err) require.NoError(t, err)
} }
teamPermissionService, err := ossaccesscontrol.ProvideTeamPermissions(cfg, routeRegister, db, ac, database.ProvideService(db), license) teamPermissionService, err := ossaccesscontrol.ProvideTeamPermissions(cfg, routeRegister, db, ac, license)
require.NoError(t, err) require.NoError(t, err)
// Create minimal HTTP Server // Create minimal HTTP Server

View File

@@ -16,7 +16,6 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
acdb "github.com/grafana/grafana/pkg/services/accesscontrol/database" acdb "github.com/grafana/grafana/pkg/services/accesscontrol/database"
"github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions"
"github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/datasources/permissions" "github.com/grafana/grafana/pkg/services/datasources/permissions"
@@ -76,7 +75,6 @@ var wireExtsSet = wire.NewSet(
provider.ProvideService, provider.ProvideService,
wire.Bind(new(plugins.BackendFactoryProvider), new(*provider.Service)), wire.Bind(new(plugins.BackendFactoryProvider), new(*provider.Service)),
acdb.ProvideService, acdb.ProvideService,
wire.Bind(new(resourcepermissions.Store), new(*acdb.AccessControlStore)),
wire.Bind(new(accesscontrol.PermissionsStore), new(*acdb.AccessControlStore)), wire.Bind(new(accesscontrol.PermissionsStore), new(*acdb.AccessControlStore)),
ldap.ProvideGroupsService, ldap.ProvideGroupsService,
wire.Bind(new(ldap.Groups), new(*ldap.OSSGroups)), wire.Bind(new(ldap.Groups), new(*ldap.OSSGroups)),

View File

@@ -16,7 +16,6 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
acdb "github.com/grafana/grafana/pkg/services/accesscontrol/database" acdb "github.com/grafana/grafana/pkg/services/accesscontrol/database"
"github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions"
"github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/datasources/permissions" "github.com/grafana/grafana/pkg/services/datasources/permissions"
@@ -75,7 +74,6 @@ var wireExtsBasicSet = wire.NewSet(
provider.ProvideService, provider.ProvideService,
wire.Bind(new(plugins.BackendFactoryProvider), new(*provider.Service)), wire.Bind(new(plugins.BackendFactoryProvider), new(*provider.Service)),
acdb.ProvideService, acdb.ProvideService,
wire.Bind(new(resourcepermissions.Store), new(*acdb.AccessControlStore)),
wire.Bind(new(accesscontrol.PermissionsStore), new(*acdb.AccessControlStore)), wire.Bind(new(accesscontrol.PermissionsStore), new(*acdb.AccessControlStore)),
osskmsproviders.ProvideService, osskmsproviders.ProvideService,
wire.Bind(new(kmsproviders.Service), new(osskmsproviders.Service)), wire.Bind(new(kmsproviders.Service), new(osskmsproviders.Service)),

View File

@@ -111,26 +111,6 @@ func userRolesFilter(orgID, userID int64, teamIDs []int64, roles []string) (stri
return "INNER JOIN (" + builder.String() + ") as all_role ON role.id = all_role.role_id", params return "INNER JOIN (" + builder.String() + ") as all_role ON role.id = all_role.role_id", params
} }
func deletePermissions(sess *sqlstore.DBSession, ids []int64) error {
if len(ids) == 0 {
return nil
}
rawSQL := "DELETE FROM permission WHERE id IN(?" + strings.Repeat(",?", len(ids)-1) + ")"
args := make([]interface{}, 0, len(ids)+1)
args = append(args, rawSQL)
for _, id := range ids {
args = append(args, id)
}
_, err := sess.Exec(args...)
if err != nil {
return err
}
return nil
}
func (s *AccessControlStore) DeleteUserPermissions(ctx context.Context, orgID, userID int64) error { func (s *AccessControlStore) DeleteUserPermissions(ctx context.Context, orgID, userID int64) error {
err := s.sql.WithDbSession(ctx, func(sess *sqlstore.DBSession) error { err := s.sql.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
roleDeleteQuery := "DELETE FROM user_role WHERE user_id = ?" roleDeleteQuery := "DELETE FROM user_role WHERE user_id = ?"

View File

@@ -9,7 +9,7 @@ import (
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions/types" rs "github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
@@ -79,12 +79,12 @@ func TestAccessControlStore_GetUserPermissions(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) { t.Run(tt.desc, func(t *testing.T) {
store, sql := setupTestEnv(t) store, permissionStore, sql := setupTestEnv(t)
user, team := createUserAndTeam(t, sql, tt.orgID) user, team := createUserAndTeam(t, sql, tt.orgID)
for _, id := range tt.userPermissions { for _, id := range tt.userPermissions {
_, err := store.SetUserResourcePermission(context.Background(), tt.orgID, accesscontrol.User{ID: user.ID}, types.SetResourcePermissionCommand{ _, err := permissionStore.SetUserResourcePermission(context.Background(), tt.orgID, accesscontrol.User{ID: user.ID}, rs.SetResourcePermissionCommand{
Actions: []string{"dashboards:write"}, Actions: []string{"dashboards:write"},
Resource: "dashboards", Resource: "dashboards",
ResourceID: id, ResourceID: id,
@@ -93,7 +93,7 @@ func TestAccessControlStore_GetUserPermissions(t *testing.T) {
} }
for _, id := range tt.teamPermissions { for _, id := range tt.teamPermissions {
_, err := store.SetTeamResourcePermission(context.Background(), tt.orgID, team.Id, types.SetResourcePermissionCommand{ _, err := permissionStore.SetTeamResourcePermission(context.Background(), tt.orgID, team.Id, rs.SetResourcePermissionCommand{
Actions: []string{"dashboards:read"}, Actions: []string{"dashboards:read"},
Resource: "dashboards", Resource: "dashboards",
ResourceID: id, ResourceID: id,
@@ -102,7 +102,7 @@ func TestAccessControlStore_GetUserPermissions(t *testing.T) {
} }
for _, id := range tt.builtinPermissions { for _, id := range tt.builtinPermissions {
_, err := store.SetBuiltInResourcePermission(context.Background(), tt.orgID, "Admin", types.SetResourcePermissionCommand{ _, err := permissionStore.SetBuiltInResourcePermission(context.Background(), tt.orgID, "Admin", rs.SetResourcePermissionCommand{
Actions: []string{"dashboards:read"}, Actions: []string{"dashboards:read"},
Resource: "dashboards", Resource: "dashboards",
ResourceID: id, ResourceID: id,
@@ -142,11 +142,11 @@ func TestAccessControlStore_GetUserPermissions(t *testing.T) {
func TestAccessControlStore_DeleteUserPermissions(t *testing.T) { func TestAccessControlStore_DeleteUserPermissions(t *testing.T) {
t.Run("expect permissions in all orgs to be deleted", func(t *testing.T) { t.Run("expect permissions in all orgs to be deleted", func(t *testing.T) {
store, sql := setupTestEnv(t) store, permissionsStore, sql := setupTestEnv(t)
user, _ := createUserAndTeam(t, sql, 1) user, _ := createUserAndTeam(t, sql, 1)
// generate permissions in org 1 // generate permissions in org 1
_, err := store.SetUserResourcePermission(context.Background(), 1, accesscontrol.User{ID: user.ID}, types.SetResourcePermissionCommand{ _, err := permissionsStore.SetUserResourcePermission(context.Background(), 1, accesscontrol.User{ID: user.ID}, rs.SetResourcePermissionCommand{
Actions: []string{"dashboards:write"}, Actions: []string{"dashboards:write"},
Resource: "dashboards", Resource: "dashboards",
ResourceID: "1", ResourceID: "1",
@@ -154,7 +154,7 @@ func TestAccessControlStore_DeleteUserPermissions(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// generate permissions in org 2 // generate permissions in org 2
_, err = store.SetUserResourcePermission(context.Background(), 2, accesscontrol.User{ID: user.ID}, types.SetResourcePermissionCommand{ _, err = permissionsStore.SetUserResourcePermission(context.Background(), 2, accesscontrol.User{ID: user.ID}, rs.SetResourcePermissionCommand{
Actions: []string{"dashboards:write"}, Actions: []string{"dashboards:write"},
Resource: "dashboards", Resource: "dashboards",
ResourceID: "1", ResourceID: "1",
@@ -182,11 +182,11 @@ func TestAccessControlStore_DeleteUserPermissions(t *testing.T) {
}) })
t.Run("expect permissions in org 1 to be deleted", func(t *testing.T) { t.Run("expect permissions in org 1 to be deleted", func(t *testing.T) {
store, sql := setupTestEnv(t) store, permissionsStore, sql := setupTestEnv(t)
user, _ := createUserAndTeam(t, sql, 1) user, _ := createUserAndTeam(t, sql, 1)
// generate permissions in org 1 // generate permissions in org 1
_, err := store.SetUserResourcePermission(context.Background(), 1, accesscontrol.User{ID: user.ID}, types.SetResourcePermissionCommand{ _, err := permissionsStore.SetUserResourcePermission(context.Background(), 1, accesscontrol.User{ID: user.ID}, rs.SetResourcePermissionCommand{
Actions: []string{"dashboards:write"}, Actions: []string{"dashboards:write"},
Resource: "dashboards", Resource: "dashboards",
ResourceID: "1", ResourceID: "1",
@@ -194,7 +194,7 @@ func TestAccessControlStore_DeleteUserPermissions(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// generate permissions in org 2 // generate permissions in org 2
_, err = store.SetUserResourcePermission(context.Background(), 2, accesscontrol.User{ID: user.ID}, types.SetResourcePermissionCommand{ _, err = permissionsStore.SetUserResourcePermission(context.Background(), 2, accesscontrol.User{ID: user.ID}, rs.SetResourcePermissionCommand{
Actions: []string{"dashboards:write"}, Actions: []string{"dashboards:write"},
Resource: "dashboards", Resource: "dashboards",
ResourceID: "1", ResourceID: "1",
@@ -240,7 +240,9 @@ func createUserAndTeam(t *testing.T, sql *sqlstore.SQLStore, orgID int64) (*user
return user, team return user, team
} }
func setupTestEnv(t testing.TB) (*AccessControlStore, *sqlstore.SQLStore) { func setupTestEnv(t testing.TB) (*AccessControlStore, rs.Store, *sqlstore.SQLStore) {
store := sqlstore.InitTestDB(t) sql := sqlstore.InitTestDB(t)
return ProvideService(store), store acstore := ProvideService(sql)
permissionStore := rs.NewStore(sql)
return acstore, permissionStore, sql
} }

View File

@@ -1,26 +0,0 @@
package database
import (
"fmt"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/util"
)
func generateNewRoleUID(sess *sqlstore.DBSession, orgID int64) (string, error) {
for i := 0; i < 3; i++ {
uid := util.GenerateShortUID()
exists, err := sess.Where("org_id=? AND uid=?", orgID, uid).Get(&accesscontrol.Role{})
if err != nil {
return "", err
}
if !exists {
return uid, nil
}
}
return "", fmt.Errorf("failed to generate uid")
}

View File

@@ -37,7 +37,7 @@ var (
func ProvideTeamPermissions( func ProvideTeamPermissions(
cfg *setting.Cfg, router routing.RouteRegister, sql *sqlstore.SQLStore, cfg *setting.Cfg, router routing.RouteRegister, sql *sqlstore.SQLStore,
ac accesscontrol.AccessControl, store resourcepermissions.Store, license models.Licensing, ac accesscontrol.AccessControl, license models.Licensing,
) (*TeamPermissionsService, error) { ) (*TeamPermissionsService, error) {
options := resourcepermissions.Options{ options := resourcepermissions.Options{
Resource: "teams", Resource: "teams",
@@ -93,7 +93,7 @@ func ProvideTeamPermissions(
}, },
} }
srv, err := resourcepermissions.New(options, cfg, router, license, ac, store, sql) srv, err := resourcepermissions.New(options, cfg, router, license, ac, sql)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -110,8 +110,7 @@ var DashboardAdminActions = append(DashboardEditActions, []string{dashboards.Act
func ProvideDashboardPermissions( func ProvideDashboardPermissions(
cfg *setting.Cfg, router routing.RouteRegister, sql *sqlstore.SQLStore, cfg *setting.Cfg, router routing.RouteRegister, sql *sqlstore.SQLStore,
ac accesscontrol.AccessControl, store resourcepermissions.Store, ac accesscontrol.AccessControl, license models.Licensing, dashboardStore dashboards.Store,
license models.Licensing, dashboardStore dashboards.Store,
) (*DashboardPermissionsService, error) { ) (*DashboardPermissionsService, error) {
getDashboard := func(ctx context.Context, orgID int64, resourceID string) (*models.Dashboard, error) { getDashboard := func(ctx context.Context, orgID int64, resourceID string) (*models.Dashboard, error) {
query := &models.GetDashboardQuery{Uid: resourceID, OrgId: orgID} query := &models.GetDashboardQuery{Uid: resourceID, OrgId: orgID}
@@ -165,7 +164,7 @@ func ProvideDashboardPermissions(
RoleGroup: "Dashboards", RoleGroup: "Dashboards",
} }
srv, err := resourcepermissions.New(options, cfg, router, license, ac, store, sql) srv, err := resourcepermissions.New(options, cfg, router, license, ac, sql)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -189,8 +188,7 @@ var FolderAdminActions = append(FolderEditActions, []string{dashboards.ActionFol
func ProvideFolderPermissions( func ProvideFolderPermissions(
cfg *setting.Cfg, router routing.RouteRegister, sql *sqlstore.SQLStore, cfg *setting.Cfg, router routing.RouteRegister, sql *sqlstore.SQLStore,
accesscontrol accesscontrol.AccessControl, store resourcepermissions.Store, accesscontrol accesscontrol.AccessControl, license models.Licensing, dashboardStore dashboards.Store,
license models.Licensing, dashboardStore dashboards.Store,
) (*FolderPermissionsService, error) { ) (*FolderPermissionsService, error) {
options := resourcepermissions.Options{ options := resourcepermissions.Options{
Resource: "folders", Resource: "folders",
@@ -221,7 +219,7 @@ func ProvideFolderPermissions(
WriterRoleName: "Folder permission writer", WriterRoleName: "Folder permission writer",
RoleGroup: "Folders", RoleGroup: "Folders",
} }
srv, err := resourcepermissions.New(options, cfg, router, license, accesscontrol, store, sql) srv, err := resourcepermissions.New(options, cfg, router, license, accesscontrol, sql)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -266,8 +264,7 @@ type ServiceAccountPermissionsService struct {
func ProvideServiceAccountPermissions( func ProvideServiceAccountPermissions(
cfg *setting.Cfg, router routing.RouteRegister, sql *sqlstore.SQLStore, cfg *setting.Cfg, router routing.RouteRegister, sql *sqlstore.SQLStore,
ac accesscontrol.AccessControl, store resourcepermissions.Store, ac accesscontrol.AccessControl, license models.Licensing, serviceAccountStore serviceaccounts.Store,
license models.Licensing, serviceAccountStore serviceaccounts.Store,
) (*ServiceAccountPermissionsService, error) { ) (*ServiceAccountPermissionsService, error) {
options := resourcepermissions.Options{ options := resourcepermissions.Options{
Resource: "serviceaccounts", Resource: "serviceaccounts",
@@ -294,7 +291,7 @@ func ProvideServiceAccountPermissions(
RoleGroup: "Service accounts", RoleGroup: "Service accounts",
} }
srv, err := resourcepermissions.New(options, cfg, router, license, ac, store, sql) srv, err := resourcepermissions.New(options, cfg, router, license, ac, sql)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1,4 +1,4 @@
package types package resourcepermissions
import ( import (
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"

View File

@@ -1,4 +1,4 @@
package types package resourcepermissions
import ( import (
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"

View File

@@ -8,7 +8,6 @@ import (
"github.com/grafana/grafana/pkg/api/routing" "github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions/types"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
@@ -20,37 +19,37 @@ type Store interface {
SetUserResourcePermission( SetUserResourcePermission(
ctx context.Context, orgID int64, ctx context.Context, orgID int64,
user accesscontrol.User, user accesscontrol.User,
cmd types.SetResourcePermissionCommand, cmd SetResourcePermissionCommand,
hook types.UserResourceHookFunc, hook UserResourceHookFunc,
) (*accesscontrol.ResourcePermission, error) ) (*accesscontrol.ResourcePermission, error)
// SetTeamResourcePermission sets permission for managed team role on a resource // SetTeamResourcePermission sets permission for managed team role on a resource
SetTeamResourcePermission( SetTeamResourcePermission(
ctx context.Context, orgID, teamID int64, ctx context.Context, orgID, teamID int64,
cmd types.SetResourcePermissionCommand, cmd SetResourcePermissionCommand,
hook types.TeamResourceHookFunc, hook TeamResourceHookFunc,
) (*accesscontrol.ResourcePermission, error) ) (*accesscontrol.ResourcePermission, error)
// SetBuiltInResourcePermission sets permissions for managed builtin role on a resource // SetBuiltInResourcePermission sets permissions for managed builtin role on a resource
SetBuiltInResourcePermission( SetBuiltInResourcePermission(
ctx context.Context, orgID int64, builtinRole string, ctx context.Context, orgID int64, builtinRole string,
cmd types.SetResourcePermissionCommand, cmd SetResourcePermissionCommand,
hook types.BuiltinResourceHookFunc, hook BuiltinResourceHookFunc,
) (*accesscontrol.ResourcePermission, error) ) (*accesscontrol.ResourcePermission, error)
SetResourcePermissions( SetResourcePermissions(
ctx context.Context, orgID int64, ctx context.Context, orgID int64,
commands []types.SetResourcePermissionsCommand, commands []SetResourcePermissionsCommand,
hooks types.ResourceHooks, hooks ResourceHooks,
) ([]accesscontrol.ResourcePermission, error) ) ([]accesscontrol.ResourcePermission, error)
// GetResourcePermissions will return all permission for supplied resource id // GetResourcePermissions will return all permission for supplied resource id
GetResourcePermissions(ctx context.Context, orgID int64, query types.GetResourcePermissionsQuery) ([]accesscontrol.ResourcePermission, error) GetResourcePermissions(ctx context.Context, orgID int64, query GetResourcePermissionsQuery) ([]accesscontrol.ResourcePermission, error)
} }
func New( func New(
options Options, cfg *setting.Cfg, router routing.RouteRegister, license models.Licensing, options Options, cfg *setting.Cfg, router routing.RouteRegister,
ac accesscontrol.AccessControl, store Store, sqlStore *sqlstore.SQLStore, license models.Licensing, ac accesscontrol.AccessControl, sqlStore *sqlstore.SQLStore,
) (*Service, error) { ) (*Service, error) {
var permissions []string var permissions []string
actionSet := make(map[string]struct{}) actionSet := make(map[string]struct{})
@@ -74,7 +73,7 @@ func New(
s := &Service{ s := &Service{
ac: ac, ac: ac,
cfg: cfg, cfg: cfg,
store: store, store: NewStore(sqlStore),
options: options, options: options,
license: license, license: license,
permissions: permissions, permissions: permissions,
@@ -117,7 +116,7 @@ func (s *Service) GetPermissions(ctx context.Context, user *user.SignedInUser, r
} }
} }
return s.store.GetResourcePermissions(ctx, user.OrgID, types.GetResourcePermissionsQuery{ return s.store.GetResourcePermissions(ctx, user.OrgID, GetResourcePermissionsQuery{
User: user, User: user,
Actions: s.actions, Actions: s.actions,
Resource: s.options.Resource, Resource: s.options.Resource,
@@ -142,7 +141,7 @@ func (s *Service) SetUserPermission(ctx context.Context, orgID int64, user acces
return nil, err return nil, err
} }
return s.store.SetUserResourcePermission(ctx, orgID, user, types.SetResourcePermissionCommand{ return s.store.SetUserResourcePermission(ctx, orgID, user, SetResourcePermissionCommand{
Actions: actions, Actions: actions,
Permission: permission, Permission: permission,
Resource: s.options.Resource, Resource: s.options.Resource,
@@ -165,7 +164,7 @@ func (s *Service) SetTeamPermission(ctx context.Context, orgID, teamID int64, re
return nil, err return nil, err
} }
return s.store.SetTeamResourcePermission(ctx, orgID, teamID, types.SetResourcePermissionCommand{ return s.store.SetTeamResourcePermission(ctx, orgID, teamID, SetResourcePermissionCommand{
Actions: actions, Actions: actions,
Permission: permission, Permission: permission,
Resource: s.options.Resource, Resource: s.options.Resource,
@@ -188,7 +187,7 @@ func (s *Service) SetBuiltInRolePermission(ctx context.Context, orgID int64, bui
return nil, err return nil, err
} }
return s.store.SetBuiltInResourcePermission(ctx, orgID, builtInRole, types.SetResourcePermissionCommand{ return s.store.SetBuiltInResourcePermission(ctx, orgID, builtInRole, SetResourcePermissionCommand{
Actions: actions, Actions: actions,
Permission: permission, Permission: permission,
Resource: s.options.Resource, Resource: s.options.Resource,
@@ -205,7 +204,7 @@ func (s *Service) SetPermissions(
return nil, err return nil, err
} }
dbCommands := make([]types.SetResourcePermissionsCommand, 0, len(commands)) dbCommands := make([]SetResourcePermissionsCommand, 0, len(commands))
for _, cmd := range commands { for _, cmd := range commands {
if cmd.UserID != 0 { if cmd.UserID != 0 {
if err := s.validateUser(ctx, orgID, cmd.UserID); err != nil { if err := s.validateUser(ctx, orgID, cmd.UserID); err != nil {
@@ -226,11 +225,11 @@ func (s *Service) SetPermissions(
return nil, err return nil, err
} }
dbCommands = append(dbCommands, types.SetResourcePermissionsCommand{ dbCommands = append(dbCommands, SetResourcePermissionsCommand{
User: accesscontrol.User{ID: cmd.UserID}, User: accesscontrol.User{ID: cmd.UserID},
TeamID: cmd.TeamID, TeamID: cmd.TeamID,
BuiltinRole: cmd.BuiltinRole, BuiltinRole: cmd.BuiltinRole,
SetResourcePermissionCommand: types.SetResourcePermissionCommand{ SetResourcePermissionCommand: SetResourcePermissionCommand{
Actions: actions, Actions: actions,
Resource: s.options.Resource, Resource: s.options.Resource,
ResourceID: resourceID, ResourceID: resourceID,
@@ -240,7 +239,7 @@ func (s *Service) SetPermissions(
}) })
} }
return s.store.SetResourcePermissions(ctx, orgID, dbCommands, types.ResourceHooks{ return s.store.SetResourcePermissions(ctx, orgID, dbCommands, ResourceHooks{
User: s.options.OnSetUser, User: s.options.OnSetUser,
Team: s.options.OnSetTeam, Team: s.options.OnSetTeam,
BuiltInRole: s.options.OnSetBuiltInRole, BuiltInRole: s.options.OnSetBuiltInRole,

View File

@@ -9,7 +9,6 @@ import (
"github.com/grafana/grafana/pkg/api/routing" "github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/database"
accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock" accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
"github.com/grafana/grafana/pkg/services/licensing/licensingtest" "github.com/grafana/grafana/pkg/services/licensing/licensingtest"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
@@ -220,13 +219,12 @@ func setupTestEnvironment(t *testing.T, permissions []accesscontrol.Permission,
t.Helper() t.Helper()
sql := sqlstore.InitTestDB(t) sql := sqlstore.InitTestDB(t)
store := database.ProvideService(sql)
cfg := setting.NewCfg() cfg := setting.NewCfg()
license := licensingtest.NewFakeLicensing() license := licensingtest.NewFakeLicensing()
license.On("FeatureEnabled", "accesscontrol.enforcement").Return(true).Maybe() license.On("FeatureEnabled", "accesscontrol.enforcement").Return(true).Maybe()
service, err := New( service, err := New(
ops, cfg, routing.NewRouteRegister(), license, ops, cfg, routing.NewRouteRegister(), license,
accesscontrolmock.New().WithPermissions(permissions), store, sql, accesscontrolmock.New().WithPermissions(permissions), sql,
) )
require.NoError(t, err) require.NoError(t, err)

View File

@@ -1,4 +1,4 @@
package database package resourcepermissions
import ( import (
"context" "context"
@@ -6,14 +6,23 @@ import (
"strings" "strings"
"time" "time"
"github.com/grafana/grafana/pkg/util"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions/types"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
) )
func NewStore(sql *sqlstore.SQLStore) *store {
return &store{sql}
}
type store struct {
sql *sqlstore.SQLStore
}
type flatResourcePermission struct { type flatResourcePermission struct {
ID int64 `xorm:"id"` ID int64 `xorm:"id"`
RoleName string RoleName string
@@ -38,10 +47,10 @@ func (p *flatResourcePermission) IsInherited(scope string) bool {
return p.Scope != scope return p.Scope != scope
} }
func (s *AccessControlStore) SetUserResourcePermission( func (s *store) SetUserResourcePermission(
ctx context.Context, orgID int64, usr accesscontrol.User, ctx context.Context, orgID int64, usr accesscontrol.User,
cmd types.SetResourcePermissionCommand, cmd SetResourcePermissionCommand,
hook types.UserResourceHookFunc, hook UserResourceHookFunc,
) (*accesscontrol.ResourcePermission, error) { ) (*accesscontrol.ResourcePermission, error) {
if usr.ID == 0 { if usr.ID == 0 {
return nil, user.ErrUserNotFound return nil, user.ErrUserNotFound
@@ -56,10 +65,10 @@ func (s *AccessControlStore) SetUserResourcePermission(
return permission, err return permission, err
} }
func (s *AccessControlStore) setUserResourcePermission( func (s *store) setUserResourcePermission(
sess *sqlstore.DBSession, orgID int64, user accesscontrol.User, sess *sqlstore.DBSession, orgID int64, user accesscontrol.User,
cmd types.SetResourcePermissionCommand, cmd SetResourcePermissionCommand,
hook types.UserResourceHookFunc, hook UserResourceHookFunc,
) (*accesscontrol.ResourcePermission, error) { ) (*accesscontrol.ResourcePermission, error) {
permission, err := s.setResourcePermission(sess, orgID, accesscontrol.ManagedUserRoleName(user.ID), s.userAdder(sess, orgID, user.ID), cmd) permission, err := s.setResourcePermission(sess, orgID, accesscontrol.ManagedUserRoleName(user.ID), s.userAdder(sess, orgID, user.ID), cmd)
if err != nil { if err != nil {
@@ -75,10 +84,10 @@ func (s *AccessControlStore) setUserResourcePermission(
return permission, nil return permission, nil
} }
func (s *AccessControlStore) SetTeamResourcePermission( func (s *store) SetTeamResourcePermission(
ctx context.Context, orgID, teamID int64, ctx context.Context, orgID, teamID int64,
cmd types.SetResourcePermissionCommand, cmd SetResourcePermissionCommand,
hook types.TeamResourceHookFunc, hook TeamResourceHookFunc,
) (*accesscontrol.ResourcePermission, error) { ) (*accesscontrol.ResourcePermission, error) {
if teamID == 0 { if teamID == 0 {
return nil, models.ErrTeamNotFound return nil, models.ErrTeamNotFound
@@ -95,10 +104,10 @@ func (s *AccessControlStore) SetTeamResourcePermission(
return permission, err return permission, err
} }
func (s *AccessControlStore) setTeamResourcePermission( func (s *store) setTeamResourcePermission(
sess *sqlstore.DBSession, orgID, teamID int64, sess *sqlstore.DBSession, orgID, teamID int64,
cmd types.SetResourcePermissionCommand, cmd SetResourcePermissionCommand,
hook types.TeamResourceHookFunc, hook TeamResourceHookFunc,
) (*accesscontrol.ResourcePermission, error) { ) (*accesscontrol.ResourcePermission, error) {
permission, err := s.setResourcePermission(sess, orgID, accesscontrol.ManagedTeamRoleName(teamID), s.teamAdder(sess, orgID, teamID), cmd) permission, err := s.setResourcePermission(sess, orgID, accesscontrol.ManagedTeamRoleName(teamID), s.teamAdder(sess, orgID, teamID), cmd)
if err != nil { if err != nil {
@@ -114,10 +123,10 @@ func (s *AccessControlStore) setTeamResourcePermission(
return permission, nil return permission, nil
} }
func (s *AccessControlStore) SetBuiltInResourcePermission( func (s *store) SetBuiltInResourcePermission(
ctx context.Context, orgID int64, builtInRole string, ctx context.Context, orgID int64, builtInRole string,
cmd types.SetResourcePermissionCommand, cmd SetResourcePermissionCommand,
hook types.BuiltinResourceHookFunc, hook BuiltinResourceHookFunc,
) (*accesscontrol.ResourcePermission, error) { ) (*accesscontrol.ResourcePermission, error) {
if !org.RoleType(builtInRole).IsValid() || builtInRole == accesscontrol.RoleGrafanaAdmin { if !org.RoleType(builtInRole).IsValid() || builtInRole == accesscontrol.RoleGrafanaAdmin {
return nil, fmt.Errorf("invalid role: %s", builtInRole) return nil, fmt.Errorf("invalid role: %s", builtInRole)
@@ -138,10 +147,10 @@ func (s *AccessControlStore) SetBuiltInResourcePermission(
return permission, nil return permission, nil
} }
func (s *AccessControlStore) setBuiltInResourcePermission( func (s *store) setBuiltInResourcePermission(
sess *sqlstore.DBSession, orgID int64, builtInRole string, sess *sqlstore.DBSession, orgID int64, builtInRole string,
cmd types.SetResourcePermissionCommand, cmd SetResourcePermissionCommand,
hook types.BuiltinResourceHookFunc, hook BuiltinResourceHookFunc,
) (*accesscontrol.ResourcePermission, error) { ) (*accesscontrol.ResourcePermission, error) {
permission, err := s.setResourcePermission(sess, orgID, accesscontrol.ManagedBuiltInRoleName(builtInRole), s.builtInRoleAdder(sess, orgID, builtInRole), cmd) permission, err := s.setResourcePermission(sess, orgID, accesscontrol.ManagedBuiltInRoleName(builtInRole), s.builtInRoleAdder(sess, orgID, builtInRole), cmd)
if err != nil { if err != nil {
@@ -157,10 +166,10 @@ func (s *AccessControlStore) setBuiltInResourcePermission(
return permission, nil return permission, nil
} }
func (s *AccessControlStore) SetResourcePermissions( func (s *store) SetResourcePermissions(
ctx context.Context, orgID int64, ctx context.Context, orgID int64,
commands []types.SetResourcePermissionsCommand, commands []SetResourcePermissionsCommand,
hooks types.ResourceHooks, hooks ResourceHooks,
) ([]accesscontrol.ResourcePermission, error) { ) ([]accesscontrol.ResourcePermission, error) {
var err error var err error
var permissions []accesscontrol.ResourcePermission var permissions []accesscontrol.ResourcePermission
@@ -191,8 +200,8 @@ func (s *AccessControlStore) SetResourcePermissions(
type roleAdder func(roleID int64) error type roleAdder func(roleID int64) error
func (s *AccessControlStore) setResourcePermission( func (s *store) setResourcePermission(
sess *sqlstore.DBSession, orgID int64, roleName string, adder roleAdder, cmd types.SetResourcePermissionCommand, sess *sqlstore.DBSession, orgID int64, roleName string, adder roleAdder, cmd SetResourcePermissionCommand,
) (*accesscontrol.ResourcePermission, error) { ) (*accesscontrol.ResourcePermission, error) {
role, err := s.getOrCreateManagedRole(sess, orgID, roleName, adder) role, err := s.getOrCreateManagedRole(sess, orgID, roleName, adder)
if err != nil { if err != nil {
@@ -255,7 +264,7 @@ func (s *AccessControlStore) setResourcePermission(
return permission, nil return permission, nil
} }
func (s *AccessControlStore) GetResourcePermissions(ctx context.Context, orgID int64, query types.GetResourcePermissionsQuery) ([]accesscontrol.ResourcePermission, error) { func (s *store) GetResourcePermissions(ctx context.Context, orgID int64, query GetResourcePermissionsQuery) ([]accesscontrol.ResourcePermission, error) {
var result []accesscontrol.ResourcePermission var result []accesscontrol.ResourcePermission
err := s.sql.WithDbSession(ctx, func(sess *sqlstore.DBSession) error { err := s.sql.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
@@ -267,7 +276,7 @@ func (s *AccessControlStore) GetResourcePermissions(ctx context.Context, orgID i
return result, err return result, err
} }
func (s *AccessControlStore) createResourcePermission(sess *sqlstore.DBSession, roleID int64, action, resource, resourceID, resourceAttribute string) (int64, error) { func (s *store) createResourcePermission(sess *sqlstore.DBSession, roleID int64, action, resource, resourceID, resourceAttribute string) (int64, error) {
permission := managedPermission(action, resource, resourceID, resourceAttribute) permission := managedPermission(action, resource, resourceID, resourceAttribute)
permission.RoleID = roleID permission.RoleID = roleID
permission.Created = time.Now() permission.Created = time.Now()
@@ -279,7 +288,7 @@ func (s *AccessControlStore) createResourcePermission(sess *sqlstore.DBSession,
return permission.ID, nil return permission.ID, nil
} }
func (s *AccessControlStore) getResourcePermissions(sess *sqlstore.DBSession, orgID int64, query types.GetResourcePermissionsQuery) ([]accesscontrol.ResourcePermission, error) { func (s *store) getResourcePermissions(sess *sqlstore.DBSession, orgID int64, query GetResourcePermissionsQuery) ([]accesscontrol.ResourcePermission, error) {
if len(query.Actions) == 0 { if len(query.Actions) == 0 {
return nil, nil return nil, nil
} }
@@ -476,7 +485,7 @@ func flatPermissionsToResourcePermission(scope string, permissions []flatResourc
} }
} }
func (s *AccessControlStore) userAdder(sess *sqlstore.DBSession, orgID, userID int64) roleAdder { func (s *store) userAdder(sess *sqlstore.DBSession, orgID, userID int64) roleAdder {
return func(roleID int64) error { return func(roleID int64) error {
if res, err := sess.Query("SELECT 1 FROM user_role WHERE org_id=? AND user_id=? AND role_id=?", orgID, userID, roleID); err != nil { if res, err := sess.Query("SELECT 1 FROM user_role WHERE org_id=? AND user_id=? AND role_id=?", orgID, userID, roleID); err != nil {
return err return err
@@ -497,7 +506,7 @@ func (s *AccessControlStore) userAdder(sess *sqlstore.DBSession, orgID, userID i
} }
} }
func (s *AccessControlStore) teamAdder(sess *sqlstore.DBSession, orgID, teamID int64) roleAdder { func (s *store) teamAdder(sess *sqlstore.DBSession, orgID, teamID int64) roleAdder {
return func(roleID int64) error { return func(roleID int64) error {
if res, err := sess.Query("SELECT 1 FROM team_role WHERE org_id=? AND team_id=? AND role_id=?", orgID, teamID, roleID); err != nil { if res, err := sess.Query("SELECT 1 FROM team_role WHERE org_id=? AND team_id=? AND role_id=?", orgID, teamID, roleID); err != nil {
return err return err
@@ -517,7 +526,7 @@ func (s *AccessControlStore) teamAdder(sess *sqlstore.DBSession, orgID, teamID i
} }
} }
func (s *AccessControlStore) builtInRoleAdder(sess *sqlstore.DBSession, orgID int64, builtinRole string) roleAdder { func (s *store) builtInRoleAdder(sess *sqlstore.DBSession, orgID int64, builtinRole string) roleAdder {
return func(roleID int64) error { return func(roleID int64) error {
if res, err := sess.Query("SELECT 1 FROM builtin_role WHERE role_id=? AND role=? AND org_id=?", roleID, builtinRole, orgID); err != nil { if res, err := sess.Query("SELECT 1 FROM builtin_role WHERE role_id=? AND role=? AND org_id=?", roleID, builtinRole, orgID); err != nil {
return err return err
@@ -537,7 +546,7 @@ func (s *AccessControlStore) builtInRoleAdder(sess *sqlstore.DBSession, orgID in
} }
} }
func (s *AccessControlStore) getOrCreateManagedRole(sess *sqlstore.DBSession, orgID int64, name string, add roleAdder) (*accesscontrol.Role, error) { func (s *store) getOrCreateManagedRole(sess *sqlstore.DBSession, orgID int64, name string, add roleAdder) (*accesscontrol.Role, error) {
role := accesscontrol.Role{OrgID: orgID, Name: name} role := accesscontrol.Role{OrgID: orgID, Name: name}
has, err := sess.Where("org_id = ? AND name = ?", orgID, name).Get(&role) has, err := sess.Where("org_id = ? AND name = ?", orgID, name).Get(&role)
@@ -572,7 +581,7 @@ func (s *AccessControlStore) getOrCreateManagedRole(sess *sqlstore.DBSession, or
return &role, nil return &role, nil
} }
func (s *AccessControlStore) getResourcePermissionsByIds(sess *sqlstore.DBSession, resource, resourceID, resourceAttribute string, ids []int64) ([]flatResourcePermission, error) { func (s *store) getResourcePermissionsByIds(sess *sqlstore.DBSession, resource, resourceID, resourceAttribute string, ids []int64) ([]flatResourcePermission, error) {
var result []flatResourcePermission var result []flatResourcePermission
if len(ids) == 0 { if len(ids) == 0 {
return result, nil return result, nil
@@ -610,6 +619,43 @@ func (s *AccessControlStore) getResourcePermissionsByIds(sess *sqlstore.DBSessio
return result, nil return result, nil
} }
func generateNewRoleUID(sess *sqlstore.DBSession, orgID int64) (string, error) {
for i := 0; i < 3; i++ {
uid := util.GenerateShortUID()
exists, err := sess.Where("org_id=? AND uid=?", orgID, uid).Get(&accesscontrol.Role{})
if err != nil {
return "", err
}
if !exists {
return uid, nil
}
}
return "", fmt.Errorf("failed to generate uid")
}
func deletePermissions(sess *sqlstore.DBSession, ids []int64) error {
if len(ids) == 0 {
return nil
}
rawSQL := "DELETE FROM permission WHERE id IN(?" + strings.Repeat(",?", len(ids)-1) + ")"
args := make([]interface{}, 0, len(ids)+1)
args = append(args, rawSQL)
for _, id := range ids {
args = append(args, id)
}
_, err := sess.Exec(args...)
if err != nil {
return err
}
return nil
}
func managedPermission(action, resource string, resourceID, resourceAttribute string) accesscontrol.Permission { func managedPermission(action, resource string, resourceID, resourceAttribute string) accesscontrol.Permission {
return accesscontrol.Permission{ return accesscontrol.Permission{
Action: action, Action: action,

View File

@@ -1,4 +1,4 @@
package database package resourcepermissions
import ( import (
"context" "context"
@@ -11,7 +11,6 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions/types"
"github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
@@ -53,10 +52,10 @@ func benchmarkDSPermissions(b *testing.B, dsNum, usersNum int) {
} }
} }
func getDSPermissions(b *testing.B, store *AccessControlStore, dataSources []int64) { func getDSPermissions(b *testing.B, store *store, dataSources []int64) {
dsId := dataSources[0] dsId := dataSources[0]
permissions, err := store.GetResourcePermissions(context.Background(), accesscontrol.GlobalOrgID, types.GetResourcePermissionsQuery{ permissions, err := store.GetResourcePermissions(context.Background(), accesscontrol.GlobalOrgID, GetResourcePermissionsQuery{
User: &user.SignedInUser{OrgID: 1, Permissions: map[int64]map[string][]string{1: {"org.users:read": {"users:*"}, "teams:read": {"teams:*"}}}}, User: &user.SignedInUser{OrgID: 1, Permissions: map[int64]map[string][]string{1: {"org.users:read": {"users:*"}, "teams:read": {"teams:*"}}}},
Actions: []string{dsAction}, Actions: []string{dsAction},
Resource: dsResource, Resource: dsResource,
@@ -67,13 +66,13 @@ func getDSPermissions(b *testing.B, store *AccessControlStore, dataSources []int
assert.GreaterOrEqual(b, len(permissions), 2) assert.GreaterOrEqual(b, len(permissions), 2)
} }
func setupResourceBenchmark(b *testing.B, dsNum, usersNum int) (*AccessControlStore, []int64) { func setupResourceBenchmark(b *testing.B, dsNum, usersNum int) (*store, []int64) {
ac, sql := setupTestEnv(b) ac, sql := setupTestEnv(b)
dataSources := GenerateDatasourcePermissions(b, sql, ac, dsNum, usersNum, permissionsPerDs) dataSources := GenerateDatasourcePermissions(b, sql, ac, dsNum, usersNum, permissionsPerDs)
return ac, dataSources return ac, dataSources
} }
func GenerateDatasourcePermissions(b *testing.B, db *sqlstore.SQLStore, ac *AccessControlStore, dsNum, usersNum, permissionsPerDs int) []int64 { func GenerateDatasourcePermissions(b *testing.B, db *sqlstore.SQLStore, ac *store, dsNum, usersNum, permissionsPerDs int) []int64 {
dataSources := make([]int64, 0) dataSources := make([]int64, 0)
for i := 0; i < dsNum; i++ { for i := 0; i < dsNum; i++ {
addDSCommand := &datasources.AddDataSourceCommand{ addDSCommand := &datasources.AddDataSourceCommand{
@@ -98,7 +97,7 @@ func GenerateDatasourcePermissions(b *testing.B, db *sqlstore.SQLStore, ac *Acce
context.Background(), context.Background(),
accesscontrol.GlobalOrgID, accesscontrol.GlobalOrgID,
accesscontrol.User{ID: userIds[i]}, accesscontrol.User{ID: userIds[i]},
types.SetResourcePermissionCommand{ SetResourcePermissionCommand{
Actions: []string{dsAction}, Actions: []string{dsAction},
Resource: dsResource, Resource: dsResource,
ResourceID: strconv.Itoa(int(dsID)), ResourceID: strconv.Itoa(int(dsID)),
@@ -116,7 +115,7 @@ func GenerateDatasourcePermissions(b *testing.B, db *sqlstore.SQLStore, ac *Acce
context.Background(), context.Background(),
accesscontrol.GlobalOrgID, accesscontrol.GlobalOrgID,
teamIds[i], teamIds[i],
types.SetResourcePermissionCommand{ SetResourcePermissionCommand{
Actions: []string{"datasources:query"}, Actions: []string{"datasources:query"},
Resource: "datasources", Resource: "datasources",
ResourceID: strconv.Itoa(int(dsID)), ResourceID: strconv.Itoa(int(dsID)),

View File

@@ -1,4 +1,4 @@
package database package resourcepermissions
import ( import (
"context" "context"
@@ -10,7 +10,6 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions/types"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
) )
@@ -23,10 +22,10 @@ type setUserResourcePermissionTest struct {
resource string resource string
resourceID string resourceID string
resourceAttribute string resourceAttribute string
seeds []types.SetResourcePermissionCommand seeds []SetResourcePermissionCommand
} }
func TestAccessControlStore_SetUserResourcePermission(t *testing.T) { func TestIntegrationStore_SetUserResourcePermission(t *testing.T) {
tests := []setUserResourcePermissionTest{ tests := []setUserResourcePermissionTest{
{ {
desc: "should set resource permission for user", desc: "should set resource permission for user",
@@ -44,7 +43,7 @@ func TestAccessControlStore_SetUserResourcePermission(t *testing.T) {
resource: "datasources", resource: "datasources",
resourceID: "1", resourceID: "1",
resourceAttribute: "uid", resourceAttribute: "uid",
seeds: []types.SetResourcePermissionCommand{ seeds: []SetResourcePermissionCommand{
{ {
Actions: []string{"datasources:query"}, Actions: []string{"datasources:query"},
Resource: "datasources", Resource: "datasources",
@@ -60,7 +59,7 @@ func TestAccessControlStore_SetUserResourcePermission(t *testing.T) {
resource: "datasources", resource: "datasources",
resourceID: "1", resourceID: "1",
resourceAttribute: "uid", resourceAttribute: "uid",
seeds: []types.SetResourcePermissionCommand{ seeds: []SetResourcePermissionCommand{
{ {
Actions: []string{"datasources:write"}, Actions: []string{"datasources:write"},
Resource: "datasources", Resource: "datasources",
@@ -79,7 +78,7 @@ func TestAccessControlStore_SetUserResourcePermission(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
} }
added, err := store.SetUserResourcePermission(context.Background(), test.userID, accesscontrol.User{ID: test.userID}, types.SetResourcePermissionCommand{ added, err := store.SetUserResourcePermission(context.Background(), test.userID, accesscontrol.User{ID: test.userID}, SetResourcePermissionCommand{
Actions: test.actions, Actions: test.actions,
Resource: test.resource, Resource: test.resource,
ResourceID: test.resourceID, ResourceID: test.resourceID,
@@ -105,10 +104,10 @@ type setTeamResourcePermissionTest struct {
resource string resource string
resourceID string resourceID string
resourceAttribute string resourceAttribute string
seeds []types.SetResourcePermissionCommand seeds []SetResourcePermissionCommand
} }
func TestAccessControlStore_SetTeamResourcePermission(t *testing.T) { func TestIntegrationStore_SetTeamResourcePermission(t *testing.T) {
tests := []setTeamResourcePermissionTest{ tests := []setTeamResourcePermissionTest{
{ {
desc: "should add new resource permission for team", desc: "should add new resource permission for team",
@@ -127,7 +126,7 @@ func TestAccessControlStore_SetTeamResourcePermission(t *testing.T) {
resource: "datasources", resource: "datasources",
resourceID: "1", resourceID: "1",
resourceAttribute: "uid", resourceAttribute: "uid",
seeds: []types.SetResourcePermissionCommand{ seeds: []SetResourcePermissionCommand{
{ {
Actions: []string{"datasources:query"}, Actions: []string{"datasources:query"},
Resource: "datasources", Resource: "datasources",
@@ -144,7 +143,7 @@ func TestAccessControlStore_SetTeamResourcePermission(t *testing.T) {
resource: "datasources", resource: "datasources",
resourceID: "1", resourceID: "1",
resourceAttribute: "uid", resourceAttribute: "uid",
seeds: []types.SetResourcePermissionCommand{ seeds: []SetResourcePermissionCommand{
{ {
Actions: []string{"datasources:query"}, Actions: []string{"datasources:query"},
Resource: "datasources", Resource: "datasources",
@@ -164,7 +163,7 @@ func TestAccessControlStore_SetTeamResourcePermission(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
} }
added, err := store.SetTeamResourcePermission(context.Background(), test.orgID, test.teamID, types.SetResourcePermissionCommand{ added, err := store.SetTeamResourcePermission(context.Background(), test.orgID, test.teamID, SetResourcePermissionCommand{
Actions: test.actions, Actions: test.actions,
Resource: test.resource, Resource: test.resource,
ResourceID: test.resourceID, ResourceID: test.resourceID,
@@ -190,10 +189,10 @@ type setBuiltInResourcePermissionTest struct {
resource string resource string
resourceID string resourceID string
resourceAttribute string resourceAttribute string
seeds []types.SetResourcePermissionCommand seeds []SetResourcePermissionCommand
} }
func TestAccessControlStore_SetBuiltInResourcePermission(t *testing.T) { func TestIntegrationStore_SetBuiltInResourcePermission(t *testing.T) {
tests := []setBuiltInResourcePermissionTest{ tests := []setBuiltInResourcePermissionTest{
{ {
desc: "should add new resource permission for builtin role", desc: "should add new resource permission for builtin role",
@@ -212,7 +211,7 @@ func TestAccessControlStore_SetBuiltInResourcePermission(t *testing.T) {
resource: "datasources", resource: "datasources",
resourceID: "1", resourceID: "1",
resourceAttribute: "uid", resourceAttribute: "uid",
seeds: []types.SetResourcePermissionCommand{ seeds: []SetResourcePermissionCommand{
{ {
Actions: []string{"datasources:query"}, Actions: []string{"datasources:query"},
Resource: "datasources", Resource: "datasources",
@@ -229,7 +228,7 @@ func TestAccessControlStore_SetBuiltInResourcePermission(t *testing.T) {
resource: "datasources", resource: "datasources",
resourceID: "1", resourceID: "1",
resourceAttribute: "uid", resourceAttribute: "uid",
seeds: []types.SetResourcePermissionCommand{ seeds: []SetResourcePermissionCommand{
{ {
Actions: []string{"datasources:query"}, Actions: []string{"datasources:query"},
Resource: "datasources", Resource: "datasources",
@@ -249,7 +248,7 @@ func TestAccessControlStore_SetBuiltInResourcePermission(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
} }
added, err := store.SetBuiltInResourcePermission(context.Background(), test.orgID, test.builtInRole, types.SetResourcePermissionCommand{ added, err := store.SetBuiltInResourcePermission(context.Background(), test.orgID, test.builtInRole, SetResourcePermissionCommand{
Actions: test.actions, Actions: test.actions,
Resource: test.resource, Resource: test.resource,
ResourceID: test.resourceID, ResourceID: test.resourceID,
@@ -271,19 +270,19 @@ type setResourcePermissionsTest struct {
desc string desc string
orgID int64 orgID int64
resourceAttribute string resourceAttribute string
commands []types.SetResourcePermissionsCommand commands []SetResourcePermissionsCommand
} }
func TestAccessControlStore_SetResourcePermissions(t *testing.T) { func TestIntegrationStore_SetResourcePermissions(t *testing.T) {
tests := []setResourcePermissionsTest{ tests := []setResourcePermissionsTest{
{ {
desc: "should set all permissions provided", desc: "should set all permissions provided",
orgID: 1, orgID: 1,
resourceAttribute: "uid", resourceAttribute: "uid",
commands: []types.SetResourcePermissionsCommand{ commands: []SetResourcePermissionsCommand{
{ {
User: accesscontrol.User{ID: 1}, User: accesscontrol.User{ID: 1},
SetResourcePermissionCommand: types.SetResourcePermissionCommand{ SetResourcePermissionCommand: SetResourcePermissionCommand{
Actions: []string{"datasources:query"}, Actions: []string{"datasources:query"},
Resource: "datasources", Resource: "datasources",
ResourceID: "1", ResourceID: "1",
@@ -292,7 +291,7 @@ func TestAccessControlStore_SetResourcePermissions(t *testing.T) {
}, },
{ {
TeamID: 3, TeamID: 3,
SetResourcePermissionCommand: types.SetResourcePermissionCommand{ SetResourcePermissionCommand: SetResourcePermissionCommand{
Actions: []string{"datasources:query"}, Actions: []string{"datasources:query"},
Resource: "datasources", Resource: "datasources",
ResourceID: "1", ResourceID: "1",
@@ -301,7 +300,7 @@ func TestAccessControlStore_SetResourcePermissions(t *testing.T) {
}, },
{ {
BuiltinRole: "Admin", BuiltinRole: "Admin",
SetResourcePermissionCommand: types.SetResourcePermissionCommand{ SetResourcePermissionCommand: SetResourcePermissionCommand{
Actions: []string{"datasources:query"}, Actions: []string{"datasources:query"},
Resource: "datasources", Resource: "datasources",
ResourceID: "1", ResourceID: "1",
@@ -316,7 +315,7 @@ func TestAccessControlStore_SetResourcePermissions(t *testing.T) {
t.Run(tt.desc, func(t *testing.T) { t.Run(tt.desc, func(t *testing.T) {
store, _ := setupTestEnv(t) store, _ := setupTestEnv(t)
permissions, err := store.SetResourcePermissions(context.Background(), tt.orgID, tt.commands, types.ResourceHooks{}) permissions, err := store.SetResourcePermissions(context.Background(), tt.orgID, tt.commands, ResourceHooks{})
require.NoError(t, err) require.NoError(t, err)
require.Len(t, permissions, len(tt.commands)) require.Len(t, permissions, len(tt.commands))
@@ -346,7 +345,7 @@ type getResourcePermissionsTest struct {
onlyManaged bool onlyManaged bool
} }
func TestAccessControlStore_GetResourcePermissions(t *testing.T) { func TestIntegrationStore_GetResourcePermissions(t *testing.T) {
tests := []getResourcePermissionsTest{ tests := []getResourcePermissionsTest{
{ {
desc: "should return permissions for resource id", desc: "should return permissions for resource id",
@@ -418,7 +417,7 @@ func TestAccessControlStore_GetResourcePermissions(t *testing.T) {
seedResourcePermissions(t, store, sql, test.actions, test.resource, test.resourceID, test.resourceAttribute, test.numUsers) seedResourcePermissions(t, store, sql, test.actions, test.resource, test.resourceID, test.resourceAttribute, test.numUsers)
permissions, err := store.GetResourcePermissions(context.Background(), test.user.OrgID, types.GetResourcePermissionsQuery{ permissions, err := store.GetResourcePermissions(context.Background(), test.user.OrgID, GetResourcePermissionsQuery{
User: test.user, User: test.user,
Actions: test.actions, Actions: test.actions,
Resource: test.resource, Resource: test.resource,
@@ -437,7 +436,7 @@ func TestAccessControlStore_GetResourcePermissions(t *testing.T) {
} }
} }
func seedResourcePermissions(t *testing.T, store *AccessControlStore, sql *sqlstore.SQLStore, actions []string, resource, resourceID, resourceAttribute string, numUsers int) { func seedResourcePermissions(t *testing.T, store *store, sql *sqlstore.SQLStore, actions []string, resource, resourceID, resourceAttribute string, numUsers int) {
t.Helper() t.Helper()
for i := 0; i < numUsers; i++ { for i := 0; i < numUsers; i++ {
org, _ := sql.GetOrgByName("test") org, _ := sql.GetOrgByName("test")
@@ -454,7 +453,7 @@ func seedResourcePermissions(t *testing.T, store *AccessControlStore, sql *sqlst
}) })
require.NoError(t, err) require.NoError(t, err)
_, err = store.SetUserResourcePermission(context.Background(), 1, accesscontrol.User{ID: u.ID}, types.SetResourcePermissionCommand{ _, err = store.SetUserResourcePermission(context.Background(), 1, accesscontrol.User{ID: u.ID}, SetResourcePermissionCommand{
Actions: actions, Actions: actions,
Resource: resource, Resource: resource,
ResourceID: resourceID, ResourceID: resourceID,
@@ -463,3 +462,8 @@ func seedResourcePermissions(t *testing.T, store *AccessControlStore, sql *sqlst
require.NoError(t, err) require.NoError(t, err)
} }
} }
func setupTestEnv(t testing.TB) (*store, *sqlstore.SQLStore) {
sql := sqlstore.InitTestDB(t)
return NewStore(sql), sql
}

View File

@@ -15,7 +15,6 @@ import (
"github.com/grafana/grafana/pkg/api/routing" "github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/database"
accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock" accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
"github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol"
"github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/dashboards"
@@ -603,10 +602,10 @@ func setupAccessControlGuardianTest(t *testing.T, uid string, permissions []acce
license.On("FeatureEnabled", "accesscontrol.enforcement").Return(true).Maybe() license.On("FeatureEnabled", "accesscontrol.enforcement").Return(true).Maybe()
folderPermissions, err := ossaccesscontrol.ProvideFolderPermissions( folderPermissions, err := ossaccesscontrol.ProvideFolderPermissions(
setting.NewCfg(), routing.NewRouteRegister(), store, ac, database.ProvideService(store), license, &dashboards.FakeDashboardStore{}) setting.NewCfg(), routing.NewRouteRegister(), store, ac, license, &dashboards.FakeDashboardStore{})
require.NoError(t, err) require.NoError(t, err)
dashboardPermissions, err := ossaccesscontrol.ProvideDashboardPermissions( dashboardPermissions, err := ossaccesscontrol.ProvideDashboardPermissions(
setting.NewCfg(), routing.NewRouteRegister(), store, ac, database.ProvideService(store), license, &dashboards.FakeDashboardStore{}) setting.NewCfg(), routing.NewRouteRegister(), store, ac, license, &dashboards.FakeDashboardStore{})
require.NoError(t, err) require.NoError(t, err)
if dashboardSvc == nil { if dashboardSvc == nil {
dashboardSvc = &dashboards.FakeDashboardService{} dashboardSvc = &dashboards.FakeDashboardService{}

View File

@@ -16,7 +16,6 @@ import (
"github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
acDatabase "github.com/grafana/grafana/pkg/services/accesscontrol/database"
accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock" accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
"github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol"
"github.com/grafana/grafana/pkg/services/apikey/apikeyimpl" "github.com/grafana/grafana/pkg/services/apikey/apikeyimpl"
@@ -279,7 +278,7 @@ func setupTestServer(t *testing.T, svc *tests.ServiceAccountMock,
acmock *accesscontrolmock.Mock, acmock *accesscontrolmock.Mock,
sqlStore *sqlstore.SQLStore, saStore serviceaccounts.Store) (*web.Mux, *ServiceAccountsAPI) { sqlStore *sqlstore.SQLStore, saStore serviceaccounts.Store) (*web.Mux, *ServiceAccountsAPI) {
cfg := setting.NewCfg() cfg := setting.NewCfg()
saPermissionService, err := ossaccesscontrol.ProvideServiceAccountPermissions(cfg, routing.NewRouteRegister(), sqlStore, acmock, acDatabase.ProvideService(sqlStore), &licensing.OSSLicensingService{}, saStore) saPermissionService, err := ossaccesscontrol.ProvideServiceAccountPermissions(cfg, routing.NewRouteRegister(), sqlStore, acmock, &licensing.OSSLicensingService{}, saStore)
require.NoError(t, err) require.NoError(t, err)
a := NewServiceAccountsAPI(cfg, svc, acmock, routerRegister, saStore, saPermissionService) a := NewServiceAccountsAPI(cfg, svc, acmock, routerRegister, saStore, saPermissionService)

View File

@@ -16,8 +16,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
acdb "github.com/grafana/grafana/pkg/services/accesscontrol/database" "github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions"
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions/types"
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models" ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
@@ -633,7 +632,7 @@ func TestPrometheusRulesPermissions(t *testing.T) {
apiClient := newAlertingApiClient(grafanaListedAddr, "grafana", "password") apiClient := newAlertingApiClient(grafanaListedAddr, "grafana", "password")
// access control permissions store // access control permissions store
permissionsStore := acdb.ProvideService(store) permissionsStore := resourcepermissions.NewStore(store)
// Create the namespace we'll save our alerts to. // Create the namespace we'll save our alerts to.
apiClient.CreateFolder(t, "folder1", "folder1") apiClient.CreateFolder(t, "folder1", "folder1")
@@ -726,17 +725,17 @@ func TestPrometheusRulesPermissions(t *testing.T) {
} }
} }
func removeFolderPermission(t *testing.T, store *acdb.AccessControlStore, orgID, userID int64, role org.RoleType, uid string) { func removeFolderPermission(t *testing.T, store resourcepermissions.Store, orgID, userID int64, role org.RoleType, uid string) {
t.Helper() t.Helper()
// remove user permissions on folder // remove user permissions on folder
_, _ = store.SetUserResourcePermission(context.Background(), orgID, accesscontrol.User{ID: userID}, types.SetResourcePermissionCommand{ _, _ = store.SetUserResourcePermission(context.Background(), orgID, accesscontrol.User{ID: userID}, resourcepermissions.SetResourcePermissionCommand{
Resource: "folders", Resource: "folders",
ResourceID: uid, ResourceID: uid,
ResourceAttribute: "uid", ResourceAttribute: "uid",
}, nil) }, nil)
// remove org role permissions from folder // remove org role permissions from folder
_, _ = store.SetBuiltInResourcePermission(context.Background(), orgID, string(role), types.SetResourcePermissionCommand{ _, _ = store.SetBuiltInResourcePermission(context.Background(), orgID, string(role), resourcepermissions.SetResourcePermissionCommand{
Resource: "folders", Resource: "folders",
ResourceID: uid, ResourceID: uid,
ResourceAttribute: "uid", ResourceAttribute: "uid",
@@ -744,7 +743,7 @@ func removeFolderPermission(t *testing.T, store *acdb.AccessControlStore, orgID,
// remove org role children permissions from folder // remove org role children permissions from folder
for _, c := range role.Children() { for _, c := range role.Children() {
_, _ = store.SetBuiltInResourcePermission(context.Background(), orgID, string(c), types.SetResourcePermissionCommand{ _, _ = store.SetBuiltInResourcePermission(context.Background(), orgID, string(c), resourcepermissions.SetResourcePermissionCommand{
Resource: "folders", Resource: "folders",
ResourceID: uid, ResourceID: uid,
ResourceAttribute: "uid", ResourceAttribute: "uid",

View File

@@ -13,7 +13,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
acdb "github.com/grafana/grafana/pkg/services/accesscontrol/database" "github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions"
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models" ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/org"
@@ -32,7 +32,7 @@ func TestAlertRulePermissions(t *testing.T) {
}) })
grafanaListedAddr, store := testinfra.StartGrafana(t, dir, path) grafanaListedAddr, store := testinfra.StartGrafana(t, dir, path)
permissionsStore := acdb.ProvideService(store) permissionsStore := resourcepermissions.NewStore(store)
// Create a user to make authenticated requests // Create a user to make authenticated requests
userID := createUser(t, store, user.CreateUserCommand{ userID := createUser(t, store, user.CreateUserCommand{