From bda3f860a8397e75b4d279016fea3d015f16a5c6 Mon Sep 17 00:00:00 2001 From: Will Browne Date: Fri, 18 Mar 2022 20:49:13 +0100 Subject: [PATCH] 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 --- pkg/api/frontendsettings.go | 273 +++++++++--------- pkg/api/pluginproxy/pluginproxy.go | 9 +- pkg/api/pluginproxy/pluginproxy_test.go | 41 ++- pkg/api/plugins.go | 27 +- pkg/plugins/plugincontext/plugincontext.go | 19 +- .../service/dashboard_updater.go | 20 +- .../service/dashboard_updater_test.go | 66 +++-- pkg/services/pluginsettings/models.go | 43 +++ pkg/services/pluginsettings/pluginsettings.go | 16 +- .../pluginsettings/service/service.go | 81 +++++- .../pluginsettings/service/service_test.go | 22 +- .../plugins/plugin_provisioner.go | 21 +- .../plugins/plugin_provisioner_test.go | 57 ++-- pkg/services/sqlstore/mockstore/mockstore.go | 2 +- pkg/services/sqlstore/plugin_setting.go | 27 +- pkg/services/sqlstore/store.go | 2 +- 16 files changed, 422 insertions(+), 304 deletions(-) create mode 100644 pkg/services/pluginsettings/models.go diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index d86cc36a0c1..1767ca37533 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -8,129 +8,20 @@ import ( "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/licensing" + "github.com/grafana/grafana/pkg/services/pluginsettings" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/tsdb/grafanads" "github.com/grafana/grafana/pkg/util" ) -func (hs *HTTPServer) getFSDataSources(c *models.ReqContext, enabledPlugins EnabledPlugins) (map[string]plugins.DataSourceDTO, error) { - orgDataSources := make([]*models.DataSource, 0) - - if c.OrgId != 0 { - query := models.GetDataSourcesQuery{OrgId: c.OrgId, DataSourceLimit: hs.Cfg.DataSourceLimit} - err := hs.SQLStore.GetDataSources(c.Req.Context(), &query) - - if err != nil { - return nil, err - } - - filtered, err := hs.filterDatasourcesByQueryPermission(c.Req.Context(), c.SignedInUser, query.Result) - if err != nil { - return nil, err - } - - orgDataSources = filtered - } - - dataSources := make(map[string]plugins.DataSourceDTO) - - for _, ds := range orgDataSources { - url := ds.Url - - if ds.Access == models.DS_ACCESS_PROXY { - url = "/api/datasources/proxy/" + strconv.FormatInt(ds.Id, 10) - } - - dsDTO := plugins.DataSourceDTO{ - ID: ds.Id, - UID: ds.Uid, - Type: ds.Type, - Name: ds.Name, - URL: url, - IsDefault: ds.IsDefault, - Access: string(ds.Access), - } - - plugin, exists := enabledPlugins.Get(plugins.DataSource, ds.Type) - if !exists { - c.Logger.Error("Could not find plugin definition for data source", "datasource_type", ds.Type) - continue - } - dsDTO.Preload = plugin.Preload - dsDTO.Module = plugin.Module - dsDTO.PluginMeta = &plugins.PluginMetaDTO{ - JSONData: plugin.JSONData, - Signature: plugin.Signature, - Module: plugin.Module, - BaseURL: plugin.BaseURL, - } - - if ds.JsonData == nil { - dsDTO.JSONData = make(map[string]interface{}) - } else { - dsDTO.JSONData = ds.JsonData.MustMap() - } - - if ds.Access == models.DS_ACCESS_DIRECT { - if ds.BasicAuth { - dsDTO.BasicAuth = util.GetBasicAuthHeader( - ds.BasicAuthUser, - hs.DataSourcesService.DecryptedBasicAuthPassword(ds), - ) - } - if ds.WithCredentials { - dsDTO.WithCredentials = ds.WithCredentials - } - - if ds.Type == models.DS_INFLUXDB_08 { - dsDTO.Username = ds.User - dsDTO.Password = hs.DataSourcesService.DecryptedPassword(ds) - dsDTO.URL = url + "/db/" + ds.Database - } - - if ds.Type == models.DS_INFLUXDB { - dsDTO.Username = ds.User - dsDTO.Password = hs.DataSourcesService.DecryptedPassword(ds) - dsDTO.URL = url - } - } - - if (ds.Type == models.DS_INFLUXDB) || (ds.Type == models.DS_ES) { - dsDTO.Database = ds.Database - } - - if ds.Type == models.DS_PROMETHEUS { - // add unproxied server URL for link to Prometheus web UI - ds.JsonData.Set("directUrl", ds.Url) - } - - dataSources[ds.Name] = dsDTO - } - - // add data sources that are built in (meaning they are not added via data sources page, nor have any entry in - // the datasource table) - for _, ds := range hs.pluginStore.Plugins(c.Req.Context(), plugins.DataSource) { - if ds.BuiltIn { - dto := plugins.DataSourceDTO{ - Type: string(ds.Type), - Name: ds.Name, - JSONData: make(map[string]interface{}), - PluginMeta: &plugins.PluginMetaDTO{ - JSONData: ds.JSONData, - Signature: ds.Signature, - Module: ds.Module, - BaseURL: ds.BaseURL, - }, - } - if ds.Name == grafanads.DatasourceName { - dto.ID = grafanads.DatasourceID - dto.UID = grafanads.DatasourceUID - } - dataSources[ds.Name] = dto - } +func (hs *HTTPServer) GetFrontendSettings(c *models.ReqContext) { + settings, err := hs.getFrontendSettingsMap(c) + if err != nil { + c.JsonApiErr(400, "Failed to get frontend settings", err) + return } - return dataSources, nil + c.JSON(200, settings) } // getFrontendSettingsMap returns a json object with all the settings needed for front end initialisation. @@ -290,6 +181,126 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *models.ReqContext) (map[string]i return jsonObj, nil } +func (hs *HTTPServer) getFSDataSources(c *models.ReqContext, enabledPlugins EnabledPlugins) (map[string]plugins.DataSourceDTO, error) { + orgDataSources := make([]*models.DataSource, 0) + + if c.OrgId != 0 { + query := models.GetDataSourcesQuery{OrgId: c.OrgId, DataSourceLimit: hs.Cfg.DataSourceLimit} + err := hs.SQLStore.GetDataSources(c.Req.Context(), &query) + + if err != nil { + return nil, err + } + + filtered, err := hs.filterDatasourcesByQueryPermission(c.Req.Context(), c.SignedInUser, query.Result) + if err != nil { + return nil, err + } + + orgDataSources = filtered + } + + dataSources := make(map[string]plugins.DataSourceDTO) + + for _, ds := range orgDataSources { + url := ds.Url + + if ds.Access == models.DS_ACCESS_PROXY { + url = "/api/datasources/proxy/" + strconv.FormatInt(ds.Id, 10) + } + + dsDTO := plugins.DataSourceDTO{ + ID: ds.Id, + UID: ds.Uid, + Type: ds.Type, + Name: ds.Name, + URL: url, + IsDefault: ds.IsDefault, + Access: string(ds.Access), + } + + plugin, exists := enabledPlugins.Get(plugins.DataSource, ds.Type) + if !exists { + c.Logger.Error("Could not find plugin definition for data source", "datasource_type", ds.Type) + continue + } + dsDTO.Preload = plugin.Preload + dsDTO.Module = plugin.Module + dsDTO.PluginMeta = &plugins.PluginMetaDTO{ + JSONData: plugin.JSONData, + Signature: plugin.Signature, + Module: plugin.Module, + BaseURL: plugin.BaseURL, + } + + if ds.JsonData == nil { + dsDTO.JSONData = make(map[string]interface{}) + } else { + dsDTO.JSONData = ds.JsonData.MustMap() + } + + if ds.Access == models.DS_ACCESS_DIRECT { + if ds.BasicAuth { + dsDTO.BasicAuth = util.GetBasicAuthHeader( + ds.BasicAuthUser, + hs.DataSourcesService.DecryptedBasicAuthPassword(ds), + ) + } + if ds.WithCredentials { + dsDTO.WithCredentials = ds.WithCredentials + } + + if ds.Type == models.DS_INFLUXDB_08 { + dsDTO.Username = ds.User + dsDTO.Password = hs.DataSourcesService.DecryptedPassword(ds) + dsDTO.URL = url + "/db/" + ds.Database + } + + if ds.Type == models.DS_INFLUXDB { + dsDTO.Username = ds.User + dsDTO.Password = hs.DataSourcesService.DecryptedPassword(ds) + dsDTO.URL = url + } + } + + if (ds.Type == models.DS_INFLUXDB) || (ds.Type == models.DS_ES) { + dsDTO.Database = ds.Database + } + + if ds.Type == models.DS_PROMETHEUS { + // add unproxied server URL for link to Prometheus web UI + ds.JsonData.Set("directUrl", ds.Url) + } + + dataSources[ds.Name] = dsDTO + } + + // add data sources that are built in (meaning they are not added via data sources page, nor have any entry in + // the datasource table) + for _, ds := range hs.pluginStore.Plugins(c.Req.Context(), plugins.DataSource) { + if ds.BuiltIn { + dto := plugins.DataSourceDTO{ + Type: string(ds.Type), + Name: ds.Name, + JSONData: make(map[string]interface{}), + PluginMeta: &plugins.PluginMetaDTO{ + JSONData: ds.JSONData, + Signature: ds.Signature, + Module: ds.Module, + BaseURL: ds.BaseURL, + }, + } + if ds.Name == grafanads.DatasourceName { + dto.ID = grafanads.DatasourceID + dto.UID = grafanads.DatasourceUID + } + dataSources[ds.Name] = dto + } + } + + return dataSources, nil +} + func getPanelSort(id string) int { sort := 100 switch id { @@ -331,16 +342,6 @@ func getPanelSort(id string) int { return sort } -func (hs *HTTPServer) GetFrontendSettings(c *models.ReqContext) { - settings, err := hs.getFrontendSettingsMap(c) - if err != nil { - c.JsonApiErr(400, "Failed to get frontend settings", err) - return - } - - c.JSON(200, settings) -} - // EnabledPlugins represents a mapping from plugin types (panel, data source, etc.) to plugin IDs to plugins // For example ["panel"] -> ["piechart"] -> {pie chart plugin DTO} type EnabledPlugins map[plugins.Type]map[string]plugins.PluginDTO @@ -389,15 +390,15 @@ func (hs *HTTPServer) enabledPlugins(ctx context.Context, orgID int64) (EnabledP return ep, nil } -func (hs *HTTPServer) pluginSettings(ctx context.Context, orgID int64) (map[string]*models.PluginSettingInfoDTO, error) { - pluginSettings := make(map[string]*models.PluginSettingInfoDTO) +func (hs *HTTPServer) pluginSettings(ctx context.Context, orgID int64) (map[string]*pluginsettings.DTO, error) { + pluginSettings := make(map[string]*pluginsettings.DTO) // fill settings from database - if pss, err := hs.PluginSettings.GetPluginSettings(ctx, orgID); err != nil { + if pss, err := hs.PluginSettings.GetPluginSettings(ctx, &pluginsettings.GetArgs{OrgID: orgID}); err != nil { return nil, err } else { for _, ps := range pss { - pluginSettings[ps.PluginId] = ps + pluginSettings[ps.PluginID] = ps } } @@ -409,9 +410,9 @@ func (hs *HTTPServer) pluginSettings(ctx context.Context, orgID int64) (map[stri } // add new setting which is enabled depending on if AutoEnabled: true - pluginSetting := &models.PluginSettingInfoDTO{ - PluginId: plugin.ID, - OrgId: orgID, + pluginSetting := &pluginsettings.DTO{ + PluginID: plugin.ID, + OrgID: orgID, Enabled: plugin.AutoEnabled, Pinned: plugin.AutoEnabled, } @@ -427,9 +428,9 @@ func (hs *HTTPServer) pluginSettings(ctx context.Context, orgID int64) (map[stri } // add new setting which is enabled by default - pluginSetting := &models.PluginSettingInfoDTO{ - PluginId: plugin.ID, - OrgId: orgID, + pluginSetting := &pluginsettings.DTO{ + PluginID: plugin.ID, + OrgID: orgID, Enabled: true, } diff --git a/pkg/api/pluginproxy/pluginproxy.go b/pkg/api/pluginproxy/pluginproxy.go index 2679dfbd9aa..ca0d3092e3a 100644 --- a/pkg/api/pluginproxy/pluginproxy.go +++ b/pkg/api/pluginproxy/pluginproxy.go @@ -24,20 +24,21 @@ type templateData struct { func NewApiPluginProxy(ctx *models.ReqContext, proxyPath string, route *plugins.Route, appID string, cfg *setting.Cfg, pluginSettingsService pluginsettings.Service, secretsService secrets.Service) *httputil.ReverseProxy { director := func(req *http.Request) { - query := models.GetPluginSettingByIdQuery{OrgId: ctx.OrgId, PluginId: appID} - if err := pluginSettingsService.GetPluginSettingById(ctx.Req.Context(), &query); err != nil { + query := pluginsettings.GetByPluginIDArgs{OrgID: ctx.OrgId, PluginID: appID} + ps, err := pluginSettingsService.GetPluginSettingByPluginID(ctx.Req.Context(), &query) + if err != nil { ctx.JsonApiErr(500, "Failed to fetch plugin settings", err) return } - secureJsonData, err := secretsService.DecryptJsonData(ctx.Req.Context(), query.Result.SecureJsonData) + secureJsonData, err := secretsService.DecryptJsonData(ctx.Req.Context(), ps.SecureJSONData) if err != nil { ctx.JsonApiErr(500, "Failed to decrypt plugin settings", err) return } data := templateData{ - JsonData: query.Result.JsonData, + JsonData: ps.JSONData, SecureJsonData: secureJsonData, } diff --git a/pkg/api/pluginproxy/pluginproxy_test.go b/pkg/api/pluginproxy/pluginproxy_test.go index 9a106b3743a..28512cbd9c3 100644 --- a/pkg/api/pluginproxy/pluginproxy_test.go +++ b/pkg/api/pluginproxy/pluginproxy_test.go @@ -32,8 +32,8 @@ func TestPluginProxy(t *testing.T) { store := &mockPluginsSettingsService{} key, _ := secretsService.Encrypt(context.Background(), []byte("123"), secrets.WithoutScope()) - store.pluginSetting = &models.PluginSetting{ - SecureJsonData: map[string][]byte{ + store.pluginSetting = &pluginsettings.DTO{ + SecureJSONData: map[string][]byte{ "key": key, }, } @@ -65,7 +65,7 @@ func TestPluginProxy(t *testing.T) { require.NoError(t, err) store := &mockPluginsSettingsService{} - store.pluginSetting = &models.PluginSetting{} + store.pluginSetting = &pluginsettings.DTO{} req := getPluginProxiedRequest( t, @@ -92,7 +92,7 @@ func TestPluginProxy(t *testing.T) { require.NoError(t, err) store := &mockPluginsSettingsService{} - store.pluginSetting = &models.PluginSetting{} + store.pluginSetting = &pluginsettings.DTO{} req := getPluginProxiedRequest( t, @@ -118,7 +118,7 @@ func TestPluginProxy(t *testing.T) { require.NoError(t, err) store := &mockPluginsSettingsService{} - store.pluginSetting = &models.PluginSetting{} + store.pluginSetting = &pluginsettings.DTO{} req := getPluginProxiedRequest( t, @@ -145,8 +145,8 @@ func TestPluginProxy(t *testing.T) { } store := &mockPluginsSettingsService{} - store.pluginSetting = &models.PluginSetting{ - JsonData: map[string]interface{}{ + store.pluginSetting = &pluginsettings.DTO{ + JSONData: map[string]interface{}{ "dynamicUrl": "https://dynamic.grafana.com", }, } @@ -180,7 +180,7 @@ func TestPluginProxy(t *testing.T) { } store := &mockPluginsSettingsService{} - store.pluginSetting = &models.PluginSetting{} + store.pluginSetting = &pluginsettings.DTO{} httpReq, err := http.NewRequest(http.MethodGet, "", nil) require.NoError(t, err) @@ -216,9 +216,9 @@ func TestPluginProxy(t *testing.T) { map[string]string{"key": "123"}, secrets.WithoutScope(), ) - store.pluginSetting = &models.PluginSetting{ - JsonData: map[string]interface{}{"dynamicUrl": "https://dynamic.grafana.com"}, - SecureJsonData: encryptedJsonData, + store.pluginSetting = &pluginsettings.DTO{ + JSONData: map[string]interface{}{"dynamicUrl": "https://dynamic.grafana.com"}, + SecureJSONData: encryptedJsonData, } httpReq, err := http.NewRequest(http.MethodGet, "", nil) @@ -268,8 +268,8 @@ func TestPluginProxy(t *testing.T) { }, } pluginSettingsService := &mockPluginsSettingsService{ - pluginSetting: &models.PluginSetting{ - SecureJsonData: map[string][]byte{}, + pluginSetting: &pluginsettings.DTO{ + SecureJSONData: map[string][]byte{}, }, } proxy := NewApiPluginProxy(ctx, "", route, "", &setting.Cfg{}, pluginSettingsService, secretsService) @@ -304,27 +304,26 @@ func getPluginProxiedRequest(t *testing.T, secretsService secrets.Service, ctx * } type mockPluginsSettingsService struct { - pluginSetting *models.PluginSetting + pluginSetting *pluginsettings.DTO err error } -func (s *mockPluginsSettingsService) GetPluginSettings(_ context.Context, _ int64) ([]*models.PluginSettingInfoDTO, error) { +func (s *mockPluginsSettingsService) GetPluginSettings(_ context.Context, _ *pluginsettings.GetArgs) ([]*pluginsettings.DTO, error) { return nil, s.err } -func (s *mockPluginsSettingsService) GetPluginSettingById(_ context.Context, query *models.GetPluginSettingByIdQuery) error { - query.Result = s.pluginSetting - return s.err +func (s *mockPluginsSettingsService) GetPluginSettingByPluginID(_ context.Context, _ *pluginsettings.GetByPluginIDArgs) (*pluginsettings.DTO, error) { + return s.pluginSetting, s.err } -func (s *mockPluginsSettingsService) UpdatePluginSettingVersion(_ context.Context, _ *models.UpdatePluginSettingVersionCmd) error { +func (s *mockPluginsSettingsService) UpdatePluginSettingPluginVersion(_ context.Context, _ *pluginsettings.UpdatePluginVersionArgs) error { return s.err } -func (s *mockPluginsSettingsService) UpdatePluginSetting(_ context.Context, _ *models.UpdatePluginSettingCmd) error { +func (s *mockPluginsSettingsService) UpdatePluginSetting(_ context.Context, _ *pluginsettings.UpdateArgs) error { return s.err } -func (s *mockPluginsSettingsService) DecryptedValues(_ *models.PluginSetting) map[string]string { +func (s *mockPluginsSettingsService) DecryptedValues(_ *pluginsettings.DTO) map[string]string { return nil } diff --git a/pkg/api/plugins.go b/pkg/api/plugins.go index 0593553e6df..01b073cdf0e 100644 --- a/pkg/api/plugins.go +++ b/pkg/api/plugins.go @@ -24,6 +24,7 @@ import ( "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins/backendplugin" "github.com/grafana/grafana/pkg/plugins/manager/installer" + "github.com/grafana/grafana/pkg/services/pluginsettings" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/util/errutil" "github.com/grafana/grafana/pkg/util/proxyutil" @@ -142,15 +143,18 @@ func (hs *HTTPServer) GetPluginSettingByID(c *models.ReqContext) response.Respon dto.Pinned = plugin.AutoEnabled } - query := models.GetPluginSettingByIdQuery{PluginId: pluginID, OrgId: c.OrgId} - if err := hs.PluginSettings.GetPluginSettingById(c.Req.Context(), &query); err != nil { + ps, err := hs.PluginSettings.GetPluginSettingByPluginID(c.Req.Context(), &pluginsettings.GetByPluginIDArgs{ + PluginID: pluginID, + OrgID: c.OrgId, + }) + if err != nil { if !errors.Is(err, models.ErrPluginSettingNotFound) { - return response.Error(500, "Failed to get login settings", nil) + return response.Error(http.StatusInternalServerError, "Failed to get plugin settings", nil) } } else { - dto.Enabled = query.Result.Enabled - dto.Pinned = query.Result.Pinned - dto.JsonData = query.Result.JsonData + dto.Enabled = ps.Enabled + dto.Pinned = ps.Pinned + dto.JsonData = ps.JSONData } update, exists := hs.pluginsUpdateChecker.HasUpdate(c.Req.Context(), plugin.ID) @@ -175,7 +179,16 @@ func (hs *HTTPServer) UpdatePluginSetting(c *models.ReqContext) response.Respons cmd.OrgId = c.OrgId cmd.PluginId = pluginID - if err := hs.PluginSettings.UpdatePluginSetting(c.Req.Context(), &cmd); err != nil { + if err := hs.PluginSettings.UpdatePluginSetting(c.Req.Context(), &pluginsettings.UpdateArgs{ + Enabled: cmd.Enabled, + Pinned: cmd.Pinned, + JSONData: cmd.JsonData, + SecureJSONData: cmd.SecureJsonData, + PluginVersion: cmd.PluginVersion, + PluginID: cmd.PluginId, + OrgID: cmd.OrgId, + EncryptedSecureJSONData: cmd.EncryptedSecureJsonData, + }); err != nil { return response.Error(500, "Failed to update plugin setting", err) } diff --git a/pkg/plugins/plugincontext/plugincontext.go b/pkg/plugins/plugincontext/plugincontext.go index 87470d95c70..865a42905fa 100644 --- a/pkg/plugins/plugincontext/plugincontext.go +++ b/pkg/plugins/plugincontext/plugincontext.go @@ -66,7 +66,7 @@ func (p *Provider) Get(ctx context.Context, pluginID string, datasourceUID strin return pc, false, errutil.Wrap("Failed to get plugin settings", err) } } else { - jsonData, err = json.Marshal(ps.JsonData) + jsonData, err = json.Marshal(ps.JSONData) if err != nil { return pc, false, errutil.Wrap("Failed to unmarshal plugin json data", err) } @@ -103,23 +103,26 @@ func (p *Provider) Get(ctx context.Context, pluginID string, datasourceUID strin const pluginSettingsCacheTTL = 5 * time.Second const pluginSettingsCachePrefix = "plugin-setting-" -func (p *Provider) getCachedPluginSettings(ctx context.Context, pluginID string, user *models.SignedInUser) (*models.PluginSetting, error) { +func (p *Provider) getCachedPluginSettings(ctx context.Context, pluginID string, user *models.SignedInUser) (*pluginsettings.DTO, error) { cacheKey := pluginSettingsCachePrefix + pluginID if cached, found := p.cacheService.Get(cacheKey); found { - ps := cached.(*models.PluginSetting) - if ps.OrgId == user.OrgId { + ps := cached.(*pluginsettings.DTO) + if ps.OrgID == user.OrgId { return ps, nil } } - query := models.GetPluginSettingByIdQuery{PluginId: pluginID, OrgId: user.OrgId} - if err := p.pluginSettingsService.GetPluginSettingById(ctx, &query); err != nil { + ps, err := p.pluginSettingsService.GetPluginSettingByPluginID(ctx, &pluginsettings.GetByPluginIDArgs{ + PluginID: pluginID, + OrgID: user.OrgId, + }) + if err != nil { return nil, err } - p.cacheService.Set(cacheKey, query.Result, pluginSettingsCacheTTL) - return query.Result, nil + p.cacheService.Set(cacheKey, ps, pluginSettingsCacheTTL) + return ps, nil } func (p *Provider) decryptSecureJsonDataFn() func(map[string][]byte) map[string]string { diff --git a/pkg/services/plugindashboards/service/dashboard_updater.go b/pkg/services/plugindashboards/service/dashboard_updater.go index 88409c968fd..d5564f8eb19 100644 --- a/pkg/services/plugindashboards/service/dashboard_updater.go +++ b/pkg/services/plugindashboards/service/dashboard_updater.go @@ -54,7 +54,7 @@ type DashboardUpdater struct { func (du *DashboardUpdater) updateAppDashboards() { du.logger.Debug("Looking for app dashboard updates") - pluginSettings, err := du.pluginSettingsService.GetPluginSettings(context.Background(), 0) + pluginSettings, err := du.pluginSettingsService.GetPluginSettings(context.Background(), &pluginsettings.GetArgs{OrgID: 0}) if err != nil { du.logger.Error("Failed to get all plugin settings", "error", err) return @@ -66,9 +66,9 @@ func (du *DashboardUpdater) updateAppDashboards() { continue } - if pluginDef, exists := du.pluginStore.Plugin(context.Background(), pluginSetting.PluginId); exists { + if pluginDef, exists := du.pluginStore.Plugin(context.Background(), pluginSetting.PluginID); exists { if pluginDef.Info.Version != pluginSetting.PluginVersion { - du.syncPluginDashboards(context.Background(), pluginDef, pluginSetting.OrgId) + du.syncPluginDashboards(context.Background(), pluginDef, pluginSetting.OrgID) } } } @@ -112,20 +112,20 @@ func (du *DashboardUpdater) syncPluginDashboards(ctx context.Context, plugin plu } // update version in plugin_setting table to mark that we have processed the update - query := models.GetPluginSettingByIdQuery{PluginId: plugin.ID, OrgId: orgID} - if err := du.pluginSettingsService.GetPluginSettingById(ctx, &query); err != nil { + query := pluginsettings.GetByPluginIDArgs{PluginID: plugin.ID, OrgID: orgID} + ps, err := du.pluginSettingsService.GetPluginSettingByPluginID(ctx, &query) + if err != nil { du.logger.Error("Failed to read plugin setting by ID", "error", err) return } - appSetting := query.Result - cmd := models.UpdatePluginSettingVersionCmd{ - OrgId: appSetting.OrgId, - PluginId: appSetting.PluginId, + cmd := pluginsettings.UpdatePluginVersionArgs{ + OrgID: ps.OrgID, + PluginID: ps.PluginID, PluginVersion: plugin.Info.Version, } - if err := du.pluginSettingsService.UpdatePluginSettingVersion(ctx, &cmd); err != nil { + if err := du.pluginSettingsService.UpdatePluginSettingPluginVersion(ctx, &cmd); err != nil { du.logger.Error("Failed to update plugin setting version", "error", err) } } diff --git a/pkg/services/plugindashboards/service/dashboard_updater_test.go b/pkg/services/plugindashboards/service/dashboard_updater_test.go index efb0c50878b..5648bb613be 100644 --- a/pkg/services/plugindashboards/service/dashboard_updater_test.go +++ b/pkg/services/plugindashboards/service/dashboard_updater_test.go @@ -11,6 +11,7 @@ import ( "github.com/grafana/grafana/pkg/services/dashboardimport" "github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/plugindashboards" + "github.com/grafana/grafana/pkg/services/pluginsettings" "github.com/grafana/grafana/pkg/services/pluginsettings/service" "github.com/stretchr/testify/require" ) @@ -29,9 +30,9 @@ func TestDashboardUpdater(t *testing.T) { scenario(t, "Without any stored enabled plugin shouldn't delete/import any dashboards", scenarioInput{ - storedPluginSettings: []*models.PluginSettingInfoDTO{ + storedPluginSettings: []*pluginsettings.DTO{ { - PluginId: "test", + PluginID: "test", Enabled: false, }, }, @@ -51,9 +52,9 @@ func TestDashboardUpdater(t *testing.T) { scenario(t, "With stored enabled plugin, but not installed shouldn't delete/import any dashboards", scenarioInput{ - storedPluginSettings: []*models.PluginSettingInfoDTO{ + storedPluginSettings: []*pluginsettings.DTO{ { - PluginId: "test", + PluginID: "test", Enabled: true, }, }, @@ -73,9 +74,9 @@ func TestDashboardUpdater(t *testing.T) { scenario(t, "With stored enabled plugin and installed with same version shouldn't delete/import any dashboards", scenarioInput{ - storedPluginSettings: []*models.PluginSettingInfoDTO{ + storedPluginSettings: []*pluginsettings.DTO{ { - PluginId: "test", + PluginID: "test", Enabled: true, PluginVersion: "1.0.0", }, @@ -105,9 +106,9 @@ func TestDashboardUpdater(t *testing.T) { scenario(t, "With stored enabled plugin and installed with different versions, but no dashboard updates shouldn't delete/import dashboards", scenarioInput{ - storedPluginSettings: []*models.PluginSettingInfoDTO{ + storedPluginSettings: []*pluginsettings.DTO{ { - PluginId: "test", + PluginID: "test", Enabled: true, PluginVersion: "1.0.0", }, @@ -140,12 +141,12 @@ func TestDashboardUpdater(t *testing.T) { scenario(t, "With stored enabled plugin and installed with different versions and with dashboard updates should delete/import dashboards", scenarioInput{ - storedPluginSettings: []*models.PluginSettingInfoDTO{ + storedPluginSettings: []*pluginsettings.DTO{ { - PluginId: "test", + PluginID: "test", Enabled: true, PluginVersion: "1.0.0", - OrgId: 2, + OrgID: 2, }, }, installedPlugins: []plugins.PluginDTO{ @@ -215,11 +216,11 @@ func TestDashboardUpdater(t *testing.T) { scenario(t, "When app plugin is disabled that have imported dashboards should delete them", scenarioInput{ - storedPluginSettings: []*models.PluginSettingInfoDTO{ + storedPluginSettings: []*pluginsettings.DTO{ { - PluginId: "test", + PluginID: "test", Enabled: true, - OrgId: 2, + OrgID: 2, }, }, installedPlugins: []plugins.PluginDTO{ @@ -262,11 +263,11 @@ func TestDashboardUpdater(t *testing.T) { scenario(t, "When app plugin is enabled, stored disabled plugin and with dashboard updates should import dashboards", scenarioInput{ - storedPluginSettings: []*models.PluginSettingInfoDTO{ + storedPluginSettings: []*pluginsettings.DTO{ { - PluginId: "test", + PluginID: "test", Enabled: false, - OrgId: 2, + OrgID: 2, PluginVersion: "1.0.0", }, }, @@ -389,38 +390,41 @@ func (m *importDashboardServiceMock) ImportDashboard(ctx context.Context, req *d type pluginsSettingsServiceMock struct { service.Service - storedPluginSettings []*models.PluginSettingInfoDTO + storedPluginSettings []*pluginsettings.DTO getPluginSettingsArgs []int64 err error } -func (s *pluginsSettingsServiceMock) GetPluginSettings(_ context.Context, orgID int64) ([]*models.PluginSettingInfoDTO, error) { - s.getPluginSettingsArgs = append(s.getPluginSettingsArgs, orgID) +func (s *pluginsSettingsServiceMock) GetPluginSettings(_ context.Context, args *pluginsettings.GetArgs) ([]*pluginsettings.DTO, error) { + s.getPluginSettingsArgs = append(s.getPluginSettingsArgs, args.OrgID) return s.storedPluginSettings, s.err } -func (s *pluginsSettingsServiceMock) GetPluginSettingById(_ context.Context, query *models.GetPluginSettingByIdQuery) error { +func (s *pluginsSettingsServiceMock) GetPluginSettingByPluginID(_ context.Context, args *pluginsettings.GetByPluginIDArgs) (*pluginsettings.DTO, error) { for _, setting := range s.storedPluginSettings { - if setting.PluginId == query.PluginId { - query.Result = &models.PluginSetting{ - PluginId: query.PluginId, - OrgId: query.OrgId, - } - break + if setting.PluginID == args.PluginID { + return &pluginsettings.DTO{ + PluginID: args.PluginID, + OrgID: args.OrgID, + }, nil } } - return s.err + return nil, s.err } -func (s *pluginsSettingsServiceMock) UpdatePluginSettingVersion(_ context.Context, _ *models.UpdatePluginSettingVersionCmd) error { +func (s *pluginsSettingsServiceMock) UpdatePluginSettingPluginVersion(_ context.Context, _ *pluginsettings.UpdatePluginVersionArgs) error { return s.err } -func (s *pluginsSettingsServiceMock) UpdatePluginSetting(_ context.Context, _ *models.UpdatePluginSettingCmd) error { +func (s *pluginsSettingsServiceMock) UpdatePluginSetting(_ context.Context, _ *pluginsettings.UpdateArgs) error { return s.err } +func (s *pluginsSettingsServiceMock) DecryptedValues(_ *pluginsettings.DTO) map[string]string { + return nil +} + type dashboardServiceMock struct { dashboards.DashboardService deleteDashboardArgs []struct { @@ -441,7 +445,7 @@ func (s *dashboardServiceMock) DeleteDashboard(_ context.Context, dashboardId in } type scenarioInput struct { - storedPluginSettings []*models.PluginSettingInfoDTO + storedPluginSettings []*pluginsettings.DTO installedPlugins []plugins.PluginDTO pluginDashboards []*plugindashboards.PluginDashboard } diff --git a/pkg/services/pluginsettings/models.go b/pkg/services/pluginsettings/models.go new file mode 100644 index 00000000000..d8e23326f2b --- /dev/null +++ b/pkg/services/pluginsettings/models.go @@ -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 +} diff --git a/pkg/services/pluginsettings/pluginsettings.go b/pkg/services/pluginsettings/pluginsettings.go index 32765572d8c..7c8a3e94ff2 100644 --- a/pkg/services/pluginsettings/pluginsettings.go +++ b/pkg/services/pluginsettings/pluginsettings.go @@ -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 } diff --git a/pkg/services/pluginsettings/service/service.go b/pkg/services/pluginsettings/service/service.go index e6f840b42d1..d1b257ec860 100644 --- a/pkg/services/pluginsettings/service/service.go +++ b/pkg/services/pluginsettings/service/service.go @@ -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, } diff --git a/pkg/services/pluginsettings/service/service_test.go b/pkg/services/pluginsettings/service/service_test.go index b976517b3f3..8459c76b4f2 100644 --- a/pkg/services/pluginsettings/service/service_test.go +++ b/pkg/services/pluginsettings/service/service_test.go @@ -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"] diff --git a/pkg/services/provisioning/plugins/plugin_provisioner.go b/pkg/services/provisioning/plugins/plugin_provisioner.go index 0f23e48f571..3a55b5bd684 100644 --- a/pkg/services/provisioning/plugins/plugin_provisioner.go +++ b/pkg/services/provisioning/plugins/plugin_provisioner.go @@ -48,27 +48,28 @@ func (ap *PluginProvisioner) apply(ctx context.Context, cfg *pluginsAsConfig) er app.OrgID = 1 } - query := &models.GetPluginSettingByIdQuery{OrgId: app.OrgID, PluginId: app.PluginID} - err := ap.pluginSettings.GetPluginSettingById(ctx, query) + ps, err := ap.pluginSettings.GetPluginSettingByPluginID(ctx, &pluginsettings.GetByPluginIDArgs{ + OrgID: app.OrgID, + PluginID: app.PluginID, + }) if err != nil { if !errors.Is(err, models.ErrPluginSettingNotFound) { return err } } else { - app.PluginVersion = query.Result.PluginVersion + app.PluginVersion = ps.PluginVersion } ap.log.Info("Updating app from configuration ", "type", app.PluginID, "enabled", app.Enabled) - cmd := &models.UpdatePluginSettingCmd{ - OrgId: app.OrgID, - PluginId: app.PluginID, + if err := ap.pluginSettings.UpdatePluginSetting(ctx, &pluginsettings.UpdateArgs{ + OrgID: app.OrgID, + PluginID: app.PluginID, Enabled: app.Enabled, Pinned: app.Pinned, - JsonData: app.JSONData, - SecureJsonData: app.SecureJSONData, + JSONData: app.JSONData, + SecureJSONData: app.SecureJSONData, PluginVersion: app.PluginVersion, - } - if err := ap.pluginSettings.UpdatePluginSetting(ctx, cmd); err != nil { + }); err != nil { return err } } diff --git a/pkg/services/provisioning/plugins/plugin_provisioner_test.go b/pkg/services/provisioning/plugins/plugin_provisioner_test.go index 59076b2a4a9..e47f9d1da0f 100644 --- a/pkg/services/provisioning/plugins/plugin_provisioner_test.go +++ b/pkg/services/provisioning/plugins/plugin_provisioner_test.go @@ -5,6 +5,8 @@ import ( "errors" "testing" + "github.com/grafana/grafana/pkg/services/pluginsettings" + "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/models" "github.com/stretchr/testify/require" @@ -25,8 +27,8 @@ func TestPluginProvisioner(t *testing.T) { Apps: []*appFromConfig{ {PluginID: "test-plugin", OrgID: 2, Enabled: true}, {PluginID: "test-plugin-2", OrgID: 3, Enabled: false}, - {PluginID: "test-plugin", OrgName: "Org 4", Enabled: true}, - {PluginID: "test-plugin-2", OrgID: 1, Enabled: true}, + {PluginID: "test-plugin", OrgName: "Org 4", Enabled: true, SecureJSONData: map[string]string{"token": "secret"}}, + {PluginID: "test-plugin-2", OrgID: 1, Enabled: true, JSONData: map[string]interface{}{"test": true}}, }, }, } @@ -36,27 +38,31 @@ func TestPluginProvisioner(t *testing.T) { err := ap.applyChanges(context.Background(), "") require.NoError(t, err) - require.Len(t, store.sentCommands, 4) + require.Len(t, store.updateRequests, 4) testCases := []struct { - ExpectedPluginID string - ExpectedOrgID int64 - ExpectedEnabled bool - ExpectedPluginVersion string + ExpectedPluginID string + ExpectedOrgID int64 + ExpectedEnabled bool + ExpectedPluginVersion string + ExpectedJSONData map[string]interface{} + ExpectedSecureJSONData map[string]string }{ {ExpectedPluginID: "test-plugin", ExpectedOrgID: 2, ExpectedEnabled: true, ExpectedPluginVersion: "2.0.1"}, {ExpectedPluginID: "test-plugin-2", ExpectedOrgID: 3, ExpectedEnabled: false}, - {ExpectedPluginID: "test-plugin", ExpectedOrgID: 4, ExpectedEnabled: true}, - {ExpectedPluginID: "test-plugin-2", ExpectedOrgID: 1, ExpectedEnabled: true}, + {ExpectedPluginID: "test-plugin", ExpectedOrgID: 4, ExpectedEnabled: true, ExpectedSecureJSONData: map[string]string{"token": "secret"}}, + {ExpectedPluginID: "test-plugin-2", ExpectedOrgID: 1, ExpectedEnabled: true, ExpectedJSONData: map[string]interface{}{"test": true}}, } for index, tc := range testCases { - cmd := store.sentCommands[index] + cmd := store.updateRequests[index] require.NotNil(t, cmd) - require.Equal(t, tc.ExpectedPluginID, cmd.PluginId) - require.Equal(t, tc.ExpectedOrgID, cmd.OrgId) + require.Equal(t, tc.ExpectedPluginID, cmd.PluginID) + require.Equal(t, tc.ExpectedOrgID, cmd.OrgID) require.Equal(t, tc.ExpectedEnabled, cmd.Enabled) require.Equal(t, tc.ExpectedPluginVersion, cmd.PluginVersion) + require.Equal(t, tc.ExpectedJSONData, cmd.JSONData) + require.Equal(t, tc.ExpectedSecureJSONData, cmd.SecureJSONData) } }) } @@ -66,45 +72,44 @@ type testConfigReader struct { err error } -func (tcr *testConfigReader) readConfig(ctx context.Context, path string) ([]*pluginsAsConfig, error) { +func (tcr *testConfigReader) readConfig(_ context.Context, _ string) ([]*pluginsAsConfig, error) { return tcr.result, tcr.err } type mockStore struct { - sentCommands []*models.UpdatePluginSettingCmd + updateRequests []*pluginsettings.UpdateArgs } -func (m *mockStore) GetOrgByNameHandler(ctx context.Context, query *models.GetOrgByNameQuery) error { +func (m *mockStore) GetOrgByNameHandler(_ context.Context, query *models.GetOrgByNameQuery) error { if query.Name == "Org 4" { query.Result = &models.Org{Id: 4} } return nil } -func (m *mockStore) GetPluginSettingById(ctx context.Context, query *models.GetPluginSettingByIdQuery) error { - if query.PluginId == "test-plugin" && query.OrgId == 2 { - query.Result = &models.PluginSetting{ +func (m *mockStore) GetPluginSettingByPluginID(_ context.Context, args *pluginsettings.GetByPluginIDArgs) (*pluginsettings.DTO, error) { + if args.PluginID == "test-plugin" && args.OrgID == 2 { + return &pluginsettings.DTO{ PluginVersion: "2.0.1", - } - return nil + }, nil } - return models.ErrPluginSettingNotFound + return nil, models.ErrPluginSettingNotFound } -func (m *mockStore) UpdatePluginSetting(_ context.Context, cmd *models.UpdatePluginSettingCmd) error { - m.sentCommands = append(m.sentCommands, cmd) +func (m *mockStore) UpdatePluginSetting(_ context.Context, args *pluginsettings.UpdateArgs) error { + m.updateRequests = append(m.updateRequests, args) return nil } -func (m *mockStore) UpdatePluginSettingVersion(_ context.Context, _ *models.UpdatePluginSettingVersionCmd) error { +func (m *mockStore) UpdatePluginSettingPluginVersion(_ context.Context, _ *pluginsettings.UpdatePluginVersionArgs) error { return nil } -func (m *mockStore) GetPluginSettings(_ context.Context, _ int64) ([]*models.PluginSettingInfoDTO, error) { +func (m *mockStore) GetPluginSettings(_ context.Context, _ *pluginsettings.GetArgs) ([]*pluginsettings.DTO, error) { return nil, nil } -func (m *mockStore) DecryptedValues(_ *models.PluginSetting) map[string]string { +func (m *mockStore) DecryptedValues(_ *pluginsettings.DTO) map[string]string { return nil } diff --git a/pkg/services/sqlstore/mockstore/mockstore.go b/pkg/services/sqlstore/mockstore/mockstore.go index 2fe47a70bfc..63e221be0b0 100644 --- a/pkg/services/sqlstore/mockstore/mockstore.go +++ b/pkg/services/sqlstore/mockstore/mockstore.go @@ -291,7 +291,7 @@ func (m *SQLStoreMock) PatchPreferences(ctx context.Context, cmd *models.PatchPr return m.ExpectedError } -func (m *SQLStoreMock) GetPluginSettings(ctx context.Context, orgID int64) ([]*models.PluginSettingInfoDTO, error) { +func (m *SQLStoreMock) GetPluginSettings(ctx context.Context, orgID int64) ([]*models.PluginSetting, error) { return nil, m.ExpectedError } diff --git a/pkg/services/sqlstore/plugin_setting.go b/pkg/services/sqlstore/plugin_setting.go index a2581c9dceb..6b9c9afc2a2 100644 --- a/pkg/services/sqlstore/plugin_setting.go +++ b/pkg/services/sqlstore/plugin_setting.go @@ -7,25 +7,22 @@ import ( "github.com/grafana/grafana/pkg/models" ) -func (ss *SQLStore) GetPluginSettings(ctx context.Context, orgID int64) ([]*models.PluginSettingInfoDTO, error) { - sql := `SELECT org_id, plugin_id, enabled, pinned, plugin_version - FROM plugin_setting ` - params := make([]interface{}, 0) +func (ss *SQLStore) GetPluginSettings(ctx context.Context, orgID int64) ([]*models.PluginSetting, error) { + var rslt = make([]*models.PluginSetting, 0) + err := ss.WithDbSession(ctx, func(sess *DBSession) error { + if orgID != 0 { + sess.Where("org_id", orgID) + } - if orgID != 0 { - sql += "WHERE org_id=?" - params = append(params, orgID) - } + err := sess.Find(&rslt) + if err != nil { + return err + } - var rslt []*models.PluginSettingInfoDTO - err := ss.WithDbSession(ctx, func(sess *DBSession) error { - return sess.SQL(sql, params...).Find(&rslt) + return nil }) - if err != nil { - return nil, err - } - return rslt, nil + return rslt, err } func (ss *SQLStore) GetPluginSettingById(ctx context.Context, query *models.GetPluginSettingByIdQuery) error { diff --git a/pkg/services/sqlstore/store.go b/pkg/services/sqlstore/store.go index 467550a1ac2..cdd6b50e58a 100644 --- a/pkg/services/sqlstore/store.go +++ b/pkg/services/sqlstore/store.go @@ -64,7 +64,7 @@ type Store interface { GetPreferences(ctx context.Context, query *models.GetPreferencesQuery) error SavePreferences(ctx context.Context, cmd *models.SavePreferencesCommand) error PatchPreferences(ctx context.Context, cmd *models.PatchPreferencesCommand) error - GetPluginSettings(ctx context.Context, orgID int64) ([]*models.PluginSettingInfoDTO, error) + GetPluginSettings(ctx context.Context, orgID int64) ([]*models.PluginSetting, error) GetPluginSettingById(ctx context.Context, query *models.GetPluginSettingByIdQuery) error UpdatePluginSetting(ctx context.Context, cmd *models.UpdatePluginSettingCmd) error UpdatePluginSettingVersion(ctx context.Context, cmd *models.UpdatePluginSettingVersionCmd) error