Chore: Remove GetSignedInUserWithCacheCtx from store interface (#53734)

* Remove delete suer from store interface

* Remove get signed in user with cache ctx from store interface

* Support options when setting up access control tests

* Fix broken tests

* Fix lint

* Add user fake to middleware

* Fix middleware tests, remove usertest being initialised twice

Co-authored-by: Karl Persson <kalle.persson@grafana.com>
This commit is contained in:
idafurjes
2022-08-16 16:08:59 +02:00
committed by GitHub
parent f3085b1cac
commit fa2e74cd6e
16 changed files with 119 additions and 97 deletions

View File

@ -68,7 +68,7 @@ func (hs *HTTPServer) registerRoutes() {
reqSnapshotPublicModeOrSignedIn := middleware.SnapshotPublicModeOrSignedIn(hs.Cfg) reqSnapshotPublicModeOrSignedIn := middleware.SnapshotPublicModeOrSignedIn(hs.Cfg)
redirectFromLegacyPanelEditURL := middleware.RedirectFromLegacyPanelEditURL(hs.Cfg) redirectFromLegacyPanelEditURL := middleware.RedirectFromLegacyPanelEditURL(hs.Cfg)
authorize := ac.Middleware(hs.AccessControl) authorize := ac.Middleware(hs.AccessControl)
authorizeInOrg := ac.AuthorizeInOrgMiddleware(hs.AccessControl, hs.SQLStore) authorizeInOrg := ac.AuthorizeInOrgMiddleware(hs.AccessControl, hs.userService)
quota := middleware.Quota(hs.QuotaService) quota := middleware.Quota(hs.QuotaService)
r := hs.RouteRegister r := hs.RouteRegister

View File

@ -285,6 +285,8 @@ type accessControlScenarioContext struct {
// acmock is an accesscontrol mock used to fake users rights. // acmock is an accesscontrol mock used to fake users rights.
acmock *accesscontrolmock.Mock acmock *accesscontrolmock.Mock
usermock *usertest.FakeUserService
// db is a test database initialized with InitTestDB // db is a test database initialized with InitTestDB
db sqlstore.Store db sqlstore.Store
@ -341,16 +343,19 @@ func setupSimpleHTTPServer(features *featuremgmt.FeatureManager) *HTTPServer {
} }
} }
func setupHTTPServer(t *testing.T, useFakeAccessControl bool) accessControlScenarioContext { func setupHTTPServer(t *testing.T, useFakeAccessControl bool, options ...APITestServerOption) accessControlScenarioContext {
return setupHTTPServerWithCfg(t, useFakeAccessControl, setting.NewCfg()) return setupHTTPServerWithCfg(t, useFakeAccessControl, setting.NewCfg(), options...)
} }
func setupHTTPServerWithCfg(t *testing.T, useFakeAccessControl bool, cfg *setting.Cfg) accessControlScenarioContext { func setupHTTPServerWithCfg(t *testing.T, useFakeAccessControl bool, cfg *setting.Cfg, options ...APITestServerOption) accessControlScenarioContext {
db := sqlstore.InitTestDB(t, sqlstore.InitTestDBOpt{}) db := sqlstore.InitTestDB(t, sqlstore.InitTestDBOpt{})
return setupHTTPServerWithCfgDb(t, useFakeAccessControl, cfg, db, db, featuremgmt.WithFeatures()) return setupHTTPServerWithCfgDb(t, useFakeAccessControl, cfg, db, db, featuremgmt.WithFeatures(), options...)
} }
func setupHTTPServerWithCfgDb(t *testing.T, useFakeAccessControl bool, cfg *setting.Cfg, db *sqlstore.SQLStore, store sqlstore.Store, features *featuremgmt.FeatureManager) accessControlScenarioContext { func setupHTTPServerWithCfgDb(
t *testing.T, useFakeAccessControl bool, cfg *setting.Cfg, db *sqlstore.SQLStore,
store sqlstore.Store, features *featuremgmt.FeatureManager, options ...APITestServerOption,
) accessControlScenarioContext {
t.Helper() t.Helper()
db.Cfg.RBACEnabled = cfg.RBACEnabled db.Cfg.RBACEnabled = cfg.RBACEnabled
@ -400,6 +405,10 @@ func setupHTTPServerWithCfgDb(t *testing.T, useFakeAccessControl bool, cfg *sett
userService: userMock, userService: userMock,
} }
for _, o := range options {
o(hs)
}
require.NoError(t, hs.declareFixedRoles()) require.NoError(t, hs.declareFixedRoles())
require.NoError(t, hs.AccessControl.(accesscontrol.RoleRegistry).RegisterFixedRoles(context.Background())) require.NoError(t, hs.AccessControl.(accesscontrol.RoleRegistry).RegisterFixedRoles(context.Background()))
@ -428,6 +437,7 @@ func setupHTTPServerWithCfgDb(t *testing.T, useFakeAccessControl bool, cfg *sett
db: db, db: db,
cfg: cfg, cfg: cfg,
dashboardsStore: dashboardsStore, dashboardsStore: dashboardsStore,
usermock: userMock,
} }
} }

View File

@ -1,7 +1,6 @@
package api package api
import ( import (
"context"
"fmt" "fmt"
"net/http" "net/http"
"strings" "strings"
@ -10,10 +9,8 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
) )
@ -191,18 +188,17 @@ func TestAPIEndpoint_PutCurrentOrgAddress_AccessControl(t *testing.T) {
// `/api/orgs/` endpoints test // `/api/orgs/` endpoints test
// setupOrgsDBForAccessControlTests stores users and create specified number of orgs // setupOrgsDBForAccessControlTests creates orgs up until orgID and fake user as member of org
func setupOrgsDBForAccessControlTests(t *testing.T, db sqlstore.Store, usr user.SignedInUser, orgsCount int) { func setupOrgsDBForAccessControlTests(t *testing.T, db sqlstore.Store, c accessControlScenarioContext, orgID int64) {
t.Helper() t.Helper()
setInitCtxSignedInViewer(c.initCtx)
_, err := db.CreateUser(context.Background(), user.CreateUserCommand{Email: usr.Email, SkipOrgSetup: true, Login: usr.Login}) u := *c.initCtx.SignedInUser
require.NoError(t, err) u.OrgID = orgID
c.usermock.ExpectedSignedInUser = &u
// Create `orgsCount` orgs // Create `orgsCount` orgs
for i := 1; i <= orgsCount; i++ { for i := 1; i <= int(orgID); i++ {
_, err = db.CreateOrgWithMember(fmt.Sprintf("TestOrg%v", i), 0) _, err := db.CreateOrgWithMember(fmt.Sprintf("TestOrg%v", i), 0)
require.NoError(t, err)
err = db.AddOrgUser(context.Background(), &models.AddOrgUserCommand{LoginOrEmail: usr.Login, Role: usr.OrgRole, OrgId: int64(i), UserId: usr.UserID})
require.NoError(t, err) require.NoError(t, err)
} }
} }
@ -240,7 +236,7 @@ func TestAPIEndpoint_CreateOrgs_AccessControl(t *testing.T) {
sc := setupHTTPServer(t, true) sc := setupHTTPServer(t, true)
setInitCtxSignedInViewer(sc.initCtx) setInitCtxSignedInViewer(sc.initCtx)
setupOrgsDBForAccessControlTests(t, sc.db, *sc.initCtx.SignedInUser, 0) setupOrgsDBForAccessControlTests(t, sc.db, sc, 0)
input := strings.NewReader(fmt.Sprintf(testCreateOrgCmd, 2)) input := strings.NewReader(fmt.Sprintf(testCreateOrgCmd, 2))
t.Run("AccessControl allows creating Orgs with correct permissions", func(t *testing.T) { t.Run("AccessControl allows creating Orgs with correct permissions", func(t *testing.T) {
@ -263,7 +259,7 @@ func TestAPIEndpoint_DeleteOrgs_LegacyAccessControl(t *testing.T) {
sc := setupHTTPServerWithCfg(t, true, cfg) sc := setupHTTPServerWithCfg(t, true, cfg)
setInitCtxSignedInViewer(sc.initCtx) setInitCtxSignedInViewer(sc.initCtx)
setupOrgsDBForAccessControlTests(t, sc.db, *sc.initCtx.SignedInUser, 2) setupOrgsDBForAccessControlTests(t, sc.db, sc, 2)
t.Run("Viewer cannot delete Orgs", func(t *testing.T) { t.Run("Viewer cannot delete Orgs", func(t *testing.T) {
response := callAPI(sc.server, http.MethodDelete, fmt.Sprintf(deleteOrgsURL, 2), nil, t) response := callAPI(sc.server, http.MethodDelete, fmt.Sprintf(deleteOrgsURL, 2), nil, t)
@ -279,9 +275,7 @@ func TestAPIEndpoint_DeleteOrgs_LegacyAccessControl(t *testing.T) {
func TestAPIEndpoint_DeleteOrgs_AccessControl(t *testing.T) { func TestAPIEndpoint_DeleteOrgs_AccessControl(t *testing.T) {
sc := setupHTTPServer(t, true) sc := setupHTTPServer(t, true)
setInitCtxSignedInViewer(sc.initCtx) setupOrgsDBForAccessControlTests(t, sc.db, sc, 2)
setupOrgsDBForAccessControlTests(t, sc.db, *sc.initCtx.SignedInUser, 2)
t.Run("AccessControl prevents deleting Orgs with incorrect permissions", func(t *testing.T) { t.Run("AccessControl prevents deleting Orgs with incorrect permissions", func(t *testing.T) {
setAccessControlPermissions(sc.acmock, []accesscontrol.Permission{{Action: "orgs:invalid"}}, 2) setAccessControlPermissions(sc.acmock, []accesscontrol.Permission{{Action: "orgs:invalid"}}, 2)
@ -346,7 +340,7 @@ func TestAPIEndpoint_GetOrg_LegacyAccessControl(t *testing.T) {
setInitCtxSignedInViewer(sc.initCtx) setInitCtxSignedInViewer(sc.initCtx)
// Create two orgs, to fetch another one than the logged in one // Create two orgs, to fetch another one than the logged in one
setupOrgsDBForAccessControlTests(t, sc.db, *sc.initCtx.SignedInUser, 2) setupOrgsDBForAccessControlTests(t, sc.db, sc, 2)
t.Run("Viewer cannot view another Org", func(t *testing.T) { t.Run("Viewer cannot view another Org", func(t *testing.T) {
response := callAPI(sc.server, http.MethodGet, fmt.Sprintf(getOrgsURL, 2), nil, t) response := callAPI(sc.server, http.MethodGet, fmt.Sprintf(getOrgsURL, 2), nil, t)
@ -365,7 +359,7 @@ func TestAPIEndpoint_GetOrg_AccessControl(t *testing.T) {
setInitCtxSignedInViewer(sc.initCtx) setInitCtxSignedInViewer(sc.initCtx)
// Create two orgs, to fetch another one than the logged in one // Create two orgs, to fetch another one than the logged in one
setupOrgsDBForAccessControlTests(t, sc.db, *sc.initCtx.SignedInUser, 2) setupOrgsDBForAccessControlTests(t, sc.db, sc, 2)
t.Run("AccessControl allows viewing another org with correct permissions", func(t *testing.T) { t.Run("AccessControl allows viewing another org with correct permissions", func(t *testing.T) {
setAccessControlPermissions(sc.acmock, []accesscontrol.Permission{{Action: ActionOrgsRead}}, 2) setAccessControlPermissions(sc.acmock, []accesscontrol.Permission{{Action: ActionOrgsRead}}, 2)
@ -391,7 +385,7 @@ func TestAPIEndpoint_GetOrgByName_LegacyAccessControl(t *testing.T) {
setInitCtxSignedInViewer(sc.initCtx) setInitCtxSignedInViewer(sc.initCtx)
// Create two orgs, to fetch another one than the logged in one // Create two orgs, to fetch another one than the logged in one
setupOrgsDBForAccessControlTests(t, sc.db, *sc.initCtx.SignedInUser, 2) setupOrgsDBForAccessControlTests(t, sc.db, sc, 2)
t.Run("Viewer cannot view another Org", func(t *testing.T) { t.Run("Viewer cannot view another Org", func(t *testing.T) {
response := callAPI(sc.server, http.MethodGet, fmt.Sprintf(getOrgsByNameURL, "TestOrg2"), nil, t) response := callAPI(sc.server, http.MethodGet, fmt.Sprintf(getOrgsByNameURL, "TestOrg2"), nil, t)
@ -410,7 +404,7 @@ func TestAPIEndpoint_GetOrgByName_AccessControl(t *testing.T) {
setInitCtxSignedInViewer(sc.initCtx) setInitCtxSignedInViewer(sc.initCtx)
// Create two orgs, to fetch another one than the logged in one // Create two orgs, to fetch another one than the logged in one
setupOrgsDBForAccessControlTests(t, sc.db, *sc.initCtx.SignedInUser, 2) setupOrgsDBForAccessControlTests(t, sc.db, sc, 2)
t.Run("AccessControl allows viewing another org with correct permissions", func(t *testing.T) { t.Run("AccessControl allows viewing another org with correct permissions", func(t *testing.T) {
setAccessControlPermissions(sc.acmock, []accesscontrol.Permission{{Action: ActionOrgsRead}}, accesscontrol.GlobalOrgID) setAccessControlPermissions(sc.acmock, []accesscontrol.Permission{{Action: ActionOrgsRead}}, accesscontrol.GlobalOrgID)
@ -431,7 +425,7 @@ func TestAPIEndpoint_PutOrg_LegacyAccessControl(t *testing.T) {
setInitCtxSignedInViewer(sc.initCtx) setInitCtxSignedInViewer(sc.initCtx)
// Create two orgs, to update another one than the logged in one // Create two orgs, to update another one than the logged in one
setupOrgsDBForAccessControlTests(t, sc.db, *sc.initCtx.SignedInUser, 2) setupOrgsDBForAccessControlTests(t, sc.db, sc, 2)
input := strings.NewReader(testUpdateOrgNameForm) input := strings.NewReader(testUpdateOrgNameForm)
@ -452,7 +446,7 @@ func TestAPIEndpoint_PutOrg_AccessControl(t *testing.T) {
setInitCtxSignedInViewer(sc.initCtx) setInitCtxSignedInViewer(sc.initCtx)
// Create two orgs, to update another one than the logged in one // Create two orgs, to update another one than the logged in one
setupOrgsDBForAccessControlTests(t, sc.db, *sc.initCtx.SignedInUser, 2) setupOrgsDBForAccessControlTests(t, sc.db, sc, 2)
input := strings.NewReader(testUpdateOrgNameForm) input := strings.NewReader(testUpdateOrgNameForm)
t.Run("AccessControl allows updating another org with correct permissions", func(t *testing.T) { t.Run("AccessControl allows updating another org with correct permissions", func(t *testing.T) {
@ -481,7 +475,7 @@ func TestAPIEndpoint_PutOrgAddress_LegacyAccessControl(t *testing.T) {
setInitCtxSignedInViewer(sc.initCtx) setInitCtxSignedInViewer(sc.initCtx)
// Create two orgs, to update another one than the logged in one // Create two orgs, to update another one than the logged in one
setupOrgsDBForAccessControlTests(t, sc.db, *sc.initCtx.SignedInUser, 2) setupOrgsDBForAccessControlTests(t, sc.db, sc, 2)
input := strings.NewReader(testUpdateOrgAddressForm) input := strings.NewReader(testUpdateOrgAddressForm)
@ -502,7 +496,7 @@ func TestAPIEndpoint_PutOrgAddress_AccessControl(t *testing.T) {
setInitCtxSignedInViewer(sc.initCtx) setInitCtxSignedInViewer(sc.initCtx)
// Create two orgs, to update another one than the logged in one // Create two orgs, to update another one than the logged in one
setupOrgsDBForAccessControlTests(t, sc.db, *sc.initCtx.SignedInUser, 2) setupOrgsDBForAccessControlTests(t, sc.db, sc, 2)
input := strings.NewReader(testUpdateOrgAddressForm) input := strings.NewReader(testUpdateOrgAddressForm)
t.Run("AccessControl allows updating another org address with correct permissions", func(t *testing.T) { t.Run("AccessControl allows updating another org address with correct permissions", func(t *testing.T) {

View File

@ -21,7 +21,7 @@ import (
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore" "github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
"github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/usertest" "github.com/grafana/grafana/pkg/services/user/userimpl"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util" "github.com/grafana/grafana/pkg/util"
) )
@ -349,7 +349,12 @@ func TestGetOrgUsersAPIEndpoint_AccessControlMetadata(t *testing.T) {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
cfg := setting.NewCfg() cfg := setting.NewCfg()
cfg.RBACEnabled = tc.enableAccessControl cfg.RBACEnabled = tc.enableAccessControl
sc := setupHTTPServerWithCfg(t, false, cfg) sc := setupHTTPServerWithCfg(t, false, cfg, func(hs *HTTPServer) {
hs.userService = userimpl.ProvideService(
hs.SQLStore, nil, nil, nil, nil,
nil, nil, nil, nil, nil, hs.SQLStore.(*sqlstore.SQLStore),
)
})
setupOrgUsersDBForAccessControlTests(t, sc.db) setupOrgUsersDBForAccessControlTests(t, sc.db)
setInitCtxSignedInUser(sc.initCtx, tc.user) setInitCtxSignedInUser(sc.initCtx, tc.user)
@ -448,9 +453,14 @@ func TestGetOrgUsersAPIEndpoint_AccessControl(t *testing.T) {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
cfg := setting.NewCfg() cfg := setting.NewCfg()
cfg.RBACEnabled = tc.enableAccessControl cfg.RBACEnabled = tc.enableAccessControl
sc := setupHTTPServerWithCfg(t, false, cfg) sc := setupHTTPServerWithCfg(t, false, cfg, func(hs *HTTPServer) {
setupOrgUsersDBForAccessControlTests(t, sc.db) hs.userService = userimpl.ProvideService(
hs.SQLStore, nil, nil, nil, nil,
nil, nil, nil, nil, nil, hs.SQLStore.(*sqlstore.SQLStore),
)
})
setInitCtxSignedInUser(sc.initCtx, tc.user) setInitCtxSignedInUser(sc.initCtx, tc.user)
setupOrgUsersDBForAccessControlTests(t, sc.db)
// Perform test // Perform test
response := callAPI(sc.server, http.MethodGet, fmt.Sprintf(url, tc.targetOrg), nil, t) response := callAPI(sc.server, http.MethodGet, fmt.Sprintf(url, tc.targetOrg), nil, t)
@ -548,13 +558,12 @@ func TestPostOrgUsersAPIEndpoint_AccessControl(t *testing.T) {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
cfg := setting.NewCfg() cfg := setting.NewCfg()
cfg.RBACEnabled = tc.enableAccessControl cfg.RBACEnabled = tc.enableAccessControl
sc := setupHTTPServerWithCfg(t, false, cfg) sc := setupHTTPServerWithCfg(t, false, cfg, func(hs *HTTPServer) {
userService := usertest.NewUserServiceFake() hs.userService = userimpl.ProvideService(
userService.ExpectedUser = &user.User{ID: 2} hs.SQLStore, nil, nil, nil, nil,
sc.hs.userService = userService nil, nil, nil, nil, nil, hs.SQLStore.(*sqlstore.SQLStore),
mockStore := mockstore.NewSQLStoreMock() )
mockStore.ExpectedUser = &user.User{ID: 2} })
sc.hs.SQLStore = mockStore
setupOrgUsersDBForAccessControlTests(t, sc.db) setupOrgUsersDBForAccessControlTests(t, sc.db)
setInitCtxSignedInUser(sc.initCtx, tc.user) setInitCtxSignedInUser(sc.initCtx, tc.user)
@ -674,10 +683,12 @@ func TestOrgUsersAPIEndpointWithSetPerms_AccessControl(t *testing.T) {
for _, test := range tests { for _, test := range tests {
t.Run(test.desc, func(t *testing.T) { t.Run(test.desc, func(t *testing.T) {
sc := setupHTTPServer(t, true) sc := setupHTTPServer(t, true, func(hs *HTTPServer) {
userService := usertest.NewUserServiceFake() hs.userService = userimpl.ProvideService(
userService.ExpectedUser = &user.User{ID: 2} hs.SQLStore, nil, nil, nil, nil,
sc.hs.userService = userService nil, nil, nil, nil, nil, hs.SQLStore.(*sqlstore.SQLStore),
)
})
setInitCtxSignedInViewer(sc.initCtx) setInitCtxSignedInViewer(sc.initCtx)
setupOrgUsersDBForAccessControlTests(t, sc.db) setupOrgUsersDBForAccessControlTests(t, sc.db)
setAccessControlPermissions(sc.acmock, test.permissions, sc.initCtx.OrgID) setAccessControlPermissions(sc.acmock, test.permissions, sc.initCtx.OrgID)
@ -791,7 +802,12 @@ func TestPatchOrgUsersAPIEndpoint_AccessControl(t *testing.T) {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
cfg := setting.NewCfg() cfg := setting.NewCfg()
cfg.RBACEnabled = tc.enableAccessControl cfg.RBACEnabled = tc.enableAccessControl
sc := setupHTTPServerWithCfg(t, false, cfg) sc := setupHTTPServerWithCfg(t, false, cfg, func(hs *HTTPServer) {
hs.userService = userimpl.ProvideService(
hs.SQLStore, nil, nil, nil, nil,
nil, nil, nil, nil, nil, hs.SQLStore.(*sqlstore.SQLStore),
)
})
setupOrgUsersDBForAccessControlTests(t, sc.db) setupOrgUsersDBForAccessControlTests(t, sc.db)
setInitCtxSignedInUser(sc.initCtx, tc.user) setInitCtxSignedInUser(sc.initCtx, tc.user)
@ -913,7 +929,12 @@ func TestDeleteOrgUsersAPIEndpoint_AccessControl(t *testing.T) {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
cfg := setting.NewCfg() cfg := setting.NewCfg()
cfg.RBACEnabled = tc.enableAccessControl cfg.RBACEnabled = tc.enableAccessControl
sc := setupHTTPServerWithCfg(t, false, cfg) sc := setupHTTPServerWithCfg(t, false, cfg, func(hs *HTTPServer) {
hs.userService = userimpl.ProvideService(
hs.SQLStore, nil, nil, nil, nil,
nil, nil, nil, nil, nil, hs.SQLStore.(*sqlstore.SQLStore),
)
})
setupOrgUsersDBForAccessControlTests(t, sc.db) setupOrgUsersDBForAccessControlTests(t, sc.db)
setInitCtxSignedInUser(sc.initCtx, tc.user) setInitCtxSignedInUser(sc.initCtx, tc.user)

View File

@ -38,7 +38,7 @@ func setupDBAndSettingsForAccessControlQuotaTests(t *testing.T, sc accessControl
setting.Quota = sc.hs.Cfg.Quota setting.Quota = sc.hs.Cfg.Quota
// Create two orgs with the context user // Create two orgs with the context user
setupOrgsDBForAccessControlTests(t, sc.db, *sc.initCtx.SignedInUser, 2) setupOrgsDBForAccessControlTests(t, sc.db, sc, 2)
} }
func TestAPIEndpoint_GetCurrentOrgQuotas_LegacyAccessControl(t *testing.T) { func TestAPIEndpoint_GetCurrentOrgQuotas_LegacyAccessControl(t *testing.T) {

View File

@ -44,7 +44,7 @@ func TestMiddlewareBasicAuth(t *testing.T) {
const password = "MyPass" const password = "MyPass"
const orgID int64 = 2 const orgID int64 = 2
sc.mockSQLStore.ExpectedSignedInUser = &user.SignedInUser{OrgID: orgID, UserID: id} sc.userService.ExpectedSignedInUser = &user.SignedInUser{OrgID: orgID, UserID: id}
authHeader := util.GetBasicAuthHeader("myUser", password) authHeader := util.GetBasicAuthHeader("myUser", password)
sc.fakeReq("GET", "/").withAuthorizationHeader(authHeader).exec() sc.fakeReq("GET", "/").withAuthorizationHeader(authHeader).exec()
@ -61,8 +61,8 @@ func TestMiddlewareBasicAuth(t *testing.T) {
encoded, err := util.EncodePassword(password, salt) encoded, err := util.EncodePassword(password, salt)
require.NoError(t, err) require.NoError(t, err)
sc.mockSQLStore.ExpectedUser = &user.User{Password: encoded, ID: id, Salt: salt} sc.userService.ExpectedUser = &user.User{Password: encoded, ID: id, Salt: salt}
sc.mockSQLStore.ExpectedSignedInUser = &user.SignedInUser{UserID: id} sc.userService.ExpectedSignedInUser = &user.SignedInUser{UserID: id}
login.ProvideService(sc.mockSQLStore, &logintest.LoginServiceFake{}, sc.userService) login.ProvideService(sc.mockSQLStore, &logintest.LoginServiceFake{}, sc.userService)
authHeader := util.GetBasicAuthHeader("myUser", password) authHeader := util.GetBasicAuthHeader("myUser", password)
@ -74,7 +74,7 @@ func TestMiddlewareBasicAuth(t *testing.T) {
}, configure) }, configure)
middlewareScenario(t, "Should return error if user is not found", func(t *testing.T, sc *scenarioContext) { middlewareScenario(t, "Should return error if user is not found", func(t *testing.T, sc *scenarioContext) {
sc.mockSQLStore.ExpectedError = user.ErrUserNotFound sc.userService.ExpectedError = user.ErrUserNotFound
sc.fakeReq("GET", "/") sc.fakeReq("GET", "/")
sc.req.SetBasicAuth("user", "password") sc.req.SetBasicAuth("user", "password")
sc.exec() sc.exec()
@ -87,7 +87,7 @@ func TestMiddlewareBasicAuth(t *testing.T) {
}, configure) }, configure)
middlewareScenario(t, "Should return error if user & password do not match", func(t *testing.T, sc *scenarioContext) { middlewareScenario(t, "Should return error if user & password do not match", func(t *testing.T, sc *scenarioContext) {
sc.mockSQLStore.ExpectedError = user.ErrUserNotFound sc.userService.ExpectedError = user.ErrUserNotFound
sc.fakeReq("GET", "/") sc.fakeReq("GET", "/")
sc.req.SetBasicAuth("killa", "gorilla") sc.req.SetBasicAuth("killa", "gorilla")
sc.exec() sc.exec()

View File

@ -46,7 +46,7 @@ func TestMiddlewareJWTAuth(t *testing.T) {
"foo-username": myUsername, "foo-username": myUsername,
}, nil }, nil
} }
sc.mockSQLStore.ExpectedSignedInUser = &user.SignedInUser{UserID: id, OrgID: orgID, Login: myUsername} sc.userService.ExpectedSignedInUser = &user.SignedInUser{UserID: id, OrgID: orgID, Login: myUsername}
sc.fakeReq("GET", "/").withJWTAuthHeader(token).exec() sc.fakeReq("GET", "/").withJWTAuthHeader(token).exec()
assert.Equal(t, verifiedToken, token) assert.Equal(t, verifiedToken, token)
@ -67,7 +67,7 @@ func TestMiddlewareJWTAuth(t *testing.T) {
"foo-email": myEmail, "foo-email": myEmail,
}, nil }, nil
} }
sc.mockSQLStore.ExpectedSignedInUser = &user.SignedInUser{UserID: id, OrgID: orgID, Email: myEmail} sc.userService.ExpectedSignedInUser = &user.SignedInUser{UserID: id, OrgID: orgID, Email: myEmail}
sc.fakeReq("GET", "/").withJWTAuthHeader(token).exec() sc.fakeReq("GET", "/").withJWTAuthHeader(token).exec()
assert.Equal(t, verifiedToken, token) assert.Equal(t, verifiedToken, token)
@ -89,7 +89,7 @@ func TestMiddlewareJWTAuth(t *testing.T) {
"foo-email": myEmail, "foo-email": myEmail,
}, nil }, nil
} }
sc.mockSQLStore.ExpectedError = user.ErrUserNotFound sc.userService.ExpectedError = user.ErrUserNotFound
sc.fakeReq("GET", "/").withJWTAuthHeader(token).exec() sc.fakeReq("GET", "/").withJWTAuthHeader(token).exec()
assert.Equal(t, verifiedToken, token) assert.Equal(t, verifiedToken, token)
@ -108,7 +108,7 @@ func TestMiddlewareJWTAuth(t *testing.T) {
"foo-email": myEmail, "foo-email": myEmail,
}, nil }, nil
} }
sc.mockSQLStore.ExpectedSignedInUser = &user.SignedInUser{UserID: id, OrgID: orgID, Email: myEmail} sc.userService.ExpectedSignedInUser = &user.SignedInUser{UserID: id, OrgID: orgID, Email: myEmail}
sc.fakeReq("GET", "/").withJWTAuthHeader(token).exec() sc.fakeReq("GET", "/").withJWTAuthHeader(token).exec()
assert.Equal(t, verifiedToken, token) assert.Equal(t, verifiedToken, token)

View File

@ -195,7 +195,7 @@ func TestMiddlewareContext(t *testing.T) {
const userID int64 = 12 const userID int64 = 12
sc.withTokenSessionCookie("token") sc.withTokenSessionCookie("token")
sc.mockSQLStore.ExpectedSignedInUser = &user.SignedInUser{OrgID: 2, UserID: userID} sc.userService.ExpectedSignedInUser = &user.SignedInUser{OrgID: 2, UserID: userID}
sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*models.UserToken, error) { sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*models.UserToken, error) {
return &models.UserToken{ return &models.UserToken{
@ -219,7 +219,7 @@ func TestMiddlewareContext(t *testing.T) {
const userID int64 = 12 const userID int64 = 12
sc.withTokenSessionCookie("token") sc.withTokenSessionCookie("token")
sc.mockSQLStore.ExpectedSignedInUser = &user.SignedInUser{OrgID: 2, UserID: userID} sc.userService.ExpectedSignedInUser = &user.SignedInUser{OrgID: 2, UserID: userID}
sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*models.UserToken, error) { sc.userAuthTokenService.LookupTokenProvider = func(ctx context.Context, unhashedToken string) (*models.UserToken, error) {
return &models.UserToken{ return &models.UserToken{
@ -631,12 +631,12 @@ func middlewareScenario(t *testing.T, desc string, fn scenarioFunc, cbs ...func(
sc.mockSQLStore = mockstore.NewSQLStoreMock() sc.mockSQLStore = mockstore.NewSQLStoreMock()
sc.loginService = &loginservice.LoginServiceMock{} sc.loginService = &loginservice.LoginServiceMock{}
sc.userService = usertest.NewUserServiceFake()
sc.apiKeyService = &apikeytest.Service{} sc.apiKeyService = &apikeytest.Service{}
ctxHdlr := getContextHandler(t, cfg, sc.mockSQLStore, sc.loginService, sc.apiKeyService) ctxHdlr := getContextHandler(t, cfg, sc.mockSQLStore, sc.loginService, sc.apiKeyService, sc.userService)
sc.sqlStore = ctxHdlr.SQLStore sc.sqlStore = ctxHdlr.SQLStore
sc.contextHandler = ctxHdlr sc.contextHandler = ctxHdlr
sc.m.Use(ctxHdlr.Middleware) sc.m.Use(ctxHdlr.Middleware)
sc.userService = usertest.NewUserServiceFake()
sc.m.Use(OrgRedirect(sc.cfg, sc.mockSQLStore)) sc.m.Use(OrgRedirect(sc.cfg, sc.mockSQLStore))
sc.userAuthTokenService = ctxHdlr.AuthTokenService.(*auth.FakeUserAuthTokenService) sc.userAuthTokenService = ctxHdlr.AuthTokenService.(*auth.FakeUserAuthTokenService)
@ -666,7 +666,7 @@ func middlewareScenario(t *testing.T, desc string, fn scenarioFunc, cbs ...func(
}) })
} }
func getContextHandler(t *testing.T, cfg *setting.Cfg, mockSQLStore *mockstore.SQLStoreMock, loginService *loginservice.LoginServiceMock, apiKeyService *apikeytest.Service) *contexthandler.ContextHandler { func getContextHandler(t *testing.T, cfg *setting.Cfg, mockSQLStore *mockstore.SQLStoreMock, loginService *loginservice.LoginServiceMock, apiKeyService *apikeytest.Service, userService *usertest.FakeUserService) *contexthandler.ContextHandler {
t.Helper() t.Helper()
if cfg == nil { if cfg == nil {
@ -683,7 +683,7 @@ func getContextHandler(t *testing.T, cfg *setting.Cfg, mockSQLStore *mockstore.S
tracer := tracing.InitializeTracerForTest() tracer := tracing.InitializeTracerForTest()
authProxy := authproxy.ProvideAuthProxy(cfg, remoteCacheSvc, loginService, mockSQLStore) authProxy := authproxy.ProvideAuthProxy(cfg, remoteCacheSvc, loginService, mockSQLStore)
authenticator := &logintest.AuthenticatorFake{ExpectedUser: &user.User{}} authenticator := &logintest.AuthenticatorFake{ExpectedUser: &user.User{}}
return contexthandler.ProvideService(cfg, userAuthTokenSvc, authJWTSvc, remoteCacheSvc, renderSvc, mockSQLStore, tracer, authProxy, loginService, apiKeyService, authenticator, usertest.NewUserServiceFake()) return contexthandler.ProvideService(cfg, userAuthTokenSvc, authJWTSvc, remoteCacheSvc, renderSvc, mockSQLStore, tracer, authProxy, loginService, apiKeyService, authenticator, userService)
} }
type fakeRenderService struct { type fakeRenderService struct {

View File

@ -33,7 +33,7 @@ func rateLimiterScenario(t *testing.T, desc string, rps int, burst int, fn rateL
m := web.New() m := web.New()
m.UseMiddleware(web.Renderer("../../public/views", "[[", "]]")) m.UseMiddleware(web.Renderer("../../public/views", "[[", "]]"))
m.Use(getContextHandler(t, cfg, nil, nil, nil).Middleware) m.Use(getContextHandler(t, cfg, nil, nil, nil, nil).Middleware)
m.Get("/foo", RateLimit(rps, burst, func() time.Time { return currentTime }), defaultHandler) m.Get("/foo", RateLimit(rps, burst, func() time.Time { return currentTime }), defaultHandler)
fn(func() *httptest.ResponseRecorder { fn(func() *httptest.ResponseRecorder {

View File

@ -67,7 +67,7 @@ func recoveryScenario(t *testing.T, desc string, url string, fn scenarioFunc) {
sc.userAuthTokenService = auth.NewFakeUserAuthTokenService() sc.userAuthTokenService = auth.NewFakeUserAuthTokenService()
sc.remoteCacheService = remotecache.NewFakeStore(t) sc.remoteCacheService = remotecache.NewFakeStore(t)
contextHandler := getContextHandler(t, nil, nil, nil, nil) contextHandler := getContextHandler(t, nil, nil, nil, nil, nil)
sc.m.Use(contextHandler.Middleware) sc.m.Use(contextHandler.Middleware)
// mock out gc goroutine // mock out gc goroutine
sc.m.Use(OrgRedirect(cfg, sc.mockSQLStore)) sc.m.Use(OrgRedirect(cfg, sc.mockSQLStore))

View File

@ -92,7 +92,7 @@ func newID() string {
type OrgIDGetter func(c *models.ReqContext) (int64, error) type OrgIDGetter func(c *models.ReqContext) (int64, error)
type userCache interface { type userCache interface {
GetSignedInUserWithCacheCtx(ctx context.Context, query *models.GetSignedInUserQuery) error GetSignedInUserWithCacheCtx(ctx context.Context, query *user.GetSignedInUserQuery) (*user.SignedInUser, error)
} }
func AuthorizeInOrgMiddleware(ac AccessControl, cache userCache) func(web.Handler, OrgIDGetter, Evaluator) web.Handler { func AuthorizeInOrgMiddleware(ac AccessControl, cache userCache) func(web.Handler, OrgIDGetter, Evaluator) web.Handler {
@ -114,15 +114,15 @@ func AuthorizeInOrgMiddleware(ac AccessControl, cache userCache) func(web.Handle
userCopy.OrgName = "" userCopy.OrgName = ""
userCopy.OrgRole = "" userCopy.OrgRole = ""
} else { } else {
query := models.GetSignedInUserQuery{UserId: c.UserID, OrgId: orgID} query := user.GetSignedInUserQuery{UserID: c.UserID, OrgID: orgID}
err := cache.GetSignedInUserWithCacheCtx(c.Req.Context(), &query) queryResult, err := cache.GetSignedInUserWithCacheCtx(c.Req.Context(), &query)
if err != nil { if err != nil {
deny(c, nil, fmt.Errorf("failed to authenticate user in target org: %w", err)) deny(c, nil, fmt.Errorf("failed to authenticate user in target org: %w", err))
return return
} }
userCopy.OrgID = query.Result.OrgID userCopy.OrgID = queryResult.OrgID
userCopy.OrgName = query.Result.OrgName userCopy.OrgName = queryResult.OrgName
userCopy.OrgRole = query.Result.OrgRole userCopy.OrgRole = queryResult.OrgRole
} }
authorize(c, ac, &userCopy, evaluator) authorize(c, ac, &userCopy, evaluator)

View File

@ -33,7 +33,7 @@ func (h *ContextHandler) initContextWithJWT(ctx *models.ReqContext, orgId int64)
return true return true
} }
query := models.GetSignedInUserQuery{OrgId: orgId} query := user.GetSignedInUserQuery{OrgID: orgId}
sub, _ := claims["sub"].(string) sub, _ := claims["sub"].(string)
@ -83,7 +83,7 @@ func (h *ContextHandler) initContextWithJWT(ctx *models.ReqContext, orgId int64)
} }
} }
err = h.SQLStore.GetSignedInUserWithCacheCtx(ctx.Req.Context(), &query) queryResult, err := h.userService.GetSignedInUserWithCacheCtx(ctx.Req.Context(), &query)
if err != nil { if err != nil {
if errors.Is(err, user.ErrUserNotFound) { if errors.Is(err, user.ErrUserNotFound) {
ctx.Logger.Debug( ctx.Logger.Debug(
@ -100,7 +100,7 @@ func (h *ContextHandler) initContextWithJWT(ctx *models.ReqContext, orgId int64)
return true return true
} }
ctx.SignedInUser = query.Result ctx.SignedInUser = queryResult
ctx.IsSignedIn = true ctx.IsSignedIn = true
return true return true

View File

@ -300,13 +300,13 @@ func (h *ContextHandler) initContextWithAPIKey(reqContext *models.ReqContext) bo
//There is a service account attached to the API key //There is a service account attached to the API key
//Use service account linked to API key as the signed in user //Use service account linked to API key as the signed in user
querySignedInUser := models.GetSignedInUserQuery{UserId: *apikey.ServiceAccountId, OrgId: apikey.OrgId} querySignedInUser := user.GetSignedInUserQuery{UserID: *apikey.ServiceAccountId, OrgID: apikey.OrgId}
err := h.SQLStore.GetSignedInUserWithCacheCtx(reqContext.Req.Context(), &querySignedInUser) querySignedInUserResult, err := h.userService.GetSignedInUserWithCacheCtx(reqContext.Req.Context(), &querySignedInUser)
if err != nil { if err != nil {
reqContext.Logger.Error( reqContext.Logger.Error(
"Failed to link API key to service account in", "Failed to link API key to service account in",
"id", querySignedInUser.UserId, "id", querySignedInUser.UserID,
"org", querySignedInUser.OrgId, "org", querySignedInUser.OrgID,
"err", err, "err", err,
) )
reqContext.JsonApiErr(http.StatusInternalServerError, "Unable to link API key to service account", err) reqContext.JsonApiErr(http.StatusInternalServerError, "Unable to link API key to service account", err)
@ -314,13 +314,13 @@ func (h *ContextHandler) initContextWithAPIKey(reqContext *models.ReqContext) bo
} }
// disabled service accounts are not allowed to access the API // disabled service accounts are not allowed to access the API
if querySignedInUser.Result.IsDisabled { if querySignedInUserResult.IsDisabled {
reqContext.JsonApiErr(http.StatusUnauthorized, "Service account is disabled", nil) reqContext.JsonApiErr(http.StatusUnauthorized, "Service account is disabled", nil)
return true return true
} }
reqContext.IsSignedIn = true reqContext.IsSignedIn = true
reqContext.SignedInUser = querySignedInUser.Result reqContext.SignedInUser = querySignedInUserResult
return true return true
} }
@ -365,8 +365,8 @@ func (h *ContextHandler) initContextWithBasicAuth(reqContext *models.ReqContext,
usr := authQuery.User usr := authQuery.User
query := models.GetSignedInUserQuery{UserId: usr.ID, OrgId: orgID} query := user.GetSignedInUserQuery{UserID: usr.ID, OrgID: orgID}
err = h.SQLStore.GetSignedInUserWithCacheCtx(ctx, &query) queryResult, err := h.userService.GetSignedInUserWithCacheCtx(ctx, &query)
if err != nil { if err != nil {
reqContext.Logger.Error( reqContext.Logger.Error(
"Failed at user signed in", "Failed at user signed in",
@ -377,7 +377,7 @@ func (h *ContextHandler) initContextWithBasicAuth(reqContext *models.ReqContext,
return true return true
} }
reqContext.SignedInUser = query.Result reqContext.SignedInUser = queryResult
reqContext.IsSignedIn = true reqContext.IsSignedIn = true
return true return true
} }
@ -402,14 +402,14 @@ func (h *ContextHandler) initContextWithToken(reqContext *models.ReqContext, org
return false return false
} }
query := models.GetSignedInUserQuery{UserId: token.UserId, OrgId: orgID} query := user.GetSignedInUserQuery{UserID: token.UserId, OrgID: orgID}
err = h.SQLStore.GetSignedInUserWithCacheCtx(ctx, &query) queryResult, err := h.userService.GetSignedInUserWithCacheCtx(ctx, &query)
if err != nil { if err != nil {
reqContext.Logger.Error("Failed to get user with id", "userId", token.UserId, "error", err) reqContext.Logger.Error("Failed to get user with id", "userId", token.UserId, "error", err)
return false return false
} }
reqContext.SignedInUser = query.Result reqContext.SignedInUser = queryResult
reqContext.IsSignedIn = true reqContext.IsSignedIn = true
reqContext.UserToken = token reqContext.UserToken = token
@ -478,10 +478,10 @@ func (h *ContextHandler) initContextWithRenderAuth(reqContext *models.ReqContext
// UserID can be 0 for background tasks and, in this case, there is no user info to retrieve // UserID can be 0 for background tasks and, in this case, there is no user info to retrieve
if renderUser.UserID != 0 { if renderUser.UserID != 0 {
query := models.GetSignedInUserQuery{UserId: renderUser.UserID, OrgId: renderUser.OrgID} query := user.GetSignedInUserQuery{UserID: renderUser.UserID, OrgID: renderUser.OrgID}
err := h.SQLStore.GetSignedInUserWithCacheCtx(ctx, &query) queryResult, err := h.userService.GetSignedInUserWithCacheCtx(ctx, &query)
if err == nil { if err == nil {
reqContext.SignedInUser = query.Result reqContext.SignedInUser = queryResult
} }
} }

View File

@ -146,11 +146,6 @@ func (m *SQLStoreMock) GetUserOrgList(ctx context.Context, query *models.GetUser
return m.ExpectedError return m.ExpectedError
} }
func (m *SQLStoreMock) GetSignedInUserWithCacheCtx(ctx context.Context, query *models.GetSignedInUserQuery) error {
query.Result = m.ExpectedSignedInUser
return m.ExpectedError
}
func (m *SQLStoreMock) GetSignedInUser(ctx context.Context, query *models.GetSignedInUserQuery) error { func (m *SQLStoreMock) GetSignedInUser(ctx context.Context, query *models.GetSignedInUserQuery) error {
query.Result = m.ExpectedSignedInUser query.Result = m.ExpectedSignedInUser
return m.ExpectedError return m.ExpectedError

View File

@ -34,7 +34,6 @@ type Store interface {
GetUserProfile(ctx context.Context, query *models.GetUserProfileQuery) error GetUserProfile(ctx context.Context, query *models.GetUserProfileQuery) error
GetUserOrgList(ctx context.Context, query *models.GetUserOrgListQuery) error GetUserOrgList(ctx context.Context, query *models.GetUserOrgListQuery) error
GetSignedInUser(ctx context.Context, query *models.GetSignedInUserQuery) error GetSignedInUser(ctx context.Context, query *models.GetSignedInUserQuery) error
GetSignedInUserWithCacheCtx(ctx context.Context, query *models.GetSignedInUserQuery) error
UpdateUserPermissions(userID int64, isAdmin bool) error UpdateUserPermissions(userID int64, isAdmin bool) error
SetUserHelpFlag(ctx context.Context, cmd *models.SetUserHelpFlagCommand) error SetUserHelpFlag(ctx context.Context, cmd *models.SetUserHelpFlagCommand) error
CreateTeam(name, email string, orgID int64) (models.Team, error) CreateTeam(name, email string, orgID int64) (models.Team, error)

View File

@ -55,10 +55,13 @@ func (f *FakeUserService) SetUsingOrg(ctx context.Context, cmd *user.SetUsingOrg
} }
func (f *FakeUserService) GetSignedInUserWithCacheCtx(ctx context.Context, query *user.GetSignedInUserQuery) (*user.SignedInUser, error) { func (f *FakeUserService) GetSignedInUserWithCacheCtx(ctx context.Context, query *user.GetSignedInUserQuery) (*user.SignedInUser, error) {
return f.ExpectedSignedInUser, f.ExpectedError return f.GetSignedInUser(ctx, query)
} }
func (f *FakeUserService) GetSignedInUser(ctx context.Context, query *user.GetSignedInUserQuery) (*user.SignedInUser, error) { func (f *FakeUserService) GetSignedInUser(ctx context.Context, query *user.GetSignedInUserQuery) (*user.SignedInUser, error) {
if f.ExpectedSignedInUser == nil {
return &user.SignedInUser{}, f.ExpectedError
}
return f.ExpectedSignedInUser, f.ExpectedError return f.ExpectedSignedInUser, f.ExpectedError
} }