diff --git a/pkg/api/org_test.go b/pkg/api/org_test.go index 777c82b4031..48ec23aab37 100644 --- a/pkg/api/org_test.go +++ b/pkg/api/org_test.go @@ -249,11 +249,11 @@ func TestAPIEndpoint_GetOrg(t *testing.T) { server := SetupAPITestServer(t, func(hs *HTTPServer) { hs.Cfg = setting.NewCfg() hs.orgService = &orgtest.FakeOrgService{ExpectedOrg: &org.Org{}} - hs.userService = &usertest.FakeUserService{ExpectedSignedInUser: &user.SignedInUser{OrgID: 0}} + hs.userService = &usertest.FakeUserService{ExpectedSignedInUser: &user.SignedInUser{OrgID: 1}} hs.accesscontrolService = &actest.FakeService{ExpectedPermissions: tt.permissions} }) verify := func(path string) { - req := webtest.RequestWithSignedInUser(server.NewGetRequest(path), userWithPermissions(2, tt.permissions)) + req := webtest.RequestWithSignedInUser(server.NewGetRequest(path), authedUserWithPermissions(1, 1, tt.permissions)) res, err := server.Send(req) require.NoError(t, err) assert.Equal(t, tt.expectedCode, res.StatusCode) diff --git a/pkg/services/accesscontrol/authorize_in_org_test.go b/pkg/services/accesscontrol/authorize_in_org_test.go index 4893e8b88ee..0af24186f16 100644 --- a/pkg/services/accesscontrol/authorize_in_org_test.go +++ b/pkg/services/accesscontrol/authorize_in_org_test.go @@ -35,16 +35,18 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) { expectedStatus int }{ { - name: "should authorize user with global org ID - no fetch", + name: "should authorize user with global org ID - fetch", orgIDGetter: func(c *contextmodel.ReqContext) (int64, error) { return accesscontrol.GlobalOrgID, nil }, evaluator: accesscontrol.EvalPermission("users:read", "users:*"), accessControl: ac, - acService: &actest.FakeService{}, userCache: &usertest.FakeUserService{}, ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{1: {"users:read": {"users:*"}}}}, - expectedStatus: http.StatusOK, + acService: &actest.FakeService{ + ExpectedPermissions: []accesscontrol.Permission{{Action: "users:read", Scope: "users:*"}}, + }, + expectedStatus: http.StatusOK, }, { name: "should authorize user with non-global org ID - no fetch", @@ -70,6 +72,30 @@ func TestAuthorizeInOrgMiddleware(t *testing.T) { acService: &actest.FakeService{}, expectedStatus: http.StatusForbidden, }, + { + name: "should return 200 when user has permissions for a global org", + orgIDGetter: func(c *contextmodel.ReqContext) (int64, error) { + return accesscontrol.GlobalOrgID, nil + }, + evaluator: accesscontrol.EvalPermission("users:read", "users:*"), + accessControl: ac, + userCache: &usertest.FakeUserService{}, + ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{accesscontrol.GlobalOrgID: {"users:read": {"users:*"}}}}, + acService: &actest.FakeService{}, + expectedStatus: http.StatusOK, + }, + { + name: "should return 403 when user has no permissions for a global org", + orgIDGetter: func(c *contextmodel.ReqContext) (int64, error) { + return accesscontrol.GlobalOrgID, nil + }, + evaluator: accesscontrol.EvalPermission("users:read", "users:*"), + accessControl: ac, + userCache: &usertest.FakeUserService{}, + ctxSignedInUser: &user.SignedInUser{UserID: 1, OrgID: 1, Permissions: map[int64]map[string][]string{1: {"users:read": {"users:*"}}}}, + acService: &actest.FakeService{}, + expectedStatus: http.StatusForbidden, + }, { name: "should return 403 when user org ID doesn't match and user does not exist in org 2", orgIDGetter: func(c *contextmodel.ReqContext) (int64, error) { diff --git a/pkg/services/accesscontrol/middleware.go b/pkg/services/accesscontrol/middleware.go index 2de72567181..9902f0146ea 100644 --- a/pkg/services/accesscontrol/middleware.go +++ b/pkg/services/accesscontrol/middleware.go @@ -190,19 +190,26 @@ func AuthorizeInOrgMiddleware(ac AccessControl, service Service, cache userCache return } - if targetOrgID != GlobalOrgID && userCopy.Permissions[targetOrgID] == nil { - query := user.GetSignedInUserQuery{UserID: c.UserID, OrgID: targetOrgID} - queryResult, err := cache.GetSignedInUserWithCacheCtx(c.Req.Context(), &query) - if err != nil { - deny(c, nil, fmt.Errorf("failed to authenticate user in target org: %w", err)) - return + if userCopy.OrgID != targetOrgID { + switch targetOrgID { + case GlobalOrgID: + userCopy.OrgID = GlobalOrgID + userCopy.OrgRole = org.RoleNone + userCopy.OrgName = "" + default: + query := user.GetSignedInUserQuery{UserID: c.UserID, OrgID: targetOrgID} + queryResult, err := cache.GetSignedInUserWithCacheCtx(c.Req.Context(), &query) + if err != nil { + deny(c, nil, fmt.Errorf("failed to authenticate user in target org: %w", err)) + return + } + userCopy.OrgID = queryResult.OrgID + userCopy.OrgName = queryResult.OrgName + userCopy.OrgRole = queryResult.OrgRole } - userCopy.OrgID = queryResult.OrgID - userCopy.OrgName = queryResult.OrgName - userCopy.OrgRole = queryResult.OrgRole } - if userCopy.Permissions[userCopy.OrgID] == nil { + if userCopy.Permissions[targetOrgID] == nil { permissions, err := service.GetUserPermissions(c.Req.Context(), &userCopy, Options{}) if err != nil { deny(c, nil, fmt.Errorf("failed to authenticate user in target org: %w", err)) @@ -212,7 +219,7 @@ func AuthorizeInOrgMiddleware(ac AccessControl, service Service, cache userCache if userCopy.Permissions == nil { userCopy.Permissions = make(map[int64]map[string][]string) } - userCopy.Permissions[userCopy.OrgID] = GroupScopesByAction(permissions) + userCopy.Permissions[targetOrgID] = GroupScopesByAction(permissions) } authorize(c, ac, &userCopy, evaluator) @@ -221,7 +228,7 @@ func AuthorizeInOrgMiddleware(ac AccessControl, service Service, cache userCache if c.SignedInUser.Permissions == nil { c.SignedInUser.Permissions = make(map[int64]map[string][]string) } - c.SignedInUser.Permissions[userCopy.OrgID] = userCopy.Permissions[userCopy.OrgID] + c.SignedInUser.Permissions[targetOrgID] = userCopy.Permissions[targetOrgID] } } }