diff --git a/pkg/services/accesscontrol/database/database_test.go b/pkg/services/accesscontrol/database/database_test.go index a6fee84e2d9..ba0f0f82793 100644 --- a/pkg/services/accesscontrol/database/database_test.go +++ b/pkg/services/accesscontrol/database/database_test.go @@ -395,7 +395,8 @@ func setupTestEnv(t testing.TB) (*AccessControlStore, rs.Store, user.Service, te cfg.AutoAssignOrgId = 1 acstore := ProvideService(sql) log := log.New("test") - permissionStore := rs.NewStore(sql, featuremgmt.WithFeatures(), rs.NewInMemoryActionSets(log)) + asService := rs.NewInMemoryActionSets(log) + permissionStore := rs.NewStore(sql, featuremgmt.WithFeatures(), &asService) teamService, err := teamimpl.ProvideService(sql, cfg) require.NoError(t, err) orgService, err := orgimpl.ProvideService(sql, cfg, quotatest.New(false, nil)) diff --git a/pkg/services/accesscontrol/resourcepermissions/service.go b/pkg/services/accesscontrol/resourcepermissions/service.go index d51a9edec84..d4e73a74596 100644 --- a/pkg/services/accesscontrol/resourcepermissions/service.go +++ b/pkg/services/accesscontrol/resourcepermissions/service.go @@ -59,7 +59,8 @@ func New(cfg *setting.Cfg, ac accesscontrol.AccessControl, service accesscontrol.Service, sqlStore db.DB, teamService team.Service, userService user.Service, ) (*Service, error) { - // TODO: add log, actionsetstore as a dependency + // TODO: add log as a dependency + // TODO: add actionsetstore from wire log := log.New("accesscontrol.resourcepermissions") actionSetsStore := NewInMemoryActionSets(log) @@ -71,7 +72,11 @@ func New(cfg *setting.Cfg, actionSet[a] = struct{}{} } // storing the actionset - actionSetsStore.StoreActionSet(options.Resource, permission, actions) + err := actionSetsStore.StoreActionSet(options.Resource, permission, actions) + if err != nil { + log.Warn("failed to store action set", "error", err) + return nil, err + } } // Sort all permissions based on action length. Will be used when mapping between actions to permissions @@ -86,7 +91,7 @@ func New(cfg *setting.Cfg, s := &Service{ ac: ac, - store: NewStore(sqlStore, features, actionSetsStore), + store: NewStore(sqlStore, features, &actionSetsStore), options: options, license: license, permissions: permissions, diff --git a/pkg/services/accesscontrol/resourcepermissions/store.go b/pkg/services/accesscontrol/resourcepermissions/store.go index 6699da8e22e..1ea1995f1d5 100644 --- a/pkg/services/accesscontrol/resourcepermissions/store.go +++ b/pkg/services/accesscontrol/resourcepermissions/store.go @@ -18,14 +18,14 @@ import ( "github.com/grafana/grafana/pkg/util" ) -func NewStore(sql db.DB, features featuremgmt.FeatureToggles, inMemoryActionSets *InMemoryActionSets) *store { - return &store{sql, features, *inMemoryActionSets} +func NewStore(sql db.DB, features featuremgmt.FeatureToggles, actionsetService *ActionSetService) *store { + return &store{sql, features, *actionsetService} } type store struct { - sql db.DB - features featuremgmt.FeatureToggles - inMemoryActionSets InMemoryActionSets + sql db.DB + features featuremgmt.FeatureToggles + actionSetService ActionSetService } type flatResourcePermission struct { @@ -679,7 +679,7 @@ func (s *store) createPermissions(sess *db.Session, roleID int64, resource, reso */ if s.features.IsEnabled(context.TODO(), featuremgmt.FlagAccessActionSets) { // FIXME: make this only one resource of view, editor, admin - actionSetName, err := s.inMemoryActionSets.CreateActionSetName(resource, permission) + actionSetName, err := s.actionSetService.GetActionSetName(resource, permission) if err != nil { return err } @@ -739,29 +739,42 @@ actionSet := &ActionSet{ Actions: []string{"folders:read", "folders:write", "dashboards:read", "dashboards:write"}, }` */ + +type ActionSetGetter interface { + GetActionSet(actionName string) []string + GetActionSetName(resource, permission string) (string, error) +} + +type ActionSetStorer interface { + StoreActionSet(resource, permission string, actions []string) error +} + +type ActionSetService interface { + ActionSetGetter + ActionSetStorer +} + type ActionSet struct { - Action string `json:"action"` - Resource string `json:"resource"` - Permission string `json:"permission"` - Actions []string `json:"actions"` + Action string `json:"action"` + Actions []string `json:"actions"` } // InMemoryActionSets is an in-memory implementation of the ActionSetService. type InMemoryActionSets struct { log log.Logger - actionSets map[string]*ActionSet + actionSets map[string][]string } // NewInMemoryActionSets returns a new instance of InMemoryActionSetService. -func NewInMemoryActionSets(log log.Logger) *InMemoryActionSets { +func NewInMemoryActionSets(log log.Logger) ActionSetService { return &InMemoryActionSets{ - actionSets: make(map[string]*ActionSet), + actionSets: make(map[string][]string), log: log, } } // GetActionSet returns the action set for the given action. -func (s *InMemoryActionSets) GetActionSet(actionName string) *ActionSet { +func (s *InMemoryActionSets) GetActionSet(actionName string) []string { actionSet, ok := s.actionSets[actionName] if !ok { return nil @@ -769,26 +782,25 @@ func (s *InMemoryActionSets) GetActionSet(actionName string) *ActionSet { return actionSet } -func (s *InMemoryActionSets) StoreActionSet(resource, permission string, actions []string) { +func (s *InMemoryActionSets) StoreActionSet(resource, permission string, actions []string) error { s.log.Debug("storing action set\n") - name, err := s.CreateActionSetName(resource, permission) + name, err := s.GetActionSetName(resource, permission) if err != nil { - s.log.Error("error creating action set", "error", err) + return err } actionSet := &ActionSet{ // folders:edit - Action: name, - Resource: resource, - Permission: permission, - Actions: actions, + Action: name, + Actions: actions, } // TODO: Do we only store the actions, or all of the information about the action set - s.actionSets[actionSet.Action] = actionSet + s.actionSets[actionSet.Action] = actions s.log.Debug("stored action set actionname \n", actionSet.Action) + return nil } -// CreateActionSetName function creates an action set from a list of actions and stores it inmemory. -func (s *InMemoryActionSets) CreateActionSetName(resource, permission string) (string, error) { +// GetActionSetName function creates an action set from a list of actions and stores it inmemory. +func (s *InMemoryActionSets) GetActionSetName(resource, permission string) (string, error) { // lower cased resource = strings.ToLower(resource) permission = strings.ToLower(permission) diff --git a/pkg/services/accesscontrol/resourcepermissions/store_test.go b/pkg/services/accesscontrol/resourcepermissions/store_test.go index 9243956f086..5bc6b6f210d 100644 --- a/pkg/services/accesscontrol/resourcepermissions/store_test.go +++ b/pkg/services/accesscontrol/resourcepermissions/store_test.go @@ -561,7 +561,8 @@ func seedResourcePermissions( func setupTestEnv(t testing.TB) (*store, db.DB, *setting.Cfg) { sql := db.InitTestDB(t) log := log.New("test") - return NewStore(sql, featuremgmt.WithFeatures(), NewInMemoryActionSets(log)), sql, sql.Cfg + asService := NewInMemoryActionSets(log) + return NewStore(sql, featuremgmt.WithFeatures(), &asService), sql, sql.Cfg } func TestStore_IsInherited(t *testing.T) { @@ -773,9 +774,7 @@ func TestStore_ResourcePermissionsActionSets(t *testing.T) { desc: "should be able to store actionset", orgID: 1, actionSet: ActionSet{ - Resource: "folders", - Permission: "edit", - Actions: []string{"folders:read", "folders:write"}, + Actions: []string{"folders:read", "folders:write"}, }, }, } @@ -790,18 +789,18 @@ func TestStore_ResourcePermissionsActionSets(t *testing.T) { User: accesscontrol.User{ID: 1}, SetResourcePermissionCommand: SetResourcePermissionCommand{ Actions: tt.actionSet.Actions, - Resource: tt.actionSet.Resource, + Resource: "folders", + Permission: "edit", ResourceID: "1", ResourceAttribute: "uid", - Permission: tt.actionSet.Permission, }, }, }, ResourceHooks{}) require.NoError(t, err) - actionname := fmt.Sprintf("%s:%s", tt.actionSet.Resource, tt.actionSet.Permission) - actionSet := store.inMemoryActionSets.GetActionSet(actionname) - require.Equal(t, tt.actionSet.Actions, actionSet.Actions) + actionname := fmt.Sprintf("%s:%s", "folders", "edit") + actionSet := store.actionSetService.GetActionSet(actionname) + require.Equal(t, tt.actionSet.Actions, actionSet) }) } }