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 }