From 5174d050f2fb70da5e68b649cb63013aebb531a6 Mon Sep 17 00:00:00 2001 From: bergquist Date: Fri, 17 Feb 2017 15:02:14 +0100 Subject: [PATCH 1/2] middlware: change org when url contains orgid closes #6948 ref #1613 --- pkg/api/http_server.go | 1 + pkg/middleware/middleware_test.go | 1 + pkg/middleware/org_redirect.go | 41 ++++++++++++++++++ pkg/middleware/org_redirect_test.go | 60 +++++++++++++++++++++++++++ pkg/services/alerting/eval_context.go | 2 +- pkg/services/sqlstore/user.go | 16 +++++++ 6 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 pkg/middleware/org_redirect.go create mode 100644 pkg/middleware/org_redirect_test.go diff --git a/pkg/api/http_server.go b/pkg/api/http_server.go index c1a3b238041..fe7ca21f402 100644 --- a/pkg/api/http_server.go +++ b/pkg/api/http_server.go @@ -150,6 +150,7 @@ func (hs *HttpServer) newMacaron() *macaron.Macaron { m.Use(middleware.GetContextHandler()) m.Use(middleware.Sessioner(&setting.SessionOptions)) m.Use(middleware.RequestMetrics()) + m.Use(middleware.OrgRedirect()) // needs to be after context handler if setting.EnforceDomain { diff --git a/pkg/middleware/middleware_test.go b/pkg/middleware/middleware_test.go index 5cffa0a2884..a1836a6744e 100644 --- a/pkg/middleware/middleware_test.go +++ b/pkg/middleware/middleware_test.go @@ -326,6 +326,7 @@ func middlewareScenario(desc string, fn scenarioFunc) { // mock out gc goroutine startSessionGC = func() {} sc.m.Use(Sessioner(&session.Options{})) + sc.m.Use(OrgRedirect()) sc.defaultHandler = func(c *Context) { sc.context = c diff --git a/pkg/middleware/org_redirect.go b/pkg/middleware/org_redirect.go new file mode 100644 index 00000000000..7dda59c01e4 --- /dev/null +++ b/pkg/middleware/org_redirect.go @@ -0,0 +1,41 @@ +package middleware + +import ( + "net/http" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/models" + + "gopkg.in/macaron.v1" +) + +func OrgRedirect() macaron.Handler { + return func(res http.ResponseWriter, req *http.Request, c *macaron.Context) { + orgId := c.QueryInt64("org-id") + if orgId == 0 { + return + } + + ctx, ok := c.Data["ctx"].(*Context) + if !ok || !ctx.IsSignedIn { + return + } + + if orgId == ctx.OrgId { + return + } + + cmd := models.SetUsingOrgCommand{UserId: ctx.UserId, OrgId: orgId} + if err := bus.Dispatch(&cmd); err != nil { + if ctx.IsApiRequest() { + ctx.JsonApiErr(404, "Not found", nil) + } else { + ctx.Error(404, "Not found") + } + + return + } + + c.Redirect(c.Req.URL.String(), 302) + } +} diff --git a/pkg/middleware/org_redirect_test.go b/pkg/middleware/org_redirect_test.go new file mode 100644 index 00000000000..1b0be22fd28 --- /dev/null +++ b/pkg/middleware/org_redirect_test.go @@ -0,0 +1,60 @@ +package middleware + +import ( + "testing" + + "fmt" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/models" + . "github.com/smartystreets/goconvey/convey" +) + +func TestOrgRedirectMiddleware(t *testing.T) { + + Convey("Can redirect to correct org", t, func() { + middlewareScenario("when setting a correct org for the user", func(sc *scenarioContext) { + sc.fakeReq("GET", "/").handler(func(c *Context) { + c.Session.Set(SESS_KEY_USERID, int64(12)) + }).exec() + + bus.AddHandler("test", func(query *models.SetUsingOrgCommand) error { + return nil + }) + + bus.AddHandler("test", func(query *models.GetSignedInUserQuery) error { + query.Result = &models.SignedInUser{OrgId: 1, UserId: 12} + return nil + }) + + sc.m.Get("/", sc.defaultHandler) + sc.fakeReq("GET", "/?org-id=3").exec() + + Convey("change org and redirect", func() { + So(sc.resp.Code, ShouldEqual, 302) + }) + }) + + middlewareScenario("when setting an invalid org for user", func(sc *scenarioContext) { + sc.fakeReq("GET", "/").handler(func(c *Context) { + c.Session.Set(SESS_KEY_USERID, int64(12)) + }).exec() + + bus.AddHandler("test", func(query *models.SetUsingOrgCommand) error { + return fmt.Errorf("") + }) + + bus.AddHandler("test", func(query *models.GetSignedInUserQuery) error { + query.Result = &models.SignedInUser{OrgId: 1, UserId: 12} + return nil + }) + + sc.m.Get("/", sc.defaultHandler) + sc.fakeReq("GET", "/?org-id=3").exec() + + Convey("not allowed to change org", func() { + So(sc.resp.Code, ShouldEqual, 404) + }) + }) + }) +} diff --git a/pkg/services/alerting/eval_context.go b/pkg/services/alerting/eval_context.go index 2b252da8c4b..3bd2f54f509 100644 --- a/pkg/services/alerting/eval_context.go +++ b/pkg/services/alerting/eval_context.go @@ -113,7 +113,7 @@ func (c *EvalContext) GetRuleUrl() (string, error) { if slug, err := c.GetDashboardSlug(); err != nil { return "", err } else { - ruleUrl := fmt.Sprintf("%sdashboard/db/%s?fullscreen&edit&tab=alert&panelId=%d", setting.AppUrl, slug, c.Rule.PanelId) + ruleUrl := fmt.Sprintf("%sdashboard/db/%s?fullscreen&edit&tab=alert&panelId=%d&org-id=%d", setting.AppUrl, slug, c.Rule.PanelId, c.Rule.OrgId) return ruleUrl, nil } } diff --git a/pkg/services/sqlstore/user.go b/pkg/services/sqlstore/user.go index 791a38f2d01..2e3c5c673d6 100644 --- a/pkg/services/sqlstore/user.go +++ b/pkg/services/sqlstore/user.go @@ -6,6 +6,8 @@ import ( "github.com/go-xorm/xorm" + "fmt" + "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/events" m "github.com/grafana/grafana/pkg/models" @@ -260,6 +262,20 @@ func ChangeUserPassword(cmd *m.ChangeUserPasswordCommand) error { } func SetUsingOrg(cmd *m.SetUsingOrgCommand) error { + getOrgsForUserCmd := &m.GetUserOrgListQuery{UserId: cmd.UserId} + GetUserOrgList(getOrgsForUserCmd) + + valid := false + for _, other := range getOrgsForUserCmd.Result { + if other.OrgId == cmd.OrgId { + valid = true + } + } + + if !valid { + return fmt.Errorf("user does not belong ot org") + } + return inTransaction(func(sess *xorm.Session) error { user := m.User{} sess.Id(cmd.UserId).Get(&user) From 6115941df083462394d652469bcc6625cb19c21b Mon Sep 17 00:00:00 2001 From: bergquist Date: Fri, 17 Feb 2017 15:18:40 +0100 Subject: [PATCH 2/2] middleware: rename org-id -> orgId --- pkg/middleware/org_redirect.go | 2 +- pkg/middleware/org_redirect_test.go | 4 ++-- pkg/services/alerting/eval_context.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/middleware/org_redirect.go b/pkg/middleware/org_redirect.go index 7dda59c01e4..b1146a500e1 100644 --- a/pkg/middleware/org_redirect.go +++ b/pkg/middleware/org_redirect.go @@ -11,7 +11,7 @@ import ( func OrgRedirect() macaron.Handler { return func(res http.ResponseWriter, req *http.Request, c *macaron.Context) { - orgId := c.QueryInt64("org-id") + orgId := c.QueryInt64("orgId") if orgId == 0 { return } diff --git a/pkg/middleware/org_redirect_test.go b/pkg/middleware/org_redirect_test.go index 1b0be22fd28..1f3d01f30f2 100644 --- a/pkg/middleware/org_redirect_test.go +++ b/pkg/middleware/org_redirect_test.go @@ -28,7 +28,7 @@ func TestOrgRedirectMiddleware(t *testing.T) { }) sc.m.Get("/", sc.defaultHandler) - sc.fakeReq("GET", "/?org-id=3").exec() + sc.fakeReq("GET", "/?orgId=3").exec() Convey("change org and redirect", func() { So(sc.resp.Code, ShouldEqual, 302) @@ -50,7 +50,7 @@ func TestOrgRedirectMiddleware(t *testing.T) { }) sc.m.Get("/", sc.defaultHandler) - sc.fakeReq("GET", "/?org-id=3").exec() + sc.fakeReq("GET", "/?orgId=3").exec() Convey("not allowed to change org", func() { So(sc.resp.Code, ShouldEqual, 404) diff --git a/pkg/services/alerting/eval_context.go b/pkg/services/alerting/eval_context.go index 3bd2f54f509..e92edd2af12 100644 --- a/pkg/services/alerting/eval_context.go +++ b/pkg/services/alerting/eval_context.go @@ -113,7 +113,7 @@ func (c *EvalContext) GetRuleUrl() (string, error) { if slug, err := c.GetDashboardSlug(); err != nil { return "", err } else { - ruleUrl := fmt.Sprintf("%sdashboard/db/%s?fullscreen&edit&tab=alert&panelId=%d&org-id=%d", setting.AppUrl, slug, c.Rule.PanelId, c.Rule.OrgId) + ruleUrl := fmt.Sprintf("%sdashboard/db/%s?fullscreen&edit&tab=alert&panelId=%d&orgId=%d", setting.AppUrl, slug, c.Rule.PanelId, c.Rule.OrgId) return ruleUrl, nil } }