Team: Add columns external_uid and is_provisioned to the team table (#103285)
* add columns external_id and is_provisioned to the team table * generate openapi specs * rename column to external_uid * generate open api specs * increase limit for external_uid to 256
This commit is contained in:
@@ -187,7 +187,11 @@ func TestAccessControlStore_GetTeamsPermissions(t *testing.T) {
|
||||
|
||||
teams := make([]team.Team, 0)
|
||||
for i := 0; i < len(tt.teamsPermissions); i++ {
|
||||
team, err := teamSvc.CreateTeam(context.Background(), fmt.Sprintf("team-%v", i), "", tt.orgID)
|
||||
teamCmd := team.CreateTeamCommand{
|
||||
Name: fmt.Sprintf("team-%v", i),
|
||||
OrgID: tt.orgID,
|
||||
}
|
||||
team, err := teamSvc.CreateTeam(context.Background(), &teamCmd)
|
||||
require.NoError(t, err)
|
||||
teams = append(teams, team)
|
||||
}
|
||||
@@ -388,7 +392,11 @@ func createUserAndTeam(t *testing.T, store db.DB, userSrv user.Service, teamSvc
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
createdTeam, err := teamSvc.CreateTeam(context.Background(), "team", "", orgID)
|
||||
teamCmd := team.CreateTeamCommand{
|
||||
Name: "team",
|
||||
OrgID: orgID,
|
||||
}
|
||||
createdTeam, err := teamSvc.CreateTeam(context.Background(), &teamCmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = store.WithDbSession(context.Background(), func(sess *db.Session) error {
|
||||
@@ -438,7 +446,11 @@ func createUsersAndTeams(t *testing.T, store db.DB, svcs helperServices, orgID i
|
||||
continue
|
||||
}
|
||||
|
||||
createdTeam, err := svcs.teamSvc.CreateTeam(context.Background(), fmt.Sprintf("team%v", i+1), "", orgID)
|
||||
teamCmd := team.CreateTeamCommand{
|
||||
Name: fmt.Sprintf("team%v", i+1),
|
||||
OrgID: orgID,
|
||||
}
|
||||
createdTeam, err := svcs.teamSvc.CreateTeam(context.Background(), &teamCmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = store.WithDbSession(context.Background(), func(sess *db.Session) error {
|
||||
|
||||
@@ -331,7 +331,12 @@ func TestApi_setTeamPermission(t *testing.T) {
|
||||
server := setupTestServer(t, &user.SignedInUser{OrgID: 1, Permissions: map[int64]map[string][]string{1: accesscontrol.GroupScopesByActionContext(context.Background(), tt.permissions)}}, service)
|
||||
|
||||
// seed team
|
||||
team, err := teamSvc.CreateTeam(context.Background(), "test", "test@test.com", 1)
|
||||
teamCmd := team.CreateTeamCommand{
|
||||
Name: "test",
|
||||
Email: "test@test.com",
|
||||
OrgID: 1,
|
||||
}
|
||||
team, err := teamSvc.CreateTeam(context.Background(), &teamCmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
assignTo := strconv.Itoa(int(tt.teamID))
|
||||
@@ -520,7 +525,12 @@ func seedPermissions(t *testing.T, resourceID string, usrSvc user.Service, teamS
|
||||
t.Helper()
|
||||
|
||||
// seed team 1 with "Edit" permission on dashboard 1
|
||||
team, err := teamSvc.CreateTeam(context.Background(), "test", "test@test.com", 1)
|
||||
teamCmd := team.CreateTeamCommand{
|
||||
Name: "test",
|
||||
Email: "test@test.com",
|
||||
OrgID: 1,
|
||||
}
|
||||
team, err := teamSvc.CreateTeam(context.Background(), &teamCmd)
|
||||
require.NoError(t, err)
|
||||
_, err = service.SetTeamPermission(context.Background(), team.OrgID, team.ID, resourceID, "Edit")
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -96,7 +96,12 @@ func TestService_SetTeamPermission(t *testing.T) {
|
||||
})
|
||||
|
||||
// seed team
|
||||
team, err := teamSvc.CreateTeam(context.Background(), "test", "test@test.com", 1)
|
||||
teamCmd := team.CreateTeamCommand{
|
||||
Name: "test",
|
||||
Email: "test@test.com",
|
||||
OrgID: 1,
|
||||
}
|
||||
team, err := teamSvc.CreateTeam(context.Background(), &teamCmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
var hookCalled bool
|
||||
@@ -211,7 +216,12 @@ func TestService_SetPermissions(t *testing.T) {
|
||||
// seed user
|
||||
_, err := usrSvc.Create(context.Background(), &user.CreateUserCommand{Login: "user", OrgID: 1})
|
||||
require.NoError(t, err)
|
||||
_, err = teamSvc.CreateTeam(context.Background(), "team", "", 1)
|
||||
|
||||
teamCmd := team.CreateTeamCommand{
|
||||
Name: "test",
|
||||
OrgID: 1,
|
||||
}
|
||||
_, err = teamSvc.CreateTeam(context.Background(), &teamCmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
permissions, err := service.SetPermissions(context.Background(), 1, "1", tt.commands...)
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/org/orgimpl"
|
||||
"github.com/grafana/grafana/pkg/services/quota/quotatest"
|
||||
"github.com/grafana/grafana/pkg/services/supportbundles/supportbundlestest"
|
||||
"github.com/grafana/grafana/pkg/services/team"
|
||||
"github.com/grafana/grafana/pkg/services/team/teamimpl"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/services/user/userimpl"
|
||||
@@ -155,9 +156,12 @@ func generateTeamsAndUsers(b *testing.B, store db.DB, cfg *setting.Cfg, users in
|
||||
teamIds := make([]int64, 0)
|
||||
for i := 0; i < numberOfTeams; i++ {
|
||||
// Create team
|
||||
teamName := fmt.Sprintf("%s%v", "team", i)
|
||||
teamEmail := fmt.Sprintf("%s@example.org", teamName)
|
||||
team, err := teamSvc.CreateTeam(context.Background(), teamName, teamEmail, 1)
|
||||
teamCmd := team.CreateTeamCommand{
|
||||
Name: fmt.Sprintf("%s%v", "team", i),
|
||||
Email: fmt.Sprintf("%s%v@example.org", "team", i),
|
||||
OrgID: 1,
|
||||
}
|
||||
team, err := teamSvc.CreateTeam(context.Background(), &teamCmd)
|
||||
require.NoError(b, err)
|
||||
teamId := team.ID
|
||||
teamIds = append(teamIds, teamId)
|
||||
|
||||
@@ -37,6 +37,14 @@ func addTeamMigrations(mg *Migrator) {
|
||||
Cols: []string{"org_id", "uid"}, Type: UniqueIndex,
|
||||
}))
|
||||
|
||||
mg.AddMigration("Add column external_uid in team", NewAddColumnMigration(teamV1, &Column{
|
||||
Name: "external_uid", Type: DB_NVarchar, Length: 256, Nullable: true,
|
||||
}))
|
||||
|
||||
mg.AddMigration("Add column is_provisioned in team", NewAddColumnMigration(teamV1, &Column{
|
||||
Name: "is_provisioned", Type: DB_Bool, Nullable: true,
|
||||
}))
|
||||
|
||||
teamMemberV1 := Table{
|
||||
Name: "team_member",
|
||||
Columns: []*Column{
|
||||
|
||||
@@ -22,11 +22,13 @@ var (
|
||||
|
||||
// Team model
|
||||
type Team struct {
|
||||
ID int64 `json:"id" xorm:"pk autoincr 'id'"`
|
||||
UID string `json:"uid" xorm:"uid"`
|
||||
OrgID int64 `json:"orgId" xorm:"org_id"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
ID int64 `json:"id" xorm:"pk autoincr 'id'"`
|
||||
UID string `json:"uid" xorm:"uid"`
|
||||
OrgID int64 `json:"orgId" xorm:"org_id"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
ExternalUID string `json:"externalUID" xorm:"external_uid"`
|
||||
IsProvisioned bool `json:"isProvisioned" xorm:"is_provisioned"`
|
||||
|
||||
Created time.Time `json:"created"`
|
||||
Updated time.Time `json:"updated"`
|
||||
@@ -36,9 +38,11 @@ type Team struct {
|
||||
// COMMANDS
|
||||
|
||||
type CreateTeamCommand struct {
|
||||
Name string `json:"name" binding:"Required"`
|
||||
Email string `json:"email"`
|
||||
OrgID int64 `json:"-"`
|
||||
Name string `json:"name" binding:"Required"`
|
||||
Email string `json:"email"`
|
||||
ExternalUID string `json:"-"`
|
||||
IsProvisioned bool `json:"-"`
|
||||
OrgID int64 `json:"-"`
|
||||
}
|
||||
|
||||
type UpdateTeamCommand struct {
|
||||
@@ -94,6 +98,8 @@ type TeamDTO struct {
|
||||
OrgID int64 `json:"orgId" xorm:"org_id"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
ExternalUID string `json:"externalUID"`
|
||||
IsProvisioned bool `json:"isProvisioned"`
|
||||
AvatarURL string `json:"avatarUrl"`
|
||||
MemberCount int64 `json:"memberCount"`
|
||||
Permission PermissionType `json:"permission"`
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
CreateTeam(ctx context.Context, name, email string, orgID int64) (Team, error)
|
||||
CreateTeam(ctx context.Context, cmd *CreateTeamCommand) (Team, error)
|
||||
UpdateTeam(ctx context.Context, cmd *UpdateTeamCommand) error
|
||||
DeleteTeam(ctx context.Context, cmd *DeleteTeamCommand) error
|
||||
SearchTeams(ctx context.Context, query *SearchTeamsQuery) (SearchTeamQueryResult, error)
|
||||
|
||||
@@ -34,7 +34,7 @@ func (tapi *TeamAPI) createTeam(c *contextmodel.ReqContext) response.Response {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
|
||||
t, err := tapi.teamService.CreateTeam(c.Req.Context(), cmd.Name, cmd.Email, c.SignedInUser.GetOrgID())
|
||||
t, err := tapi.teamService.CreateTeam(c.Req.Context(), &cmd)
|
||||
if err != nil {
|
||||
if errors.Is(err, team.ErrTeamNameTaken) {
|
||||
return response.Error(http.StatusConflict, "Team name taken", err)
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
)
|
||||
|
||||
type store interface {
|
||||
Create(name, email string, orgID int64) (team.Team, error)
|
||||
Create(ctx context.Context, cmd *team.CreateTeamCommand) (team.Team, error)
|
||||
Update(ctx context.Context, cmd *team.UpdateTeamCommand) error
|
||||
Delete(ctx context.Context, cmd *team.DeleteTeamCommand) error
|
||||
Search(ctx context.Context, query *team.SearchTeamsQuery) (team.SearchTeamQueryResult, error)
|
||||
@@ -71,22 +71,26 @@ func getTeamSelectSQLBase(db db.DB, filteredUsers []string) string {
|
||||
team.uid,
|
||||
team.org_id,
|
||||
team.name as name,
|
||||
team.email as email, ` +
|
||||
team.email as email,
|
||||
team.external_uid as external_uid,
|
||||
team.is_provisioned as is_provisioned, ` +
|
||||
getTeamMemberCount(db, filteredUsers) +
|
||||
` FROM team as team `
|
||||
}
|
||||
|
||||
func (ss *xormStore) Create(name, email string, orgID int64) (team.Team, error) {
|
||||
func (ss *xormStore) Create(ctx context.Context, cmd *team.CreateTeamCommand) (team.Team, error) {
|
||||
t := team.Team{
|
||||
UID: util.GenerateShortUID(),
|
||||
Name: name,
|
||||
Email: email,
|
||||
OrgID: orgID,
|
||||
Created: time.Now(),
|
||||
Updated: time.Now(),
|
||||
UID: util.GenerateShortUID(),
|
||||
Name: cmd.Name,
|
||||
Email: cmd.Email,
|
||||
OrgID: cmd.OrgID,
|
||||
ExternalUID: cmd.ExternalUID,
|
||||
IsProvisioned: cmd.IsProvisioned,
|
||||
Created: time.Now(),
|
||||
Updated: time.Now(),
|
||||
}
|
||||
err := ss.db.WithTransactionalDbSession(context.Background(), func(sess *db.Session) error {
|
||||
if isNameTaken, err := isTeamNameTaken(orgID, name, 0, sess); err != nil {
|
||||
err := ss.db.WithTransactionalDbSession(ctx, func(sess *db.Session) error {
|
||||
if isNameTaken, err := isTeamNameTaken(cmd.OrgID, cmd.Name, 0, sess); err != nil {
|
||||
return err
|
||||
} else if isNameTaken {
|
||||
return team.ErrTeamNameTaken
|
||||
|
||||
@@ -77,9 +77,21 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) {
|
||||
userIds = append(userIds, usr.ID)
|
||||
userUIDs = append(userUIDs, usr.UID)
|
||||
}
|
||||
team1, err = teamSvc.CreateTeam(context.Background(), "group1 name", "test1@test.com", testOrgID)
|
||||
|
||||
team1Cmd := team.CreateTeamCommand{
|
||||
Name: "group1 name",
|
||||
Email: "test1@test.com",
|
||||
OrgID: testOrgID,
|
||||
}
|
||||
team1, err = teamSvc.CreateTeam(context.Background(), &team1Cmd)
|
||||
require.NoError(t, err)
|
||||
team2, err = teamSvc.CreateTeam(context.Background(), "group2 name", "test2@test.com", testOrgID)
|
||||
|
||||
team2Cmd := team.CreateTeamCommand{
|
||||
Name: "group2 name",
|
||||
Email: "test2@test.com",
|
||||
OrgID: testOrgID,
|
||||
}
|
||||
team2, err = teamSvc.CreateTeam(context.Background(), &team2Cmd)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
setup()
|
||||
@@ -540,7 +552,12 @@ func TestIntegrationSQLStore_SearchTeams(t *testing.T) {
|
||||
|
||||
// Seed 10 teams
|
||||
for i := 1; i <= 10; i++ {
|
||||
_, err := teamSvc.CreateTeam(context.Background(), fmt.Sprintf("team-%d", i), fmt.Sprintf("team-%d@example.org", i), 1)
|
||||
teamCmd := team.CreateTeamCommand{
|
||||
Name: fmt.Sprintf("team-%d", i),
|
||||
Email: fmt.Sprintf("team-%d@example.org", i),
|
||||
OrgID: 1,
|
||||
}
|
||||
_, err := teamSvc.CreateTeam(context.Background(), &teamCmd)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -574,10 +591,23 @@ func TestIntegrationSQLStore_GetTeamMembers_ACFilter(t *testing.T) {
|
||||
setup := func(store db.DB, cfg *setting.Cfg) {
|
||||
teamSvc, err := ProvideService(store, cfg, tracing.InitializeTracerForTest())
|
||||
require.NoError(t, err)
|
||||
team1, errCreateTeam := teamSvc.CreateTeam(context.Background(), "group1 name", "test1@example.org", testOrgID)
|
||||
|
||||
team1Cmd := team.CreateTeamCommand{
|
||||
Name: "group1 name",
|
||||
Email: "test1@example.org",
|
||||
OrgID: testOrgID,
|
||||
}
|
||||
team1, errCreateTeam := teamSvc.CreateTeam(context.Background(), &team1Cmd)
|
||||
require.NoError(t, errCreateTeam)
|
||||
team2, errCreateTeam := teamSvc.CreateTeam(context.Background(), "group2 name", "test2@example.org", testOrgID)
|
||||
|
||||
team2Cmd := team.CreateTeamCommand{
|
||||
Name: "group2 name",
|
||||
Email: "test2@example.org",
|
||||
OrgID: testOrgID,
|
||||
}
|
||||
team2, errCreateTeam := teamSvc.CreateTeam(context.Background(), &team2Cmd)
|
||||
require.NoError(t, errCreateTeam)
|
||||
|
||||
quotaService := quotaimpl.ProvideService(store, cfg)
|
||||
orgSvc, err := orgimpl.ProvideService(store, cfg, quotaService)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -32,13 +32,13 @@ func ProvideService(db db.DB, cfg *setting.Cfg, tracer tracing.Tracer) (team.Ser
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Service) CreateTeam(ctx context.Context, name, email string, orgID int64) (team.Team, error) {
|
||||
func (s *Service) CreateTeam(ctx context.Context, cmd *team.CreateTeamCommand) (team.Team, error) {
|
||||
_, span := s.tracer.Start(ctx, "team.CreateTeam", trace.WithAttributes(
|
||||
attribute.Int64("orgID", orgID),
|
||||
attribute.String("name", name),
|
||||
attribute.Int64("orgID", cmd.OrgID),
|
||||
attribute.String("name", cmd.Name),
|
||||
))
|
||||
defer span.End()
|
||||
return s.store.Create(name, email, orgID)
|
||||
return s.store.Create(ctx, cmd)
|
||||
}
|
||||
|
||||
func (s *Service) UpdateTeam(ctx context.Context, cmd *team.UpdateTeamCommand) error {
|
||||
|
||||
@@ -20,7 +20,7 @@ func NewFakeService() *FakeService {
|
||||
return &FakeService{}
|
||||
}
|
||||
|
||||
func (s *FakeService) CreateTeam(ctx context.Context, name, email string, orgID int64) (team.Team, error) {
|
||||
func (s *FakeService) CreateTeam(ctx context.Context, cmd *team.CreateTeamCommand) (team.Team, error) {
|
||||
return s.ExpectedTeam, s.ExpectedError
|
||||
}
|
||||
|
||||
|
||||
@@ -688,7 +688,12 @@ func (c *K8sTestHelper) CreateDS(cmd *datasources.AddDataSourceCommand) *datasou
|
||||
func (c *K8sTestHelper) CreateTeam(name, email string, orgID int64) team.Team {
|
||||
c.t.Helper()
|
||||
|
||||
team, err := c.teamSvc.CreateTeam(context.Background(), name, email, orgID)
|
||||
teamCmd := team.CreateTeamCommand{
|
||||
Name: name,
|
||||
Email: email,
|
||||
OrgID: orgID,
|
||||
}
|
||||
team, err := c.teamSvc.CreateTeam(context.Background(), &teamCmd)
|
||||
require.NoError(c.t, err)
|
||||
return team
|
||||
}
|
||||
|
||||
@@ -21063,10 +21063,16 @@
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"externalUID": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"isProvisioned": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"memberCount": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
|
||||
@@ -11135,10 +11135,16 @@
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"externalUID": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"isProvisioned": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"memberCount": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
|
||||
Reference in New Issue
Block a user