refactor: use named Permission field in Repository struct instead of anonymous embedding (#37441)

The `Repository` struct in `services/context/repo.go` embedded
`access_model.Permission` anonymously, causing all permission methods to
be promoted directly onto `Repository`. This made it unclear at call
sites whether a method belonged to `Repository` itself or to its
embedded `Permission`.

### Changes

- **`services/context/repo.go`**: Replace anonymous
`access_model.Permission` with named field `Permission
access_model.Permission`
- **49 files** updated to route permission method calls through the
named field:

```go
// Before
ctx.Repo.IsAdmin()
ctx.Repo.CanWrite(unit.TypeCode)
ctx.Repo.CanReadIssuesOrPulls(isPull)
slices.ContainsFunc(unitTypes, ctx.Repo.CanWrite)

// After
ctx.Repo.Permission.IsAdmin()
ctx.Repo.Permission.CanWrite(unit.TypeCode)
ctx.Repo.Permission.CanReadIssuesOrPulls(isPull)
slices.ContainsFunc(unitTypes, ctx.Repo.Permission.CanWrite)
```

Methods defined directly on `*Repository` (`CanWriteToBranch`,
`CanCreateBranch`, etc.) are unchanged.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: wxiaoguang <2114189+wxiaoguang@users.noreply.github.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Nicolas <bircni@icloud.com>
This commit is contained in:
Copilot
2026-04-26 20:18:28 +00:00
committed by GitHub
parent 55c9b936cb
commit 45b4fffae4
49 changed files with 169 additions and 171 deletions

View File

@@ -340,10 +340,10 @@ func (ctx *APIContext) IsUserSiteAdmin() bool {
// IsUserRepoAdmin returns true if current user is admin in current repo
func (ctx *APIContext) IsUserRepoAdmin() bool {
return ctx.Repo.IsAdmin()
return ctx.Repo.Permission.IsAdmin()
}
// IsUserRepoWriter returns true if current user has "write" privilege in current repo
func (ctx *APIContext) IsUserRepoWriter(unitTypes []unit.Type) bool {
return slices.ContainsFunc(unitTypes, ctx.Repo.CanWrite)
return slices.ContainsFunc(unitTypes, ctx.Repo.Permission.CanWrite)
}

View File

@@ -15,7 +15,7 @@ import (
// RequireRepoAdmin returns a middleware for requiring repository admin permission
func RequireRepoAdmin() func(ctx *Context) {
return func(ctx *Context) {
if !ctx.IsSigned || !ctx.Repo.IsAdmin() {
if !ctx.IsSigned || !ctx.Repo.Permission.IsAdmin() {
ctx.NotFound(nil)
return
}
@@ -35,7 +35,7 @@ func CanWriteToBranch() func(ctx *Context) {
// RequireUnitWriter returns a middleware for requiring repository write to one of the unit permission
func RequireUnitWriter(unitTypes ...unit.Type) func(ctx *Context) {
return func(ctx *Context) {
if slices.ContainsFunc(unitTypes, ctx.Repo.CanWrite) {
if slices.ContainsFunc(unitTypes, ctx.Repo.Permission.CanWrite) {
return
}
ctx.NotFound(nil)
@@ -46,7 +46,7 @@ func RequireUnitWriter(unitTypes ...unit.Type) func(ctx *Context) {
func RequireUnitReader(unitTypes ...unit.Type) func(ctx *Context) {
return func(ctx *Context) {
for _, unitType := range unitTypes {
if ctx.Repo.CanRead(unitType) {
if ctx.Repo.Permission.CanRead(unitType) {
return
}
if unitType == unit.TypeCode && canWriteAsMaintainer(ctx) {

View File

@@ -58,7 +58,7 @@ func (prc *PullRequestContext) CanCreateNewPull() bool {
ctx := prc.ctx
// People who have push access or have forked repository can propose a new pull request.
can := prc.baseRepo.CanContentChange() &&
(ctx.Repo.CanWrite(unit_model.TypeCode) || (ctx.IsSigned && repo_model.HasForkedRepo(ctx, ctx.Doer.ID, ctx.Repo.Repository.ID)))
(ctx.Repo.Permission.CanWrite(unit_model.TypeCode) || (ctx.IsSigned && repo_model.HasForkedRepo(ctx, ctx.Doer.ID, ctx.Repo.Repository.ID)))
prc.canCreateNewPull = &can
return can
}
@@ -81,7 +81,7 @@ func (prc *PullRequestContext) DefaultTargetBranch() string {
// Repository contains information to operate a repository
type Repository struct {
access_model.Permission
Permission access_model.Permission
Repository *repo_model.Repository
Owner *user_model.User
@@ -597,7 +597,7 @@ func repoAssignmentPrepareTemplateData(ctx *Context, data *repoAssignmentPrepare
}
ctx.Data["NumReleases"], err = db.Count[repo_model.Release](ctx, repo_model.FindReleasesOptions{
// only show draft releases for users who can write, read-only users shouldn't see draft releases.
IncludeDrafts: ctx.Repo.CanWrite(unit_model.TypeReleases),
IncludeDrafts: ctx.Repo.Permission.CanWrite(unit_model.TypeReleases),
RepoID: ctx.Repo.Repository.ID,
})
if err != nil {
@@ -609,10 +609,10 @@ func repoAssignmentPrepareTemplateData(ctx *Context, data *repoAssignmentPrepare
ctx.Data["PageTitleCommon"] = repo.Name + " - " + setting.AppName
ctx.Data["Repository"] = repo
ctx.Data["Owner"] = ctx.Repo.Repository.Owner
ctx.Data["CanWriteCode"] = ctx.Repo.CanWrite(unit_model.TypeCode)
ctx.Data["CanWriteIssues"] = ctx.Repo.CanWrite(unit_model.TypeIssues)
ctx.Data["CanWritePulls"] = ctx.Repo.CanWrite(unit_model.TypePullRequests)
ctx.Data["CanWriteActions"] = ctx.Repo.CanWrite(unit_model.TypeActions)
ctx.Data["CanWriteCode"] = ctx.Repo.Permission.CanWrite(unit_model.TypeCode)
ctx.Data["CanWriteIssues"] = ctx.Repo.Permission.CanWrite(unit_model.TypeIssues)
ctx.Data["CanWritePulls"] = ctx.Repo.Permission.CanWrite(unit_model.TypePullRequests)
ctx.Data["CanWriteActions"] = ctx.Repo.Permission.CanWrite(unit_model.TypeActions)
canSignedUserFork, err := repo_module.CanUserForkRepo(ctx, ctx.Doer, ctx.Repo.Repository)
if err != nil {