diff --git a/conf/grafana.ini b/conf/grafana.ini index 3c197462cd7..562fd6dee2e 100644 --- a/conf/grafana.ini +++ b/conf/grafana.ini @@ -59,9 +59,9 @@ default_role = Editor ; enable anonymous access enabled = false ; specify account name that should be used for unauthenticated users -account = main +account_name = main ; specify role for unauthenticated users -role = Viewer +account_role = Viewer [auth.github] enabled = false diff --git a/pkg/middleware/auth.go b/pkg/middleware/auth.go index e4216341443..c49f5298f9b 100644 --- a/pkg/middleware/auth.go +++ b/pkg/middleware/auth.go @@ -6,7 +6,6 @@ import ( "github.com/Unknwon/macaron" - "github.com/torkelo/grafana-pro/pkg/log" m "github.com/torkelo/grafana-pro/pkg/models" "github.com/torkelo/grafana-pro/pkg/setting" ) @@ -70,15 +69,13 @@ func RoleAuth(roles ...m.RoleType) macaron.Handler { func Auth(options *AuthOptions) macaron.Handler { return func(c *Context) { - - if !c.IsSignedIn && options.ReqSignedIn { - log.Info("AppSubUrl: %v", setting.AppSubUrl) - c.SetCookie("redirect_to", url.QueryEscape(setting.AppSubUrl+c.Req.RequestURI), 0, setting.AppSubUrl+"/") + if !c.IsGrafanaAdmin && options.ReqGrafanaAdmin { authDenied(c) return } - if !c.IsGrafanaAdmin && options.ReqGrafanaAdmin { + if !c.IsSignedIn && options.ReqSignedIn && !c.HasAnonymousAccess { + c.SetCookie("redirect_to", url.QueryEscape(setting.AppSubUrl+c.Req.RequestURI), 0, setting.AppSubUrl+"/") authDenied(c) return } diff --git a/pkg/middleware/middleware.go b/pkg/middleware/middleware.go index f8f5700cb18..411ee62547f 100644 --- a/pkg/middleware/middleware.go +++ b/pkg/middleware/middleware.go @@ -20,14 +20,18 @@ type Context struct { Session session.Store - IsSignedIn bool + IsSignedIn bool + HasAnonymousAccess bool } func GetContextHandler() macaron.Handler { return func(c *macaron.Context, sess session.Store) { ctx := &Context{ - Context: c, - Session: sess, + Context: c, + Session: sess, + SignedInUser: &m.SignedInUser{}, + IsSignedIn: false, + HasAnonymousAccess: false, } // try get account id from request @@ -36,8 +40,8 @@ func GetContextHandler() macaron.Handler { if err := bus.Dispatch(&query); err != nil { log.Error(3, "Failed to get user by id, %v, %v", userId, err) } else { - ctx.IsSignedIn = true ctx.SignedInUser = query.Result + ctx.IsSignedIn = true } } else if key := getApiKey(ctx); key != "" { // Try API Key auth @@ -56,6 +60,19 @@ func GetContextHandler() macaron.Handler { ctx.ApiKeyId = keyInfo.Id ctx.AccountId = keyInfo.AccountId } + } else if setting.AnonymousEnabled { + accountQuery := m.GetAccountByNameQuery{Name: setting.AnonymousAccountName} + if err := bus.Dispatch(&accountQuery); err != nil { + if err == m.ErrAccountNotFound { + log.Error(3, "Anonymous access account name does not exist", nil) + } + } else { + ctx.IsSignedIn = false + ctx.HasAnonymousAccess = true + ctx.SignedInUser = &m.SignedInUser{} + ctx.AccountRole = m.RoleType(setting.AnonymousAccountRole) + ctx.AccountId = accountQuery.Result.Id + } } c.Map(ctx) diff --git a/pkg/models/account.go b/pkg/models/account.go index 43afb7d7488..8a1b80e534a 100644 --- a/pkg/models/account.go +++ b/pkg/models/account.go @@ -43,6 +43,11 @@ type GetAccountByIdQuery struct { Result *Account } +type GetAccountByNameQuery struct { + Name string + Result *Account +} + type AccountDTO struct { Id int64 `json:"id"` Name string `json:"name"` diff --git a/pkg/models/user.go b/pkg/models/user.go index 822d79187cd..42062bb8290 100644 --- a/pkg/models/user.go +++ b/pkg/models/user.go @@ -84,6 +84,9 @@ type SearchUsersQuery struct { // DTO & Projections type SignedInUser struct { + IsSignedIn bool + IsAnonymous bool + UserId int64 AccountId int64 AccountName string diff --git a/pkg/services/sqlstore/account.go b/pkg/services/sqlstore/account.go index be3bb0d8b8f..89c5b1ac46a 100644 --- a/pkg/services/sqlstore/account.go +++ b/pkg/services/sqlstore/account.go @@ -10,13 +10,14 @@ import ( ) func init() { - bus.AddHandler("sql", GetAccount) + bus.AddHandler("sql", GetAccountById) bus.AddHandler("sql", CreateAccount) bus.AddHandler("sql", SetUsingAccount) bus.AddHandler("sql", UpdateAccount) + bus.AddHandler("sql", GetAccountByName) } -func GetAccount(query *m.GetAccountByIdQuery) error { +func GetAccountById(query *m.GetAccountByIdQuery) error { var account m.Account exists, err := x.Id(query.Id).Get(&account) if err != nil { @@ -31,6 +32,21 @@ func GetAccount(query *m.GetAccountByIdQuery) error { return nil } +func GetAccountByName(query *m.GetAccountByNameQuery) error { + var account m.Account + exists, err := x.Where("name=?", query.Name).Get(&account) + if err != nil { + return err + } + + if !exists { + return m.ErrAccountNotFound + } + + query.Result = &account + return nil +} + func CreateAccount(cmd *m.CreateAccountCommand) error { return inTransaction(func(sess *xorm.Session) error { diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index dcba1afbb23..fc866eb97f9 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -70,10 +70,12 @@ var ( DefaultAccountRole string // Http auth - AdminUser string - AdminPassword string - Anonymous bool - AnonymousAccountId int64 + AdminUser string + AdminPassword string + + AnonymousEnabled bool + AnonymousAccountName string + AnonymousAccountRole string // Session settings. SessionOptions session.Options @@ -195,17 +197,19 @@ func NewConfigContext() { CookieUserName = security.Key("cookie_username").String() CookieRememberName = security.Key("cookie_remember_name").String() + // admin + AdminUser = security.Key("admin_user").String() + AdminPassword = security.Key("admin_password").String() + // single account SingleAccountMode = Cfg.Section("account.single").Key("enabled").MustBool(false) DefaultAccountName = Cfg.Section("account.single").Key("account_name").MustString("main") DefaultAccountRole = Cfg.Section("account.single").Key("default_role").In("Editor", []string{"Editor", "Admin", "Viewer"}) - // admin - AdminUser = security.Key("admin_user").String() - AdminPassword = security.Key("admin_password").String() - - // Anonymous = Cfg.MustBool("auth", "anonymous", false) - // AnonymousAccountId = Cfg.MustInt64("auth", "anonymous_account_id", 0) + // anonymous access + AnonymousEnabled = Cfg.Section("auth.anonymous").Key("enabled").MustBool(false) + AnonymousAccountName = Cfg.Section("auth.anonymous").Key("account_name").String() + AnonymousAccountRole = Cfg.Section("auth.anonymous").Key("account_role").String() // PhantomJS rendering ImagesDir = "data/png"