From 30c334a2b81d03cd6472f36c94d668518c961ebd Mon Sep 17 00:00:00 2001 From: Alexander Menzhinsky Date: Wed, 1 Feb 2017 16:32:51 +0300 Subject: [PATCH] Add common type for oauth authorization errors --- pkg/api/login.go | 5 ++++ pkg/api/login_oauth.go | 30 +++++++++++++++-------- pkg/social/github_oauth.go | 8 ++---- pkg/social/social.go | 8 ++++++ public/app/core/controllers/login_ctrl.js | 14 ++--------- 5 files changed, 37 insertions(+), 28 deletions(-) diff --git a/pkg/api/login.go b/pkg/api/login.go index 8fbe414c08c..d664f65619b 100644 --- a/pkg/api/login.go +++ b/pkg/api/login.go @@ -35,6 +35,11 @@ func LoginView(c *middleware.Context) { viewData.Settings["loginHint"] = setting.LoginHint viewData.Settings["disableLoginForm"] = setting.DisableLoginForm + if loginError, ok := c.Session.Get("loginError").(string); ok { + c.Session.Set("loginError", "") // TODO: is there a proper way to delete a session var? + viewData.Settings["loginError"] = loginError + } + if !tryLoginUsingRememberCookie(c) { c.HTML(200, VIEW_INDEX, viewData) return diff --git a/pkg/api/login_oauth.go b/pkg/api/login_oauth.go index 574d08af09f..9e356347bfd 100644 --- a/pkg/api/login_oauth.go +++ b/pkg/api/login_oauth.go @@ -22,6 +22,13 @@ import ( "github.com/grafana/grafana/pkg/social" ) +var ( + ErrProviderDeniedRequest = errors.New("Login provider denied login request") + ErrEmailNotAllowed = errors.New("Required email domain not fulfilled") + ErrSignUpNotAllowed = errors.New("Signup is not allowed for this adapter") + ErrUsersQuotaReached = errors.New("Users quota reached") +) + func GenStateString() string { rnd := make([]byte, 32) rand.Read(rnd) @@ -44,8 +51,7 @@ func OAuthLogin(ctx *middleware.Context) { error := ctx.Query("error") if error != "" { errorDesc := ctx.Query("error_description") - ctx.Logger.Info("OAuthLogin Failed", "error", error, "errorDesc", errorDesc) - ctx.Redirect(setting.AppSubUrl + "/login?failCode=1003") + redirectWithError(ctx, ErrProviderDeniedRequest, "error", error, "errorDesc", errorDesc) return } @@ -117,10 +123,8 @@ func OAuthLogin(ctx *middleware.Context) { // get user info userInfo, err := connect.UserInfo(client) if err != nil { - if err == social.ErrMissingTeamMembership { - ctx.Redirect(setting.AppSubUrl + "/login?failCode=1000") - } else if err == social.ErrMissingOrganizationMembership { - ctx.Redirect(setting.AppSubUrl + "/login?failCode=1001") + if sErr, ok := err.(*social.Error); ok { + redirectWithError(ctx, sErr) } else { ctx.Handle(500, fmt.Sprintf("login.OAuthLogin(get info from %s)", name), err) } @@ -131,8 +135,7 @@ func OAuthLogin(ctx *middleware.Context) { // validate that the email is allowed to login to grafana if !connect.IsEmailAllowed(userInfo.Email) { - ctx.Logger.Info("OAuth login attempt with unallowed email", "email", userInfo.Email) - ctx.Redirect(setting.AppSubUrl + "/login?failCode=1002") + redirectWithError(ctx, ErrEmailNotAllowed) return } @@ -142,7 +145,7 @@ func OAuthLogin(ctx *middleware.Context) { // create account if missing if err == m.ErrUserNotFound { if !connect.IsSignupAllowed() { - ctx.Redirect(setting.AppSubUrl + "/login") + redirectWithError(ctx, ErrSignUpNotAllowed) return } limitReached, err := middleware.QuotaReached(ctx, "user") @@ -151,7 +154,7 @@ func OAuthLogin(ctx *middleware.Context) { return } if limitReached { - ctx.Redirect(setting.AppSubUrl + "/login") + redirectWithError(ctx, ErrUsersQuotaReached) return } cmd := m.CreateUserCommand{ @@ -179,3 +182,10 @@ func OAuthLogin(ctx *middleware.Context) { ctx.Redirect(setting.AppSubUrl + "/") } + +func redirectWithError(ctx *middleware.Context, err error, v ...interface{}) { + ctx.Logger.Info(err.Error(), v...) + // TODO: we can use the flash storage here once it's implemented + ctx.Session.Set("loginError", err.Error()) + ctx.Redirect(setting.AppSubUrl + "/login") +} diff --git a/pkg/social/github_oauth.go b/pkg/social/github_oauth.go index 64ff1d86851..271a472be84 100644 --- a/pkg/social/github_oauth.go +++ b/pkg/social/github_oauth.go @@ -2,7 +2,6 @@ package social import ( "encoding/json" - "errors" "fmt" "net/http" @@ -21,11 +20,8 @@ type SocialGithub struct { } var ( - ErrMissingTeamMembership = errors.New("User not a member of one of the required teams") -) - -var ( - ErrMissingOrganizationMembership = errors.New("User not a member of one of the required organizations") + ErrMissingTeamMembership = &Error{"User not a member of one of the required teams"} + ErrMissingOrganizationMembership = &Error{"User not a member of one of the required organizations"} ) func (s *SocialGithub) Type() int { diff --git a/pkg/social/social.go b/pkg/social/social.go index 860d068957e..29c4b7ecbb4 100644 --- a/pkg/social/social.go +++ b/pkg/social/social.go @@ -29,6 +29,14 @@ type SocialConnector interface { Client(ctx context.Context, t *oauth2.Token) *http.Client } +type Error struct { + s string +} + +func (e *Error) Error() string { + return e.s +} + var ( SocialBaseUrl = "/login/" SocialMap = make(map[string]SocialConnector) diff --git a/public/app/core/controllers/login_ctrl.js b/public/app/core/controllers/login_ctrl.js index fa3af3d10f0..54323711604 100644 --- a/public/app/core/controllers/login_ctrl.js +++ b/public/app/core/controllers/login_ctrl.js @@ -7,13 +7,6 @@ define([ function (angular, _, coreModule, config) { 'use strict'; - var failCodes = { - "1000": "Required team membership not fulfilled", - "1001": "Required organization membership not fulfilled", - "1002": "Required email domain not fulfilled", - "1003": "Login provider denied login request", - }; - coreModule.default.controller('LoginCtrl', function($scope, backendSrv, contextSrv, $location) { $scope.formModel = { user: '', @@ -36,11 +29,8 @@ function (angular, _, coreModule, config) { $scope.init = function() { $scope.$watch("loginMode", $scope.loginModeChanged); - var params = $location.search(); - if (params.failCode) { - $scope.appEvent('alert-warning', ['Login Failed', failCodes[params.failCode]]); - delete params.failedMsg; - $location.search(params); + if (config.loginError) { + $scope.appEvent('alert-warning', ['Login Failed', config.loginError]); } };