diff --git a/pkg/api/folder_bench_test.go b/pkg/api/folder_bench_test.go index 3c394bf44c9..17bb27e0dd9 100644 --- a/pkg/api/folder_bench_test.go +++ b/pkg/api/folder_bench_test.go @@ -46,7 +46,6 @@ import ( "github.com/grafana/grafana/pkg/services/team/teamimpl" "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user/userimpl" - "github.com/grafana/grafana/pkg/services/user/usertest" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/web" "github.com/grafana/grafana/pkg/web/webtest" @@ -444,7 +443,7 @@ func setupServer(b testing.TB, sc benchScenario, features featuremgmt.FeatureTog license := licensingtest.NewFakeLicensing() license.On("FeatureEnabled", "accesscontrol.enforcement").Return(true).Maybe() - acSvc := acimpl.ProvideOSSService(sc.cfg, acdb.ProvideService(sc.db), localcache.ProvideService(), usertest.NewUserServiceFake(), features) + acSvc := acimpl.ProvideOSSService(sc.cfg, acdb.ProvideService(sc.db), localcache.ProvideService(), features) quotaSrv := quotatest.New(false, nil) diff --git a/pkg/cmd/grafana-cli/commands/conflict_user_command.go b/pkg/cmd/grafana-cli/commands/conflict_user_command.go index 43cd08073a4..3e607cecca8 100644 --- a/pkg/cmd/grafana-cli/commands/conflict_user_command.go +++ b/pkg/cmd/grafana-cli/commands/conflict_user_command.go @@ -69,7 +69,7 @@ func initializeConflictResolver(cmd *utils.ContextCommandLine, f Formatter, ctx return nil, fmt.Errorf("%v: %w", "failed to get user service", err) } routing := routing.ProvideRegister() - acService, err := acimpl.ProvideService(cfg, s, routing, nil, nil, nil, features) + acService, err := acimpl.ProvideService(cfg, s, routing, nil, nil, features) if err != nil { return nil, fmt.Errorf("%v: %w", "failed to get access control", err) } diff --git a/pkg/services/accesscontrol/accesscontrol.go b/pkg/services/accesscontrol/accesscontrol.go index ab9a93e68f4..cc0c60bc272 100644 --- a/pkg/services/accesscontrol/accesscontrol.go +++ b/pkg/services/accesscontrol/accesscontrol.go @@ -2,7 +2,9 @@ package accesscontrol import ( "context" + "errors" "fmt" + "strconv" "strings" "github.com/grafana/grafana/pkg/registry" @@ -57,8 +59,7 @@ type SearchOptions struct { ActionPrefix string // Needed for the PoC v1, it's probably going to be removed. Action string Scope string - UserLogin string // Login for which to return information, if none is specified information is returned for all users. - UserID int64 // ID for the user for which to return information, if none is specified information is returned for all users. + NamespacedID string // ID of the identity (ex: user:3, service-account:4) wildcards Wildcards // private field computed based on the Scope } @@ -77,17 +78,26 @@ func (s *SearchOptions) Wildcards() []string { return s.wildcards } -func (s *SearchOptions) ResolveUserLogin(ctx context.Context, userSvc user.Service) error { - if s.UserLogin == "" { - return nil +func (s *SearchOptions) ComputeUserID() (int64, error) { + if s.NamespacedID == "" { + return 0, errors.New("namespacedID must be set") } - // Resolve userLogin -> userID - dbUsr, err := userSvc.GetByLogin(ctx, &user.GetUserByLoginQuery{LoginOrEmail: s.UserLogin}) + // Split namespaceID into namespace and ID + parts := strings.Split(s.NamespacedID, ":") + // Validate namespace ID format + if len(parts) != 2 { + return 0, fmt.Errorf("invalid namespaced ID: %s", s.NamespacedID) + } + // Validate namespace type is user or service account + if parts[0] != identity.NamespaceUser && parts[0] != identity.NamespaceServiceAccount { + return 0, fmt.Errorf("invalid namespace: %s", parts[0]) + } + // Validate namespace ID is a number + id, err := strconv.ParseInt(parts[1], 10, 64) if err != nil { - return err + return 0, fmt.Errorf("invalid namespaced ID: %s", s.NamespacedID) } - s.UserID = dbUsr.ID - return nil + return id, nil } type SyncUserRolesCommand struct { diff --git a/pkg/services/accesscontrol/acimpl/service.go b/pkg/services/accesscontrol/acimpl/service.go index 56b669b74e4..d6118feb16e 100644 --- a/pkg/services/accesscontrol/acimpl/service.go +++ b/pkg/services/accesscontrol/acimpl/service.go @@ -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, userSvc user.Service, features featuremgmt.FeatureToggles) (*Service, error) { - service := ProvideOSSService(cfg, database.ProvideService(db), cache, userSvc, features) + accessControl accesscontrol.AccessControl, features featuremgmt.FeatureToggles) (*Service, error) { + service := ProvideOSSService(cfg, database.ProvideService(db), cache, features) api.NewAccessControlAPI(routeRegister, accessControl, service, features).RegisterAPIEndpoints() if err := accesscontrol.DeclareFixedRoles(service, cfg); err != nil { @@ -61,7 +61,7 @@ func ProvideService(cfg *setting.Cfg, db db.DB, routeRegister routing.RouteRegis return service, nil } -func ProvideOSSService(cfg *setting.Cfg, store store, cache *localcache.CacheService, userSvc user.Service, features featuremgmt.FeatureToggles) *Service { +func ProvideOSSService(cfg *setting.Cfg, store store, cache *localcache.CacheService, features featuremgmt.FeatureToggles) *Service { s := &Service{ cache: cache, cfg: cfg, @@ -69,7 +69,6 @@ func ProvideOSSService(cfg *setting.Cfg, store store, cache *localcache.CacheSer log: log.New("accesscontrol.service"), roles: accesscontrol.BuildBasicRoleDefinitions(), store: store, - userSvc: userSvc, } return s @@ -94,7 +93,6 @@ type Service struct { registrations accesscontrol.RegistrationList roles map[string]*accesscontrol.RoleDTO store store - userSvc user.Service } func (s *Service) GetUsageStats(_ context.Context) map[string]any { @@ -245,21 +243,20 @@ 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, 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 { + if options.NamespacedID != "" { + userID, err := options.ComputeUserID() + if err != nil { + s.log.Error("Failed to resolve user ID", "error", err) 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 + return map[int64][]accesscontrol.Permission{userID: userPerms}, nil } timer := prometheus.NewTimer(metrics.MAccessSearchPermissionsSummary) @@ -346,15 +343,8 @@ 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 or login to be specified") + if searchOptions.NamespacedID == "" { + return nil, fmt.Errorf("expected namespaced ID to be specified") } if permissions, success := s.searchUserPermissionsFromCache(orgID, searchOptions); success { @@ -364,15 +354,20 @@ func (s *Service) SearchUserPermissions(ctx context.Context, orgID int64, search } func (s *Service) searchUserPermissions(ctx context.Context, orgID int64, searchOptions accesscontrol.SearchOptions) ([]accesscontrol.Permission, error) { + userID, err := searchOptions.ComputeUserID() + if err != nil { + return nil, err + } + // Get permissions for user's basic roles from RAM - roleList, err := s.store.GetUsersBasicRoles(ctx, []int64{searchOptions.UserID}, orgID) + roleList, err := s.store.GetUsersBasicRoles(ctx, []int64{userID}, orgID) if err != nil { return nil, fmt.Errorf("could not fetch basic roles for the user: %w", err) } var roles []string var ok bool - if roles, ok = roleList[searchOptions.UserID]; !ok { - return nil, fmt.Errorf("found no basic roles for user %d in organisation %d", searchOptions.UserID, orgID) + if roles, ok = roleList[userID]; !ok { + return nil, fmt.Errorf("found no basic roles for user %d in organisation %d", userID, orgID) } permissions := make([]accesscontrol.Permission, 0) for _, builtin := range roles { @@ -390,15 +385,20 @@ func (s *Service) searchUserPermissions(ctx context.Context, orgID int64, search if err != nil { return nil, err } - permissions = append(permissions, dbPermissions[searchOptions.UserID]...) + permissions = append(permissions, dbPermissions[userID]...) return permissions, nil } func (s *Service) searchUserPermissionsFromCache(orgID int64, searchOptions accesscontrol.SearchOptions) ([]accesscontrol.Permission, bool) { + userID, err := searchOptions.ComputeUserID() + if err != nil { + return nil, false + } + // Create a temp signed in user object to retrieve cache key tempUser := &user.SignedInUser{ - UserID: searchOptions.UserID, + UserID: userID, OrgID: orgID, } diff --git a/pkg/services/accesscontrol/acimpl/service_test.go b/pkg/services/accesscontrol/acimpl/service_test.go index d9e6467a072..053448e48f2 100644 --- a/pkg/services/accesscontrol/acimpl/service_test.go +++ b/pkg/services/accesscontrol/acimpl/service_test.go @@ -15,11 +15,11 @@ import ( "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol/actest" "github.com/grafana/grafana/pkg/services/accesscontrol/database" + "github.com/grafana/grafana/pkg/services/auth/identity" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/licensing" "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/user" - "github.com/grafana/grafana/pkg/services/user/usertest" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/tests/testsuite" ) @@ -40,7 +40,6 @@ func setupTestEnv(t testing.TB) *Service { registrations: accesscontrol.RegistrationList{}, roles: accesscontrol.BuildBasicRoleDefinitions(), store: database.ProvideService(db.InitTestDB(t)), - userSvc: usertest.NewUserServiceFake(), } require.NoError(t, ac.RegisterFixedRoles(context.Background())) return ac @@ -65,7 +64,6 @@ func TestUsageMetrics(t *testing.T) { cfg, database.ProvideService(db.InitTestDB(t)), localcache.ProvideService(), - usertest.NewUserServiceFake(), featuremgmt.WithFeatures(), ) assert.Equal(t, tt.expectedValue, s.GetUsageStats(context.Background())["stats.oss.accesscontrol.enabled.count"]) @@ -537,9 +535,9 @@ func TestService_SearchUsersPermissions(t *testing.T) { { // This test is not exactly representative as normally the store would return // only the user's basic roles and the user's stored permissions - name: "check userID filter works correctly", + name: "check namespacedId filter works correctly", siuPermissions: listAllPerms, - searchOption: accesscontrol.SearchOptions{UserID: 1}, + searchOption: accesscontrol.SearchOptions{NamespacedID: identity.NamespaceServiceAccount + ":1"}, ramRoles: map[string]*accesscontrol.RoleDTO{ string(roletype.RoleEditor): {Permissions: []accesscontrol.Permission{ {Action: accesscontrol.ActionTeamsRead, Scope: "teams:*"}, @@ -564,47 +562,11 @@ func TestService_SearchUsersPermissions(t *testing.T) { 1: {{Action: accesscontrol.ActionTeamsRead, Scope: "teams:id:1"}, {Action: accesscontrol.ActionTeamsRead, Scope: "teams:*"}}, }, }, - { - // This test is not exactly representative as normally the store would return - // only the user's basic roles and the user's stored permissions - name: "check userLogin filter works correctly", - siuPermissions: listAllPerms, - searchOption: accesscontrol.SearchOptions{UserLogin: "testUser"}, - ramRoles: map[string]*accesscontrol.RoleDTO{ - string(roletype.RoleEditor): {Permissions: []accesscontrol.Permission{ - {Action: accesscontrol.ActionTeamsRead, Scope: "teams:*"}, - }}, - string(roletype.RoleAdmin): {Permissions: []accesscontrol.Permission{ - {Action: accesscontrol.ActionTeamsWrite, Scope: "teams:*"}, - }}, - accesscontrol.RoleGrafanaAdmin: {Permissions: []accesscontrol.Permission{ - {Action: accesscontrol.ActionTeamsPermissionsRead, Scope: "teams:*"}, - }}, - }, - storedPerms: map[int64][]accesscontrol.Permission{ - 1: {{Action: accesscontrol.ActionTeamsRead, Scope: "teams:id:1"}}, - 2: {{Action: accesscontrol.ActionTeamsRead, Scope: "teams:id:1"}, - {Action: accesscontrol.ActionTeamsPermissionsRead, Scope: "teams:id:1"}}, - }, - storedRoles: map[int64][]string{ - 1: {string(roletype.RoleEditor)}, - 2: {string(roletype.RoleAdmin), accesscontrol.RoleGrafanaAdmin}, - }, - want: map[int64][]accesscontrol.Permission{ - 2: {{Action: accesscontrol.ActionTeamsWrite, Scope: "teams:*"}, - {Action: accesscontrol.ActionTeamsRead, Scope: "teams:id:1"}, - {Action: accesscontrol.ActionTeamsPermissionsRead, Scope: "teams:id:1"}, - {Action: accesscontrol.ActionTeamsPermissionsRead, Scope: "teams:*"}}, - }, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { ac := setupTestEnv(t) - // Resolve user login to id 2 - ac.userSvc = &usertest.FakeUserService{ExpectedUser: &user.User{ID: 2}} - ac.roles = tt.ramRoles ac.store = actest.FakeStore{ ExpectedUsersPermissions: tt.storedPerms, @@ -645,7 +607,7 @@ func TestService_SearchUserPermissions(t *testing.T) { name: "ram only", searchOption: accesscontrol.SearchOptions{ ActionPrefix: "teams", - UserID: 2, + NamespacedID: identity.NamespaceUser + ":2", }, ramRoles: map[string]*accesscontrol.RoleDTO{ string(roletype.RoleEditor): {Permissions: []accesscontrol.Permission{ @@ -670,7 +632,7 @@ func TestService_SearchUserPermissions(t *testing.T) { name: "stored only", searchOption: accesscontrol.SearchOptions{ ActionPrefix: "teams", - UserID: 2, + NamespacedID: identity.NamespaceUser + ":2", }, storedPerms: map[int64][]accesscontrol.Permission{ 1: {{Action: accesscontrol.ActionTeamsRead, Scope: "teams:id:1"}}, @@ -690,7 +652,7 @@ func TestService_SearchUserPermissions(t *testing.T) { name: "ram and stored", searchOption: accesscontrol.SearchOptions{ ActionPrefix: "teams", - UserID: 2, + NamespacedID: identity.NamespaceUser + ":2", }, ramRoles: map[string]*accesscontrol.RoleDTO{ string(roletype.RoleAdmin): {Permissions: []accesscontrol.Permission{ @@ -720,7 +682,7 @@ func TestService_SearchUserPermissions(t *testing.T) { name: "check action prefix filter works correctly", searchOption: accesscontrol.SearchOptions{ ActionPrefix: "teams", - UserID: 1, + NamespacedID: identity.NamespaceUser + ":1", }, ramRoles: map[string]*accesscontrol.RoleDTO{ string(roletype.RoleEditor): {Permissions: []accesscontrol.Permission{ @@ -741,8 +703,8 @@ func TestService_SearchUserPermissions(t *testing.T) { { name: "check action filter works correctly", searchOption: accesscontrol.SearchOptions{ - Action: accesscontrol.ActionTeamsRead, - UserID: 1, + Action: accesscontrol.ActionTeamsRead, + NamespacedID: identity.NamespaceUser + ":1", }, ramRoles: map[string]*accesscontrol.RoleDTO{ string(roletype.RoleEditor): {Permissions: []accesscontrol.Permission{ diff --git a/pkg/services/accesscontrol/api/api.go b/pkg/services/accesscontrol/api/api.go index c5f276ec8ac..67e7951267b 100644 --- a/pkg/services/accesscontrol/api/api.go +++ b/pkg/services/accesscontrol/api/api.go @@ -2,7 +2,6 @@ package api import ( "net/http" - "strconv" "github.com/grafana/grafana/pkg/api/response" "github.com/grafana/grafana/pkg/api/routing" @@ -69,30 +68,17 @@ func (api *AccessControlAPI) getUserPermissions(c *contextmodel.ReqContext) resp // GET /api/access-control/users/permissions/search func (api *AccessControlAPI) searchUsersPermissions(c *contextmodel.ReqContext) response.Response { searchOptions := ac.SearchOptions{ - UserLogin: c.Query("userLogin"), ActionPrefix: c.Query("actionPrefix"), Action: c.Query("action"), Scope: c.Query("scope"), - } - - userIDString := c.Query("userId") - if userIDString != "" { - userID, err := strconv.ParseInt(userIDString, 10, 64) - if err != nil { - return response.Error(http.StatusBadRequest, "user ID is invalid", err) - } - searchOptions.UserID = userID + NamespacedID: c.Query("namespacedId"), } // Validate inputs - if (searchOptions.ActionPrefix != "") && (searchOptions.Action != "") { + if searchOptions.ActionPrefix != "" && searchOptions.Action != "" { return response.JSON(http.StatusBadRequest, "'action' and 'actionPrefix' are mutually exclusive") } - if (searchOptions.UserLogin != "") && (searchOptions.UserID > 0) { - return response.JSON(http.StatusBadRequest, "'userId' and 'userLogin' are mutually exclusive") - } - if searchOptions.UserID <= 0 && searchOptions.UserLogin == "" && - searchOptions.ActionPrefix == "" && searchOptions.Action == "" { + if searchOptions.NamespacedID == "" && searchOptions.ActionPrefix == "" && searchOptions.Action == "" { return response.JSON(http.StatusBadRequest, "at least one search option must be provided") } diff --git a/pkg/services/accesscontrol/api/api_test.go b/pkg/services/accesscontrol/api/api_test.go index 85ec4620b1d..0502504a373 100644 --- a/pkg/services/accesscontrol/api/api_test.go +++ b/pkg/services/accesscontrol/api/api_test.go @@ -139,31 +139,21 @@ func TestAccessControlAPI_searchUsersPermissions(t *testing.T) { expectedCode: http.StatusBadRequest, }, { - desc: "Should reject if conflicting user filters are provided", - filters: "?userLogin=admin&userId=2", - expectedCode: http.StatusBadRequest, - }, - { - desc: "Should reject if invalid userID is provided", - filters: "?userId=invalid", - expectedCode: http.StatusBadRequest, - }, - { - desc: "Should work with valid filter provided", - filters: "?userId=2", + desc: "Should work with valid namespacedId filter provided", + filters: "?namespacedId=service-account:2", permissions: map[int64][]ac.Permission{2: {{Action: "users:read", Scope: "users:*"}}}, expectedCode: http.StatusOK, expectedOutput: map[int64]map[string][]string{2: {"users:read": {"users:*"}}}, }, { desc: "Should reduce permissions", - filters: "?userId=2", + filters: "?namespacedId=service-account:2", permissions: map[int64][]ac.Permission{2: {{Action: "users:read", Scope: "users:id:1"}, {Action: "users:read", Scope: "users:*"}}}, expectedCode: http.StatusOK, expectedOutput: map[int64]map[string][]string{2: {"users:read": {"users:*"}}}, }, { - desc: "Should work with valid action filter", + desc: "Should work with valid action prefix filter", filters: "?actionPrefix=users:", permissions: map[int64][]ac.Permission{ 1: {{Action: "users:write", Scope: "users:id:1"}}, diff --git a/pkg/services/accesscontrol/database/database.go b/pkg/services/accesscontrol/database/database.go index f7a84ccaa88..b914f2c3ff5 100644 --- a/pkg/services/accesscontrol/database/database.go +++ b/pkg/services/accesscontrol/database/database.go @@ -113,10 +113,13 @@ func (s *AccessControlStore) SearchUsersPermissions(ctx context.Context, orgID i params = append(params, scopes[i]) } } - - if options.UserID != 0 { + if options.NamespacedID != "" { + userID, err := options.ComputeUserID() + if err != nil { + return err + } q += ` AND user_id = ?` - params = append(params, options.UserID) + params = append(params, userID) } return sess.SQL(q, params...). diff --git a/pkg/services/accesscontrol/database/database_test.go b/pkg/services/accesscontrol/database/database_test.go index 26596c72d6e..cbfbd43bb4d 100644 --- a/pkg/services/accesscontrol/database/database_test.go +++ b/pkg/services/accesscontrol/database/database_test.go @@ -13,6 +13,7 @@ import ( "github.com/grafana/grafana/pkg/infra/localcache" "github.com/grafana/grafana/pkg/services/accesscontrol" rs "github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions" + "github.com/grafana/grafana/pkg/services/auth/identity" "github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/org" @@ -468,7 +469,7 @@ func TestIntegrationAccessControlStore_SearchUsersPermissions(t *testing.T) { }, options: accesscontrol.SearchOptions{ ActionPrefix: "teams:", - UserID: 1, + NamespacedID: identity.NamespaceUser + ":1", }, wantPerm: map[int64][]accesscontrol.Permission{ 1: {{Action: "teams:read", Scope: "teams:id:1"}, {Action: "teams:read", Scope: "teams:id:10"}, diff --git a/pkg/services/extsvcauth/oauthserver/oasimpl/service_test.go b/pkg/services/extsvcauth/oauthserver/oasimpl/service_test.go index 1f810a94669..42a77a24e13 100644 --- a/pkg/services/extsvcauth/oauthserver/oasimpl/service_test.go +++ b/pkg/services/extsvcauth/oauthserver/oasimpl/service_test.go @@ -83,7 +83,7 @@ func setupTestEnv(t *testing.T) *TestEnv { cache: localcache.New(cacheExpirationTime, cacheCleanupInterval), cfg: cfg, accessControl: acimpl.ProvideAccessControl(cfg), - acService: acimpl.ProvideOSSService(cfg, env.AcStore, localcache.New(0, 0), env.UserService, fmgt), + acService: acimpl.ProvideOSSService(cfg, env.AcStore, localcache.New(0, 0), fmgt), memstore: storage.NewMemoryStore(), sqlstore: env.OAuthStore, logger: log.New("oauthserver.test"), diff --git a/pkg/services/extsvcauth/oauthserver/oasimpl/token.go b/pkg/services/extsvcauth/oauthserver/oasimpl/token.go index 2dc18d6370d..d36f6b4ce05 100644 --- a/pkg/services/extsvcauth/oauthserver/oasimpl/token.go +++ b/pkg/services/extsvcauth/oauthserver/oasimpl/token.go @@ -11,6 +11,7 @@ import ( "github.com/ory/fosite/handler/oauth2" ac "github.com/grafana/grafana/pkg/services/accesscontrol" + "github.com/grafana/grafana/pkg/services/auth/identity" "github.com/grafana/grafana/pkg/services/extsvcauth/oauthserver" "github.com/grafana/grafana/pkg/services/extsvcauth/oauthserver/utils" "github.com/grafana/grafana/pkg/services/team" @@ -224,7 +225,8 @@ func (s *OAuth2ServiceImpl) handleJWTBearer(ctx context.Context, accessRequest f // filteredUserPermissions gets the user permissions and applies the actions filter func (s *OAuth2ServiceImpl) filteredUserPermissions(ctx context.Context, userID int64, actionsFilter map[string]bool) ([]ac.Permission, error) { - permissions, err := s.acService.SearchUserPermissions(ctx, oauthserver.TmpOrgID, ac.SearchOptions{UserID: userID}) + permissions, err := s.acService.SearchUserPermissions(ctx, oauthserver.TmpOrgID, + ac.SearchOptions{NamespacedID: fmt.Sprintf("%s:%d", identity.NamespaceUser, userID)}) if err != nil { return nil, &fosite.RFC6749Error{ DescriptionField: "The permissions scope could not be processed.", diff --git a/pkg/services/ngalert/migration/store/testing.go b/pkg/services/ngalert/migration/store/testing.go index 4de16e239f7..1c00676e791 100644 --- a/pkg/services/ngalert/migration/store/testing.go +++ b/pkg/services/ngalert/migration/store/testing.go @@ -64,7 +64,7 @@ func NewTestMigrationStore(t testing.TB, sqlStore *sqlstore.SQLStore, cfg *setti userSvc, err := userimpl.ProvideService(sqlStore, orgService, cfg, teamSvc, cache, quotaService, bundleregistry.ProvideService()) require.NoError(t, err) - acSvc, err := acimpl.ProvideService(cfg, sqlStore, routing.ProvideRegister(), cache, ac, userSvc, features) + acSvc, err := acimpl.ProvideService(cfg, sqlStore, routing.ProvideRegister(), cache, ac, features) require.NoError(t, err) dashboardStore, err := database.ProvideDashboardStore(sqlStore, sqlStore.Cfg, features, tagimpl.ProvideService(sqlStore), quotaService) diff --git a/pkg/services/serviceaccounts/extsvcaccounts/service_test.go b/pkg/services/serviceaccounts/extsvcaccounts/service_test.go index db1e6521efd..1624c71ed82 100644 --- a/pkg/services/serviceaccounts/extsvcaccounts/service_test.go +++ b/pkg/services/serviceaccounts/extsvcaccounts/service_test.go @@ -20,7 +20,6 @@ import ( "github.com/grafana/grafana/pkg/services/secrets/kvstore" sa "github.com/grafana/grafana/pkg/services/serviceaccounts" "github.com/grafana/grafana/pkg/services/serviceaccounts/tests" - "github.com/grafana/grafana/pkg/services/user/usertest" "github.com/grafana/grafana/pkg/setting" ) @@ -44,7 +43,7 @@ func setupTestEnv(t *testing.T) *TestEnv { } logger := log.New("extsvcaccounts.test") env.S = &ExtSvcAccountsService{ - acSvc: acimpl.ProvideOSSService(cfg, env.AcStore, localcache.New(0, 0), usertest.NewUserServiceFake(), fmgt), + acSvc: acimpl.ProvideOSSService(cfg, env.AcStore, localcache.New(0, 0), fmgt), features: fmgt, logger: logger, metrics: newMetrics(nil, env.SaSvc, logger),