86 lines
2.2 KiB
Go
86 lines
2.2 KiB
Go
package store
|
|
|
|
import "github.uio.no/torjus/apiary/models"
|
|
|
|
type CachingStore struct {
|
|
backend LoginAttemptStore
|
|
|
|
totalStatsCache []StatsResult
|
|
usernameQueryCache map[string][]models.LoginAttempt
|
|
passwordQueryCache map[string][]models.LoginAttempt
|
|
ipQueryCache map[string][]models.LoginAttempt
|
|
}
|
|
|
|
func NewCachingStore(backend LoginAttemptStore) *CachingStore {
|
|
return &CachingStore{
|
|
backend: backend,
|
|
usernameQueryCache: make(map[string][]models.LoginAttempt),
|
|
passwordQueryCache: make(map[string][]models.LoginAttempt),
|
|
ipQueryCache: make(map[string][]models.LoginAttempt),
|
|
}
|
|
}
|
|
|
|
func (s *CachingStore) AddAttempt(l *models.LoginAttempt) error {
|
|
s.totalStatsCache = nil
|
|
delete(s.ipQueryCache, l.RemoteIP.String())
|
|
delete(s.passwordQueryCache, l.Password)
|
|
delete(s.usernameQueryCache, l.Username)
|
|
return s.backend.AddAttempt(l)
|
|
}
|
|
|
|
func (s *CachingStore) All() ([]models.LoginAttempt, error) {
|
|
return s.backend.All()
|
|
}
|
|
|
|
func (s *CachingStore) Stats(statType LoginStats, limit int) ([]StatsResult, error) {
|
|
// Only cache totals for now, as they are the most queried
|
|
if statType == LoginStatsTotals {
|
|
if s.totalStatsCache != nil {
|
|
return s.totalStatsCache, nil
|
|
}
|
|
stats, err := s.backend.Stats(statType, limit)
|
|
if err != nil {
|
|
return stats, err
|
|
}
|
|
s.totalStatsCache = stats
|
|
|
|
return stats, err
|
|
}
|
|
|
|
// TODO: Maybe cache the default limits
|
|
|
|
return s.backend.Stats(statType, limit)
|
|
}
|
|
|
|
func (s *CachingStore) Query(query AttemptQuery) ([]models.LoginAttempt, error) {
|
|
switch query.QueryType {
|
|
case AttemptQueryTypeIP:
|
|
if attempts, ok := s.ipQueryCache[query.Query]; ok {
|
|
return attempts, nil
|
|
}
|
|
case AttemptQueryTypePassword:
|
|
if attempts, ok := s.passwordQueryCache[query.Query]; ok {
|
|
return attempts, nil
|
|
}
|
|
case AttemptQueryTypeUsername:
|
|
if attempts, ok := s.usernameQueryCache[query.Query]; ok {
|
|
return attempts, nil
|
|
}
|
|
}
|
|
attempts, err := s.backend.Query(query)
|
|
if err != nil {
|
|
return attempts, err
|
|
}
|
|
|
|
switch query.QueryType {
|
|
case AttemptQueryTypeIP:
|
|
s.ipQueryCache[query.Query] = attempts
|
|
case AttemptQueryTypeUsername:
|
|
s.ipQueryCache[query.Query] = attempts
|
|
case AttemptQueryTypePassword:
|
|
s.ipQueryCache[query.Query] = attempts
|
|
}
|
|
|
|
return attempts, err
|
|
}
|