2022-09-23 04:04:48 +08:00
package navtreeimpl
import (
"sort"
"github.com/grafana/grafana/pkg/api/dtos"
2024-06-13 12:11:35 +08:00
"github.com/grafana/grafana/pkg/apimachinery/identity"
2022-09-23 04:04:48 +08:00
"github.com/grafana/grafana/pkg/infra/kvstore"
"github.com/grafana/grafana/pkg/infra/log"
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/apikey"
2024-04-10 18:42:13 +08:00
"github.com/grafana/grafana/pkg/services/authn"
2023-01-27 15:50:36 +08:00
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
2022-09-23 04:04:48 +08:00
"github.com/grafana/grafana/pkg/services/dashboards"
2023-01-06 16:11:27 +08:00
"github.com/grafana/grafana/pkg/services/datasources"
2022-09-23 04:04:48 +08:00
"github.com/grafana/grafana/pkg/services/featuremgmt"
2023-04-13 22:07:43 +08:00
"github.com/grafana/grafana/pkg/services/licensing"
2022-09-23 04:04:48 +08:00
"github.com/grafana/grafana/pkg/services/navtree"
"github.com/grafana/grafana/pkg/services/org"
2023-03-08 00:22:30 +08:00
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
2023-09-11 19:59:24 +08:00
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
2022-09-23 04:04:48 +08:00
pref "github.com/grafana/grafana/pkg/services/preference"
"github.com/grafana/grafana/pkg/services/star"
2023-01-28 04:04:04 +08:00
"github.com/grafana/grafana/pkg/services/supportbundles/supportbundlesimpl"
2022-09-23 04:04:48 +08:00
"github.com/grafana/grafana/pkg/setting"
)
type ServiceImpl struct {
cfg * setting . Cfg
log log . Logger
accessControl ac . AccessControl
2024-04-10 18:42:13 +08:00
authnService authn . Service
2023-09-11 19:59:24 +08:00
pluginStore pluginstore . Store
2022-09-23 04:04:48 +08:00
pluginSettings pluginsettings . Service
starService star . Service
2024-01-10 02:38:06 +08:00
features featuremgmt . FeatureToggles
2022-09-23 04:04:48 +08:00
dashboardService dashboards . DashboardService
accesscontrolService ac . Service
kvStore kvstore . KVStore
apiKeyService apikey . Service
2023-04-13 22:07:43 +08:00
license licensing . Licensing
2022-09-28 14:29:35 +08:00
// Navigation
navigationAppConfig map [ string ] NavigationAppConfig
navigationAppPathConfig map [ string ] NavigationAppConfig
}
type NavigationAppConfig struct {
SectionID string
SortWeight int64
2022-11-14 17:01:23 +08:00
Text string
2023-01-10 18:29:07 +08:00
Icon string
2022-09-23 04:04:48 +08:00
}
2024-04-10 18:42:13 +08:00
func ProvideService ( cfg * setting . Cfg , accessControl ac . AccessControl , pluginStore pluginstore . Store , pluginSettings pluginsettings . Service , starService star . Service ,
features featuremgmt . FeatureToggles , dashboardService dashboards . DashboardService , accesscontrolService ac . Service , kvStore kvstore . KVStore , apiKeyService apikey . Service ,
license licensing . Licensing , authnService authn . Service ) navtree . Service {
2022-09-28 14:29:35 +08:00
service := & ServiceImpl {
2022-09-23 04:04:48 +08:00
cfg : cfg ,
log : log . New ( "navtree service" ) ,
accessControl : accessControl ,
2024-04-10 18:42:13 +08:00
authnService : authnService ,
2022-09-23 04:04:48 +08:00
pluginStore : pluginStore ,
pluginSettings : pluginSettings ,
starService : starService ,
features : features ,
dashboardService : dashboardService ,
accesscontrolService : accesscontrolService ,
kvStore : kvStore ,
apiKeyService : apiKeyService ,
2023-04-13 22:07:43 +08:00
license : license ,
2022-09-23 04:04:48 +08:00
}
2022-09-28 14:29:35 +08:00
service . readNavigationSettings ( )
return service
2022-09-23 04:04:48 +08:00
}
//nolint:gocyclo
2023-05-30 21:39:09 +08:00
func ( s * ServiceImpl ) GetNavTree ( c * contextmodel . ReqContext , prefs * pref . Preference ) ( * navtree . NavTreeRoot , error ) {
2022-09-23 04:04:48 +08:00
hasAccess := ac . HasAccess ( s . accessControl , c )
2022-09-28 14:29:35 +08:00
treeRoot := & navtree . NavTreeRoot { }
2022-09-23 04:04:48 +08:00
2022-11-23 00:48:07 +08:00
treeRoot . AddSection ( s . getHomeNode ( c , prefs ) )
2022-10-03 22:05:19 +08:00
2023-05-30 21:39:09 +08:00
if hasAccess ( ac . EvalPermission ( dashboards . ActionDashboardsRead ) ) {
2022-10-03 22:05:19 +08:00
starredItemsLinks , err := s . buildStarredItemsNavLinks ( c )
2022-09-23 04:04:48 +08:00
if err != nil {
return nil , err
}
2022-09-28 14:29:35 +08:00
treeRoot . AddSection ( & navtree . NavLink {
2022-09-23 04:04:48 +08:00
Text : "Starred" ,
Id : "starred" ,
Icon : "star" ,
SortWeight : navtree . WeightSavedItems ,
Children : starredItemsLinks ,
EmptyMessageId : "starred-empty" ,
2023-02-08 23:18:13 +08:00
Url : s . cfg . AppSubURL + "/dashboards?starred" ,
2022-09-23 04:04:48 +08:00
} )
2022-10-18 17:15:52 +08:00
}
2022-09-23 04:04:48 +08:00
2023-08-26 02:56:02 +08:00
if c . IsPublicDashboardView ( ) || hasAccess ( ac . EvalAny (
2023-04-24 15:02:42 +08:00
ac . EvalPermission ( dashboards . ActionFoldersRead ) , ac . EvalPermission ( dashboards . ActionFoldersCreate ) ,
ac . EvalPermission ( dashboards . ActionDashboardsRead ) , ac . EvalPermission ( dashboards . ActionDashboardsCreate ) ) ,
) {
2023-05-30 21:39:09 +08:00
dashboardChildLinks := s . buildDashboardNavLinks ( c )
2022-09-23 04:04:48 +08:00
dashboardLink := & navtree . NavLink {
2022-10-03 17:09:32 +08:00
Text : "Dashboards" ,
Id : navtree . NavIDDashboards ,
SubTitle : "Create and manage dashboards to visualize your data" ,
Icon : "apps" ,
Url : s . cfg . AppSubURL + "/dashboards" ,
SortWeight : navtree . WeightDashboard ,
Children : dashboardChildLinks ,
2022-09-23 04:04:48 +08:00
}
2022-09-28 14:29:35 +08:00
treeRoot . AddSection ( dashboardLink )
2022-09-23 04:04:48 +08:00
}
2024-01-23 19:36:22 +08:00
if s . cfg . ExploreEnabled && hasAccess ( ac . EvalPermission ( ac . ActionDatasourcesExplore ) ) {
2024-01-17 06:05:44 +08:00
exploreChildNavLinks := s . buildExploreNavLinks ( c )
2022-09-28 14:29:35 +08:00
treeRoot . AddSection ( & navtree . NavLink {
2022-09-23 04:04:48 +08:00
Text : "Explore" ,
2023-11-30 23:18:05 +08:00
Id : navtree . NavIDExplore ,
2022-09-23 04:04:48 +08:00
SubTitle : "Explore your data" ,
Icon : "compass" ,
SortWeight : navtree . WeightExplore ,
Url : s . cfg . AppSubURL + "/explore" ,
2024-01-17 06:05:44 +08:00
Children : exploreChildNavLinks ,
2022-09-23 04:04:48 +08:00
} )
}
2024-01-23 19:36:22 +08:00
if s . cfg . ProfileEnabled && c . IsSignedIn {
2022-09-28 14:29:35 +08:00
treeRoot . AddSection ( s . getProfileNode ( c ) )
}
2022-09-23 04:04:48 +08:00
2023-10-09 16:40:19 +08:00
_ , uaIsDisabledForOrg := s . cfg . UnifiedAlerting . DisabledOrgs [ c . SignedInUser . GetOrgID ( ) ]
2022-09-23 04:04:48 +08:00
uaVisibleForOrg := s . cfg . UnifiedAlerting . IsEnabled ( ) && ! uaIsDisabledForOrg
2024-03-14 22:36:35 +08:00
if uaVisibleForOrg {
2023-05-30 21:39:09 +08:00
if alertingSection := s . buildAlertNavLinks ( c ) ; alertingSection != nil {
2022-09-28 14:29:35 +08:00
treeRoot . AddSection ( alertingSection )
}
2022-09-23 04:04:48 +08:00
}
2023-07-24 16:54:52 +08:00
if connectionsSection := s . buildDataConnectionsNavLink ( c ) ; connectionsSection != nil {
treeRoot . AddSection ( connectionsSection )
2022-09-23 04:04:48 +08:00
}
2023-04-20 18:10:12 +08:00
orgAdminNode , err := s . getAdminNode ( c )
2022-09-23 04:04:48 +08:00
2024-06-12 23:45:13 +08:00
if orgAdminNode != nil && len ( orgAdminNode . Children ) > 0 {
2022-09-28 14:29:35 +08:00
treeRoot . AddSection ( orgAdminNode )
} else if err != nil {
return nil , err
2022-09-23 04:04:48 +08:00
}
2022-09-28 14:29:35 +08:00
s . addHelpLinks ( treeRoot , c )
2022-09-23 04:04:48 +08:00
2022-09-28 14:29:35 +08:00
if err := s . addAppLinks ( treeRoot , c ) ; err != nil {
return nil , err
}
2022-09-23 04:04:48 +08:00
2024-07-24 21:10:19 +08:00
// remove user access if empty. Happens if grafana-auth-app is not injected
2024-08-21 23:40:42 +08:00
if sec := treeRoot . FindById ( navtree . NavIDCfgAccess ) ; sec != nil && len ( sec . Children ) == 0 {
2024-07-24 21:10:19 +08:00
treeRoot . RemoveSectionByID ( navtree . NavIDCfgAccess )
}
2024-07-22 18:43:40 +08:00
if s . features . IsEnabled ( c . Req . Context ( ) , featuremgmt . FlagPinNavItems ) {
treeRoot . AddSection ( & navtree . NavLink {
Text : "Bookmarks" ,
2024-07-23 19:58:50 +08:00
Id : navtree . NavIDBookmarks ,
2024-07-22 18:43:40 +08:00
Icon : "bookmark" ,
SortWeight : navtree . WeightBookmarks ,
2024-08-15 20:35:20 +08:00
Children : [ ] * navtree . NavLink { } ,
2024-07-22 18:43:40 +08:00
EmptyMessageId : "bookmarks-empty" ,
Url : s . cfg . AppSubURL + "/bookmarks" ,
} )
}
2022-09-28 14:29:35 +08:00
return treeRoot , nil
2022-09-23 04:04:48 +08:00
}
2023-01-27 15:50:36 +08:00
func ( s * ServiceImpl ) getHomeNode ( c * contextmodel . ReqContext , prefs * pref . Preference ) * navtree . NavLink {
2022-10-03 22:05:19 +08:00
homeUrl := s . cfg . AppSubURL + "/"
2023-03-10 00:42:45 +08:00
if ! c . IsSignedIn && ! s . cfg . AnonymousEnabled {
homeUrl = s . cfg . AppSubURL + "/login"
} else {
homePage := s . cfg . HomePage
2022-10-03 22:05:19 +08:00
2023-03-10 00:42:45 +08:00
if prefs . HomeDashboardID == 0 && len ( homePage ) > 0 {
homeUrl = homePage
}
2022-10-03 22:05:19 +08:00
}
2022-11-23 00:48:07 +08:00
homeNode := & navtree . NavLink {
2022-10-03 22:05:19 +08:00
Text : "Home" ,
Id : "home" ,
Url : homeUrl ,
Icon : "home-alt" ,
SortWeight : navtree . WeightHome ,
}
2024-09-26 01:20:04 +08:00
ctx := c . Req . Context ( )
if s . features . IsEnabled ( ctx , featuremgmt . FlagHomeSetupGuide ) {
var children [ ] * navtree . NavLink
// setup guide (a submenu item under Home)
children = append ( children , & navtree . NavLink {
Id : "home-setup-guide" ,
Text : "Setup guide" ,
Url : homeUrl + "/setup-guide" ,
SortWeight : navtree . WeightHome ,
} )
homeNode . Children = children
}
2022-11-23 00:48:07 +08:00
return homeNode
2022-10-03 22:05:19 +08:00
}
2023-01-28 04:04:04 +08:00
func isSupportBundlesEnabled ( s * ServiceImpl ) bool {
2023-02-10 17:12:04 +08:00
return s . cfg . SectionWithEnvOverrides ( "support_bundles" ) . Key ( "enabled" ) . MustBool ( true )
2023-01-28 04:04:04 +08:00
}
2023-01-27 15:50:36 +08:00
func ( s * ServiceImpl ) addHelpLinks ( treeRoot * navtree . NavTreeRoot , c * contextmodel . ReqContext ) {
2024-01-23 19:36:22 +08:00
if s . cfg . HelpEnabled {
2024-03-16 00:39:13 +08:00
// The version subtitle is set later by NavTree.ApplyHelpVersion
2023-01-28 04:04:04 +08:00
helpNode := & navtree . NavLink {
2022-09-23 04:04:48 +08:00
Text : "Help" ,
Id : "help" ,
Url : "#" ,
Icon : "question-circle" ,
SortWeight : navtree . WeightHelp ,
2023-01-28 04:04:04 +08:00
Children : [ ] * navtree . NavLink { } ,
}
treeRoot . AddSection ( helpNode )
hasAccess := ac . HasAccess ( s . accessControl , c )
supportBundleAccess := ac . EvalAny (
ac . EvalPermission ( supportbundlesimpl . ActionRead ) ,
ac . EvalPermission ( supportbundlesimpl . ActionCreate ) ,
)
2023-05-30 21:39:09 +08:00
if isSupportBundlesEnabled ( s ) && hasAccess ( supportBundleAccess ) {
2023-01-28 04:04:04 +08:00
supportBundleNode := & navtree . NavLink {
Text : "Support bundles" ,
Id : "support-bundles" ,
Url : "/support-bundles" ,
Icon : "wrench" ,
SortWeight : navtree . WeightHelp ,
}
helpNode . Children = append ( helpNode . Children , supportBundleNode )
}
2022-09-23 04:04:48 +08:00
}
}
2023-01-27 15:50:36 +08:00
func ( s * ServiceImpl ) getProfileNode ( c * contextmodel . ReqContext ) * navtree . NavLink {
2022-09-23 04:04:48 +08:00
// Only set login if it's different from the name
var login string
2023-11-14 22:47:34 +08:00
if c . SignedInUser . GetLogin ( ) != c . SignedInUser . GetDisplayName ( ) {
login = c . SignedInUser . GetLogin ( )
2022-09-23 04:04:48 +08:00
}
2024-01-23 19:36:22 +08:00
gravatarURL := dtos . GetGravatarUrl ( s . cfg , c . SignedInUser . GetEmail ( ) )
2022-09-23 04:04:48 +08:00
children := [ ] * navtree . NavLink {
{
2023-01-24 16:32:49 +08:00
Text : "Profile" , Id : "profile/settings" , Url : s . cfg . AppSubURL + "/profile" , Icon : "sliders-v-alt" ,
2022-09-23 04:04:48 +08:00
} ,
}
children = append ( children , & navtree . NavLink {
Text : "Notification history" , Id : "profile/notifications" , Url : s . cfg . AppSubURL + "/profile/notifications" , Icon : "bell" ,
} )
2023-02-27 22:28:49 +08:00
if s . cfg . AddChangePasswordLink ( ) {
2022-09-23 04:04:48 +08:00
children = append ( children , & navtree . NavLink {
Text : "Change password" , Id : "profile/password" , Url : s . cfg . AppSubURL + "/profile/password" ,
Icon : "lock" ,
} )
}
2024-01-23 19:36:22 +08:00
if ! s . cfg . DisableSignoutMenu {
2022-09-23 04:04:48 +08:00
// add sign out first
children = append ( children , & navtree . NavLink {
Text : "Sign out" ,
Id : "sign-out" ,
Url : s . cfg . AppSubURL + "/logout" ,
Icon : "arrow-from-right" ,
Target : "_self" ,
HideFromTabs : true ,
} )
}
return & navtree . NavLink {
2023-11-14 22:47:34 +08:00
Text : c . SignedInUser . GetDisplayName ( ) ,
2022-09-23 04:04:48 +08:00
SubTitle : login ,
Id : "profile" ,
Img : gravatarURL ,
Url : s . cfg . AppSubURL + "/profile" ,
SortWeight : navtree . WeightProfile ,
Children : children ,
RoundIcon : true ,
}
}
2023-01-27 15:50:36 +08:00
func ( s * ServiceImpl ) buildStarredItemsNavLinks ( c * contextmodel . ReqContext ) ( [ ] * navtree . NavLink , error ) {
2022-09-23 04:04:48 +08:00
starredItemsChildNavs := [ ] * navtree . NavLink { }
2024-08-09 23:20:24 +08:00
userID , _ := identity . UserIdentifier ( c . SignedInUser . GetID ( ) )
2022-09-23 04:04:48 +08:00
query := star . GetUserStarsQuery {
2023-11-14 22:47:34 +08:00
UserID : userID ,
2022-09-23 04:04:48 +08:00
}
starredDashboardResult , err := s . starService . GetByUser ( c . Req . Context ( ) , & query )
if err != nil {
return nil , err
}
2023-03-16 17:20:07 +08:00
if len ( starredDashboardResult . UserStars ) > 0 {
var ids [ ] int64
for id := range starredDashboardResult . UserStars {
ids = append ( ids , id )
2022-09-23 04:04:48 +08:00
}
2023-10-09 16:40:19 +08:00
starredDashboards , err := s . dashboardService . GetDashboards ( c . Req . Context ( ) , & dashboards . GetDashboardsQuery { DashboardIDs : ids , OrgID : c . SignedInUser . GetOrgID ( ) } )
2023-03-16 17:20:07 +08:00
if err != nil {
return nil , err
2022-09-23 04:04:48 +08:00
}
2023-03-16 17:20:07 +08:00
// Set a loose limit to the first 50 starred dashboards found
if len ( starredDashboards ) > 50 {
starredDashboards = starredDashboards [ : 50 ]
2022-09-23 04:04:48 +08:00
}
sort . Slice ( starredDashboards , func ( i , j int ) bool {
return starredDashboards [ i ] . Title < starredDashboards [ j ] . Title
} )
for _ , starredItem := range starredDashboards {
starredItemsChildNavs = append ( starredItemsChildNavs , & navtree . NavLink {
2023-01-16 23:33:55 +08:00
Id : "starred/" + starredItem . UID ,
2022-09-23 04:04:48 +08:00
Text : starredItem . Title ,
2023-01-16 23:33:55 +08:00
Url : starredItem . GetURL ( ) ,
2022-09-23 04:04:48 +08:00
} )
}
}
return starredItemsChildNavs , nil
}
2023-05-30 21:39:09 +08:00
func ( s * ServiceImpl ) buildDashboardNavLinks ( c * contextmodel . ReqContext ) [ ] * navtree . NavLink {
2022-09-23 04:04:48 +08:00
hasAccess := ac . HasAccess ( s . accessControl , c )
dashboardChildNavs := [ ] * navtree . NavLink { }
2022-09-28 14:29:35 +08:00
2022-09-23 04:04:48 +08:00
dashboardChildNavs = append ( dashboardChildNavs , & navtree . NavLink {
2022-10-03 17:09:32 +08:00
Text : "Playlists" , SubTitle : "Groups of dashboards that are displayed in a sequence" , Id : "dashboards/playlists" , Url : s . cfg . AppSubURL + "/playlists" , Icon : "presentation-play" ,
2022-09-23 04:04:48 +08:00
} )
if c . IsSignedIn {
2023-01-26 21:28:11 +08:00
if s . cfg . SnapshotEnabled {
dashboardChildNavs = append ( dashboardChildNavs , & navtree . NavLink {
Text : "Snapshots" ,
2024-07-11 18:20:04 +08:00
SubTitle : "Interactive, publicly available, point-in-time representations of dashboards" ,
2023-01-26 21:28:11 +08:00
Id : "dashboards/snapshots" ,
Url : s . cfg . AppSubURL + "/dashboard/snapshots" ,
Icon : "camera" ,
} )
}
2022-09-23 04:04:48 +08:00
dashboardChildNavs = append ( dashboardChildNavs , & navtree . NavLink {
2022-10-03 17:09:32 +08:00
Text : "Library panels" ,
SubTitle : "Reusable panels that can be added to multiple dashboards" ,
Id : "dashboards/library-panels" ,
Url : s . cfg . AppSubURL + "/library-panels" ,
Icon : "library-panel" ,
2022-09-23 04:04:48 +08:00
} )
2022-10-13 13:36:05 +08:00
2023-12-19 18:43:54 +08:00
if s . features . IsEnabled ( c . Req . Context ( ) , featuremgmt . FlagPublicDashboards ) && s . cfg . PublicDashboardsEnabled {
2022-10-13 13:36:05 +08:00
dashboardChildNavs = append ( dashboardChildNavs , & navtree . NavLink {
Text : "Public dashboards" ,
Id : "dashboards/public" ,
Url : s . cfg . AppSubURL + "/dashboard/public" ,
Icon : "library-panel" ,
} )
}
2024-05-28 16:26:06 +08:00
2024-07-11 18:20:04 +08:00
if s . features . IsEnabled ( c . Req . Context ( ) , featuremgmt . FlagDashboardRestoreUI ) && c . SignedInUser . GetOrgRole ( ) == org . RoleAdmin {
2024-05-28 16:26:06 +08:00
dashboardChildNavs = append ( dashboardChildNavs , & navtree . NavLink {
2024-07-11 18:20:04 +08:00
Text : "Recently deleted" ,
2024-06-04 15:03:33 +08:00
SubTitle : "Any items listed here for more than 30 days will be automatically deleted." ,
2024-06-18 23:24:48 +08:00
Id : "dashboards/recently-deleted" ,
Url : s . cfg . AppSubURL + "/dashboard/recently-deleted" ,
2024-05-28 16:26:06 +08:00
} )
}
2022-09-23 04:04:48 +08:00
}
2023-05-30 21:39:09 +08:00
if hasAccess ( ac . EvalPermission ( dashboards . ActionDashboardsCreate ) ) {
dashboardChildNavs = append ( dashboardChildNavs , & navtree . NavLink {
Text : "New dashboard" , Icon : "plus" , Url : s . cfg . AppSubURL + "/dashboard/new" , HideFromTabs : true , Id : "dashboards/new" , IsCreateAction : true ,
} )
2023-03-30 17:34:16 +08:00
2023-05-30 21:39:09 +08:00
dashboardChildNavs = append ( dashboardChildNavs , & navtree . NavLink {
Text : "Import dashboard" , SubTitle : "Import dashboard from file or Grafana.com" , Id : "dashboards/import" , Icon : "plus" ,
Url : s . cfg . AppSubURL + "/dashboard/import" , HideFromTabs : true , IsCreateAction : true ,
} )
2022-11-15 20:08:15 +08:00
}
2022-09-23 04:04:48 +08:00
return dashboardChildNavs
}
2023-05-30 21:39:09 +08:00
func ( s * ServiceImpl ) buildAlertNavLinks ( c * contextmodel . ReqContext ) * navtree . NavLink {
2022-09-23 04:04:48 +08:00
hasAccess := ac . HasAccess ( s . accessControl , c )
var alertChildNavs [ ] * navtree . NavLink
2023-05-30 21:39:09 +08:00
if hasAccess ( ac . EvalAny ( ac . EvalPermission ( ac . ActionAlertingRuleRead ) , ac . EvalPermission ( ac . ActionAlertingRuleExternalRead ) ) ) {
2022-09-23 04:04:48 +08:00
alertChildNavs = append ( alertChildNavs , & navtree . NavLink {
2022-10-03 17:09:32 +08:00
Text : "Alert rules" , SubTitle : "Rules that determine whether an alert will fire" , Id : "alert-list" , Url : s . cfg . AppSubURL + "/alerting/list" , Icon : "list-ul" ,
2022-09-23 04:04:48 +08:00
} )
}
2023-05-30 21:39:09 +08:00
if hasAccess ( ac . EvalAny ( ac . EvalPermission ( ac . ActionAlertingNotificationsRead ) , ac . EvalPermission ( ac . ActionAlertingNotificationsExternalRead ) ) ) {
2022-09-23 04:04:48 +08:00
alertChildNavs = append ( alertChildNavs , & navtree . NavLink {
2023-01-30 23:26:21 +08:00
Text : "Contact points" , SubTitle : "Choose how to notify your contact points when an alert instance fires" , Id : "receivers" , Url : s . cfg . AppSubURL + "/alerting/notifications" ,
2022-10-03 17:09:32 +08:00
Icon : "comment-alt-share" ,
2022-09-23 04:04:48 +08:00
} )
2022-10-03 17:09:32 +08:00
alertChildNavs = append ( alertChildNavs , & navtree . NavLink { Text : "Notification policies" , SubTitle : "Determine how alerts are routed to contact points" , Id : "am-routes" , Url : s . cfg . AppSubURL + "/alerting/routes" , Icon : "sitemap" } )
2022-09-23 04:04:48 +08:00
}
2024-06-08 00:19:28 +08:00
if hasAccess ( ac . EvalAny (
ac . EvalPermission ( ac . ActionAlertingInstanceRead ) ,
ac . EvalPermission ( ac . ActionAlertingInstancesExternalRead ) ,
ac . EvalPermission ( ac . ActionAlertingSilencesRead ) ,
) ) {
2022-10-03 17:09:32 +08:00
alertChildNavs = append ( alertChildNavs , & navtree . NavLink { Text : "Silences" , SubTitle : "Stop notifications from one or more alerting rules" , Id : "silences" , Url : s . cfg . AppSubURL + "/alerting/silences" , Icon : "bell-slash" } )
2024-06-08 00:19:28 +08:00
}
if hasAccess ( ac . EvalAny ( ac . EvalPermission ( ac . ActionAlertingInstanceRead ) , ac . EvalPermission ( ac . ActionAlertingInstancesExternalRead ) ) ) {
2024-07-11 19:33:41 +08:00
alertChildNavs = append ( alertChildNavs , & navtree . NavLink { Text : "Alert groups" , SubTitle : "See grouped alerts with active notifications" , Id : "groups" , Url : s . cfg . AppSubURL + "/alerting/groups" , Icon : "layer-group" } )
2022-09-23 04:04:48 +08:00
}
2024-06-17 20:54:15 +08:00
if s . features . IsEnabled ( c . Req . Context ( ) , featuremgmt . FlagAlertingCentralAlertHistory ) {
2024-07-11 18:09:52 +08:00
if hasAccess ( ac . EvalAny ( ac . EvalPermission ( ac . ActionAlertingRuleRead ) ) ) {
alertChildNavs = append ( alertChildNavs , & navtree . NavLink {
Text : "History" ,
SubTitle : "View a history of all alert events generated by your Grafana-managed alert rules. All alert events are displayed regardless of whether silences or mute timings are set." ,
Id : "alerts-history" ,
Url : s . cfg . AppSubURL + "/alerting/history" ,
Icon : "history" ,
} )
}
2024-06-17 20:54:15 +08:00
}
2023-11-14 22:47:34 +08:00
if c . SignedInUser . GetOrgRole ( ) == org . RoleAdmin {
2022-09-23 04:04:48 +08:00
alertChildNavs = append ( alertChildNavs , & navtree . NavLink {
2024-05-03 23:42:42 +08:00
Text : "Settings" , Id : "alerting-admin" , Url : s . cfg . AppSubURL + "/alerting/admin" ,
2022-09-23 04:04:48 +08:00
Icon : "cog" ,
} )
}
2023-05-30 21:39:09 +08:00
if hasAccess ( ac . EvalAny ( ac . EvalPermission ( ac . ActionAlertingRuleCreate ) , ac . EvalPermission ( ac . ActionAlertingRuleExternalWrite ) ) ) {
2022-09-23 04:04:48 +08:00
alertChildNavs = append ( alertChildNavs , & navtree . NavLink {
2023-01-30 23:26:21 +08:00
Text : "Create alert rule" , SubTitle : "Create an alert rule" , Id : "alert" ,
2023-04-17 23:01:32 +08:00
Icon : "plus" , Url : s . cfg . AppSubURL + "/alerting/new" , HideFromTabs : true , IsCreateAction : true ,
2022-09-23 04:04:48 +08:00
} )
}
if len ( alertChildNavs ) > 0 {
var alertNav = navtree . NavLink {
2022-10-03 17:09:32 +08:00
Text : "Alerting" ,
SubTitle : "Learn about problems in your systems moments after they occur" ,
Id : navtree . NavIDAlerting ,
Icon : "bell" ,
Children : alertChildNavs ,
SortWeight : navtree . WeightAlerting ,
2023-04-14 16:43:11 +08:00
Url : s . cfg . AppSubURL + "/alerting" ,
2022-09-23 04:04:48 +08:00
}
2022-09-28 14:29:35 +08:00
return & alertNav
2022-09-23 04:04:48 +08:00
}
2022-09-28 14:29:35 +08:00
2022-09-23 04:04:48 +08:00
return nil
}
2023-01-27 15:50:36 +08:00
func ( s * ServiceImpl ) buildDataConnectionsNavLink ( c * contextmodel . ReqContext ) * navtree . NavLink {
2023-01-06 16:11:27 +08:00
hasAccess := ac . HasAccess ( s . accessControl , c )
2022-09-23 04:04:48 +08:00
var children [ ] * navtree . NavLink
var navLink * navtree . NavLink
2022-11-10 18:14:23 +08:00
baseUrl := s . cfg . AppSubURL + "/connections"
2022-09-23 04:04:48 +08:00
2023-05-30 21:39:09 +08:00
if hasAccess ( datasources . ConfigurationPageAccess ) {
2023-05-02 16:51:59 +08:00
// Add new connection
2023-01-11 18:40:21 +08:00
children = append ( children , & navtree . NavLink {
2023-05-02 16:51:59 +08:00
Id : "connections-add-new-connection" ,
Text : "Add new connection" ,
SubTitle : "Browse and create new connections" ,
Url : baseUrl + "/add-new-connection" ,
Children : [ ] * navtree . NavLink { } ,
2024-01-15 19:30:55 +08:00
Keywords : [ ] string { "csv" , "graphite" , "json" , "loki" , "prometheus" , "sql" , "tempo" } ,
2023-01-11 18:40:21 +08:00
} )
2023-05-03 15:39:13 +08:00
// Data sources
2023-01-06 16:11:27 +08:00
children = append ( children , & navtree . NavLink {
2023-05-03 15:39:13 +08:00
Id : "connections-datasources" ,
Text : "Data sources" ,
2023-05-02 16:51:59 +08:00
SubTitle : "View and manage your connected data source connections" ,
2023-05-03 15:39:13 +08:00
Url : baseUrl + "/datasources" ,
2023-05-02 16:51:59 +08:00
Children : [ ] * navtree . NavLink { } ,
2023-01-06 16:11:27 +08:00
} )
}
2022-09-23 04:04:48 +08:00
2023-01-06 16:11:27 +08:00
if len ( children ) > 0 {
// Connections (main)
navLink = & navtree . NavLink {
Text : "Connections" ,
Icon : "adjust-circle" ,
Id : "connections" ,
Url : baseUrl ,
Children : children ,
SortWeight : navtree . WeightDataConnections ,
}
return navLink
}
return nil
2022-09-23 04:04:48 +08:00
}
2024-01-17 06:05:44 +08:00
func ( s * ServiceImpl ) buildExploreNavLinks ( c * contextmodel . ReqContext ) [ ] * navtree . NavLink {
exploreChildNavs := [ ] * navtree . NavLink { }
2024-04-10 02:15:18 +08:00
if s . features . IsEnabled ( c . Req . Context ( ) , featuremgmt . FlagExploreMetrics ) {
2024-01-17 06:05:44 +08:00
exploreChildNavs = append ( exploreChildNavs , & navtree . NavLink {
Text : "Metrics" ,
SubTitle : "Queryless exploration of your metrics" ,
Id : "explore/metrics" ,
Url : s . cfg . AppSubURL + "/explore/metrics" ,
Icon : "code-branch" ,
} )
}
return exploreChildNavs
}