2014-12-29 06:36:08 -06:00
|
|
|
package api
|
|
|
|
|
|
|
|
import (
|
2021-11-02 07:42:55 -05:00
|
|
|
"context"
|
2023-01-27 08:08:17 -06:00
|
|
|
"fmt"
|
2022-04-15 07:01:58 -05:00
|
|
|
"net/http"
|
2014-12-29 06:36:08 -06:00
|
|
|
|
2023-01-31 13:14:15 -06:00
|
|
|
"github.com/grafana/grafana/pkg/api/dtos"
|
2015-02-27 15:29:00 -06:00
|
|
|
"github.com/grafana/grafana/pkg/plugins"
|
2021-10-05 08:54:26 -05:00
|
|
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
2023-01-27 01:50:36 -06:00
|
|
|
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
2022-06-27 11:23:15 -05:00
|
|
|
"github.com/grafana/grafana/pkg/services/datasources"
|
2022-10-07 05:39:14 -05:00
|
|
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
2022-03-16 08:37:19 -05:00
|
|
|
"github.com/grafana/grafana/pkg/services/licensing"
|
2022-03-18 14:49:13 -05:00
|
|
|
"github.com/grafana/grafana/pkg/services/pluginsettings"
|
2022-08-10 14:47:03 -05:00
|
|
|
"github.com/grafana/grafana/pkg/services/secrets/kvstore"
|
2015-02-05 03:37:13 -06:00
|
|
|
"github.com/grafana/grafana/pkg/setting"
|
2021-10-05 08:54:26 -05:00
|
|
|
"github.com/grafana/grafana/pkg/tsdb/grafanads"
|
|
|
|
"github.com/grafana/grafana/pkg/util"
|
2014-12-29 06:36:08 -06:00
|
|
|
)
|
|
|
|
|
2023-01-27 01:50:36 -06:00
|
|
|
func (hs *HTTPServer) GetFrontendSettings(c *contextmodel.ReqContext) {
|
2023-01-31 13:14:15 -06:00
|
|
|
settings, err := hs.getFrontendSettings(c)
|
2022-03-18 14:49:13 -05:00
|
|
|
if err != nil {
|
|
|
|
c.JsonApiErr(400, "Failed to get frontend settings", err)
|
|
|
|
return
|
2015-08-16 13:52:30 -05:00
|
|
|
}
|
2015-02-28 02:46:37 -06:00
|
|
|
|
2022-04-15 07:01:58 -05:00
|
|
|
c.JSON(http.StatusOK, settings)
|
2020-09-07 15:10:06 -05:00
|
|
|
}
|
|
|
|
|
2023-01-31 13:14:15 -06:00
|
|
|
// getFrontendSettings returns a json object with all the settings needed for front end initialisation.
|
|
|
|
func (hs *HTTPServer) getFrontendSettings(c *contextmodel.ReqContext) (*dtos.FrontendSettingsDTO, error) {
|
2023-02-07 10:20:05 -06:00
|
|
|
availablePlugins, err := hs.availablePlugins(c.Req.Context(), c.OrgID)
|
2020-09-07 15:10:06 -05:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2021-02-25 03:00:21 -06:00
|
|
|
|
2023-02-07 10:20:05 -06:00
|
|
|
apps := make(map[string]*plugins.AppDTO, 0)
|
|
|
|
for _, ap := range availablePlugins[plugins.App] {
|
|
|
|
apps[ap.Plugin.ID] = newAppDTO(
|
|
|
|
ap.Plugin,
|
|
|
|
ap.Settings,
|
|
|
|
)
|
2020-09-07 15:10:06 -05:00
|
|
|
}
|
|
|
|
|
2023-02-07 10:20:05 -06:00
|
|
|
dataSources, err := hs.getFSDataSources(c, availablePlugins)
|
2020-09-07 15:10:06 -05:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
defaultDS := "-- Grafana --"
|
|
|
|
for n, ds := range dataSources {
|
2021-12-14 04:16:13 -06:00
|
|
|
if ds.IsDefault {
|
2020-09-07 15:10:06 -05:00
|
|
|
defaultDS = n
|
|
|
|
}
|
2014-12-29 06:36:08 -06:00
|
|
|
}
|
|
|
|
|
2021-12-14 04:16:13 -06:00
|
|
|
panels := make(map[string]plugins.PanelDTO)
|
2023-02-07 10:20:05 -06:00
|
|
|
for _, ap := range availablePlugins[plugins.Panel] {
|
|
|
|
panel := ap.Plugin
|
2021-11-01 04:53:33 -05:00
|
|
|
if panel.State == plugins.AlphaRelease && !hs.Cfg.PluginsEnableAlpha {
|
2018-10-09 10:47:43 -05:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2022-10-07 05:39:14 -05:00
|
|
|
hideFromList := panel.HideFromList
|
|
|
|
if panel.ID == "flamegraph" {
|
|
|
|
hideFromList = !hs.Features.IsEnabled(featuremgmt.FlagFlameGraph)
|
|
|
|
}
|
|
|
|
|
2021-12-14 04:16:13 -06:00
|
|
|
panels[panel.ID] = plugins.PanelDTO{
|
|
|
|
ID: panel.ID,
|
|
|
|
Name: panel.Name,
|
|
|
|
Info: panel.Info,
|
|
|
|
Module: panel.Module,
|
|
|
|
BaseURL: panel.BaseURL,
|
|
|
|
SkipDataQuery: panel.SkipDataQuery,
|
2022-10-07 05:39:14 -05:00
|
|
|
HideFromList: hideFromList,
|
2021-12-14 04:16:13 -06:00
|
|
|
ReleaseState: string(panel.State),
|
|
|
|
Signature: string(panel.Signature),
|
|
|
|
Sort: getPanelSort(panel.ID),
|
2015-11-21 06:46:18 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-17 00:39:50 -05:00
|
|
|
hideVersion := hs.Cfg.AnonymousHideVersion && !c.IsSignedIn
|
|
|
|
version := setting.BuildVersion
|
|
|
|
commit := setting.BuildCommit
|
|
|
|
buildstamp := setting.BuildStamp
|
|
|
|
|
|
|
|
if hideVersion {
|
|
|
|
version = ""
|
|
|
|
commit = ""
|
|
|
|
buildstamp = 0
|
|
|
|
}
|
|
|
|
|
2021-10-05 08:54:26 -05:00
|
|
|
hasAccess := accesscontrol.HasAccess(hs.AccessControl, c)
|
2022-09-02 07:20:10 -05:00
|
|
|
secretsManagerPluginEnabled := kvstore.EvaluateRemoteSecretsPlugin(c.Req.Context(), hs.secretsPluginManager, hs.Cfg) == nil
|
2021-10-05 08:54:26 -05:00
|
|
|
|
2023-01-31 13:14:15 -06:00
|
|
|
frontendSettings := &dtos.FrontendSettingsDTO{
|
|
|
|
DefaultDatasource: defaultDS,
|
|
|
|
Datasources: dataSources,
|
|
|
|
MinRefreshInterval: setting.MinRefreshInterval,
|
|
|
|
Panels: panels,
|
2023-02-07 10:20:05 -06:00
|
|
|
Apps: apps,
|
2023-01-31 13:14:15 -06:00
|
|
|
AppUrl: hs.Cfg.AppURL,
|
|
|
|
AppSubUrl: hs.Cfg.AppSubURL,
|
|
|
|
AllowOrgCreate: (setting.AllowUserOrgCreate && c.IsSignedIn) || c.IsGrafanaAdmin,
|
|
|
|
AuthProxyEnabled: setting.AuthProxyEnabled,
|
|
|
|
LdapEnabled: hs.Cfg.LDAPEnabled,
|
|
|
|
JwtHeaderName: hs.Cfg.JWTAuthHeaderName,
|
|
|
|
JwtUrlLogin: hs.Cfg.JWTAuthURLLogin,
|
|
|
|
AlertingErrorOrTimeout: setting.AlertingErrorOrTimeout,
|
|
|
|
AlertingNoDataOrNullValues: setting.AlertingNoDataOrNullValues,
|
|
|
|
AlertingMinInterval: setting.AlertingMinInterval,
|
|
|
|
LiveEnabled: hs.Cfg.LiveMaxConnections != 0,
|
|
|
|
AutoAssignOrg: setting.AutoAssignOrg,
|
|
|
|
VerifyEmailEnabled: setting.VerifyEmailEnabled,
|
|
|
|
SigV4AuthEnabled: setting.SigV4AuthEnabled,
|
|
|
|
AzureAuthEnabled: setting.AzureAuthEnabled,
|
|
|
|
RbacEnabled: hs.Cfg.RBACEnabled,
|
|
|
|
ExploreEnabled: setting.ExploreEnabled,
|
|
|
|
HelpEnabled: setting.HelpEnabled,
|
|
|
|
ProfileEnabled: setting.ProfileEnabled,
|
|
|
|
QueryHistoryEnabled: hs.Cfg.QueryHistoryEnabled,
|
|
|
|
GoogleAnalyticsId: setting.GoogleAnalyticsId,
|
|
|
|
GoogleAnalytics4Id: setting.GoogleAnalytics4Id,
|
|
|
|
GoogleAnalytics4SendManualPageViews: setting.GoogleAnalytics4SendManualPageViews,
|
|
|
|
RudderstackWriteKey: setting.RudderstackWriteKey,
|
|
|
|
RudderstackDataPlaneUrl: setting.RudderstackDataPlaneUrl,
|
|
|
|
RudderstackSdkUrl: setting.RudderstackSdkUrl,
|
|
|
|
RudderstackConfigUrl: setting.RudderstackConfigUrl,
|
|
|
|
FeedbackLinksEnabled: hs.Cfg.FeedbackLinksEnabled,
|
|
|
|
ApplicationInsightsConnectionString: hs.Cfg.ApplicationInsightsConnectionString,
|
|
|
|
ApplicationInsightsEndpointUrl: hs.Cfg.ApplicationInsightsEndpointUrl,
|
|
|
|
DisableLoginForm: setting.DisableLoginForm,
|
|
|
|
DisableUserSignUp: !setting.AllowUserSignUp,
|
|
|
|
LoginHint: setting.LoginHint,
|
|
|
|
PasswordHint: setting.PasswordHint,
|
|
|
|
ExternalUserMngInfo: setting.ExternalUserMngInfo,
|
|
|
|
ExternalUserMngLinkUrl: setting.ExternalUserMngLinkUrl,
|
|
|
|
ExternalUserMngLinkName: setting.ExternalUserMngLinkName,
|
|
|
|
ViewersCanEdit: setting.ViewersCanEdit,
|
|
|
|
AngularSupportEnabled: hs.Cfg.AngularSupportEnabled,
|
|
|
|
EditorsCanAdmin: hs.Cfg.EditorsCanAdmin,
|
|
|
|
DisableSanitizeHtml: hs.Cfg.DisableSanitizeHtml,
|
|
|
|
DateFormats: hs.Cfg.DateFormats,
|
|
|
|
|
|
|
|
Auth: dtos.FrontendSettingsAuthDTO{
|
2023-02-01 10:27:53 -06:00
|
|
|
OAuthSkipOrgRoleUpdateSync: hs.Cfg.OAuthSkipOrgRoleUpdateSync,
|
|
|
|
SAMLSkipOrgRoleSync: hs.Cfg.SectionWithEnvOverrides("auth.saml").Key("skip_org_role_sync").MustBool(false),
|
|
|
|
LDAPSkipOrgRoleSync: hs.Cfg.LDAPSkipOrgRoleSync,
|
|
|
|
GoogleSkipOrgRoleSync: hs.Cfg.GoogleSkipOrgRoleSync,
|
|
|
|
JWTAuthSkipOrgRoleSync: hs.Cfg.JWTAuthSkipOrgRoleSync,
|
|
|
|
GrafanaComSkipOrgRoleSync: hs.Cfg.GrafanaComSkipOrgRoleSync,
|
|
|
|
GenericOAuthSkipOrgRoleSync: hs.Cfg.GenericOAuthSkipOrgRoleSync,
|
|
|
|
AzureADSkipOrgRoleSync: hs.Cfg.AzureADSkipOrgRoleSync,
|
|
|
|
GithubSkipOrgRoleSync: hs.Cfg.GithubSkipOrgRoleSync,
|
|
|
|
GitLabSkipOrgRoleSync: hs.Cfg.GitLabSkipOrgRoleSync,
|
|
|
|
OktaSkipOrgRoleSync: hs.Cfg.OktaSkipOrgRoleSync,
|
|
|
|
DisableSyncLock: hs.Cfg.DisableSyncLock,
|
2022-09-15 11:06:09 -05:00
|
|
|
},
|
2023-01-31 13:14:15 -06:00
|
|
|
|
|
|
|
BuildInfo: dtos.FrontendSettingsBuildInfoDTO{
|
|
|
|
HideVersion: hideVersion,
|
|
|
|
Version: version,
|
|
|
|
Commit: commit,
|
|
|
|
Buildstamp: buildstamp,
|
|
|
|
Edition: hs.License.Edition(),
|
|
|
|
LatestVersion: hs.grafanaUpdateChecker.LatestVersion(),
|
|
|
|
HasUpdate: hs.grafanaUpdateChecker.UpdateAvailable(),
|
|
|
|
Env: setting.Env,
|
2019-11-01 08:56:12 -05:00
|
|
|
},
|
2023-01-31 13:14:15 -06:00
|
|
|
|
|
|
|
LicenseInfo: dtos.FrontendSettingsLicenseInfoDTO{
|
|
|
|
Expiry: hs.License.Expiry(),
|
|
|
|
StateInfo: hs.License.StateInfo(),
|
|
|
|
LicenseUrl: hs.License.LicenseURL(hasAccess(accesscontrol.ReqGrafanaAdmin, licensing.PageAccess)),
|
|
|
|
Edition: hs.License.Edition(),
|
|
|
|
EnabledFeatures: hs.License.EnabledFeatures(),
|
2015-01-05 03:46:58 -06:00
|
|
|
},
|
2023-01-31 13:14:15 -06:00
|
|
|
|
|
|
|
FeatureToggles: hs.Features.GetEnabled(c.Req.Context()),
|
|
|
|
RendererAvailable: hs.RenderService.IsAvailable(c.Req.Context()),
|
|
|
|
RendererVersion: hs.RenderService.Version(),
|
|
|
|
SecretsManagerPluginEnabled: secretsManagerPluginEnabled,
|
|
|
|
Http2Enabled: hs.Cfg.Protocol == setting.HTTP2Scheme,
|
|
|
|
Sentry: hs.Cfg.Sentry,
|
|
|
|
GrafanaJavascriptAgent: hs.Cfg.GrafanaJavascriptAgent,
|
|
|
|
PluginCatalogURL: hs.Cfg.PluginCatalogURL,
|
|
|
|
PluginAdminEnabled: hs.Cfg.PluginAdminEnabled,
|
|
|
|
PluginAdminExternalManageEnabled: hs.Cfg.PluginAdminEnabled && hs.Cfg.PluginAdminExternalManageEnabled,
|
|
|
|
PluginCatalogHiddenPlugins: hs.Cfg.PluginCatalogHiddenPlugins,
|
|
|
|
ExpressionsEnabled: hs.Cfg.ExpressionsEnabled,
|
|
|
|
AwsAllowedAuthProviders: hs.Cfg.AWSAllowedAuthProviders,
|
|
|
|
AwsAssumeRoleEnabled: hs.Cfg.AWSAssumeRoleEnabled,
|
|
|
|
SupportBundlesEnabled: isSupportBundlesEnabled(hs),
|
|
|
|
|
|
|
|
Azure: dtos.FrontendSettingsAzureDTO{
|
|
|
|
Cloud: hs.Cfg.Azure.Cloud,
|
|
|
|
ManagedIdentityEnabled: hs.Cfg.Azure.ManagedIdentityEnabled,
|
2021-05-12 09:23:37 -05:00
|
|
|
},
|
2023-01-31 13:14:15 -06:00
|
|
|
|
|
|
|
Caching: dtos.FrontendSettingsCachingDTO{
|
|
|
|
Enabled: hs.Cfg.SectionWithEnvOverrides("caching").Key("enabled").MustBool(true),
|
2021-05-26 12:27:28 -05:00
|
|
|
},
|
2023-01-31 13:14:15 -06:00
|
|
|
RecordedQueries: dtos.FrontendSettingsRecordedQueriesDTO{
|
|
|
|
Enabled: hs.Cfg.SectionWithEnvOverrides("recorded_queries").Key("enabled").MustBool(true),
|
2021-11-17 15:45:05 -06:00
|
|
|
},
|
2023-01-31 13:14:15 -06:00
|
|
|
Reporting: dtos.FrontendSettingsReportingDTO{
|
|
|
|
Enabled: hs.Cfg.SectionWithEnvOverrides("reporting").Key("enabled").MustBool(true),
|
2022-03-22 15:30:45 -05:00
|
|
|
},
|
2023-01-31 13:14:15 -06:00
|
|
|
|
|
|
|
UnifiedAlerting: dtos.FrontendSettingsUnifiedAlertingDTO{
|
|
|
|
MinInterval: hs.Cfg.UnifiedAlerting.MinInterval.String(),
|
2022-08-01 08:01:14 -05:00
|
|
|
},
|
2023-01-31 13:14:15 -06:00
|
|
|
|
|
|
|
Oauth: hs.getEnabledOAuthProviders(),
|
|
|
|
SamlEnabled: hs.samlEnabled(),
|
|
|
|
SamlName: hs.samlName(),
|
|
|
|
TokenExpirationDayLimit: hs.Cfg.SATokenExpirationDayLimit,
|
|
|
|
|
|
|
|
SnapshotEnabled: hs.Cfg.SnapshotEnabled,
|
|
|
|
}
|
|
|
|
|
|
|
|
if hs.Cfg.UnifiedAlerting.Enabled != nil {
|
|
|
|
frontendSettings.UnifiedAlertingEnabled = *hs.Cfg.UnifiedAlerting.Enabled
|
|
|
|
}
|
|
|
|
|
|
|
|
if setting.AlertingEnabled != nil {
|
|
|
|
frontendSettings.AlertingEnabled = *setting.AlertingEnabled
|
2021-07-21 15:48:20 -05:00
|
|
|
}
|
|
|
|
|
2023-01-27 08:08:17 -06:00
|
|
|
if hs.pluginsCDNService != nil && hs.pluginsCDNService.IsEnabled() {
|
|
|
|
cdnBaseURL, err := hs.pluginsCDNService.BaseURL()
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("plugins cdn base url: %w", err)
|
|
|
|
}
|
2023-01-31 13:14:15 -06:00
|
|
|
frontendSettings.PluginsCDNBaseURL = cdnBaseURL
|
2023-01-27 08:08:17 -06:00
|
|
|
}
|
|
|
|
|
2022-02-16 11:49:50 -06:00
|
|
|
if hs.ThumbService != nil {
|
2023-01-31 13:14:15 -06:00
|
|
|
frontendSettings.DashboardPreviews = hs.ThumbService.GetDashboardPreviewsSetupSettings(c)
|
2022-02-16 11:49:50 -06:00
|
|
|
}
|
|
|
|
|
2021-07-21 15:48:20 -05:00
|
|
|
if hs.Cfg.GeomapDefaultBaseLayerConfig != nil {
|
2023-01-31 13:14:15 -06:00
|
|
|
frontendSettings.GeomapDefaultBaseLayerConfig = &hs.Cfg.GeomapDefaultBaseLayerConfig
|
2021-07-21 15:48:20 -05:00
|
|
|
}
|
2023-01-31 13:14:15 -06:00
|
|
|
|
2021-07-21 15:48:20 -05:00
|
|
|
if !hs.Cfg.GeomapEnableCustomBaseLayers {
|
2023-01-31 13:14:15 -06:00
|
|
|
frontendSettings.GeomapDisableCustomBaseLayer = true
|
2014-12-29 06:36:08 -06:00
|
|
|
}
|
|
|
|
|
2023-01-31 13:14:15 -06:00
|
|
|
return frontendSettings, nil
|
2014-12-29 06:36:08 -06:00
|
|
|
}
|
2015-02-18 07:06:44 -06:00
|
|
|
|
2023-01-23 10:23:20 -06:00
|
|
|
func isSupportBundlesEnabled(hs *HTTPServer) bool {
|
2023-01-31 09:12:20 -06:00
|
|
|
return hs.Cfg.SectionWithEnvOverrides("support_bundles").Key("enabled").MustBool(true) &&
|
2023-01-23 10:23:20 -06:00
|
|
|
hs.Features.IsEnabled(featuremgmt.FlagSupportBundles)
|
|
|
|
}
|
|
|
|
|
2023-02-07 10:20:05 -06:00
|
|
|
func (hs *HTTPServer) getFSDataSources(c *contextmodel.ReqContext, availablePlugins AvailablePlugins) (map[string]plugins.DataSourceDTO, error) {
|
2022-06-27 11:23:15 -05:00
|
|
|
orgDataSources := make([]*datasources.DataSource, 0)
|
2022-08-11 06:28:55 -05:00
|
|
|
if c.OrgID != 0 {
|
2023-02-02 10:22:43 -06:00
|
|
|
query := datasources.GetDataSourcesQuery{OrgID: c.OrgID, DataSourceLimit: hs.Cfg.DataSourceLimit}
|
2022-08-10 08:04:51 -05:00
|
|
|
err := hs.DataSourcesService.GetDataSources(c.Req.Context(), &query)
|
2022-03-18 14:49:13 -05:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-10-18 14:44:33 -05:00
|
|
|
if c.IsPublicDashboardView {
|
|
|
|
// If RBAC is enabled, it will filter out all datasources for a public user, so we need to skip it
|
|
|
|
orgDataSources = query.Result
|
|
|
|
} else {
|
|
|
|
filtered, err := hs.filterDatasourcesByQueryPermission(c.Req.Context(), c.SignedInUser, query.Result)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
orgDataSources = filtered
|
2022-03-18 14:49:13 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dataSources := make(map[string]plugins.DataSourceDTO)
|
|
|
|
|
|
|
|
for _, ds := range orgDataSources {
|
2023-02-02 10:22:43 -06:00
|
|
|
url := ds.URL
|
2022-03-18 14:49:13 -05:00
|
|
|
|
2022-06-27 11:23:15 -05:00
|
|
|
if ds.Access == datasources.DS_ACCESS_PROXY {
|
2023-02-02 10:22:43 -06:00
|
|
|
url = "/api/datasources/proxy/uid/" + ds.UID
|
2022-03-18 14:49:13 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
dsDTO := plugins.DataSourceDTO{
|
2023-02-02 10:22:43 -06:00
|
|
|
ID: ds.ID,
|
|
|
|
UID: ds.UID,
|
2022-03-18 14:49:13 -05:00
|
|
|
Type: ds.Type,
|
|
|
|
Name: ds.Name,
|
|
|
|
URL: url,
|
|
|
|
IsDefault: ds.IsDefault,
|
|
|
|
Access: string(ds.Access),
|
2022-08-26 05:27:28 -05:00
|
|
|
ReadOnly: ds.ReadOnly,
|
2022-03-18 14:49:13 -05:00
|
|
|
}
|
|
|
|
|
2023-02-07 10:20:05 -06:00
|
|
|
ap, exists := availablePlugins.Get(plugins.DataSource, ds.Type)
|
2022-03-18 14:49:13 -05:00
|
|
|
if !exists {
|
|
|
|
c.Logger.Error("Could not find plugin definition for data source", "datasource_type", ds.Type)
|
|
|
|
continue
|
|
|
|
}
|
2023-02-07 10:20:05 -06:00
|
|
|
plugin := ap.Plugin
|
2022-03-18 14:49:13 -05:00
|
|
|
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()
|
|
|
|
}
|
|
|
|
|
2022-06-27 11:23:15 -05:00
|
|
|
if ds.Access == datasources.DS_ACCESS_DIRECT {
|
2022-03-18 14:49:13 -05:00
|
|
|
if ds.BasicAuth {
|
2022-04-25 11:57:45 -05:00
|
|
|
password, err := hs.DataSourcesService.DecryptedBasicAuthPassword(c.Req.Context(), ds)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-03-18 14:49:13 -05:00
|
|
|
dsDTO.BasicAuth = util.GetBasicAuthHeader(
|
|
|
|
ds.BasicAuthUser,
|
2022-04-25 11:57:45 -05:00
|
|
|
password,
|
2022-03-18 14:49:13 -05:00
|
|
|
)
|
|
|
|
}
|
|
|
|
if ds.WithCredentials {
|
|
|
|
dsDTO.WithCredentials = ds.WithCredentials
|
|
|
|
}
|
|
|
|
|
2022-06-27 11:23:15 -05:00
|
|
|
if ds.Type == datasources.DS_INFLUXDB_08 {
|
2022-04-25 11:57:45 -05:00
|
|
|
password, err := hs.DataSourcesService.DecryptedPassword(c.Req.Context(), ds)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-03-18 14:49:13 -05:00
|
|
|
dsDTO.Username = ds.User
|
2022-04-25 11:57:45 -05:00
|
|
|
dsDTO.Password = password
|
2022-03-18 14:49:13 -05:00
|
|
|
dsDTO.URL = url + "/db/" + ds.Database
|
|
|
|
}
|
|
|
|
|
2022-06-27 11:23:15 -05:00
|
|
|
if ds.Type == datasources.DS_INFLUXDB {
|
2022-04-25 11:57:45 -05:00
|
|
|
password, err := hs.DataSourcesService.DecryptedPassword(c.Req.Context(), ds)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-03-18 14:49:13 -05:00
|
|
|
dsDTO.Username = ds.User
|
2022-04-25 11:57:45 -05:00
|
|
|
dsDTO.Password = password
|
2022-03-18 14:49:13 -05:00
|
|
|
dsDTO.URL = url
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-27 11:23:15 -05:00
|
|
|
if (ds.Type == datasources.DS_INFLUXDB) || (ds.Type == datasources.DS_ES) {
|
2022-03-18 14:49:13 -05:00
|
|
|
dsDTO.Database = ds.Database
|
|
|
|
}
|
|
|
|
|
2022-06-27 11:23:15 -05:00
|
|
|
if ds.Type == datasources.DS_PROMETHEUS {
|
2022-03-18 14:49:13 -05:00
|
|
|
// add unproxied server URL for link to Prometheus web UI
|
2023-02-02 10:22:43 -06:00
|
|
|
ds.JsonData.Set("directUrl", ds.URL)
|
2022-03-18 14:49:13 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2023-02-07 10:20:05 -06:00
|
|
|
func newAppDTO(plugin plugins.PluginDTO, settings pluginsettings.InfoDTO) *plugins.AppDTO {
|
|
|
|
app := &plugins.AppDTO{
|
|
|
|
ID: plugin.ID,
|
|
|
|
Version: plugin.Info.Version,
|
|
|
|
Path: plugin.Module,
|
|
|
|
Preload: plugin.Preload,
|
|
|
|
}
|
|
|
|
|
|
|
|
if settings.Enabled {
|
|
|
|
app.Extensions = plugin.Extensions
|
|
|
|
}
|
|
|
|
|
|
|
|
return app
|
|
|
|
}
|
|
|
|
|
2016-10-26 10:42:39 -05:00
|
|
|
func getPanelSort(id string) int {
|
|
|
|
sort := 100
|
|
|
|
switch id {
|
2021-01-10 10:41:20 -06:00
|
|
|
case "timeseries":
|
2021-05-05 06:19:14 -05:00
|
|
|
sort = 1
|
2021-05-03 09:49:09 -05:00
|
|
|
case "barchart":
|
2021-05-05 06:19:14 -05:00
|
|
|
sort = 2
|
2021-05-03 09:49:09 -05:00
|
|
|
case "stat":
|
2021-05-05 06:19:14 -05:00
|
|
|
sort = 3
|
2021-05-03 09:49:09 -05:00
|
|
|
case "gauge":
|
2021-05-05 06:19:14 -05:00
|
|
|
sort = 4
|
2021-05-03 09:49:09 -05:00
|
|
|
case "bargauge":
|
2021-05-05 06:19:14 -05:00
|
|
|
sort = 5
|
2021-05-03 09:49:09 -05:00
|
|
|
case "table":
|
2021-05-05 06:19:14 -05:00
|
|
|
sort = 6
|
2021-05-03 09:49:09 -05:00
|
|
|
case "singlestat":
|
2021-05-05 06:19:14 -05:00
|
|
|
sort = 7
|
2021-05-03 09:49:09 -05:00
|
|
|
case "piechart":
|
2021-05-05 06:19:14 -05:00
|
|
|
sort = 8
|
2021-05-17 15:00:04 -05:00
|
|
|
case "state-timeline":
|
2019-02-15 14:33:36 -06:00
|
|
|
sort = 9
|
2021-03-25 02:33:13 -05:00
|
|
|
case "heatmap":
|
2020-01-17 02:43:17 -06:00
|
|
|
sort = 10
|
2021-05-29 13:24:14 -05:00
|
|
|
case "status-history":
|
2021-01-10 10:41:20 -06:00
|
|
|
sort = 11
|
2021-05-20 10:36:20 -05:00
|
|
|
case "histogram":
|
2021-01-10 10:41:20 -06:00
|
|
|
sort = 12
|
2021-05-20 10:36:20 -05:00
|
|
|
case "graph":
|
2021-03-25 02:33:13 -05:00
|
|
|
sort = 13
|
2021-05-20 10:36:20 -05:00
|
|
|
case "text":
|
2021-05-03 09:49:09 -05:00
|
|
|
sort = 14
|
2021-05-20 10:36:20 -05:00
|
|
|
case "alertlist":
|
2021-05-05 06:19:14 -05:00
|
|
|
sort = 15
|
2021-05-20 10:36:20 -05:00
|
|
|
case "dashlist":
|
2021-05-17 15:00:04 -05:00
|
|
|
sort = 16
|
2021-05-20 10:36:20 -05:00
|
|
|
case "news":
|
|
|
|
sort = 17
|
2016-10-26 10:42:39 -05:00
|
|
|
}
|
|
|
|
return sort
|
|
|
|
}
|
|
|
|
|
2023-02-07 10:20:05 -06:00
|
|
|
type availablePluginDTO struct {
|
|
|
|
Plugin plugins.PluginDTO
|
|
|
|
Settings pluginsettings.InfoDTO
|
|
|
|
}
|
|
|
|
|
|
|
|
// AvailablePlugins represents a mapping from plugin types (panel, data source, etc.) to plugin IDs to plugins
|
2021-11-17 05:04:22 -06:00
|
|
|
// For example ["panel"] -> ["piechart"] -> {pie chart plugin DTO}
|
2023-02-07 10:20:05 -06:00
|
|
|
type AvailablePlugins map[plugins.Type]map[string]*availablePluginDTO
|
2021-11-01 04:53:33 -05:00
|
|
|
|
2023-02-07 10:20:05 -06:00
|
|
|
func (ap AvailablePlugins) Get(pluginType plugins.Type, pluginID string) (*availablePluginDTO, bool) {
|
|
|
|
if _, exists := ap[pluginType][pluginID]; exists {
|
|
|
|
return ap[pluginType][pluginID], true
|
2021-11-01 04:53:33 -05:00
|
|
|
}
|
|
|
|
|
2023-02-07 10:20:05 -06:00
|
|
|
return nil, false
|
2021-11-01 04:53:33 -05:00
|
|
|
}
|
|
|
|
|
2023-02-07 10:20:05 -06:00
|
|
|
func (hs *HTTPServer) availablePlugins(ctx context.Context, orgID int64) (AvailablePlugins, error) {
|
|
|
|
ap := make(AvailablePlugins)
|
2021-11-01 04:53:33 -05:00
|
|
|
|
2021-11-02 07:42:55 -05:00
|
|
|
pluginSettingMap, err := hs.pluginSettings(ctx, orgID)
|
2021-11-01 04:53:33 -05:00
|
|
|
if err != nil {
|
2023-02-07 10:20:05 -06:00
|
|
|
return ap, err
|
2021-11-01 04:53:33 -05:00
|
|
|
}
|
|
|
|
|
2023-02-07 10:20:05 -06:00
|
|
|
apps := make(map[string]*availablePluginDTO)
|
2021-11-17 05:04:22 -06:00
|
|
|
for _, app := range hs.pluginStore.Plugins(ctx, plugins.App) {
|
2023-02-07 10:20:05 -06:00
|
|
|
if s, exists := pluginSettingMap[app.ID]; exists {
|
|
|
|
app.Pinned = s.Pinned
|
|
|
|
apps[app.ID] = &availablePluginDTO{
|
|
|
|
Plugin: app,
|
|
|
|
Settings: *s,
|
|
|
|
}
|
2021-11-01 04:53:33 -05:00
|
|
|
}
|
|
|
|
}
|
2023-02-07 10:20:05 -06:00
|
|
|
ap[plugins.App] = apps
|
2021-11-01 04:53:33 -05:00
|
|
|
|
2023-02-07 10:20:05 -06:00
|
|
|
dataSources := make(map[string]*availablePluginDTO)
|
2021-11-17 05:04:22 -06:00
|
|
|
for _, ds := range hs.pluginStore.Plugins(ctx, plugins.DataSource) {
|
2023-02-07 10:20:05 -06:00
|
|
|
if s, exists := pluginSettingMap[ds.ID]; exists {
|
|
|
|
dataSources[ds.ID] = &availablePluginDTO{
|
|
|
|
Plugin: ds,
|
|
|
|
Settings: *s,
|
|
|
|
}
|
2021-11-01 04:53:33 -05:00
|
|
|
}
|
|
|
|
}
|
2023-02-07 10:20:05 -06:00
|
|
|
ap[plugins.DataSource] = dataSources
|
2021-11-01 04:53:33 -05:00
|
|
|
|
2023-02-07 10:20:05 -06:00
|
|
|
panels := make(map[string]*availablePluginDTO)
|
2021-11-17 05:04:22 -06:00
|
|
|
for _, p := range hs.pluginStore.Plugins(ctx, plugins.Panel) {
|
2023-02-07 10:20:05 -06:00
|
|
|
if s, exists := pluginSettingMap[p.ID]; exists {
|
|
|
|
panels[p.ID] = &availablePluginDTO{
|
|
|
|
Plugin: p,
|
|
|
|
Settings: *s,
|
|
|
|
}
|
2021-11-01 04:53:33 -05:00
|
|
|
}
|
|
|
|
}
|
2023-02-07 10:20:05 -06:00
|
|
|
ap[plugins.Panel] = panels
|
2021-11-01 04:53:33 -05:00
|
|
|
|
2023-02-07 10:20:05 -06:00
|
|
|
return ap, nil
|
2021-11-01 04:53:33 -05:00
|
|
|
}
|
|
|
|
|
2022-09-21 05:20:11 -05:00
|
|
|
func (hs *HTTPServer) pluginSettings(ctx context.Context, orgID int64) (map[string]*pluginsettings.InfoDTO, error) {
|
|
|
|
pluginSettings := make(map[string]*pluginsettings.InfoDTO)
|
2021-11-01 04:53:33 -05:00
|
|
|
|
2021-11-05 09:07:53 -05:00
|
|
|
// fill settings from database
|
2022-03-18 14:49:13 -05:00
|
|
|
if pss, err := hs.PluginSettings.GetPluginSettings(ctx, &pluginsettings.GetArgs{OrgID: orgID}); err != nil {
|
2021-11-05 09:07:53 -05:00
|
|
|
return nil, err
|
|
|
|
} else {
|
|
|
|
for _, ps := range pss {
|
2022-03-18 14:49:13 -05:00
|
|
|
pluginSettings[ps.PluginID] = ps
|
2021-11-05 09:07:53 -05:00
|
|
|
}
|
2021-11-01 04:53:33 -05:00
|
|
|
}
|
|
|
|
|
2021-11-05 09:07:53 -05:00
|
|
|
// fill settings from app plugins
|
2021-11-17 05:04:22 -06:00
|
|
|
for _, plugin := range hs.pluginStore.Plugins(ctx, plugins.App) {
|
2021-11-05 09:07:53 -05:00
|
|
|
// ignore settings that already exist
|
|
|
|
if _, exists := pluginSettings[plugin.ID]; exists {
|
2021-11-01 04:53:33 -05:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-11-05 09:07:53 -05:00
|
|
|
// add new setting which is enabled depending on if AutoEnabled: true
|
2022-09-21 05:20:11 -05:00
|
|
|
pluginSetting := &pluginsettings.InfoDTO{
|
|
|
|
PluginID: plugin.ID,
|
|
|
|
OrgID: orgID,
|
|
|
|
Enabled: plugin.AutoEnabled,
|
|
|
|
Pinned: plugin.AutoEnabled,
|
|
|
|
PluginVersion: plugin.Info.Version,
|
2021-11-01 04:53:33 -05:00
|
|
|
}
|
|
|
|
|
2021-11-05 09:07:53 -05:00
|
|
|
pluginSettings[plugin.ID] = pluginSetting
|
|
|
|
}
|
|
|
|
|
|
|
|
// fill settings from all remaining plugins (including potential app child plugins)
|
2021-11-17 05:04:22 -06:00
|
|
|
for _, plugin := range hs.pluginStore.Plugins(ctx) {
|
2021-11-05 09:07:53 -05:00
|
|
|
// ignore settings that already exist
|
|
|
|
if _, exists := pluginSettings[plugin.ID]; exists {
|
|
|
|
continue
|
2021-11-01 04:53:33 -05:00
|
|
|
}
|
|
|
|
|
2021-11-05 09:07:53 -05:00
|
|
|
// add new setting which is enabled by default
|
2022-09-21 05:20:11 -05:00
|
|
|
pluginSetting := &pluginsettings.InfoDTO{
|
|
|
|
PluginID: plugin.ID,
|
|
|
|
OrgID: orgID,
|
|
|
|
Enabled: true,
|
|
|
|
Pinned: false,
|
|
|
|
PluginVersion: plugin.Info.Version,
|
2021-11-05 09:07:53 -05:00
|
|
|
}
|
2021-11-01 04:53:33 -05:00
|
|
|
|
2021-11-05 09:07:53 -05:00
|
|
|
// if plugin is included in an app, check app settings
|
|
|
|
if plugin.IncludedInAppID != "" {
|
|
|
|
// app child plugins are disabled unless app is enabled
|
|
|
|
pluginSetting.Enabled = false
|
|
|
|
if p, exists := pluginSettings[plugin.IncludedInAppID]; exists {
|
|
|
|
pluginSetting.Enabled = p.Enabled
|
2021-11-01 04:53:33 -05:00
|
|
|
}
|
|
|
|
}
|
2021-11-05 09:07:53 -05:00
|
|
|
pluginSettings[plugin.ID] = pluginSetting
|
2021-11-01 04:53:33 -05:00
|
|
|
}
|
|
|
|
|
2021-11-05 09:07:53 -05:00
|
|
|
return pluginSettings, nil
|
2021-11-01 04:53:33 -05:00
|
|
|
}
|
2022-11-15 03:50:37 -06:00
|
|
|
|
|
|
|
func (hs *HTTPServer) getEnabledOAuthProviders() map[string]interface{} {
|
|
|
|
providers := make(map[string]interface{})
|
|
|
|
for key, oauth := range hs.SocialService.GetOAuthInfoProviders() {
|
|
|
|
providers[key] = map[string]string{
|
|
|
|
"name": oauth.Name,
|
|
|
|
"icon": oauth.Icon,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return providers
|
|
|
|
}
|