Skip to content

Commit 2e5d360

Browse files
committed
Merge branch 'lunny/fix_maintainer_edit_check' into lunny/fix_maintainer_edit_check2
2 parents 397930d + c7ef602 commit 2e5d360

File tree

9 files changed

+78
-31
lines changed

9 files changed

+78
-31
lines changed

models/issues/pull_list.go

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,37 +50,38 @@ func listPullRequestStatement(ctx context.Context, baseRepoID int64, opts *PullR
5050
}
5151

5252
// GetUnmergedPullRequestsByHeadInfo returns all pull requests that are open and has not been merged
53-
func GetUnmergedPullRequestsByHeadInfo(ctx context.Context, repoID int64, branch string) ([]*PullRequest, error) {
53+
func GetUnmergedPullRequestsByHeadInfo(ctx context.Context, repoID int64, branch string) (PullRequestList, error) {
5454
prs := make([]*PullRequest, 0, 2)
5555
sess := db.GetEngine(ctx).
5656
Join("INNER", "issue", "issue.id = pull_request.issue_id").
5757
Where("head_repo_id = ? AND head_branch = ? AND has_merged = ? AND issue.is_closed = ? AND flow = ?", repoID, branch, false, false, PullRequestFlowGithub)
5858
return prs, sess.Find(&prs)
5959
}
6060

61-
// CanMaintainerWriteToBranch check whether user is a maintainer and could write to the branch
62-
func CanMaintainerWriteToBranch(ctx context.Context, p access_model.Permission, branch string, user *user_model.User) bool {
61+
func CanUserWriteToBranch(ctx context.Context, p access_model.Permission, headRepoID int64, branch string, user *user_model.User) bool {
6362
if p.CanWrite(unit.TypeCode) {
6463
return true
6564
}
6665

67-
// the code below depends on units to get the repository ID, not ideal but just keep it for now
68-
firstUnitRepoID := p.GetFirstUnitRepoID()
69-
if firstUnitRepoID == 0 {
66+
return canMaintainerWriteToHeadBranch(ctx, headRepoID, branch, user)
67+
}
68+
69+
// canMaintainerWriteToHeadBranch check whether user is a maintainer and could write to the branch
70+
func canMaintainerWriteToHeadBranch(ctx context.Context, headRepoID int64, branch string, user *user_model.User) bool {
71+
prs, err := GetUnmergedPullRequestsByHeadInfo(ctx, headRepoID, branch)
72+
if err != nil {
73+
log.Error("GetUnmergedPullRequestsByHeadInfo: %v", err)
7074
return false
7175
}
7276

73-
prs, err := GetUnmergedPullRequestsByHeadInfo(ctx, firstUnitRepoID, branch)
74-
if err != nil {
77+
if err := prs.LoadRepositories(ctx); err != nil {
78+
log.Error("LoadBaseRepos: %v", err)
7579
return false
7680
}
7781

82+
// user can write to the branch once one pull request allowed the user edit the branch
7883
for _, pr := range prs {
7984
if pr.AllowMaintainerEdit {
80-
err = pr.LoadBaseRepo(ctx)
81-
if err != nil {
82-
continue
83-
}
8485
prPerm, err := access_model.GetUserRepoPermission(ctx, pr.BaseRepo, user)
8586
if err != nil {
8687
continue

models/perm/access/repo_permission.go

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,6 @@ func (p *Permission) HasUnits() bool {
6363
return len(p.units) > 0
6464
}
6565

66-
// GetFirstUnitRepoID returns the repo ID of the first unit, it is a fragile design and should NOT be used anymore
67-
// deprecated
68-
func (p *Permission) GetFirstUnitRepoID() int64 {
69-
if len(p.units) > 0 {
70-
return p.units[0].RepoID
71-
}
72-
return 0
73-
}
74-
7566
// UnitAccessMode returns current user access mode to the specify unit of the repository
7667
// It also considers "everyone access mode"
7768
func (p *Permission) UnitAccessMode(unitType unit.Type) perm_model.AccessMode {

routers/private/hook_pre_receive.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func (ctx *preReceiveContext) CanWriteCode() bool {
5555
if !ctx.loadPusherAndPermission() {
5656
return false
5757
}
58-
ctx.canWriteCode = issues_model.CanMaintainerWriteToBranch(ctx, ctx.userPerm, ctx.branchName, ctx.user) || ctx.deployKeyAccessMode >= perm_model.AccessModeWrite
58+
ctx.canWriteCode = issues_model.CanUserWriteToBranch(ctx, ctx.userPerm, ctx.Repo.Repository.ID, ctx.branchName, ctx.user) || ctx.deployKeyAccessMode >= perm_model.AccessModeWrite
5959
ctx.checkedCanWriteCode = true
6060
}
6161
return ctx.canWriteCode

routers/web/repo/pull.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -871,7 +871,7 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi
871871
return
872872
}
873873

874-
if perm.CanWrite(unit.TypeCode) || issues_model.CanMaintainerWriteToBranch(ctx, perm, pull.HeadBranch, ctx.Doer) {
874+
if issues_model.CanUserWriteToBranch(ctx, perm, pull.HeadRepoID, pull.HeadBranch, ctx.Doer) {
875875
ctx.Data["CanEditFile"] = true
876876
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.edit_this_file")
877877
ctx.Data["HeadRepoLink"] = pull.HeadRepo.Link()

services/context/repo.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ type Repository struct {
7070

7171
// CanWriteToBranch checks if the branch is writable by the user
7272
func (r *Repository) CanWriteToBranch(ctx context.Context, user *user_model.User, branch string) bool {
73-
return issues_model.CanMaintainerWriteToBranch(ctx, r.Permission, branch, user)
73+
return issues_model.CanUserWriteToBranch(ctx, r.Permission, r.Repository.ID, branch, user)
7474
}
7575

7676
// CanEnableEditor returns true if repository is editable and user has proper access level.

services/convert/convert.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func ToBranch(ctx context.Context, repo *repo_model.Repository, branchName strin
6767
if err != nil {
6868
return nil, err
6969
}
70-
canPush = issues_model.CanMaintainerWriteToBranch(ctx, perms, branchName, user)
70+
canPush = issues_model.CanUserWriteToBranch(ctx, perms, repo.ID, branchName, user)
7171
}
7272

7373
return &api.Branch{

services/pull/pull.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -331,11 +331,10 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string,
331331
}
332332

333333
if isSync {
334-
requests := issues_model.PullRequestList(prs)
335-
if err = requests.LoadAttributes(ctx); err != nil {
334+
if err = prs.LoadAttributes(ctx); err != nil {
336335
log.Error("PullRequestList.LoadAttributes: %v", err)
337336
}
338-
if invalidationErr := checkForInvalidation(ctx, requests, repoID, doer, branch); invalidationErr != nil {
337+
if invalidationErr := checkForInvalidation(ctx, prs, repoID, doer, branch); invalidationErr != nil {
339338
log.Error("checkForInvalidation: %v", invalidationErr)
340339
}
341340
if err == nil {
@@ -627,7 +626,7 @@ func CloseBranchPulls(ctx context.Context, doer *user_model.User, repoID int64,
627626
}
628627

629628
prs = append(prs, prs2...)
630-
if err := issues_model.PullRequestList(prs).LoadAttributes(ctx); err != nil {
629+
if err := prs.LoadAttributes(ctx); err != nil {
631630
return err
632631
}
633632

@@ -657,7 +656,7 @@ func CloseRepoBranchesPulls(ctx context.Context, doer *user_model.User, repo *re
657656
return err
658657
}
659658

660-
if err = issues_model.PullRequestList(prs).LoadAttributes(ctx); err != nil {
659+
if err = prs.LoadAttributes(ctx); err != nil {
661660
return err
662661
}
663662

services/pull/review.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
issues_model "code.gitea.io/gitea/models/issues"
1717
repo_model "code.gitea.io/gitea/models/repo"
1818
user_model "code.gitea.io/gitea/models/user"
19+
"code.gitea.io/gitea/modules/container"
1920
"code.gitea.io/gitea/modules/git"
2021
"code.gitea.io/gitea/modules/gitrepo"
2122
"code.gitea.io/gitea/modules/log"
@@ -71,7 +72,10 @@ func InvalidateCodeComments(ctx context.Context, prs issues_model.PullRequestLis
7172
if len(prs) == 0 {
7273
return nil
7374
}
74-
issueIDs := prs.GetIssueIDs()
75+
76+
issueIDs := container.FilterSlice(prs, func(pr *issues_model.PullRequest) (int64, bool) {
77+
return pr.IssueID, true
78+
})
7579

7680
codeComments, err := db.Find[issues_model.Comment](ctx, issues_model.FindCommentsOptions{
7781
ListOptions: db.ListOptionsAll,
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright 2024 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package integration
5+
6+
import (
7+
"net/url"
8+
"testing"
9+
10+
"code.gitea.io/gitea/models/db"
11+
issues_model "code.gitea.io/gitea/models/issues"
12+
repo_model "code.gitea.io/gitea/models/repo"
13+
"code.gitea.io/gitea/models/unittest"
14+
user_model "code.gitea.io/gitea/models/user"
15+
pull_service "code.gitea.io/gitea/services/pull"
16+
17+
"github.com/stretchr/testify/assert"
18+
)
19+
20+
func TestPullAllowMaintainerEdit(t *testing.T) {
21+
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
22+
// create a pull request
23+
session := loginUser(t, "user1")
24+
user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
25+
forkedName := "repo1"
26+
testRepoFork(t, session, "org3", "repo5", "user1", forkedName, "master")
27+
defer func() {
28+
testDeleteRepository(t, session, "user1", forkedName)
29+
}()
30+
testEditFile(t, session, "user1", forkedName, "master", "README.md", "Hello, World (Edited)\n")
31+
testPullCreate(t, session, "user1", forkedName, false, "master", "master", "Indexer notifier test pull")
32+
33+
baseRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "org3", Name: "repo5"})
34+
forkedRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user1", Name: forkedName})
35+
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{
36+
BaseRepoID: baseRepo.ID,
37+
BaseBranch: "master",
38+
HeadRepoID: forkedRepo.ID,
39+
HeadBranch: "master",
40+
})
41+
assert.False(t, pr.AllowMaintainerEdit)
42+
assert.NoError(t, pr.LoadIssue(db.DefaultContext))
43+
44+
// allow org3's member to edit the branch's files
45+
err := pull_service.SetAllowEdits(db.DefaultContext, user1, pr, true)
46+
assert.NoError(t, err)
47+
48+
// user2 is in org3 team
49+
session = loginUser(t, "user2")
50+
testEditFile(t, session, "user1", forkedName, "master", "README.md", "Hello, World (Edited)\n")
51+
})
52+
}

0 commit comments

Comments
 (0)