fix(api): enforce organization listing token scope (#39041)

Enforce organization token scope before listing organizations and retain
public-only filtering.

---------

Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
bircni
2026-08-23 09:23:16 +02:00
committed by GitHub
parent 55a5f50961
commit adc3db1f27
2 changed files with 12 additions and 1 deletions

View File

@@ -1781,7 +1781,7 @@ func Routes() *web.Router {
m.Get("/{org}/permissions", reqToken(), org.GetUserOrgsPermissions)
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser, auth_model.AccessTokenScopeCategoryOrganization), context.UserAssignmentAPI(), checkTokenPublicOnly(), individualPermsChecker)
m.Post("/orgs", tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), reqToken(), bind(api.CreateOrgOption{}), org.Create)
m.Get("/orgs", org.GetAll, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization))
m.Get("/orgs", tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), org.GetAll)
m.Group("/orgs/{org}", func() {
m.Combo("").Get(org.Get).
Patch(reqToken(), reqOrgOwnership(), bind(api.EditOrgOption{}), org.Edit).

View File

@@ -121,6 +121,9 @@ func testAPIOrgGeneral(t *testing.T) {
user1Token := getTokenForLoggedInUser(t, user1Session, auth_model.AccessTokenScopeWriteOrganization)
t.Run("OrgGetAll", func(t *testing.T) {
miscToken := getTokenForLoggedInUser(t, user1Session, auth_model.AccessTokenScopeReadMisc)
MakeRequest(t, NewRequest(t, "GET", "/api/v1/orgs").AddTokenAuth(miscToken), http.StatusForbidden)
// accessing with a token will return all orgs
req := NewRequest(t, "GET", "/api/v1/orgs").AddTokenAuth(user1Token)
resp := MakeRequest(t, req, http.StatusOK)
@@ -130,6 +133,14 @@ func testAPIOrgGeneral(t *testing.T) {
assert.Equal(t, "Limited Org 36", apiOrgList[1].FullName)
assert.Equal(t, api.VisibilityStringLimited, apiOrgList[1].Visibility)
publicOnlyToken := getTokenForLoggedInUser(t, user1Session, auth_model.AccessTokenScopeReadOrganization, auth_model.AccessTokenScopePublicOnly)
resp = MakeRequest(t, NewRequest(t, "GET", "/api/v1/orgs").AddTokenAuth(publicOnlyToken), http.StatusOK)
apiOrgList = DecodeJSON(t, resp, []*api.Organization{})
assert.Len(t, apiOrgList, 9)
for _, org := range apiOrgList {
assert.Equal(t, api.VisibilityStringPublic, org.Visibility)
}
// accessing without a token will return only public orgs
req = NewRequest(t, "GET", "/api/v1/orgs")
resp = MakeRequest(t, req, http.StatusOK)