AccessControl: SQL filters for team search (#44557)

* AccessControl: SQL filters for team search

Set test config

* Remove userIdFilter when FGAC is on
This commit is contained in:
Gabriel MABILLE
2022-02-09 16:17:31 +01:00
committed by GitHub
parent f016e19d1a
commit 01b88adb3a
6 changed files with 190 additions and 6 deletions

View File

@@ -12,6 +12,7 @@ import (
var sqlIDAcceptList = map[string]struct{}{
"org_user.user_id": {},
"role.id": {},
"team.id": {},
}
var (

View File

@@ -10,6 +10,7 @@ import (
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/models"
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/featuremgmt"
)
func (ss *SQLStore) addTeamQueryAndCommandHandlers() {
@@ -210,6 +211,19 @@ func (ss *SQLStore) SearchTeams(ctx context.Context, query *models.SearchTeamsQu
params = append(params, query.Name)
}
var (
acFilter ac.SQLFilter
err error
)
if ss.Cfg.IsFeatureToggleEnabled(featuremgmt.FlagAccesscontrol) {
acFilter, err = ac.Filter(ctx, "team.id", "teams", ac.ActionTeamsRead, query.SignedInUser)
if err != nil {
return err
}
sql.WriteString(` and` + acFilter.Where)
params = append(params, acFilter.Args...)
}
sql.WriteString(` order by team.name asc`)
if query.Limit != 0 {
@@ -245,6 +259,11 @@ func (ss *SQLStore) SearchTeams(ctx context.Context, query *models.SearchTeamsQu
)`, query.UserIdFilter)
}
// Only count teams user can see
if ss.Cfg.IsFeatureToggleEnabled(featuremgmt.FlagAccesscontrol) {
countSess.Where(acFilter.Where, acFilter.Args...)
}
count, err := countSess.Count(&team)
query.Result.TotalCount = count

View File

@@ -9,6 +9,9 @@ import (
"testing"
"github.com/grafana/grafana/pkg/models"
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -344,3 +347,75 @@ func TestTeamCommandsAndQueries(t *testing.T) {
})
})
}
func TestSQLStore_SearchTeams(t *testing.T) {
type searchTeamsTestCase struct {
desc string
query *models.SearchTeamsQuery
expectedNumUsers int
}
tests := []searchTeamsTestCase{
{
desc: "should return all teams",
query: &models.SearchTeamsQuery{
OrgId: 1,
SignedInUser: &models.SignedInUser{
OrgId: 1,
Permissions: map[int64]map[string][]string{1: {ac.ActionTeamsRead: {ac.ScopeTeamsAll}}},
},
},
expectedNumUsers: 10,
},
{
desc: "should return no teams",
query: &models.SearchTeamsQuery{
OrgId: 1,
SignedInUser: &models.SignedInUser{
OrgId: 1,
Permissions: map[int64]map[string][]string{1: {ac.ActionTeamsRead: {""}}},
},
},
expectedNumUsers: 0,
},
{
desc: "should return some teams",
query: &models.SearchTeamsQuery{
OrgId: 1,
SignedInUser: &models.SignedInUser{
OrgId: 1,
Permissions: map[int64]map[string][]string{1: {ac.ActionTeamsRead: {
"teams:id:1",
"teams:id:5",
"teams:id:9",
}}},
},
},
expectedNumUsers: 3,
},
}
store := InitTestDB(t)
store.Cfg.IsFeatureToggleEnabled = featuremgmt.WithFeatures(featuremgmt.FlagAccesscontrol).IsEnabled
// Seed 10 teams
for i := 1; i <= 10; i++ {
_, err := store.CreateTeam(fmt.Sprintf("team-%d", i), fmt.Sprintf("team-%d@example.org", i), 1)
require.NoError(t, err)
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
err := store.SearchTeams(context.Background(), tt.query)
require.NoError(t, err)
assert.Len(t, tt.query.Result.Teams, tt.expectedNumUsers)
assert.Equal(t, tt.query.Result.TotalCount, int64(tt.expectedNumUsers))
if !hasWildcardScope(tt.query.SignedInUser, ac.ActionTeamsRead) {
for _, team := range tt.query.Result.Teams {
assert.Contains(t, tt.query.SignedInUser.Permissions[tt.query.SignedInUser.OrgId][ac.ActionTeamsRead], fmt.Sprintf("teams:id:%d", team.Id))
}
}
})
}
}