mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Plugins: Add secure JSON fields to plugin setting DTO (#55313)
* add secure JSON fields to plugin setting DTO * add nil pointer fix * adding secureJsonFields to the plugin meta. Co-authored-by: Marcus Andersson <marcus.andersson@grafana.com>
This commit is contained in:
@@ -69,6 +69,7 @@ export interface PluginMeta<T extends KeyValue = {}> {
|
||||
// Filled in by the backend
|
||||
jsonData?: T;
|
||||
secureJsonData?: KeyValue;
|
||||
secureJsonFields?: KeyValue<boolean>;
|
||||
enabled?: boolean;
|
||||
defaultNavUrl?: string;
|
||||
hasUpdate?: boolean;
|
||||
|
@@ -6,18 +6,19 @@ import (
|
||||
)
|
||||
|
||||
type PluginSetting struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Id string `json:"id"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Pinned bool `json:"pinned"`
|
||||
Module string `json:"module"`
|
||||
BaseUrl string `json:"baseUrl"`
|
||||
Info plugins.Info `json:"info"`
|
||||
Includes []*plugins.Includes `json:"includes"`
|
||||
Dependencies plugins.Dependencies `json:"dependencies"`
|
||||
JsonData map[string]interface{} `json:"jsonData"`
|
||||
DefaultNavUrl string `json:"defaultNavUrl"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Id string `json:"id"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Pinned bool `json:"pinned"`
|
||||
Module string `json:"module"`
|
||||
BaseUrl string `json:"baseUrl"`
|
||||
Info plugins.Info `json:"info"`
|
||||
Includes []*plugins.Includes `json:"includes"`
|
||||
Dependencies plugins.Dependencies `json:"dependencies"`
|
||||
JsonData map[string]interface{} `json:"jsonData"`
|
||||
SecureJsonFields map[string]bool `json:"secureJsonFields"`
|
||||
DefaultNavUrl string `json:"defaultNavUrl"`
|
||||
|
||||
LatestVersion string `json:"latestVersion"`
|
||||
HasUpdate bool `json:"hasUpdate"`
|
||||
|
@@ -86,10 +86,16 @@ type fakePluginSettings struct {
|
||||
}
|
||||
|
||||
// GetPluginSettings returns all Plugin Settings for the provided Org
|
||||
func (ps *fakePluginSettings) GetPluginSettings(ctx context.Context, args *pluginsettings.GetArgs) ([]*pluginsettings.DTO, error) {
|
||||
res := []*pluginsettings.DTO{}
|
||||
func (ps *fakePluginSettings) GetPluginSettings(_ context.Context, _ *pluginsettings.GetArgs) ([]*pluginsettings.InfoDTO, error) {
|
||||
res := []*pluginsettings.InfoDTO{}
|
||||
for _, dto := range ps.plugins {
|
||||
res = append(res, dto)
|
||||
res = append(res, &pluginsettings.InfoDTO{
|
||||
PluginID: dto.PluginID,
|
||||
OrgID: dto.OrgID,
|
||||
Enabled: dto.Enabled,
|
||||
Pinned: dto.Pinned,
|
||||
PluginVersion: dto.PluginVersion,
|
||||
})
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
@@ -431,8 +431,8 @@ func (hs *HTTPServer) enabledPlugins(ctx context.Context, orgID int64) (EnabledP
|
||||
return ep, nil
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) pluginSettings(ctx context.Context, orgID int64) (map[string]*pluginsettings.DTO, error) {
|
||||
pluginSettings := make(map[string]*pluginsettings.DTO)
|
||||
func (hs *HTTPServer) pluginSettings(ctx context.Context, orgID int64) (map[string]*pluginsettings.InfoDTO, error) {
|
||||
pluginSettings := make(map[string]*pluginsettings.InfoDTO)
|
||||
|
||||
// fill settings from database
|
||||
if pss, err := hs.PluginSettings.GetPluginSettings(ctx, &pluginsettings.GetArgs{OrgID: orgID}); err != nil {
|
||||
@@ -451,11 +451,12 @@ func (hs *HTTPServer) pluginSettings(ctx context.Context, orgID int64) (map[stri
|
||||
}
|
||||
|
||||
// add new setting which is enabled depending on if AutoEnabled: true
|
||||
pluginSetting := &pluginsettings.DTO{
|
||||
PluginID: plugin.ID,
|
||||
OrgID: orgID,
|
||||
Enabled: plugin.AutoEnabled,
|
||||
Pinned: plugin.AutoEnabled,
|
||||
pluginSetting := &pluginsettings.InfoDTO{
|
||||
PluginID: plugin.ID,
|
||||
OrgID: orgID,
|
||||
Enabled: plugin.AutoEnabled,
|
||||
Pinned: plugin.AutoEnabled,
|
||||
PluginVersion: plugin.Info.Version,
|
||||
}
|
||||
|
||||
pluginSettings[plugin.ID] = pluginSetting
|
||||
@@ -469,10 +470,12 @@ func (hs *HTTPServer) pluginSettings(ctx context.Context, orgID int64) (map[stri
|
||||
}
|
||||
|
||||
// add new setting which is enabled by default
|
||||
pluginSetting := &pluginsettings.DTO{
|
||||
PluginID: plugin.ID,
|
||||
OrgID: orgID,
|
||||
Enabled: true,
|
||||
pluginSetting := &pluginsettings.InfoDTO{
|
||||
PluginID: plugin.ID,
|
||||
OrgID: orgID,
|
||||
Enabled: true,
|
||||
Pinned: false,
|
||||
PluginVersion: plugin.Info.Version,
|
||||
}
|
||||
|
||||
// if plugin is included in an app, check app settings
|
||||
|
@@ -170,19 +170,20 @@ func (hs *HTTPServer) GetPluginSettingByID(c *models.ReqContext) response.Respon
|
||||
}
|
||||
|
||||
dto := &dtos.PluginSetting{
|
||||
Type: string(plugin.Type),
|
||||
Id: plugin.ID,
|
||||
Name: plugin.Name,
|
||||
Info: plugin.Info,
|
||||
Dependencies: plugin.Dependencies,
|
||||
Includes: plugin.Includes,
|
||||
BaseUrl: plugin.BaseURL,
|
||||
Module: plugin.Module,
|
||||
DefaultNavUrl: path.Join(hs.Cfg.AppSubURL, plugin.DefaultNavURL),
|
||||
State: plugin.State,
|
||||
Signature: plugin.Signature,
|
||||
SignatureType: plugin.SignatureType,
|
||||
SignatureOrg: plugin.SignatureOrg,
|
||||
Type: string(plugin.Type),
|
||||
Id: plugin.ID,
|
||||
Name: plugin.Name,
|
||||
Info: plugin.Info,
|
||||
Dependencies: plugin.Dependencies,
|
||||
Includes: plugin.Includes,
|
||||
BaseUrl: plugin.BaseURL,
|
||||
Module: plugin.Module,
|
||||
DefaultNavUrl: path.Join(hs.Cfg.AppSubURL, plugin.DefaultNavURL),
|
||||
State: plugin.State,
|
||||
Signature: plugin.Signature,
|
||||
SignatureType: plugin.SignatureType,
|
||||
SignatureOrg: plugin.SignatureOrg,
|
||||
SecureJsonFields: map[string]bool{},
|
||||
}
|
||||
|
||||
if plugin.IsApp() {
|
||||
@@ -202,6 +203,12 @@ func (hs *HTTPServer) GetPluginSettingByID(c *models.ReqContext) response.Respon
|
||||
dto.Enabled = ps.Enabled
|
||||
dto.Pinned = ps.Pinned
|
||||
dto.JsonData = ps.JSONData
|
||||
|
||||
for k, v := range hs.PluginSettings.DecryptedValues(ps) {
|
||||
if len(v) > 0 {
|
||||
dto.SecureJsonFields[k] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update, exists := hs.pluginsUpdateChecker.HasUpdate(c.Req.Context(), plugin.ID)
|
||||
|
@@ -23,6 +23,14 @@ type PluginSetting struct {
|
||||
Updated time.Time
|
||||
}
|
||||
|
||||
type PluginSettingInfo struct {
|
||||
PluginID string `xorm:"plugin_id"`
|
||||
OrgID int64 `xorm:"org_id"`
|
||||
Enabled bool `xorm:"enabled"`
|
||||
Pinned bool `xorm:"pinned"`
|
||||
PluginVersion string `xorm:"plugin_id"`
|
||||
}
|
||||
|
||||
// ----------------------
|
||||
// COMMANDS
|
||||
|
||||
|
@@ -397,9 +397,21 @@ type pluginsSettingsServiceMock struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (s *pluginsSettingsServiceMock) GetPluginSettings(_ context.Context, args *pluginsettings.GetArgs) ([]*pluginsettings.DTO, error) {
|
||||
func (s *pluginsSettingsServiceMock) GetPluginSettings(_ context.Context, args *pluginsettings.GetArgs) ([]*pluginsettings.InfoDTO, error) {
|
||||
s.getPluginSettingsArgs = append(s.getPluginSettingsArgs, args.OrgID)
|
||||
return s.storedPluginSettings, s.err
|
||||
|
||||
var res []*pluginsettings.InfoDTO
|
||||
for _, ps := range s.storedPluginSettings {
|
||||
res = append(res, &pluginsettings.InfoDTO{
|
||||
PluginID: ps.PluginID,
|
||||
OrgID: ps.OrgID,
|
||||
Enabled: ps.Enabled,
|
||||
Pinned: ps.Pinned,
|
||||
PluginVersion: ps.PluginVersion,
|
||||
})
|
||||
}
|
||||
|
||||
return res, s.err
|
||||
}
|
||||
|
||||
func (s *pluginsSettingsServiceMock) GetPluginSettingByPluginID(_ context.Context, args *pluginsettings.GetByPluginIDArgs) (*pluginsettings.DTO, error) {
|
||||
|
@@ -16,6 +16,14 @@ type DTO struct {
|
||||
Updated time.Time
|
||||
}
|
||||
|
||||
type InfoDTO struct {
|
||||
PluginID string
|
||||
OrgID int64
|
||||
Enabled bool
|
||||
Pinned bool
|
||||
PluginVersion string
|
||||
}
|
||||
|
||||
type UpdateArgs struct {
|
||||
Enabled bool
|
||||
Pinned bool
|
||||
|
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
type Service interface {
|
||||
// GetPluginSettings returns all Plugin Settings for the provided Org
|
||||
GetPluginSettings(ctx context.Context, args *GetArgs) ([]*DTO, error)
|
||||
GetPluginSettings(ctx context.Context, args *GetArgs) ([]*InfoDTO, error)
|
||||
// GetPluginSettingByPluginID returns a Plugin Settings by Plugin ID
|
||||
GetPluginSettingByPluginID(ctx context.Context, args *GetByPluginIDArgs) (*DTO, error)
|
||||
// UpdatePluginSetting updates a Plugin Setting
|
||||
|
@@ -44,24 +44,20 @@ type secureJSONDecryptionCache struct {
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
func (s *Service) GetPluginSettings(ctx context.Context, args *pluginsettings.GetArgs) ([]*pluginsettings.DTO, error) {
|
||||
ps, err := s.getPluginSettings(ctx, args.OrgID)
|
||||
func (s *Service) GetPluginSettings(ctx context.Context, args *pluginsettings.GetArgs) ([]*pluginsettings.InfoDTO, error) {
|
||||
ps, err := s.getPluginSettingsInfo(ctx, args.OrgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result []*pluginsettings.DTO
|
||||
var result []*pluginsettings.InfoDTO
|
||||
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,
|
||||
result = append(result, &pluginsettings.InfoDTO{
|
||||
OrgID: p.OrgID,
|
||||
PluginID: p.PluginID,
|
||||
PluginVersion: p.PluginVersion,
|
||||
Enabled: p.Enabled,
|
||||
Pinned: p.Pinned,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -140,7 +136,7 @@ func (s *Service) DecryptedValues(ps *pluginsettings.DTO) map[string]string {
|
||||
return json
|
||||
}
|
||||
|
||||
func (s *Service) getPluginSettings(ctx context.Context, orgID int64) ([]*models.PluginSetting, error) {
|
||||
func (s *Service) getPluginSettingsInfo(ctx context.Context, orgID int64) ([]*models.PluginSettingInfo, error) {
|
||||
sql := `SELECT org_id, plugin_id, enabled, pinned, plugin_version FROM plugin_setting `
|
||||
params := make([]interface{}, 0)
|
||||
|
||||
@@ -149,7 +145,7 @@ func (s *Service) getPluginSettings(ctx context.Context, orgID int64) ([]*models
|
||||
params = append(params, orgID)
|
||||
}
|
||||
|
||||
var rslt []*models.PluginSetting
|
||||
var rslt []*models.PluginSettingInfo
|
||||
err := s.db.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
return sess.SQL(sql, params...).Find(&rslt)
|
||||
})
|
||||
|
@@ -137,8 +137,6 @@ func TestIntegrationPluginSettings(t *testing.T) {
|
||||
require.Equal(t, existing.OrgId, ps.OrgID)
|
||||
require.Equal(t, existing.PluginId, ps.PluginID)
|
||||
require.False(t, ps.Enabled)
|
||||
require.Nil(t, ps.JSONData)
|
||||
require.Nil(t, ps.SecureJSONData)
|
||||
})
|
||||
|
||||
t.Run("GetPluginSettings with orgID=1 should return all existing plugin settings", func(t *testing.T) {
|
||||
@@ -149,8 +147,6 @@ func TestIntegrationPluginSettings(t *testing.T) {
|
||||
require.Equal(t, existing.OrgId, ps.OrgID)
|
||||
require.Equal(t, existing.PluginId, ps.PluginID)
|
||||
require.False(t, ps.Enabled)
|
||||
require.Nil(t, ps.JSONData)
|
||||
require.Nil(t, ps.SecureJSONData)
|
||||
})
|
||||
|
||||
t.Run("GetPluginSettingById should return existing plugin settings", func(t *testing.T) {
|
||||
|
@@ -106,7 +106,7 @@ func (m *mockStore) UpdatePluginSettingPluginVersion(_ context.Context, _ *plugi
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockStore) GetPluginSettings(_ context.Context, _ *pluginsettings.GetArgs) ([]*pluginsettings.DTO, error) {
|
||||
func (m *mockStore) GetPluginSettings(_ context.Context, _ *pluginsettings.GetArgs) ([]*pluginsettings.InfoDTO, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user