From ad8d831f0e5c4f0b46ab227935525847301cd2c5 Mon Sep 17 00:00:00 2001 From: viehlieb Date: Wed, 12 Oct 2022 15:11:45 +0200 Subject: [PATCH] introduce functionality to assign/create team via group claim --- pkg/models/teams.go | 61 ++++++++++++++++++++++++++- pkg/modules/auth/openid/openid.go | 69 ++++++++++++++++++++++++++++--- 2 files changed, 124 insertions(+), 6 deletions(-) diff --git a/pkg/models/teams.go b/pkg/models/teams.go index cd067dbf4..1d4e7f48f 100644 --- a/pkg/models/teams.go +++ b/pkg/models/teams.go @@ -79,7 +79,7 @@ type TeamMember struct { } // TableName makes beautiful table names -func (*TeamMember) TableName() string { +func (TeamMember) TableName() string { return "team_members" } @@ -119,6 +119,34 @@ func GetTeamByID(s *xorm.Session, id int64) (team *Team, err error) { return } +func GetTeamsByName(s *xorm.Session, name string) (teams []*Team, err error) { + if name == "" { + return teams, ErrTeamsDoNotExist{name} + } + + var ts []*Team + + exists := s. + Where("name = ?", name). + Find(&ts) + if exists != nil { + return + } + if len(ts) == 0 { + return ts, ErrTeamsDoNotExist{name} + } + + // //for each ts + // teamSlice := []*Team{ts} + // err = addMoreInfoToTeams(s, teamSlice) + // if err != nil { + // return + // } + + teams = ts + + return +} func addMoreInfoToTeams(s *xorm.Session, teams []*Team) (err error) { @@ -282,6 +310,37 @@ func (t *Team) Create(s *xorm.Session, a web.Auth) (err error) { }) } +func (t *Team) CreateNoAdmin(s *xorm.Session, a web.Auth) (err error) { + doer, err := user.GetFromAuth(a) + if err != nil { + return err + } + + // Check if we have a name + if t.Name == "" { + return ErrTeamNameCannotBeEmpty{} + } + + t.CreatedByID = doer.ID + t.CreatedBy = doer + + _, err = s.Insert(t) + if err != nil { + return + } + + // Insert the current user as member and admin + tm := TeamMember{TeamID: t.ID, Username: doer.Username, Admin: false} + if err = tm.Create(s, doer); err != nil { + return err + } + + return events.Dispatch(&TeamCreatedEvent{ + Team: t, + Doer: a, + }) +} + // Delete deletes a team // @Summary Deletes a team // @Description Delets a team. This will also remove the access for all users in that team. diff --git a/pkg/modules/auth/openid/openid.go b/pkg/modules/auth/openid/openid.go index a5649eb84..fe2c53fa3 100644 --- a/pkg/modules/auth/openid/openid.go +++ b/pkg/modules/auth/openid/openid.go @@ -51,16 +51,18 @@ type Provider struct { AuthURL string `json:"auth_url"` LogoutURL string `json:"logout_url"` ClientID string `json:"client_id"` + Scope string `json:"scope"` ClientSecret string `json:"-"` openIDProvider *oidc.Provider Oauth2Config *oauth2.Config `json:"-"` } type claims struct { - Email string `json:"email"` - Name string `json:"name"` - PreferredUsername string `json:"preferred_username"` - Nickname string `json:"nickname"` + Email string `json:"email"` + Name string `json:"name"` + PreferredUsername string `json:"preferred_username"` + Nickname string `json:"nickname"` + Group []string `json:"groups"` } func init() { @@ -188,22 +190,79 @@ func HandleCallback(c echo.Context) error { // Check if we have seen this user before u, err := getOrCreateUser(s, cl, idToken.Issuer, idToken.Subject) + + log.Errorf("Issuer %s: %v", idToken.Issuer, err) + if err != nil { _ = s.Rollback() log.Errorf("Error creating new user for provider %s: %v", provider.Name, err) return handler.HandleHTTPError(err, c) } + // Check if we have seen this user before + teams, err := GetOrCreateTeamsByNames(s, cl.Group, u) + if err != nil { + log.Errorf("Error verifying team for name %v, got %v", cl.Name, teams, err) + return err + } else { + for _, team := range teams { + tm := models.TeamMember{TeamID: team.ID, Username: u.Username} + if err = tm.Create(s, u); err != nil { + switch t := err.(type) { + case *models.ErrUserIsMemberOfTeam: + log.Errorf("ErrUserIsMemberOfTeam", t) + break + default: + log.Errorf("Error assigning User to team", t) + } + } + } + } + err = s.Commit() if err != nil { return handler.HandleHTTPError(err, c) } - // Create token return auth.NewUserAuthTokenResponse(u, c, false) } +func GetOrCreateTeamsByNames(s *xorm.Session, teamNames []string, u *user.User) (te []models.Team, err error) { + te = []models.Team{} + for _, t := range teamNames { + team, err := models.GetTeamsByName(s, t) + + if models.IsErrTeamsDoNotExist(err) { + log.Errorf("No such Team: %v, got %v", t, team, err) + tea := &models.Team{ + Name: t, + } + err := tea.CreateNoAdmin(s, u) + if err != nil { + log.Errorf("Teams: %v, err: %v", tea, err) + } else { + te = append(te, *tea) + } + } else { + // if multiple teams with same name are found, + if len(team) == 1 { + te = append(te, *team[len(team)-1]) + } else { + log.Errorf("Multiple Teams have the same name: %v, ", team[len(team)-1].Name) + } + } + } + return te, err +} + +// assign user to team +// remove user from team if not in group +// if multiple teams found with same name -> do nothing +// optional: assign by id +// + func getOrCreateUser(s *xorm.Session, cl *claims, issuer, subject string) (u *user.User, err error) { + // Check if the user exists for that issuer and subject u, err = user.GetUserWithEmail(s, &user.User{ Issuer: issuer,