mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
AuthService: Move database logic to its own class and package (#44835)
* Move database logic to its own class and package * Fix lint
This commit is contained in:
parent
9b3cb4a306
commit
3ce0730558
@ -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()
|
||||
|
@ -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{
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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{}
|
||||
|
@ -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)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user