Plugins: Add plugin settings DTO (#46283)

* add clearer service layer

* re-order frontend settings for clarity

* fix fetch fail

* fix API response

* fix mockstore

* in -> where
This commit is contained in:
Will Browne
2022-03-18 20:49:13 +01:00
committed by GitHub
parent 1afd278bd0
commit bda3f860a8
16 changed files with 426 additions and 308 deletions
+43
View File
@@ -0,0 +1,43 @@
package pluginsettings
import (
"time"
)
type DTO struct {
ID int64
OrgID int64
PluginID string
PluginVersion string
JSONData map[string]interface{}
SecureJSONData map[string][]byte
Enabled bool
Pinned bool
Updated time.Time
}
type UpdateArgs struct {
Enabled bool
Pinned bool
JSONData map[string]interface{}
SecureJSONData map[string]string
PluginVersion string
PluginID string
OrgID int64
EncryptedSecureJSONData map[string][]byte
}
type UpdatePluginVersionArgs struct {
PluginVersion string
PluginID string
OrgID int64
}
type GetArgs struct {
OrgID int64
}
type GetByPluginIDArgs struct {
PluginID string
OrgID int64
}
@@ -2,20 +2,18 @@ package pluginsettings
import (
"context"
"github.com/grafana/grafana/pkg/models"
)
type Service interface {
// GetPluginSettings returns all Plugin Settings for the provided Org
GetPluginSettings(ctx context.Context, orgID int64) ([]*models.PluginSettingInfoDTO, error)
// GetPluginSettingById returns a Plugin Settings by Plugin ID
GetPluginSettingById(ctx context.Context, query *models.GetPluginSettingByIdQuery) error
GetPluginSettings(ctx context.Context, args *GetArgs) ([]*DTO, error)
// GetPluginSettingByPluginID returns a Plugin Settings by Plugin ID
GetPluginSettingByPluginID(ctx context.Context, args *GetByPluginIDArgs) (*DTO, error)
// UpdatePluginSetting updates a Plugin Setting
UpdatePluginSetting(ctx context.Context, cmd *models.UpdatePluginSettingCmd) error
// UpdatePluginSettingVersion updates a Plugin Setting's plugin version
UpdatePluginSettingVersion(ctx context.Context, cmd *models.UpdatePluginSettingVersionCmd) error
UpdatePluginSetting(ctx context.Context, args *UpdateArgs) error
// UpdatePluginSettingPluginVersion updates a Plugin Setting's plugin version
UpdatePluginSettingPluginVersion(ctx context.Context, args *UpdatePluginVersionArgs) error
// DecryptedValues decrypts the encrypted secureJSONData of the provided plugin setting and
// returns the decrypted values.
DecryptedValues(ps *models.PluginSetting) map[string]string
DecryptedValues(ps *DTO) map[string]string
}
+67 -14
View File
@@ -7,6 +7,7 @@ import (
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/pluginsettings"
"github.com/grafana/grafana/pkg/services/secrets"
"github.com/grafana/grafana/pkg/services/sqlstore"
)
@@ -42,43 +43,95 @@ type secureJSONDecryptionCache struct {
sync.Mutex
}
func (s *Service) GetPluginSettings(ctx context.Context, orgID int64) ([]*models.PluginSettingInfoDTO, error) {
return s.sqlStore.GetPluginSettings(ctx, orgID)
func (s *Service) GetPluginSettings(ctx context.Context, args *pluginsettings.GetArgs) ([]*pluginsettings.DTO, error) {
ps, err := s.sqlStore.GetPluginSettings(ctx, args.OrgID)
if err != nil {
return nil, err
}
var result []*pluginsettings.DTO
for _, p := range ps {
result = append(result, &pluginsettings.DTO{
ID: p.Id,
OrgID: p.OrgId,
PluginID: p.PluginId,
PluginVersion: p.PluginVersion,
JSONData: p.JsonData,
SecureJSONData: p.SecureJsonData,
Enabled: p.Enabled,
Pinned: p.Pinned,
Updated: p.Updated,
})
}
return result, nil
}
func (s *Service) GetPluginSettingById(ctx context.Context, query *models.GetPluginSettingByIdQuery) error {
return s.sqlStore.GetPluginSettingById(ctx, query)
func (s *Service) GetPluginSettingByPluginID(ctx context.Context, args *pluginsettings.GetByPluginIDArgs) (*pluginsettings.DTO, error) {
query := &models.GetPluginSettingByIdQuery{
OrgId: args.OrgID,
PluginId: args.PluginID,
}
err := s.sqlStore.GetPluginSettingById(ctx, query)
if err != nil {
return nil, err
}
return &pluginsettings.DTO{
ID: query.Result.Id,
OrgID: query.Result.OrgId,
PluginID: query.Result.PluginId,
PluginVersion: query.Result.PluginVersion,
JSONData: query.Result.JsonData,
SecureJSONData: query.Result.SecureJsonData,
Enabled: query.Result.Enabled,
Pinned: query.Result.Pinned,
Updated: query.Result.Updated,
}, nil
}
func (s *Service) UpdatePluginSetting(ctx context.Context, cmd *models.UpdatePluginSettingCmd) error {
var err error
cmd.EncryptedSecureJsonData, err = s.secretsService.EncryptJsonData(ctx, cmd.SecureJsonData, secrets.WithoutScope())
func (s *Service) UpdatePluginSetting(ctx context.Context, args *pluginsettings.UpdateArgs) error {
encryptedSecureJsonData, err := s.secretsService.EncryptJsonData(ctx, args.SecureJSONData, secrets.WithoutScope())
if err != nil {
return err
}
return s.sqlStore.UpdatePluginSetting(ctx, cmd)
return s.sqlStore.UpdatePluginSetting(ctx, &models.UpdatePluginSettingCmd{
Enabled: args.Enabled,
Pinned: args.Pinned,
JsonData: args.JSONData,
SecureJsonData: args.SecureJSONData,
PluginVersion: args.PluginVersion,
PluginId: args.PluginID,
OrgId: args.OrgID,
EncryptedSecureJsonData: encryptedSecureJsonData,
})
}
func (s *Service) UpdatePluginSettingVersion(ctx context.Context, cmd *models.UpdatePluginSettingVersionCmd) error {
return s.sqlStore.UpdatePluginSettingVersion(ctx, cmd)
func (s *Service) UpdatePluginSettingPluginVersion(ctx context.Context, args *pluginsettings.UpdatePluginVersionArgs) error {
return s.sqlStore.UpdatePluginSettingVersion(ctx, &models.UpdatePluginSettingVersionCmd{
PluginVersion: args.PluginVersion,
PluginId: args.PluginID,
OrgId: args.OrgID,
})
}
func (s *Service) DecryptedValues(ps *models.PluginSetting) map[string]string {
func (s *Service) DecryptedValues(ps *pluginsettings.DTO) map[string]string {
s.decryptionCache.Lock()
defer s.decryptionCache.Unlock()
if item, present := s.decryptionCache.cache[ps.Id]; present && ps.Updated.Equal(item.updated) {
if item, present := s.decryptionCache.cache[ps.ID]; present && ps.Updated.Equal(item.updated) {
return item.json
}
json, err := s.secretsService.DecryptJsonData(context.Background(), ps.SecureJsonData)
json, err := s.secretsService.DecryptJsonData(context.Background(), ps.SecureJSONData)
if err != nil {
s.logger.Error("Failed to decrypt secure json data", "error", err)
return map[string]string{}
}
s.decryptionCache.cache[ps.Id] = cachedDecryptedJSON{
s.decryptionCache.cache[ps.ID] = cachedDecryptedJSON{
updated: ps.Updated,
json: json,
}
@@ -5,7 +5,7 @@ import (
"testing"
"time"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/pluginsettings"
"github.com/grafana/grafana/pkg/services/secrets"
"github.com/grafana/grafana/pkg/services/secrets/fakes"
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
@@ -27,10 +27,10 @@ func TestService_DecryptedValuesCache(t *testing.T) {
}, secrets.WithoutScope())
require.NoError(t, err)
ps := models.PluginSetting{
Id: 1,
JsonData: map[string]interface{}{},
SecureJsonData: encryptedJsonData,
ps := pluginsettings.DTO{
ID: 1,
JSONData: map[string]interface{}{},
SecureJSONData: encryptedJsonData,
}
// Populate cache
@@ -45,7 +45,7 @@ func TestService_DecryptedValuesCache(t *testing.T) {
}, secrets.WithoutScope())
require.NoError(t, err)
ps.SecureJsonData = encryptedJsonData
ps.SecureJSONData = encryptedJsonData
password, ok = psService.DecryptedValues(&ps)["password"]
require.Equal(t, "password", password)
@@ -65,10 +65,10 @@ func TestService_DecryptedValuesCache(t *testing.T) {
}, secrets.WithoutScope())
require.NoError(t, err)
ps := models.PluginSetting{
Id: 1,
JsonData: map[string]interface{}{},
SecureJsonData: encryptedJsonData,
ps := pluginsettings.DTO{
ID: 1,
JSONData: map[string]interface{}{},
SecureJSONData: encryptedJsonData,
}
// Populate cache
@@ -83,7 +83,7 @@ func TestService_DecryptedValuesCache(t *testing.T) {
}, secrets.WithoutScope())
require.NoError(t, err)
ps.SecureJsonData = encryptedJsonData
ps.SecureJSONData = encryptedJsonData
ps.Updated = time.Now()
password, ok = psService.DecryptedValues(&ps)["password"]