Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support public code/issue access for private repositories #33127

Merged
merged 10 commits into from
Jan 14, 2025
47 changes: 32 additions & 15 deletions models/perm/access/repo_permission.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,14 @@ func (p *Permission) LogString() string {
return fmt.Sprintf(format, args...)
}

func applyEveryoneRepoPermission(user *user_model.User, perm *Permission) {
func finalProcessRepoUnitPermission(user *user_model.User, perm *Permission) {
if user == nil || user.ID <= 0 {
// for anonymous access, it could be:
// AccessMode is None or Read, units has repo units, unitModes is nil
return
}

// apply everyone access permissions
for _, u := range perm.units {
if u.EveryoneAccessMode >= perm_model.AccessModeRead && u.EveryoneAccessMode > perm.everyoneAccessMode[u.Type] {
if perm.everyoneAccessMode == nil {
Expand All @@ -187,17 +191,40 @@ func applyEveryoneRepoPermission(user *user_model.User, perm *Permission) {
perm.everyoneAccessMode[u.Type] = u.EveryoneAccessMode
}
}

if perm.unitsMode == nil {
// if unitsMode is not set, then it means that the default p.AccessMode applies to all units
return
}

// remove no permission units
origPermUnits := perm.units
perm.units = make([]*repo_model.RepoUnit, 0, len(perm.units))
for _, u := range origPermUnits {
shouldKeep := false
for t := range perm.unitsMode {
if shouldKeep = u.Type == t; shouldKeep {
break
}
}
for t := range perm.everyoneAccessMode {
if shouldKeep = shouldKeep || u.Type == t; shouldKeep {
break
}
}
if shouldKeep {
perm.units = append(perm.units, u)
}
}
}

// GetUserRepoPermission returns the user permissions to the repository
func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, user *user_model.User) (perm Permission, err error) {
defer func() {
if err == nil {
applyEveryoneRepoPermission(user, &perm)
}
if log.IsTrace() {
log.Trace("Permission Loaded for user %-v in repo %-v, permissions: %-+v", user, repo, perm)
finalProcessRepoUnitPermission(user, &perm)
}
log.Trace("Permission Loaded for user %-v in repo %-v, permissions: %-+v", user, repo, perm)
}()

if err = repo.LoadUnits(ctx); err != nil {
Expand Down Expand Up @@ -294,16 +321,6 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use
}
}

// remove no permission units
perm.units = make([]*repo_model.RepoUnit, 0, len(repo.Units))
for t := range perm.unitsMode {
for _, u := range repo.Units {
if u.Type == t {
perm.units = append(perm.units, u)
}
}
}

return perm, err
}

Expand Down
12 changes: 7 additions & 5 deletions models/perm/access/repo_permission_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func TestApplyEveryoneRepoPermission(t *testing.T) {
{Type: unit.TypeWiki, EveryoneAccessMode: perm_model.AccessModeRead},
},
}
applyEveryoneRepoPermission(nil, &perm)
finalProcessRepoUnitPermission(nil, &perm)
assert.False(t, perm.CanRead(unit.TypeWiki))

perm = Permission{
Expand All @@ -59,7 +59,7 @@ func TestApplyEveryoneRepoPermission(t *testing.T) {
{Type: unit.TypeWiki, EveryoneAccessMode: perm_model.AccessModeRead},
},
}
applyEveryoneRepoPermission(&user_model.User{ID: 0}, &perm)
finalProcessRepoUnitPermission(&user_model.User{ID: 0}, &perm)
assert.False(t, perm.CanRead(unit.TypeWiki))

perm = Permission{
Expand All @@ -68,7 +68,7 @@ func TestApplyEveryoneRepoPermission(t *testing.T) {
{Type: unit.TypeWiki, EveryoneAccessMode: perm_model.AccessModeRead},
},
}
applyEveryoneRepoPermission(&user_model.User{ID: 1}, &perm)
finalProcessRepoUnitPermission(&user_model.User{ID: 1}, &perm)
assert.True(t, perm.CanRead(unit.TypeWiki))

perm = Permission{
Expand All @@ -77,20 +77,22 @@ func TestApplyEveryoneRepoPermission(t *testing.T) {
{Type: unit.TypeWiki, EveryoneAccessMode: perm_model.AccessModeRead},
},
}
applyEveryoneRepoPermission(&user_model.User{ID: 1}, &perm)
finalProcessRepoUnitPermission(&user_model.User{ID: 1}, &perm)
// it should work the same as "EveryoneAccessMode: none" because the default AccessMode should be applied to units
assert.True(t, perm.CanWrite(unit.TypeWiki))

