Przeglądaj źródła

support logging in with grafana.net credentials

Dan Cech 9 lat temu
rodzic
commit
fc17ed351c

+ 1 - 0
pkg/api/login.go

@@ -27,6 +27,7 @@ func LoginView(c *middleware.Context) {
 
 	viewData.Settings["googleAuthEnabled"] = setting.OAuthService.Google
 	viewData.Settings["githubAuthEnabled"] = setting.OAuthService.GitHub
+	viewData.Settings["grafanaNetAuthEnabled"] = setting.OAuthService.GrafanaNet
 	viewData.Settings["genericOAuthEnabled"] = setting.OAuthService.Generic
 	viewData.Settings["oauthProviderName"] = setting.OAuthService.OAuthProviderName
 	viewData.Settings["disableUserSignUp"] = !setting.AllowUserSignUp

+ 1 - 0
pkg/models/models.go

@@ -7,4 +7,5 @@ const (
 	GOOGLE
 	TWITTER
 	GENERIC
+	GRAFANANET
 )

+ 1 - 1
pkg/setting/setting_oauth.go

@@ -11,7 +11,7 @@ type OAuthInfo struct {
 }
 
 type OAuther struct {
-	GitHub, Google, Twitter, Generic bool
+	GitHub, Google, Twitter, Generic, GrafanaNet bool
 	OAuthInfos                       map[string]*OAuthInfo
 	OAuthProviderName                string
 }

+ 112 - 0
pkg/social/grafananet_oauth.go

@@ -0,0 +1,112 @@
+package social
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"strconv"
+
+	"github.com/grafana/grafana/pkg/models"
+
+	"golang.org/x/oauth2"
+)
+
+type SocialGrafanaNet struct {
+	*oauth2.Config
+	url                  string
+	allowedOrganizations []string
+	allowSignup          bool
+}
+
+func (s *SocialGrafanaNet) Type() int {
+	return int(models.GRAFANANET)
+}
+
+func (s *SocialGrafanaNet) IsEmailAllowed(email string) bool {
+	return true
+}
+
+func (s *SocialGrafanaNet) IsSignupAllowed() bool {
+	return s.allowSignup
+}
+
+func (s *SocialGrafanaNet) IsOrganizationMember(client *http.Client) bool {
+	if len(s.allowedOrganizations) == 0 {
+		return true
+	}
+
+	organizations, err := s.FetchOrganizations(client)
+	if err != nil {
+		return false
+	}
+
+	for _, allowedOrganization := range s.allowedOrganizations {
+		for _, organization := range organizations {
+			if organization == allowedOrganization {
+				return true
+			}
+		}
+	}
+
+	return false
+}
+
+func (s *SocialGrafanaNet) FetchOrganizations(client *http.Client) ([]string, error) {
+	type Record struct {
+		Login string `json:"login"`
+	}
+
+	url := fmt.Sprintf(s.url + "/api/oauth2/user/orgs")
+	r, err := client.Get(url)
+	if err != nil {
+		return nil, err
+	}
+
+	defer r.Body.Close()
+
+	var records []Record
+
+	if err = json.NewDecoder(r.Body).Decode(&records); err != nil {
+		return nil, err
+	}
+
+	var logins = make([]string, len(records))
+	for i, record := range records {
+		logins[i] = record.Login
+	}
+
+	return logins, nil
+}
+
+func (s *SocialGrafanaNet) UserInfo(token *oauth2.Token) (*BasicUserInfo, error) {
+	var data struct {
+		Id    int    `json:"id"`
+		Name  string `json:"login"`
+		Email string `json:"email"`
+	}
+
+	var err error
+	client := s.Client(oauth2.NoContext, token)
+	r, err := client.Get(s.url + "/api/oauth2/user")
+	if err != nil {
+		return nil, err
+	}
+
+	defer r.Body.Close()
+
+	if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
+		return nil, err
+	}
+
+	userInfo := &BasicUserInfo{
+		Identity: strconv.Itoa(data.Id),
+		Name:     data.Name,
+		Email:    data.Email,
+	}
+
+	if !s.IsOrganizationMember(client) {
+		return nil, ErrMissingOrganizationMembership
+	}
+
+	return userInfo, nil
+}

+ 29 - 1
pkg/social/social.go

