Commit b47f0ff0 by Alexander Zobnin Committed by GitHub

OAuth: return GitLab groups as a part of user info (enable team sync) (#18388)

* GitLab OAuth: GetGroups refactor

* GitLab OAuth: fetch groups into UserInfo

* GitLab OAuth: minor refactor

* GitLab OAuth: team sync docs
parent b424e12a
......@@ -116,3 +116,14 @@ api_url = https://gitlab.com/api/v4
allowed_groups = example, foo/bar
```
### Team Sync (Enterprise only)
> Only available in Grafana Enterprise v6.4+
With Team Sync you can map your GitLab groups to teams in Grafana so that your users will automatically be added to
the correct teams.
Your GitLab groups can be referenced in the same way as `allowed_groups`, like `example` or `foo/bar`.
[Learn more about Team Sync]({{< relref "auth/enhanced_ldap.md" >}})
......@@ -35,12 +35,11 @@ func (s *SocialGitlab) IsSignupAllowed() bool {
return s.allowSignup
}
func (s *SocialGitlab) IsGroupMember(client *http.Client) bool {
func (s *SocialGitlab) IsGroupMember(groups []string) bool {
if len(s.allowedGroups) == 0 {
return true
}
for groups, url := s.GetGroups(client, s.apiUrl+"/groups"); groups != nil; groups, url = s.GetGroups(client, url) {
for _, allowedGroup := range s.allowedGroups {
for _, group := range groups {
if group == allowedGroup {
......@@ -48,12 +47,22 @@ func (s *SocialGitlab) IsGroupMember(client *http.Client) bool {
}
}
}
}
return false
}
func (s *SocialGitlab) GetGroups(client *http.Client, url string) ([]string, string) {
func (s *SocialGitlab) GetGroups(client *http.Client) []string {
groups := make([]string, 0)
for page, url := s.GetGroupsPage(client, s.apiUrl+"/groups"); page != nil; page, url = s.GetGroupsPage(client, url) {
groups = append(groups, page...)
}
return groups
}
// GetGroupsPage returns groups and link to the next page if response is paginated
func (s *SocialGitlab) GetGroupsPage(client *http.Client, url string) ([]string, string) {
type Group struct {
FullPath string `json:"full_path"`
}
......@@ -83,6 +92,7 @@ func (s *SocialGitlab) GetGroups(client *http.Client, url string) ([]string, str
fullPaths[i] = group.FullPath
}
// GitLab uses Link header with "rel" set to prev/next/first/last page. We need "next".
if link, ok := response.Headers["Link"]; ok {
pattern := regexp.MustCompile(`<([^>]+)>; rel="next"`)
if matches := pattern.FindStringSubmatch(link[0]); matches != nil {
......@@ -117,14 +127,17 @@ func (s *SocialGitlab) UserInfo(client *http.Client, token *oauth2.Token) (*Basi
return nil, fmt.Errorf("User %s is inactive", data.Username)
}
groups := s.GetGroups(client)
userInfo := &BasicUserInfo{
Id: fmt.Sprintf("%d", data.Id),
Name: data.Name,
Login: data.Username,
Email: data.Email,
Groups: groups,
}
if !s.IsGroupMember(client) {
if !s.IsGroupMember(groups) {
return nil, ErrMissingGroupMembership
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment