UserService: use the UserService instead of calling sqlstore directly (#55745)

* UserService: update callers to use the UserService instead of calling sqlstore directly

There is one major change hiding in this PR. UserService.Delete originally called a number of services to delete user-related records. I moved everything except the actual call to the user table, and moved those into the API. This was done to avoid dependencies cycles; many of our services depend on the user service, so the user service itself should have as few dependencies as possible.
This commit is contained in:
Kristin Laemmert
2022-09-27 07:58:49 -04:00
committed by GitHub
parent 4f6c2d35c2
commit 701f6d5436
33 changed files with 277 additions and 360 deletions
@@ -40,7 +40,7 @@ var (
func ProvideTeamPermissions(
cfg *setting.Cfg, router routing.RouteRegister, sql *sqlstore.SQLStore,
ac accesscontrol.AccessControl, license models.Licensing, service accesscontrol.Service,
teamService team.Service,
teamService team.Service, userService user.Service,
) (*TeamPermissionsService, error) {
options := resourcepermissions.Options{
Resource: "teams",
@@ -96,7 +96,7 @@ func ProvideTeamPermissions(
},
}
srv, err := resourcepermissions.New(options, cfg, router, license, ac, service, sql, teamService)
srv, err := resourcepermissions.New(options, cfg, router, license, ac, service, sql, teamService, userService)
if err != nil {
return nil, err
}
@@ -114,7 +114,7 @@ var DashboardAdminActions = append(DashboardEditActions, []string{dashboards.Act
func ProvideDashboardPermissions(
cfg *setting.Cfg, router routing.RouteRegister, sql *sqlstore.SQLStore, ac accesscontrol.AccessControl,
license models.Licensing, dashboardStore dashboards.Store, service accesscontrol.Service,
teamService team.Service,
teamService team.Service, userService user.Service,
) (*DashboardPermissionsService, error) {
getDashboard := func(ctx context.Context, orgID int64, resourceID string) (*models.Dashboard, error) {
query := &models.GetDashboardQuery{Uid: resourceID, OrgId: orgID}
@@ -168,7 +168,7 @@ func ProvideDashboardPermissions(
RoleGroup: "Dashboards",
}
srv, err := resourcepermissions.New(options, cfg, router, license, ac, service, sql, teamService)
srv, err := resourcepermissions.New(options, cfg, router, license, ac, service, sql, teamService, userService)
if err != nil {
return nil, err
}
@@ -193,7 +193,7 @@ var FolderAdminActions = append(FolderEditActions, []string{dashboards.ActionFol
func ProvideFolderPermissions(
cfg *setting.Cfg, router routing.RouteRegister, sql *sqlstore.SQLStore, accesscontrol accesscontrol.AccessControl,
license models.Licensing, dashboardStore dashboards.Store, service accesscontrol.Service,
teamService team.Service,
teamService team.Service, userService user.Service,
) (*FolderPermissionsService, error) {
options := resourcepermissions.Options{
Resource: "folders",
@@ -224,7 +224,7 @@ func ProvideFolderPermissions(
WriterRoleName: "Folder permission writer",
RoleGroup: "Folders",
}
srv, err := resourcepermissions.New(options, cfg, router, license, accesscontrol, service, sql, teamService)
srv, err := resourcepermissions.New(options, cfg, router, license, accesscontrol, service, sql, teamService, userService)
if err != nil {
return nil, err
}
@@ -284,7 +284,7 @@ type ServiceAccountPermissionsService struct {
func ProvideServiceAccountPermissions(
cfg *setting.Cfg, router routing.RouteRegister, sql *sqlstore.SQLStore, ac accesscontrol.AccessControl,
license models.Licensing, serviceAccountStore serviceaccounts.Store, service accesscontrol.Service,
teamService team.Service,
teamService team.Service, userService user.Service,
) (*ServiceAccountPermissionsService, error) {
options := resourcepermissions.Options{
Resource: "serviceaccounts",
@@ -311,7 +311,7 @@ func ProvideServiceAccountPermissions(
RoleGroup: "Service accounts",
}
srv, err := resourcepermissions.New(options, cfg, router, license, ac, service, sql, teamService)
srv, err := resourcepermissions.New(options, cfg, router, license, ac, service, sql, teamService, userService)
if err != nil {
return nil, err
}
@@ -51,7 +51,7 @@ type Store interface {
func New(
options Options, cfg *setting.Cfg, router routing.RouteRegister, license models.Licensing,
ac accesscontrol.AccessControl, service accesscontrol.Service, sqlStore *sqlstore.SQLStore,
teamService team.Service,
teamService team.Service, userService user.Service,
) (*Service, error) {
var permissions []string
actionSet := make(map[string]struct{})
@@ -83,6 +83,7 @@ func New(
sqlStore: sqlStore,
service: service,
teamService: teamService,
userService: userService,
}
s.api = newApi(ac, router, s)
@@ -110,6 +111,7 @@ type Service struct {
actions []string
sqlStore *sqlstore.SQLStore
teamService team.Service
userService user.Service
}
func (s *Service) GetPermissions(ctx context.Context, user *user.SignedInUser, resourceID string) ([]accesscontrol.ResourcePermission, error) {
@@ -286,10 +288,8 @@ func (s *Service) validateUser(ctx context.Context, orgID, userID int64) error {
return ErrInvalidAssignment
}
if err := s.sqlStore.GetSignedInUser(ctx, &models.GetSignedInUserQuery{OrgId: orgID, UserId: userID}); err != nil {
return err
}
return nil
_, err := s.userService.GetSignedInUser(ctx, &user.GetSignedInUserQuery{OrgID: orgID, UserID: userID})
return err
}
func (s *Service) validateTeam(ctx context.Context, orgID, teamID int64) error {
@@ -15,6 +15,7 @@ import (
"github.com/grafana/grafana/pkg/services/team"
"github.com/grafana/grafana/pkg/services/team/teamimpl"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
"github.com/grafana/grafana/pkg/setting"
)
@@ -223,12 +224,13 @@ func setupTestEnvironment(t *testing.T, permissions []accesscontrol.Permission,
sql := sqlstore.InitTestDB(t)
cfg := setting.NewCfg()
teamSvc := teamimpl.ProvideService(sql, cfg)
userSvc := userimpl.ProvideService(sql, nil, cfg, sql)
license := licensingtest.NewFakeLicensing()
license.On("FeatureEnabled", "accesscontrol.enforcement").Return(true).Maybe()
mock := accesscontrolmock.New().WithPermissions(permissions)
service, err := New(
ops, cfg, routing.NewRouteRegister(), license,
accesscontrolmock.New().WithPermissions(permissions), mock, sql, teamSvc,
accesscontrolmock.New().WithPermissions(permissions), mock, sql, teamSvc, userSvc,
)
require.NoError(t, err)
+17 -3
View File
@@ -6,6 +6,8 @@ import (
"net/http"
"testing"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/remotecache"
"github.com/grafana/grafana/pkg/infra/tracing"
@@ -19,7 +21,6 @@ import (
"github.com/grafana/grafana/pkg/services/user/usertest"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web"
"github.com/stretchr/testify/require"
)
const userID = int64(1)
@@ -84,10 +85,23 @@ func getContextHandler(t *testing.T) *ContextHandler {
tracer := tracing.InitializeTracerForTest()
loginService := loginservice.LoginServiceMock{ExpectedUser: &user.User{ID: userID}}
authProxy := authproxy.ProvideAuthProxy(cfg, remoteCacheSvc, loginService, &FakeGetSignUserStore{})
userService := usertest.FakeUserService{
GetSignedInUserFn: func(ctx context.Context, query *user.GetSignedInUserQuery) (*user.SignedInUser, error) {
if query.UserID != userID {
return &user.SignedInUser{}, user.ErrUserNotFound
}
return &user.SignedInUser{
UserID: userID,
OrgID: orgID,
}, nil
},
}
authProxy := authproxy.ProvideAuthProxy(cfg, remoteCacheSvc, loginService, &userService, &FakeGetSignUserStore{})
authenticator := &fakeAuthenticator{}
return ProvideService(cfg, userAuthTokenSvc, authJWTSvc, remoteCacheSvc, renderSvc, sqlStore, tracer, authProxy, loginService, nil, authenticator, &usertest.FakeUserService{})
return ProvideService(cfg, userAuthTokenSvc, authJWTSvc, remoteCacheSvc,
renderSvc, sqlStore, tracer, authProxy, loginService, nil, authenticator, &userService)
}
type FakeGetSignUserStore struct {
@@ -56,16 +56,18 @@ type AuthProxy struct {
remoteCache *remotecache.RemoteCache
loginService login.Service
sqlStore sqlstore.Store
userService user.Service
logger log.Logger
}
func ProvideAuthProxy(cfg *setting.Cfg, remoteCache *remotecache.RemoteCache, loginService login.Service, sqlStore sqlstore.Store) *AuthProxy {
func ProvideAuthProxy(cfg *setting.Cfg, remoteCache *remotecache.RemoteCache, loginService login.Service, userService user.Service, sqlStore sqlstore.Store) *AuthProxy {
return &AuthProxy{
cfg: cfg,
remoteCache: remoteCache,
loginService: loginService,
sqlStore: sqlStore,
userService: userService,
logger: log.New("auth.proxy"),
}
}
@@ -347,16 +349,10 @@ func (auth *AuthProxy) headersIterator(reqCtx *models.ReqContext, fn func(field
// GetSignedInUser gets full signed in user info.
func (auth *AuthProxy) GetSignedInUser(userID int64, orgID int64) (*user.SignedInUser, error) {
query := &models.GetSignedInUserQuery{
OrgId: orgID,
UserId: userID,
}
if err := auth.sqlStore.GetSignedInUser(context.Background(), query); err != nil {
return nil, err
}
return query.Result, nil
return auth.userService.GetSignedInUser(context.Background(), &user.GetSignedInUserQuery{
OrgID: orgID,
UserID: userID,
})
}
// Remember user in cache
@@ -7,6 +7,9 @@ import (
"net/http"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/infra/remotecache"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/ldap"
@@ -15,9 +18,6 @@ import (
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
const hdrName = "markelog"
@@ -48,7 +48,7 @@ func prepareMiddleware(t *testing.T, remoteCache *remotecache.RemoteCache, confi
},
}
return ProvideAuthProxy(cfg, remoteCache, loginService, nil), ctx
return ProvideAuthProxy(cfg, remoteCache, loginService, nil, nil), ctx
}
func TestMiddlewareContext(t *testing.T) {
@@ -9,6 +9,7 @@ import (
"github.com/grafana/grafana/pkg/services/tag/tagimpl"
"github.com/grafana/grafana/pkg/services/team/teamimpl"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
@@ -603,12 +604,13 @@ func setupAccessControlGuardianTest(t *testing.T, uid string, permissions []acce
license := licensingtest.NewFakeLicensing()
license.On("FeatureEnabled", "accesscontrol.enforcement").Return(true).Maybe()
teamSvc := teamimpl.ProvideService(store, store.Cfg)
userSvc := userimpl.ProvideService(store, nil, store.Cfg, store)
folderPermissions, err := ossaccesscontrol.ProvideFolderPermissions(
setting.NewCfg(), routing.NewRouteRegister(), store, ac, license, &dashboards.FakeDashboardStore{}, ac, teamSvc)
setting.NewCfg(), routing.NewRouteRegister(), store, ac, license, &dashboards.FakeDashboardStore{}, ac, teamSvc, userSvc)
require.NoError(t, err)
dashboardPermissions, err := ossaccesscontrol.ProvideDashboardPermissions(
setting.NewCfg(), routing.NewRouteRegister(), store, ac, license, &dashboards.FakeDashboardStore{}, ac, teamSvc)
setting.NewCfg(), routing.NewRouteRegister(), store, ac, license, &dashboards.FakeDashboardStore{}, ac, teamSvc, userSvc)
require.NoError(t, err)
if dashboardSvc == nil {
dashboardSvc = &dashboards.FakeDashboardService{}
@@ -148,7 +148,7 @@ func (ls *Implementation) UpsertUser(ctx context.Context, cmd *models.UpsertUser
// Sync isGrafanaAdmin permission
if extUser.IsGrafanaAdmin != nil && *extUser.IsGrafanaAdmin != cmd.Result.IsAdmin {
if errPerms := ls.SQLStore.UpdateUserPermissions(cmd.Result.ID, *extUser.IsGrafanaAdmin); errPerms != nil {
if errPerms := ls.userService.UpdatePermissions(cmd.Result.ID, *extUser.IsGrafanaAdmin); errPerms != nil {
return errPerms
}
}
@@ -334,9 +334,9 @@ func (ls *Implementation) syncOrgRoles(ctx context.Context, usr *user.User, extU
break
}
return ls.SQLStore.SetUsingOrg(ctx, &models.SetUsingOrgCommand{
UserId: usr.ID,
OrgId: usr.OrgID,
return ls.userService.SetUsingOrg(ctx, &user.SetUsingOrgCommand{
UserID: usr.ID,
OrgID: usr.OrgID,
})
}
@@ -9,6 +9,8 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana-plugin-sdk-go/experimental"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/infra/tracing"
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
@@ -17,7 +19,6 @@ import (
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/require"
)
var (
@@ -83,7 +84,9 @@ var (
)
func service(t *testing.T) *StandardSearchService {
service, ok := ProvideService(&setting.Cfg{Search: setting.SearchSettings{}}, nil, nil, accesscontrolmock.New(), tracing.InitializeTracerForTest(), featuremgmt.WithFeatures(), nil).(*StandardSearchService)
service, ok := ProvideService(&setting.Cfg{Search: setting.SearchSettings{}},
nil, nil, accesscontrolmock.New(), tracing.InitializeTracerForTest(), featuremgmt.WithFeatures(),
nil, nil).(*StandardSearchService)
require.True(t, ok)
return service
}
+23 -20
View File
@@ -6,6 +6,10 @@ import (
"fmt"
"time"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/models"
@@ -17,10 +21,6 @@ import (
"github.com/grafana/grafana/pkg/services/store"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/grafana/grafana-plugin-sdk-go/backend"
)
var (
@@ -63,11 +63,12 @@ var (
type StandardSearchService struct {
registry.BackgroundService
cfg *setting.Cfg
sql *sqlstore.SQLStore
auth FutureAuthService // eventually injected from elsewhere
ac accesscontrol.Service
orgService org.Service
cfg *setting.Cfg
sql *sqlstore.SQLStore
auth FutureAuthService // eventually injected from elsewhere
ac accesscontrol.Service
orgService org.Service
userService user.Service
logger log.Logger
dashboardIndex *searchIndex
@@ -79,7 +80,9 @@ func (s *StandardSearchService) IsReady(ctx context.Context, orgId int64) IsSear
return s.dashboardIndex.isInitialized(ctx, orgId)
}
func ProvideService(cfg *setting.Cfg, sql *sqlstore.SQLStore, entityEventStore store.EntityEventsService, ac accesscontrol.Service, tracer tracing.Tracer, features featuremgmt.FeatureToggles, orgService org.Service) SearchService {
func ProvideService(cfg *setting.Cfg, sql *sqlstore.SQLStore, entityEventStore store.EntityEventsService,
ac accesscontrol.Service, tracer tracing.Tracer, features featuremgmt.FeatureToggles, orgService org.Service,
userService user.Service) SearchService {
extender := &NoopExtender{}
s := &StandardSearchService{
cfg: cfg,
@@ -98,10 +101,11 @@ func ProvideService(cfg *setting.Cfg, sql *sqlstore.SQLStore, entityEventStore s
features,
cfg.Search,
),
logger: log.New("searchV2"),
extender: extender,
reIndexCh: make(chan struct{}, 1),
orgService: orgService,
logger: log.New("searchV2"),
extender: extender,
reIndexCh: make(chan struct{}, 1),
orgService: orgService,
userService: userService,
}
return s
}
@@ -157,23 +161,22 @@ func (s *StandardSearchService) getUser(ctx context.Context, backendUser *backen
IsAnonymous: true,
}
} else {
getSignedInUserQuery := &models.GetSignedInUserQuery{
getSignedInUserQuery := &user.GetSignedInUserQuery{
Login: backendUser.Login,
Email: backendUser.Email,
OrgId: orgId,
OrgID: orgId,
}
err := s.sql.GetSignedInUser(ctx, getSignedInUserQuery)
var err error
usr, err = s.userService.GetSignedInUser(ctx, getSignedInUserQuery)
if err != nil {
s.logger.Error("Error while retrieving user", "error", err, "email", backendUser.Email, "login", getSignedInUserQuery.Login)
return nil, errors.New("auth error")
}
if getSignedInUserQuery.Result == nil {
if usr == nil {
s.logger.Error("No user found", "email", backendUser.Email)
return nil, errors.New("auth error")
}
usr = getSignedInUserQuery.Result
}
if s.ac.IsDisabled() {
+7 -3
View File
@@ -11,6 +11,9 @@ import (
"strconv"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/infra/kvstore"
"github.com/grafana/grafana/pkg/infra/log"
@@ -29,10 +32,9 @@ import (
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/team/teamimpl"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var (
@@ -282,7 +284,9 @@ func setupTestServer(t *testing.T, svc *tests.ServiceAccountMock,
sqlStore *sqlstore.SQLStore, saStore serviceaccounts.Store) (*web.Mux, *ServiceAccountsAPI) {
cfg := setting.NewCfg()
teamSvc := teamimpl.ProvideService(sqlStore, cfg)
saPermissionService, err := ossaccesscontrol.ProvideServiceAccountPermissions(cfg, routing.NewRouteRegister(), sqlStore, acmock, &licensing.OSSLicensingService{}, saStore, acmock, teamSvc)
userSvc := userimpl.ProvideService(sqlStore, nil, cfg, sqlStore)
saPermissionService, err := ossaccesscontrol.ProvideServiceAccountPermissions(
cfg, routing.NewRouteRegister(), sqlStore, acmock, &licensing.OSSLicensingService{}, saStore, acmock, teamSvc, userSvc)
require.NoError(t, err)
a := NewServiceAccountsAPI(cfg, svc, acmock, routerRegister, saStore, saPermissionService)
+3 -9
View File
@@ -5,11 +5,12 @@ import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/user"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestIntegrationStatsDataAccess(t *testing.T) {
@@ -118,13 +119,6 @@ func populateDB(t *testing.T, sqlStore *SQLStore) {
err = sqlStore.AddOrgUser(context.Background(), cmd)
require.NoError(t, err)
// update 1st user last seen at
updateUserLastSeenAtCmd := &models.UpdateUserLastSeenAtCommand{
UserId: users[0].ID,
}
err = sqlStore.UpdateUserLastSeenAt(context.Background(), updateUserLastSeenAtCmd)
require.NoError(t, err)
// force renewal of user stats
err = sqlStore.updateUserRoleCountsIfNecessary(context.Background(), true)
require.NoError(t, err)
+1 -22
View File
@@ -17,27 +17,6 @@ import (
"github.com/grafana/grafana/pkg/util"
)
type ErrCaseInsensitiveLoginConflict struct {
users []user.User
}
func (e *ErrCaseInsensitiveLoginConflict) Unwrap() error {
return user.ErrCaseInsensitive
}
func (e *ErrCaseInsensitiveLoginConflict) Error() string {
n := len(e.users)
userStrings := make([]string, 0, n)
for _, v := range e.users {
userStrings = append(userStrings, fmt.Sprintf("%s (email:%s, id:%d)", v.Login, v.Email, v.ID))
}
return fmt.Sprintf(
"Found a conflict in user login information. %d users already exist with either the same login or email: [%s].",
n, strings.Join(userStrings, ", "))
}
func (ss *SQLStore) getOrgIDForNewUser(sess *DBSession, args user.CreateUserCommand) (int64, error) {
if ss.Cfg.AutoAssignOrg && args.OrgID != 0 {
if err := verifyExistingOrg(sess, args.OrgID); err != nil {
@@ -63,7 +42,7 @@ func (ss *SQLStore) userCaseInsensitiveLoginConflict(ctx context.Context, sess *
}
if len(users) > 1 {
return &ErrCaseInsensitiveLoginConflict{users}
return &user.ErrCaseInsensitiveLoginConflict{Users: users}
}
return nil
+13
View File
@@ -5,10 +5,12 @@ import (
"fmt"
"github.com/grafana/grafana/pkg/events"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/sqlstore/db"
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
)
type store interface {
@@ -23,6 +25,17 @@ type store interface {
type sqlStore struct {
db db.DB
dialect migrator.Dialect
logger log.Logger
cfg *setting.Cfg
}
func ProvideStore(db db.DB, cfg *setting.Cfg) sqlStore {
return sqlStore{
db: db,
dialect: db.GetDialect(),
cfg: cfg,
logger: log.New("user.store"),
}
}
func (ss *sqlStore) Insert(ctx context.Context, cmd *user.User) (int64, error) {
+4 -3
View File
@@ -5,10 +5,11 @@ import (
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/setting"
)
func TestIntegrationUserDataAccess(t *testing.T) {
@@ -17,7 +18,7 @@ func TestIntegrationUserDataAccess(t *testing.T) {
}
ss := sqlstore.InitTestDB(t)
userStore := sqlStore{db: ss}
userStore := ProvideStore(ss, setting.NewCfg())
t.Run("user not found", func(t *testing.T) {
_, err := userStore.Get(context.Background(),
+10 -109
View File
@@ -6,67 +6,34 @@ import (
"time"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/org"
pref "github.com/grafana/grafana/pkg/services/preference"
"github.com/grafana/grafana/pkg/services/quota"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/sqlstore/db"
"github.com/grafana/grafana/pkg/services/star"
"github.com/grafana/grafana/pkg/services/teamguardian"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/userauth"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
"golang.org/x/sync/errgroup"
)
type Service struct {
store store
orgService org.Service
starService star.Service
dashboardService dashboards.DashboardService
preferenceService pref.Service
teamMemberService teamguardian.TeamGuardian
userAuthService userauth.Service
quotaService quota.Service
accessControlStore accesscontrol.Service
store store
orgService org.Service
// TODO remove sqlstore
sqlStore *sqlstore.SQLStore
cfg *setting.Cfg
cfg *setting.Cfg
}
func ProvideService(
db db.DB,
orgService org.Service,
starService star.Service,
dashboardService dashboards.DashboardService,
preferenceService pref.Service,
teamMemberService teamguardian.TeamGuardian,
userAuthService userauth.Service,
quotaService quota.Service,
accessControlStore accesscontrol.Service,
cfg *setting.Cfg,
ss *sqlstore.SQLStore,
) user.Service {
store := ProvideStore(db, cfg)
return &Service{
store: &sqlStore{
db: db,
dialect: db.GetDialect(),
},
orgService: orgService,
starService: starService,
dashboardService: dashboardService,
preferenceService: preferenceService,
teamMemberService: teamMemberService,
userAuthService: userAuthService,
quotaService: quotaService,
accessControlStore: accessControlStore,
cfg: cfg,
sqlStore: ss,
store: &store,
orgService: orgService,
cfg: cfg,
sqlStore: ss,
}
}
@@ -169,70 +136,7 @@ func (s *Service) Delete(ctx context.Context, cmd *user.DeleteUserCommand) error
return err
}
// delete from all the stores
if err := s.store.Delete(ctx, cmd.UserID); err != nil {
return err
}
g, ctx := errgroup.WithContext(ctx)
g.Go(func() error {
if err := s.starService.DeleteByUser(ctx, cmd.UserID); err != nil {
return err
}
return nil
})
g.Go(func() error {
if err := s.orgService.DeleteUserFromAll(ctx, cmd.UserID); err != nil {
return err
}
return nil
})
g.Go(func() error {
if err := s.dashboardService.DeleteACLByUser(ctx, cmd.UserID); err != nil {
return err
}
return nil
})
g.Go(func() error {
if err := s.preferenceService.DeleteByUser(ctx, cmd.UserID); err != nil {
return err
}
return nil
})
g.Go(func() error {
if err := s.teamMemberService.DeleteByUser(ctx, cmd.UserID); err != nil {
return err
}
return nil
})
g.Go(func() error {
if err := s.userAuthService.Delete(ctx, cmd.UserID); err != nil {
return err
}
return nil
})
g.Go(func() error {
if err := s.userAuthService.DeleteToken(ctx, cmd.UserID); err != nil {
return err
}
return nil
})
g.Go(func() error {
if err := s.quotaService.DeleteByUser(ctx, cmd.UserID); err != nil {
return err
}
return nil
})
g.Go(func() error {
if err := s.accessControlStore.DeleteUserPermissions(ctx, accesscontrol.GlobalOrgID, cmd.UserID); err != nil {
return err
}
return nil
})
if err := g.Wait(); err != nil {
return err
}
return nil
return s.store.Delete(ctx, cmd.UserID)
}
func (s *Service) GetByID(ctx context.Context, query *user.GetUserByIDQuery) (*user.User, error) {
@@ -331,10 +235,7 @@ func (s *Service) GetSignedInUser(ctx context.Context, query *user.GetSignedInUs
OrgId: query.OrgID,
}
err := s.sqlStore.GetSignedInUser(ctx, q)
if err != nil {
return nil, err
}
return q.Result, nil
return q.Result, err
}
// TODO: remove wrapper around sqlstore
+2 -64
View File
@@ -2,18 +2,10 @@ package userimpl
import (
"context"
"errors"
"testing"
"github.com/grafana/grafana/pkg/services/accesscontrol/mock"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/org/orgtest"
"github.com/grafana/grafana/pkg/services/preference/preftest"
"github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/star/startest"
"github.com/grafana/grafana/pkg/services/teamguardian/manager"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/userauth/userauthtest"
"github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/require"
@@ -22,23 +14,9 @@ import (
func TestUserService(t *testing.T) {
userStore := newUserStoreFake()
orgService := orgtest.NewOrgServiceFake()
starService := startest.NewStarServiceFake()
dashboardService := dashboards.NewFakeDashboardService(t)
preferenceService := preftest.NewPreferenceServiceFake()
teamMemberService := manager.NewTeamGuardianMock()
userAuthService := userauthtest.NewFakeUserAuthService()
quotaService := quotatest.NewQuotaServiceFake()
accessControlStore := mock.New()
userService := Service{
store: userStore,
orgService: orgService,
starService: starService,
dashboardService: dashboardService,
preferenceService: preferenceService,
teamMemberService: teamMemberService,
userAuthService: userAuthService,
quotaService: quotaService,
accessControlStore: accessControlStore,
store: userStore,
orgService: orgService,
}
t.Run("create user", func(t *testing.T) {
@@ -81,26 +59,6 @@ func TestUserService(t *testing.T) {
require.Error(t, err, user.ErrUserNotFound)
})
t.Run("delete user returns from team", func(t *testing.T) {
teamMemberService.ExpectedError = errors.New("some error")
t.Cleanup(func() {
teamMemberService.ExpectedError = nil
})
err := userService.Delete(context.Background(), &user.DeleteUserCommand{UserID: 1})
require.Error(t, err)
})
t.Run("delete user returns from team and pref", func(t *testing.T) {
teamMemberService.ExpectedError = errors.New("some error")
preferenceService.ExpectedError = errors.New("some error 2")
t.Cleanup(func() {
teamMemberService.ExpectedError = nil
preferenceService.ExpectedError = nil
})
err := userService.Delete(context.Background(), &user.DeleteUserCommand{UserID: 1})
require.Error(t, err)
})
t.Run("delete user successfully", func(t *testing.T) {
err := userService.Delete(context.Background(), &user.DeleteUserCommand{UserID: 1})
require.NoError(t, err)
@@ -115,26 +73,6 @@ func TestUserService(t *testing.T) {
require.Error(t, err, user.ErrUserNotFound)
})
t.Run("delete user returns from team", func(t *testing.T) {
teamMemberService.ExpectedError = errors.New("some error")
t.Cleanup(func() {
teamMemberService.ExpectedError = nil
})
err := userService.Delete(context.Background(), &user.DeleteUserCommand{UserID: 1})
require.Error(t, err)
})
t.Run("delete user returns from team and pref", func(t *testing.T) {
teamMemberService.ExpectedError = errors.New("some error")
preferenceService.ExpectedError = errors.New("some error 2")
t.Cleanup(func() {
teamMemberService.ExpectedError = nil
preferenceService.ExpectedError = nil
})
err := userService.Delete(context.Background(), &user.DeleteUserCommand{UserID: 1})
require.Error(t, err)
})
t.Run("delete user successfully", func(t *testing.T) {
err := userService.Delete(context.Background(), &user.DeleteUserCommand{UserID: 1})
require.NoError(t, err)
+5
View File
@@ -13,6 +13,8 @@ type FakeUserService struct {
ExpectedSetUsingOrgError error
ExpectedSearchUsers user.SearchUserQueryResult
ExpectedUSerProfileDTO user.UserProfileDTO
GetSignedInUserFn func(ctx context.Context, query *user.GetSignedInUserQuery) (*user.SignedInUser, error)
}
func NewUserServiceFake() *FakeUserService {
@@ -60,6 +62,9 @@ func (f *FakeUserService) GetSignedInUserWithCacheCtx(ctx context.Context, query
}
func (f *FakeUserService) GetSignedInUser(ctx context.Context, query *user.GetSignedInUserQuery) (*user.SignedInUser, error) {
if f.GetSignedInUserFn != nil {
return f.GetSignedInUserFn(ctx, query)
}
if f.ExpectedSignedInUser == nil {
return &user.SignedInUser{}, f.ExpectedError
}