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:
Gabriel MABILLE
2024-01-26 09:43:16 +01:00
committed by GitHub
parent 2e352ba4d6
commit 722b78f3e0
11 changed files with 246 additions and 30 deletions
@@ -19,6 +19,7 @@ import (
"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"
)
@@ -27,12 +28,14 @@ func setupTestEnv(t testing.TB) *Service {
cfg := setting.NewCfg()
ac := &Service{
cache: localcache.ProvideService(),
cfg: cfg,
features: featuremgmt.WithFeatures(),
log: log.New("accesscontrol"),
registrations: accesscontrol.RegistrationList{},
store: database.ProvideService(db.InitTestDB(t)),
roles: accesscontrol.BuildBasicRoleDefinitions(),
features: featuremgmt.WithFeatures(),
store: database.ProvideService(db.InitTestDB(t)),
userSvc: usertest.NewUserServiceFake(),
}
require.NoError(t, ac.RegisterFixedRoles(context.Background()))
return ac
@@ -57,6 +60,7 @@ 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"])
@@ -525,11 +529,77 @@ 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",
siuPermissions: listAllPerms,
searchOption: accesscontrol.SearchOptions{UserID: 1},
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{
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,