LoginAttempt: Move logic around login attempts into the service (#58962)

* LoginAttemps: Remove from sqlstore mock

* LoginAttemps: Move from models package to service package

* LoginAttemps: Implement functionallity from brute force login in service

* LoginAttemps: Call service

* LoginAttempts: Update name and remove internal functions

* LoginAttempts: Add tests

* LoginAttempt: Add service fake

* LoginAttempt: Register service as a background_services and remove job
from cleanup service

* LoginAttemps: Remove result from command struct

* LoginAttempt: No longer pass pointers
This commit is contained in:
Karl Persson
2022-11-22 11:37:18 +01:00
committed by GitHub
parent 082c8ba7a0
commit 189bf102cf
18 changed files with 388 additions and 415 deletions
+1 -32
View File
@@ -20,7 +20,6 @@ import (
"github.com/grafana/grafana/pkg/services/annotations"
"github.com/grafana/grafana/pkg/services/dashboardsnapshots"
dashver "github.com/grafana/grafana/pkg/services/dashboardversion"
"github.com/grafana/grafana/pkg/services/loginattempt"
"github.com/grafana/grafana/pkg/services/ngalert/image"
"github.com/grafana/grafana/pkg/services/queryhistory"
"github.com/grafana/grafana/pkg/services/shorturls"
@@ -31,7 +30,7 @@ import (
func ProvideService(cfg *setting.Cfg, serverLockService *serverlock.ServerLockService,
shortURLService shorturls.Service, sqlstore db.DB, queryHistoryService queryhistory.Service,
dashboardVersionService dashver.Service, dashSnapSvc dashboardsnapshots.Service, deleteExpiredImageService *image.DeleteExpiredService,
loginAttemptService loginattempt.Service, tempUserService tempuser.Service, tracer tracing.Tracer, annotationCleaner annotations.Cleaner) *CleanUpService {
tempUserService tempuser.Service, tracer tracing.Tracer, annotationCleaner annotations.Cleaner) *CleanUpService {
s := &CleanUpService{
Cfg: cfg,
ServerLockService: serverLockService,
@@ -42,7 +41,6 @@ func ProvideService(cfg *setting.Cfg, serverLockService *serverlock.ServerLockSe
dashboardVersionService: dashboardVersionService,
dashboardSnapshotService: dashSnapSvc,
deleteExpiredImageService: deleteExpiredImageService,
loginAttemptService: loginAttemptService,
tempUserService: tempUserService,
tracer: tracer,
annotationCleaner: annotationCleaner,
@@ -61,7 +59,6 @@ type CleanUpService struct {
dashboardVersionService dashver.Service
dashboardSnapshotService dashboardsnapshots.Service
deleteExpiredImageService *image.DeleteExpiredService
loginAttemptService loginattempt.Service
tempUserService tempuser.Service
annotationCleaner annotations.Cleaner
}
@@ -106,7 +103,6 @@ func (srv *CleanUpService) clean(ctx context.Context) {
{"expire old user invites", srv.expireOldUserInvites},
{"delete stale short URLs", srv.deleteStaleShortURLs},
{"delete stale query history", srv.deleteStaleQueryHistory},
{"delete old login attempts", srv.deleteOldLoginAttempts},
}
logger := srv.log.FromContext(ctx)
@@ -227,33 +223,6 @@ func (srv *CleanUpService) deleteExpiredImages(ctx context.Context) {
}
}
func (srv *CleanUpService) deleteOldLoginAttempts(ctx context.Context) {
logger := srv.log.FromContext(ctx)
err := srv.ServerLockService.LockAndExecute(ctx, "delete old login attempts",
time.Minute*10, func(context.Context) {
srv.deleteOldLoginAttemptsWithoutLock(ctx)
})
if err != nil {
logger.Error("failed to lock and execute cleanup of old login attempts", "error", err)
}
}
func (srv *CleanUpService) deleteOldLoginAttemptsWithoutLock(ctx context.Context) {
logger := srv.log.FromContext(ctx)
if srv.Cfg.DisableBruteForceLoginProtection {
return
}
cmd := models.DeleteOldLoginAttemptsCommand{
OlderThan: time.Now().Add(time.Minute * -10),
}
if err := srv.loginAttemptService.DeleteOldLoginAttempts(ctx, &cmd); err != nil {
logger.Error("Problem deleting expired login attempts", "error", err.Error())
} else {
logger.Debug("Deleted expired login attempts", "rows affected", cmd.DeletedRows)
}
}
func (srv *CleanUpService) expireOldUserInvites(ctx context.Context) {
logger := srv.log.FromContext(ctx)
maxInviteLifetime := srv.Cfg.UserInviteMaxLifetime
+12 -5
View File
@@ -2,12 +2,19 @@ package loginattempt
import (
"context"
"github.com/grafana/grafana/pkg/models"
)
type Service interface {
CreateLoginAttempt(ctx context.Context, cmd *models.CreateLoginAttemptCommand) error
DeleteOldLoginAttempts(ctx context.Context, cmd *models.DeleteOldLoginAttemptsCommand) error
GetUserLoginAttemptCount(ctx context.Context, query *models.GetUserLoginAttemptCountQuery) error
// Add adds a new login attempt record for provided username
Add(ctx context.Context, username, IPAddress string) error
// Validate checks if username has to many login attempts inside a window.
// Will return true if provided username do not have too many attempts.
Validate(ctx context.Context, username string) (bool, error)
}
type LoginAttempt struct {
Id int64
Username string
IpAddress string
Created int64
}
@@ -5,40 +5,95 @@ import (
"time"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/loginattempt"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/serverlock"
"github.com/grafana/grafana/pkg/setting"
)
type Service struct {
store store
}
const (
maxInvalidLoginAttempts int64 = 5
loginAttemptsWindow = time.Minute * 5
)
func ProvideService(db db.DB) loginattempt.Service {
func ProvideService(db db.DB, cfg *setting.Cfg, lock *serverlock.ServerLockService) *Service {
return &Service{
store: &xormStore{db: db, now: time.Now},
&xormStore{db: db, now: time.Now},
cfg,
lock,
log.New("login_attempt"),
}
}
func (s *Service) CreateLoginAttempt(ctx context.Context, cmd *models.CreateLoginAttemptCommand) error {
err := s.store.CreateLoginAttempt(ctx, cmd)
if err != nil {
return err
}
return nil
type Service struct {
store store
cfg *setting.Cfg
lock *serverlock.ServerLockService
logger log.Logger
}
func (s *Service) DeleteOldLoginAttempts(ctx context.Context, cmd *models.DeleteOldLoginAttemptsCommand) error {
err := s.store.DeleteOldLoginAttempts(ctx, cmd)
if err != nil {
return err
func (s *Service) Run(ctx context.Context) error {
// no need to run clean up job if it is disabled
if s.cfg.DisableBruteForceLoginProtection {
return nil
}
ticker := time.NewTicker(time.Minute * 10)
for {
select {
case <-ticker.C:
s.cleanup(ctx)
case <-ctx.Done():
return ctx.Err()
}
}
return nil
}
func (s *Service) GetUserLoginAttemptCount(ctx context.Context, cmd *models.GetUserLoginAttemptCountQuery) error {
err := s.store.GetUserLoginAttemptCount(ctx, cmd)
func (s *Service) Add(ctx context.Context, username, IPAddress string) error {
if s.cfg.DisableBruteForceLoginProtection {
return nil
}
return s.store.CreateLoginAttempt(ctx, CreateLoginAttemptCommand{
Username: username,
IpAddress: IPAddress,
})
}
func (s *Service) Validate(ctx context.Context, username string) (bool, error) {
if s.cfg.DisableBruteForceLoginProtection {
return true, nil
}
loginAttemptCountQuery := GetUserLoginAttemptCountQuery{
Username: username,
Since: time.Now().Add(-loginAttemptsWindow),
}
count, err := s.store.GetUserLoginAttemptCount(ctx, loginAttemptCountQuery)
if err != nil {
return err
return false, err
}
if count >= maxInvalidLoginAttempts {
return false, nil
}
return true, nil
}
func (s *Service) cleanup(ctx context.Context) {
err := s.lock.LockAndExecute(ctx, "delete old login attempts", time.Minute*10, func(context.Context) {
cmd := DeleteOldLoginAttemptsCommand{
OlderThan: time.Now().Add(time.Minute * -10),
}
if deletedLogs, err := s.store.DeleteOldLoginAttempts(ctx, cmd); err != nil {
s.logger.Error("Problem deleting expired login attempts", "error", err.Error())
} else {
s.logger.Debug("Deleted expired login attempts", "rows affected", deletedLogs)
}
})
if err != nil {
s.logger.Error("failed to lock and execute cleanup of old login attempts", "error", err)
}
return nil
}
@@ -0,0 +1,98 @@
package loginattemptimpl
import (
"context"
"testing"
"github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/assert"
)
func TestService_Validate(t *testing.T) {
testCases := []struct {
name string
loginAttempts int64
disabled bool
expected bool
expectedErr error
}{
{
name: "When brute force protection enabled and user login attempt count is less than max",
loginAttempts: maxInvalidLoginAttempts - 1,
expected: true,
expectedErr: nil,
},
{
name: "When brute force protection enabled and user login attempt count equals max",
loginAttempts: maxInvalidLoginAttempts,
expected: false,
expectedErr: nil,
},
{
name: "When brute force protection enabled and user login attempt count is greater than max",
loginAttempts: maxInvalidLoginAttempts + 1,
expected: false,
expectedErr: nil,
},
{
name: "When brute force protection disabled and user login attempt count is less than max",
loginAttempts: maxInvalidLoginAttempts - 1,
disabled: true,
expected: true,
expectedErr: nil,
},
{
name: "When brute force protection disabled and user login attempt count equals max",
loginAttempts: maxInvalidLoginAttempts,
disabled: true,
expected: true,
expectedErr: nil,
},
{
name: "When brute force protection disabled and user login attempt count is greater than max",
loginAttempts: maxInvalidLoginAttempts + 1,
disabled: true,
expected: true,
expectedErr: nil,
},
}
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
cfg := setting.NewCfg()
cfg.DisableBruteForceLoginProtection = tt.disabled
service := &Service{
store: fakeStore{
ExpectedCount: tt.loginAttempts,
ExpectedErr: tt.expectedErr,
},
cfg: cfg,
}
ok, err := service.Validate(context.Background(), "test")
assert.Equal(t, tt.expected, ok)
assert.Equal(t, tt.expectedErr, err)
})
}
}
var _ store = new(fakeStore)
type fakeStore struct {
ExpectedErr error
ExpectedCount int64
ExpectedDeletedRows int64
}
func (f fakeStore) GetUserLoginAttemptCount(ctx context.Context, query GetUserLoginAttemptCountQuery) (int64, error) {
return f.ExpectedCount, f.ExpectedErr
}
func (f fakeStore) CreateLoginAttempt(ctx context.Context, command CreateLoginAttemptCommand) error {
return f.ExpectedErr
}
func (f fakeStore) DeleteOldLoginAttempts(ctx context.Context, command DeleteOldLoginAttemptsCommand) (int64, error) {
return f.ExpectedDeletedRows, f.ExpectedErr
}
@@ -0,0 +1,23 @@
package loginattemptimpl
import (
"time"
"github.com/grafana/grafana/pkg/services/loginattempt"
)
type CreateLoginAttemptCommand struct {
Username string
IpAddress string
Result loginattempt.LoginAttempt
}
type GetUserLoginAttemptCountQuery struct {
Username string
Since time.Time
}
type DeleteOldLoginAttemptsCommand struct {
OlderThan time.Time
}
@@ -6,7 +6,7 @@ import (
"time"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/loginattempt"
)
type xormStore struct {
@@ -15,14 +15,14 @@ type xormStore struct {
}
type store interface {
CreateLoginAttempt(context.Context, *models.CreateLoginAttemptCommand) error
DeleteOldLoginAttempts(context.Context, *models.DeleteOldLoginAttemptsCommand) error
GetUserLoginAttemptCount(context.Context, *models.GetUserLoginAttemptCountQuery) error
CreateLoginAttempt(ctx context.Context, cmd CreateLoginAttemptCommand) error
DeleteOldLoginAttempts(ctx context.Context, cmd DeleteOldLoginAttemptsCommand) (int64, error)
GetUserLoginAttemptCount(ctx context.Context, query GetUserLoginAttemptCountQuery) (int64, error)
}
func (xs *xormStore) CreateLoginAttempt(ctx context.Context, cmd *models.CreateLoginAttemptCommand) error {
func (xs *xormStore) CreateLoginAttempt(ctx context.Context, cmd CreateLoginAttemptCommand) error {
return xs.db.WithTransactionalDbSession(ctx, func(sess *db.Session) error {
loginAttempt := models.LoginAttempt{
loginAttempt := loginattempt.LoginAttempt{
Username: cmd.Username,
IpAddress: cmd.IpAddress,
Created: xs.now().Unix(),
@@ -38,8 +38,9 @@ func (xs *xormStore) CreateLoginAttempt(ctx context.Context, cmd *models.CreateL
})
}
func (xs *xormStore) DeleteOldLoginAttempts(ctx context.Context, cmd *models.DeleteOldLoginAttemptsCommand) error {
return xs.db.WithTransactionalDbSession(ctx, func(sess *db.Session) error {
func (xs *xormStore) DeleteOldLoginAttempts(ctx context.Context, cmd DeleteOldLoginAttemptsCommand) (int64, error) {
var deletedRows int64
err := xs.db.WithTransactionalDbSession(ctx, func(sess *db.Session) error {
var maxId int64
sql := "SELECT max(id) as id FROM login_attempt WHERE created < ?"
result, err := sess.Query(sql, cmd.OlderThan.Unix())
@@ -59,31 +60,38 @@ func (xs *xormStore) DeleteOldLoginAttempts(ctx context.Context, cmd *models.Del
sql = "DELETE FROM login_attempt WHERE id <= ?"
if result, err := sess.Exec(sql, maxId); err != nil {
return err
} else if cmd.DeletedRows, err = result.RowsAffected(); err != nil {
return err
}
return nil
})
}
func (xs *xormStore) GetUserLoginAttemptCount(ctx context.Context, query *models.GetUserLoginAttemptCountQuery) error {
return xs.db.WithDbSession(ctx, func(dbSession *db.Session) error {
loginAttempt := new(models.LoginAttempt)
total, err := dbSession.
Where("username = ?", query.Username).
And("created >= ?", query.Since.Unix()).
Count(loginAttempt)
deleteResult, err := sess.Exec(sql, maxId)
if err != nil {
return err
}
query.Result = total
deletedRows, err = deleteResult.RowsAffected()
if err != nil {
return err
}
return nil
})
return deletedRows, err
}
func (xs *xormStore) GetUserLoginAttemptCount(ctx context.Context, query GetUserLoginAttemptCountQuery) (int64, error) {
var total int64
err := xs.db.WithDbSession(ctx, func(dbSession *db.Session) error {
var queryErr error
loginAttempt := new(loginattempt.LoginAttempt)
total, queryErr = dbSession.
Where("username = ?", query.Username).
And("created >= ?", query.Since.Unix()).
Count(loginAttempt)
if queryErr != nil {
return queryErr
}
return nil
})
return total, err
}
func toInt64(i interface{}) int64 {
@@ -8,15 +8,12 @@ import (
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/loginattempt"
)
func TestIntegrationLoginAttemptsQuery(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
var loginAttemptService loginattempt.Service
user := "user"
beginningOfTime := time.Date(2017, 10, 22, 8, 0, 0, 0, time.Local)
@@ -25,58 +22,60 @@ func TestIntegrationLoginAttemptsQuery(t *testing.T) {
for _, test := range []struct {
Name string
Query models.GetUserLoginAttemptCountQuery
Query GetUserLoginAttemptCountQuery
Err error
Result int64
}{
{
"Should return a total count of zero login attempts when comparing since beginning of time + 2min and 1s",
models.GetUserLoginAttemptCountQuery{Username: user, Since: timePlusTwoMinutes.Add(time.Second * 1)}, nil, 0,
GetUserLoginAttemptCountQuery{Username: user, Since: timePlusTwoMinutes.Add(time.Second * 1)}, nil, 0,
},
{
"Should return a total count of zero login attempts when comparing since beginning of time + 2min and 1s",
models.GetUserLoginAttemptCountQuery{Username: user, Since: timePlusTwoMinutes.Add(time.Second * 1)}, nil, 0,
GetUserLoginAttemptCountQuery{Username: user, Since: timePlusTwoMinutes.Add(time.Second * 1)}, nil, 0,
},
{
"Should return the total count of login attempts since beginning of time",
models.GetUserLoginAttemptCountQuery{Username: user, Since: beginningOfTime}, nil, 3,
GetUserLoginAttemptCountQuery{Username: user, Since: beginningOfTime}, nil, 3,
},
{
"Should return the total count of login attempts since beginning of time + 1min",
models.GetUserLoginAttemptCountQuery{Username: user, Since: timePlusOneMinute}, nil, 2,
GetUserLoginAttemptCountQuery{Username: user, Since: timePlusOneMinute}, nil, 2,
},
{
"Should return the total count of login attempts since beginning of time + 2min",
models.GetUserLoginAttemptCountQuery{Username: user, Since: timePlusTwoMinutes}, nil, 1,
GetUserLoginAttemptCountQuery{Username: user, Since: timePlusTwoMinutes}, nil, 1,
},
} {
mockTime := beginningOfTime
loginAttemptService = &Service{
store: &xormStore{
db: db.InitTestDB(t),
now: func() time.Time { return mockTime },
},
s := &xormStore{
db: db.InitTestDB(t),
now: func() time.Time { return mockTime },
}
err := loginAttemptService.CreateLoginAttempt(context.Background(), &models.CreateLoginAttemptCommand{
err := s.CreateLoginAttempt(context.Background(), CreateLoginAttemptCommand{
Username: user,
IpAddress: "192.168.0.1",
})
require.Nil(t, err)
mockTime = timePlusOneMinute
err = loginAttemptService.CreateLoginAttempt(context.Background(), &models.CreateLoginAttemptCommand{
err = s.CreateLoginAttempt(context.Background(), CreateLoginAttemptCommand{
Username: user,
IpAddress: "192.168.0.1",
})
require.Nil(t, err)
mockTime = timePlusTwoMinutes
err = loginAttemptService.CreateLoginAttempt(context.Background(), &models.CreateLoginAttemptCommand{
err = s.CreateLoginAttempt(context.Background(), CreateLoginAttemptCommand{
Username: user,
IpAddress: "192.168.0.1",
})
require.Nil(t, err)
err = loginAttemptService.GetUserLoginAttemptCount(context.Background(), &test.Query)
count, err := s.GetUserLoginAttemptCount(context.Background(), test.Query)
require.Equal(t, test.Err, err, test.Name)
require.Equal(t, test.Result, test.Query.Result, test.Name)
require.Equal(t, test.Result, count, test.Name)
}
}
@@ -84,7 +83,6 @@ func TestIntegrationLoginAttemptsDelete(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
var loginAttemptService loginattempt.Service
user := "user"
beginningOfTime := time.Date(2017, 10, 22, 8, 0, 0, 0, time.Local)
@@ -93,53 +91,55 @@ func TestIntegrationLoginAttemptsDelete(t *testing.T) {
for _, test := range []struct {
Name string
Cmd models.DeleteOldLoginAttemptsCommand
Cmd DeleteOldLoginAttemptsCommand
Err error
DeletedRows int64
}{
{
"Should return deleted rows older than beginning of time",
models.DeleteOldLoginAttemptsCommand{OlderThan: beginningOfTime}, nil, 0,
DeleteOldLoginAttemptsCommand{OlderThan: beginningOfTime}, nil, 0,
},
{
"Should return deleted rows older than beginning of time + 1min",
models.DeleteOldLoginAttemptsCommand{OlderThan: timePlusOneMinute}, nil, 1,
DeleteOldLoginAttemptsCommand{OlderThan: timePlusOneMinute}, nil, 1,
},
{
"Should return deleted rows older than beginning of time + 2min",
models.DeleteOldLoginAttemptsCommand{OlderThan: timePlusTwoMinutes}, nil, 2,
DeleteOldLoginAttemptsCommand{OlderThan: timePlusTwoMinutes}, nil, 2,
},
{
"Should return deleted rows older than beginning of time + 2min and 1s",
models.DeleteOldLoginAttemptsCommand{OlderThan: timePlusTwoMinutes.Add(time.Second * 1)}, nil, 3,
DeleteOldLoginAttemptsCommand{OlderThan: timePlusTwoMinutes.Add(time.Second * 1)}, nil, 3,
},
} {
mockTime := beginningOfTime
loginAttemptService = &Service{
store: &xormStore{
db: db.InitTestDB(t),
now: func() time.Time { return mockTime },
},
s := &xormStore{
db: db.InitTestDB(t),
now: func() time.Time { return mockTime },
}
err := loginAttemptService.CreateLoginAttempt(context.Background(), &models.CreateLoginAttemptCommand{
err := s.CreateLoginAttempt(context.Background(), CreateLoginAttemptCommand{
Username: user,
IpAddress: "192.168.0.1",
})
require.Nil(t, err)
mockTime = timePlusOneMinute
err = loginAttemptService.CreateLoginAttempt(context.Background(), &models.CreateLoginAttemptCommand{
err = s.CreateLoginAttempt(context.Background(), CreateLoginAttemptCommand{
Username: user,
IpAddress: "192.168.0.1",
})
require.Nil(t, err)
mockTime = timePlusTwoMinutes
err = loginAttemptService.CreateLoginAttempt(context.Background(), &models.CreateLoginAttemptCommand{
err = s.CreateLoginAttempt(context.Background(), CreateLoginAttemptCommand{
Username: user,
IpAddress: "192.168.0.1",
})
require.Nil(t, err)
err = loginAttemptService.DeleteOldLoginAttempts(context.Background(), &test.Cmd)
deletedRows, err := s.DeleteOldLoginAttempts(context.Background(), test.Cmd)
require.Equal(t, test.Err, err, test.Name)
require.Equal(t, test.DeletedRows, test.Cmd.DeletedRows, test.Name)
require.Equal(t, test.DeletedRows, deletedRows, test.Name)
}
}
@@ -0,0 +1,22 @@
package loginattempttest
import (
"context"
"github.com/grafana/grafana/pkg/services/loginattempt"
)
var _ loginattempt.Service = new(FakeLoginAttemptService)
type FakeLoginAttemptService struct {
ExpectedValid bool
ExpectedErr error
}
func (f FakeLoginAttemptService) Add(ctx context.Context, username, IPAddress string) error {
return f.ExpectedErr
}
func (f FakeLoginAttemptService) Validate(ctx context.Context, username string) (bool, error) {
return f.ExpectedValid, f.ExpectedErr
}
@@ -0,0 +1,27 @@
package loginattempttest
import (
"context"
"github.com/grafana/grafana/pkg/services/loginattempt"
)
var _ loginattempt.Service = new(MockLoginAttemptService)
type MockLoginAttemptService struct {
AddCalled bool
ValidateCalled bool
ExpectedValid bool
ExpectedErr error
}
func (f *MockLoginAttemptService) Add(ctx context.Context, username, IPAddress string) error {
f.AddCalled = true
return f.ExpectedErr
}
func (f *MockLoginAttemptService) Validate(ctx context.Context, username string) (bool, error) {
f.ValidateCalled = true
return f.ExpectedValid, f.ExpectedErr
}
+1 -17
View File
@@ -17,8 +17,7 @@ type OrgListResponse []struct {
Response error
}
type SQLStoreMock struct {
LastGetAlertsQuery *models.GetAlertsQuery
LastLoginAttemptCommand *models.CreateLoginAttemptCommand
LastGetAlertsQuery *models.GetAlertsQuery
ExpectedUser *user.User
ExpectedTeamsByUser []*models.TeamDTO
@@ -28,7 +27,6 @@ type SQLStoreMock struct {
ExpectedDataSourcesAccessStats []*models.DataSourceAccessStats
ExpectedNotifierUsageStats []*models.NotifierUsageStats
ExpectedSignedInUser *user.SignedInUser
ExpectedLoginAttempts int64
ExpectedError error
}
@@ -130,11 +128,6 @@ func (m *SQLStoreMock) GetSqlxSession() *session.SessionDB {
return nil
}
func (m *SQLStoreMock) CreateLoginAttempt(ctx context.Context, cmd *models.CreateLoginAttemptCommand) error {
m.LastLoginAttemptCommand = cmd
return m.ExpectedError
}
func (m *SQLStoreMock) GetAlertById(ctx context.Context, query *models.GetAlertByIdQuery) error {
query.Result = m.ExpectedAlert
return m.ExpectedError
@@ -144,19 +137,10 @@ func (m *SQLStoreMock) GetAlertNotificationUidWithId(ctx context.Context, query
return m.ExpectedError
}
func (m *SQLStoreMock) DeleteOldLoginAttempts(ctx context.Context, cmd *models.DeleteOldLoginAttemptsCommand) error {
return m.ExpectedError
}
func (m *SQLStoreMock) GetAlertNotificationsWithUidToSend(ctx context.Context, query *models.GetAlertNotificationsWithUidToSendQuery) error {
return m.ExpectedError
}
func (m *SQLStoreMock) GetUserLoginAttemptCount(ctx context.Context, query *models.GetUserLoginAttemptCountQuery) error {
query.Result = m.ExpectedLoginAttempts
return m.ExpectedError
}
func (m *SQLStoreMock) GetAlertStatesForDashboard(ctx context.Context, query *models.GetAlertStatesForDashboardQuery) error {
return m.ExpectedError
}