diff --git a/pkg/api/api.go b/pkg/api/api.go index 602f5a8d596..5c5596d5da2 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -22,66 +22,66 @@ func (hs *HTTPServer) registerRoutes() { r := hs.RouteRegister // not logged in views - r.Get("/", reqSignedIn, Index) + r.Get("/", reqSignedIn, hs.Index) r.Get("/logout", Logout) r.Post("/login", quota("session"), bind(dtos.LoginCommand{}), Wrap(LoginPost)) r.Get("/login/:name", quota("session"), OAuthLogin) - r.Get("/login", LoginView) - r.Get("/invite/:code", Index) + r.Get("/login", hs.LoginView) + r.Get("/invite/:code", hs.Index) // authed views - r.Get("/profile/", reqSignedIn, Index) - r.Get("/profile/password", reqSignedIn, Index) - r.Get("/profile/switch-org/:id", reqSignedIn, ChangeActiveOrgAndRedirectToHome) - r.Get("/org/", reqSignedIn, Index) - r.Get("/org/new", reqSignedIn, Index) - r.Get("/datasources/", reqSignedIn, Index) - r.Get("/datasources/new", reqSignedIn, Index) - r.Get("/datasources/edit/*", reqSignedIn, Index) - r.Get("/org/users", reqSignedIn, Index) - r.Get("/org/users/new", reqSignedIn, Index) - r.Get("/org/users/invite", reqSignedIn, Index) - r.Get("/org/teams", reqSignedIn, Index) - r.Get("/org/teams/*", reqSignedIn, Index) - r.Get("/org/apikeys/", reqSignedIn, Index) - r.Get("/dashboard/import/", reqSignedIn, Index) - r.Get("/configuration", reqGrafanaAdmin, Index) - r.Get("/admin", reqGrafanaAdmin, Index) - r.Get("/admin/settings", reqGrafanaAdmin, Index) - r.Get("/admin/users", reqGrafanaAdmin, Index) - r.Get("/admin/users/create", reqGrafanaAdmin, Index) - r.Get("/admin/users/edit/:id", reqGrafanaAdmin, Index) - r.Get("/admin/orgs", reqGrafanaAdmin, Index) - r.Get("/admin/orgs/edit/:id", reqGrafanaAdmin, Index) - r.Get("/admin/stats", reqGrafanaAdmin, Index) + r.Get("/profile/", reqSignedIn, hs.Index) + r.Get("/profile/password", reqSignedIn, hs.Index) + r.Get("/profile/switch-org/:id", reqSignedIn, hs.ChangeActiveOrgAndRedirectToHome) + r.Get("/org/", reqSignedIn, hs.Index) + r.Get("/org/new", reqSignedIn, hs.Index) + r.Get("/datasources/", reqSignedIn, hs.Index) + r.Get("/datasources/new", reqSignedIn, hs.Index) + r.Get("/datasources/edit/*", reqSignedIn, hs.Index) + r.Get("/org/users", reqSignedIn, hs.Index) + r.Get("/org/users/new", reqSignedIn, hs.Index) + r.Get("/org/users/invite", reqSignedIn, hs.Index) + r.Get("/org/teams", reqSignedIn, hs.Index) + r.Get("/org/teams/*", reqSignedIn, hs.Index) + r.Get("/org/apikeys/", reqSignedIn, hs.Index) + r.Get("/dashboard/import/", reqSignedIn, hs.Index) + r.Get("/configuration", reqGrafanaAdmin, hs.Index) + r.Get("/admin", reqGrafanaAdmin, hs.Index) + r.Get("/admin/settings", reqGrafanaAdmin, hs.Index) + r.Get("/admin/users", reqGrafanaAdmin, hs.Index) + r.Get("/admin/users/create", reqGrafanaAdmin, hs.Index) + r.Get("/admin/users/edit/:id", reqGrafanaAdmin, hs.Index) + r.Get("/admin/orgs", reqGrafanaAdmin, hs.Index) + r.Get("/admin/orgs/edit/:id", reqGrafanaAdmin, hs.Index) + r.Get("/admin/stats", reqGrafanaAdmin, hs.Index) - r.Get("/styleguide", reqSignedIn, Index) + r.Get("/styleguide", reqSignedIn, hs.Index) - r.Get("/plugins", reqSignedIn, Index) - r.Get("/plugins/:id/edit", reqSignedIn, Index) - r.Get("/plugins/:id/page/:page", reqSignedIn, Index) + r.Get("/plugins", reqSignedIn, hs.Index) + r.Get("/plugins/:id/edit", reqSignedIn, hs.Index) + r.Get("/plugins/:id/page/:page", reqSignedIn, hs.Index) - r.Get("/d/:uid/:slug", reqSignedIn, Index) - r.Get("/d/:uid", reqSignedIn, Index) - r.Get("/dashboard/db/:slug", reqSignedIn, redirectFromLegacyDashboardURL, Index) - r.Get("/dashboard/script/*", reqSignedIn, Index) - r.Get("/dashboard-solo/snapshot/*", Index) - r.Get("/d-solo/:uid/:slug", reqSignedIn, Index) - r.Get("/dashboard-solo/db/:slug", reqSignedIn, redirectFromLegacyDashboardSoloURL, Index) - r.Get("/dashboard-solo/script/*", reqSignedIn, Index) - r.Get("/import/dashboard", reqSignedIn, Index) - r.Get("/dashboards/", reqSignedIn, Index) - r.Get("/dashboards/*", reqSignedIn, Index) + r.Get("/d/:uid/:slug", reqSignedIn, hs.Index) + r.Get("/d/:uid", reqSignedIn, hs.Index) + r.Get("/dashboard/db/:slug", reqSignedIn, redirectFromLegacyDashboardURL, hs.Index) + r.Get("/dashboard/script/*", reqSignedIn, hs.Index) + r.Get("/dashboard-solo/snapshot/*", hs.Index) + r.Get("/d-solo/:uid/:slug", reqSignedIn, hs.Index) + r.Get("/dashboard-solo/db/:slug", reqSignedIn, redirectFromLegacyDashboardSoloURL, hs.Index) + r.Get("/dashboard-solo/script/*", reqSignedIn, hs.Index) + r.Get("/import/dashboard", reqSignedIn, hs.Index) + r.Get("/dashboards/", reqSignedIn, hs.Index) + r.Get("/dashboards/*", reqSignedIn, hs.Index) - r.Get("/explore", reqEditorRole, Index) + r.Get("/explore", reqEditorRole, hs.Index) - r.Get("/playlists/", reqSignedIn, Index) - r.Get("/playlists/*", reqSignedIn, Index) - r.Get("/alerting/", reqSignedIn, Index) - r.Get("/alerting/*", reqSignedIn, Index) + r.Get("/playlists/", reqSignedIn, hs.Index) + r.Get("/playlists/*", reqSignedIn, hs.Index) + r.Get("/alerting/", reqSignedIn, hs.Index) + r.Get("/alerting/*", reqSignedIn, hs.Index) // sign up - r.Get("/signup", Index) + r.Get("/signup", hs.Index) r.Get("/api/user/signup/options", Wrap(GetSignUpOptions)) r.Post("/api/user/signup", quota("user"), bind(dtos.SignUpForm{}), Wrap(SignUp)) r.Post("/api/user/signup/step2", bind(dtos.SignUpStep2Form{}), Wrap(SignUpStep2)) @@ -91,15 +91,15 @@ func (hs *HTTPServer) registerRoutes() { r.Post("/api/user/invite/complete", bind(dtos.CompleteInviteForm{}), Wrap(CompleteInvite)) // reset password - r.Get("/user/password/send-reset-email", Index) - r.Get("/user/password/reset", Index) + r.Get("/user/password/send-reset-email", hs.Index) + r.Get("/user/password/reset", hs.Index) r.Post("/api/user/password/send-reset-email", bind(dtos.SendResetPasswordEmailForm{}), Wrap(SendResetPasswordEmail)) r.Post("/api/user/password/reset", bind(dtos.ResetUserPasswordForm{}), Wrap(ResetPassword)) // dashboard snapshots - r.Get("/dashboard/snapshot/*", Index) - r.Get("/dashboard/snapshots/", reqSignedIn, Index) + r.Get("/dashboard/snapshot/*", hs.Index) + r.Get("/dashboard/snapshots/", reqSignedIn, hs.Index) // api for dashboard snapshots r.Post("/api/snapshots/", bind(m.CreateDashboardSnapshotCommand{}), CreateDashboardSnapshot) diff --git a/pkg/api/http_server.go b/pkg/api/http_server.go index 432d6a18369..858b3c5a8c5 100644 --- a/pkg/api/http_server.go +++ b/pkg/api/http_server.go @@ -28,6 +28,7 @@ import ( "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/registry" + "github.com/grafana/grafana/pkg/services/hooks" "github.com/grafana/grafana/pkg/services/rendering" "github.com/grafana/grafana/pkg/setting" ) @@ -52,6 +53,7 @@ type HTTPServer struct { Bus bus.Bus `inject:""` RenderService rendering.Service `inject:""` Cfg *setting.Cfg `inject:""` + HooksService *hooks.HooksService `inject:""` } func (hs *HTTPServer) Init() error { @@ -184,7 +186,7 @@ func (hs *HTTPServer) applyRoutes() { // then custom app proxy routes hs.initAppPluginRoutes(hs.macaron) // lastly not found route - hs.macaron.NotFound(NotFoundHandler) + hs.macaron.NotFound(hs.NotFoundHandler) } func (hs *HTTPServer) addMiddlewaresAndStaticRoutes() { diff --git a/pkg/api/index.go b/pkg/api/index.go index b78ee6e0a41..9f867d51cad 100644 --- a/pkg/api/index.go +++ b/pkg/api/index.go @@ -17,7 +17,7 @@ const ( darkName = "dark" ) -func setIndexViewData(c *m.ReqContext) (*dtos.IndexViewData, error) { +func (hs *HTTPServer) setIndexViewData(c *m.ReqContext) (*dtos.IndexViewData, error) { settings, err := getFrontendSettingsMap(c) if err != nil { return nil, err @@ -316,19 +316,6 @@ func setIndexViewData(c *m.ReqContext) (*dtos.IndexViewData, error) { } if c.IsGrafanaAdmin { - children := []*dtos.NavLink{ - {Text: "Users", Id: "global-users", Url: setting.AppSubUrl + "/admin/users", Icon: "gicon gicon-user"}, - {Text: "Orgs", Id: "global-orgs", Url: setting.AppSubUrl + "/admin/orgs", Icon: "gicon gicon-org"}, - {Text: "Settings", Id: "server-settings", Url: setting.AppSubUrl + "/admin/settings", Icon: "gicon gicon-preferences"}, - {Text: "Stats", Id: "server-stats", Url: setting.AppSubUrl + "/admin/stats", Icon: "fa fa-fw fa-bar-chart"}, - } - - if setting.IsEnterprise { - children = append(children, &dtos.NavLink{Text: "Licensing", Id: "licensing", Url: setting.AppSubUrl + "/admin/licensing", Icon: "fa fa-fw fa-unlock-alt"}) - } - - children = append(children, &dtos.NavLink{Text: "Style Guide", Id: "styleguide", Url: setting.AppSubUrl + "/styleguide", Icon: "fa fa-fw fa-eyedropper"}) - cfgNode.Children = append(cfgNode.Children, &dtos.NavLink{ Text: "Server Admin", HideFromTabs: true, @@ -336,7 +323,13 @@ func setIndexViewData(c *m.ReqContext) (*dtos.IndexViewData, error) { Id: "admin", Icon: "gicon gicon-shield", Url: setting.AppSubUrl + "/admin/users", - Children: children, + Children: []*dtos.NavLink{ + {Text: "Users", Id: "global-users", Url: setting.AppSubUrl + "/admin/users", Icon: "gicon gicon-user"}, + {Text: "Orgs", Id: "global-orgs", Url: setting.AppSubUrl + "/admin/orgs", Icon: "gicon gicon-org"}, + {Text: "Settings", Id: "server-settings", Url: setting.AppSubUrl + "/admin/settings", Icon: "gicon gicon-preferences"}, + {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"}, + }, }) } @@ -357,11 +350,12 @@ func setIndexViewData(c *m.ReqContext) (*dtos.IndexViewData, error) { }, }) + hs.HooksService.RunIndexDataHooks(&data) return &data, nil } -func Index(c *m.ReqContext) { - data, err := setIndexViewData(c) +func (hs *HTTPServer) Index(c *m.ReqContext) { + data, err := hs.setIndexViewData(c) if err != nil { c.Handle(500, "Failed to get settings", err) return @@ -369,13 +363,13 @@ func Index(c *m.ReqContext) { c.HTML(200, "index", data) } -func NotFoundHandler(c *m.ReqContext) { +func (hs *HTTPServer) NotFoundHandler(c *m.ReqContext) { if c.IsApiRequest() { c.JsonApiErr(404, "Not found", nil) return } - data, err := setIndexViewData(c) + data, err := hs.setIndexViewData(c) if err != nil { c.Handle(500, "Failed to get settings", err) return diff --git a/pkg/api/login.go b/pkg/api/login.go index 632d04e37f1..1083f89adfd 100644 --- a/pkg/api/login.go +++ b/pkg/api/login.go @@ -17,8 +17,8 @@ const ( ViewIndex = "index" ) -func LoginView(c *m.ReqContext) { - viewData, err := setIndexViewData(c) +func (hs *HTTPServer) LoginView(c *m.ReqContext) { + viewData, err := hs.setIndexViewData(c) if err != nil { c.Handle(500, "Failed to get settings", err) return diff --git a/pkg/api/user.go b/pkg/api/user.go index 4b916202e65..7116ad83f3f 100644 --- a/pkg/api/user.go +++ b/pkg/api/user.go @@ -177,17 +177,17 @@ func UserSetUsingOrg(c *m.ReqContext) Response { } // GET /profile/switch-org/:id -func ChangeActiveOrgAndRedirectToHome(c *m.ReqContext) { +func (hs *HTTPServer) ChangeActiveOrgAndRedirectToHome(c *m.ReqContext) { orgID := c.ParamsInt64(":id") if !validateUsingOrg(c.UserId, orgID) { - NotFoundHandler(c) + hs.NotFoundHandler(c) } cmd := m.SetUsingOrgCommand{UserId: c.UserId, OrgId: orgID} if err := bus.Dispatch(&cmd); err != nil { - NotFoundHandler(c) + hs.NotFoundHandler(c) } c.Redirect(setting.AppSubUrl + "/") diff --git a/pkg/services/hooks/hooks.go b/pkg/services/hooks/hooks.go new file mode 100644 index 00000000000..c51650cf6c9 --- /dev/null +++ b/pkg/services/hooks/hooks.go @@ -0,0 +1,30 @@ +package hooks + +import ( + "github.com/grafana/grafana/pkg/api/dtos" + "github.com/grafana/grafana/pkg/registry" +) + +type IndexDataHook func(indexData *dtos.IndexViewData) + +type HooksService struct { + indexDataHooks []IndexDataHook +} + +func init() { + registry.RegisterService(&HooksService{}) +} + +func (srv *HooksService) Init() error { + return nil +} + +func (srv *HooksService) AddIndexDataHook(hook IndexDataHook) { + srv.indexDataHooks = append(srv.indexDataHooks, hook) +} + +func (srv *HooksService) RunIndexDataHooks(indexData *dtos.IndexViewData) { + for _, hook := range srv.indexDataHooks { + hook(indexData) + } +}