Plugins: Refactor kvstore usage in signing keys and angular patterns (#73154)

* Initial refactoring work for plugins kvstore

* Replace implementations for keystore and angularstore

* Cleanup

* add interface check

* lint

* fix storeKeyGetter not being called in namespacedstore set

* Fix tests

* Comments

* Add tests

* Fix invalid cap in ListKeys when store is empty

* Update docstrings

* Add setLastUpdatedOnDelete

* Renamed DefaultStoreKeyGetterFunc, add TestDefaultStoreKeyGetter

* Sort imports

* PR review: removed last_updated key

* PR review: Removed setLastUpdatedOnDelete

* Re-added relevant tests

* PR review: Removed SingleKeyStore

* PR review: Removed custom marshaling support

* Renamed marshaler.go to marshal.go

* PR review: removed unused interfaces

* PR review: Moved marshal into namespacedstore.go

* PR review: removed storekeygetter

* Removed unused file cachekvstore.go

* Renamed NamespacedStore to CacheKvStore

* removed todo
This commit is contained in:
Giuseppe Guerra
2023-09-05 16:20:42 +02:00
committed by GitHub
parent 41ca13418b
commit 2e67a9463d
9 changed files with 361 additions and 110 deletions
@@ -1,74 +1,25 @@
package keystore
import (
"context"
"fmt"
"time"
"github.com/grafana/grafana/pkg/infra/kvstore"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/pluginsintegration/cachekvstore"
)
// Service is a service for storing and retrieving public keys.
type Service struct {
kv *kvstore.NamespacedKVStore
*cachekvstore.CacheKvStore
}
const (
prefix = "key-"
lastUpdatedKey = "last_updated"
namespace = "plugin.publickeys"
prefix = "key-"
)
var _ plugins.KeyStore = (*Service)(nil)
func ProvideService(kv kvstore.KVStore) *Service {
return &Service{
kv: kvstore.WithNamespace(kv, 0, "plugin.publickeys"),
CacheKvStore: cachekvstore.NewCacheKvStoreWithPrefix(kv, namespace, prefix),
}
}
func (s *Service) Get(ctx context.Context, key string) (string, bool, error) {
return s.kv.Get(ctx, prefix+key)
}
func (s *Service) Set(ctx context.Context, key string, value string) error {
return s.kv.Set(ctx, prefix+key, value)
}
func (s *Service) Del(ctx context.Context, key string) error {
return s.kv.Del(ctx, prefix+key)
}
func (s *Service) GetLastUpdated(ctx context.Context) (*time.Time, error) {
lastUpdated := &time.Time{}
if val, ok, err := s.kv.Get(ctx, lastUpdatedKey); err != nil {
return nil, fmt.Errorf("failed to get last updated time: %v", err)
} else if ok {
if parsed, err := time.Parse(time.RFC3339, val); err != nil {
return nil, fmt.Errorf("failed to parse last updated time: %v", err)
} else {
lastUpdated = &parsed
}
}
return lastUpdated, nil
}
func (s *Service) SetLastUpdated(ctx context.Context) error {
lastUpdated := time.Now()
if err := s.kv.Set(ctx, lastUpdatedKey, lastUpdated.Format(time.RFC3339)); err != nil {
return fmt.Errorf("failed to update last updated time: %v", err)
}
return nil
}
func (s *Service) ListKeys(ctx context.Context) ([]string, error) {
keys, err := s.kv.Keys(ctx, prefix)
if err != nil {
return nil, err
}
res := make([]string, 0, len(keys))
for _, key := range keys {
res = append(res, key.Key)
}
return res, nil
}