switch to passing ReqContext as a property

This commit is contained in:
Dan Cech 2018-03-23 15:50:07 -04:00
parent e53315dce8
commit d837be91ec
No known key found for this signature in database
GPG Key ID: 6F1146C5B66FBD41
13 changed files with 75 additions and 54 deletions

View File

@ -101,13 +101,14 @@ func LoginPost(c *m.ReqContext, cmd dtos.LoginCommand) Response {
return Error(401, "Login is disabled", nil) return Error(401, "Login is disabled", nil)
} }
authQuery := m.LoginUserQuery{ authQuery := &m.LoginUserQuery{
ReqContext: c,
Username: cmd.User, Username: cmd.User,
Password: cmd.Password, Password: cmd.Password,
IpAddress: c.Req.RemoteAddr, IpAddress: c.Req.RemoteAddr,
} }
if err := login.AuthenticateUser(c, &authQuery); err != nil { if err := bus.Dispatch(authQuery); err != nil {
if err == login.ErrInvalidCredentials || err == login.ErrTooManyLoginAttempts { if err == login.ErrInvalidCredentials || err == login.ErrTooManyLoginAttempts {
return Error(401, "Invalid username or password", err) return Error(401, "Invalid username or password", err)
} }

View File

@ -13,6 +13,7 @@ import (
"golang.org/x/oauth2" "golang.org/x/oauth2"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/log" "github.com/grafana/grafana/pkg/log"
"github.com/grafana/grafana/pkg/login" "github.com/grafana/grafana/pkg/login"
"github.com/grafana/grafana/pkg/metrics" "github.com/grafana/grafana/pkg/metrics"
@ -150,7 +151,7 @@ func OAuthLogin(ctx *m.ReqContext) {
return return
} }
extUser := m.ExternalUserInfo{ extUser := &m.ExternalUserInfo{
AuthModule: "oauth_" + name, AuthModule: "oauth_" + name,
AuthId: userInfo.Id, AuthId: userInfo.Id,
Name: userInfo.Name, Name: userInfo.Name,
@ -165,10 +166,11 @@ func OAuthLogin(ctx *m.ReqContext) {
// add/update user in grafana // add/update user in grafana
cmd := &m.UpsertUserCommand{ cmd := &m.UpsertUserCommand{
ExternalUser: &extUser, ReqContext: ctx,
ExternalUser: extUser,
SignupAllowed: connect.IsSignupAllowed(), SignupAllowed: connect.IsSignupAllowed(),
} }
err = login.UpsertUser(ctx, cmd) err = bus.Dispatch(cmd)
if err != nil { if err != nil {
redirectWithError(ctx, err) redirectWithError(ctx, err)
return return

View File

@ -23,7 +23,7 @@ func Init() {
loadLdapConfig() loadLdapConfig()
} }
func AuthenticateUser(ctx *m.ReqContext, query *m.LoginUserQuery) error { func AuthenticateUser(query *m.LoginUserQuery) error {
if err := validateLoginAttempts(query.Username); err != nil { if err := validateLoginAttempts(query.Username); err != nil {
return err return err
} }
@ -33,7 +33,7 @@ func AuthenticateUser(ctx *m.ReqContext, query *m.LoginUserQuery) error {
return err return err
} }
ldapEnabled, ldapErr := loginUsingLdap(ctx, query) ldapEnabled, ldapErr := loginUsingLdap(query)
if ldapEnabled { if ldapEnabled {
if ldapErr == nil || ldapErr != ErrInvalidCredentials { if ldapErr == nil || ldapErr != ErrInvalidCredentials {
return ldapErr return ldapErr

View File

@ -16,7 +16,7 @@ func TestAuthenticateUser(t *testing.T) {
mockLoginUsingLdap(true, nil, sc) mockLoginUsingLdap(true, nil, sc)
mockSaveInvalidLoginAttempt(sc) mockSaveInvalidLoginAttempt(sc)
err := AuthenticateUser(nil, sc.loginUserQuery) err := AuthenticateUser(sc.loginUserQuery)
Convey("it should result in", func() { Convey("it should result in", func() {
So(err, ShouldEqual, ErrTooManyLoginAttempts) So(err, ShouldEqual, ErrTooManyLoginAttempts)
@ -33,7 +33,7 @@ func TestAuthenticateUser(t *testing.T) {
mockLoginUsingLdap(true, ErrInvalidCredentials, sc) mockLoginUsingLdap(true, ErrInvalidCredentials, sc)
mockSaveInvalidLoginAttempt(sc) mockSaveInvalidLoginAttempt(sc)
err := AuthenticateUser(nil, sc.loginUserQuery) err := AuthenticateUser(sc.loginUserQuery)
Convey("it should result in", func() { Convey("it should result in", func() {
So(err, ShouldEqual, nil) So(err, ShouldEqual, nil)
@ -51,7 +51,7 @@ func TestAuthenticateUser(t *testing.T) {
mockLoginUsingLdap(true, ErrInvalidCredentials, sc) mockLoginUsingLdap(true, ErrInvalidCredentials, sc)
mockSaveInvalidLoginAttempt(sc) mockSaveInvalidLoginAttempt(sc)
err := AuthenticateUser(nil, sc.loginUserQuery) err := AuthenticateUser(sc.loginUserQuery)
Convey("it should result in", func() { Convey("it should result in", func() {
So(err, ShouldEqual, customErr) So(err, ShouldEqual, customErr)
@ -68,7 +68,7 @@ func TestAuthenticateUser(t *testing.T) {
mockLoginUsingLdap(false, nil, sc) mockLoginUsingLdap(false, nil, sc)
mockSaveInvalidLoginAttempt(sc) mockSaveInvalidLoginAttempt(sc)
err := AuthenticateUser(nil, sc.loginUserQuery) err := AuthenticateUser(sc.loginUserQuery)
Convey("it should result in", func() { Convey("it should result in", func() {
So(err, ShouldEqual, ErrInvalidCredentials) So(err, ShouldEqual, ErrInvalidCredentials)
@ -85,7 +85,7 @@ func TestAuthenticateUser(t *testing.T) {
mockLoginUsingLdap(true, ErrInvalidCredentials, sc) mockLoginUsingLdap(true, ErrInvalidCredentials, sc)
mockSaveInvalidLoginAttempt(sc) mockSaveInvalidLoginAttempt(sc)
err := AuthenticateUser(nil, sc.loginUserQuery) err := AuthenticateUser(sc.loginUserQuery)
Convey("it should result in", func() { Convey("it should result in", func() {
So(err, ShouldEqual, ErrInvalidCredentials) So(err, ShouldEqual, ErrInvalidCredentials)
@ -102,7 +102,7 @@ func TestAuthenticateUser(t *testing.T) {
mockLoginUsingLdap(true, nil, sc) mockLoginUsingLdap(true, nil, sc)
mockSaveInvalidLoginAttempt(sc) mockSaveInvalidLoginAttempt(sc)
err := AuthenticateUser(nil, sc.loginUserQuery) err := AuthenticateUser(sc.loginUserQuery)
Convey("it should result in", func() { Convey("it should result in", func() {
So(err, ShouldBeNil) So(err, ShouldBeNil)
@ -120,7 +120,7 @@ func TestAuthenticateUser(t *testing.T) {
mockLoginUsingLdap(true, customErr, sc) mockLoginUsingLdap(true, customErr, sc)
mockSaveInvalidLoginAttempt(sc) mockSaveInvalidLoginAttempt(sc)
err := AuthenticateUser(nil, sc.loginUserQuery) err := AuthenticateUser(sc.loginUserQuery)
Convey("it should result in", func() { Convey("it should result in", func() {
So(err, ShouldEqual, customErr) So(err, ShouldEqual, customErr)
@ -137,7 +137,7 @@ func TestAuthenticateUser(t *testing.T) {
mockLoginUsingLdap(true, ErrInvalidCredentials, sc) mockLoginUsingLdap(true, ErrInvalidCredentials, sc)
mockSaveInvalidLoginAttempt(sc) mockSaveInvalidLoginAttempt(sc)
err := AuthenticateUser(nil, sc.loginUserQuery) err := AuthenticateUser(sc.loginUserQuery)
Convey("it should result in", func() { Convey("it should result in", func() {
So(err, ShouldEqual, ErrInvalidCredentials) So(err, ShouldEqual, ErrInvalidCredentials)
@ -168,7 +168,7 @@ func mockLoginUsingGrafanaDB(err error, sc *authScenarioContext) {
} }
func mockLoginUsingLdap(enabled bool, err error, sc *authScenarioContext) { func mockLoginUsingLdap(enabled bool, err error, sc *authScenarioContext) {
loginUsingLdap = func(c *m.ReqContext, query *m.LoginUserQuery) (bool, error) { loginUsingLdap = func(query *m.LoginUserQuery) (bool, error) {
sc.ldapLoginWasCalled = true sc.ldapLoginWasCalled = true
return enabled, err return enabled, err
} }

View File

@ -9,7 +9,11 @@ import (
"github.com/grafana/grafana/pkg/services/quota" "github.com/grafana/grafana/pkg/services/quota"
) )
var UpsertUser = func(ctx *m.ReqContext, cmd *m.UpsertUserCommand) error { func init() {
bus.AddHandler("auth", UpsertUser)
}
func UpsertUser(cmd *m.UpsertUserCommand) error {
extUser := cmd.ExternalUser extUser := cmd.ExternalUser
userQuery := m.GetUserByAuthInfoQuery{ userQuery := m.GetUserByAuthInfoQuery{
@ -30,7 +34,7 @@ var UpsertUser = func(ctx *m.ReqContext, cmd *m.UpsertUserCommand) error {
return ErrInvalidCredentials return ErrInvalidCredentials
} }
limitReached, err := quota.QuotaReached(ctx, "user") limitReached, err := quota.QuotaReached(cmd.ReqContext, "user")
if err != nil { if err != nil {
log.Warn("Error getting user quota", "err", err) log.Warn("Error getting user quota", "err", err)
return ErrGettingUserQuota return ErrGettingUserQuota

View File

@ -10,6 +10,7 @@ import (
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/go-ldap/ldap" "github.com/go-ldap/ldap"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/log" "github.com/grafana/grafana/pkg/log"
m "github.com/grafana/grafana/pkg/models" m "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
@ -23,7 +24,7 @@ type ILdapConn interface {
} }
type ILdapAuther interface { type ILdapAuther interface {
Login(ctx *m.ReqContext, query *m.LoginUserQuery) error Login(query *m.LoginUserQuery) error
SyncSignedInUser(ctx *m.ReqContext, signedInUser *m.SignedInUser) error SyncSignedInUser(ctx *m.ReqContext, signedInUser *m.SignedInUser) error
GetGrafanaUserFor(ctx *m.ReqContext, ldapUser *LdapUserInfo) (*m.User, error) GetGrafanaUserFor(ctx *m.ReqContext, ldapUser *LdapUserInfo) (*m.User, error)
} }
@ -87,17 +88,15 @@ func (a *ldapAuther) Dial() error {
return err return err
} }
func (a *ldapAuther) Login(ctx *m.ReqContext, query *m.LoginUserQuery) error { func (a *ldapAuther) Login(query *m.LoginUserQuery) error {
// connect to ldap server // connect to ldap server
err := a.Dial() if err := a.Dial(); err != nil {
if err != nil {
return err return err
} }
defer a.conn.Close() defer a.conn.Close()
// perform initial authentication // perform initial authentication
err = a.initialBind(query.Username, query.Password) if err := a.initialBind(query.Username, query.Password); err != nil {
if err != nil {
return err return err
} }
@ -117,7 +116,7 @@ func (a *ldapAuther) Login(ctx *m.ReqContext, query *m.LoginUserQuery) error {
} }
} }
grafanaUser, err := a.GetGrafanaUserFor(ctx, ldapUser) grafanaUser, err := a.GetGrafanaUserFor(query.ReqContext, ldapUser)
if err != nil { if err != nil {
return err return err
} }
@ -158,7 +157,7 @@ func (a *ldapAuther) SyncSignedInUser(ctx *m.ReqContext, signedInUser *m.SignedI
} }
func (a *ldapAuther) GetGrafanaUserFor(ctx *m.ReqContext, ldapUser *LdapUserInfo) (*m.User, error) { func (a *ldapAuther) GetGrafanaUserFor(ctx *m.ReqContext, ldapUser *LdapUserInfo) (*m.User, error) {
extUser := m.ExternalUserInfo{ extUser := &m.ExternalUserInfo{
AuthModule: "ldap", AuthModule: "ldap",
AuthId: ldapUser.DN, AuthId: ldapUser.DN,
Name: fmt.Sprintf("%s %s", ldapUser.FirstName, ldapUser.LastName), Name: fmt.Sprintf("%s %s", ldapUser.FirstName, ldapUser.LastName),
@ -190,11 +189,12 @@ func (a *ldapAuther) GetGrafanaUserFor(ctx *m.ReqContext, ldapUser *LdapUserInfo
} }
// add/update user in grafana // add/update user in grafana
userQuery := m.UpsertUserCommand{ userQuery := &m.UpsertUserCommand{
ExternalUser: &extUser, ReqContext: ctx,
ExternalUser: extUser,
SignupAllowed: setting.LdapAllowSignup, SignupAllowed: setting.LdapAllowSignup,
} }
err := UpsertUser(ctx, &userQuery) err := bus.Dispatch(userQuery)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -5,14 +5,14 @@ import (
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
) )
var loginUsingLdap = func(ctx *m.ReqContext, query *m.LoginUserQuery) (bool, error) { var loginUsingLdap = func(query *m.LoginUserQuery) (bool, error) {
if !setting.LdapEnabled { if !setting.LdapEnabled {
return false, nil return false, nil
} }
for _, server := range LdapCfg.Servers { for _, server := range LdapCfg.Servers {
author := NewLdapAuthenticator(server) author := NewLdapAuthenticator(server)
err := author.Login(ctx, query) err := author.Login(query)
if err == nil || err != ErrInvalidCredentials { if err == nil || err != ErrInvalidCredentials {
return true, err return true, err
} }

View File

@ -19,7 +19,7 @@ func TestLdapLogin(t *testing.T) {
ldapLoginScenario("When login with invalid credentials", func(sc *ldapLoginScenarioContext) { ldapLoginScenario("When login with invalid credentials", func(sc *ldapLoginScenarioContext) {
sc.withLoginResult(false) sc.withLoginResult(false)
enabled, err := loginUsingLdap(nil, sc.loginUserQuery) enabled, err := loginUsingLdap(sc.loginUserQuery)
Convey("it should return true", func() { Convey("it should return true", func() {
So(enabled, ShouldBeTrue) So(enabled, ShouldBeTrue)
@ -36,7 +36,7 @@ func TestLdapLogin(t *testing.T) {
ldapLoginScenario("When login with valid credentials", func(sc *ldapLoginScenarioContext) { ldapLoginScenario("When login with valid credentials", func(sc *ldapLoginScenarioContext) {
sc.withLoginResult(true) sc.withLoginResult(true)
enabled, err := loginUsingLdap(nil, sc.loginUserQuery) enabled, err := loginUsingLdap(sc.loginUserQuery)
Convey("it should return true", func() { Convey("it should return true", func() {
So(enabled, ShouldBeTrue) So(enabled, ShouldBeTrue)
@ -58,7 +58,7 @@ func TestLdapLogin(t *testing.T) {
ldapLoginScenario("When login", func(sc *ldapLoginScenarioContext) { ldapLoginScenario("When login", func(sc *ldapLoginScenarioContext) {
sc.withLoginResult(true) sc.withLoginResult(true)
enabled, err := loginUsingLdap(nil, sc.loginUserQuery) enabled, err := loginUsingLdap(sc.loginUserQuery)
Convey("it should return true", func() { Convey("it should return true", func() {
So(enabled, ShouldBeTrue) So(enabled, ShouldBeTrue)
@ -79,7 +79,7 @@ func TestLdapLogin(t *testing.T) {
ldapLoginScenario("When login", func(sc *ldapLoginScenarioContext) { ldapLoginScenario("When login", func(sc *ldapLoginScenarioContext) {
sc.withLoginResult(false) sc.withLoginResult(false)
enabled, err := loginUsingLdap(nil, &m.LoginUserQuery{ enabled, err := loginUsingLdap(&m.LoginUserQuery{
Username: "user", Username: "user",
Password: "pwd", Password: "pwd",
}) })
@ -117,7 +117,7 @@ type mockLdapAuther struct {
loginCalled bool loginCalled bool
} }
func (a *mockLdapAuther) Login(ctx *m.ReqContext, query *m.LoginUserQuery) error { func (a *mockLdapAuther) Login(query *m.LoginUserQuery) error {
a.loginCalled = true a.loginCalled = true
if !a.validLogin { if !a.validLogin {

View File

@ -192,6 +192,8 @@ func ldapAutherScenario(desc string, fn scenarioFunc) {
sc := &scenarioContext{} sc := &scenarioContext{}
bus.AddHandler("test", UpsertUser)
bus.AddHandler("test", func(cmd *m.GetUserByAuthInfoQuery) error { bus.AddHandler("test", func(cmd *m.GetUserByAuthInfoQuery) error {
sc.getUserByAuthInfoQuery = cmd sc.getUserByAuthInfoQuery = cmd
sc.getUserByAuthInfoQuery.User = &m.User{Login: cmd.Login} sc.getUserByAuthInfoQuery.User = &m.User{Login: cmd.Login}

View File

@ -50,7 +50,7 @@ func initContextWithAuthProxy(ctx *m.ReqContext, orgID int64) bool {
return true return true
} }
} else { } else {
extUser := m.ExternalUserInfo{ extUser := &m.ExternalUserInfo{
AuthModule: "authproxy", AuthModule: "authproxy",
AuthId: proxyHeaderValue, AuthId: proxyHeaderValue,
} }
@ -73,10 +73,11 @@ func initContextWithAuthProxy(ctx *m.ReqContext, orgID int64) bool {
// add/update user in grafana // add/update user in grafana
cmd := &m.UpsertUserCommand{ cmd := &m.UpsertUserCommand{
ExternalUser: &extUser, ReqContext: ctx,
ExternalUser: extUser,
SignupAllowed: setting.AuthProxyAutoSignUp, SignupAllowed: setting.AuthProxyAutoSignUp,
} }
err := login.UpsertUser(ctx, cmd) err := bus.Dispatch(cmd)
if err != nil { if err != nil {
ctx.Handle(500, "Failed to login as user specified in auth proxy header", err) ctx.Handle(500, "Failed to login as user specified in auth proxy header", err)
return true return true

View File

@ -116,7 +116,7 @@ type mockLdapAuthenticator struct {
syncSignedInUserCalled bool syncSignedInUserCalled bool
} }
func (a *mockLdapAuthenticator) Login(ctx *m.ReqContext, query *m.LoginUserQuery) error { func (a *mockLdapAuthenticator) Login(query *m.LoginUserQuery) error {
return nil return nil
} }

View File

@ -9,7 +9,6 @@ import (
ms "github.com/go-macaron/session" ms "github.com/go-macaron/session"
"github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/login"
m "github.com/grafana/grafana/pkg/models" m "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/session" "github.com/grafana/grafana/pkg/services/session"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
@ -183,10 +182,10 @@ func TestMiddlewareContext(t *testing.T) {
return nil return nil
}) })
login.UpsertUser = func(ctx *m.ReqContext, cmd *m.UpsertUserCommand) error { bus.AddHandler("test", func(cmd *m.UpsertUserCommand) error {
cmd.Result = &m.User{Id: 12} cmd.Result = &m.User{Id: 12}
return nil return nil
} })
sc.fakeReq("GET", "/") sc.fakeReq("GET", "/")
sc.req.Header.Add("X-WEBAUTH-USER", "torkelo") sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
@ -214,10 +213,10 @@ func TestMiddlewareContext(t *testing.T) {
} }
}) })
login.UpsertUser = func(ctx *m.ReqContext, cmd *m.UpsertUserCommand) error { bus.AddHandler("test", func(cmd *m.UpsertUserCommand) error {
cmd.Result = &m.User{Id: 33} cmd.Result = &m.User{Id: 33}
return nil return nil
} })
sc.fakeReq("GET", "/") sc.fakeReq("GET", "/")
sc.req.Header.Add("X-WEBAUTH-USER", "torkelo") sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
@ -276,10 +275,10 @@ func TestMiddlewareContext(t *testing.T) {
return nil return nil
}) })
login.UpsertUser = func(ctx *m.ReqContext, cmd *m.UpsertUserCommand) error { bus.AddHandler("test", func(cmd *m.UpsertUserCommand) error {
cmd.Result = &m.User{Id: 33} cmd.Result = &m.User{Id: 33}
return nil return nil
} })
sc.fakeReq("GET", "/") sc.fakeReq("GET", "/")
sc.req.Header.Add("X-WEBAUTH-USER", "torkelo") sc.req.Header.Add("X-WEBAUTH-USER", "torkelo")
@ -299,6 +298,11 @@ func TestMiddlewareContext(t *testing.T) {
setting.AuthProxyHeaderProperty = "username" setting.AuthProxyHeaderProperty = "username"
setting.AuthProxyWhitelist = "" setting.AuthProxyWhitelist = ""
bus.AddHandler("test", func(query *m.UpsertUserCommand) error {
query.Result = &m.User{Id: 32}
return nil
})
bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error { bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
query.Result = &m.SignedInUser{OrgId: 4, UserId: 32} query.Result = &m.SignedInUser{OrgId: 4, UserId: 32}
return nil return nil
@ -334,6 +338,11 @@ func TestMiddlewareContext(t *testing.T) {
return nil return nil
} }
bus.AddHandler("test", func(query *m.UpsertUserCommand) error {
query.Result = &m.User{Id: 32}
return nil
})
bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error { bus.AddHandler("test", func(query *m.GetSignedInUserQuery) error {
query.Result = &m.SignedInUser{OrgId: 4, UserId: 32} query.Result = &m.SignedInUser{OrgId: 4, UserId: 32}
return nil return nil

View File

@ -26,6 +26,7 @@ type ExternalUserInfo struct {
// COMMANDS // COMMANDS
type UpsertUserCommand struct { type UpsertUserCommand struct {
ReqContext *ReqContext
ExternalUser *ExternalUserInfo ExternalUser *ExternalUserInfo
SignupAllowed bool SignupAllowed bool
@ -46,6 +47,7 @@ type DeleteAuthInfoCommand struct {
// QUERIES // QUERIES
type LoginUserQuery struct { type LoginUserQuery struct {
ReqContext *ReqContext
Username string Username string
Password string Password string
User *User User *User