diff --git a/pkg/api/http_server.go b/pkg/api/http_server.go index c9e52e6dbe5..73012c9ffa0 100644 --- a/pkg/api/http_server.go +++ b/pkg/api/http_server.go @@ -44,7 +44,6 @@ import ( "github.com/grafana/grafana/pkg/services/live" "github.com/grafana/grafana/pkg/services/live/pushhttp" "github.com/grafana/grafana/pkg/services/login" - "github.com/grafana/grafana/pkg/services/login/authinfoservice" "github.com/grafana/grafana/pkg/services/ngalert" "github.com/grafana/grafana/pkg/services/notifications" "github.com/grafana/grafana/pkg/services/provisioning" @@ -128,7 +127,7 @@ type HTTPServer struct { teamGuardian teamguardian.TeamGuardian queryDataService *query.Service serviceAccountsService serviceaccounts.Service - authInfoService authinfoservice.Service + authInfoService login.AuthInfoService TeamPermissionsService *resourcepermissions.Service NotificationService *notifications.NotificationService } @@ -157,7 +156,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi pluginsUpdateChecker *updatechecker.PluginsService, searchUsersService searchusers.Service, dataSourcesService *datasources.Service, secretsService secrets.Service, queryDataService *query.Service, ldapGroups ldap.Groups, teamGuardian teamguardian.TeamGuardian, serviceaccountsService serviceaccounts.Service, - authInfoService authinfoservice.Service, resourcePermissionServices *resourceservices.ResourceServices, + authInfoService login.AuthInfoService, resourcePermissionServices *resourceservices.ResourceServices, notificationService *notifications.NotificationService) (*HTTPServer, error) { web.Env = cfg.Env m := web.New() diff --git a/pkg/api/user_test.go b/pkg/api/user_test.go index 727c08ccbad..2841d5bd5d2 100644 --- a/pkg/api/user_test.go +++ b/pkg/api/user_test.go @@ -10,6 +10,7 @@ import ( "github.com/grafana/grafana/pkg/api/dtos" "github.com/grafana/grafana/pkg/services/login/authinfoservice" + authinfostore "github.com/grafana/grafana/pkg/services/login/authinfoservice/database" "github.com/grafana/grafana/pkg/services/searchusers/filters" "github.com/grafana/grafana/pkg/services/secrets/database" secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager" @@ -46,7 +47,8 @@ func TestUserAPIEndpoint_userLoggedIn(t *testing.T) { loggedInUserScenario(t, "When calling GET on", "api/users/1", "api/users/:id", func(sc *scenarioContext) { fakeNow := time.Date(2019, 2, 11, 17, 30, 40, 0, time.UTC) secretsService := secretsManager.SetupTestService(t, database.ProvideSecretsStore(sqlStore)) - srv := authinfoservice.ProvideAuthInfoService(bus.New(), sqlStore, &authinfoservice.OSSUserProtectionImpl{}, secretsService) + authInfoStore := authinfostore.ProvideAuthInfoStore(sqlStore, bus.New(), secretsService) + srv := authinfoservice.ProvideAuthInfoService(&authinfoservice.OSSUserProtectionImpl{}, authInfoStore) hs.authInfoService = srv createUserCmd := models.CreateUserCommand{ diff --git a/pkg/server/wire.go b/pkg/server/wire.go index f39a816b895..263a3844ea7 100644 --- a/pkg/server/wire.go +++ b/pkg/server/wire.go @@ -45,6 +45,7 @@ import ( "github.com/grafana/grafana/pkg/services/live/pushhttp" "github.com/grafana/grafana/pkg/services/login" "github.com/grafana/grafana/pkg/services/login/authinfoservice" + authinfodatabase "github.com/grafana/grafana/pkg/services/login/authinfoservice/database" "github.com/grafana/grafana/pkg/services/login/loginservice" "github.com/grafana/grafana/pkg/services/ngalert" ngmetrics "github.com/grafana/grafana/pkg/services/ngalert/metrics" @@ -144,6 +145,8 @@ var wireBasicSet = wire.NewSet( wire.Bind(new(login.Service), new(*loginservice.Implementation)), authinfoservice.ProvideAuthInfoService, wire.Bind(new(login.AuthInfoService), new(*authinfoservice.Implementation)), + authinfodatabase.ProvideAuthInfoStore, + wire.Bind(new(login.Store), new(*authinfodatabase.AuthInfoStore)), datasourceproxy.ProvideService, search.ProvideService, live.ProvideService, @@ -190,7 +193,6 @@ var wireBasicSet = wire.NewSet( wire.Bind(new(teamguardian.Store), new(*teamguardianDatabase.TeamGuardianStoreImpl)), teamguardianManager.ProvideService, wire.Bind(new(teamguardian.TeamGuardian), new(*teamguardianManager.Service)), - wire.Bind(new(authinfoservice.Service), new(*authinfoservice.Implementation)), featuremgmt.ProvideManagerService, featuremgmt.ProvideToggles, resourceservices.ProvideResourceServices, diff --git a/pkg/services/login/authinfo.go b/pkg/services/login/authinfo.go index 5b350760136..447ca6f6afc 100644 --- a/pkg/services/login/authinfo.go +++ b/pkg/services/login/authinfo.go @@ -8,4 +8,5 @@ import ( type AuthInfoService interface { LookupAndUpdate(ctx context.Context, query *models.GetUserByAuthInfoQuery) (*models.User, error) + GetAuthInfo(ctx context.Context, query *models.GetAuthInfoQuery) error } diff --git a/pkg/services/login/authinfoservice/database.go b/pkg/services/login/authinfoservice/database/database.go similarity index 63% rename from pkg/services/login/authinfoservice/database.go rename to pkg/services/login/authinfoservice/database/database.go index 230d22abe26..777f9a7f8ab 100644 --- a/pkg/services/login/authinfoservice/database.go +++ b/pkg/services/login/authinfoservice/database/database.go @@ -1,27 +1,54 @@ -package authinfoservice +package database import ( "context" "encoding/base64" "time" + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/infra/log" + "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/secrets" "github.com/grafana/grafana/pkg/services/sqlstore" - - "github.com/grafana/grafana/pkg/models" ) -var getTime = time.Now +var GetTime = time.Now -func (s *Implementation) GetExternalUserInfoByLogin(ctx context.Context, query *models.GetExternalUserInfoByLoginQuery) error { +type AuthInfoStore struct { + sqlStore sqlstore.Store + bus bus.Bus + secretsService secrets.Service + logger log.Logger +} + +func ProvideAuthInfoStore(sqlStore sqlstore.Store, bus bus.Bus, secretsService secrets.Service) *AuthInfoStore { + store := &AuthInfoStore{ + sqlStore: sqlStore, + bus: bus, + secretsService: secretsService, + logger: log.New("login.authinfo.store"), + } + store.registerBusHandlers() + return store +} + +func (s *AuthInfoStore) registerBusHandlers() { + s.bus.AddHandler(s.GetExternalUserInfoByLogin) + s.bus.AddHandler(s.GetAuthInfo) + s.bus.AddHandler(s.SetAuthInfo) + s.bus.AddHandler(s.UpdateAuthInfo) + s.bus.AddHandler(s.DeleteAuthInfo) +} + +func (s *AuthInfoStore) GetExternalUserInfoByLogin(ctx context.Context, query *models.GetExternalUserInfoByLoginQuery) error { userQuery := models.GetUserByLoginQuery{LoginOrEmail: query.LoginOrEmail} - err := s.Bus.Dispatch(ctx, &userQuery) + err := s.bus.Dispatch(ctx, &userQuery) if err != nil { return err } authInfoQuery := &models.GetAuthInfoQuery{UserId: userQuery.Result.Id} - if err := s.Bus.Dispatch(ctx, authInfoQuery); err != nil { + if err := s.bus.Dispatch(ctx, authInfoQuery); err != nil { return err } @@ -37,7 +64,7 @@ func (s *Implementation) GetExternalUserInfoByLogin(ctx context.Context, query * return nil } -func (s *Implementation) GetAuthInfo(ctx context.Context, query *models.GetAuthInfoQuery) error { +func (s *AuthInfoStore) GetAuthInfo(ctx context.Context, query *models.GetAuthInfoQuery) error { if query.UserId == 0 && query.AuthId == "" { return models.ErrUserNotFound } @@ -51,7 +78,7 @@ func (s *Implementation) GetAuthInfo(ctx context.Context, query *models.GetAuthI var has bool var err error - err = s.SQLStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error { + err = s.sqlStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error { has, err = sess.Desc("created").Get(userAuth) return err }) @@ -88,12 +115,12 @@ func (s *Implementation) GetAuthInfo(ctx context.Context, query *models.GetAuthI return nil } -func (s *Implementation) SetAuthInfo(ctx context.Context, cmd *models.SetAuthInfoCommand) error { +func (s *AuthInfoStore) SetAuthInfo(ctx context.Context, cmd *models.SetAuthInfoCommand) error { authUser := &models.UserAuth{ UserId: cmd.UserId, AuthModule: cmd.AuthModule, AuthId: cmd.AuthId, - Created: getTime(), + Created: GetTime(), } if cmd.OAuthToken != nil { @@ -125,18 +152,18 @@ func (s *Implementation) SetAuthInfo(ctx context.Context, cmd *models.SetAuthInf authUser.OAuthExpiry = cmd.OAuthToken.Expiry } - return s.SQLStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error { + return s.sqlStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error { _, err := sess.Insert(authUser) return err }) } -func (s *Implementation) UpdateAuthInfo(ctx context.Context, cmd *models.UpdateAuthInfoCommand) error { +func (s *AuthInfoStore) UpdateAuthInfo(ctx context.Context, cmd *models.UpdateAuthInfoCommand) error { authUser := &models.UserAuth{ UserId: cmd.UserId, AuthModule: cmd.AuthModule, AuthId: cmd.AuthId, - Created: getTime(), + Created: GetTime(), } if cmd.OAuthToken != nil { @@ -173,22 +200,51 @@ func (s *Implementation) UpdateAuthInfo(ctx context.Context, cmd *models.UpdateA AuthModule: cmd.AuthModule, } - return s.SQLStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error { + return s.sqlStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error { upd, err := sess.Update(authUser, cond) s.logger.Debug("Updated user_auth", "user_id", cmd.UserId, "auth_module", cmd.AuthModule, "rows", upd) return err }) } -func (s *Implementation) DeleteAuthInfo(ctx context.Context, cmd *models.DeleteAuthInfoCommand) error { - return s.SQLStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error { +func (s *AuthInfoStore) DeleteAuthInfo(ctx context.Context, cmd *models.DeleteAuthInfoCommand) error { + return s.sqlStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error { _, err := sess.Delete(cmd.UserAuth) return err }) } +func (s *AuthInfoStore) GetUserById(id int64) (bool, *models.User, error) { + var ( + has bool + err error + ) + user := &models.User{} + err = s.sqlStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error { + has, err = sess.ID(id).Get(user) + return err + }) + if err != nil { + return false, nil, err + } + + return has, user, nil +} + +func (s *AuthInfoStore) GetUser(user *models.User) (bool, error) { + var err error + var has bool + + err = s.sqlStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error { + has, err = sess.Get(user) + return err + }) + + return has, err +} + // decodeAndDecrypt will decode the string with the standard base64 decoder and then decrypt it -func (s *Implementation) decodeAndDecrypt(str string) (string, error) { +func (s *AuthInfoStore) decodeAndDecrypt(str string) (string, error) { // Bail out if empty string since it'll cause a segfault in Decrypt if str == "" { return "", nil @@ -197,7 +253,7 @@ func (s *Implementation) decodeAndDecrypt(str string) (string, error) { if err != nil { return "", err } - decrypted, err := s.SecretsService.Decrypt(context.Background(), decoded) + decrypted, err := s.secretsService.Decrypt(context.Background(), decoded) if err != nil { return "", err } @@ -206,8 +262,8 @@ func (s *Implementation) decodeAndDecrypt(str string) (string, error) { // encryptAndEncode will encrypt a string with grafana's secretKey, and // then encode it with the standard bas64 encoder -func (s *Implementation) encryptAndEncode(str string) (string, error) { - encrypted, err := s.SecretsService.Encrypt(context.Background(), []byte(str), secrets.WithoutScope()) +func (s *AuthInfoStore) encryptAndEncode(str string) (string, error) { + encrypted, err := s.secretsService.Encrypt(context.Background(), []byte(str), secrets.WithoutScope()) if err != nil { return "", err } diff --git a/pkg/services/login/authinfoservice/service.go b/pkg/services/login/authinfoservice/service.go index e1a13cea8c2..b72c257d434 100644 --- a/pkg/services/login/authinfoservice/service.go +++ b/pkg/services/login/authinfoservice/service.go @@ -4,76 +4,29 @@ import ( "context" "errors" - "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/login" - "github.com/grafana/grafana/pkg/services/secrets" - "github.com/grafana/grafana/pkg/services/sqlstore" ) const genericOAuthModule = "oauth_generic_oauth" type Implementation struct { - Bus bus.Bus - SQLStore *sqlstore.SQLStore UserProtectionService login.UserProtectionService - SecretsService secrets.Service + authInfoStore login.Store logger log.Logger } -type Service interface { - GetAuthInfo(ctx context.Context, query *models.GetAuthInfoQuery) error -} - -func ProvideAuthInfoService(bus bus.Bus, store *sqlstore.SQLStore, userProtectionService login.UserProtectionService, - secretsService secrets.Service) *Implementation { +func ProvideAuthInfoService(userProtectionService login.UserProtectionService, authInfoStore login.Store) *Implementation { s := &Implementation{ - Bus: bus, - SQLStore: store, UserProtectionService: userProtectionService, - SecretsService: secretsService, + authInfoStore: authInfoStore, logger: log.New("login.authinfo"), } - s.Bus.AddHandler(s.GetExternalUserInfoByLogin) - s.Bus.AddHandler(s.GetAuthInfo) - s.Bus.AddHandler(s.SetAuthInfo) - s.Bus.AddHandler(s.UpdateAuthInfo) - s.Bus.AddHandler(s.DeleteAuthInfo) - return s } -func (s *Implementation) getUserById(id int64) (bool, *models.User, error) { - var ( - has bool - err error - ) - user := &models.User{} - err = s.SQLStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error { - has, err = sess.ID(id).Get(user) - return err - }) - if err != nil { - return false, nil, err - } - - return has, user, nil -} - -func (s *Implementation) getUser(user *models.User) (bool, error) { - var err error - var has bool - - err = s.SQLStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error { - has, err = sess.Get(user) - return err - }) - - return has, err -} - func (s *Implementation) LookupAndFix(ctx context.Context, query *models.GetUserByAuthInfoQuery) (bool, *models.User, *models.UserAuth, error) { authQuery := &models.GetAuthInfoQuery{} @@ -82,7 +35,7 @@ func (s *Implementation) LookupAndFix(ctx context.Context, query *models.GetUser authQuery.AuthModule = query.AuthModule authQuery.AuthId = query.AuthId - err := s.GetAuthInfo(ctx, authQuery) + err := s.authInfoStore.GetAuthInfo(ctx, authQuery) if !errors.Is(err, models.ErrUserNotFound) { if err != nil { return false, nil, nil, err @@ -90,7 +43,7 @@ func (s *Implementation) LookupAndFix(ctx context.Context, query *models.GetUser // if user id was specified and doesn't match the user_auth entry, remove it if query.UserId != 0 && query.UserId != authQuery.Result.UserId { - err := s.DeleteAuthInfo(ctx, &models.DeleteAuthInfoCommand{ + err := s.authInfoStore.DeleteAuthInfo(ctx, &models.DeleteAuthInfoCommand{ UserAuth: authQuery.Result, }) if err != nil { @@ -99,14 +52,14 @@ func (s *Implementation) LookupAndFix(ctx context.Context, query *models.GetUser return false, nil, nil, models.ErrUserNotFound } else { - has, user, err := s.getUserById(authQuery.Result.UserId) + has, user, err := s.authInfoStore.GetUserById(authQuery.Result.UserId) if err != nil { return false, nil, nil, err } if !has { // if the user has been deleted then remove the entry - err = s.DeleteAuthInfo(ctx, &models.DeleteAuthInfoCommand{ + err = s.authInfoStore.DeleteAuthInfo(ctx, &models.DeleteAuthInfoCommand{ UserAuth: authQuery.Result, }) if err != nil { @@ -131,7 +84,7 @@ func (s *Implementation) LookupByOneOf(userId int64, email string, login string) // If not found, try to find the user by id if userId != 0 { - foundUser, user, err = s.getUserById(userId) + foundUser, user, err = s.authInfoStore.GetUserById(userId) if err != nil { return false, nil, err } @@ -140,7 +93,7 @@ func (s *Implementation) LookupByOneOf(userId int64, email string, login string) // If not found, try to find the user by email address if !foundUser && email != "" { user = &models.User{Email: email} - foundUser, err = s.getUser(user) + foundUser, err = s.authInfoStore.GetUser(user) if err != nil { return false, nil, err } @@ -149,7 +102,7 @@ func (s *Implementation) LookupByOneOf(userId int64, email string, login string) // If not found, try to find the user by login if !foundUser && login != "" { user = &models.User{Login: login} - foundUser, err = s.getUser(user) + foundUser, err = s.authInfoStore.GetUser(user) if err != nil { return false, nil, err } @@ -168,7 +121,7 @@ func (s *Implementation) GenericOAuthLookup(ctx context.Context, authModule stri authQuery.AuthModule = authModule authQuery.AuthId = authId authQuery.UserId = userID - err := s.GetAuthInfo(ctx, authQuery) + err := s.authInfoStore.GetAuthInfo(ctx, authQuery) if err != nil { return nil, err } @@ -215,10 +168,18 @@ func (s *Implementation) LookupAndUpdate(ctx context.Context, query *models.GetU AuthModule: query.AuthModule, AuthId: query.AuthId, } - if err := s.SetAuthInfo(ctx, cmd); err != nil { + if err := s.authInfoStore.SetAuthInfo(ctx, cmd); err != nil { return nil, err } } return user, nil } + +func (s *Implementation) GetAuthInfo(ctx context.Context, query *models.GetAuthInfoQuery) error { + return s.authInfoStore.GetAuthInfo(ctx, query) +} + +func (s *Implementation) UpdateAuthInfo(ctx context.Context, cmd *models.UpdateAuthInfoCommand) error { + return s.authInfoStore.UpdateAuthInfo(ctx, cmd) +} diff --git a/pkg/services/login/authinfoservice/user_auth_test.go b/pkg/services/login/authinfoservice/user_auth_test.go index a5cf659db1b..7465654d8a0 100644 --- a/pkg/services/login/authinfoservice/user_auth_test.go +++ b/pkg/services/login/authinfoservice/user_auth_test.go @@ -1,6 +1,3 @@ -//go:build integration -// +build integration - package authinfoservice import ( @@ -11,7 +8,8 @@ import ( "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/models" - "github.com/grafana/grafana/pkg/services/secrets/database" + "github.com/grafana/grafana/pkg/services/login/authinfoservice/database" + secretstore "github.com/grafana/grafana/pkg/services/secrets/database" secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/stretchr/testify/require" @@ -21,8 +19,9 @@ import ( //nolint:goconst func TestUserAuth(t *testing.T) { sqlStore := sqlstore.InitTestDB(t) - secretsService := secretsManager.SetupTestService(t, database.ProvideSecretsStore(sqlStore)) - srv := ProvideAuthInfoService(bus.New(), sqlStore, &OSSUserProtectionImpl{}, secretsService) + secretsService := secretsManager.SetupTestService(t, secretstore.ProvideSecretsStore(sqlStore)) + authInfoStore := database.ProvideAuthInfoStore(sqlStore, bus.New(), secretsService) + srv := ProvideAuthInfoService(&OSSUserProtectionImpl{}, authInfoStore) t.Run("Given 5 users", func(t *testing.T) { for i := 0; i < 5; i++ { @@ -31,7 +30,7 @@ func TestUserAuth(t *testing.T) { Name: fmt.Sprint("user", i), Login: fmt.Sprint("loginuser", i), } - _, err := srv.SQLStore.CreateUser(context.Background(), cmd) + _, err := sqlStore.CreateUser(context.Background(), cmd) require.Nil(t, err) } @@ -111,12 +110,11 @@ func TestUserAuth(t *testing.T) { require.Equal(t, user.Login, "loginuser1") // remove user - srv.SQLStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error { - sess.Exec("DELETE FROM "+srv.SQLStore.Dialect.Quote("user")+" WHERE id=?", user.Id) - require.NoError(t, err) - - return nil + err = sqlStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error { + _, err := sess.Exec("DELETE FROM "+sqlStore.Dialect.Quote("user")+" WHERE id=?", user.Id) + return err }) + require.NoError(t, err) // get via user_auth for deleted user query = &models.GetUserByAuthInfoQuery{AuthModule: "test", AuthId: "test"} @@ -152,7 +150,7 @@ func TestUserAuth(t *testing.T) { AuthModule: query.AuthModule, OAuthToken: token, } - err = srv.UpdateAuthInfo(context.Background(), cmd) + err = srv.authInfoStore.UpdateAuthInfo(context.Background(), cmd) require.Nil(t, err) @@ -160,7 +158,7 @@ func TestUserAuth(t *testing.T) { UserId: user.Id, } - err = srv.GetAuthInfo(context.Background(), getAuthQuery) + err = srv.authInfoStore.GetAuthInfo(context.Background(), getAuthQuery) require.Nil(t, err) require.Equal(t, token.AccessToken, getAuthQuery.Result.OAuthAccessToken) @@ -188,20 +186,20 @@ func TestUserAuth(t *testing.T) { // Calling srv.LookupAndUpdateQuery on an existing user will populate an entry in the user_auth table // Make the first log-in during the past - getTime = func() time.Time { return time.Now().AddDate(0, 0, -2) } + database.GetTime = func() time.Time { return time.Now().AddDate(0, 0, -2) } query := &models.GetUserByAuthInfoQuery{Login: login, AuthModule: "test1", AuthId: "test1"} user, err := srv.LookupAndUpdate(context.Background(), query) - getTime = time.Now + database.GetTime = time.Now require.Nil(t, err) require.Equal(t, user.Login, login) // Add a second auth module for this user // Have this module's last log-in be more recent - getTime = func() time.Time { return time.Now().AddDate(0, 0, -1) } + database.GetTime = func() time.Time { return time.Now().AddDate(0, 0, -1) } query = &models.GetUserByAuthInfoQuery{Login: login, AuthModule: "test2", AuthId: "test2"} user, err = srv.LookupAndUpdate(context.Background(), query) - getTime = time.Now + database.GetTime = time.Now require.Nil(t, err) require.Equal(t, user.Login, login) @@ -211,14 +209,14 @@ func TestUserAuth(t *testing.T) { UserId: user.Id, } - err = srv.GetAuthInfo(context.Background(), getAuthQuery) + err = authInfoStore.GetAuthInfo(context.Background(), getAuthQuery) require.Nil(t, err) require.Equal(t, getAuthQuery.Result.AuthModule, "test2") // "log in" again with the first auth module updateAuthCmd := &models.UpdateAuthInfoCommand{UserId: user.Id, AuthModule: "test1", AuthId: "test1"} - err = srv.UpdateAuthInfo(context.Background(), updateAuthCmd) + err = authInfoStore.UpdateAuthInfo(context.Background(), updateAuthCmd) require.Nil(t, err) @@ -227,7 +225,7 @@ func TestUserAuth(t *testing.T) { UserId: user.Id, } - err = srv.GetAuthInfo(context.Background(), getAuthQuery) + err = authInfoStore.GetAuthInfo(context.Background(), getAuthQuery) require.Nil(t, err) require.Equal(t, getAuthQuery.Result.AuthModule, "test1") @@ -238,19 +236,19 @@ func TestUserAuth(t *testing.T) { login := "loginuser0" // Expect to pass since there's a matching login user - getTime = func() time.Time { return time.Now().AddDate(0, 0, -2) } + database.GetTime = func() time.Time { return time.Now().AddDate(0, 0, -2) } query := &models.GetUserByAuthInfoQuery{Login: login, AuthModule: genericOAuthModule, AuthId: ""} user, err := srv.LookupAndUpdate(context.Background(), query) - getTime = time.Now + database.GetTime = time.Now require.Nil(t, err) require.Equal(t, user.Login, login) // Should throw a "user not found" error since there's no matching login user - getTime = func() time.Time { return time.Now().AddDate(0, 0, -2) } + database.GetTime = func() time.Time { return time.Now().AddDate(0, 0, -2) } query = &models.GetUserByAuthInfoQuery{Login: "aloginuser", AuthModule: genericOAuthModule, AuthId: ""} user, err = srv.LookupAndUpdate(context.Background(), query) - getTime = time.Now + database.GetTime = time.Now require.NotNil(t, err) require.Nil(t, user) diff --git a/pkg/services/login/loginservice/loginservice_test.go b/pkg/services/login/loginservice/loginservice_test.go index 14f1c146b0f..480c6376fc8 100644 --- a/pkg/services/login/loginservice/loginservice_test.go +++ b/pkg/services/login/loginservice/loginservice_test.go @@ -84,6 +84,10 @@ func (a *authInfoServiceMock) LookupAndUpdate(ctx context.Context, query *models return a.user, a.err } +func (a *authInfoServiceMock) GetAuthInfo(ctx context.Context, query *models.GetAuthInfoQuery) error { + return nil +} + func Test_teamSync(t *testing.T) { b := bus.New() authInfoMock := &authInfoServiceMock{} diff --git a/pkg/services/login/userprotection.go b/pkg/services/login/userprotection.go index dcc7d026d24..1bc65f9bb83 100644 --- a/pkg/services/login/userprotection.go +++ b/pkg/services/login/userprotection.go @@ -1,7 +1,22 @@ package login -import "github.com/grafana/grafana/pkg/models" +import ( + "context" + + "github.com/grafana/grafana/pkg/models" +) type UserProtectionService interface { AllowUserMapping(user *models.User, authModule string) error } + +type Store interface { + GetExternalUserInfoByLogin(ctx context.Context, query *models.GetExternalUserInfoByLoginQuery) error + GetAuthInfo(ctx context.Context, query *models.GetAuthInfoQuery) error + SetAuthInfo(ctx context.Context, cmd *models.SetAuthInfoCommand) error + UpdateAuthInfo(ctx context.Context, cmd *models.UpdateAuthInfoCommand) error + DeleteAuthInfo(ctx context.Context, cmd *models.DeleteAuthInfoCommand) error + + GetUserById(id int64) (bool, *models.User, error) + GetUser(user *models.User) (bool, error) +}