mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
AccessControl: Add resource permission deletion helper (#71222)
* add method for deleting managed resource permissions * test method
This commit is contained in:
parent
a7aca983a5
commit
49e42d1a8d
@ -96,6 +96,8 @@ type PermissionsService interface {
|
||||
SetPermissions(ctx context.Context, orgID int64, resourceID string, commands ...SetResourcePermissionCommand) ([]ResourcePermission, error)
|
||||
// MapActions will map actions for a ResourcePermissions to it's "friendly" name configured in PermissionsToActions map.
|
||||
MapActions(permission ResourcePermission) string
|
||||
// DeleteResourcePermissions removes all permissions for a resource
|
||||
DeleteResourcePermissions(ctx context.Context, orgID int64, resourceID string) error
|
||||
}
|
||||
|
||||
type User struct {
|
||||
|
@ -140,6 +140,10 @@ func (f *FakePermissionsService) SetPermissions(ctx context.Context, orgID int64
|
||||
return f.ExpectedPermissions, f.ExpectedErr
|
||||
}
|
||||
|
||||
func (f *FakePermissionsService) DeleteResourcePermissions(ctx context.Context, orgID int64, resourceID string) error {
|
||||
return f.ExpectedErr
|
||||
}
|
||||
|
||||
func (f *FakePermissionsService) MapActions(permission accesscontrol.ResourcePermission) string {
|
||||
return f.ExpectedMappedAction
|
||||
}
|
||||
|
@ -44,6 +44,11 @@ func (m *MockPermissionsService) SetPermissions(ctx context.Context, orgID int64
|
||||
return mockedArgs.Get(0).([]accesscontrol.ResourcePermission), mockedArgs.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockPermissionsService) DeleteResourcePermissions(ctx context.Context, orgID int64, resourceID string) error {
|
||||
mockedArgs := m.Called(ctx, orgID, resourceID)
|
||||
return mockedArgs.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockPermissionsService) MapActions(permission accesscontrol.ResourcePermission) string {
|
||||
mockedArgs := m.Called(permission)
|
||||
return mockedArgs.Get(0).(string)
|
||||
|
@ -273,6 +273,11 @@ func (e DatasourcePermissionsService) SetPermissions(ctx context.Context, orgID
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (e DatasourcePermissionsService) DeleteResourcePermissions(ctx context.Context, orgID int64, resourceID string) error {
|
||||
// TODO: implement
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e DatasourcePermissionsService) MapActions(permission accesscontrol.ResourcePermission) string {
|
||||
return ""
|
||||
}
|
||||
|
@ -46,6 +46,9 @@ type Store interface {
|
||||
|
||||
// GetResourcePermissions will return all permission for supplied resource id
|
||||
GetResourcePermissions(ctx context.Context, orgID int64, query GetResourcePermissionsQuery) ([]accesscontrol.ResourcePermission, error)
|
||||
|
||||
// DeleteResourcePermissions will delete all permissions for supplied resource id
|
||||
DeleteResourcePermissions(ctx context.Context, orgID int64, cmd *DeleteResourcePermissionsCmd) error
|
||||
}
|
||||
|
||||
func New(
|
||||
@ -264,6 +267,14 @@ func (s *Service) MapActions(permission accesscontrol.ResourcePermission) string
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s *Service) DeleteResourcePermissions(ctx context.Context, orgID int64, resourceID string) error {
|
||||
return s.store.DeleteResourcePermissions(ctx, orgID, &DeleteResourcePermissionsCmd{
|
||||
Resource: s.options.Resource,
|
||||
ResourceAttribute: s.options.ResourceAttribute,
|
||||
ResourceID: resourceID,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Service) mapPermission(permission string) ([]string, error) {
|
||||
if permission == "" {
|
||||
return []string{}, nil
|
||||
|
@ -48,6 +48,33 @@ func (p *flatResourcePermission) IsInherited(scope string) bool {
|
||||
return strings.HasPrefix(p.RoleName, accesscontrol.ManagedRolePrefix) && p.Scope != scope
|
||||
}
|
||||
|
||||
type DeleteResourcePermissionsCmd struct {
|
||||
Resource string
|
||||
ResourceAttribute string
|
||||
ResourceID string
|
||||
}
|
||||
|
||||
func (s *store) DeleteResourcePermissions(ctx context.Context, orgID int64, cmd *DeleteResourcePermissionsCmd) error {
|
||||
scope := accesscontrol.Scope(cmd.Resource, cmd.ResourceAttribute, cmd.ResourceID)
|
||||
|
||||
err := s.sql.WithTransactionalDbSession(ctx, func(sess *db.Session) error {
|
||||
var permissionIDs []int64
|
||||
err := sess.SQL(
|
||||
"SELECT permission.id FROM permission INNER JOIN role ON permission.role_id = role.id WHERE permission.scope = ? AND role.org_id = ?",
|
||||
scope, orgID).Find(&permissionIDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := deletePermissions(sess, permissionIDs); err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *store) SetUserResourcePermission(
|
||||
ctx context.Context, orgID int64, usr accesscontrol.User,
|
||||
cmd SetResourcePermissionCommand,
|
||||
|
@ -577,3 +577,140 @@ func TestStore_IsInherited(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type orgPermission struct {
|
||||
OrgID int64 `xorm:"org_id"`
|
||||
Action string `json:"action"`
|
||||
Scope string `json:"scope"`
|
||||
}
|
||||
|
||||
func TestIntegrationStore_DeleteResourcePermissions(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
|
||||
type deleteResourcePermissionsTest struct {
|
||||
desc string
|
||||
orgID int64
|
||||
resourceAttribute string
|
||||
command DeleteResourcePermissionsCmd
|
||||
shouldExist []orgPermission
|
||||
shouldNotExist []orgPermission
|
||||
}
|
||||
|
||||
tests := []deleteResourcePermissionsTest{
|
||||
{
|
||||
desc: "should delete all permissions for resource id in org 1",
|
||||
orgID: 1,
|
||||
resourceAttribute: "uid",
|
||||
command: DeleteResourcePermissionsCmd{
|
||||
Resource: "datasources",
|
||||
ResourceID: "1",
|
||||
ResourceAttribute: "uid",
|
||||
},
|
||||
shouldExist: []orgPermission{
|
||||
{
|
||||
OrgID: 2,
|
||||
Action: "datasources:query",
|
||||
Scope: "datasources:uid:1",
|
||||
}, {
|
||||
OrgID: 2,
|
||||
Action: "datasources:write",
|
||||
Scope: "datasources:uid:1",
|
||||
},
|
||||
{
|
||||
OrgID: 1,
|
||||
Action: "datasources:query",
|
||||
Scope: "datasources:uid:2",
|
||||
}, {
|
||||
OrgID: 1,
|
||||
Action: "datasources:write",
|
||||
Scope: "datasources:uid:2",
|
||||
}},
|
||||
shouldNotExist: []orgPermission{
|
||||
{
|
||||
OrgID: 1,
|
||||
Action: "datasources:query",
|
||||
Scope: "datasources:uid:1",
|
||||
}, {
|
||||
OrgID: 1,
|
||||
Action: "datasources:write",
|
||||
Scope: "datasources:uid:1",
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.desc, func(t *testing.T) {
|
||||
store, _ := setupTestEnv(t)
|
||||
|
||||
_, err := store.SetResourcePermissions(context.Background(), 1, []SetResourcePermissionsCommand{
|
||||
{
|
||||
User: accesscontrol.User{ID: 1},
|
||||
SetResourcePermissionCommand: SetResourcePermissionCommand{
|
||||
Actions: []string{"datasources:query", "datasources:write"},
|
||||
Resource: "datasources",
|
||||
ResourceID: "1",
|
||||
ResourceAttribute: "uid",
|
||||
},
|
||||
},
|
||||
}, ResourceHooks{})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = store.SetResourcePermissions(context.Background(), 1, []SetResourcePermissionsCommand{
|
||||
{
|
||||
User: accesscontrol.User{ID: 1},
|
||||
SetResourcePermissionCommand: SetResourcePermissionCommand{
|
||||
Actions: []string{"datasources:query", "datasources:write"},
|
||||
Resource: "datasources",
|
||||
ResourceID: "2",
|
||||
ResourceAttribute: "uid",
|
||||
},
|
||||
},
|
||||
}, ResourceHooks{})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = store.SetResourcePermissions(context.Background(), 2, []SetResourcePermissionsCommand{
|
||||
{
|
||||
User: accesscontrol.User{ID: 1},
|
||||
SetResourcePermissionCommand: SetResourcePermissionCommand{
|
||||
Actions: []string{"datasources:query", "datasources:write"},
|
||||
Resource: "datasources",
|
||||
ResourceID: "1",
|
||||
ResourceAttribute: "uid",
|
||||
},
|
||||
},
|
||||
}, ResourceHooks{})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = store.DeleteResourcePermissions(context.Background(), tt.orgID, &tt.command)
|
||||
require.NoError(t, err)
|
||||
|
||||
permissions := retrievePermissionsHelper(store, t)
|
||||
|
||||
for _, p := range tt.shouldExist {
|
||||
assert.Contains(t, permissions, p)
|
||||
}
|
||||
|
||||
for _, p := range tt.shouldNotExist {
|
||||
assert.NotContains(t, permissions, p)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func retrievePermissionsHelper(store *store, t *testing.T) []orgPermission {
|
||||
permissions := []orgPermission{}
|
||||
err := store.sql.WithDbSession(context.Background(), func(sess *db.Session) error {
|
||||
err := sess.SQL(`
|
||||
SELECT permission.*, role.org_id
|
||||
FROM permission
|
||||
INNER JOIN role ON permission.role_id = role.id
|
||||
`).Find(&permissions)
|
||||
require.NoError(t, err)
|
||||
return nil
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
return permissions
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user