The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/pkg/social/gitlab_oauth.go

132 lines
2.6 KiB

package social
import (
"encoding/json"
"fmt"
"net/http"
"regexp"
"github.com/grafana/grafana/pkg/models"
"golang.org/x/oauth2"
)
type SocialGitlab struct {
*SocialBase
allowedDomains []string
allowedGroups []string
apiUrl string
allowSignup bool
}
var (
ErrMissingGroupMembership = &Error{"User not a member of one of the required groups"}
)
func (s *SocialGitlab) Type() int {
return int(models.GITLAB)
}
func (s *SocialGitlab) IsEmailAllowed(email string) bool {
return isEmailAllowed(email, s.allowedDomains)
}
func (s *SocialGitlab) IsSignupAllowed() bool {
return s.allowSignup
}
func (s *SocialGitlab) IsGroupMember(client *http.Client) 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 {
return true
}
}
}
}
return false
}
func (s *SocialGitlab) GetGroups(client *http.Client, url string) ([]string, string) {
type Group struct {
FullPath string `json:"full_path"`
}
var (
groups []Group
next string
)
if url == "" {
return nil, next
}
response, err := HttpGet(client, url)
if err != nil {
s.log.Error("Error getting groups from GitLab API", "err", err)
return nil, next
}
if err := json.Unmarshal(response.Body, &groups); err != nil {
s.log.Error("Error parsing JSON from GitLab API", "err", err)
return nil, next
}
fullPaths := make([]string, len(groups))
for i, group := range groups {
fullPaths[i] = group.FullPath
}
if link, ok := response.Headers["Link"]; ok {
pattern := regexp.MustCompile(`<([^>]+)>; rel="next"`)
if matches := pattern.FindStringSubmatch(link[0]); matches != nil {
next = matches[1]
}
}
return fullPaths, next
}
func (s *SocialGitlab) UserInfo(client *http.Client, token *oauth2.Token) (*BasicUserInfo, error) {
var data struct {
Id int
Username string
Email string
Name string
State string
}
response, err := HttpGet(client, s.apiUrl+"/user")
if err != nil {
return nil, fmt.Errorf("Error getting user info: %s", err)
}
err = json.Unmarshal(response.Body, &data)
if err != nil {
return nil, fmt.Errorf("Error getting user info: %s", err)
}
if data.State != "active" {
return nil, fmt.Errorf("User %s is inactive", data.Username)
}
userInfo := &BasicUserInfo{
Id: fmt.Sprintf("%d", data.Id),
Name: data.Name,
Login: data.Username,
Email: data.Email,
}
if !s.IsGroupMember(client) {
return nil, ErrMissingGroupMembership
}
return userInfo, nil
}