mirror of
https://github.com/grafana/grafana.git
synced 2025-07-29 04:52:10 +08:00
IAM: Run user creation inside transaction (#106113)
This commit is contained in:
@ -21,6 +21,7 @@ type FakeOrgService struct {
|
|||||||
ExpectedSearchOrgUsersResult *org.SearchOrgUsersQueryResult
|
ExpectedSearchOrgUsersResult *org.SearchOrgUsersQueryResult
|
||||||
ExpectedOrgListResponse OrgListResponse
|
ExpectedOrgListResponse OrgListResponse
|
||||||
SearchOrgUsersFn func(context.Context, *org.SearchOrgUsersQuery) (*org.SearchOrgUsersQueryResult, error)
|
SearchOrgUsersFn func(context.Context, *org.SearchOrgUsersQuery) (*org.SearchOrgUsersQueryResult, error)
|
||||||
|
InsertOrgUserFn func(context.Context, *org.OrgUser) (int64, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewOrgServiceFake() *FakeOrgService {
|
func NewOrgServiceFake() *FakeOrgService {
|
||||||
@ -36,6 +37,9 @@ func (f *FakeOrgService) Insert(ctx context.Context, cmd *org.OrgUser) (int64, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *FakeOrgService) InsertOrgUser(ctx context.Context, cmd *org.OrgUser) (int64, error) {
|
func (f *FakeOrgService) InsertOrgUser(ctx context.Context, cmd *org.OrgUser) (int64, error) {
|
||||||
|
if f.InsertOrgUserFn != nil {
|
||||||
|
return f.InsertOrgUserFn(ctx, cmd)
|
||||||
|
}
|
||||||
return f.ExpectedOrgUserID, f.ExpectedError
|
return f.ExpectedOrgUserID, f.ExpectedError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ type Service struct {
|
|||||||
cacheService *localcache.CacheService
|
cacheService *localcache.CacheService
|
||||||
cfg *setting.Cfg
|
cfg *setting.Cfg
|
||||||
tracer tracing.Tracer
|
tracer tracing.Tracer
|
||||||
|
db db.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func ProvideService(
|
func ProvideService(
|
||||||
@ -50,6 +51,7 @@ func ProvideService(
|
|||||||
teamService: teamService,
|
teamService: teamService,
|
||||||
cacheService: cacheService,
|
cacheService: cacheService,
|
||||||
tracer: tracer,
|
tracer: tracer,
|
||||||
|
db: db,
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultLimits, err := readQuotaConfig(cfg)
|
defaultLimits, err := readQuotaConfig(cfg)
|
||||||
@ -172,9 +174,10 @@ func (s *Service) Create(ctx context.Context, cmd *user.CreateUserCommand) (*use
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = s.db.InTransaction(ctx, func(ctx context.Context) error {
|
||||||
_, err = s.store.Insert(ctx, usr)
|
_, err = s.store.Insert(ctx, usr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// create org user link
|
// create org user link
|
||||||
@ -195,12 +198,11 @@ func (s *Service) Create(ctx context.Context, cmd *user.CreateUserCommand) (*use
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_, err = s.orgService.InsertOrgUser(ctx, &orgUser)
|
_, err = s.orgService.InsertOrgUser(ctx, &orgUser)
|
||||||
if err != nil {
|
return err
|
||||||
err := s.store.Delete(ctx, usr.ID)
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
return usr, err
|
return usr, err
|
||||||
}
|
|
||||||
}
|
|
||||||
return usr, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) Delete(ctx context.Context, cmd *user.DeleteUserCommand) error {
|
func (s *Service) Delete(ctx context.Context, cmd *user.DeleteUserCommand) error {
|
||||||
|
@ -9,7 +9,9 @@ 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/infra/db"
|
||||||
"github.com/grafana/grafana/pkg/infra/localcache"
|
"github.com/grafana/grafana/pkg/infra/localcache"
|
||||||
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||||
"github.com/grafana/grafana/pkg/services/org"
|
"github.com/grafana/grafana/pkg/services/org"
|
||||||
"github.com/grafana/grafana/pkg/services/org/orgtest"
|
"github.com/grafana/grafana/pkg/services/org/orgtest"
|
||||||
@ -27,6 +29,7 @@ func TestUserService(t *testing.T) {
|
|||||||
cacheService: localcache.ProvideService(),
|
cacheService: localcache.ProvideService(),
|
||||||
teamService: &teamtest.FakeService{},
|
teamService: &teamtest.FakeService{},
|
||||||
tracer: tracing.InitializeTracerForTest(),
|
tracer: tracing.InitializeTracerForTest(),
|
||||||
|
db: db.InitTestDB(t),
|
||||||
}
|
}
|
||||||
userService.cfg = setting.NewCfg()
|
userService.cfg = setting.NewCfg()
|
||||||
|
|
||||||
@ -266,6 +269,46 @@ func TestMetrics(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIntegrationCreateUser(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("skipping integration test")
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg := setting.NewCfg()
|
||||||
|
ss := db.InitTestDB(t)
|
||||||
|
userStore := &sqlStore{
|
||||||
|
db: ss,
|
||||||
|
dialect: ss.GetDialect(),
|
||||||
|
logger: log.NewNopLogger(),
|
||||||
|
cfg: cfg,
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("create user should roll back created user if OrgUser cannot be created", func(t *testing.T) {
|
||||||
|
userService := Service{
|
||||||
|
store: userStore,
|
||||||
|
orgService: &orgtest.FakeOrgService{InsertOrgUserFn: func(ctx context.Context, orgUser *org.OrgUser) (int64, error) {
|
||||||
|
return 0, errors.New("some error")
|
||||||
|
}},
|
||||||
|
cacheService: localcache.ProvideService(),
|
||||||
|
teamService: &teamtest.FakeService{},
|
||||||
|
tracer: tracing.InitializeTracerForTest(),
|
||||||
|
cfg: setting.NewCfg(),
|
||||||
|
db: ss,
|
||||||
|
}
|
||||||
|
_, err := userService.Create(context.Background(), &user.CreateUserCommand{
|
||||||
|
Email: "email",
|
||||||
|
Login: "login",
|
||||||
|
Name: "name",
|
||||||
|
})
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
usr, err := userService.GetByLogin(context.Background(), &user.GetUserByLoginQuery{LoginOrEmail: "login"})
|
||||||
|
require.Nil(t, usr)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.ErrorIs(t, err, user.ErrUserNotFound)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
type FakeUserStore struct {
|
type FakeUserStore struct {
|
||||||
ExpectedUser *user.User
|
ExpectedUser *user.User
|
||||||
ExpectedSignedInUser *user.SignedInUser
|
ExpectedSignedInUser *user.SignedInUser
|
||||||
|
Reference in New Issue
Block a user