Backend: Remove more globals (#29644)
Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
This commit is contained in:
@@ -81,7 +81,7 @@ type Options struct {
|
||||
OrgID int64
|
||||
}
|
||||
|
||||
// New instance of the AuthProxy
|
||||
// New instance of the AuthProxy.
|
||||
func New(cfg *setting.Cfg, options *Options) *AuthProxy {
|
||||
header := options.Ctx.Req.Header.Get(cfg.AuthProxyHeaderName)
|
||||
return &AuthProxy{
|
||||
@@ -93,7 +93,7 @@ func New(cfg *setting.Cfg, options *Options) *AuthProxy {
|
||||
}
|
||||
}
|
||||
|
||||
// IsEnabled checks if the proxy auth is enabled
|
||||
// IsEnabled checks if the auth proxy is enabled.
|
||||
func (auth *AuthProxy) IsEnabled() bool {
|
||||
// Bail if the setting is not enabled
|
||||
return auth.cfg.AuthProxyEnabled
|
||||
|
||||
@@ -350,13 +350,13 @@ func logUserIn(auth *authproxy.AuthProxy, username string, logger log.Logger, ig
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func handleError(ctx *models.ReqContext, err error, statusCode int, cb func(error)) {
|
||||
func (h *ContextHandler) handleError(ctx *models.ReqContext, err error, statusCode int, cb func(error)) {
|
||||
details := err
|
||||
var e authproxy.Error
|
||||
if errors.As(err, &e) {
|
||||
details = e.DetailsError
|
||||
}
|
||||
ctx.Handle(statusCode, err.Error(), details)
|
||||
ctx.Handle(h.Cfg, statusCode, err.Error(), details)
|
||||
|
||||
if cb != nil {
|
||||
cb(details)
|
||||
@@ -385,7 +385,7 @@ func (h *ContextHandler) initContextWithAuthProxy(ctx *models.ReqContext, orgID
|
||||
|
||||
// Check if allowed to continue with this IP
|
||||
if err := auth.IsAllowedIP(); err != nil {
|
||||
handleError(ctx, err, 407, func(details error) {
|
||||
h.handleError(ctx, err, 407, func(details error) {
|
||||
logger.Error("Failed to check whitelisted IP addresses", "message", err.Error(), "error", details)
|
||||
})
|
||||
return true
|
||||
@@ -393,7 +393,7 @@ func (h *ContextHandler) initContextWithAuthProxy(ctx *models.ReqContext, orgID
|
||||
|
||||
id, err := logUserIn(auth, username, logger, false)
|
||||
if err != nil {
|
||||
handleError(ctx, err, 407, nil)
|
||||
h.handleError(ctx, err, 407, nil)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -414,13 +414,13 @@ func (h *ContextHandler) initContextWithAuthProxy(ctx *models.ReqContext, orgID
|
||||
}
|
||||
id, err = logUserIn(auth, username, logger, true)
|
||||
if err != nil {
|
||||
handleError(ctx, err, 407, nil)
|
||||
h.handleError(ctx, err, 407, nil)
|
||||
return true
|
||||
}
|
||||
|
||||
user, err = auth.GetSignedInUser(id)
|
||||
if err != nil {
|
||||
handleError(ctx, err, 407, nil)
|
||||
h.handleError(ctx, err, 407, nil)
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -433,7 +433,7 @@ func (h *ContextHandler) initContextWithAuthProxy(ctx *models.ReqContext, orgID
|
||||
|
||||
// Remember user data in cache
|
||||
if err := auth.Remember(id); err != nil {
|
||||
handleError(ctx, err, 500, func(details error) {
|
||||
h.handleError(ctx, err, 500, func(details error) {
|
||||
logger.Error(
|
||||
"Failed to store user in cache",
|
||||
"username", username,
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/auth"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -22,7 +21,7 @@ func TestDontRotateTokensOnCancelledRequests(t *testing.T) {
|
||||
ctxHdlr := getContextHandler(t)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
reqContext, _, err := initTokenRotationScenario(ctx, t)
|
||||
reqContext, _, err := initTokenRotationScenario(ctx, t, ctxHdlr)
|
||||
require.NoError(t, err)
|
||||
|
||||
tryRotateCallCount := 0
|
||||
@@ -46,7 +45,7 @@ func TestDontRotateTokensOnCancelledRequests(t *testing.T) {
|
||||
func TestTokenRotationAtEndOfRequest(t *testing.T) {
|
||||
ctxHdlr := getContextHandler(t)
|
||||
|
||||
reqContext, rr, err := initTokenRotationScenario(context.Background(), t)
|
||||
reqContext, rr, err := initTokenRotationScenario(context.Background(), t, ctxHdlr)
|
||||
require.NoError(t, err)
|
||||
|
||||
uts := &auth.FakeUserAuthTokenService{
|
||||
@@ -80,18 +79,13 @@ func TestTokenRotationAtEndOfRequest(t *testing.T) {
|
||||
assert.True(t, foundLoginCookie, "Could not find cookie")
|
||||
}
|
||||
|
||||
func initTokenRotationScenario(ctx context.Context, t *testing.T) (*models.ReqContext, *httptest.ResponseRecorder, error) {
|
||||
func initTokenRotationScenario(ctx context.Context, t *testing.T, ctxHdlr *ContextHandler) (
|
||||
*models.ReqContext, *httptest.ResponseRecorder, error) {
|
||||
t.Helper()
|
||||
|
||||
origLoginCookieName := setting.LoginCookieName
|
||||
origLoginMaxLifetime := setting.LoginMaxLifetime
|
||||
t.Cleanup(func() {
|
||||
setting.LoginCookieName = origLoginCookieName
|
||||
setting.LoginMaxLifetime = origLoginMaxLifetime
|
||||
})
|
||||
setting.LoginCookieName = "login_token"
|
||||
ctxHdlr.Cfg.LoginCookieName = "login_token"
|
||||
var err error
|
||||
setting.LoginMaxLifetime, err = gtime.ParseDuration("7d")
|
||||
ctxHdlr.Cfg.LoginMaxLifetime, err = gtime.ParseDuration("7d")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
package quota
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/registry"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
var ErrInvalidQuotaTarget = errors.New("invalid quota target")
|
||||
|
||||
func init() {
|
||||
registry.RegisterService(&QuotaService{})
|
||||
}
|
||||
|
||||
type QuotaService struct {
|
||||
AuthTokenService models.UserTokenService `inject:""`
|
||||
Cfg *setting.Cfg `inject:""`
|
||||
}
|
||||
|
||||
func (qs *QuotaService) Init() error {
|
||||
@@ -20,7 +25,7 @@ func (qs *QuotaService) Init() error {
|
||||
}
|
||||
|
||||
func (qs *QuotaService) QuotaReached(c *models.ReqContext, target string) (bool, error) {
|
||||
if !setting.Quota.Enabled {
|
||||
if !qs.Cfg.Quota.Enabled {
|
||||
return false, nil
|
||||
}
|
||||
// No request context means this is a background service, like LDAP Background Sync.
|
||||
@@ -29,8 +34,9 @@ func (qs *QuotaService) QuotaReached(c *models.ReqContext, target string) (bool,
|
||||
if c == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// get the list of scopes that this target is valid for. Org, User, Global
|
||||
scopes, err := models.GetQuotaScopes(target)
|
||||
scopes, err := qs.getQuotaScopes(target)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -106,3 +112,46 @@ func (qs *QuotaService) QuotaReached(c *models.ReqContext, target string) (bool,
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (qs *QuotaService) getQuotaScopes(target string) ([]models.QuotaScope, error) {
|
||||
scopes := make([]models.QuotaScope, 0)
|
||||
switch target {
|
||||
case "user":
|
||||
scopes = append(scopes,
|
||||
models.QuotaScope{Name: "global", Target: target, DefaultLimit: qs.Cfg.Quota.Global.User},
|
||||
models.QuotaScope{Name: "org", Target: "org_user", DefaultLimit: qs.Cfg.Quota.Org.User},
|
||||
)
|
||||
return scopes, nil
|
||||
case "org":
|
||||
scopes = append(scopes,
|
||||
models.QuotaScope{Name: "global", Target: target, DefaultLimit: qs.Cfg.Quota.Global.Org},
|
||||
models.QuotaScope{Name: "user", Target: "org_user", DefaultLimit: qs.Cfg.Quota.User.Org},
|
||||
)
|
||||
return scopes, nil
|
||||
case "dashboard":
|
||||
scopes = append(scopes,
|
||||
models.QuotaScope{Name: "global", Target: target, DefaultLimit: qs.Cfg.Quota.Global.Dashboard},
|
||||
models.QuotaScope{Name: "org", Target: target, DefaultLimit: qs.Cfg.Quota.Org.Dashboard},
|
||||
)
|
||||
return scopes, nil
|
||||
case "data_source":
|
||||
scopes = append(scopes,
|
||||
models.QuotaScope{Name: "global", Target: target, DefaultLimit: qs.Cfg.Quota.Global.DataSource},
|
||||
models.QuotaScope{Name: "org", Target: target, DefaultLimit: qs.Cfg.Quota.Org.DataSource},
|
||||
)
|
||||
return scopes, nil
|
||||
case "api_key":
|
||||
scopes = append(scopes,
|
||||
models.QuotaScope{Name: "global", Target: target, DefaultLimit: qs.Cfg.Quota.Global.ApiKey},
|
||||
models.QuotaScope{Name: "org", Target: target, DefaultLimit: qs.Cfg.Quota.Org.ApiKey},
|
||||
)
|
||||
return scopes, nil
|
||||
case "session":
|
||||
scopes = append(scopes,
|
||||
models.QuotaScope{Name: "global", Target: target, DefaultLimit: qs.Cfg.Quota.Global.Session},
|
||||
)
|
||||
return scopes, nil
|
||||
default:
|
||||
return scopes, ErrInvalidQuotaTarget
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package sqlstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
@@ -275,14 +274,3 @@ func getOrCreateOrg(sess *DBSession, orgName string) (int64, error) {
|
||||
|
||||
return org.Id, nil
|
||||
}
|
||||
|
||||
func createDefaultOrg(ctx context.Context) error {
|
||||
return inTransactionCtx(ctx, func(sess *DBSession) error {
|
||||
_, err := getOrCreateOrg(sess, mainOrgName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -118,10 +118,13 @@ func (ss *SQLStore) Init() error {
|
||||
|
||||
func (ss *SQLStore) ensureMainOrgAndAdminUser() error {
|
||||
err := ss.InTransaction(context.Background(), func(ctx context.Context) error {
|
||||
ss.log.Debug("Ensuring main org and admin user exist")
|
||||
var stats models.SystemUserCountStats
|
||||
err := ss.WithDbSession(ctx, func(sess *DBSession) error {
|
||||
var rawSql = `SELECT COUNT(id) AS Count FROM ` + dialect.Quote("user")
|
||||
if _, err := sess.SQL(rawSql).Get(&stats); err != nil {
|
||||
// TODO: Should be able to rename "Count" to "count", for more standard SQL style
|
||||
// Just have to make sure it gets deserialized properly into models.SystemUserCountStats
|
||||
rawSQL := `SELECT COUNT(id) AS Count FROM ` + dialect.Quote("user")
|
||||
if _, err := sess.SQL(rawSQL).Get(&stats); err != nil {
|
||||
return fmt.Errorf("could not determine if admin user exists: %w", err)
|
||||
}
|
||||
|
||||
@@ -137,23 +140,27 @@ func (ss *SQLStore) ensureMainOrgAndAdminUser() error {
|
||||
|
||||
// ensure admin user
|
||||
if !ss.Cfg.DisableInitAdminCreation {
|
||||
cmd := models.CreateUserCommand{}
|
||||
cmd.Login = setting.AdminUser
|
||||
cmd.Email = setting.AdminUser + "@localhost"
|
||||
cmd.Password = setting.AdminPassword
|
||||
cmd.IsAdmin = true
|
||||
|
||||
ss.log.Debug("Creating default admin user")
|
||||
cmd := models.CreateUserCommand{
|
||||
Login: ss.Cfg.AdminUser,
|
||||
Email: ss.Cfg.AdminUser + "@localhost",
|
||||
Password: ss.Cfg.AdminPassword,
|
||||
IsAdmin: true,
|
||||
}
|
||||
if err := bus.DispatchCtx(ctx, &cmd); err != nil {
|
||||
return fmt.Errorf("failed to create admin user: %s", err)
|
||||
}
|
||||
|
||||
ss.log.Info("Created default admin", "user", setting.AdminUser)
|
||||
ss.log.Info("Created default admin", "user", ss.Cfg.AdminUser)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ensure default org if default admin user is disabled
|
||||
if err := createDefaultOrg(ctx); err != nil {
|
||||
return errutil.Wrap("Failed to create default organization", err)
|
||||
// ensure default org even if default admin user is disabled
|
||||
if err := inTransactionCtx(ctx, func(sess *DBSession) error {
|
||||
_, err := getOrCreateOrg(sess, mainOrgName)
|
||||
return err
|
||||
}); err != nil {
|
||||
return fmt.Errorf("failed to create default organization: %w", err)
|
||||
}
|
||||
|
||||
ss.log.Info("Created default organization")
|
||||
|
||||
Reference in New Issue
Block a user