package cache import ( "sync" "time" "github.com/fiskerinc/cloud-services/pkg/common" "github.com/pkg/errors" "github.com/fiskerinc/cloud-services/pkg/db/queries" "github.com/ReneKroon/ttlcache/v2" ) const ApiKeyHeader = "Api-Key" var ( ErrInvalidToken = errors.New("invalid API token") ErrTokenExpired = errors.New("token is expired") ) type APITokenCache struct { APITokens queries.APITokensInterface cache *ttlcache.Cache onceCache sync.Once } func (a *APITokenCache) Get(key string) (string, error) { value, err := a.Cache().Get(key) if err == nil { apiToken, ok := value.(*common.APIToken) if !ok { return "", ErrInvalidToken } if apiToken.ExpiresAt != nil && apiToken.ExpiresAt.Before(time.Now()) { return "", ErrTokenExpired } return apiToken.Roles, nil } else if !errors.Is(err, ttlcache.ErrNotFound) { return "", err } item, err := a.APITokens.Get(key) if err != nil { return "", err } if item.ExpiresAt != nil && item.ExpiresAt.Before(time.Now()) { return "", ErrTokenExpired } err = a.Cache().Set(key, item) if err != nil { return "", err } return item.Roles, nil } func (a *APITokenCache) Cache() *ttlcache.Cache { a.onceCache.Do(func() { if a.cache == nil { cache := ttlcache.NewCache() cache.SetTTL(10 * time.Minute) cache.SetCacheSizeLimit(10) a.cache = cache } }) return a.cache } func (a *APITokenCache) Close() { a.cache.Close() a.cache = nil a.APITokens = nil }