2015-01-29 12:10:34 +01:00
package api
import (
2016-09-23 12:29:53 +02:00
"fmt"
2016-07-05 17:59:43 +02:00
"strings"
2015-02-05 10:37:13 +01:00
"github.com/grafana/grafana/pkg/api/dtos"
2016-04-02 13:54:06 -07:00
"github.com/grafana/grafana/pkg/bus"
2015-11-20 09:43:10 +01:00
m "github.com/grafana/grafana/pkg/models"
2015-10-06 17:20:50 +08:00
"github.com/grafana/grafana/pkg/plugins"
2015-02-05 10:37:13 +01:00
"github.com/grafana/grafana/pkg/setting"
2015-01-29 12:10:34 +01:00
)
2018-03-07 11:54:50 -05:00
func setIndexViewData ( c * m . ReqContext ) ( * dtos . IndexViewData , error ) {
2015-02-18 14:06:44 +01:00
settings , err := getFrontendSettingsMap ( c )
2015-01-29 12:10:34 +01:00
if err != nil {
2015-11-20 09:43:10 +01:00
return nil , err
2015-01-29 12:10:34 +01:00
}
2016-04-02 13:54:06 -07:00
prefsQuery := m . GetPreferencesWithDefaultsQuery { OrgId : c . OrgId , UserId : c . UserId }
if err := bus . Dispatch ( & prefsQuery ) ; err != nil {
return nil , err
}
prefs := prefsQuery . Result
2016-07-05 17:59:43 +02:00
// Read locale from acccept-language
acceptLang := c . Req . Header . Get ( "Accept-Language" )
locale := "en-US"
if len ( acceptLang ) > 0 {
parts := strings . Split ( acceptLang , "," )
locale = parts [ 0 ]
}
2018-03-22 12:37:35 +01:00
appURL := setting . AppUrl
appSubURL := setting . AppSubUrl
2016-09-23 12:29:53 +02:00
// special case when doing localhost call from phantomjs
if c . IsRenderCall {
2018-03-22 12:37:35 +01:00
appURL = fmt . Sprintf ( "%s://localhost:%s" , setting . Protocol , setting . HttpPort )
appSubURL = ""
2016-09-23 12:29:53 +02:00
settings [ "appSubUrl" ] = ""
}
2018-04-30 15:34:31 +02:00
hasEditPermissionInFoldersQuery := m . HasEditPermissionInFoldersQuery { SignedInUser : c . SignedInUser }
if err := bus . Dispatch ( & hasEditPermissionInFoldersQuery ) ; err != nil {
return nil , err
}
2015-11-20 09:43:10 +01:00
var data = dtos . IndexViewData {
User : & dtos . CurrentUser {
2018-04-30 15:34:31 +02:00
Id : c . UserId ,
IsSignedIn : c . IsSignedIn ,
Login : c . Login ,
Email : c . Email ,
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 == "light" ,
Timezone : prefs . Timezone ,
Locale : locale ,
HelpFlags1 : c . HelpFlags1 ,
HasEditPermissionInFolders : hasEditPermissionInFoldersQuery . Result ,
2015-11-20 09:43:10 +01:00
} ,
2016-05-03 09:00:58 +02:00
Settings : settings ,
2017-10-11 21:36:03 +02:00
Theme : prefs . Theme ,
2018-03-22 12:37:35 +01:00
AppUrl : appURL ,
AppSubUrl : appSubURL ,
2016-05-03 09:00:58 +02:00
GoogleAnalyticsId : setting . GoogleAnalyticsId ,
GoogleTagManagerId : setting . GoogleTagManagerId ,
BuildVersion : setting . BuildVersion ,
BuildCommit : setting . BuildCommit ,
NewGrafanaVersion : plugins . GrafanaLatestVersion ,
NewGrafanaVersionExists : plugins . GrafanaHasUpdate ,
2015-01-29 12:10:34 +01:00
}
2015-05-01 08:40:13 +02:00
if setting . DisableGravatar {
2018-03-06 11:46:01 +01:00
data . User . GravatarUrl = setting . AppSubUrl + "/public/img/user_profile.png"
2015-05-01 08:40:13 +02:00
}
2015-11-20 09:43:10 +01:00
if len ( data . User . Name ) == 0 {
data . User . Name = data . User . Login
2015-02-03 10:46:52 +01:00
}
2018-03-22 12:37:35 +01:00
themeURLParam := c . Query ( "theme" )
if themeURLParam == "light" {
2015-11-20 09:43:10 +01:00
data . User . LightTheme = true
2017-10-18 09:48:37 +02:00
data . Theme = "light"
2015-04-02 09:21:38 +02:00
}
2018-05-28 20:37:39 +02:00
if hasEditPermissionInFoldersQuery . Result {
children := [ ] * dtos . NavLink {
{ Text : "Dashboard" , Icon : "gicon gicon-dashboard-new" , Url : setting . AppSubUrl + "/dashboard/new" } ,
}
if c . OrgRole == m . ROLE_ADMIN || c . OrgRole == m . ROLE_EDITOR {
children = append ( children , & dtos . NavLink { Text : "Folder" , SubTitle : "Create a new folder to organize your dashboards" , Id : "folder" , Icon : "gicon gicon-folder-new" , Url : setting . AppSubUrl + "/dashboards/folder/new" } )
}
2018-06-07 17:05:56 +03:00
children = append ( children , & dtos . NavLink { Text : "Import" , SubTitle : "Import dashboard from file or Grafana.com" , Id : "import" , Icon : "gicon gicon-dashboard-import" , Url : setting . AppSubUrl + "/dashboard/import" } )
2017-08-15 17:52:52 +02:00
data . NavTree = append ( data . NavTree , & dtos . NavLink {
2018-05-28 20:37:39 +02:00
Text : "Create" ,
Id : "create" ,
Icon : "fa fa-fw fa-plus" ,
Url : setting . AppSubUrl + "/dashboard/new" ,
Children : children ,
2017-06-22 18:41:39 -04:00
} )
2016-03-10 16:38:16 +01:00
}
2017-06-22 18:41:39 -04:00
dashboardChildNavs := [ ] * dtos . NavLink {
2018-01-11 15:42:45 +01:00
{ Text : "Home" , Id : "home" , Url : setting . AppSubUrl + "/" , Icon : "gicon gicon-home" , HideFromTabs : true } ,
{ Text : "Divider" , Divider : true , Id : "divider" , HideFromTabs : true } ,
2017-12-13 17:48:44 -05:00
{ Text : "Manage" , Id : "manage-dashboards" , Url : setting . AppSubUrl + "/dashboards" , Icon : "gicon gicon-manage" } ,
{ Text : "Playlists" , Id : "playlists" , Url : setting . AppSubUrl + "/playlists" , Icon : "gicon gicon-playlists" } ,
{ Text : "Snapshots" , Id : "snapshots" , Url : setting . AppSubUrl + "/dashboard/snapshots" , Icon : "gicon gicon-snapshots" } ,
2016-03-10 16:38:16 +01:00
}
2017-08-15 17:52:52 +02:00
data . NavTree = append ( data . NavTree , & dtos . NavLink {
2016-03-10 16:38:16 +01:00
Text : "Dashboards" ,
2017-08-15 20:24:16 +02:00
Id : "dashboards" ,
2017-12-01 11:32:00 +01:00
SubTitle : "Manage dashboards & folders" ,
2017-10-14 21:17:16 +02:00
Icon : "gicon gicon-dashboard" ,
2017-12-01 12:51:46 +01:00
Url : setting . AppSubUrl + "/" ,
2016-03-10 16:38:16 +01:00
Children : dashboardChildNavs ,
2015-11-20 09:43:10 +01:00
} )
2018-05-30 13:13:29 +02:00
if setting . ExploreEnabled && ( c . OrgRole == m . ROLE_ADMIN || c . OrgRole == m . ROLE_EDITOR ) {
2018-04-27 11:39:14 +02:00
data . NavTree = append ( data . NavTree , & dtos . NavLink {
Text : "Explore" ,
Id : "explore" ,
SubTitle : "Explore your data" ,
Icon : "fa fa-rocket" ,
Url : setting . AppSubUrl + "/explore" ,
Children : [ ] * dtos . NavLink {
2018-04-27 15:35:46 +02:00
{ Text : "New tab" , Icon : "gicon gicon-dashboard-new" , Url : setting . AppSubUrl + "/explore" } ,
2018-04-27 11:39:14 +02:00
} ,
} )
}
2018-04-26 11:58:42 +02:00
2017-08-15 20:24:16 +02:00
if c . IsSignedIn {
2018-04-16 13:37:05 +02:00
// Only set login if it's different from the name
var login string
if c . SignedInUser . Login != c . SignedInUser . NameOrFallback ( ) {
login = c . SignedInUser . Login
}
2017-08-16 15:03:49 +02:00
profileNode := & dtos . NavLink {
2017-12-15 13:06:11 +01:00
Text : c . SignedInUser . NameOrFallback ( ) ,
2018-04-16 13:37:05 +02:00
SubTitle : login ,
2017-08-15 23:17:34 +02:00
Id : "profile" ,
Img : data . User . GravatarUrl ,
Url : setting . AppSubUrl + "/profile" ,
HideFromMenu : true ,
2017-08-15 20:24:16 +02:00
Children : [ ] * dtos . NavLink {
2017-12-13 17:48:44 -05:00
{ Text : "Preferences" , Id : "profile-settings" , Url : setting . AppSubUrl + "/profile" , Icon : "gicon gicon-preferences" } ,
2017-08-15 20:24:16 +02:00
{ Text : "Change Password" , Id : "change-password" , Url : setting . AppSubUrl + "/profile/password" , Icon : "fa fa-fw fa-lock" , HideFromMenu : true } ,
} ,
2017-08-16 15:03:49 +02:00
}
if ! setting . DisableSignoutMenu {
// add sign out first
2017-11-30 17:28:24 +01:00
profileNode . Children = append ( profileNode . Children , & dtos . NavLink {
Text : "Sign out" , Id : "sign-out" , Url : setting . AppSubUrl + "/logout" , Icon : "fa fa-fw fa-sign-out" , Target : "_self" ,
} )
2017-08-16 15:03:49 +02:00
}
data . NavTree = append ( data . NavTree , profileNode )
2017-08-15 20:24:16 +02:00
}
2017-01-25 13:32:26 +01:00
if setting . AlertingEnabled && ( c . OrgRole == m . ROLE_ADMIN || c . OrgRole == m . ROLE_EDITOR ) {
2016-06-16 15:21:23 +02:00
alertChildNavs := [ ] * dtos . NavLink {
2017-12-13 17:48:44 -05:00
{ Text : "Alert Rules" , Id : "alert-list" , Url : setting . AppSubUrl + "/alerting/list" , Icon : "gicon gicon-alert-rules" } ,
2017-11-30 11:31:38 +01:00
{ Text : "Notification channels" , Id : "channels" , Url : setting . AppSubUrl + "/alerting/notifications" , Icon : "gicon gicon-alert-notification-channel" } ,
2016-06-16 15:21:23 +02:00
}
2017-08-15 17:52:52 +02:00
data . NavTree = append ( data . NavTree , & dtos . NavLink {
2016-06-16 15:21:23 +02:00
Text : "Alerting" ,
2017-11-30 15:37:03 +01:00
SubTitle : "Alert rules & notifications" ,
2017-08-15 20:24:16 +02:00
Id : "alerting" ,
2017-10-14 21:17:16 +02:00
Icon : "gicon gicon-alert" ,
2016-08-16 09:52:45 +02:00
Url : setting . AppSubUrl + "/alerting/list" ,
2016-06-16 15:21:23 +02:00
Children : alertChildNavs ,
2016-05-03 16:46:10 +02:00
} )
}
2016-01-10 21:37:11 +01:00
enabledPlugins , err := plugins . GetEnabledPlugins ( c . OrgId )
2015-12-03 23:43:55 +08:00
if err != nil {
return nil , err
}
2015-12-21 23:09:27 +01:00
for _ , plugin := range enabledPlugins . Apps {
2016-01-11 18:03:08 +01:00
if plugin . Pinned {
2016-03-21 19:07:08 +01:00
appLink := & dtos . NavLink {
2016-01-11 18:03:08 +01:00
Text : plugin . Name ,
2017-08-15 20:24:16 +02:00
Id : "plugin-page-" + plugin . Id ,
2016-03-22 10:15:47 +01:00
Url : plugin . DefaultNavUrl ,
2016-01-11 18:03:08 +01:00
Img : plugin . Info . Logos . Small ,
2016-02-09 14:06:23 +01:00
}
2016-03-21 19:07:08 +01:00
for _ , include := range plugin . Includes {
2016-04-25 14:00:49 +02:00
if ! c . HasUserRole ( include . Role ) {
continue
}
2016-03-21 19:07:08 +01:00
if include . Type == "page" && include . AddToNav {
link := & dtos . NavLink {
Url : setting . AppSubUrl + "/plugins/" + plugin . Id + "/page/" + include . Slug ,
Text : include . Name ,
}
appLink . Children = append ( appLink . Children , link )
2016-03-01 18:07:51 +08:00
}
2016-04-25 14:00:49 +02:00
2016-03-21 19:07:08 +01:00
if include . Type == "dashboard" && include . AddToNav {
link := & dtos . NavLink {
Url : setting . AppSubUrl + "/dashboard/db/" + include . Slug ,
Text : include . Name ,
}
appLink . Children = append ( appLink . Children , link )
}
}
2016-09-27 14:39:51 +02:00
if len ( appLink . Children ) > 0 && c . OrgRole == m . ROLE_ADMIN {
2016-03-21 19:07:08 +01:00
appLink . Children = append ( appLink . Children , & dtos . NavLink { Divider : true } )
2017-12-13 17:48:44 -05:00
appLink . Children = append ( appLink . Children , & dtos . NavLink { Text : "Plugin Config" , Icon : "gicon gicon-cog" , Url : setting . AppSubUrl + "/plugins/" + plugin . Id + "/edit" } )
2016-02-09 14:06:23 +01:00
}
2016-04-25 14:00:49 +02:00
if len ( appLink . Children ) > 0 {
2017-08-15 17:52:52 +02:00
data . NavTree = append ( data . NavTree , appLink )
2016-04-25 14:00:49 +02:00
}
2015-10-06 17:20:50 +08:00
}
2015-08-21 09:30:39 +02:00
}
2015-11-11 14:30:07 +08:00
2018-06-04 19:28:01 +02:00
if c . IsGrafanaAdmin || c . OrgRole == m . ROLE_ADMIN {
2017-08-15 14:49:12 +02:00
cfgNode := & dtos . NavLink {
2017-11-30 15:37:03 +01:00
Id : "cfg" ,
Text : "Configuration" ,
SubTitle : "Organization: " + c . OrgName ,
2017-12-13 17:48:44 -05:00
Icon : "gicon gicon-cog" ,
2017-11-30 15:37:03 +01:00
Url : setting . AppSubUrl + "/datasources" ,
2016-02-19 22:00:29 -05:00
Children : [ ] * dtos . NavLink {
2017-08-15 14:49:12 +02:00
{
2017-08-15 17:52:52 +02:00
Text : "Data Sources" ,
2017-10-27 08:33:04 +02:00
Icon : "gicon gicon-datasources" ,
2017-08-15 17:52:52 +02:00
Description : "Add and configure data sources" ,
Id : "datasources" ,
Url : setting . AppSubUrl + "/datasources" ,
2017-08-15 14:49:12 +02:00
} ,
2017-08-15 17:52:52 +02:00
{
2017-12-13 11:21:33 +01:00
Text : "Users" ,
2017-08-15 17:52:52 +02:00
Id : "users" ,
2017-08-18 14:49:04 +02:00
Description : "Manage org members" ,
2017-12-13 17:48:44 -05:00
Icon : "gicon gicon-user" ,
2017-08-15 17:52:52 +02:00
Url : setting . AppSubUrl + "/org/users" ,
} ,
2017-08-18 14:49:04 +02:00
{
2017-11-30 15:37:03 +01:00
Text : "Teams" ,
2017-12-01 10:47:21 +01:00
Id : "teams" ,
2017-08-18 14:49:04 +02:00
Description : "Manage org groups" ,
2017-12-08 18:25:45 +03:00
Icon : "gicon gicon-team" ,
Url : setting . AppSubUrl + "/org/teams" ,
2017-08-18 14:49:04 +02:00
} ,
2017-11-30 15:37:03 +01:00
{
Text : "Plugins" ,
Id : "plugins" ,
Description : "View and configure plugins" ,
2017-12-13 17:48:44 -05:00
Icon : "gicon gicon-plugins" ,
2017-11-30 15:37:03 +01:00
Url : setting . AppSubUrl + "/plugins" ,
} ,
{
Text : "Preferences" ,
Id : "org-settings" ,
Description : "Organization preferences" ,
2017-12-13 17:48:44 -05:00
Icon : "gicon gicon-preferences" ,
2017-11-30 15:37:03 +01:00
Url : setting . AppSubUrl + "/org" ,
} ,
2017-08-15 17:52:52 +02:00
{
Text : "API Keys" ,
2017-08-15 20:24:16 +02:00
Id : "apikeys" ,
2017-08-15 17:52:52 +02:00
Description : "Create & manage API keys" ,
2017-12-13 17:48:44 -05:00
Icon : "gicon gicon-apikeys" ,
2017-08-15 17:52:52 +02:00
Url : setting . AppSubUrl + "/org/apikeys" ,
} ,
2016-02-20 18:31:09 +01:00
} ,
2017-08-15 14:49:12 +02:00
}
2018-06-04 19:28:01 +02:00
if c . OrgRole != m . ROLE_ADMIN {
cfgNode = & dtos . NavLink {
Id : "cfg" ,
Text : "Configuration" ,
SubTitle : "Organization: " + c . OrgName ,
Icon : "gicon gicon-cog" ,
Url : setting . AppSubUrl + "/admin/users" ,
Children : make ( [ ] * dtos . NavLink , 0 ) ,
}
}
if c . OrgRole == m . ROLE_ADMIN && c . IsGrafanaAdmin {
2017-12-01 12:51:46 +01:00
cfgNode . Children = append ( cfgNode . Children , & dtos . NavLink {
2018-01-18 18:17:58 +01:00
Divider : true , HideFromTabs : true , Id : "admin-divider" , Text : "Text" ,
2017-12-01 12:51:46 +01:00
} )
2018-06-04 19:28:01 +02:00
}
if c . IsGrafanaAdmin {
2017-12-01 12:51:46 +01:00
cfgNode . Children = append ( cfgNode . Children , & dtos . NavLink {
2017-12-01 13:49:15 +01:00
Text : "Server Admin" ,
HideFromTabs : true ,
SubTitle : "Manage all users & orgs" ,
Id : "admin" ,
2017-12-13 17:48:44 -05:00
Icon : "gicon gicon-shield" ,
2017-12-01 13:49:15 +01:00
Url : setting . AppSubUrl + "/admin/users" ,
2017-12-01 12:51:46 +01:00
Children : [ ] * dtos . NavLink {
2017-12-13 17:48:44 -05:00
{ Text : "Users" , Id : "global-users" , Url : setting . AppSubUrl + "/admin/users" , Icon : "gicon gicon-user" } ,
2017-12-01 13:49:15 +01:00
{ Text : "Orgs" , Id : "global-orgs" , Url : setting . AppSubUrl + "/admin/orgs" , Icon : "gicon gicon-org" } ,
2017-12-13 17:48:44 -05:00
{ Text : "Settings" , Id : "server-settings" , Url : setting . AppSubUrl + "/admin/settings" , Icon : "gicon gicon-preferences" } ,
2017-12-01 13:49:15 +01:00
{ Text : "Stats" , Id : "server-stats" , Url : setting . AppSubUrl + "/admin/stats" , Icon : "fa fa-fw fa-bar-chart" } ,
{ Text : "Style Guide" , Id : "styleguide" , Url : setting . AppSubUrl + "/styleguide" , Icon : "fa fa-fw fa-eyedropper" } ,
2017-12-01 12:51:46 +01:00
} ,
} )
}
2017-08-15 14:49:12 +02:00
2017-08-15 17:52:52 +02:00
data . NavTree = append ( data . NavTree , cfgNode )
2016-02-14 17:37:05 +01:00
}
2017-08-16 15:03:49 +02:00
data . NavTree = append ( data . NavTree , & dtos . NavLink {
Text : "Help" ,
2018-04-27 13:41:58 +02:00
SubTitle : fmt . Sprintf ( ` %s v%s (%s) ` , setting . ApplicationName , setting . BuildVersion , setting . BuildCommit ) ,
2017-08-16 15:03:49 +02:00
Id : "help" ,
Url : "#" ,
2017-12-13 17:48:44 -05:00
Icon : "gicon gicon-question" ,
2017-08-16 15:03:49 +02:00
HideFromMenu : true ,
Children : [ ] * dtos . NavLink {
{ Text : "Keyboard shortcuts" , Url : "/shortcuts" , Icon : "fa fa-fw fa-keyboard-o" , Target : "_self" } ,
{ Text : "Community site" , Url : "http://community.grafana.com" , Icon : "fa fa-fw fa-comment" , Target : "_blank" } ,
{ Text : "Documentation" , Url : "http://docs.grafana.org" , Icon : "fa fa-fw fa-file" , Target : "_blank" } ,
} ,
} )
2015-11-20 09:43:10 +01:00
return & data , nil
2015-01-29 12:10:34 +01:00
}
2018-03-07 11:54:50 -05:00
func Index ( c * m . ReqContext ) {
2018-03-22 12:37:35 +01:00
data , err := setIndexViewData ( c )
if err != nil {
2015-01-29 12:10:34 +01:00
c . Handle ( 500 , "Failed to get settings" , err )
return
}
2018-03-22 12:37:35 +01:00
c . HTML ( 200 , "index" , data )
2015-01-29 12:10:34 +01:00
}
2018-03-07 11:54:50 -05:00
func NotFoundHandler ( c * m . ReqContext ) {
2015-01-29 12:10:34 +01:00
if c . IsApiRequest ( ) {
2015-03-22 15:14:00 -04:00
c . JsonApiErr ( 404 , "Not found" , nil )
2015-01-29 12:10:34 +01:00
return
}
2018-03-22 12:37:35 +01:00
data , err := setIndexViewData ( c )
if err != nil {
2015-01-29 12:10:34 +01:00
c . Handle ( 500 , "Failed to get settings" , err )
return
}
2018-03-22 12:37:35 +01:00
c . HTML ( 404 , "index" , data )
2015-01-29 12:10:34 +01:00
}