perm = Permission{
units: []*repo_model.RepoUnit{
{Type: unit.TypeCode}, // will be removed
{Type: unit.TypeWiki, EveryoneAccessMode: perm_model.AccessModeRead},
},
unitsMode: map[unit.Type]perm_model.AccessMode{
unit.TypeWiki: perm_model.AccessModeWrite,
},
}
applyEveryoneRepoPermission(&user_model.User{ID: 1}, &perm)
finalProcessRepoUnitPermission(&user_model.User{ID: 1}, &perm)
assert.True(t, perm.CanWrite(unit.TypeWiki))
assert.Len(t, perm.units, 1)
}

func TestUnitAccessMode(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2158,7 +2158,7 @@ settings.advanced_settings = Advanced Settings
settings.wiki_desc = Enable Repository Wiki
settings.use_internal_wiki = Use Built-In Wiki
settings.default_wiki_branch_name = Default Wiki Branch Name
settings.default_wiki_everyone_access = Default Access Permission for signed-in users:
settings.default_permission_everyone_access = Default access permission for all signed-in users:
settings.failed_to_change_default_wiki_branch = Failed to change the default wiki branch.
settings.use_external_wiki = Use External Wiki
settings.external_wiki_url = External Wiki URL
Expand Down
10 changes: 3 additions & 7 deletions routers/web/repo/issue_poster.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,9 @@ type userSearchResponse struct {
Results []*userSearchInfo `json:"results"`
}

// IssuePosters get posters for current repo's issues/pull requests
func IssuePosters(ctx *context.Context) {
issuePosters(ctx, false)
}

func PullPosters(ctx *context.Context) {
issuePosters(ctx, true)
func IssuePullPosters(ctx *context.Context) {
isPullList := ctx.PathParam("type") == "pulls"
issuePosters(ctx, isPullList)
}

func issuePosters(ctx *context.Context, isPullList bool) {
Expand Down
17 changes: 14 additions & 3 deletions routers/web/repo/setting/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ const (
tplDeployKeys templates.TplName = "repo/settings/deploy_keys"
)

func parseEveryoneAccessMode(permission string, allowed ...perm.AccessMode) perm.AccessMode {
// if site admin forces repositories to be private, then do not allow any other access mode,
// otherwise the "force private" setting would be bypassed
if setting.Repository.ForcePrivate {
return perm.AccessModeNone
}
return perm.ParseAccessMode(permission, allowed...)
}

// SettingsCtxData is a middleware that sets all the general context data for the
// settings template.
func SettingsCtxData(ctx *context.Context) {
Expand Down Expand Up @@ -447,8 +456,9 @@ func SettingsPost(ctx *context.Context) {

if form.EnableCode && !unit_model.TypeCode.UnitGlobalDisabled() {
units = append(units, repo_model.RepoUnit{
RepoID: repo.ID,
Type: unit_model.TypeCode,
RepoID: repo.ID,
Type: unit_model.TypeCode,
EveryoneAccessMode: parseEveryoneAccessMode(form.DefaultCodeEveryoneAccess, perm.AccessModeNone, perm.AccessModeRead),
})
} else if !unit_model.TypeCode.UnitGlobalDisabled() {
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeCode)
Expand All @@ -474,7 +484,7 @@ func SettingsPost(ctx *context.Context) {
RepoID: repo.ID,
Type: unit_model.TypeWiki,
Config: new(repo_model.UnitConfig),
EveryoneAccessMode: perm.ParseAccessMode(form.DefaultWikiEveryoneAccess, perm.AccessModeNone, perm.AccessModeRead, perm.AccessModeWrite),
EveryoneAccessMode: parseEveryoneAccessMode(form.DefaultWikiEveryoneAccess, perm.AccessModeNone, perm.AccessModeRead, perm.AccessModeWrite),
})
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeExternalWiki)
} else {
Expand Down Expand Up @@ -524,6 +534,7 @@ func SettingsPost(ctx *context.Context) {
AllowOnlyContributorsToTrackTime: form.AllowOnlyContributorsToTrackTime,
EnableDependencies: form.EnableIssueDependencies,
},
EveryoneAccessMode: parseEveryoneAccessMode(form.DefaultIssuesEveryoneAccess, perm.AccessModeNone, perm.AccessModeRead),
})
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeExternalTracker)
} else {
Expand Down
Loading
Loading