Chore: Remove legacy AC checks from team (#68715)

* removing legacy AC checks from team API handlers

* Chore: remove `UserIDFilter` from team queries (#68820)

* remove userIDfilter from team queries in favour of RBAC SQL filtering

* fix typo

* remove redundant tests

* remove another unused function

* fix failing test
This commit is contained in:
Ieva
2023-05-22 18:41:53 +02:00
committed by GitHub
parent e42c3ee55e
commit d54fa569ec
21 changed files with 74 additions and 929 deletions
+28 -65
View File
@@ -23,6 +23,7 @@ type store interface {
Search(ctx context.Context, query *team.SearchTeamsQuery) (team.SearchTeamQueryResult, error)
GetByID(ctx context.Context, query *team.GetTeamByIDQuery) (*team.TeamDTO, error)
GetByUser(ctx context.Context, query *team.GetTeamsByUserQuery) ([]*team.TeamDTO, error)
RemoveUsersMemberships(ctx context.Context, userID int64) error
AddMember(userID, orgID, teamID int64, isExternal bool, permission dashboards.PermissionType) error
UpdateMember(ctx context.Context, cmd *team.UpdateTeamMemberCommand) error
IsMember(orgId int64, teamId int64, userId int64) (bool, error)
@@ -76,19 +77,6 @@ func getTeamSelectSQLBase(db db.DB, filteredUsers []string) string {
` FROM team as team `
}
func getTeamSelectWithPermissionsSQLBase(db db.DB, filteredUsers []string) string {
return `SELECT
team.id AS id,
team.uid,
team.org_id,
team.name AS name,
team.email AS email,
team_member.permission, ` +
getTeamMemberCount(db, filteredUsers) +
` FROM team AS team
INNER JOIN team_member ON team.id = team_member.team_id AND team_member.user_id = ? `
}
func (ss *xormStore) Create(name, email string, orgID int64) (team.Team, error) {
t := team.Team{
UID: util.GenerateShortUID(),
@@ -207,13 +195,7 @@ func (ss *xormStore) Search(ctx context.Context, query *team.SearchTeamsQuery) (
params = append(params, user)
}
if query.UserIDFilter == team.FilterIgnoreUser {
sql.WriteString(getTeamSelectSQLBase(ss.db, filteredUsers))
} else {
sql.WriteString(getTeamSelectWithPermissionsSQLBase(ss.db, filteredUsers))
params = append(params, query.UserIDFilter)
}
sql.WriteString(getTeamSelectSQLBase(ss.db, filteredUsers))
sql.WriteString(` WHERE team.org_id = ?`)
params = append(params, query.OrgID)
@@ -227,18 +209,12 @@ func (ss *xormStore) Search(ctx context.Context, query *team.SearchTeamsQuery) (
params = append(params, query.Name)
}
var (
acFilter ac.SQLFilter
err error
)
if !ac.IsDisabled(ss.cfg) {
acFilter, err = ac.Filter(query.SignedInUser, "team.id", "teams:id:", ac.ActionTeamsRead)
if err != nil {
return err
}
sql.WriteString(` and` + acFilter.Where)
params = append(params, acFilter.Args...)
acFilter, err := ac.Filter(query.SignedInUser, "team.id", "teams:id:", ac.ActionTeamsRead)
if err != nil {
return err
}
sql.WriteString(` and` + acFilter.Where)
params = append(params, acFilter.Args...)
sql.WriteString(` order by team.name asc`)
@@ -263,22 +239,8 @@ func (ss *xormStore) Search(ctx context.Context, query *team.SearchTeamsQuery) (
countSess.Where("name=?", query.Name)
}
// If we're not retrieving all results, then only search for teams that this user has access to
if query.UserIDFilter != team.FilterIgnoreUser {
countSess.
Where(`
team.id IN (
SELECT
team_id
FROM team_member
WHERE team_member.user_id = ?
)`, query.UserIDFilter)
}
// Only count teams user can see
if !ac.IsDisabled(ss.cfg) {
countSess.Where(acFilter.Where, acFilter.Args...)
}
countSess.Where(acFilter.Where, acFilter.Args...)
count, err := countSess.Count(&t)
queryResult.TotalCount = count
@@ -303,11 +265,6 @@ func (ss *xormStore) GetByID(ctx context.Context, query *team.GetTeamByIDQuery)
params = append(params, user)
}
if query.UserIdFilter != team.FilterIgnoreUser {
sql.WriteString(` INNER JOIN team_member ON team.id = team_member.team_id AND team_member.user_id = ?`)
params = append(params, query.UserIdFilter)
}
sql.WriteString(` WHERE team.org_id = ? and team.id = ?`)
params = append(params, query.OrgID, query.ID)
@@ -343,16 +300,14 @@ func (ss *xormStore) GetByUser(ctx context.Context, query *team.GetTeamsByUserQu
sql.WriteString(` INNER JOIN team_member on team.id = team_member.team_id`)
sql.WriteString(` WHERE team.org_id = ? and team_member.user_id = ?`)
if !ac.IsDisabled(ss.cfg) {
acFilter, err := ac.Filter(query.SignedInUser, "team.id", "teams:id:", ac.ActionTeamsRead)
if err != nil {
return err
}
sql.WriteString(` and` + acFilter.Where)
params = append(params, acFilter.Args...)
acFilter, err := ac.Filter(query.SignedInUser, "team.id", "teams:id:", ac.ActionTeamsRead)
if err != nil {
return err
}
sql.WriteString(` and` + acFilter.Where)
params = append(params, acFilter.Args...)
err := sess.SQL(sql.String(), params...).Find(&queryResult)
err = sess.SQL(sql.String(), params...).Find(&queryResult)
return err
})
if err != nil {
@@ -500,6 +455,16 @@ func removeTeamMember(sess *db.Session, cmd *team.RemoveTeamMemberCommand) error
return err
}
// RemoveUsersMemberships removes all the team membership entries for the given user.
// Only used when removing a user from a Grafana instance.
func (ss *xormStore) RemoveUsersMemberships(ctx context.Context, userID int64) error {
return ss.db.WithTransactionalDbSession(ctx, func(sess *db.Session) error {
var rawSQL = "DELETE FROM team_member WHERE user_id = ?"
_, err := sess.Exec(rawSQL, userID)
return err
})
}
// GetUserTeamMemberships return a list of memberships to teams granted to a user
// If external is specified, only memberships provided by an external auth provider will be listed
// This function doesn't perform any accesscontrol filtering.
@@ -521,12 +486,10 @@ func (ss *xormStore) GetMembers(ctx context.Context, query *team.GetTeamMembersQ
// With accesscontrol we filter out users based on the SignedInUser's permissions
// Note we assume that checking SignedInUser is allowed to see team members for this team has already been performed
// If the signed in user is not set no member will be returned
if !ac.IsDisabled(ss.cfg) {
sqlID := fmt.Sprintf("%s.%s", ss.db.GetDialect().Quote("user"), ss.db.GetDialect().Quote("id"))
*acFilter, err = ac.Filter(query.SignedInUser, sqlID, "users:id:", ac.ActionOrgUsersRead)
if err != nil {
return nil, err
}
sqlID := fmt.Sprintf("%s.%s", ss.db.GetDialect().Quote("user"), ss.db.GetDialect().Quote("id"))
*acFilter, err = ac.Filter(query.SignedInUser, sqlID, "users:id:", ac.ActionOrgUsersRead)
if err != nil {
return nil, err
}
return ss.getTeamMembers(ctx, query, acFilter)
+8 -15
View File
@@ -369,13 +369,6 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) {
team1 := searchQueryResult.Teams[0]
require.EqualValues(t, team1.MemberCount, 2)
searchQueryFilteredByUser := &team.SearchTeamsQuery{OrgID: testOrgID, Page: 1, Limit: 10, UserIDFilter: userIds[0], SignedInUser: signedInUser, HiddenUsers: hiddenUsers}
searchQueryFilteredByUserResult, err := teamSvc.SearchTeams(context.Background(), searchQueryFilteredByUser)
require.NoError(t, err)
require.Equal(t, len(searchQueryFilteredByUserResult.Teams), 1)
team1 = searchQueryResult.Teams[0]
require.EqualValues(t, team1.MemberCount, 2)
getTeamQuery := &team.GetTeamByIDQuery{OrgID: testOrgID, ID: teamId, SignedInUser: signedInUser, HiddenUsers: hiddenUsers}
getTeamQueryResult, err := teamSvc.GetTeamByID(context.Background(), getTeamQuery)
require.NoError(t, err)
@@ -427,9 +420,9 @@ func TestIntegrationSQLStore_SearchTeams(t *testing.T) {
t.Skip("skipping integration test")
}
type searchTeamsTestCase struct {
desc string
query *team.SearchTeamsQuery
expectedNumUsers int
desc string
query *team.SearchTeamsQuery
expectedTeamCount int
}
tests := []searchTeamsTestCase{
@@ -442,7 +435,7 @@ func TestIntegrationSQLStore_SearchTeams(t *testing.T) {
Permissions: map[int64]map[string][]string{1: {ac.ActionTeamsRead: {ac.ScopeTeamsAll}}},
},
},
expectedNumUsers: 10,
expectedTeamCount: 10,
},
{
desc: "should return no teams",
@@ -453,7 +446,7 @@ func TestIntegrationSQLStore_SearchTeams(t *testing.T) {
Permissions: map[int64]map[string][]string{1: {ac.ActionTeamsRead: {""}}},
},
},
expectedNumUsers: 0,
expectedTeamCount: 0,
},
{
desc: "should return some teams",
@@ -468,7 +461,7 @@ func TestIntegrationSQLStore_SearchTeams(t *testing.T) {
}}},
},
},
expectedNumUsers: 3,
expectedTeamCount: 3,
},
}
@@ -485,8 +478,8 @@ func TestIntegrationSQLStore_SearchTeams(t *testing.T) {
t.Run(tt.desc, func(t *testing.T) {
queryResult, err := teamSvc.SearchTeams(context.Background(), tt.query)
require.NoError(t, err)
assert.Len(t, queryResult.Teams, tt.expectedNumUsers)
assert.Equal(t, queryResult.TotalCount, int64(tt.expectedNumUsers))
assert.Len(t, queryResult.Teams, tt.expectedTeamCount)
assert.Equal(t, queryResult.TotalCount, int64(tt.expectedTeamCount))
if !hasWildcardScope(tt.query.SignedInUser, ac.ActionTeamsRead) {
for _, team := range queryResult.Teams {
+4
View File
@@ -57,6 +57,10 @@ func (s *Service) RemoveTeamMember(ctx context.Context, cmd *team.RemoveTeamMemb
return s.store.RemoveMember(ctx, cmd)
}
func (s *Service) RemoveUsersMemberships(ctx context.Context, userID int64) error {
return s.store.RemoveUsersMemberships(ctx, userID)
}
func (s *Service) GetUserTeamMemberships(ctx context.Context, orgID, userID int64, external bool) ([]*team.TeamMemberDTO, error) {
return s.store.GetMemberships(ctx, orgID, userID, external)
}