mirror of https://github.com/grafana/grafana.git
Compare commits
2 Commits
e9c7a1244b
...
e189d8547f
| Author | SHA1 | Date |
|---|---|---|
|
|
e189d8547f | |
|
|
9e07387de2 |
|
|
@ -24,6 +24,7 @@ func newIAMAuthorizer(accessClient authlib.AccessClient, legacyAccessClient auth
|
||||||
// Identity specific resources
|
// Identity specific resources
|
||||||
legacyAuthorizer := gfauthorizer.NewResourceAuthorizer(legacyAccessClient)
|
legacyAuthorizer := gfauthorizer.NewResourceAuthorizer(legacyAccessClient)
|
||||||
resourceAuthorizer[iamv0.TeamResourceInfo.GetName()] = legacyAuthorizer
|
resourceAuthorizer[iamv0.TeamResourceInfo.GetName()] = legacyAuthorizer
|
||||||
|
resourceAuthorizer[iamv0.TeamBindingResourceInfo.GetName()] = legacyAuthorizer
|
||||||
resourceAuthorizer["display"] = legacyAuthorizer
|
resourceAuthorizer["display"] = legacyAuthorizer
|
||||||
|
|
||||||
// Access specific resources
|
// Access specific resources
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
INSERT INTO {{ .Ident .TeamMemberTable }}
|
INSERT INTO {{ .Ident .TeamMemberTable }}
|
||||||
(team_id, user_id, created, updated, external, permission)
|
(team_id, user_id, org_id, created, updated, external, permission)
|
||||||
VALUES
|
VALUES
|
||||||
({{ .Arg .Command.TeamID }}, {{ .Arg .Command.UserID }}, {{ .Arg .Command.Created }},
|
({{ .Arg .Command.TeamID }}, {{ .Arg .Command.UserID }}, {{ .Arg .Command.OrgID }}, {{ .Arg .Command.Created }},
|
||||||
{{ .Arg .Command.Updated }}, {{ .Arg .Command.External }}, {{ .Arg .Command.Permission }})
|
{{ .Arg .Command.Updated }}, {{ .Arg .Command.External }}, {{ .Arg .Command.Permission }})
|
||||||
|
|
|
||||||
|
|
@ -226,7 +226,8 @@ func TestIdentityQueries(t *testing.T) {
|
||||||
Name: "team_1_bindings",
|
Name: "team_1_bindings",
|
||||||
Data: listTeamBindings(&ListTeamBindingsQuery{
|
Data: listTeamBindings(&ListTeamBindingsQuery{
|
||||||
OrgID: 1,
|
OrgID: 1,
|
||||||
UID: "team-1",
|
TeamID: 1,
|
||||||
|
UserID: 1,
|
||||||
Pagination: common.Pagination{Limit: 1},
|
Pagination: common.Pagination{Limit: 1},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -414,8 +414,8 @@ func (s *legacySQLStore) DeleteTeam(ctx context.Context, ns claims.NamespaceInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
type ListTeamBindingsQuery struct {
|
type ListTeamBindingsQuery struct {
|
||||||
// UID is team uid to list bindings for. If not set store should list bindings for all teams
|
TeamID int64
|
||||||
UID string
|
UserID int64
|
||||||
OrgID int64
|
OrgID int64
|
||||||
Pagination common.Pagination
|
Pagination common.Pagination
|
||||||
}
|
}
|
||||||
|
|
@ -432,6 +432,7 @@ type TeamMember struct {
|
||||||
TeamUID string
|
TeamUID string
|
||||||
UserID int64
|
UserID int64
|
||||||
UserUID string
|
UserUID string
|
||||||
|
OrgID int64
|
||||||
Name string
|
Name string
|
||||||
Email string
|
Email string
|
||||||
Username string
|
Username string
|
||||||
|
|
@ -486,7 +487,7 @@ func (s *legacySQLStore) ListTeamBindings(ctx context.Context, ns claims.Namespa
|
||||||
req := newListTeamBindings(sql, &query)
|
req := newListTeamBindings(sql, &query)
|
||||||
q, err := sqltemplate.Execute(sqlQueryTeamBindingsTemplate, req)
|
q, err := sqltemplate.Execute(sqlQueryTeamBindingsTemplate, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("execute template %q: %w", sqlQueryTeamsTemplate.Name(), err)
|
return nil, fmt.Errorf("execute template %q: %w", sqlQueryTeamBindingsTemplate.Name(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
rows, err := sql.DB.GetSqlxSession().Query(ctx, q, req.GetArgs()...)
|
rows, err := sql.DB.GetSqlxSession().Query(ctx, q, req.GetArgs()...)
|
||||||
|
|
@ -508,7 +509,7 @@ func (s *legacySQLStore) ListTeamBindings(ctx context.Context, ns claims.Namespa
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
m := TeamMember{}
|
m := TeamMember{}
|
||||||
err = rows.Scan(&m.ID, &m.TeamUID, &m.TeamID, &m.UserUID, &m.Created, &m.Updated, &m.Permission)
|
err = rows.Scan(&m.ID, &m.TeamUID, &m.TeamID, &m.UserUID, &m.UserID, &m.Created, &m.Updated, &m.Permission)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
@ -522,16 +523,15 @@ func (s *legacySQLStore) ListTeamBindings(ctx context.Context, ns claims.Namespa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if query.UID == "" {
|
|
||||||
res.RV, err = sql.GetResourceVersion(ctx, "team_member", "updated")
|
|
||||||
}
|
|
||||||
|
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateTeamMemberCommand struct {
|
type CreateTeamMemberCommand struct {
|
||||||
TeamID int64
|
TeamID int64
|
||||||
|
TeamUID string
|
||||||
UserID int64
|
UserID int64
|
||||||
|
UserUID string
|
||||||
|
OrgID int64
|
||||||
Created DBTime
|
Created DBTime
|
||||||
Updated DBTime
|
Updated DBTime
|
||||||
External bool
|
External bool
|
||||||
|
|
@ -566,6 +566,11 @@ func (s *legacySQLStore) CreateTeamMember(ctx context.Context, ns claims.Namespa
|
||||||
now := time.Now().UTC().Truncate(time.Second)
|
now := time.Now().UTC().Truncate(time.Second)
|
||||||
cmd.Created = NewDBTime(now)
|
cmd.Created = NewDBTime(now)
|
||||||
cmd.Updated = NewDBTime(now)
|
cmd.Updated = NewDBTime(now)
|
||||||
|
cmd.OrgID = ns.OrgID
|
||||||
|
|
||||||
|
if cmd.OrgID == 0 {
|
||||||
|
return nil, fmt.Errorf("expected non zero org id")
|
||||||
|
}
|
||||||
|
|
||||||
sql, err := s.sql(ctx)
|
sql, err := s.sql(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -589,7 +594,10 @@ func (s *legacySQLStore) CreateTeamMember(ctx context.Context, ns claims.Namespa
|
||||||
createdTeamMember = TeamMember{
|
createdTeamMember = TeamMember{
|
||||||
ID: teamMemberID,
|
ID: teamMemberID,
|
||||||
TeamID: cmd.TeamID,
|
TeamID: cmd.TeamID,
|
||||||
|
TeamUID: cmd.TeamUID,
|
||||||
UserID: cmd.UserID,
|
UserID: cmd.UserID,
|
||||||
|
UserUID: cmd.UserUID,
|
||||||
|
OrgID: cmd.OrgID,
|
||||||
Created: cmd.Created.Time,
|
Created: cmd.Created.Time,
|
||||||
Updated: cmd.Updated.Time,
|
Updated: cmd.Updated.Time,
|
||||||
External: cmd.External,
|
External: cmd.External,
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission
|
SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, u.id as user_id, tm.created, tm.updated, tm.permission
|
||||||
FROM {{ .Ident .TeamMemberTable }} tm
|
FROM {{ .Ident .TeamMemberTable }} tm
|
||||||
INNER JOIN {{ .Ident .TeamTable }} t ON tm.team_id = t.id
|
INNER JOIN {{ .Ident .TeamTable }} t ON tm.team_id = t.id
|
||||||
INNER JOIN {{ .Ident .UserTable }} u ON tm.user_id = u.id
|
INNER JOIN {{ .Ident .UserTable }} u ON tm.user_id = u.id
|
||||||
WHERE
|
WHERE
|
||||||
tm.org_id = {{ .Arg .Query.OrgID}}
|
tm.org_id = {{ .Arg .Query.OrgID}}
|
||||||
{{ if .Query.UID }}
|
{{ if .Query.TeamID }}
|
||||||
AND t.uid = {{ .Arg .Query.UID }}
|
AND tm.team_id = {{ .Arg .Query.TeamID }}
|
||||||
|
{{ end }}
|
||||||
|
{{ if .Query.UserID }}
|
||||||
|
AND tm.user_id = {{ .Arg .Query.UserID }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{- if .Query.Pagination.Continue }}
|
{{- if .Query.Pagination.Continue }}
|
||||||
AND tm.id >= {{ .Arg .Query.Pagination.Continue }}
|
AND tm.id >= {{ .Arg .Query.Pagination.Continue }}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
INSERT INTO `grafana`.`team_member`
|
INSERT INTO `grafana`.`team_member`
|
||||||
(team_id, user_id, created, updated, external, permission)
|
(team_id, user_id, org_id, created, updated, external, permission)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 1, '2023-01-01 12:00:00',
|
(1, 1, 0, '2023-01-01 12:00:00',
|
||||||
'2023-01-01 12:00:00', FALSE, 'Member')
|
'2023-01-01 12:00:00', FALSE, 'Member')
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
INSERT INTO `grafana`.`team_member`
|
INSERT INTO `grafana`.`team_member`
|
||||||
(team_id, user_id, created, updated, external, permission)
|
(team_id, user_id, org_id, created, updated, external, permission)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 1, '2023-01-01 12:00:00',
|
(1, 1, 0, '2023-01-01 12:00:00',
|
||||||
'2023-01-01 12:00:00', FALSE, 'Admin')
|
'2023-01-01 12:00:00', FALSE, 'Admin')
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission
|
SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, u.id as user_id, tm.created, tm.updated, tm.permission
|
||||||
FROM `grafana`.`team_member` tm
|
FROM `grafana`.`team_member` tm
|
||||||
INNER JOIN `grafana`.`team` t ON tm.team_id = t.id
|
INNER JOIN `grafana`.`team` t ON tm.team_id = t.id
|
||||||
INNER JOIN `grafana`.`user` u ON tm.user_id = u.id
|
INNER JOIN `grafana`.`user` u ON tm.user_id = u.id
|
||||||
WHERE
|
WHERE
|
||||||
tm.org_id = 1
|
tm.org_id = 1
|
||||||
AND t.uid = 'team-1'
|
AND tm.team_id = 1
|
||||||
|
AND tm.user_id = 1
|
||||||
AND NOT tm.external
|
AND NOT tm.external
|
||||||
ORDER BY t.id ASC
|
ORDER BY t.id ASC
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission
|
SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, u.id as user_id, tm.created, tm.updated, tm.permission
|
||||||
FROM `grafana`.`team_member` tm
|
FROM `grafana`.`team_member` tm
|
||||||
INNER JOIN `grafana`.`team` t ON tm.team_id = t.id
|
INNER JOIN `grafana`.`team` t ON tm.team_id = t.id
|
||||||
INNER JOIN `grafana`.`user` u ON tm.user_id = u.id
|
INNER JOIN `grafana`.`user` u ON tm.user_id = u.id
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission
|
SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, u.id as user_id, tm.created, tm.updated, tm.permission
|
||||||
FROM `grafana`.`team_member` tm
|
FROM `grafana`.`team_member` tm
|
||||||
INNER JOIN `grafana`.`team` t ON tm.team_id = t.id
|
INNER JOIN `grafana`.`team` t ON tm.team_id = t.id
|
||||||
INNER JOIN `grafana`.`user` u ON tm.user_id = u.id
|
INNER JOIN `grafana`.`user` u ON tm.user_id = u.id
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
INSERT INTO "grafana"."team_member"
|
INSERT INTO "grafana"."team_member"
|
||||||
(team_id, user_id, created, updated, external, permission)
|
(team_id, user_id, org_id, created, updated, external, permission)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 1, '2023-01-01 12:00:00',
|
(1, 1, 0, '2023-01-01 12:00:00',
|
||||||
'2023-01-01 12:00:00', FALSE, 'Member')
|
'2023-01-01 12:00:00', FALSE, 'Member')
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
INSERT INTO "grafana"."team_member"
|
INSERT INTO "grafana"."team_member"
|
||||||
(team_id, user_id, created, updated, external, permission)
|
(team_id, user_id, org_id, created, updated, external, permission)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 1, '2023-01-01 12:00:00',
|
(1, 1, 0, '2023-01-01 12:00:00',
|
||||||
'2023-01-01 12:00:00', FALSE, 'Admin')
|
'2023-01-01 12:00:00', FALSE, 'Admin')
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission
|
SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, u.id as user_id, tm.created, tm.updated, tm.permission
|
||||||
FROM "grafana"."team_member" tm
|
FROM "grafana"."team_member" tm
|
||||||
INNER JOIN "grafana"."team" t ON tm.team_id = t.id
|
INNER JOIN "grafana"."team" t ON tm.team_id = t.id
|
||||||
INNER JOIN "grafana"."user" u ON tm.user_id = u.id
|
INNER JOIN "grafana"."user" u ON tm.user_id = u.id
|
||||||
WHERE
|
WHERE
|
||||||
tm.org_id = 1
|
tm.org_id = 1
|
||||||
AND t.uid = 'team-1'
|
AND tm.team_id = 1
|
||||||
|
AND tm.user_id = 1
|
||||||
AND NOT tm.external
|
AND NOT tm.external
|
||||||
ORDER BY t.id ASC
|
ORDER BY t.id ASC
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission
|
SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, u.id as user_id, tm.created, tm.updated, tm.permission
|
||||||
FROM "grafana"."team_member" tm
|
FROM "grafana"."team_member" tm
|
||||||
INNER JOIN "grafana"."team" t ON tm.team_id = t.id
|
INNER JOIN "grafana"."team" t ON tm.team_id = t.id
|
||||||
INNER JOIN "grafana"."user" u ON tm.user_id = u.id
|
INNER JOIN "grafana"."user" u ON tm.user_id = u.id
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission
|
SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, u.id as user_id, tm.created, tm.updated, tm.permission
|
||||||
FROM "grafana"."team_member" tm
|
FROM "grafana"."team_member" tm
|
||||||
INNER JOIN "grafana"."team" t ON tm.team_id = t.id
|
INNER JOIN "grafana"."team" t ON tm.team_id = t.id
|
||||||
INNER JOIN "grafana"."user" u ON tm.user_id = u.id
|
INNER JOIN "grafana"."user" u ON tm.user_id = u.id
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
INSERT INTO "grafana"."team_member"
|
INSERT INTO "grafana"."team_member"
|
||||||
(team_id, user_id, created, updated, external, permission)
|
(team_id, user_id, org_id, created, updated, external, permission)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 1, '2023-01-01 12:00:00',
|
(1, 1, 0, '2023-01-01 12:00:00',
|
||||||
'2023-01-01 12:00:00', FALSE, 'Member')
|
'2023-01-01 12:00:00', FALSE, 'Member')
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
INSERT INTO "grafana"."team_member"
|
INSERT INTO "grafana"."team_member"
|
||||||
(team_id, user_id, created, updated, external, permission)
|
(team_id, user_id, org_id, created, updated, external, permission)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 1, '2023-01-01 12:00:00',
|
(1, 1, 0, '2023-01-01 12:00:00',
|
||||||
'2023-01-01 12:00:00', FALSE, 'Admin')
|
'2023-01-01 12:00:00', FALSE, 'Admin')
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission
|
SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, u.id as user_id, tm.created, tm.updated, tm.permission
|
||||||
FROM "grafana"."team_member" tm
|
FROM "grafana"."team_member" tm
|
||||||
INNER JOIN "grafana"."team" t ON tm.team_id = t.id
|
INNER JOIN "grafana"."team" t ON tm.team_id = t.id
|
||||||
INNER JOIN "grafana"."user" u ON tm.user_id = u.id
|
INNER JOIN "grafana"."user" u ON tm.user_id = u.id
|
||||||
WHERE
|
WHERE
|
||||||
tm.org_id = 1
|
tm.org_id = 1
|
||||||
AND t.uid = 'team-1'
|
AND tm.team_id = 1
|
||||||
|
AND tm.user_id = 1
|
||||||
AND NOT tm.external
|
AND NOT tm.external
|
||||||
ORDER BY t.id ASC
|
ORDER BY t.id ASC
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission
|
SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, u.id as user_id, tm.created, tm.updated, tm.permission
|
||||||
FROM "grafana"."team_member" tm
|
FROM "grafana"."team_member" tm
|
||||||
INNER JOIN "grafana"."team" t ON tm.team_id = t.id
|
INNER JOIN "grafana"."team" t ON tm.team_id = t.id
|
||||||
INNER JOIN "grafana"."user" u ON tm.user_id = u.id
|
INNER JOIN "grafana"."user" u ON tm.user_id = u.id
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, tm.created, tm.updated, tm.permission
|
SELECT tm.id as id, t.uid as team_uid, t.id as team_id, u.uid as user_uid, u.id as user_id, tm.created, tm.updated, tm.permission
|
||||||
FROM "grafana"."team_member" tm
|
FROM "grafana"."team_member" tm
|
||||||
INNER JOIN "grafana"."team" t ON tm.team_id = t.id
|
INNER JOIN "grafana"."team" t ON tm.team_id = t.id
|
||||||
INNER JOIN "grafana"."user" u ON tm.user_id = u.id
|
INNER JOIN "grafana"."user" u ON tm.user_id = u.id
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
|
@ -99,6 +100,12 @@ func (l *LegacyBindingStore) Create(ctx context.Context, obj runtime.Object, cre
|
||||||
return nil, fmt.Errorf("expected TeamBinding object, got %T", obj)
|
return nil, fmt.Errorf("expected TeamBinding object, got %T", obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if createValidation != nil {
|
||||||
|
if err := createValidation(ctx, teamMemberObj); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch the user by ID
|
// Fetch the user by ID
|
||||||
userObj, err := l.store.GetUserInternalID(ctx, ns, legacy.GetUserInternalIDQuery{
|
userObj, err := l.store.GetUserInternalID(ctx, ns, legacy.GetUserInternalIDQuery{
|
||||||
UID: teamMemberObj.Spec.Subject.Name,
|
UID: teamMemberObj.Spec.Subject.Name,
|
||||||
|
|
@ -115,12 +122,6 @@ func (l *LegacyBindingStore) Create(ctx context.Context, obj runtime.Object, cre
|
||||||
return nil, fmt.Errorf("failed to fetch team by id %s: %w", teamMemberObj.Spec.TeamRef.Name, err)
|
return nil, fmt.Errorf("failed to fetch team by id %s: %w", teamMemberObj.Spec.TeamRef.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if createValidation != nil {
|
|
||||||
if err := createValidation(ctx, obj); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var permission team.PermissionType
|
var permission team.PermissionType
|
||||||
switch teamMemberObj.Spec.Permission {
|
switch teamMemberObj.Spec.Permission {
|
||||||
case iamv0alpha1.TeamBindingTeamPermissionAdmin:
|
case iamv0alpha1.TeamBindingTeamPermissionAdmin:
|
||||||
|
|
@ -131,7 +132,9 @@ func (l *LegacyBindingStore) Create(ctx context.Context, obj runtime.Object, cre
|
||||||
|
|
||||||
createCmd := legacy.CreateTeamMemberCommand{
|
createCmd := legacy.CreateTeamMemberCommand{
|
||||||
TeamID: teamObj.ID,
|
TeamID: teamObj.ID,
|
||||||
|
TeamUID: teamMemberObj.Spec.TeamRef.Name,
|
||||||
UserID: userObj.ID,
|
UserID: userObj.ID,
|
||||||
|
UserUID: teamMemberObj.Spec.Subject.Name,
|
||||||
Permission: permission,
|
Permission: permission,
|
||||||
External: false,
|
External: false,
|
||||||
}
|
}
|
||||||
|
|
@ -152,8 +155,11 @@ func (l *LegacyBindingStore) Get(ctx context.Context, name string, options *meta
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
teamID, userID := mapFromBindingName(name)
|
||||||
|
|
||||||
res, err := l.store.ListTeamBindings(ctx, ns, legacy.ListTeamBindingsQuery{
|
res, err := l.store.ListTeamBindings(ctx, ns, legacy.ListTeamBindingsQuery{
|
||||||
UID: name,
|
TeamID: teamID,
|
||||||
|
UserID: userID,
|
||||||
Pagination: common.Pagination{Limit: 1},
|
Pagination: common.Pagination{Limit: 1},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -210,7 +216,7 @@ func mapToBindingObject(ns claims.NamespaceInfo, tm legacy.TeamMember) iamv0alph
|
||||||
|
|
||||||
return iamv0alpha1.TeamBinding{
|
return iamv0alpha1.TeamBinding{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: tm.TeamUID,
|
Name: mapToBindingName(tm.TeamID, tm.UserID),
|
||||||
Namespace: ns.Value,
|
Namespace: ns.Value,
|
||||||
ResourceVersion: strconv.FormatInt(rv.UnixMilli(), 10),
|
ResourceVersion: strconv.FormatInt(rv.UnixMilli(), 10),
|
||||||
CreationTimestamp: metav1.NewTime(ct),
|
CreationTimestamp: metav1.NewTime(ct),
|
||||||
|
|
@ -227,6 +233,33 @@ func mapToBindingObject(ns claims.NamespaceInfo, tm legacy.TeamMember) iamv0alph
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mapToBindingName(teamID int64, userID int64) string {
|
||||||
|
return fmt.Sprintf("binding-%d-%d", teamID, userID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapFromBindingName(name string) (int64, int64) {
|
||||||
|
parts := strings.Split(name, "-")
|
||||||
|
if len(parts) != 3 {
|
||||||
|
return 0, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if parts[0] != "binding" {
|
||||||
|
return 0, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
teamID, err := strconv.ParseInt(parts[1], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
userID, err := strconv.ParseInt(parts[2], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return teamID, userID
|
||||||
|
}
|
||||||
|
|
||||||
func mapPermisson(p team.PermissionType) iamv0.TeamPermission {
|
func mapPermisson(p team.PermissionType) iamv0.TeamPermission {
|
||||||
if p == team.PermissionTypeAdmin {
|
if p == team.PermissionTypeAdmin {
|
||||||
return iamv0.TeamPermissionAdmin
|
return iamv0.TeamPermissionAdmin
|
||||||
|
|
|
||||||
|
|
@ -57,9 +57,22 @@ func ValidateOnUpdate(ctx context.Context, obj, old *iamv0alpha1.Team) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ValidateOnBindingCreate(ctx context.Context, obj *iamv0alpha1.TeamBinding) error {
|
func ValidateOnBindingCreate(ctx context.Context, obj *iamv0alpha1.TeamBinding) error {
|
||||||
|
_, err := identity.GetRequester(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return apierrors.NewUnauthorized("no identity found")
|
||||||
|
}
|
||||||
|
|
||||||
if obj.Spec.Permission != iamv0alpha1.TeamBindingTeamPermissionAdmin && obj.Spec.Permission != iamv0alpha1.TeamBindingTeamPermissionMember {
|
if obj.Spec.Permission != iamv0alpha1.TeamBindingTeamPermissionAdmin && obj.Spec.Permission != iamv0alpha1.TeamBindingTeamPermissionMember {
|
||||||
return apierrors.NewBadRequest("invalid permission")
|
return apierrors.NewBadRequest("invalid permission")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if obj.Spec.Subject.Name == "" {
|
||||||
|
return apierrors.NewBadRequest("subject is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
if obj.Spec.TeamRef.Name == "" {
|
||||||
|
return apierrors.NewBadRequest("teamRef is required")
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -371,6 +371,60 @@ func TestValidateOnBindingCreate(t *testing.T) {
|
||||||
},
|
},
|
||||||
want: apierrors.NewBadRequest("invalid permission"),
|
want: apierrors.NewBadRequest("invalid permission"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "invalid team binding - no subject",
|
||||||
|
requester: &identity.StaticRequester{
|
||||||
|
Type: types.TypeUser,
|
||||||
|
OrgRole: identity.RoleAdmin,
|
||||||
|
},
|
||||||
|
obj: &iamv0alpha1.TeamBinding{
|
||||||
|
Spec: iamv0alpha1.TeamBindingSpec{
|
||||||
|
Subject: iamv0alpha1.TeamBindingspecSubject{
|
||||||
|
Name: "",
|
||||||
|
},
|
||||||
|
TeamRef: iamv0alpha1.TeamBindingTeamRef{
|
||||||
|
Name: "test-team",
|
||||||
|
},
|
||||||
|
Permission: iamv0alpha1.TeamBindingTeamPermissionAdmin,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: apierrors.NewBadRequest("subject is required"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid team binding - no teamRef",
|
||||||
|
requester: &identity.StaticRequester{
|
||||||
|
Type: types.TypeUser,
|
||||||
|
OrgRole: identity.RoleAdmin,
|
||||||
|
},
|
||||||
|
obj: &iamv0alpha1.TeamBinding{
|
||||||
|
Spec: iamv0alpha1.TeamBindingSpec{
|
||||||
|
Subject: iamv0alpha1.TeamBindingspecSubject{
|
||||||
|
Name: "test-user",
|
||||||
|
},
|
||||||
|
TeamRef: iamv0alpha1.TeamBindingTeamRef{
|
||||||
|
Name: "",
|
||||||
|
},
|
||||||
|
Permission: iamv0alpha1.TeamBindingTeamPermissionAdmin,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: apierrors.NewBadRequest("teamRef is required"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid team binding - no requester in context",
|
||||||
|
requester: nil,
|
||||||
|
obj: &iamv0alpha1.TeamBinding{
|
||||||
|
Spec: iamv0alpha1.TeamBindingSpec{
|
||||||
|
Subject: iamv0alpha1.TeamBindingspecSubject{
|
||||||
|
Name: "test-user",
|
||||||
|
},
|
||||||
|
TeamRef: iamv0alpha1.TeamBindingTeamRef{
|
||||||
|
Name: "test-team",
|
||||||
|
},
|
||||||
|
Permission: iamv0alpha1.TeamBindingTeamPermissionAdmin,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: apierrors.NewUnauthorized("no identity found"),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,12 @@ var gvrUsers = schema.GroupVersionResource{
|
||||||
Resource: "users",
|
Resource: "users",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var gvrTeamBindings = schema.GroupVersionResource{
|
||||||
|
Group: "iam.grafana.app",
|
||||||
|
Version: "v0alpha1",
|
||||||
|
Resource: "teambindings",
|
||||||
|
}
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
testsuite.Run(m)
|
testsuite.Run(m)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,295 @@
|
||||||
|
package identity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/apiserver/rest"
|
||||||
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||||
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
|
"github.com/grafana/grafana/pkg/tests/apis"
|
||||||
|
"github.com/grafana/grafana/pkg/tests/testinfra"
|
||||||
|
"github.com/grafana/grafana/pkg/util/testutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIntegrationTeamBindings(t *testing.T) {
|
||||||
|
testutil.SkipIntegrationTestInShortMode(t)
|
||||||
|
|
||||||
|
// TODO: Add rest.Mode4 when it's supported
|
||||||
|
modes := []rest.DualWriterMode{rest.Mode0, rest.Mode1, rest.Mode2, rest.Mode3}
|
||||||
|
for _, mode := range modes {
|
||||||
|
t.Run(fmt.Sprintf("Team binding CRUD operations with dual writer mode %d", mode), func(t *testing.T) {
|
||||||
|
helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{
|
||||||
|
AppModeProduction: false,
|
||||||
|
DisableAnonymous: true,
|
||||||
|
APIServerStorageType: "unified",
|
||||||
|
UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{
|
||||||
|
"teambindings.iam.grafana.app": {
|
||||||
|
DualWriterMode: mode,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
EnableFeatureToggles: []string{
|
||||||
|
featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs,
|
||||||
|
featuremgmt.FlagKubernetesAuthnMutation,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
// Create a team
|
||||||
|
teamClient := helper.GetResourceClient(apis.ResourceClientArgs{
|
||||||
|
User: helper.Org1.Admin,
|
||||||
|
Namespace: helper.Namespacer(helper.Org1.Admin.Identity.GetOrgID()),
|
||||||
|
GVR: gvrTeams,
|
||||||
|
})
|
||||||
|
|
||||||
|
team, err := teamClient.Resource.Create(ctx, helper.LoadYAMLOrJSONFile("testdata/team-test-create-v0.yaml"), metav1.CreateOptions{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, team)
|
||||||
|
|
||||||
|
// Create a user
|
||||||
|
userClient := helper.GetResourceClient(apis.ResourceClientArgs{
|
||||||
|
User: helper.Org1.Admin,
|
||||||
|
Namespace: helper.Namespacer(helper.Org1.Admin.Identity.GetOrgID()),
|
||||||
|
GVR: gvrUsers,
|
||||||
|
})
|
||||||
|
|
||||||
|
user, err := userClient.Resource.Create(ctx, helper.LoadYAMLOrJSONFile("testdata/user-test-create-v0.yaml"), metav1.CreateOptions{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, user)
|
||||||
|
|
||||||
|
doTeamBindingCRUDTestsUsingTheNewAPIs(t, helper, team, user)
|
||||||
|
|
||||||
|
if mode < 3 {
|
||||||
|
doTeamBindingCRUDTestsUsingTheLegacyAPIs(t, helper, mode)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func doTeamBindingCRUDTestsUsingTheNewAPIs(t *testing.T, helper *apis.K8sTestHelper, team *unstructured.Unstructured, user *unstructured.Unstructured) {
|
||||||
|
t.Run("should create/get team binding using the new APIs", func(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
teamBindingClient := helper.GetResourceClient(apis.ResourceClientArgs{
|
||||||
|
User: helper.Org1.Admin,
|
||||||
|
Namespace: helper.Namespacer(helper.Org1.Admin.Identity.GetOrgID()),
|
||||||
|
GVR: gvrTeamBindings,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Create the team binding
|
||||||
|
toCreate := helper.LoadYAMLOrJSONFile("testdata/teambinding-test-create-v0.yaml")
|
||||||
|
toCreate.Object["spec"].(map[string]interface{})["subject"].(map[string]interface{})["name"] = user.GetName()
|
||||||
|
toCreate.Object["spec"].(map[string]interface{})["teamRef"].(map[string]interface{})["name"] = team.GetName()
|
||||||
|
created, err := teamBindingClient.Resource.Create(ctx, toCreate, metav1.CreateOptions{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, created)
|
||||||
|
|
||||||
|
createdSpec := created.Object["spec"].(map[string]interface{})
|
||||||
|
require.Equal(t, user.GetName(), createdSpec["subject"].(map[string]interface{})["name"])
|
||||||
|
require.Equal(t, team.GetName(), createdSpec["teamRef"].(map[string]interface{})["name"])
|
||||||
|
require.Equal(t, "admin", createdSpec["permission"])
|
||||||
|
|
||||||
|
createdUID := created.GetName()
|
||||||
|
require.NotEmpty(t, createdUID)
|
||||||
|
|
||||||
|
// Get the team binding
|
||||||
|
fetched, err := teamBindingClient.Resource.Get(ctx, createdUID, metav1.GetOptions{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, fetched)
|
||||||
|
|
||||||
|
fetchedSpec := fetched.Object["spec"].(map[string]interface{})
|
||||||
|
require.Equal(t, user.GetName(), fetchedSpec["subject"].(map[string]interface{})["name"])
|
||||||
|
require.Equal(t, team.GetName(), fetchedSpec["teamRef"].(map[string]interface{})["name"])
|
||||||
|
require.Equal(t, "admin", fetchedSpec["permission"])
|
||||||
|
|
||||||
|
require.Equal(t, createdUID, fetched.GetName())
|
||||||
|
require.Equal(t, "default", fetched.GetNamespace())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should not be able to create team binding when using a user with insufficient permissions", func(t *testing.T) {
|
||||||
|
for _, u := range []apis.User{
|
||||||
|
helper.Org1.Editor,
|
||||||
|
helper.Org1.Viewer,
|
||||||
|
} {
|
||||||
|
t.Run(fmt.Sprintf("with basic role_%s", u.Identity.GetOrgRole()), func(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
teamBindingClient := helper.GetResourceClient(apis.ResourceClientArgs{
|
||||||
|
User: u,
|
||||||
|
Namespace: helper.Namespacer(helper.Org1.Admin.Identity.GetOrgID()),
|
||||||
|
GVR: gvrTeamBindings,
|
||||||
|
})
|
||||||
|
|
||||||
|
toCreate := helper.LoadYAMLOrJSONFile("testdata/teambinding-test-create-v0.yaml")
|
||||||
|
toCreate.Object["spec"].(map[string]interface{})["subject"].(map[string]interface{})["name"] = user.GetName()
|
||||||
|
toCreate.Object["spec"].(map[string]interface{})["teamRef"].(map[string]interface{})["name"] = team.GetName()
|
||||||
|
_, err := teamBindingClient.Resource.Create(ctx, toCreate, metav1.CreateOptions{})
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
var statusErr *errors.StatusError
|
||||||
|
require.ErrorAs(t, err, &statusErr)
|
||||||
|
require.Equal(t, int32(403), statusErr.ErrStatus.Code)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should not be able to create team binding without a subject", func(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
teamBindingClient := helper.GetResourceClient(apis.ResourceClientArgs{
|
||||||
|
User: helper.Org1.Admin,
|
||||||
|
Namespace: helper.Namespacer(helper.Org1.Admin.Identity.GetOrgID()),
|
||||||
|
GVR: gvrTeamBindings,
|
||||||
|
})
|
||||||
|
|
||||||
|
toCreate := helper.LoadYAMLOrJSONFile("testdata/teambinding-test-create-v0.yaml")
|
||||||
|
toCreate.Object["spec"].(map[string]interface{})["subject"].(map[string]interface{})["name"] = ""
|
||||||
|
toCreate.Object["spec"].(map[string]interface{})["teamRef"].(map[string]interface{})["name"] = team.GetName()
|
||||||
|
|
||||||
|
_, err := teamBindingClient.Resource.Create(ctx, toCreate, metav1.CreateOptions{})
|
||||||
|
require.Error(t, err)
|
||||||
|
var statusErr *errors.StatusError
|
||||||
|
require.ErrorAs(t, err, &statusErr)
|
||||||
|
require.Equal(t, int32(400), statusErr.ErrStatus.Code)
|
||||||
|
require.Contains(t, statusErr.ErrStatus.Message, "subject is required")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should not be able to create team binding without a teamRef", func(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
teamBindingClient := helper.GetResourceClient(apis.ResourceClientArgs{
|
||||||
|
User: helper.Org1.Admin,
|
||||||
|
Namespace: helper.Namespacer(helper.Org1.Admin.Identity.GetOrgID()),
|
||||||
|
GVR: gvrTeamBindings,
|
||||||
|
})
|
||||||
|
|
||||||
|
toCreate := helper.LoadYAMLOrJSONFile("testdata/teambinding-test-create-v0.yaml")
|
||||||
|
toCreate.Object["spec"].(map[string]interface{})["subject"].(map[string]interface{})["name"] = user.GetName()
|
||||||
|
toCreate.Object["spec"].(map[string]interface{})["teamRef"].(map[string]interface{})["name"] = ""
|
||||||
|
|
||||||
|
_, err := teamBindingClient.Resource.Create(ctx, toCreate, metav1.CreateOptions{})
|
||||||
|
require.Error(t, err)
|
||||||
|
var statusErr *errors.StatusError
|
||||||
|
require.ErrorAs(t, err, &statusErr)
|
||||||
|
require.Equal(t, int32(400), statusErr.ErrStatus.Code)
|
||||||
|
require.Contains(t, statusErr.ErrStatus.Message, "teamRef is required")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("should not be able to create team binding with invalid permission", func(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
teamBindingClient := helper.GetResourceClient(apis.ResourceClientArgs{
|
||||||
|
User: helper.Org1.Admin,
|
||||||
|
Namespace: helper.Namespacer(helper.Org1.Admin.Identity.GetOrgID()),
|
||||||
|
GVR: gvrTeamBindings,
|
||||||
|
})
|
||||||
|
|
||||||
|
toCreate := helper.LoadYAMLOrJSONFile("testdata/teambinding-test-create-v0.yaml")
|
||||||
|
toCreate.Object["spec"].(map[string]interface{})["subject"].(map[string]interface{})["name"] = user.GetName()
|
||||||
|
toCreate.Object["spec"].(map[string]interface{})["teamRef"].(map[string]interface{})["name"] = team.GetName()
|
||||||
|
toCreate.Object["spec"].(map[string]interface{})["permission"] = "invalid"
|
||||||
|
|
||||||
|
_, err := teamBindingClient.Resource.Create(ctx, toCreate, metav1.CreateOptions{})
|
||||||
|
require.Error(t, err)
|
||||||
|
var statusErr *errors.StatusError
|
||||||
|
require.ErrorAs(t, err, &statusErr)
|
||||||
|
require.Equal(t, int32(400), statusErr.ErrStatus.Code)
|
||||||
|
require.Contains(t, statusErr.ErrStatus.Message, "invalid permission")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func doTeamBindingCRUDTestsUsingTheLegacyAPIs(t *testing.T, helper *apis.K8sTestHelper, mode rest.DualWriterMode) {
|
||||||
|
t.Run("should create team binding using legacy APIs and get it using the new APIs", func(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
// Create a team using legacy API
|
||||||
|
legacyTeamPayload := `{
|
||||||
|
"name": "Test Team Legacy",
|
||||||
|
"email": "testteamlegacy@example.com"
|
||||||
|
}`
|
||||||
|
|
||||||
|
type legacyTeamResponse struct {
|
||||||
|
UID string `json:"uid"`
|
||||||
|
ID int64 `json:"teamId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
teamRsp := apis.DoRequest(helper, apis.RequestParams{
|
||||||
|
User: helper.Org1.Admin,
|
||||||
|
Method: "POST",
|
||||||
|
Path: "/api/teams",
|
||||||
|
Body: []byte(legacyTeamPayload),
|
||||||
|
}, &legacyTeamResponse{})
|
||||||
|
|
||||||
|
require.NotNil(t, teamRsp)
|
||||||
|
require.Equal(t, 200, teamRsp.Response.StatusCode)
|
||||||
|
require.NotEmpty(t, teamRsp.Result.UID)
|
||||||
|
|
||||||
|
// Create a user using legacy API
|
||||||
|
legacyUserPayload := `{
|
||||||
|
"name": "Test User 2",
|
||||||
|
"email": "testuser2@example.com",
|
||||||
|
"login": "testuser2",
|
||||||
|
"password": "password123"
|
||||||
|
}`
|
||||||
|
|
||||||
|
type legacyUserResponse struct {
|
||||||
|
UID string `json:"uid"`
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
userRsp := apis.DoRequest(helper, apis.RequestParams{
|
||||||
|
User: helper.Org1.Admin,
|
||||||
|
Method: "POST",
|
||||||
|
Path: "/api/admin/users",
|
||||||
|
Body: []byte(legacyUserPayload),
|
||||||
|
}, &legacyUserResponse{})
|
||||||
|
|
||||||
|
require.NotNil(t, userRsp)
|
||||||
|
require.Equal(t, 200, userRsp.Response.StatusCode)
|
||||||
|
require.NotEmpty(t, userRsp.Result.UID)
|
||||||
|
|
||||||
|
// Create team binding using legacy API
|
||||||
|
legacyTeamBindingPayload := `{
|
||||||
|
"userId": ` + fmt.Sprintf("%d", userRsp.Result.ID) + `,
|
||||||
|
"teamId": ` + fmt.Sprintf("%d", teamRsp.Result.ID) + `,
|
||||||
|
"permission": "member"
|
||||||
|
}`
|
||||||
|
|
||||||
|
type legacyTeamBindingResponse struct {
|
||||||
|
UserID int64 `json:"userId"`
|
||||||
|
TeamID int64 `json:"teamId"`
|
||||||
|
Permission string `json:"permission"`
|
||||||
|
}
|
||||||
|
|
||||||
|
teamBindingRsp := apis.DoRequest(helper, apis.RequestParams{
|
||||||
|
User: helper.Org1.Admin,
|
||||||
|
Method: "POST",
|
||||||
|
Path: "/api/teams/" + teamRsp.Result.UID + "/members",
|
||||||
|
Body: []byte(legacyTeamBindingPayload),
|
||||||
|
}, &legacyTeamBindingResponse{})
|
||||||
|
|
||||||
|
require.NotNil(t, teamBindingRsp)
|
||||||
|
require.Equal(t, 200, teamBindingRsp.Response.StatusCode)
|
||||||
|
|
||||||
|
// Get team binding using new API
|
||||||
|
teamBindingClient := helper.GetResourceClient(apis.ResourceClientArgs{
|
||||||
|
User: helper.Org1.Admin,
|
||||||
|
Namespace: helper.Namespacer(helper.Org1.Admin.Identity.GetOrgID()),
|
||||||
|
GVR: gvrTeamBindings,
|
||||||
|
})
|
||||||
|
|
||||||
|
teamBindingName := fmt.Sprintf("binding-%d-%d", teamRsp.Result.ID, userRsp.Result.ID)
|
||||||
|
teamBinding, err := teamBindingClient.Resource.Get(ctx, teamBindingName, metav1.GetOptions{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, teamBinding)
|
||||||
|
|
||||||
|
teamBindingSpec := teamBinding.Object["spec"].(map[string]interface{})
|
||||||
|
require.Equal(t, "member", teamBindingSpec["permission"])
|
||||||
|
require.Equal(t, userRsp.Result.UID, teamBindingSpec["subject"].(map[string]interface{})["name"])
|
||||||
|
require.Equal(t, teamRsp.Result.UID, teamBindingSpec["teamRef"].(map[string]interface{})["name"])
|
||||||
|
require.Equal(t, teamBindingName, teamBinding.GetName())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
apiVersion: iam.grafana.app/v0alpha1
|
||||||
|
kind: TeamBinding
|
||||||
|
metadata:
|
||||||
|
name: test-team-binding-1
|
||||||
|
spec:
|
||||||
|
subject:
|
||||||
|
name: ""
|
||||||
|
teamRef:
|
||||||
|
name: ""
|
||||||
|
permission: "admin"
|
||||||
Loading…
Reference in New Issue