@@ -36,7 +36,7 @@ func NewOAuthService() {
 	setting.OAuthService = &setting.OAuther{}
 	setting.OAuthService.OAuthInfos = make(map[string]*setting.OAuthInfo)
 
-	allOauthes := []string{"github", "google", "generic_oauth"}
+	allOauthes := []string{"github", "google", "generic_oauth", "grafananet"}
 
 	for _, name := range allOauthes {
 		sec := setting.Cfg.Section("auth." + name)
@@ -108,5 +108,33 @@ func NewOAuthService() {
 				allowedOrganizations: allowedOrganizations,
 			}
 		}
+
+		if name == "grafananet" {
+			setting.OAuthService.GrafanaNet = true
+			allowedOrganizations := sec.Key("allowed_organizations").Strings(" ")
+
+			url := sec.Key("url").String()
+			if url == "" {
+				url = "https://grafana.net"
+			}
+
+			config := oauth2.Config{
+				ClientID:     info.ClientId,
+				ClientSecret: info.ClientSecret,
+				Endpoint: oauth2.Endpoint{
+					AuthURL:  url + "/oauth2/authorize",
+					TokenURL: url + "/api/oauth2/token",
+				},
+				RedirectURL: strings.TrimSuffix(setting.AppUrl, "/") + SocialBaseUrl + name,
+				Scopes:      info.Scopes,
+			}
+
+			SocialMap["grafananet"] = &SocialGrafanaNet{
+				Config:               &config,
+				url:                  url,
+				allowSignup:          info.AllowSignup,
+				allowedOrganizations: allowedOrganizations,
+			}
+		}
 	}
 }

+ 7 - 1
public/app/core/controllers/login_ctrl.js

@@ -17,7 +17,13 @@ function (angular, coreModule, config) {
 
     $scope.googleAuthEnabled = config.googleAuthEnabled;
     $scope.githubAuthEnabled = config.githubAuthEnabled;
-    $scope.oauthEnabled = config.githubAuthEnabled || config.googleAuthEnabled || config.genericOAuthEnabled;
+    $scope.grafanaNetAuthEnabled = config.grafanaNetAuthEnabled;
+    $scope.oauthEnabled = (
+      config.githubAuthEnabled
+      || config.googleAuthEnabled
+      || config.grafanaNetAuthEnabled
+      || config.genericOAuthEnabled
+    );
     $scope.allowUserPassLogin = config.allowUserPassLogin;
     $scope.genericOAuthEnabled = config.genericOAuthEnabled;
     $scope.oauthProviderName = config.oauthProviderName;

+ 5 - 2
public/app/partials/login.html

@@ -59,10 +59,13 @@
 						<i class="fa fa-github"></i>
 						with Github
 					</a>
+					<a class="btn btn-large btn-grafana-net" href="login/grafananet" target="_self" ng-if="grafanaNetAuthEnabled">
+						with <span>Grafana.net</span>
+					</a>
 					<a class="btn btn-large btn-generic-oauth" href="login/generic_oauth" target="_self" ng-if="genericOAuthEnabled">
 						<i class="fa fa-gear"></i>
-            with {{oauthProviderName || "OAuth 2"}}
-          </a>
+						with {{oauthProviderName || "OAuth 2"}}
+					</a>
 				</div>
 			</div>
 

+ 1 - 1
public/sass/components/_search.scss

@@ -111,7 +111,7 @@
     font-size: $font-size-sm;
     padding-right: 7rem;
     background: url(../img/grafana_net_logo.svg);
-    background-size: 6.5rem 3rem;
+    background-size: 6.5rem;
     background-repeat: no-repeat;
     background-position: right;
     position: relative;

+ 14 - 1
public/sass/pages/_login.scss

@@ -112,6 +112,19 @@
     background: #555;
     color: white;
   }
+
+  .btn-grafana-net {
+    background: url(../img/grafana_net_logo.svg);
+    background-size: 10rem;
+    background-repeat: no-repeat;
+    background-position: right 35%;
+    overflow: hidden;
+    padding-right: 10.5rem;
+
+    span {
+      display: none;
+    }
+  }
 }
 
 .password-recovery {
@@ -157,7 +170,7 @@
 .invite-box {
   text-align: center;
   border: 1px solid $tight-form-func-bg;
-	background-color: $panel-bg;
+  background-color: $panel-bg;
   max-width: 800px;
   margin-left: auto;
   margin-right: auto;