2022-09-22 15:04:48 -05:00
package navtreeimpl
import (
"fmt"
"sort"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/infra/kvstore"
"github.com/grafana/grafana/pkg/infra/log"
2023-11-14 08:47:34 -06:00
"github.com/grafana/grafana/pkg/models/roletype"
2022-09-22 15:04:48 -05:00
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/apikey"
2023-11-14 08:47:34 -06:00
"github.com/grafana/grafana/pkg/services/auth/identity"
2023-01-27 01:50:36 -06:00
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
2022-09-22 15:04:48 -05:00
"github.com/grafana/grafana/pkg/services/dashboards"
2023-01-06 02:11:27 -06:00
"github.com/grafana/grafana/pkg/services/datasources"
2022-09-22 15:04:48 -05:00
"github.com/grafana/grafana/pkg/services/featuremgmt"
2023-04-13 09:07:43 -05:00
"github.com/grafana/grafana/pkg/services/licensing"
2022-09-22 15:04:48 -05:00
"github.com/grafana/grafana/pkg/services/navtree"
"github.com/grafana/grafana/pkg/services/org"
2023-03-07 10:22:30 -06:00
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
2023-09-11 06:59:24 -05:00
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
2022-09-22 15:04:48 -05:00
pref "github.com/grafana/grafana/pkg/services/preference"
"github.com/grafana/grafana/pkg/services/star"
2023-01-27 14:04:04 -06:00
"github.com/grafana/grafana/pkg/services/supportbundles/supportbundlesimpl"
2022-09-22 15:04:48 -05:00
"github.com/grafana/grafana/pkg/setting"
)
type ServiceImpl struct {
cfg * setting . Cfg
log log . Logger
accessControl ac . AccessControl
2023-09-11 06:59:24 -05:00
pluginStore pluginstore . Store
2022-09-22 15:04:48 -05:00
pluginSettings pluginsettings . Service
starService star . Service
2024-01-09 12:38:06 -06:00
features featuremgmt . FeatureToggles
2022-09-22 15:04:48 -05:00
dashboardService dashboards . DashboardService
accesscontrolService ac . Service
kvStore kvstore . KVStore
apiKeyService apikey . Service
2023-04-13 09:07:43 -05:00
license licensing . Licensing
2022-09-28 01:29:35 -05:00
// Navigation
navigationAppConfig map [ string ] NavigationAppConfig
navigationAppPathConfig map [ string ] NavigationAppConfig
}
type NavigationAppConfig struct {
SectionID string
SortWeight int64
2022-11-14 03:01:23 -06:00
Text string
2023-01-10 04:29:07 -06:00
Icon string
2022-09-22 15:04:48 -05:00
}
2024-01-09 12:38:06 -06: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 ) navtree . Service {
2022-09-28 01:29:35 -05:00
service := & ServiceImpl {
2022-09-22 15:04:48 -05:00
cfg : cfg ,
log : log . New ( "navtree service" ) ,
accessControl : accessControl ,
pluginStore : pluginStore ,
pluginSettings : pluginSettings ,
starService : starService ,
features : features ,
dashboardService : dashboardService ,
accesscontrolService : accesscontrolService ,
kvStore : kvStore ,
apiKeyService : apiKeyService ,
2023-04-13 09:07:43 -05:00
license : license ,
2022-09-22 15:04:48 -05:00
}
2022-09-28 01:29:35 -05:00
service . readNavigationSettings ( )
return service
2022-09-22 15:04:48 -05:00
}
//nolint:gocyclo
2023-05-30 08:39:09 -05:00
func ( s * ServiceImpl ) GetNavTree ( c * contextmodel . ReqContext , prefs * pref . Preference ) ( * navtree . NavTreeRoot , error ) {
2022-09-22 15:04:48 -05:00
hasAccess := ac . HasAccess ( s . accessControl , c )
2022-09-28 01:29:35 -05:00
treeRoot := & navtree . NavTreeRoot { }
2022-09-22 15:04:48 -05:00
2022-11-22 10:48:07 -06:00
treeRoot . AddSection ( s . getHomeNode ( c , prefs ) )
2022-10-03 09:05:19 -05:00
2023-05-30 08:39:09 -05:00
if hasAccess ( ac . EvalPermission ( dashboards . ActionDashboardsRead ) ) {
2022-10-03 09:05:19 -05:00
starredItemsLinks , err := s . buildStarredItemsNavLinks ( c )
2022-09-22 15:04:48 -05:00
if err != nil {
return nil , err
}
2022-09-28 01:29:35 -05:00
treeRoot . AddSection ( & navtree . NavLink {
2022-09-22 15:04:48 -05:00
Text : "Starred" ,
Id : "starred" ,
Icon : "star" ,
SortWeight : navtree . WeightSavedItems ,
Children : starredItemsLinks ,
EmptyMessageId : "starred-empty" ,
2023-02-08 09:18:13 -06:00
Url : s . cfg . AppSubURL + "/dashboards?starred" ,
2022-09-22 15:04:48 -05:00
} )
2022-10-18 04:15:52 -05:00
}
2022-09-22 15:04:48 -05:00
2023-08-25 13:56:02 -05:00
if c . IsPublicDashboardView ( ) || hasAccess ( ac . EvalAny (
2023-04-24 02:02:42 -05:00
ac . EvalPermission ( dashboards . ActionFoldersRead ) , ac . EvalPermission ( dashboards . ActionFoldersCreate ) ,
ac . EvalPermission ( dashboards . ActionDashboardsRead ) , ac . EvalPermission ( dashboards . ActionDashboardsCreate ) ) ,
) {
2023-05-30 08:39:09 -05:00
dashboardChildLinks := s . buildDashboardNavLinks ( c )
2022-09-22 15:04:48 -05:00
dashboardLink := & navtree . NavLink {
2022-10-03 04:09:32 -05: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-22 15:04:48 -05:00
}
2022-09-28 01:29:35 -05:00
treeRoot . AddSection ( dashboardLink )
2022-09-22 15:04:48 -05:00
}
2024-01-23 05:36:22 -06:00
if s . cfg . ExploreEnabled && hasAccess ( ac . EvalPermission ( ac . ActionDatasourcesExplore ) ) {
2024-01-16 16:05:44 -06:00
exploreChildNavLinks := s . buildExploreNavLinks ( c )
2022-09-28 01:29:35 -05:00
treeRoot . AddSection ( & navtree . NavLink {
2022-09-22 15:04:48 -05:00
Text : "Explore" ,
2023-11-30 09:18:05 -06:00
Id : navtree . NavIDExplore ,
2022-09-22 15:04:48 -05:00
SubTitle : "Explore your data" ,
Icon : "compass" ,
SortWeight : navtree . WeightExplore ,
Url : s . cfg . AppSubURL + "/explore" ,
2024-01-16 16:05:44 -06:00
Children : exploreChildNavLinks ,
2022-09-22 15:04:48 -05:00
} )
}
2024-01-23 05:36:22 -06:00
if s . cfg . ProfileEnabled && c . IsSignedIn {
2022-09-28 01:29:35 -05:00
treeRoot . AddSection ( s . getProfileNode ( c ) )
}
2022-09-22 15:04:48 -05:00
2023-10-09 03:40:19 -05:00
_ , uaIsDisabledForOrg := s . cfg . UnifiedAlerting . DisabledOrgs [ c . SignedInUser . GetOrgID ( ) ]
2022-09-22 15:04:48 -05:00
uaVisibleForOrg := s . cfg . UnifiedAlerting . IsEnabled ( ) && ! uaIsDisabledForOrg
2024-01-23 05:36:22 -06:00
if s . cfg . AlertingEnabled != nil && * ( s . cfg . AlertingEnabled ) {
2022-09-28 01:29:35 -05:00
if legacyAlertSection := s . buildLegacyAlertNavLinks ( c ) ; legacyAlertSection != nil {
treeRoot . AddSection ( legacyAlertSection )
}
2024-01-05 17:19:12 -06:00
if s . features . IsEnabled ( c . Req . Context ( ) , featuremgmt . FlagAlertingPreviewUpgrade ) && ! uaIsDisabledForOrg {
if alertingSection := s . buildAlertNavLinks ( c ) ; alertingSection != nil {
treeRoot . AddSection ( alertingSection )
}
}
2022-09-22 15:04:48 -05:00
} else if uaVisibleForOrg {
2023-05-30 08:39:09 -05:00
if alertingSection := s . buildAlertNavLinks ( c ) ; alertingSection != nil {
2022-09-28 01:29:35 -05:00
treeRoot . AddSection ( alertingSection )
}
2022-09-22 15:04:48 -05:00
}
2023-07-24 03:54:52 -05:00
if connectionsSection := s . buildDataConnectionsNavLink ( c ) ; connectionsSection != nil {
treeRoot . AddSection ( connectionsSection )
2022-09-22 15:04:48 -05:00
}
2023-04-20 05:10:12 -05:00
orgAdminNode , err := s . getAdminNode ( c )
2022-09-22 15:04:48 -05:00
2022-09-28 01:29:35 -05:00
if orgAdminNode != nil {
treeRoot . AddSection ( orgAdminNode )
} else if err != nil {
return nil , err
2022-09-22 15:04:48 -05:00
}
2022-09-28 01:29:35 -05:00
s . addHelpLinks ( treeRoot , c )
2022-09-22 15:04:48 -05:00
2022-09-28 01:29:35 -05:00
if err := s . addAppLinks ( treeRoot , c ) ; err != nil {
return nil , err
}
2022-09-22 15:04:48 -05:00
2022-09-28 01:29:35 -05:00
return treeRoot , nil
2022-09-22 15:04:48 -05:00
}
2023-01-27 01:50:36 -06:00
func ( s * ServiceImpl ) getHomeNode ( c * contextmodel . ReqContext , prefs * pref . Preference ) * navtree . NavLink {
2022-10-03 09:05:19 -05:00
homeUrl := s . cfg . AppSubURL + "/"
2023-03-09 10:42:45 -06:00
if ! c . IsSignedIn && ! s . cfg . AnonymousEnabled {
homeUrl = s . cfg . AppSubURL + "/login"
} else {
homePage := s . cfg . HomePage
2022-10-03 09:05:19 -05:00
2023-03-09 10:42:45 -06:00
if prefs . HomeDashboardID == 0 && len ( homePage ) > 0 {
homeUrl = homePage
}
2022-10-03 09:05:19 -05:00
}
2022-11-22 10:48:07 -06:00
homeNode := & navtree . NavLink {
2022-10-03 09:05:19 -05:00
Text : "Home" ,
Id : "home" ,
Url : homeUrl ,
Icon : "home-alt" ,
SortWeight : navtree . WeightHome ,
}
2022-11-22 10:48:07 -06:00
return homeNode
2022-10-03 09:05:19 -05:00
}
2023-01-27 14:04:04 -06:00
func isSupportBundlesEnabled ( s * ServiceImpl ) bool {
2023-02-10 03:12:04 -06:00
return s . cfg . SectionWithEnvOverrides ( "support_bundles" ) . Key ( "enabled" ) . MustBool ( true )
2023-01-27 14:04:04 -06:00
}
2023-11-14 07:22:46 -06:00
// don't need to show the full commit hash in the UI
// let's substring to 10 chars like local git does automatically
func getShortCommitHash ( commitHash string , maxLength int ) string {
if len ( commitHash ) > maxLength {
return commitHash [ : maxLength ]
}
return commitHash
}
2023-01-27 01:50:36 -06:00
func ( s * ServiceImpl ) addHelpLinks ( treeRoot * navtree . NavTreeRoot , c * contextmodel . ReqContext ) {
2024-01-23 05:36:22 -06:00
if s . cfg . HelpEnabled {
2023-11-14 07:22:46 -06:00
helpVersion := fmt . Sprintf ( ` %s v%s (%s) ` , setting . ApplicationName , setting . BuildVersion , getShortCommitHash ( setting . BuildCommit , 10 ) )
2022-09-22 15:04:48 -05:00
if s . cfg . AnonymousHideVersion && ! c . IsSignedIn {
helpVersion = setting . ApplicationName
}
2023-01-27 14:04:04 -06:00
helpNode := & navtree . NavLink {
2022-09-22 15:04:48 -05:00
Text : "Help" ,
SubTitle : helpVersion ,
Id : "help" ,
Url : "#" ,
Icon : "question-circle" ,
SortWeight : navtree . WeightHelp ,
2023-01-27 14:04:04 -06: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 08:39:09 -05:00
if isSupportBundlesEnabled ( s ) && hasAccess ( supportBundleAccess ) {
2023-01-27 14:04:04 -06: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-22 15:04:48 -05:00
}
}
2023-01-27 01:50:36 -06:00
func ( s * ServiceImpl ) getProfileNode ( c * contextmodel . ReqContext ) * navtree . NavLink {
2022-09-22 15:04:48 -05:00
// Only set login if it's different from the name
var login string
2023-11-14 08:47:34 -06:00
if c . SignedInUser . GetLogin ( ) != c . SignedInUser . GetDisplayName ( ) {
login = c . SignedInUser . GetLogin ( )
2022-09-22 15:04:48 -05:00
}
2024-01-23 05:36:22 -06:00
gravatarURL := dtos . GetGravatarUrl ( s . cfg , c . SignedInUser . GetEmail ( ) )
2022-09-22 15:04:48 -05:00
children := [ ] * navtree . NavLink {
{
2023-01-24 02:32:49 -06:00
Text : "Profile" , Id : "profile/settings" , Url : s . cfg . AppSubURL + "/profile" , Icon : "sliders-v-alt" ,
2022-09-22 15:04:48 -05:00
} ,
}
children = append ( children , & navtree . NavLink {
Text : "Notification history" , Id : "profile/notifications" , Url : s . cfg . AppSubURL + "/profile/notifications" , Icon : "bell" ,
} )
2023-02-27 08:28:49 -06:00
if s . cfg . AddChangePasswordLink ( ) {
2022-09-22 15:04:48 -05:00
children = append ( children , & navtree . NavLink {
Text : "Change password" , Id : "profile/password" , Url : s . cfg . AppSubURL + "/profile/password" ,
Icon : "lock" ,
} )
}
2024-01-23 05:36:22 -06:00
if ! s . cfg . DisableSignoutMenu {
2022-09-22 15:04:48 -05: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 08:47:34 -06:00
Text : c . SignedInUser . GetDisplayName ( ) ,
2022-09-22 15:04:48 -05:00
SubTitle : login ,
Id : "profile" ,
Img : gravatarURL ,
Url : s . cfg . AppSubURL + "/profile" ,
SortWeight : navtree . WeightProfile ,
Children : children ,
RoundIcon : true ,
}
}
2023-01-27 01:50:36 -06:00
func ( s * ServiceImpl ) buildStarredItemsNavLinks ( c * contextmodel . ReqContext ) ( [ ] * navtree . NavLink , error ) {
2022-09-22 15:04:48 -05:00
starredItemsChildNavs := [ ] * navtree . NavLink { }
2023-11-14 08:47:34 -06:00
userID , _ := identity . UserIdentifier ( c . SignedInUser . GetNamespacedID ( ) )
2022-09-22 15:04:48 -05:00
query := star . GetUserStarsQuery {
2023-11-14 08:47:34 -06:00
UserID : userID ,
2022-09-22 15:04:48 -05:00
}
starredDashboardResult , err := s . starService . GetByUser ( c . Req . Context ( ) , & query )
if err != nil {
return nil , err
}
2023-03-16 04:20:07 -05:00
if len ( starredDashboardResult . UserStars ) > 0 {
var ids [ ] int64
for id := range starredDashboardResult . UserStars {
ids = append ( ids , id )
2022-09-22 15:04:48 -05:00
}
2023-10-09 03:40:19 -05:00
starredDashboards , err := s . dashboardService . GetDashboards ( c . Req . Context ( ) , & dashboards . GetDashboardsQuery { DashboardIDs : ids , OrgID : c . SignedInUser . GetOrgID ( ) } )
2023-03-16 04:20:07 -05:00
if err != nil {
return nil , err
2022-09-22 15:04:48 -05:00
}
2023-03-16 04:20:07 -05:00
// Set a loose limit to the first 50 starred dashboards found
if len ( starredDashboards ) > 50 {
starredDashboards = starredDashboards [ : 50 ]
2022-09-22 15:04:48 -05: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 09:33:55 -06:00
Id : "starred/" + starredItem . UID ,
2022-09-22 15:04:48 -05:00
Text : starredItem . Title ,
2023-01-16 09:33:55 -06:00
Url : starredItem . GetURL ( ) ,
2022-09-22 15:04:48 -05:00
} )
}
}
return starredItemsChildNavs , nil
}
2023-05-30 08:39:09 -05:00
func ( s * ServiceImpl ) buildDashboardNavLinks ( c * contextmodel . ReqContext ) [ ] * navtree . NavLink {
2022-09-22 15:04:48 -05:00
hasAccess := ac . HasAccess ( s . accessControl , c )
dashboardChildNavs := [ ] * navtree . NavLink { }
2022-09-28 01:29:35 -05:00
2022-09-22 15:04:48 -05:00
dashboardChildNavs = append ( dashboardChildNavs , & navtree . NavLink {
2022-10-03 04:09:32 -05: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-22 15:04:48 -05:00
} )
if c . IsSignedIn {
2023-01-26 07:28:11 -06:00
if s . cfg . SnapshotEnabled {
dashboardChildNavs = append ( dashboardChildNavs , & navtree . NavLink {
Text : "Snapshots" ,
SubTitle : "Interactive, publically available, point-in-time representations of dashboards" ,
Id : "dashboards/snapshots" ,
Url : s . cfg . AppSubURL + "/dashboard/snapshots" ,
Icon : "camera" ,
} )
}
2022-09-22 15:04:48 -05:00
dashboardChildNavs = append ( dashboardChildNavs , & navtree . NavLink {
2022-10-03 04:09:32 -05: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-22 15:04:48 -05:00
} )
2022-10-13 00:36:05 -05:00
2023-12-19 04:43:54 -06:00
if s . features . IsEnabled ( c . Req . Context ( ) , featuremgmt . FlagPublicDashboards ) && s . cfg . PublicDashboardsEnabled {
2022-10-13 00:36:05 -05:00
dashboardChildNavs = append ( dashboardChildNavs , & navtree . NavLink {
Text : "Public dashboards" ,
Id : "dashboards/public" ,
Url : s . cfg . AppSubURL + "/dashboard/public" ,
Icon : "library-panel" ,
} )
}
2022-09-22 15:04:48 -05:00
}
2023-05-30 08:39:09 -05: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 04:34:16 -05:00
2023-05-30 08:39:09 -05: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 06:08:15 -06:00
}
2022-09-22 15:04:48 -05:00
return dashboardChildNavs
}
2023-01-27 01:50:36 -06:00
func ( s * ServiceImpl ) buildLegacyAlertNavLinks ( c * contextmodel . ReqContext ) * navtree . NavLink {
2022-09-22 15:04:48 -05:00
var alertChildNavs [ ] * navtree . NavLink
alertChildNavs = append ( alertChildNavs , & navtree . NavLink {
2024-01-04 17:01:57 -06:00
Text : "Alert rules" , Id : "alert-list-legacy" , Url : s . cfg . AppSubURL + "/alerting-legacy/list" , Icon : "list-ul" ,
2022-09-22 15:04:48 -05:00
} )
2023-11-14 08:47:34 -06:00
if c . SignedInUser . HasRole ( roletype . RoleEditor ) {
2022-09-22 15:04:48 -05:00
alertChildNavs = append ( alertChildNavs , & navtree . NavLink {
2024-01-04 17:01:57 -06:00
Text : "Notification channels" , Id : "channels" , Url : s . cfg . AppSubURL + "/alerting-legacy/notifications" ,
2022-09-22 15:04:48 -05:00
Icon : "comment-alt-share" ,
} )
}
2024-01-05 17:19:12 -06:00
if s . features . IsEnabled ( c . Req . Context ( ) , featuremgmt . FlagAlertingPreviewUpgrade ) && c . HasRole ( org . RoleAdmin ) {
alertChildNavs = append ( alertChildNavs , & navtree . NavLink {
Text : "Upgrade Alerting" , Id : "alerting-upgrade" , Url : s . cfg . AppSubURL + "/alerting-legacy/upgrade" ,
SubTitle : "Upgrade your existing legacy alerts and notification channels to the new Grafana Alerting" ,
Icon : "cog" ,
} )
}
2022-09-22 15:04:48 -05:00
var alertNav = navtree . NavLink {
2022-10-03 04:09:32 -05:00
Text : "Alerting" ,
SubTitle : "Learn about problems in your systems moments after they occur" ,
Id : "alerting-legacy" ,
Icon : "bell" ,
Children : alertChildNavs ,
SortWeight : navtree . WeightAlerting ,
2024-01-04 17:01:57 -06:00
Url : s . cfg . AppSubURL + "/alerting-legacy" ,
2022-09-22 15:04:48 -05:00
}
2022-09-28 01:29:35 -05:00
return & alertNav
2022-09-22 15:04:48 -05:00
}
2023-05-30 08:39:09 -05:00
func ( s * ServiceImpl ) buildAlertNavLinks ( c * contextmodel . ReqContext ) * navtree . NavLink {
2022-09-22 15:04:48 -05:00
hasAccess := ac . HasAccess ( s . accessControl , c )
var alertChildNavs [ ] * navtree . NavLink
2023-05-30 08:39:09 -05:00
if hasAccess ( ac . EvalAny ( ac . EvalPermission ( ac . ActionAlertingRuleRead ) , ac . EvalPermission ( ac . ActionAlertingRuleExternalRead ) ) ) {
2022-09-22 15:04:48 -05:00
alertChildNavs = append ( alertChildNavs , & navtree . NavLink {
2022-10-03 04:09:32 -05: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-22 15:04:48 -05:00
} )
}
2023-05-30 08:39:09 -05:00
if hasAccess ( ac . EvalAny ( ac . EvalPermission ( ac . ActionAlertingNotificationsRead ) , ac . EvalPermission ( ac . ActionAlertingNotificationsExternalRead ) ) ) {
2022-09-22 15:04:48 -05:00
alertChildNavs = append ( alertChildNavs , & navtree . NavLink {
2023-01-30 09:26:21 -06: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 04:09:32 -05:00
Icon : "comment-alt-share" ,
2022-09-22 15:04:48 -05:00
} )
2022-10-03 04:09:32 -05: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-22 15:04:48 -05:00
}
2023-05-30 08:39:09 -05:00
if hasAccess ( ac . EvalAny ( ac . EvalPermission ( ac . ActionAlertingInstanceRead ) , ac . EvalPermission ( ac . ActionAlertingInstancesExternalRead ) ) ) {
2022-10-03 04:09:32 -05: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" } )
alertChildNavs = append ( alertChildNavs , & navtree . NavLink { Text : "Alert groups" , SubTitle : "See grouped alerts from an Alertmanager instance" , Id : "groups" , Url : s . cfg . AppSubURL + "/alerting/groups" , Icon : "layer-group" } )
2022-09-22 15:04:48 -05:00
}
2023-11-14 08:47:34 -06:00
if c . SignedInUser . GetOrgRole ( ) == org . RoleAdmin {
2022-09-22 15:04:48 -05:00
alertChildNavs = append ( alertChildNavs , & navtree . NavLink {
Text : "Admin" , Id : "alerting-admin" , Url : s . cfg . AppSubURL + "/alerting/admin" ,
Icon : "cog" ,
} )
}
2023-05-30 08:39:09 -05:00
if hasAccess ( ac . EvalAny ( ac . EvalPermission ( ac . ActionAlertingRuleCreate ) , ac . EvalPermission ( ac . ActionAlertingRuleExternalWrite ) ) ) {
2022-09-22 15:04:48 -05:00
alertChildNavs = append ( alertChildNavs , & navtree . NavLink {
2023-01-30 09:26:21 -06:00
Text : "Create alert rule" , SubTitle : "Create an alert rule" , Id : "alert" ,
2023-04-17 10:01:32 -05:00
Icon : "plus" , Url : s . cfg . AppSubURL + "/alerting/new" , HideFromTabs : true , IsCreateAction : true ,
2022-09-22 15:04:48 -05:00
} )
}
if len ( alertChildNavs ) > 0 {
var alertNav = navtree . NavLink {
2022-10-03 04:09:32 -05: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 03:43:11 -05:00
Url : s . cfg . AppSubURL + "/alerting" ,
2022-09-22 15:04:48 -05:00
}
2022-09-28 01:29:35 -05:00
return & alertNav
2022-09-22 15:04:48 -05:00
}
2022-09-28 01:29:35 -05:00
2022-09-22 15:04:48 -05:00
return nil
}
2023-01-27 01:50:36 -06:00
func ( s * ServiceImpl ) buildDataConnectionsNavLink ( c * contextmodel . ReqContext ) * navtree . NavLink {
2023-01-06 02:11:27 -06:00
hasAccess := ac . HasAccess ( s . accessControl , c )
2022-09-22 15:04:48 -05:00
var children [ ] * navtree . NavLink
var navLink * navtree . NavLink
2022-11-10 04:14:23 -06:00
baseUrl := s . cfg . AppSubURL + "/connections"
2022-09-22 15:04:48 -05:00
2023-05-30 08:39:09 -05:00
if hasAccess ( datasources . ConfigurationPageAccess ) {
2023-05-02 03:51:59 -05:00
// Add new connection
2023-01-11 04:40:21 -06:00
children = append ( children , & navtree . NavLink {
2023-05-02 03:51:59 -05: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 05:30:55 -06:00
Keywords : [ ] string { "csv" , "graphite" , "json" , "loki" , "prometheus" , "sql" , "tempo" } ,
2023-01-11 04:40:21 -06:00
} )
2023-05-03 02:39:13 -05:00
// Data sources
2023-01-06 02:11:27 -06:00
children = append ( children , & navtree . NavLink {
2023-05-03 02:39:13 -05:00
Id : "connections-datasources" ,
Text : "Data sources" ,
2023-05-02 03:51:59 -05:00
SubTitle : "View and manage your connected data source connections" ,
2023-05-03 02:39:13 -05:00
Url : baseUrl + "/datasources" ,
2023-05-02 03:51:59 -05:00
Children : [ ] * navtree . NavLink { } ,
2023-01-06 02:11:27 -06:00
} )
}
2022-09-22 15:04:48 -05:00
2023-01-06 02:11:27 -06: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-22 15:04:48 -05:00
}
2024-01-16 16:05:44 -06:00
func ( s * ServiceImpl ) buildExploreNavLinks ( c * contextmodel . ReqContext ) [ ] * navtree . NavLink {
exploreChildNavs := [ ] * navtree . NavLink { }
if s . features . IsEnabled ( c . Req . Context ( ) , featuremgmt . FlagDatatrails ) {
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
}