RBAC: Add userLogin filter to the permission search endpoint (#81137)
* RBAC: Search add user login filter * Switch to a userService resolving instead * Remove unused error * Fallback to use the cache * account for userID filter * Account for the error * snake case * Add test cases * Add api tests * Fix return on error * Re-order imports
This commit is contained in:
@@ -42,8 +42,8 @@ var SharedWithMeFolderPermission = accesscontrol.Permission{
|
||||
}
|
||||
|
||||
func ProvideService(cfg *setting.Cfg, db db.DB, routeRegister routing.RouteRegister, cache *localcache.CacheService,
|
||||
accessControl accesscontrol.AccessControl, features featuremgmt.FeatureToggles) (*Service, error) {
|
||||
service := ProvideOSSService(cfg, database.ProvideService(db), cache, features)
|
||||
accessControl accesscontrol.AccessControl, userSvc user.Service, features featuremgmt.FeatureToggles) (*Service, error) {
|
||||
service := ProvideOSSService(cfg, database.ProvideService(db), cache, userSvc, features)
|
||||
|
||||
api.NewAccessControlAPI(routeRegister, accessControl, service, features).RegisterAPIEndpoints()
|
||||
if err := accesscontrol.DeclareFixedRoles(service, cfg); err != nil {
|
||||
@@ -63,14 +63,15 @@ func ProvideService(cfg *setting.Cfg, db db.DB, routeRegister routing.RouteRegis
|
||||
return service, nil
|
||||
}
|
||||
|
||||
func ProvideOSSService(cfg *setting.Cfg, store store, cache *localcache.CacheService, features featuremgmt.FeatureToggles) *Service {
|
||||
func ProvideOSSService(cfg *setting.Cfg, store store, cache *localcache.CacheService, userSvc user.Service, features featuremgmt.FeatureToggles) *Service {
|
||||
s := &Service{
|
||||
cfg: cfg,
|
||||
store: store,
|
||||
log: log.New("accesscontrol.service"),
|
||||
cache: cache,
|
||||
roles: accesscontrol.BuildBasicRoleDefinitions(),
|
||||
cfg: cfg,
|
||||
features: features,
|
||||
log: log.New("accesscontrol.service"),
|
||||
roles: accesscontrol.BuildBasicRoleDefinitions(),
|
||||
store: store,
|
||||
userSvc: userSvc,
|
||||
}
|
||||
|
||||
return s
|
||||
@@ -88,13 +89,14 @@ type store interface {
|
||||
|
||||
// Service is the service implementing role based access control.
|
||||
type Service struct {
|
||||
log log.Logger
|
||||
cfg *setting.Cfg
|
||||
store store
|
||||
cache *localcache.CacheService
|
||||
cfg *setting.Cfg
|
||||
features featuremgmt.FeatureToggles
|
||||
log log.Logger
|
||||
registrations accesscontrol.RegistrationList
|
||||
roles map[string]*accesscontrol.RoleDTO
|
||||
features featuremgmt.FeatureToggles
|
||||
store store
|
||||
userSvc user.Service
|
||||
}
|
||||
|
||||
func (s *Service) GetUsageStats(_ context.Context) map[string]any {
|
||||
@@ -243,8 +245,25 @@ func (s *Service) DeclarePluginRoles(ctx context.Context, ID, name string, regs
|
||||
}
|
||||
|
||||
// SearchUsersPermissions returns all users' permissions filtered by action prefixes
|
||||
func (s *Service) SearchUsersPermissions(ctx context.Context, user identity.Requester,
|
||||
func (s *Service) SearchUsersPermissions(ctx context.Context, usr identity.Requester,
|
||||
options accesscontrol.SearchOptions) (map[int64][]accesscontrol.Permission, error) {
|
||||
if options.UserLogin != "" {
|
||||
// Resolve userLogin -> userID
|
||||
if err := options.ResolveUserLogin(ctx, s.userSvc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
options.UserLogin = ""
|
||||
}
|
||||
if options.UserID > 0 {
|
||||
// Reroute to the user specific implementation of search permissions
|
||||
// because it leverages the user permission cache.
|
||||
userPerms, err := s.SearchUserPermissions(ctx, usr.GetOrgID(), options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return map[int64][]accesscontrol.Permission{options.UserID: userPerms}, nil
|
||||
}
|
||||
|
||||
timer := prometheus.NewTimer(metrics.MAccessSearchPermissionsSummary)
|
||||
defer timer.ObserveDuration()
|
||||
|
||||
@@ -258,20 +277,20 @@ func (s *Service) SearchUsersPermissions(ctx context.Context, user identity.Requ
|
||||
}
|
||||
}
|
||||
|
||||
usersRoles, err := s.store.GetUsersBasicRoles(ctx, nil, user.GetOrgID())
|
||||
usersRoles, err := s.store.GetUsersBasicRoles(ctx, nil, usr.GetOrgID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get managed permissions (DB)
|
||||
usersPermissions, err := s.store.SearchUsersPermissions(ctx, user.GetOrgID(), options)
|
||||
usersPermissions, err := s.store.SearchUsersPermissions(ctx, usr.GetOrgID(), options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// helper to filter out permissions the signed in users cannot see
|
||||
canView := func() func(userID int64) bool {
|
||||
siuPermissions := user.GetPermissions()
|
||||
siuPermissions := usr.GetPermissions()
|
||||
if len(siuPermissions) == 0 {
|
||||
return func(_ int64) bool { return false }
|
||||
}
|
||||
@@ -329,8 +348,15 @@ func (s *Service) SearchUserPermissions(ctx context.Context, orgID int64, search
|
||||
timer := prometheus.NewTimer(metrics.MAccessPermissionsSummary)
|
||||
defer timer.ObserveDuration()
|
||||
|
||||
if searchOptions.UserLogin != "" {
|
||||
// Resolve userLogin -> userID
|
||||
if err := searchOptions.ResolveUserLogin(ctx, s.userSvc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if searchOptions.UserID == 0 {
|
||||
return nil, fmt.Errorf("expected user ID to be specified")
|
||||
return nil, fmt.Errorf("expected user ID or login to be specified")
|
||||
}
|
||||
|
||||
if permissions, success := s.searchUserPermissionsFromCache(orgID, searchOptions); success {
|
||||
|
||||
Reference in New Issue
Block a user