fix: Unify public-only token filtering in API queries and repo access checks (#37118) (#37773)

backport #37118 

This PR closes remaining `public-only` token gaps in the API by making
the restriction apply consistently across repository, organization,
activity, notification, and authenticated `/api/v1/user/...` routes.

Previously, `public-only` tokens were still able to:
- receive private results from some list/search/self endpoints,
- access repository data through ID-based lookups,
- and reach several authenticated self routes that should remain
unavailable for public-only access.

This change treats `public-only` as a cross-cutting visibility boundary:
- list/search endpoints now filter private resources consistently,
- repository lookups enforce the same restriction even when addressed
indirectly,
- and self routes that inherently expose or mutate private account state
now reject `public-only` tokens.

---
Generated by a coding agent with Codex 5.2

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
Co-authored-by: Nicolas <bircni@icloud.com>
This commit is contained in:
Lunny Xiao
2026-05-19 08:38:51 -07:00
committed by GitHub
parent 6d2b02dac1
commit a34eac5ef4
22 changed files with 561 additions and 87 deletions
+8 -3
View File
@@ -33,6 +33,7 @@ func listUserOrgs(ctx *context.APIContext, u *user_model.User) {
UserID: u.ID,
IncludeVisibility: organization.DoerViewOtherVisibility(ctx.Doer, u),
}
opts.ApplyPublicOnly(ctx.PublicOnly)
orgs, maxResults, err := db.FindAndCount[organization.Organization](ctx, opts)
if err != nil {
ctx.APIErrorInternal(err)
@@ -192,7 +193,7 @@ func GetAll(ctx *context.APIContext) {
// "$ref": "#/responses/OrganizationList"
vMode := []api.VisibleType{api.VisibleTypePublic}
if ctx.IsSigned && !ctx.PublicOnly {
if ctx.IsSigned {
vMode = append(vMode, api.VisibleTypeLimited)
if ctx.Doer.IsAdmin {
vMode = append(vMode, api.VisibleTypePrivate)
@@ -201,13 +202,16 @@ func GetAll(ctx *context.APIContext) {
listOptions := utils.GetListOptions(ctx)
publicOrgs, maxResults, err := user_model.SearchUsers(ctx, user_model.SearchUserOptions{
searchOpts := user_model.SearchUserOptions{
Actor: ctx.Doer,
ListOptions: listOptions,
Types: []user_model.UserType{user_model.UserTypeOrganization},
OrderBy: db.SearchOrderByAlphabetically,
Visible: vMode,
})
}
searchOpts.ApplyPublicOnly(ctx.PublicOnly)
publicOrgs, maxResults, err := user_model.SearchUsers(ctx, searchOpts)
if err != nil {
ctx.APIErrorInternal(err)
return
@@ -487,6 +491,7 @@ func ListOrgActivityFeeds(ctx *context.APIContext) {
Date: ctx.FormString("date"),
ListOptions: listOptions,
}
opts.ApplyPublicOnly(ctx.PublicOnly)
feeds, count, err := feed_service.GetFeeds(ctx, opts)
if err != nil {