diff --git a/models/perm/access/repo_permission.go b/models/perm/access/repo_permission.go index c14d5e9341..3168b90a5f 100644 --- a/models/perm/access/repo_permission.go +++ b/models/perm/access/repo_permission.go @@ -405,8 +405,11 @@ func GetIndividualUserRepoPermission(ctx context.Context, repo *repo_model.Repos perm.units = repo.Units // anonymous user visit private repo. + // Still process unit-level anonymous access so that units with + // AnonymousAccessMode (e.g. public wiki on a private repo) are visible. if user == nil && repo.IsPrivate { perm.AccessMode = perm_model.AccessModeNone + finalProcessRepoUnitPermission(user, &perm) return perm, nil } diff --git a/models/repo/repo_list.go b/models/repo/repo_list.go index 3903a56b14..99c547bc17 100644 --- a/models/repo/repo_list.go +++ b/models/repo/repo_list.go @@ -673,6 +673,14 @@ func AccessibleRepositoryCondition(user *user_model.User, unitType unit.Type) bu cond = userAllPublicRepoCond(cond, orgVisibilityLimit) } + // Include private repos that have at least one unit with public anonymous access. + // This enables discovery of repos where e.g. wiki or releases are public. + cond = cond.Or(builder.In("`repository`.id", + builder.Select("repo_id").From("repo_unit").Where( + builder.Gt{"anonymous_access_mode": 0}, + ), + )) + if user != nil { // 2. Be able to see all repositories that we have unit independent access to // 3. Be able to see all repositories through team membership(s) diff --git a/routers/web/repo/githttp.go b/routers/web/repo/githttp.go index 2e2c3f3b01..403c5d89b7 100644 --- a/routers/web/repo/githttp.go +++ b/routers/web/repo/githttp.go @@ -128,7 +128,15 @@ func httpBase(ctx *context.Context, optGitService ...string) *serviceHandler { } // Only public pull don't need auth. - isPublicPull := repoExist && !repo.IsPrivate && isPull + // For private repos, also allow anonymous pull if the specific unit + // (code or wiki) has AnonymousAccessMode >= Read. + isPublicPull := repoExist && isPull && !repo.IsPrivate + if repoExist && isPull && repo.IsPrivate { + repoUnit := repo.MustGetUnit(ctx, unitType) + if repoUnit.AnonymousAccessMode >= perm.AccessModeRead { + isPublicPull = true + } + } askAuth := !isPublicPull || setting.Service.RequireSignInViewStrict // don't allow anonymous pulls if organization is not public