mirror of
https://github.com/grafana/grafana.git
synced 2025-07-31 19:52:17 +08:00

* wip * add simple scenes object with logs panel * return hardcoded log message from runtime ds * simplify log entry * use log in links registry * wired the log together. * wip * Connected the extensions log to the runtime datasource to steam logs * wired the other registies. * implemented child function. * set right field type on labels * set meta type * using the logger in various places. * added type of onclick. * removed time picker. * removed imports. * passing log to functions where they are needed. * moved scene into admin page. * minor improvement to the message. * added possibility to update query with values based on the data. * added filter suppoert. * wip * wip * fixed so extension points are displayed. * use log level from grafana data * fixed bugs with the filtering. * Fixed some logs. * only register extensions page in development mode. * fixed filtering. * added on click debug log. * PluginExtensions: Add debug log to Grafana (Rewrite to scenes-react) (#93954) * refactoring. * simplify it even more. * Update public/app/features/plugins/extensions/logs/LogViewer.tsx Co-authored-by: Erik Sundell <erik.sundell87@gmail.com> * used VizGridLayout instead of VizGrid component. * Fixed feedback and fixed bug in filtering logic. * fixed another nit. * empty string instead of title. * Added tests and fixed error. * added test file. * regenerated yarn.lock * Update public/app/features/plugins/extensions/logs/filterTransformation.test.ts Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> * fixed nit. * more nits. * added more test cases. * simplified filtering logic. * removed unused dep. * defined broadcast channel in jest setup. * added tests for datasource. * fixed failed tests. * fixed tests. * fixing go lint issue. * silent go lint. * fixed lint issue. --------- Co-authored-by: Erik Sundell <erik.sundell87@gmail.com> Co-authored-by: Torkel Ödegaard <torkel@grafana.com> Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com>
225 lines
8.4 KiB
Go
225 lines
8.4 KiB
Go
package navtreeimpl
|
|
|
|
import (
|
|
"github.com/grafana/grafana/pkg/login/social"
|
|
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
|
"github.com/grafana/grafana/pkg/services/accesscontrol/ssoutils"
|
|
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
|
"github.com/grafana/grafana/pkg/services/correlations"
|
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
|
"github.com/grafana/grafana/pkg/services/navtree"
|
|
"github.com/grafana/grafana/pkg/services/org"
|
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginaccesscontrol"
|
|
"github.com/grafana/grafana/pkg/services/serviceaccounts"
|
|
"github.com/grafana/grafana/pkg/setting"
|
|
)
|
|
|
|
// nolint: gocyclo
|
|
func (s *ServiceImpl) getAdminNode(c *contextmodel.ReqContext) (*navtree.NavLink, error) {
|
|
var configNodes []*navtree.NavLink
|
|
ctx := c.Req.Context()
|
|
hasAccess := ac.HasAccess(s.accessControl, c)
|
|
hasGlobalAccess := ac.HasGlobalAccess(s.accessControl, s.authnService, c)
|
|
orgsAccessEvaluator := ac.EvalPermission(ac.ActionOrgsRead)
|
|
authConfigUIAvailable := s.license.FeatureEnabled(social.SAMLProviderName) || s.cfg.LDAPAuthEnabled
|
|
|
|
generalNodeLinks := []*navtree.NavLink{}
|
|
if hasAccess(ac.OrgPreferencesAccessEvaluator) {
|
|
generalNodeLinks = append(generalNodeLinks, &navtree.NavLink{
|
|
Text: "Default preferences",
|
|
Id: "org-settings",
|
|
SubTitle: "Manage preferences across an organization",
|
|
Icon: "sliders-v-alt",
|
|
Url: s.cfg.AppSubURL + "/org",
|
|
})
|
|
}
|
|
if hasAccess(ac.EvalPermission(ac.ActionSettingsRead, ac.ScopeSettingsAll)) {
|
|
generalNodeLinks = append(generalNodeLinks, &navtree.NavLink{
|
|
Text: "Settings", SubTitle: "View the settings defined in your Grafana config", Id: "server-settings", Url: s.cfg.AppSubURL + "/admin/settings", Icon: "sliders-v-alt",
|
|
})
|
|
}
|
|
if hasGlobalAccess(orgsAccessEvaluator) {
|
|
generalNodeLinks = append(generalNodeLinks, &navtree.NavLink{
|
|
Text: "Organizations", SubTitle: "Isolated instances of Grafana running on the same server", Id: "global-orgs", Url: s.cfg.AppSubURL + "/admin/orgs", Icon: "building",
|
|
})
|
|
}
|
|
if s.features.IsEnabled(ctx, featuremgmt.FlagFeatureToggleAdminPage) && hasAccess(ac.EvalPermission(ac.ActionFeatureManagementRead)) {
|
|
generalNodeLinks = append(generalNodeLinks, &navtree.NavLink{
|
|
Text: "Feature toggles",
|
|
SubTitle: "View and edit feature toggles",
|
|
Id: "feature-toggles",
|
|
Url: s.cfg.AppSubURL + "/admin/featuretoggles",
|
|
Icon: "toggle-on",
|
|
})
|
|
}
|
|
if hasAccess(ac.EvalPermission(ac.ActionSettingsRead, ac.ScopeSettingsAll)) && s.features.IsEnabled(ctx, featuremgmt.FlagStorage) {
|
|
generalNodeLinks = append(generalNodeLinks, &navtree.NavLink{
|
|
Text: "Storage",
|
|
Id: "storage",
|
|
SubTitle: "Manage file storage",
|
|
Icon: "cube",
|
|
Url: s.cfg.AppSubURL + "/admin/storage",
|
|
})
|
|
}
|
|
if s.features.IsEnabled(ctx, featuremgmt.FlagOnPremToCloudMigrations) && c.SignedInUser.HasRole(org.RoleAdmin) {
|
|
generalNodeLinks = append(generalNodeLinks, &navtree.NavLink{
|
|
Text: "Migrate to Grafana Cloud",
|
|
Id: "migrate-to-cloud",
|
|
SubTitle: "Copy configuration from your self-managed installation to a cloud stack",
|
|
Url: s.cfg.AppSubURL + "/admin/migrate-to-cloud",
|
|
})
|
|
}
|
|
|
|
generalNode := &navtree.NavLink{
|
|
Text: "General",
|
|
SubTitle: "Manage default preferences and settings across Grafana",
|
|
Id: navtree.NavIDCfgGeneral,
|
|
Url: "/admin/general",
|
|
Icon: "shield",
|
|
Children: generalNodeLinks,
|
|
}
|
|
|
|
if len(generalNode.Children) > 0 {
|
|
configNodes = append(configNodes, generalNode)
|
|
}
|
|
|
|
pluginsNodeLinks := []*navtree.NavLink{}
|
|
// FIXME: If plugin admin is disabled or externally managed, server admins still need to access the page, this is why
|
|
// while we don't have a permissions for listing plugins the legacy check has to stay as a default
|
|
if pluginaccesscontrol.ReqCanAdminPlugins(s.cfg)(c) || hasAccess(pluginaccesscontrol.AdminAccessEvaluator) {
|
|
pluginsNodeLinks = append(pluginsNodeLinks, &navtree.NavLink{
|
|
Text: "Plugins",
|
|
Id: "plugins",
|
|
SubTitle: "Extend the Grafana experience with plugins",
|
|
Icon: "plug",
|
|
Url: s.cfg.AppSubURL + "/plugins",
|
|
})
|
|
}
|
|
if s.features.IsEnabled(ctx, featuremgmt.FlagCorrelations) && hasAccess(correlations.ConfigurationPageAccess) {
|
|
pluginsNodeLinks = append(pluginsNodeLinks, &navtree.NavLink{
|
|
Text: "Correlations",
|
|
Icon: "gf-glue",
|
|
SubTitle: "Add and configure correlations",
|
|
Id: "correlations",
|
|
Url: s.cfg.AppSubURL + "/datasources/correlations",
|
|
})
|
|
}
|
|
|
|
if s.cfg.Env == setting.Dev {
|
|
pluginsNodeLinks = append(pluginsNodeLinks, &navtree.NavLink{
|
|
Text: "Extensions",
|
|
Icon: "plug",
|
|
SubTitle: "Extend the UI of plugins and Grafana",
|
|
Id: "extensions",
|
|
Url: s.cfg.AppSubURL + "/admin/extensions",
|
|
})
|
|
}
|
|
|
|
pluginsNode := &navtree.NavLink{
|
|
Text: "Plugins and data",
|
|
SubTitle: "Install plugins and define the relationships between data",
|
|
Id: navtree.NavIDCfgPlugins,
|
|
Url: "/admin/plugins",
|
|
Icon: "shield",
|
|
Children: pluginsNodeLinks,
|
|
}
|
|
|
|
if len(pluginsNode.Children) > 0 {
|
|
configNodes = append(configNodes, pluginsNode)
|
|
}
|
|
|
|
accessNodeLinks := []*navtree.NavLink{}
|
|
if hasAccess(ac.EvalAny(ac.EvalPermission(ac.ActionOrgUsersRead), ac.EvalPermission(ac.ActionUsersRead, ac.ScopeGlobalUsersAll))) {
|
|
accessNodeLinks = append(accessNodeLinks, &navtree.NavLink{
|
|
Text: "Users", SubTitle: "Manage users in Grafana", Id: "global-users", Url: s.cfg.AppSubURL + "/admin/users", Icon: "user",
|
|
})
|
|
}
|
|
if hasAccess(ac.TeamsAccessEvaluator) {
|
|
accessNodeLinks = append(accessNodeLinks, &navtree.NavLink{
|
|
Text: "Teams",
|
|
Id: "teams",
|
|
SubTitle: "Groups of users that have common dashboard and permission needs",
|
|
Icon: "users-alt",
|
|
Url: s.cfg.AppSubURL + "/org/teams",
|
|
})
|
|
}
|
|
if enableServiceAccount(s, c) {
|
|
accessNodeLinks = append(accessNodeLinks, &navtree.NavLink{
|
|
Text: "Service accounts",
|
|
Id: "serviceaccounts",
|
|
SubTitle: "Use service accounts to run automated workloads in Grafana",
|
|
Icon: "gf-service-account",
|
|
Url: s.cfg.AppSubURL + "/org/serviceaccounts",
|
|
})
|
|
}
|
|
disabled, err := s.apiKeyService.IsDisabled(ctx, c.SignedInUser.GetOrgID())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if hasAccess(ac.ApiKeyAccessEvaluator) && !disabled {
|
|
accessNodeLinks = append(accessNodeLinks, &navtree.NavLink{
|
|
Text: "API keys",
|
|
Id: "apikeys",
|
|
SubTitle: "Manage and create API keys that are used to interact with Grafana HTTP APIs",
|
|
Icon: "key-skeleton-alt",
|
|
Url: s.cfg.AppSubURL + "/org/apikeys",
|
|
})
|
|
}
|
|
|
|
if s.license.FeatureEnabled("groupsync") &&
|
|
s.features.IsEnabled(ctx, featuremgmt.FlagGroupAttributeSync) &&
|
|
hasAccess(ac.EvalAny(
|
|
ac.EvalPermission("groupsync.mappings:read"),
|
|
ac.EvalPermission("groupsync.mappings:write"),
|
|
)) {
|
|
accessNodeLinks = append(accessNodeLinks, &navtree.NavLink{
|
|
Text: "External group sync",
|
|
Id: "groupsync",
|
|
SubTitle: "Manage mappings of Identity Provider groups to Grafana Roles",
|
|
Icon: "",
|
|
Url: s.cfg.AppSubURL + "/admin/access/groupsync",
|
|
})
|
|
}
|
|
|
|
usersNode := &navtree.NavLink{
|
|
Text: "Users and access",
|
|
SubTitle: "Configure access for individual users, teams, and service accounts",
|
|
Id: navtree.NavIDCfgAccess,
|
|
Url: "/admin/access",
|
|
Icon: "shield",
|
|
Children: accessNodeLinks,
|
|
}
|
|
|
|
// Always append admin access as it's injected by grafana-auth-app.
|
|
configNodes = append(configNodes, usersNode)
|
|
|
|
if authConfigUIAvailable && hasAccess(ssoutils.EvalAuthenticationSettings(s.cfg)) ||
|
|
(hasAccess(ssoutils.OauthSettingsEvaluator(s.cfg)) && s.features.IsEnabled(ctx, featuremgmt.FlagSsoSettingsApi)) {
|
|
configNodes = append(configNodes, &navtree.NavLink{
|
|
Text: "Authentication",
|
|
Id: "authentication",
|
|
SubTitle: "Manage your auth settings and configure single sign-on",
|
|
Icon: "signin",
|
|
IsSection: true,
|
|
Url: s.cfg.AppSubURL + "/admin/authentication",
|
|
})
|
|
}
|
|
|
|
configNode := &navtree.NavLink{
|
|
Id: navtree.NavIDCfg,
|
|
Text: "Administration",
|
|
SubTitle: "Organization: " + c.SignedInUser.GetOrgName(),
|
|
Icon: "cog",
|
|
SortWeight: navtree.WeightConfig,
|
|
Children: configNodes,
|
|
Url: "/admin",
|
|
}
|
|
|
|
return configNode, nil
|
|
}
|
|
|
|
func enableServiceAccount(s *ServiceImpl, c *contextmodel.ReqContext) bool {
|
|
hasAccess := ac.HasAccess(s.accessControl, c)
|
|
return hasAccess(serviceaccounts.AccessEvaluator)
|
|
}
|