The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
grafana/pkg/api/index.go

188 lines
6.2 KiB

package api
import (
"fmt"
"net/http"
"strings"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/models"
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/featuremgmt"
pref "github.com/grafana/grafana/pkg/services/preference"
"github.com/grafana/grafana/pkg/setting"
)
Fix goconst issues See, $ gometalinter --vendor --disable-all --enable=goconst --disable=gotype --deadline=6m ./... build.go:113:15:warning: 2 other occurrence(s) of "linux" found in: build.go:119:15 build.go:491:34 (goconst) build.go:119:15:warning: 2 other occurrence(s) of "linux" found in: build.go:113:15 build.go:491:34 (goconst) build.go:491:34:warning: 2 other occurrence(s) of "linux" found in: build.go:113:15 build.go:119:15 (goconst) build.go:381:21:warning: 2 other occurrence(s) of "windows" found in: build.go:423:13 build.go:487:13 (goconst) build.go:423:13:warning: 2 other occurrence(s) of "windows" found in: build.go:381:21 build.go:487:13 (goconst) build.go:487:13:warning: 2 other occurrence(s) of "windows" found in: build.go:381:21 build.go:423:13 (goconst) pkg/api/dashboard.go:67:22:warning: 5 other occurrence(s) of "Anonymous" found in: pkg/api/dashboard.go:67:35 pkg/api/dashboard.go:131:10 pkg/api/dashboard.go:406:13 pkg/api/folder.go:98:22 pkg/api/folder.go:98:35 (goconst) pkg/api/dashboard.go:67:35:warning: 5 other occurrence(s) of "Anonymous" found in: pkg/api/dashboard.go:67:22 pkg/api/dashboard.go:131:10 pkg/api/dashboard.go:406:13 pkg/api/folder.go:98:22 pkg/api/folder.go:98:35 (goconst) pkg/api/dashboard.go:131:10:warning: 5 other occurrence(s) of "Anonymous" found in: pkg/api/dashboard.go:67:22 pkg/api/dashboard.go:67:35 pkg/api/dashboard.go:406:13 pkg/api/folder.go:98:22 pkg/api/folder.go:98:35 (goconst) pkg/api/dashboard.go:406:13:warning: 5 other occurrence(s) of "Anonymous" found in: pkg/api/dashboard.go:67:22 pkg/api/dashboard.go:67:35 pkg/api/dashboard.go:131:10 pkg/api/folder.go:98:22 pkg/api/folder.go:98:35 (goconst) pkg/api/folder.go:98:22:warning: 5 other occurrence(s) of "Anonymous" found in: pkg/api/dashboard.go:67:22 pkg/api/dashboard.go:67:35 pkg/api/dashboard.go:131:10 pkg/api/dashboard.go:406:13 pkg/api/folder.go:98:35 (goconst) pkg/api/folder.go:98:35:warning: 5 other occurrence(s) of "Anonymous" found in: pkg/api/dashboard.go:67:22 pkg/api/dashboard.go:67:35 pkg/api/dashboard.go:131:10 pkg/api/dashboard.go:406:13 pkg/api/folder.go:98:22 (goconst) pkg/api/index.go:63:47:warning: 2 other occurrence(s) of "light" found in: pkg/api/index.go:91:22 pkg/api/index.go:93:16 (goconst) pkg/api/index.go:91:22:warning: 2 other occurrence(s) of "light" found in: pkg/api/index.go:63:47 pkg/api/index.go:93:16 (goconst) pkg/api/index.go:93:16:warning: 2 other occurrence(s) of "light" found in: pkg/api/index.go:63:47 pkg/api/index.go:91:22 (goconst) pkg/components/null/float.go:71:25:warning: 2 other occurrence(s) of "null" found in: pkg/components/null/float.go:103:10 pkg/components/null/float.go:112:10 (goconst) pkg/components/null/float.go:103:10:warning: 2 other occurrence(s) of "null" found in: pkg/components/null/float.go:71:25 pkg/components/null/float.go:112:10 (goconst) pkg/components/null/float.go:112:10:warning: 2 other occurrence(s) of "null" found in: pkg/components/null/float.go:71:25 pkg/components/null/float.go:103:10 (goconst) pkg/services/alerting/notifiers/pagerduty.go:79:16:warning: 2 other occurrence(s) of "Triggered metrics:\n\n" found in: pkg/services/alerting/notifiers/kafka.go:64:16 pkg/services/alerting/notifiers/opsgenie.go:98:16 (goconst) pkg/services/alerting/notifiers/kafka.go:64:16:warning: 2 other occurrence(s) of "Triggered metrics:\n\n" found in: pkg/services/alerting/notifiers/pagerduty.go:79:16 pkg/services/alerting/notifiers/opsgenie.go:98:16 (goconst) pkg/services/alerting/notifiers/opsgenie.go:98:16:warning: 2 other occurrence(s) of "Triggered metrics:\n\n" found in: pkg/services/alerting/notifiers/pagerduty.go:79:16 pkg/services/alerting/notifiers/kafka.go:64:16 (goconst) pkg/social/social.go:85:11:warning: 2 other occurrence(s) of "grafana_com" found in: pkg/social/social.go:162:14 pkg/social/social.go:197:11 (goconst) pkg/social/social.go:162:14:warning: 2 other occurrence(s) of "grafana_com" found in: pkg/social/social.go:85:11 pkg/social/social.go:197:11 (goconst) pkg/social/social.go:197:11:warning: 2 other occurrence(s) of "grafana_com" found in: pkg/social/social.go:85:11 pkg/social/social.go:162:14 (goconst) pkg/tsdb/elasticsearch/time_series_query.go:92:17:warning: 3 other occurrence(s) of "count" found in: pkg/tsdb/elasticsearch/response_parser.go:152:8 pkg/tsdb/elasticsearch/response_parser.go:167:31 pkg/tsdb/elasticsearch/response_parser.go:315:9 (goconst) pkg/tsdb/elasticsearch/response_parser.go:152:8:warning: 3 other occurrence(s) of "count" found in: pkg/tsdb/elasticsearch/time_series_query.go:92:17 pkg/tsdb/elasticsearch/response_parser.go:167:31 pkg/tsdb/elasticsearch/response_parser.go:315:9 (goconst) pkg/tsdb/elasticsearch/response_parser.go:167:31:warning: 3 other occurrence(s) of "count" found in: pkg/tsdb/elasticsearch/time_series_query.go:92:17 pkg/tsdb/elasticsearch/response_parser.go:152:8 pkg/tsdb/elasticsearch/response_parser.go:315:9 (goconst) pkg/tsdb/elasticsearch/response_parser.go:315:9:warning: 3 other occurrence(s) of "count" found in: pkg/tsdb/elasticsearch/time_series_query.go:92:17 pkg/tsdb/elasticsearch/response_parser.go:152:8 pkg/tsdb/elasticsearch/response_parser.go:167:31 (goconst) pkg/tsdb/elasticsearch/time_series_query.go:78:9:warning: 2 other occurrence(s) of "date_histogram" found in: pkg/tsdb/elasticsearch/response_parser.go:84:22 pkg/tsdb/elasticsearch/response_parser.go:369:24 (goconst) pkg/tsdb/elasticsearch/response_parser.go:84:22:warning: 2 other occurrence(s) of "date_histogram" found in: pkg/tsdb/elasticsearch/time_series_query.go:78:9 pkg/tsdb/elasticsearch/response_parser.go:369:24 (goconst) pkg/tsdb/elasticsearch/response_parser.go:369:24:warning: 2 other occurrence(s) of "date_histogram" found in: pkg/tsdb/elasticsearch/time_series_query.go:78:9 pkg/tsdb/elasticsearch/response_parser.go:84:22 (goconst)
7 years ago
const (
// Themes
lightName = "light"
darkName = "dark"
)
func (hs *HTTPServer) editorInAnyFolder(c *models.ReqContext) bool {
hasEditPermissionInFoldersQuery := models.HasEditPermissionInFoldersQuery{SignedInUser: c.SignedInUser}
if err := hs.DashboardService.HasEditPermissionInFolders(c.Req.Context(), &hasEditPermissionInFoldersQuery); err != nil {
return false
}
return hasEditPermissionInFoldersQuery.Result
}
func (hs *HTTPServer) setIndexViewData(c *models.ReqContext) (*dtos.IndexViewData, error) {
Access control: Use access control for dashboard and folder (#44702) * Add actions and scopes * add resource service for dashboard and folder * Add dashboard guardian with fgac permission evaluation * Add CanDelete function to guardian interface * Add CanDelete property to folder and dashboard dto and set values * change to correct function name * Add accesscontrol to folder endpoints * add access control to dashboard endpoints * check access for nav links * Add fixed roles for dashboard and folders * use correct package * add hack to override guardian Constructor if accesscontrol is enabled * Add services * Add function to handle api backward compatability * Add permissionServices to HttpServer * Set permission when new dashboard is created * Add default permission when creating new dashboard * Set default permission when creating folder and dashboard * Add access control filter for dashboard search * Add to accept list * Add accesscontrol to dashboardimport * Disable access control in tests * Add check to see if user is allow to create a dashboard * Use SetPermissions * Use function to set several permissions at once * remove permissions for folder and dashboard on delete * update required permission * set permission for provisioning * Add CanCreate to dashboard guardian and set correct permisisons for provisioning * Dont set admin on folder / dashboard creation * Add dashboard and folder permission migrations * Add tests for CanCreate * Add roles and update descriptions * Solve uid to id for dashboard and folder permissions * Add folder and dashboard actions to permission filter * Handle viewer_can_edit flag * set folder and dashboard permissions services * Add dashboard permissions when importing a new dashboard * Set access control permissions on provisioning * Pass feature flags and only set permissions if access control is enabled * only add default permissions for folders and dashboards without folders * Batch create permissions in migrations * Remove `dashboards:edit` action * Remove unused function from interface * Update pkg/services/guardian/accesscontrol_guardian_test.go Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com> Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>
3 years ago
hasAccess := ac.HasAccess(hs.AccessControl, c)
hasEditPerm := hasAccess(hs.editorInAnyFolder, ac.EvalAny(ac.EvalPermission(dashboards.ActionDashboardsCreate), ac.EvalPermission(dashboards.ActionFoldersCreate)))
settings, err := hs.getFrontendSettingsMap(c)
if err != nil {
return nil, err
}
settings["dateFormats"] = hs.Cfg.DateFormats
prefsQuery := pref.GetPreferenceWithDefaultsQuery{UserID: c.UserID, OrgID: c.OrgID, Teams: c.Teams}
prefs, err := hs.preferenceService.GetWithDefaults(c.Req.Context(), &prefsQuery)
if err != nil {
return nil, err
}
// Set locale to the preference, otherwise fall back to the accept language header.
// In practice, because the preference has configuration-backed default, the header
// shouldn't frequently be used
acceptLangHeader := c.Req.Header.Get("Accept-Language")
locale := "en-US"
if hs.Features.IsEnabled(featuremgmt.FlagInternationalization) && prefs.JSONData.Locale != "" {
locale = prefs.JSONData.Locale
} else if len(acceptLangHeader) > 0 {
parts := strings.Split(acceptLangHeader, ",")
locale = parts[0]
}
appURL := setting.AppUrl
appSubURL := hs.Cfg.AppSubURL
// special case when doing localhost call from image renderer
if c.IsRenderCall && !hs.Cfg.ServeFromSubPath {
appURL = fmt.Sprintf("%s://localhost:%s", hs.Cfg.Protocol, hs.Cfg.HTTPPort)
appSubURL = ""
settings["appSubUrl"] = ""
}
navTree, err := hs.navTreeService.GetNavTree(c, hasEditPerm, prefs)
if err != nil {
return nil, err
}
PublicDashboards: Frontend routing for public dashboards (#48834) * add isPublic to dashboard * refactor routes to use route group and add placeholder method for sharing apii * add sharing pane and utils for public dashboard config to sharing modal * Sharing modal now persists data through the api * moves ShareDashboard endpoint to new file and starts adding tests * generates mocks. Adds tests for public dashboard feature flag * Adds ability to pass in array of features to enable for the test * test to update public flag on dashboard WIP * Adds mock for SaveDashboardSharingConfig * Fixes tests. Had to use FakeDashboardService * Adds React tests for public dashboards toggle * removes semicolons * refactors SharePublic component to use hooks * rename from `share publicly` to `public dashboard config` * checkpoint. debugging tests. need to verify name changes * checkpoint. test bugs fixed. need to finish returning proper response codes * finish renaming. fix test * Update pkg/api/api.go Co-authored-by: Torkel Ödegaard <torkel@grafana.com> * update backend url * rename internal objects and commands. fix configuration modal labels * add endpoint for retrieving public dashboard configuration and populate the frontend state from it * add test for dashboardCanBePublic * adds backend routes * copy DashboardPage component into component for public dashboards. WIP * adds react routes, and doesnt render main nav bar when viewing a public route * removes extra react route from testing * updates component name * Wrap the original dashboard component so we can pass props relevant to public dashboards, turn kiosk mode on/off, etc * Wraps DashboardPage in PublicDashboardPage component. DashboardPage gets rendered in kiosk mode when public prop is passed. * removes commented out code from exploratory work * Makes public dashboard routes require no auth * extracts helper to own util file to check if were viewing a public page * Hides panel dropdown when its being viewed publicly * formatting * use function from utils file for determining if publicly viewed. If public, hides app notifications, searchwrapper, and commandpalette. * adds unit tests for util function used to see if page is being viewed publicly * cant added annotations to panel when being publicly viewed * removes useless comment * hides backend and frontend pubdash routes behind feature flag * consider feature flag when checking url path to see if on public dashboard * renames function * still render app notifications when in public view * Extract pubdash route logic into own file * fixes failing tests * Determines path using location locationUtils. This covers the case when grafana is being hosted on a subpath. Updates tests. * renames pubdash web route to be more understandable * rename route * fixes failing test * fixes failing test. Needed to update pubdash urls * sets flag on grafana boot config for if viewing public dashboard. Removes hacky check that looks at the url * fixes failing tests. Uses config to determine if viewing public dashboard * renders the blue panel timeInfo on public dashboard panel * Extracts conditional logic for rendering components out into their own functions * removes publicDashboardView check, and uses dashboard meta instead * the timeInfo is always displayed on the panel * After fetch of public dashboard dto, the meta isPublic flag gets set and used to determine if viewing public dashboard for child components. Fixes tests for PanelHeader. * Fixes failing test. Needed to add isPublic flag to dashboard meta. Co-authored-by: Jeff Levin <jeff@levinology.com> Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
3 years ago
if c.IsPublicDashboardView {
settings["isPublicDashboardView"] = true
}
weekStart := ""
if prefs.WeekStart != nil {
weekStart = *prefs.WeekStart
}
data := dtos.IndexViewData{
User: &dtos.CurrentUser{
Id: c.UserID,
IsSignedIn: c.IsSignedIn,
Login: c.Login,
Email: c.Email,
ExternalUserId: c.SignedInUser.ExternalAuthID,
Name: c.Name,
OrgCount: c.OrgCount,
OrgId: c.OrgID,
OrgName: c.OrgName,
OrgRole: c.OrgRole,
GravatarUrl: dtos.GetGravatarUrl(c.Email),
IsGrafanaAdmin: c.IsGrafanaAdmin,
LightTheme: prefs.Theme == lightName,
Timezone: prefs.Timezone,
WeekStart: weekStart,
Locale: locale,
HelpFlags1: c.HelpFlags1,
HasEditPermissionInFolders: hasEditPerm,
},
Settings: settings,
Theme: prefs.Theme,
AppUrl: appURL,
AppSubUrl: appSubURL,
GoogleAnalyticsId: setting.GoogleAnalyticsId,
GoogleAnalytics4Id: setting.GoogleAnalytics4Id,
GoogleAnalytics4SendManualPageViews: setting.GoogleAnalytics4SendManualPageViews,
GoogleTagManagerId: setting.GoogleTagManagerId,
BuildVersion: setting.BuildVersion,
BuildCommit: setting.BuildCommit,
NewGrafanaVersion: hs.grafanaUpdateChecker.LatestVersion(),
NewGrafanaVersionExists: hs.grafanaUpdateChecker.UpdateAvailable(),
AppName: setting.ApplicationName,
AppNameBodyClass: "app-grafana",
FavIcon: "public/img/fav32.png",
AppleTouchIcon: "public/img/apple-touch-icon.png",
AppTitle: "Grafana",
NavTree: navTree,
Sentry: &hs.Cfg.Sentry,
Nonce: c.RequestNonce,
ContentDeliveryURL: hs.Cfg.GetContentDeliveryURL(hs.License.ContentDeliveryPrefix()),
LoadingLogo: "public/img/grafana_icon.svg",
}
if !hs.AccessControl.IsDisabled() {
userPermissions, err := hs.accesscontrolService.GetUserPermissions(c.Req.Context(), c.SignedInUser, ac.Options{ReloadCache: false})
if err != nil {
return nil, err
}
data.User.Permissions = ac.BuildPermissionsMap(userPermissions)
}
if setting.DisableGravatar {
data.User.GravatarUrl = hs.Cfg.AppSubURL + "/public/img/user_profile.png"
}
if len(data.User.Name) == 0 {
data.User.Name = data.User.Login
}
themeURLParam := c.Query("theme")
if themeURLParam == lightName {
data.User.LightTheme = true
data.Theme = lightName
} else if themeURLParam == darkName {
data.User.LightTheme = false
data.Theme = darkName
}
hs.HooksService.RunIndexDataHooks(&data, c)
// This will remove empty cfg or admin sections and move sections around if topnav is enabled
data.NavTree.RemoveEmptySectionsAndApplyNewInformationArchitecture(hs.Features.IsEnabled(featuremgmt.FlagTopnav))
data.NavTree.Sort()
return &data, nil
}
func (hs *HTTPServer) Index(c *models.ReqContext) {
data, err := hs.setIndexViewData(c)
if err != nil {
c.Handle(hs.Cfg, 500, "Failed to get settings", err)
return
}
c.HTML(http.StatusOK, "index", data)
}
func (hs *HTTPServer) NotFoundHandler(c *models.ReqContext) {
if c.IsApiRequest() {
c.JsonApiErr(404, "Not found", nil)
return
}
data, err := hs.setIndexViewData(c)
if err != nil {
c.Handle(hs.Cfg, 500, "Failed to get settings", err)
return
}
c.HTML(404, "index", data)
}