Gitea Version
1.27.0
What happened?
An organization set to Limited ("Visible only to authenticated users") shows a signed-in non-member only the Repositories tab. Packages, Code and Projects are gone from the org menu. Packages still loads if the URL is entered directly, despite the hidden tab; Code and Projects return 404. The same organization set to Public shows all of these tabs to everyone, including anonymous visitors.
Expected behaviour: limited should show the same tabs as public, with the audience narrowed to authenticated users.
Root cause
Organization.UnitPermission() in models/organization/org.go:
if doer != nil {
teams, _ := GetUserOrgTeams(ctx, org.ID, doer.ID)
if len(teams) > 0 {
return teams.UnitMaxAccess(unitType)
}
}
if org.Visibility.IsPublic() {
return perm.AccessModeRead
}
return perm.AccessModeNone
A signed-in non-member has no teams in the org, so it skips the first block. IsPublic() is a strict == VisibleTypePublic, so limited falls through to AccessModeNone.
That one check causes both symptoms:
Hidden tabs — services/context/org.go:
ctx.Data["CanReadProjects"] = ctx.Org.CanReadUnit(ctx, unit.TypeProjects)
ctx.Data["CanReadPackages"] = ctx.Org.CanReadUnit(ctx, unit.TypePackages)
ctx.Data["CanReadCode"] = ctx.Org.CanReadUnit(ctx, unit.TypeCode)
CanReadUnit() just wraps UnitPermission(), and templates/org/menu.tmpl shows the tabs only {{if .CanReadPackages}} etc. All three are false, so all three tabs vanish. Repositories stays because it uses repo-level visibility, not this function.
404s — reqUnitAccess in routers/web/web.go, used on /-/code and /-/projects:
if ctx.Org.Organization.UnitPermission(ctx, ctx.Doer, unitType) < accessMode {
ctx.NotFound(nil)
}
Packages still loads, because that route uses a different guard, determineAccessMode() in services/context/package.go, which handles limited correctly:
if accessMode == perm.AccessModeNone && organization.HasOrgOrUserVisible(ctx, pkgOwner, doer) {
accessMode = perm.AccessModeRead
}
So the page is served, but the tab linking to it is hidden. UnitPermission() is the only place that checks IsPublic() instead of HasOrgOrUserVisible().
How are you running Gitea?
Official gitea/gitea Docker image running on Kubernetes managed by Rancher, with PostgreSQL as the database.
Gitea Version
1.27.0
What happened?
An organization set to Limited ("Visible only to authenticated users") shows a signed-in non-member only the Repositories tab. Packages, Code and Projects are gone from the org menu. Packages still loads if the URL is entered directly, despite the hidden tab; Code and Projects return 404. The same organization set to Public shows all of these tabs to everyone, including anonymous visitors.
Expected behaviour:
limitedshould show the same tabs aspublic, with the audience narrowed to authenticated users.Root cause
Organization.UnitPermission()inmodels/organization/org.go:A signed-in non-member has no teams in the org, so it skips the first block.
IsPublic()is a strict== VisibleTypePublic, solimitedfalls through toAccessModeNone.That one check causes both symptoms:
Hidden tabs —
services/context/org.go:CanReadUnit()just wrapsUnitPermission(), andtemplates/org/menu.tmplshows the tabs only{{if .CanReadPackages}}etc. All three are false, so all three tabs vanish. Repositories stays because it uses repo-level visibility, not this function.404s —
reqUnitAccessinrouters/web/web.go, used on/-/codeand/-/projects:Packages still loads, because that route uses a different guard,
determineAccessMode()inservices/context/package.go, which handleslimitedcorrectly:So the page is served, but the tab linking to it is hidden.
UnitPermission()is the only place that checksIsPublic()instead ofHasOrgOrUserVisible().How are you running Gitea?
Official
gitea/giteaDocker image running on Kubernetes managed by Rancher, with PostgreSQL as the database.