Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 8 additions & 11 deletions services/pull/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func Update(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.

// IsUserAllowedToUpdate check if user is allowed to update PR with given permissions and branch protections
// update PR means send new commits to PR head branch from base branch
func IsUserAllowedToUpdate(ctx context.Context, pull *issues_model.PullRequest, user *user_model.User) (mergeAllowed, rebaseAllowed bool, err error) {
func IsUserAllowedToUpdate(ctx context.Context, pull *issues_model.PullRequest, user *user_model.User) (pushAllowed, rebaseAllowed bool, err error) {
if pull.Flow == issues_model.PullRequestFlowAGit {
return false, false, nil
}
Expand All @@ -116,6 +116,7 @@ func IsUserAllowedToUpdate(ctx context.Context, pull *issues_model.PullRequest,
}
return false, false, err
}
pushAllowed = headRepoPerm.CanWrite(unit.TypeCode)

if err := pull.LoadBaseRepo(ctx); err != nil {
return false, false, err
Expand Down Expand Up @@ -143,20 +144,16 @@ func IsUserAllowedToUpdate(ctx context.Context, pull *issues_model.PullRequest,
if pb != nil {
pb.Repo = pull.HeadRepo
rebaseAllowed = rebaseAllowed && pb.CanUserForcePush(ctx, user)
pushAllowed = pb.CanUserPush(ctx, user)
}
}

// 3. check whether user has write access to head branch
// 3. check whether user has write access to base branch
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment is not right

baseRepoPerm, err := access_model.GetUserRepoPermission(ctx, pull.BaseRepo, user)
if err != nil {
return false, false, err
}

mergeAllowed, err = isUserAllowedToMergeInRepoBranch(ctx, pull.HeadRepoID, pull.HeadBranch, headRepoPerm, user)
if err != nil {
return false, false, err
}

// 4. if the pull creator allows maintainer to edit, it means the write permissions of the head branch has been
// granted to the user with write permission of the base repository
if pull.AllowMaintainerEdit {
Expand All @@ -165,13 +162,13 @@ func IsUserAllowedToUpdate(ctx context.Context, pull *issues_model.PullRequest,
return false, false, err
}

mergeAllowed = mergeAllowed || mergeAllowedMaintainer
pushAllowed = pushAllowed || mergeAllowedMaintainer
}

// if merge is not allowed, rebase is also not allowed
rebaseAllowed = rebaseAllowed && mergeAllowed
// if push is not allowed, rebase is also not allowed
rebaseAllowed = rebaseAllowed && pushAllowed

return mergeAllowed, rebaseAllowed, nil
return pushAllowed, rebaseAllowed, nil
}

func syncCommitDivergence(ctx context.Context, pr *issues_model.PullRequest) error {
Expand Down
39 changes: 39 additions & 0 deletions services/pull/update_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package pull

import (
"testing"

"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"

"github.com/stretchr/testify/assert"
)

func TestIsUserAllowedToUpdateRespectsProtectedBranch(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())

pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2})
assert.NoError(t, pr.LoadHeadRepo(t.Context()))

user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})

protectedBranch := &git_model.ProtectedBranch{
RepoID: pr.HeadRepoID,
RuleName: pr.HeadBranch,
CanPush: false,
CanForcePush: false,
}
_, err := db.GetEngine(t.Context()).Insert(protectedBranch)
assert.NoError(t, err)

pushAllowed, rebaseAllowed, err := IsUserAllowedToUpdate(t.Context(), pr, user)
assert.NoError(t, err)
assert.False(t, pushAllowed)
assert.False(t, rebaseAllowed)
}
Loading