Просмотр исходного кода

Merge branch 'github-team-membership-requirement' of https://github.com/dewski/grafana into dewski-github-team-membership-requirement

Torkel Ödegaard 10 лет назад
Родитель
Сommit
d812414621
4 измененных файлов с 67 добавлено и 6 удалено
  1. 1 0
      conf/defaults.ini
  2. 16 2
      docs/sources/installation/configuration.md
  3. 5 1
      pkg/api/login_oauth.go
  4. 45 3
      pkg/social/social.go

+ 1 - 0
conf/defaults.ini

@@ -140,6 +140,7 @@ enabled = false
 client_id = some_id
 client_secret = some_secret
 scopes = user:email
+team_ids =
 auth_url = https://github.com/login/oauth/authorize
 token_url = https://github.com/login/oauth/access_token
 api_url = https://api.github.com/user

+ 16 - 2
docs/sources/installation/configuration.md

@@ -179,6 +179,7 @@ Client ID and a Client Secret. Specify these in the grafana config file. Example
     client_id = YOUR_GITHUB_APP_CLIENT_ID
     client_secret = YOUR_GITHUB_APP_CLIENT_SECRET
     scopes = user:email
+    team_ids =
     auth_url = https://github.com/login/oauth/authorize
     token_url = https://github.com/login/oauth/access_token
     allow_sign_up = false
@@ -189,6 +190,21 @@ now login or signup with your github accounts.
 You may allow users to sign-up via github auth by setting allow_sign_up to true. When this option is
 set to true, any user successfully authenticating via github auth will be automatically signed up.
 
+### team_ids
+Require an active team membership for at least one of the given teams on GitHub.
+If the authenticated user isn't a member of at least one the teams they will not
+be able to register or authenticate with your Grafana instance. Example:
+
+    [auth.github]
+    enabled = true
+    client_id = YOUR_GITHUB_APP_CLIENT_ID
+    client_secret = YOUR_GITHUB_APP_CLIENT_SECRET
+    scopes = user:email
+    team_ids = 150,300
+    auth_url = https://github.com/login/oauth/authorize
+    token_url = https://github.com/login/oauth/access_token
+    allow_sign_up = false
+
 ## [auth.google]
 You need to create a google project. You can do this in the [Google Developer Console](https://console.developers.google.com/project).
 When you create the project you will need to specify a callback URL. Specify this as callback:
@@ -257,5 +273,3 @@ enabled. Counters are sent every 24 hours. Default value is `true`.
 ### google_analytics_ua_id
 If you want to track Grafana usage via Google analytics specify *your* Univeral Analytics ID
 here. By defualt this feature is disabled.
-
-

+ 5 - 1
pkg/api/login_oauth.go

@@ -45,7 +45,11 @@ func OAuthLogin(ctx *middleware.Context) {
 
 	userInfo, err := connect.UserInfo(token)
 	if err != nil {
-		ctx.Handle(500, fmt.Sprintf("login.OAuthLogin(get info from %s)", name), err)
+		if err == social.ErrMissingTeamMembership {
+			ctx.Redirect(setting.AppSubUrl + "/login?missing_team_membership=1")
+		} else {
+			ctx.Handle(500, fmt.Sprintf("login.OAuthLogin(get info from %s)", name), err)
+		}
 		return
 	}
 

+ 45 - 3
pkg/social/social.go

@@ -5,6 +5,8 @@ import (
 	"fmt"
 	"strconv"
 	"strings"
+	"errors"
+	"net/http"
 
 	"github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/setting"
@@ -75,7 +77,8 @@ func NewOAuthService() {
 		// GitHub.
 		if name == "github" {
 			setting.OAuthService.GitHub = true
-			SocialMap["github"] = &SocialGithub{Config: &config, allowedDomains: info.AllowedDomains, ApiUrl: info.ApiUrl, allowSignup: info.AllowSignup}
+			teamIds := sec.Key("team_ids").Ints(",")
+			SocialMap["github"] = &SocialGithub{Config: &config, allowedDomains: info.AllowedDomains, ApiUrl: info.ApiUrl, allowSignup: info.AllowSignup, teamIds: teamIds}
 		}
 
 		// Google.
@@ -105,8 +108,13 @@ type SocialGithub struct {
 	allowedDomains []string
 	ApiUrl         string
 	allowSignup    bool
+	teamIds        []int
 }
 
+var (
+	ErrMissingTeamMembership = errors.New("User not a member of one of the required teams")
+)
+
 func (s *SocialGithub) Type() int {
 	return int(models.GITHUB)
 }
@@ -119,6 +127,28 @@ func (s *SocialGithub) IsSignupAllowed() bool {
 	return s.allowSignup
 }
 
+func (s *SocialGithub) IsTeamMember(client *http.Client, username string, teamId int) bool {
+	var data struct {
+		Url    string `json:"url"`
+		State  string `json:"state"`
+	}
+
+	membershipUrl := fmt.Sprintf("https://api.github.com/teams/%d/memberships/%s", teamId, username)
+	r, err := client.Get(membershipUrl)
+	if err != nil {
+		return false
+	}
+
+	defer r.Body.Close()
+
+	if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
+		return false
+	}
+
+	active := data.State == "active"
+	return active
+}
+
 func (s *SocialGithub) UserInfo(token *oauth2.Token) (*BasicUserInfo, error) {
 	var data struct {
 		Id    int    `json:"id"`
@@ -139,11 +169,23 @@ func (s *SocialGithub) UserInfo(token *oauth2.Token) (*BasicUserInfo, error) {
 		return nil, err
 	}
 
-	return &BasicUserInfo{
+	userInfo := &BasicUserInfo{
 		Identity: strconv.Itoa(data.Id),
 		Name:     data.Name,
 		Email:    data.Email,
-	}, nil
+	}
+
+	if len(s.teamIds) > 0 {
+		for _, teamId := range s.teamIds {
+			if s.IsTeamMember(client, data.Name, teamId) {
+				return userInfo, nil
+			}
+		}
+
+		return nil, ErrMissingTeamMembership
+	} else {
+		return userInfo, nil
+	}
 }
 
 //   ________                     .__