Template
1
0
Fork 0
mirror of https://codeberg.org/forgejo/forgejo synced 2024-11-28 20:56:11 +01:00

fix(hook): repo admins are wrongly denied the right to force merge

The right to force merge is uses the wrong predicate and
applies to instance admins:

  ctx.user.IsAdmin

It must apply to repository admins and use the following predicate:

 ctx.userPerm.IsAdmin()

This regression is from the ApplyToAdmins implementation in
79b7089360.

Fixes: https://codeberg.org/forgejo/forgejo/issues/3780
This commit is contained in:
Earl Warren 2024-06-01 10:45:20 +02:00
parent 05f0007437
commit 09f3518069
No known key found for this signature in database
GPG key ID: 0579CB2928A78A00
3 changed files with 13 additions and 8 deletions

View file

@ -0,0 +1 @@
- repository admins are always denied the right to force merge and instance admins are subject to restrictions to merge that must only apply to repository admins

View file

@ -404,7 +404,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
// It's not allowed t overwrite protected files. Unless if the user is an // It's not allowed t overwrite protected files. Unless if the user is an
// admin and the protected branch rule doesn't apply to admins. // admin and the protected branch rule doesn't apply to admins.
if changedProtectedfiles && (!ctx.user.IsAdmin || protectBranch.ApplyToAdmins) { if changedProtectedfiles && (!ctx.userPerm.IsAdmin() || protectBranch.ApplyToAdmins) {
log.Warn("Forbidden: Branch: %s in %-v is protected from changing file %s", branchName, repo, protectedFilePath) log.Warn("Forbidden: Branch: %s in %-v is protected from changing file %s", branchName, repo, protectedFilePath)
ctx.JSON(http.StatusForbidden, private.Response{ ctx.JSON(http.StatusForbidden, private.Response{
UserMsg: fmt.Sprintf("branch %s is protected from changing file %s", branchName, protectedFilePath), UserMsg: fmt.Sprintf("branch %s is protected from changing file %s", branchName, protectedFilePath),
@ -416,7 +416,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
if pb, err := pull_service.CheckPullBranchProtections(ctx, pr, true); err != nil { if pb, err := pull_service.CheckPullBranchProtections(ctx, pr, true); err != nil {
if models.IsErrDisallowedToMerge(err) { if models.IsErrDisallowedToMerge(err) {
// Allow this if the rule doesn't apply to admins and the user is an admin. // Allow this if the rule doesn't apply to admins and the user is an admin.
if ctx.user.IsAdmin && !pb.ApplyToAdmins { if ctx.userPerm.IsAdmin() && !pb.ApplyToAdmins {
return return
} }
log.Warn("Forbidden: User %d is not allowed push to protected branch %s in %-v and pr #%d is not ready to be merged: %s", ctx.opts.UserID, branchName, repo, pr.Index, err.Error()) log.Warn("Forbidden: User %d is not allowed push to protected branch %s in %-v and pr #%d is not ready to be merged: %s", ctx.opts.UserID, branchName, repo, pr.Index, err.Error())

View file

@ -119,12 +119,16 @@ func CheckPullMergeable(stdCtx context.Context, doer *user_model.User, perm *acc
// * if the doer is admin, they could skip the branch protection check, // * if the doer is admin, they could skip the branch protection check,
// if that's allowed by the protected branch rule. // if that's allowed by the protected branch rule.
if adminSkipProtectionCheck && !pb.ApplyToAdmins { if adminSkipProtectionCheck {
if isRepoAdmin, errCheckAdmin := access_model.IsUserRepoAdmin(ctx, pr.BaseRepo, doer); errCheckAdmin != nil { if doer.IsAdmin {
log.Error("Unable to check if %-v is a repo admin in %-v: %v", doer, pr.BaseRepo, errCheckAdmin) err = nil // instance admin can skip the check, so clear the error
return errCheckAdmin } else if !pb.ApplyToAdmins {
} else if isRepoAdmin { if isRepoAdmin, errCheckAdmin := access_model.IsUserRepoAdmin(ctx, pr.BaseRepo, doer); errCheckAdmin != nil {
err = nil // repo admin can skip the check, so clear the error log.Error("Unable to check if %-v is a repo admin in %-v: %v", doer, pr.BaseRepo, errCheckAdmin)
return errCheckAdmin
} else if isRepoAdmin {
err = nil // repo admin can skip the check, so clear the error
}
} }
} }