diff --git a/pkg/middleware/middleware_test.go b/pkg/middleware/middleware_test.go index 21913122667..08054c84ce8 100644 --- a/pkg/middleware/middleware_test.go +++ b/pkg/middleware/middleware_test.go @@ -4,10 +4,12 @@ import ( "context" "errors" "fmt" + "io" "net" "net/http" "path/filepath" "strconv" + "strings" "testing" "time" @@ -497,6 +499,58 @@ func TestMiddlewareContext(t *testing.T) { cfg.AuthProxyAutoSignUp = true }) + middlewareScenario(t, "Should use organisation specified by targetOrgId parameter", func(t *testing.T, sc *scenarioContext) { + bus.AddHandlerCtx("test", func(ctx context.Context, query *models.GetSignedInUserQuery) error { + if query.UserId > 0 { + query.Result = &models.SignedInUser{OrgId: query.OrgId, UserId: userID} + return nil + } + return models.ErrUserNotFound + }) + + bus.AddHandler("test", func(cmd *models.UpsertUserCommand) error { + cmd.Result = &models.User{Id: userID} + return nil + }) + + targetOrgID := 123 + sc.fakeReq("GET", fmt.Sprintf("/?targetOrgId=%d", targetOrgID)) + sc.req.Header.Set(sc.cfg.AuthProxyHeaderName, hdrName) + sc.exec() + + assert.True(t, sc.context.IsSignedIn) + assert.Equal(t, userID, sc.context.UserId) + assert.Equal(t, int64(targetOrgID), sc.context.OrgId) + }, func(cfg *setting.Cfg) { + configure(cfg) + cfg.LDAPEnabled = false + cfg.AuthProxyAutoSignUp = true + }) + + middlewareScenario(t, "Request body should not be read in default context handler", func(t *testing.T, sc *scenarioContext) { + sc.fakeReq("POST", "/?targetOrgId=123") + body := "key=value" + sc.req.Body = io.NopCloser(strings.NewReader(body)) + + sc.handlerFunc = func(c *models.ReqContext) { + t.Log("Handler called") + defer func() { + err := c.Req.Body.Close() + require.NoError(t, err) + }() + + bodyAfterHandler, e := io.ReadAll(c.Req.Body) + require.NoError(t, e) + require.Equal(t, body, string(bodyAfterHandler)) + } + + sc.req.Header.Set(sc.cfg.AuthProxyHeaderName, hdrName) + sc.req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + sc.req.Header.Set("Content-Length", strconv.Itoa(len(body))) + sc.m.Post("/", sc.defaultHandler) + sc.exec() + }) + middlewareScenario(t, "Should get an existing user from header", func(t *testing.T, sc *scenarioContext) { const userID int64 = 12 const orgID int64 = 2 diff --git a/pkg/services/contexthandler/contexthandler.go b/pkg/services/contexthandler/contexthandler.go index b38ca26a09a..8008d4121d9 100644 --- a/pkg/services/contexthandler/contexthandler.go +++ b/pkg/services/contexthandler/contexthandler.go @@ -4,6 +4,7 @@ package contexthandler import ( "context" "errors" + "net/url" "strconv" "strings" "time" @@ -105,6 +106,19 @@ func (h *ContextHandler) Middleware(mContext *web.Context) { } } + queryParameters, err := url.ParseQuery(reqContext.Req.URL.RawQuery) + if err != nil { + reqContext.Logger.Error("Failed to parse query parameters", "error", err) + } + if queryParameters.Has("targetOrgId") { + targetOrg, err := strconv.ParseInt(queryParameters.Get("targetOrgId"), 10, 64) + if err == nil { + orgID = targetOrg + } else { + reqContext.Logger.Error("Invalid target organization ID", "error", err) + } + } + // the order in which these are tested are important // look for api key in Authorization header first // then init session and look for userId in session