IAM: Refactor team bindings to store one pair of team and member (#111871)
* store one pair of team member in team bindings object * generate queries for sql unit tests * remove TeamBinding struct
This commit is contained in:
@@ -421,7 +421,7 @@ type ListTeamBindingsQuery struct {
|
||||
}
|
||||
|
||||
type ListTeamBindingsResult struct {
|
||||
Bindings []TeamBinding
|
||||
Bindings []TeamMember
|
||||
Continue int64
|
||||
RV int64
|
||||
}
|
||||
@@ -445,11 +445,6 @@ func (m TeamMember) MemberID() string {
|
||||
return claims.NewTypeID(claims.TypeUser, m.UserUID)
|
||||
}
|
||||
|
||||
type TeamBinding struct {
|
||||
TeamUID string
|
||||
Members []TeamMember
|
||||
}
|
||||
|
||||
var sqlQueryTeamBindingsTemplate = mustTemplate("team_bindings_query.sql")
|
||||
|
||||
type listTeamBindingsQuery struct {
|
||||
@@ -505,11 +500,11 @@ func (s *legacySQLStore) ListTeamBindings(ctx context.Context, ns claims.Namespa
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := &ListTeamBindingsResult{}
|
||||
grouped := map[string][]TeamMember{}
|
||||
res := &ListTeamBindingsResult{
|
||||
Bindings: make([]TeamMember, 0, int(query.Pagination.Limit)),
|
||||
}
|
||||
|
||||
var lastID int64
|
||||
var atTeamLimit bool
|
||||
|
||||
for rows.Next() {
|
||||
m := TeamMember{}
|
||||
@@ -518,16 +513,11 @@ func (s *legacySQLStore) ListTeamBindings(ctx context.Context, ns claims.Namespa
|
||||
return res, err
|
||||
}
|
||||
|
||||
lastID = m.TeamID
|
||||
members, ok := grouped[m.TeamUID]
|
||||
if ok {
|
||||
grouped[m.TeamUID] = append(members, m)
|
||||
} else if !atTeamLimit {
|
||||
grouped[m.TeamUID] = []TeamMember{m}
|
||||
}
|
||||
res.Bindings = append(res.Bindings, m)
|
||||
|
||||
if len(grouped) >= int(query.Pagination.Limit)-1 {
|
||||
atTeamLimit = true
|
||||
lastID = m.ID
|
||||
|
||||
if len(res.Bindings) >= int(query.Pagination.Limit)-1 {
|
||||
res.Continue = lastID
|
||||
}
|
||||
}
|
||||
@@ -536,14 +526,6 @@ func (s *legacySQLStore) ListTeamBindings(ctx context.Context, ns claims.Namespa
|
||||
res.RV, err = sql.GetResourceVersion(ctx, "team_member", "updated")
|
||||
}
|
||||
|
||||
res.Bindings = make([]TeamBinding, 0, len(grouped))
|
||||
for uid, members := range grouped {
|
||||
res.Bindings = append(res.Bindings, TeamBinding{
|
||||
TeamUID: uid,
|
||||
Members: members,
|
||||
})
|
||||
}
|
||||
|
||||
return res, err
|
||||
}
|
||||
|
||||
|
||||
@@ -3,18 +3,13 @@ FROM {{ .Ident .TeamMemberTable }} tm
|
||||
INNER JOIN {{ .Ident .TeamTable }} t ON tm.team_id = t.id
|
||||
INNER JOIN {{ .Ident .UserTable }} u ON tm.user_id = u.id
|
||||
WHERE
|
||||
{{ if .Query.UID }}
|
||||
t.uid = {{ .Arg .Query.UID }}
|
||||
{{ else }}
|
||||
t.uid IN(
|
||||
SELECT uid
|
||||
FROM {{ .Ident .TeamTable }} t
|
||||
{{ if .Query.Pagination.Continue }}
|
||||
WHERE t.id >= {{ .Arg .Query.Pagination.Continue }}
|
||||
{{ end }}
|
||||
ORDER BY t.id ASC LIMIT {{ .Arg .Query.Pagination.Limit }}
|
||||
)
|
||||
{{ end }}
|
||||
AND tm.org_id = {{ .Arg .Query.OrgID}}
|
||||
tm.org_id = {{ .Arg .Query.OrgID}}
|
||||
{{ if .Query.UID }}
|
||||
AND t.uid = {{ .Arg .Query.UID }}
|
||||
{{ end }}
|
||||
{{- if .Query.Pagination.Continue }}
|
||||
AND tm.id >= {{ .Arg .Query.Pagination.Continue }}
|
||||
{{- end }}
|
||||
AND NOT tm.external
|
||||
ORDER BY t.id ASC;
|
||||
ORDER BY t.id ASC
|
||||
LIMIT {{ .Arg .Query.Pagination.Limit }};
|
||||
|
||||
+4
-3
@@ -3,7 +3,8 @@ FROM `grafana`.`team_member` tm
|
||||
INNER JOIN `grafana`.`team` t ON tm.team_id = t.id
|
||||
INNER JOIN `grafana`.`user` u ON tm.user_id = u.id
|
||||
WHERE
|
||||
t.uid = 'team-1'
|
||||
AND tm.org_id = 1
|
||||
tm.org_id = 1
|
||||
AND t.uid = 'team-1'
|
||||
AND NOT tm.external
|
||||
ORDER BY t.id ASC;
|
||||
ORDER BY t.id ASC
|
||||
LIMIT 1;
|
||||
|
||||
+3
-7
@@ -3,11 +3,7 @@ FROM `grafana`.`team_member` tm
|
||||
INNER JOIN `grafana`.`team` t ON tm.team_id = t.id
|
||||
INNER JOIN `grafana`.`user` u ON tm.user_id = u.id
|
||||
WHERE
|
||||
t.uid IN(
|
||||
SELECT uid
|
||||
FROM `grafana`.`team` t
|
||||
ORDER BY t.id ASC LIMIT 5
|
||||
)
|
||||
AND tm.org_id = 1
|
||||
tm.org_id = 1
|
||||
AND NOT tm.external
|
||||
ORDER BY t.id ASC;
|
||||
ORDER BY t.id ASC
|
||||
LIMIT 5;
|
||||
|
||||
+4
-8
@@ -3,12 +3,8 @@ FROM `grafana`.`team_member` tm
|
||||
INNER JOIN `grafana`.`team` t ON tm.team_id = t.id
|
||||
INNER JOIN `grafana`.`user` u ON tm.user_id = u.id
|
||||
WHERE
|
||||
t.uid IN(
|
||||
SELECT uid
|
||||
FROM `grafana`.`team` t
|
||||
WHERE t.id >= 2
|
||||
ORDER BY t.id ASC LIMIT 1
|
||||
)
|
||||
AND tm.org_id = 1
|
||||
tm.org_id = 1
|
||||
AND tm.id >= 2
|
||||
AND NOT tm.external
|
||||
ORDER BY t.id ASC;
|
||||
ORDER BY t.id ASC
|
||||
LIMIT 1;
|
||||
|
||||
+4
-3
@@ -3,7 +3,8 @@ FROM "grafana"."team_member" tm
|
||||
INNER JOIN "grafana"."team" t ON tm.team_id = t.id
|
||||
INNER JOIN "grafana"."user" u ON tm.user_id = u.id
|
||||
WHERE
|
||||
t.uid = 'team-1'
|
||||
AND tm.org_id = 1
|
||||
tm.org_id = 1
|
||||
AND t.uid = 'team-1'
|
||||
AND NOT tm.external
|
||||
ORDER BY t.id ASC;
|
||||
ORDER BY t.id ASC
|
||||
LIMIT 1;
|
||||
|
||||
Vendored
+3
-7
@@ -3,11 +3,7 @@ FROM "grafana"."team_member" tm
|
||||
INNER JOIN "grafana"."team" t ON tm.team_id = t.id
|
||||
INNER JOIN "grafana"."user" u ON tm.user_id = u.id
|
||||
WHERE
|
||||
t.uid IN(
|
||||
SELECT uid
|
||||
FROM "grafana"."team" t
|
||||
ORDER BY t.id ASC LIMIT 5
|
||||
)
|
||||
AND tm.org_id = 1
|
||||
tm.org_id = 1
|
||||
AND NOT tm.external
|
||||
ORDER BY t.id ASC;
|
||||
ORDER BY t.id ASC
|
||||
LIMIT 5;
|
||||
|
||||
Vendored
+4
-8
@@ -3,12 +3,8 @@ FROM "grafana"."team_member" tm
|
||||
INNER JOIN "grafana"."team" t ON tm.team_id = t.id
|
||||
INNER JOIN "grafana"."user" u ON tm.user_id = u.id
|
||||
WHERE
|
||||
t.uid IN(
|
||||
SELECT uid
|
||||
FROM "grafana"."team" t
|
||||
WHERE t.id >= 2
|
||||
ORDER BY t.id ASC LIMIT 1
|
||||
)
|
||||
AND tm.org_id = 1
|
||||
tm.org_id = 1
|
||||
AND tm.id >= 2
|
||||
AND NOT tm.external
|
||||
ORDER BY t.id ASC;
|
||||
ORDER BY t.id ASC
|
||||
LIMIT 1;
|
||||
|
||||
+4
-3
@@ -3,7 +3,8 @@ FROM "grafana"."team_member" tm
|
||||
INNER JOIN "grafana"."team" t ON tm.team_id = t.id
|
||||
INNER JOIN "grafana"."user" u ON tm.user_id = u.id
|
||||
WHERE
|
||||
t.uid = 'team-1'
|
||||
AND tm.org_id = 1
|
||||
tm.org_id = 1
|
||||
AND t.uid = 'team-1'
|
||||
AND NOT tm.external
|
||||
ORDER BY t.id ASC;
|
||||
ORDER BY t.id ASC
|
||||
LIMIT 1;
|
||||
|
||||
+3
-7
@@ -3,11 +3,7 @@ FROM "grafana"."team_member" tm
|
||||
INNER JOIN "grafana"."team" t ON tm.team_id = t.id
|
||||
INNER JOIN "grafana"."user" u ON tm.user_id = u.id
|
||||
WHERE
|
||||
t.uid IN(
|
||||
SELECT uid
|
||||
FROM "grafana"."team" t
|
||||
ORDER BY t.id ASC LIMIT 5
|
||||
)
|
||||
AND tm.org_id = 1
|
||||
tm.org_id = 1
|
||||
AND NOT tm.external
|
||||
ORDER BY t.id ASC;
|
||||
ORDER BY t.id ASC
|
||||
LIMIT 5;
|
||||
|
||||
+4
-8
@@ -3,12 +3,8 @@ FROM "grafana"."team_member" tm
|
||||
INNER JOIN "grafana"."team" t ON tm.team_id = t.id
|
||||
INNER JOIN "grafana"."user" u ON tm.user_id = u.id
|
||||
WHERE
|
||||
t.uid IN(
|
||||
SELECT uid
|
||||
FROM "grafana"."team" t
|
||||
WHERE t.id >= 2
|
||||
ORDER BY t.id ASC LIMIT 1
|
||||
)
|
||||
AND tm.org_id = 1
|
||||
tm.org_id = 1
|
||||
AND tm.id >= 2
|
||||
AND NOT tm.external
|
||||
ORDER BY t.id ASC;
|
||||
ORDER BY t.id ASC
|
||||
LIMIT 1;
|
||||
|
||||
@@ -117,46 +117,36 @@ func (l *LegacyBindingStore) List(ctx context.Context, options *internalversion.
|
||||
return &list, nil
|
||||
}
|
||||
|
||||
func mapToBindingObject(ns claims.NamespaceInfo, b legacy.TeamBinding) iamv0alpha1.TeamBinding {
|
||||
func mapToBindingObject(ns claims.NamespaceInfo, tm legacy.TeamMember) iamv0alpha1.TeamBinding {
|
||||
rv := time.Time{}
|
||||
ct := time.Now()
|
||||
|
||||
for _, m := range b.Members {
|
||||
if m.Updated.After(rv) {
|
||||
rv = m.Updated
|
||||
}
|
||||
if m.Created.Before(ct) {
|
||||
ct = m.Created
|
||||
}
|
||||
if tm.Updated.After(rv) {
|
||||
rv = tm.Updated
|
||||
}
|
||||
if tm.Created.Before(ct) {
|
||||
ct = tm.Created
|
||||
}
|
||||
|
||||
return iamv0alpha1.TeamBinding{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: b.TeamUID,
|
||||
Name: tm.TeamUID,
|
||||
Namespace: ns.Value,
|
||||
ResourceVersion: strconv.FormatInt(rv.UnixMilli(), 10),
|
||||
CreationTimestamp: metav1.NewTime(ct),
|
||||
},
|
||||
Spec: iamv0alpha1.TeamBindingSpec{
|
||||
TeamRef: iamv0alpha1.TeamBindingTeamRef{
|
||||
Name: b.TeamUID,
|
||||
Name: tm.TeamUID,
|
||||
},
|
||||
Subjects: mapToSubjects(b.Members),
|
||||
Subject: iamv0alpha1.TeamBindingspecSubject{
|
||||
Name: tm.UserUID,
|
||||
},
|
||||
Permission: common.MapTeamPermission(tm.Permission),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func mapToSubjects(members []legacy.TeamMember) []iamv0alpha1.TeamBindingspecSubject {
|
||||
out := make([]iamv0alpha1.TeamBindingspecSubject, 0, len(members))
|
||||
for _, m := range members {
|
||||
out = append(out, iamv0alpha1.TeamBindingspecSubject{
|
||||
Name: m.UserUID,
|
||||
Permission: common.MapTeamPermission(m.Permission),
|
||||
})
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func mapPermisson(p team.PermissionType) iamv0.TeamPermission {
|
||||
if p == team.PermissionTypeAdmin {
|
||||
return iamv0.TeamPermissionAdmin
|
||||
|
||||
@@ -3737,20 +3737,23 @@
|
||||
"com.github.grafana.grafana.apps.iam.pkg.apis.iam.v0alpha1.TeamBindingSpec": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"subjects",
|
||||
"teamRef"
|
||||
"subject",
|
||||
"teamRef",
|
||||
"permission"
|
||||
],
|
||||
"properties": {
|
||||
"subjects": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"default": {},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.iam.pkg.apis.iam.v0alpha1.TeamBindingspecSubject"
|
||||
}
|
||||
]
|
||||
}
|
||||
"permission": {
|
||||
"description": "permission of the identity in the team",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"subject": {
|
||||
"default": {},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.iam.pkg.apis.iam.v0alpha1.TeamBindingspecSubject"
|
||||
}
|
||||
]
|
||||
},
|
||||
"teamRef": {
|
||||
"default": {},
|
||||
@@ -3778,19 +3781,13 @@
|
||||
"com.github.grafana.grafana.apps.iam.pkg.apis.iam.v0alpha1.TeamBindingspecSubject": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"permission"
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "uid of the identity",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"permission": {
|
||||
"description": "permission of the identity in the team",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -5594,15 +5591,18 @@
|
||||
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingSpec": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"subjects",
|
||||
"teamRef"
|
||||
"subject",
|
||||
"teamRef",
|
||||
"permission"
|
||||
],
|
||||
"properties": {
|
||||
"subjects": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"default": {}
|
||||
}
|
||||
"permission": {
|
||||
"description": "permission of the identity in the team",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"subject": {
|
||||
"default": {}
|
||||
},
|
||||
"teamRef": {
|
||||
"default": {}
|
||||
@@ -5644,19 +5644,13 @@
|
||||
"github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1.TeamBindingspecSubject": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"permission"
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "uid of the identity",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"permission": {
|
||||
"description": "permission of the identity in the team",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user