Auth: remove org count from signedInUser (#72661)

* tweaks

* remove org count from signedinUser

* remove org count from signedinUser store

* fix broken tests

* restore frontend interface
pull/72671/head
Jo 2 years ago committed by GitHub
parent a0b0d704d9
commit 7d347cd428
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      pkg/api/common_test.go
  2. 13
      pkg/api/index.go
  3. 6
      pkg/api/login_test.go
  4. 4
      pkg/services/authn/authn.go
  5. 1
      pkg/services/authn/authnimpl/sync/user_sync.go
  6. 2
      pkg/services/authn/clients/api_key_test.go
  7. 1
      pkg/services/authn/clients/ext_jwt_test.go
  8. 1
      pkg/services/authn/clients/jwt_test.go
  9. 1
      pkg/services/user/model.go
  10. 1
      pkg/services/user/userimpl/store.go
  11. 87
      pkg/tests/web/index_view_test.go

@ -21,12 +21,14 @@ import (
"github.com/grafana/grafana/pkg/infra/fs" "github.com/grafana/grafana/pkg/infra/fs"
"github.com/grafana/grafana/pkg/infra/remotecache" "github.com/grafana/grafana/pkg/infra/remotecache"
"github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/models/usertoken"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl" "github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
"github.com/grafana/grafana/pkg/services/annotations/annotationstest" "github.com/grafana/grafana/pkg/services/annotations/annotationstest"
"github.com/grafana/grafana/pkg/services/anonymous/anontest" "github.com/grafana/grafana/pkg/services/anonymous/anontest"
"github.com/grafana/grafana/pkg/services/auth/authtest" "github.com/grafana/grafana/pkg/services/auth/authtest"
"github.com/grafana/grafana/pkg/services/auth/jwt" "github.com/grafana/grafana/pkg/services/auth/jwt"
"github.com/grafana/grafana/pkg/services/authn"
"github.com/grafana/grafana/pkg/services/authn/authntest" "github.com/grafana/grafana/pkg/services/authn/authntest"
"github.com/grafana/grafana/pkg/services/contexthandler" "github.com/grafana/grafana/pkg/services/contexthandler"
"github.com/grafana/grafana/pkg/services/contexthandler/authproxy" "github.com/grafana/grafana/pkg/services/contexthandler/authproxy"
@ -177,6 +179,7 @@ type scenarioContext struct {
authInfoService *logintest.AuthInfoServiceFake authInfoService *logintest.AuthInfoServiceFake
dashboardVersionService dashver.Service dashboardVersionService dashver.Service
userService user.Service userService user.Service
ctxHdlr *contexthandler.ContextHandler
} }
func (sc *scenarioContext) exec() { func (sc *scenarioContext) exec() {
@ -208,17 +211,20 @@ func getContextHandler(t *testing.T, cfg *setting.Cfg) *contexthandler.ContextHa
ctxHdlr := contexthandler.ProvideService(cfg, userAuthTokenSvc, authJWTSvc, ctxHdlr := contexthandler.ProvideService(cfg, userAuthTokenSvc, authJWTSvc,
remoteCacheSvc, renderSvc, sqlStore, tracer, authProxy, loginService, nil, remoteCacheSvc, renderSvc, sqlStore, tracer, authProxy, loginService, nil,
authenticator, usertest.NewUserServiceFake(), orgtest.NewOrgServiceFake(), authenticator, usertest.NewUserServiceFake(), orgtest.NewOrgServiceFake(),
nil, featuremgmt.WithFeatures(), &authntest.FakeService{}, &anontest.FakeAnonymousSessionService{}) nil, featuremgmt.WithFeatures(), &authntest.FakeService{
ExpectedIdentity: &authn.Identity{OrgID: 1, ID: "user:1", SessionToken: &usertoken.UserToken{}}}, &anontest.FakeAnonymousSessionService{})
return ctxHdlr return ctxHdlr
} }
func setupScenarioContext(t *testing.T, url string) *scenarioContext { func setupScenarioContext(t *testing.T, url string) *scenarioContext {
cfg := setting.NewCfg() cfg := setting.NewCfg()
ctxHdlr := getContextHandler(t, cfg)
sc := &scenarioContext{ sc := &scenarioContext{
url: url, url: url,
t: t, t: t,
cfg: cfg, cfg: cfg,
ctxHdlr: ctxHdlr,
} }
viewsPath, err := filepath.Abs("../../public/views") viewsPath, err := filepath.Abs("../../public/views")
require.NoError(t, err) require.NoError(t, err)
@ -228,7 +234,7 @@ func setupScenarioContext(t *testing.T, url string) *scenarioContext {
sc.m = web.New() sc.m = web.New()
sc.m.UseMiddleware(web.Renderer(viewsPath, "[[", "]]")) sc.m.UseMiddleware(web.Renderer(viewsPath, "[[", "]]"))
sc.m.Use(getContextHandler(t, cfg).Middleware) sc.m.Use(ctxHdlr.Middleware)
return sc return sc
} }

@ -17,6 +17,7 @@ import (
"github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/login" "github.com/grafana/grafana/pkg/services/login"
"github.com/grafana/grafana/pkg/services/org"
pref "github.com/grafana/grafana/pkg/services/preference" pref "github.com/grafana/grafana/pkg/services/preference"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
@ -80,6 +81,16 @@ func (hs *HTTPServer) setIndexViewData(c *contextmodel.ReqContext) (*dtos.IndexV
theme := hs.getThemeForIndexData(prefs.Theme, c.Query("theme")) theme := hs.getThemeForIndexData(prefs.Theme, c.Query("theme"))
userOrgCount := 1
userOrgs, err := hs.orgService.GetUserOrgList(c.Req.Context(), &org.GetUserOrgListQuery{UserID: c.UserID})
if err != nil {
hs.log.Error("Failed to count user orgs", "error", err)
}
if len(userOrgs) > 0 {
userOrgCount = len(userOrgs)
}
hasAccess := ac.HasAccess(hs.AccessControl, c) hasAccess := ac.HasAccess(hs.AccessControl, c)
hasEditPerm := hasAccess(ac.EvalAny(ac.EvalPermission(dashboards.ActionDashboardsCreate), ac.EvalPermission(dashboards.ActionFoldersCreate))) hasEditPerm := hasAccess(ac.EvalAny(ac.EvalPermission(dashboards.ActionDashboardsCreate), ac.EvalPermission(dashboards.ActionFoldersCreate)))
@ -90,10 +101,10 @@ func (hs *HTTPServer) setIndexViewData(c *contextmodel.ReqContext) (*dtos.IndexV
Login: c.Login, Login: c.Login,
Email: c.Email, Email: c.Email,
Name: c.Name, Name: c.Name,
OrgCount: c.OrgCount,
OrgId: c.OrgID, OrgId: c.OrgID,
OrgName: c.OrgName, OrgName: c.OrgName,
OrgRole: c.OrgRole, OrgRole: c.OrgRole,
OrgCount: userOrgCount,
GravatarUrl: dtos.GetGravatarUrl(c.Email), GravatarUrl: dtos.GetGravatarUrl(c.Email),
IsGrafanaAdmin: c.IsGrafanaAdmin, IsGrafanaAdmin: c.IsGrafanaAdmin,
Theme: theme.ID, Theme: theme.ID,

@ -595,18 +595,22 @@ func (r *loginHookTest) LoginHook(loginInfo *loginservice.LoginInfo, req *contex
r.info = loginInfo r.info = loginInfo
} }
// TOREMOVE: remove with context handler auth
func TestLoginPostRunLokingHook(t *testing.T) { func TestLoginPostRunLokingHook(t *testing.T) {
sc := setupScenarioContext(t, "/login") sc := setupScenarioContext(t, "/login")
hookService := &hooks.HooksService{} hookService := &hooks.HooksService{}
hs := &HTTPServer{ hs := &HTTPServer{
log: log.New("test"), log: log.New("test"),
Cfg: setting.NewCfg(), Cfg: sc.cfg,
License: &licensing.OSSLicensingService{}, License: &licensing.OSSLicensingService{},
AuthTokenService: authtest.NewFakeUserAuthTokenService(), AuthTokenService: authtest.NewFakeUserAuthTokenService(),
Features: featuremgmt.WithFeatures(), Features: featuremgmt.WithFeatures(),
HooksService: hookService, HooksService: hookService,
authnService: sc.ctxHdlr.AuthnService,
} }
sc.cfg.AuthBrokerEnabled = false
sc.defaultHandler = routing.Wrap(func(c *contextmodel.ReqContext) response.Response { sc.defaultHandler = routing.Wrap(func(c *contextmodel.ReqContext) response.Response {
c.Req.Header.Set("Content-Type", "application/json") c.Req.Header.Set("Content-Type", "application/json")
c.Req.Body = io.NopCloser(bytes.NewBufferString(`{"user":"admin","password":"admin"}`)) c.Req.Body = io.NopCloser(bytes.NewBufferString(`{"user":"admin","password":"admin"}`))

@ -180,8 +180,6 @@ const (
type Identity struct { type Identity struct {
// OrgID is the active organization for the entity. // OrgID is the active organization for the entity.
OrgID int64 OrgID int64
// OrgCount is the number of organizations the entity is a member of.
OrgCount int
// OrgName is the name of the active organization. // OrgName is the name of the active organization.
OrgName string OrgName string
// OrgRoles is the list of organizations the entity is a member of and their roles. // OrgRoles is the list of organizations the entity is a member of and their roles.
@ -271,7 +269,6 @@ func (i *Identity) SignedInUser() *user.SignedInUser {
Name: i.Name, Name: i.Name,
Email: i.Email, Email: i.Email,
AuthenticatedBy: i.AuthenticatedBy, AuthenticatedBy: i.AuthenticatedBy,
OrgCount: i.OrgCount,
IsGrafanaAdmin: isGrafanaAdmin, IsGrafanaAdmin: isGrafanaAdmin,
IsAnonymous: i.IsAnonymous, IsAnonymous: i.IsAnonymous,
IsDisabled: i.IsDisabled, IsDisabled: i.IsDisabled,
@ -320,7 +317,6 @@ func IdentityFromSignedInUser(id string, usr *user.SignedInUser, params ClientPa
Name: usr.Name, Name: usr.Name,
Email: usr.Email, Email: usr.Email,
AuthenticatedBy: authenticatedBy, AuthenticatedBy: authenticatedBy,
OrgCount: usr.OrgCount,
IsGrafanaAdmin: &usr.IsGrafanaAdmin, IsGrafanaAdmin: &usr.IsGrafanaAdmin,
IsDisabled: usr.IsDisabled, IsDisabled: usr.IsDisabled,
HelpFlags1: usr.HelpFlags1, HelpFlags1: usr.HelpFlags1,

@ -387,7 +387,6 @@ func syncSignedInUserToIdentity(usr *user.SignedInUser, identity *authn.Identity
identity.Email = usr.Email identity.Email = usr.Email
identity.OrgID = usr.OrgID identity.OrgID = usr.OrgID
identity.OrgName = usr.OrgName identity.OrgName = usr.OrgName
identity.OrgCount = usr.OrgCount
identity.OrgRoles = map[int64]org.RoleType{identity.OrgID: usr.OrgRole} identity.OrgRoles = map[int64]org.RoleType{identity.OrgID: usr.OrgRole}
identity.HelpFlags1 = usr.HelpFlags1 identity.HelpFlags1 = usr.HelpFlags1
identity.Teams = usr.Teams identity.Teams = usr.Teams

@ -76,14 +76,12 @@ func TestAPIKey_Authenticate(t *testing.T) {
UserID: 1, UserID: 1,
OrgID: 1, OrgID: 1,
IsServiceAccount: true, IsServiceAccount: true,
OrgCount: 1,
OrgRole: org.RoleViewer, OrgRole: org.RoleViewer,
Name: "test", Name: "test",
}, },
expectedIdentity: &authn.Identity{ expectedIdentity: &authn.Identity{
ID: "service-account:1", ID: "service-account:1",
OrgID: 1, OrgID: 1,
OrgCount: 1,
Name: "test", Name: "test",
OrgRoles: map[int64]org.RoleType{1: org.RoleViewer}, OrgRoles: map[int64]org.RoleType{1: org.RoleViewer},
IsGrafanaAdmin: boolPtr(false), IsGrafanaAdmin: boolPtr(false),

@ -151,7 +151,6 @@ func TestExtendedJWT_Authenticate(t *testing.T) {
}, },
want: &authn.Identity{ want: &authn.Identity{
OrgID: 1, OrgID: 1,
OrgCount: 0,
OrgName: "", OrgName: "",
OrgRoles: map[int64]roletype.RoleType{1: roletype.RoleAdmin}, OrgRoles: map[int64]roletype.RoleType{1: roletype.RoleAdmin},
ID: "user:2", ID: "user:2",

@ -36,7 +36,6 @@ func TestAuthenticateJWT(t *testing.T) {
jwtHeaderName := "X-Forwarded-User" jwtHeaderName := "X-Forwarded-User"
wantID := &authn.Identity{ wantID := &authn.Identity{
OrgID: 0, OrgID: 0,
OrgCount: 0,
OrgName: "", OrgName: "",
OrgRoles: map[int64]roletype.RoleType{1: roletype.RoleAdmin}, OrgRoles: map[int64]roletype.RoleType{1: roletype.RoleAdmin},
ID: "", ID: "",

@ -211,7 +211,6 @@ type SignedInUser struct {
AuthenticatedBy string AuthenticatedBy string
ApiKeyID int64 `xorm:"api_key_id"` ApiKeyID int64 `xorm:"api_key_id"`
IsServiceAccount bool `xorm:"is_service_account"` IsServiceAccount bool `xorm:"is_service_account"`
OrgCount int
IsGrafanaAdmin bool IsGrafanaAdmin bool
IsAnonymous bool IsAnonymous bool
IsDisabled bool IsDisabled bool

@ -396,7 +396,6 @@ func (ss *sqlStore) GetSignedInUser(ctx context.Context, query *user.GetSignedIn
u.is_disabled as is_disabled, u.is_disabled as is_disabled,
u.help_flags1 as help_flags1, u.help_flags1 as help_flags1,
u.last_seen_at as last_seen_at, u.last_seen_at as last_seen_at,
(SELECT COUNT(*) FROM org_user where org_user.user_id = u.id) as org_count,
org.name as org_name, org.name as org_name,
org_user.role as org_role, org_user.role as org_role,
org.id as org_id, org.id as org_id,

@ -117,56 +117,53 @@ func TestIntegrationIndexViewAnalytics(t *testing.T) {
}, },
} }
// can be removed once ff is removed for _, tc := range testCases {
authBrokerStates := map[string]bool{"none": false, "authnService": true} t.Run(tc.name, func(t *testing.T) {
grafDir, cfgPath := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
for k, enabled := range authBrokerStates { AuthBrokerEnabled: true,
for _, tc := range testCases { })
t.Run(tc.name+"-"+k, func(t *testing.T) { addr, store := testinfra.StartGrafana(t, grafDir, cfgPath)
grafDir, cfgPath := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{AuthBrokerEnabled: enabled}) createdUser := testinfra.CreateUser(t, store, user.CreateUserCommand{
addr, store := testinfra.StartGrafana(t, grafDir, cfgPath) Login: "admin",
createdUser := testinfra.CreateUser(t, store, user.CreateUserCommand{ Password: "admin",
Login: "admin", Email: "admin@grafana.com",
Password: "admin", OrgID: 1,
Email: "admin@grafana.com", })
OrgID: 1,
})
secretsService := secretsManager.SetupTestService(t, database.ProvideSecretsStore(store)) secretsService := secretsManager.SetupTestService(t, database.ProvideSecretsStore(store))
authInfoStore := databaseAuthInfo.ProvideAuthInfoStore(store, secretsService, nil) authInfoStore := databaseAuthInfo.ProvideAuthInfoStore(store, secretsService, nil)
// insert user_auth relationship // insert user_auth relationship
err := authInfoStore.SetAuthInfo(context.Background(), &login.SetAuthInfoCommand{
AuthModule: tc.authModule,
AuthId: tc.setID,
UserId: createdUser.ID,
})
require.NoError(t, err)
if tc.secondModule != "" {
// wait for the user_auth relationship to be inserted. TOFIX: this is a hack
time.Sleep(1 * time.Second)
err := authInfoStore.SetAuthInfo(context.Background(), &login.SetAuthInfoCommand{ err := authInfoStore.SetAuthInfo(context.Background(), &login.SetAuthInfoCommand{
AuthModule: tc.authModule, AuthModule: tc.secondModule,
AuthId: tc.setID, AuthId: tc.secondID,
UserId: createdUser.ID, UserId: createdUser.ID,
}) })
require.NoError(t, err) require.NoError(t, err)
if tc.secondModule != "" { }
// wait for the user_auth relationship to be inserted. TOFIX: this is a hack
time.Sleep(1 * time.Second) // nolint:bodyclose
err := authInfoStore.SetAuthInfo(context.Background(), &login.SetAuthInfoCommand{ response, html := makeRequest(t, addr, "admin", "admin")
AuthModule: tc.secondModule, assert.Equal(t, http.StatusOK, response.StatusCode)
AuthId: tc.secondID,
UserId: createdUser.ID, // parse User.Analytics HTML view into user.AnalyticsSettings model
}) parsedHTML := strings.Split(html, "analytics\":")[1]
require.NoError(t, err) parsedHTML = strings.Split(parsedHTML, "},\n")[0]
}
var analyticsSettings user.AnalyticsSettings
// nolint:bodyclose require.NoError(t, json.Unmarshal([]byte(parsedHTML), &analyticsSettings))
response, html := makeRequest(t, addr, "admin", "admin")
assert.Equal(t, http.StatusOK, response.StatusCode) require.NotEmpty(t, analyticsSettings.IntercomIdentifier)
require.Equal(t, tc.wantIdentifier, analyticsSettings.Identifier)
// parse User.Analytics HTML view into user.AnalyticsSettings model })
parsedHTML := strings.Split(html, "analytics\":")[1]
parsedHTML = strings.Split(parsedHTML, "},\n")[0]
var analyticsSettings user.AnalyticsSettings
require.NoError(t, json.Unmarshal([]byte(parsedHTML), &analyticsSettings))
require.NotEmpty(t, analyticsSettings.IntercomIdentifier)
require.Equal(t, tc.wantIdentifier, analyticsSettings.Identifier)
})
}
} }
} }

Loading…
Cancel
Save