diff --git a/pkg/api/http_server.go b/pkg/api/http_server.go index 7fddd31bfaa..7e6602d46db 100644 --- a/pkg/api/http_server.go +++ b/pkg/api/http_server.go @@ -48,7 +48,7 @@ import ( "github.com/grafana/grafana/pkg/services/login" "github.com/grafana/grafana/pkg/services/ngalert" "github.com/grafana/grafana/pkg/services/notifications" - "github.com/grafana/grafana/pkg/services/pluginsettings" + pluginSettings "github.com/grafana/grafana/pkg/services/pluginsettings/service" "github.com/grafana/grafana/pkg/services/provisioning" "github.com/grafana/grafana/pkg/services/query" "github.com/grafana/grafana/pkg/services/queryhistory" @@ -140,7 +140,7 @@ type HTTPServer struct { commentsService *comments.Service AlertNotificationService *alerting.AlertNotificationService DashboardsnapshotsService *dashboardsnapshots.Service - PluginSettings *pluginsettings.ServiceImpl + PluginSettings *pluginSettings.Service } type ServerOptions struct { @@ -171,7 +171,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi notificationService *notifications.NotificationService, dashboardService dashboards.DashboardService, dashboardProvisioningService dashboards.DashboardProvisioningService, folderService dashboards.FolderService, datasourcePermissionsService permissions.DatasourcePermissionsService, alertNotificationService *alerting.AlertNotificationService, - dashboardsnapshotsService *dashboardsnapshots.Service, commentsService *comments.Service, pluginSettings *pluginsettings.ServiceImpl, + dashboardsnapshotsService *dashboardsnapshots.Service, commentsService *comments.Service, pluginSettings *pluginSettings.Service, ) (*HTTPServer, error) { web.Env = cfg.Env m := web.New() diff --git a/pkg/api/pluginproxy/pluginproxy.go b/pkg/api/pluginproxy/pluginproxy.go index 663d8a1130f..2679dfbd9aa 100644 --- a/pkg/api/pluginproxy/pluginproxy.go +++ b/pkg/api/pluginproxy/pluginproxy.go @@ -22,10 +22,10 @@ type templateData struct { // NewApiPluginProxy create a plugin proxy func NewApiPluginProxy(ctx *models.ReqContext, proxyPath string, route *plugins.Route, - appID string, cfg *setting.Cfg, store pluginsettings.Service, secretsService secrets.Service) *httputil.ReverseProxy { + 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 := store.GetPluginSettingById(ctx.Req.Context(), &query); err != nil { + if err := pluginSettingsService.GetPluginSettingById(ctx.Req.Context(), &query); err != nil { ctx.JsonApiErr(500, "Failed to fetch plugin settings", err) return } diff --git a/pkg/api/pluginproxy/pluginproxy_test.go b/pkg/api/pluginproxy/pluginproxy_test.go index 8a401f86671..0b0c166b8b4 100644 --- a/pkg/api/pluginproxy/pluginproxy_test.go +++ b/pkg/api/pluginproxy/pluginproxy_test.go @@ -267,11 +267,12 @@ func TestPluginProxy(t *testing.T) { Resp: responseWriter, }, } - store := &mockPluginsSettingsService{} - store.pluginSetting = &models.PluginSetting{ - SecureJsonData: map[string][]byte{}, + pluginSettingsService := &mockPluginsSettingsService{ + pluginSetting: &models.PluginSetting{ + SecureJsonData: map[string][]byte{}, + }, } - proxy := NewApiPluginProxy(ctx, "", route, "", &setting.Cfg{}, store, secretsService) + proxy := NewApiPluginProxy(ctx, "", route, "", &setting.Cfg{}, pluginSettingsService, secretsService) proxy.ServeHTTP(ctx.Resp, ctx.Req) for { @@ -285,7 +286,7 @@ func TestPluginProxy(t *testing.T) { } // getPluginProxiedRequest is a helper for easier setup of tests based on global config and ReqContext. -func getPluginProxiedRequest(t *testing.T, secretsService secrets.Service, ctx *models.ReqContext, cfg *setting.Cfg, route *plugins.Route, store pluginsettings.Service) *http.Request { +func getPluginProxiedRequest(t *testing.T, secretsService secrets.Service, ctx *models.ReqContext, cfg *setting.Cfg, route *plugins.Route, pluginSettingsService pluginsettings.Service) *http.Request { // insert dummy route if none is specified if route == nil { route = &plugins.Route{ @@ -294,7 +295,7 @@ func getPluginProxiedRequest(t *testing.T, secretsService secrets.Service, ctx * ReqRole: models.ROLE_EDITOR, } } - proxy := NewApiPluginProxy(ctx, "", route, "", cfg, store, secretsService) + proxy := NewApiPluginProxy(ctx, "", route, "", cfg, pluginSettingsService, secretsService) req, err := http.NewRequest(http.MethodGet, "/api/plugin-proxy/grafana-simple-app/api/v4/alerts", nil) require.NoError(t, err) @@ -307,15 +308,19 @@ type mockPluginsSettingsService struct { err error } -func (s *mockPluginsSettingsService) GetPluginSettingById(ctx context.Context, query *models.GetPluginSettingByIdQuery) error { +func (s *mockPluginsSettingsService) GetPluginSettings(_ context.Context, _ int64) ([]*models.PluginSettingInfoDTO, 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) UpdatePluginSettingVersion(ctx context.Context, cmd *models.UpdatePluginSettingVersionCmd) error { +func (s *mockPluginsSettingsService) UpdatePluginSettingVersion(_ context.Context, _ *models.UpdatePluginSettingVersionCmd) error { return s.err } -func (s *mockPluginsSettingsService) UpdatePluginSetting(ctx context.Context, cmd *models.UpdatePluginSettingCmd) error { +func (s *mockPluginsSettingsService) UpdatePluginSetting(_ context.Context, _ *models.UpdatePluginSettingCmd) error { return s.err } diff --git a/pkg/plugins/plugincontext/plugincontext.go b/pkg/plugins/plugincontext/plugincontext.go index 30157455b6a..034fc4d613d 100644 --- a/pkg/plugins/plugincontext/plugincontext.go +++ b/pkg/plugins/plugincontext/plugincontext.go @@ -15,32 +15,32 @@ import ( "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins/adapters" "github.com/grafana/grafana/pkg/services/datasources" - "github.com/grafana/grafana/pkg/services/pluginsettings" + pluginSettings "github.com/grafana/grafana/pkg/services/pluginsettings/service" "github.com/grafana/grafana/pkg/services/secrets" "github.com/grafana/grafana/pkg/util/errutil" ) func ProvideService(bus bus.Bus, cacheService *localcache.CacheService, pluginStore plugins.Store, dataSourceCache datasources.CacheService, secretsService secrets.Service, - pluginSettingsService *pluginsettings.ServiceImpl) *Provider { + pluginSettingsService *pluginSettings.Service) *Provider { return &Provider{ - Bus: bus, - CacheService: cacheService, + bus: bus, + cacheService: cacheService, pluginStore: pluginStore, - DataSourceCache: dataSourceCache, - SecretsService: secretsService, - PluginSettingsService: pluginSettingsService, + dataSourceCache: dataSourceCache, + secretsService: secretsService, + pluginSettingsService: pluginSettingsService, logger: log.New("plugincontext"), } } type Provider struct { - Bus bus.Bus - CacheService *localcache.CacheService + bus bus.Bus + cacheService *localcache.CacheService pluginStore plugins.Store - DataSourceCache datasources.CacheService - SecretsService secrets.Service - PluginSettingsService *pluginsettings.ServiceImpl + dataSourceCache datasources.CacheService + secretsService secrets.Service + pluginSettingsService *pluginSettings.Service logger log.Logger } @@ -70,7 +70,7 @@ func (p *Provider) Get(ctx context.Context, pluginID string, datasourceUID strin if err != nil { return pc, false, errutil.Wrap("Failed to unmarshal plugin json data", err) } - decryptedSecureJSONData = p.PluginSettingsService.DecryptedValues(ps) + decryptedSecureJSONData = p.pluginSettingsService.DecryptedValues(ps) updated = ps.Updated } @@ -86,7 +86,7 @@ func (p *Provider) Get(ctx context.Context, pluginID string, datasourceUID strin } if datasourceUID != "" { - ds, err := p.DataSourceCache.GetDatasourceByUID(ctx, datasourceUID, user, skipCache) + ds, err := p.dataSourceCache.GetDatasourceByUID(ctx, datasourceUID, user, skipCache) if err != nil { return pc, false, errutil.Wrap("Failed to get datasource", err) } @@ -106,7 +106,7 @@ const pluginSettingsCachePrefix = "plugin-setting-" func (p *Provider) getCachedPluginSettings(ctx context.Context, pluginID string, user *models.SignedInUser) (*models.PluginSetting, error) { cacheKey := pluginSettingsCachePrefix + pluginID - if cached, found := p.CacheService.Get(cacheKey); found { + if cached, found := p.cacheService.Get(cacheKey); found { ps := cached.(*models.PluginSetting) if ps.OrgId == user.OrgId { return ps, nil @@ -114,17 +114,17 @@ func (p *Provider) getCachedPluginSettings(ctx context.Context, pluginID string, } query := models.GetPluginSettingByIdQuery{PluginId: pluginID, OrgId: user.OrgId} - if err := p.PluginSettingsService.GetPluginSettingById(ctx, &query); err != nil { + if err := p.pluginSettingsService.GetPluginSettingById(ctx, &query); err != nil { return nil, err } - p.CacheService.Set(cacheKey, query.Result, pluginSettingsCacheTTL) + p.cacheService.Set(cacheKey, query.Result, pluginSettingsCacheTTL) return query.Result, nil } func (p *Provider) decryptSecureJsonDataFn() func(map[string][]byte) map[string]string { return func(m map[string][]byte) map[string]string { - decryptedJsonData, err := p.SecretsService.DecryptJsonData(context.Background(), m) + decryptedJsonData, err := p.secretsService.DecryptJsonData(context.Background(), m) if err != nil { p.logger.Error("Failed to decrypt secure json data", "error", err) } diff --git a/pkg/server/backgroundsvcs/background_services.go b/pkg/server/backgroundsvcs/background_services.go index e77f4c17c46..cb6f7ec27e4 100644 --- a/pkg/server/backgroundsvcs/background_services.go +++ b/pkg/server/backgroundsvcs/background_services.go @@ -17,7 +17,6 @@ import ( "github.com/grafana/grafana/pkg/services/ngalert" "github.com/grafana/grafana/pkg/services/notifications" "github.com/grafana/grafana/pkg/services/plugindashboards" - "github.com/grafana/grafana/pkg/services/pluginsettings" "github.com/grafana/grafana/pkg/services/provisioning" "github.com/grafana/grafana/pkg/services/rendering" secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager" @@ -35,7 +34,7 @@ func ProvideBackgroundServiceRegistry( metrics *metrics.InternalMetricsService, secretsService *secretsManager.SecretsService, remoteCache *remotecache.RemoteCache, thumbnailsService thumbs.Service, // Need to make sure these are initialized, is there a better place to put them? - _ *plugindashboards.Service, _ *dashboardsnapshots.Service, _ *pluginsettings.ServiceImpl, + _ *plugindashboards.Service, _ *dashboardsnapshots.Service, _ *alerting.AlertNotificationService, _ serviceaccounts.Service, ) *BackgroundServiceRegistry { return NewBackgroundServiceRegistry( diff --git a/pkg/server/wire.go b/pkg/server/wire.go index 530d0f43806..80569c670ed 100644 --- a/pkg/server/wire.go +++ b/pkg/server/wire.go @@ -58,6 +58,7 @@ import ( "github.com/grafana/grafana/pkg/services/oauthtoken" "github.com/grafana/grafana/pkg/services/plugindashboards" "github.com/grafana/grafana/pkg/services/pluginsettings" + pluginSettings "github.com/grafana/grafana/pkg/services/pluginsettings/service" "github.com/grafana/grafana/pkg/services/query" "github.com/grafana/grafana/pkg/services/queryhistory" "github.com/grafana/grafana/pkg/services/quota" @@ -193,8 +194,8 @@ var wireBasicSet = wire.NewSet( dashboardsnapshots.ProvideService, datasourceservice.ProvideService, wire.Bind(new(datasources.DataSourceService), new(*datasourceservice.Service)), - pluginsettings.ProvideService, - wire.Bind(new(pluginsettings.Service), new(*pluginsettings.ServiceImpl)), + pluginSettings.ProvideService, + wire.Bind(new(pluginsettings.Service), new(*pluginSettings.Service)), alerting.ProvideService, serviceaccountsmanager.ProvideServiceAccountsService, wire.Bind(new(serviceaccounts.Service), new(*serviceaccountsmanager.ServiceAccountsService)), diff --git a/pkg/services/plugindashboards/plugindashboards.go b/pkg/services/plugindashboards/plugindashboards.go index 28fb7b1dffb..feaaf48e382 100644 --- a/pkg/services/plugindashboards/plugindashboards.go +++ b/pkg/services/plugindashboards/plugindashboards.go @@ -10,32 +10,24 @@ import ( "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/services/dashboardimport" "github.com/grafana/grafana/pkg/services/pluginsettings" - "github.com/grafana/grafana/pkg/services/sqlstore" ) -type pluginSettingsStore interface { - GetPluginSettings(ctx context.Context, orgID int64) ([]*models.PluginSettingInfoDTO, error) -} - -func ProvideService(sqlStore *sqlstore.SQLStore, bus bus.Bus, pluginStore plugins.Store, - pluginDashboardManager plugins.PluginDashboardManager, dashboardImportService dashboardimport.Service, - pluginSettingsStore *pluginsettings.ServiceImpl) *Service { - s := new(sqlStore, bus, pluginStore, pluginDashboardManager, dashboardImportService, pluginSettingsStore) +func ProvideService(bus bus.Bus, pluginStore plugins.Store, pluginDashboardManager plugins.PluginDashboardManager, + dashboardImportService dashboardimport.Service, pluginSettingsService pluginsettings.Service) *Service { + s := newService(bus, pluginStore, pluginDashboardManager, dashboardImportService, pluginSettingsService) s.updateAppDashboards() return s } -func new(pluginSettingsStore pluginSettingsStore, bus bus.Bus, pluginStore plugins.Store, - pluginDashboardManager plugins.PluginDashboardManager, dashboardImportService dashboardimport.Service, - pluginSettings pluginsettings.Service) *Service { +func newService(bus bus.Bus, pluginStore plugins.Store, pluginDashboardManager plugins.PluginDashboardManager, + dashboardImportService dashboardimport.Service, pluginSettingsService pluginsettings.Service) *Service { s := &Service{ - pluginSettingsStore: pluginSettingsStore, bus: bus, pluginStore: pluginStore, pluginDashboardManager: pluginDashboardManager, dashboardImportService: dashboardImportService, + pluginSettingsService: pluginSettingsService, logger: log.New("plugindashboards"), - pluginSettings: pluginSettings, } bus.AddEventListener(s.handlePluginStateChanged) @@ -43,19 +35,18 @@ func new(pluginSettingsStore pluginSettingsStore, bus bus.Bus, pluginStore plugi } type Service struct { - pluginSettingsStore pluginSettingsStore bus bus.Bus pluginStore plugins.Store pluginDashboardManager plugins.PluginDashboardManager dashboardImportService dashboardimport.Service + pluginSettingsService pluginsettings.Service logger log.Logger - pluginSettings pluginsettings.Service } func (s *Service) updateAppDashboards() { s.logger.Debug("Looking for app dashboard updates") - pluginSettings, err := s.pluginSettingsStore.GetPluginSettings(context.Background(), 0) + pluginSettings, err := s.pluginSettingsService.GetPluginSettings(context.Background(), 0) if err != nil { s.logger.Error("Failed to get all plugin settings", "error", err) return @@ -111,7 +102,7 @@ func (s *Service) syncPluginDashboards(ctx context.Context, plugin plugins.Plugi // update version in plugin_setting table to mark that we have processed the update query := models.GetPluginSettingByIdQuery{PluginId: plugin.ID, OrgId: orgID} - if err := s.pluginSettings.GetPluginSettingById(ctx, &query); err != nil { + if err := s.pluginSettingsService.GetPluginSettingById(ctx, &query); err != nil { s.logger.Error("Failed to read plugin setting by ID", "error", err) return } @@ -123,7 +114,7 @@ func (s *Service) syncPluginDashboards(ctx context.Context, plugin plugins.Plugi PluginVersion: plugin.Info.Version, } - if err := s.pluginSettings.UpdatePluginSettingVersion(ctx, &cmd); err != nil { + if err := s.pluginSettingsService.UpdatePluginSettingVersion(ctx, &cmd); err != nil { s.logger.Error("Failed to update plugin setting version", "error", err) } } diff --git a/pkg/services/plugindashboards/plugindashboards_test.go b/pkg/services/plugindashboards/plugindashboards_test.go index 4ba48d18f2a..76fc9eed2e3 100644 --- a/pkg/services/plugindashboards/plugindashboards_test.go +++ b/pkg/services/plugindashboards/plugindashboards_test.go @@ -9,6 +9,7 @@ import ( "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/services/dashboardimport" + "github.com/grafana/grafana/pkg/services/pluginsettings/service" "github.com/stretchr/testify/require" ) @@ -18,8 +19,8 @@ func TestService(t *testing.T) { scenarioInput{}, func(ctx *scenarioContext) { ctx.s.updateAppDashboards() - require.Len(t, ctx.getPluginSettingsArgs, 1) - require.Equal(t, int64(0), ctx.getPluginSettingsArgs[0]) + require.Len(t, ctx.pluginSettingsService.getPluginSettingsArgs, 1) + require.Equal(t, int64(0), ctx.pluginSettingsService.getPluginSettingsArgs[0]) require.Empty(t, ctx.deleteDashboardArgs) require.Empty(t, ctx.importDashboardArgs) }) @@ -41,7 +42,7 @@ func TestService(t *testing.T) { }, func(ctx *scenarioContext) { ctx.s.updateAppDashboards() - require.NotEmpty(t, ctx.getPluginSettingsArgs) + require.NotEmpty(t, ctx.pluginSettingsService.getPluginSettingsArgs) require.Empty(t, ctx.deleteDashboardArgs) require.Empty(t, ctx.importDashboardArgs) }) @@ -63,7 +64,7 @@ func TestService(t *testing.T) { }, func(ctx *scenarioContext) { ctx.s.updateAppDashboards() - require.NotEmpty(t, ctx.getPluginSettingsArgs) + require.NotEmpty(t, ctx.pluginSettingsService.getPluginSettingsArgs) require.Empty(t, ctx.deleteDashboardArgs) require.Empty(t, ctx.importDashboardArgs) }) @@ -95,7 +96,7 @@ func TestService(t *testing.T) { }, func(ctx *scenarioContext) { ctx.s.updateAppDashboards() - require.NotEmpty(t, ctx.getPluginSettingsArgs) + require.NotEmpty(t, ctx.pluginSettingsService.getPluginSettingsArgs) require.Empty(t, ctx.deleteDashboardArgs) require.Empty(t, ctx.importDashboardArgs) }) @@ -130,7 +131,7 @@ func TestService(t *testing.T) { }, func(ctx *scenarioContext) { ctx.s.updateAppDashboards() - require.NotEmpty(t, ctx.getPluginSettingsArgs) + require.NotEmpty(t, ctx.pluginSettingsService.getPluginSettingsArgs) require.Empty(t, ctx.deleteDashboardArgs) require.Empty(t, ctx.importDashboardArgs) }) @@ -178,7 +179,7 @@ func TestService(t *testing.T) { }, func(ctx *scenarioContext) { ctx.s.updateAppDashboards() - require.NotEmpty(t, ctx.getPluginSettingsArgs) + require.NotEmpty(t, ctx.pluginSettingsService.getPluginSettingsArgs) require.Len(t, ctx.deleteDashboardArgs, 1) require.Equal(t, int64(2), ctx.deleteDashboardArgs[0].OrgId) require.Equal(t, int64(3), ctx.deleteDashboardArgs[0].Id) @@ -334,18 +335,6 @@ func TestService(t *testing.T) { }) } -type pluginSettingsStoreMock struct { - getPluginSettingsFunc func(ctx context.Context, orgID int64) ([]*models.PluginSettingInfoDTO, error) -} - -func (m *pluginSettingsStoreMock) GetPluginSettings(ctx context.Context, orgID int64) ([]*models.PluginSettingInfoDTO, error) { - if m.getPluginSettingsFunc != nil { - return m.getPluginSettingsFunc(ctx, orgID) - } - - return nil, nil -} - type pluginStoreMock struct { plugins.Store pluginFunc func(ctx context.Context, pluginID string) (plugins.PluginDTO, bool) @@ -394,6 +383,41 @@ func (m *importDashboardServiceMock) ImportDashboard(ctx context.Context, req *d return nil, nil } +type pluginsSettingsServiceMock struct { + service.Service + + storedPluginSettings []*models.PluginSettingInfoDTO + getPluginSettingsArgs []int64 + err error +} + +func (s *pluginsSettingsServiceMock) GetPluginSettings(_ context.Context, orgID int64) ([]*models.PluginSettingInfoDTO, error) { + s.getPluginSettingsArgs = append(s.getPluginSettingsArgs, orgID) + return s.storedPluginSettings, s.err +} + +func (s *pluginsSettingsServiceMock) GetPluginSettingById(_ context.Context, query *models.GetPluginSettingByIdQuery) error { + for _, setting := range s.storedPluginSettings { + if setting.PluginId == query.PluginId { + query.Result = &models.PluginSetting{ + PluginId: query.PluginId, + OrgId: query.OrgId, + } + break + } + } + + return s.err +} + +func (s *pluginsSettingsServiceMock) UpdatePluginSettingVersion(_ context.Context, _ *models.UpdatePluginSettingVersionCmd) error { + return s.err +} + +func (s *pluginsSettingsServiceMock) UpdatePluginSetting(_ context.Context, _ *models.UpdatePluginSettingCmd) error { + return s.err +} + type scenarioInput struct { storedPluginSettings []*models.PluginSettingInfoDTO installedPlugins []plugins.PluginDTO @@ -403,8 +427,7 @@ type scenarioInput struct { type scenarioContext struct { t *testing.T bus bus.Bus - pluginSettingsStore pluginSettingsStore - getPluginSettingsArgs []int64 + pluginSettingsService *pluginsSettingsServiceMock pluginStore plugins.Store pluginDashboardManager plugins.PluginDashboardManager importDashboardService dashboardimport.Service @@ -422,7 +445,6 @@ func scenario(t *testing.T, desc string, input scenarioInput, f func(ctx *scenar sCtx := &scenarioContext{ t: t, bus: bus.New(), - getPluginSettingsArgs: []int64{}, importDashboardArgs: []*dashboardimport.ImportDashboardRequest{}, deleteDashboardArgs: []*models.DeleteDashboardCommand{}, getPluginSettingsByIdArgs: []*models.GetPluginSettingByIdQuery{}, @@ -430,15 +452,6 @@ func scenario(t *testing.T, desc string, input scenarioInput, f func(ctx *scenar getDashboardsByPluginIdQueryArgs: []*models.GetDashboardsByPluginIdQuery{}, } - getPluginSettings := func(_ context.Context, orgID int64) ([]*models.PluginSettingInfoDTO, error) { - sCtx.getPluginSettingsArgs = append(sCtx.getPluginSettingsArgs, orgID) - return input.storedPluginSettings, nil - } - - sCtx.pluginSettingsStore = &pluginSettingsStoreMock{ - getPluginSettingsFunc: getPluginSettings, - } - getPlugin := func(ctx context.Context, pluginID string) (plugins.PluginDTO, bool) { for _, p := range input.installedPlugins { if p.ID == pluginID { @@ -449,6 +462,10 @@ func scenario(t *testing.T, desc string, input scenarioInput, f func(ctx *scenar return plugins.PluginDTO{}, false } + sCtx.pluginSettingsService = &pluginsSettingsServiceMock{ + storedPluginSettings: input.storedPluginSettings, + } + sCtx.pluginStore = &pluginStoreMock{ pluginFunc: getPlugin, } @@ -498,14 +515,6 @@ func scenario(t *testing.T, desc string, input scenarioInput, f func(ctx *scenar return nil }) - mock := &mockPluginsSettingsService{} - for _, p := range input.storedPluginSettings { - mock.pluginSetting = &models.PluginSetting{ - PluginId: p.PluginId, - OrgId: p.OrgId, - } - } - sCtx.bus.AddHandler(func(ctx context.Context, query *models.GetDashboardsByPluginIdQuery) error { sCtx.getDashboardsByPluginIdQueryArgs = append(sCtx.getDashboardsByPluginIdQueryArgs, query) dashboards := []*models.Dashboard{} @@ -536,7 +545,7 @@ func scenario(t *testing.T, desc string, input scenarioInput, f func(ctx *scenar return nil }) - sCtx.s = new(sCtx.pluginSettingsStore, sCtx.bus, sCtx.pluginStore, sCtx.pluginDashboardManager, sCtx.importDashboardService, mock) + sCtx.s = newService(sCtx.bus, sCtx.pluginStore, sCtx.pluginDashboardManager, sCtx.importDashboardService, sCtx.pluginSettingsService) t.Cleanup(bus.ClearBusHandlers) @@ -544,21 +553,3 @@ func scenario(t *testing.T, desc string, input scenarioInput, f func(ctx *scenar f(sCtx) }) } - -type mockPluginsSettingsService struct { - pluginSetting *models.PluginSetting - err error -} - -func (s *mockPluginsSettingsService) GetPluginSettingById(ctx context.Context, query *models.GetPluginSettingByIdQuery) error { - query.Result = s.pluginSetting - return s.err -} - -func (s *mockPluginsSettingsService) UpdatePluginSettingVersion(ctx context.Context, cmd *models.UpdatePluginSettingVersionCmd) error { - return s.err -} - -func (s *mockPluginsSettingsService) UpdatePluginSetting(ctx context.Context, cmd *models.UpdatePluginSettingCmd) error { - return s.err -} diff --git a/pkg/services/pluginsettings/ifaces.go b/pkg/services/pluginsettings/ifaces.go new file mode 100644 index 00000000000..4aa6ec0bc4e --- /dev/null +++ b/pkg/services/pluginsettings/ifaces.go @@ -0,0 +1,14 @@ +package pluginsettings + +import ( + "context" + + "github.com/grafana/grafana/pkg/models" +) + +type Service interface { + GetPluginSettings(ctx context.Context, orgID int64) ([]*models.PluginSettingInfoDTO, 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 +} diff --git a/pkg/services/pluginsettings/service.go b/pkg/services/pluginsettings/service.go deleted file mode 100644 index 032b0c99c8e..00000000000 --- a/pkg/services/pluginsettings/service.go +++ /dev/null @@ -1,96 +0,0 @@ -package pluginsettings - -import ( - "context" - "sync" - "time" - - "github.com/grafana/grafana/pkg/bus" - "github.com/grafana/grafana/pkg/infra/log" - "github.com/grafana/grafana/pkg/models" - "github.com/grafana/grafana/pkg/services/secrets" - "github.com/grafana/grafana/pkg/services/sqlstore" -) - -type ServiceImpl struct { - Bus bus.Bus - SQLStore *sqlstore.SQLStore - SecretsService secrets.Service - - logger log.Logger - pluginSettingDecryptionCache secureJSONDecryptionCache -} - -type Service interface { - GetPluginSettingById(ctx context.Context, query *models.GetPluginSettingByIdQuery) error - UpdatePluginSetting(ctx context.Context, cmd *models.UpdatePluginSettingCmd) error - UpdatePluginSettingVersion(ctx context.Context, cmd *models.UpdatePluginSettingVersionCmd) error -} - -type cachedDecryptedJSON struct { - updated time.Time - json map[string]string -} - -type secureJSONDecryptionCache struct { - cache map[int64]cachedDecryptedJSON - sync.Mutex -} - -func ProvideService(bus bus.Bus, store *sqlstore.SQLStore, secretsService secrets.Service) *ServiceImpl { - s := &ServiceImpl{ - Bus: bus, - SQLStore: store, - SecretsService: secretsService, - logger: log.New("pluginsettings"), - pluginSettingDecryptionCache: secureJSONDecryptionCache{ - cache: make(map[int64]cachedDecryptedJSON), - }, - } - - s.Bus.AddHandler(s.GetPluginSettingById) - s.Bus.AddHandler(s.UpdatePluginSetting) - s.Bus.AddHandler(s.UpdatePluginSettingVersion) - - return s -} - -func (s *ServiceImpl) GetPluginSettingById(ctx context.Context, query *models.GetPluginSettingByIdQuery) error { - return s.SQLStore.GetPluginSettingById(ctx, query) -} - -func (s *ServiceImpl) UpdatePluginSetting(ctx context.Context, cmd *models.UpdatePluginSettingCmd) error { - var err error - cmd.EncryptedSecureJsonData, err = s.SecretsService.EncryptJsonData(ctx, cmd.SecureJsonData, secrets.WithoutScope()) - if err != nil { - return err - } - - return s.SQLStore.UpdatePluginSetting(ctx, cmd) -} - -func (s *ServiceImpl) UpdatePluginSettingVersion(ctx context.Context, cmd *models.UpdatePluginSettingVersionCmd) error { - return s.SQLStore.UpdatePluginSettingVersion(ctx, cmd) -} - -func (s *ServiceImpl) DecryptedValues(ps *models.PluginSetting) map[string]string { - s.pluginSettingDecryptionCache.Lock() - defer s.pluginSettingDecryptionCache.Unlock() - - if item, present := s.pluginSettingDecryptionCache.cache[ps.Id]; present && ps.Updated.Equal(item.updated) { - return item.json - } - - 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.pluginSettingDecryptionCache.cache[ps.Id] = cachedDecryptedJSON{ - updated: ps.Updated, - json: json, - } - - return json -} diff --git a/pkg/services/pluginsettings/service/service.go b/pkg/services/pluginsettings/service/service.go new file mode 100644 index 00000000000..54b7e3bce85 --- /dev/null +++ b/pkg/services/pluginsettings/service/service.go @@ -0,0 +1,94 @@ +package service + +import ( + "context" + "sync" + "time" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/infra/log" + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/secrets" + "github.com/grafana/grafana/pkg/services/sqlstore" +) + +func ProvideService(bus bus.Bus, store *sqlstore.SQLStore, secretsService secrets.Service) *Service { + s := &Service{ + bus: bus, + sqlStore: store, + secretsService: secretsService, + logger: log.New("pluginsettings"), + pluginSettingDecryptionCache: secureJSONDecryptionCache{ + cache: make(map[int64]cachedDecryptedJSON), + }, + } + + s.bus.AddHandler(s.GetPluginSettingById) + s.bus.AddHandler(s.UpdatePluginSetting) + s.bus.AddHandler(s.UpdatePluginSettingVersion) + + return s +} + +type Service struct { + bus bus.Bus + sqlStore *sqlstore.SQLStore + secretsService secrets.Service + + logger log.Logger + pluginSettingDecryptionCache secureJSONDecryptionCache +} + +type cachedDecryptedJSON struct { + updated time.Time + json map[string]string +} + +type secureJSONDecryptionCache struct { + cache map[int64]cachedDecryptedJSON + sync.Mutex +} + +func (s *Service) GetPluginSettings(ctx context.Context, orgID int64) ([]*models.PluginSettingInfoDTO, error) { + return s.sqlStore.GetPluginSettings(ctx, orgID) +} + +func (s *Service) GetPluginSettingById(ctx context.Context, query *models.GetPluginSettingByIdQuery) error { + return s.sqlStore.GetPluginSettingById(ctx, query) +} + +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()) + if err != nil { + return err + } + + return s.sqlStore.UpdatePluginSetting(ctx, cmd) +} + +func (s *Service) UpdatePluginSettingVersion(ctx context.Context, cmd *models.UpdatePluginSettingVersionCmd) error { + return s.sqlStore.UpdatePluginSettingVersion(ctx, cmd) +} + +func (s *Service) DecryptedValues(ps *models.PluginSetting) map[string]string { + s.pluginSettingDecryptionCache.Lock() + defer s.pluginSettingDecryptionCache.Unlock() + + if item, present := s.pluginSettingDecryptionCache.cache[ps.Id]; present && ps.Updated.Equal(item.updated) { + return item.json + } + + 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.pluginSettingDecryptionCache.cache[ps.Id] = cachedDecryptedJSON{ + updated: ps.Updated, + json: json, + } + + return json +} diff --git a/pkg/services/pluginsettings/service_test.go b/pkg/services/pluginsettings/service/service_test.go similarity index 99% rename from pkg/services/pluginsettings/service_test.go rename to pkg/services/pluginsettings/service/service_test.go index bdd7bb2269c..81f87261093 100644 --- a/pkg/services/pluginsettings/service_test.go +++ b/pkg/services/pluginsettings/service/service_test.go @@ -1,4 +1,4 @@ -package pluginsettings +package service import ( "context"