aboutsummaryrefslogtreecommitdiff
path: root/services
diff options
context:
space:
mode:
authorAnthony Wang2023-03-04 00:03:38 +0000
committerAnthony Wang2023-03-04 00:03:38 +0000
commitb4640101f3c8938ed689743606a79601201141ca (patch)
tree8469fc5ef817560db646837b41417d50e2f8ebfc /services
parentdc20c2832871f6462990751ea802e14b02bf41b0 (diff)
parent8540fc45b11eff9a73753ca139f8ea5c38509bf5 (diff)
Merge remote-tracking branch 'origin/main' into forgejo-federation
Diffstat (limited to 'services')
-rw-r--r--services/actions/notifier_helper.go48
-rw-r--r--services/auth/source/oauth2/jwtsigningkey.go2
-rw-r--r--services/automerge/automerge.go2
-rw-r--r--services/convert/mirror.go1
-rw-r--r--services/forms/repo_form.go3
-rw-r--r--services/lfs/server.go2
-rw-r--r--services/mailer/token/token.go3
-rw-r--r--services/pull/check.go37
-rw-r--r--services/pull/merge.go4
-rw-r--r--services/repository/files/tree.go5
-rw-r--r--services/webhook/deliver.go2
-rw-r--r--services/webhook/notifier.go7
12 files changed, 94 insertions, 22 deletions
diff --git a/services/actions/notifier_helper.go b/services/actions/notifier_helper.go
index df67d2fa1..ef63b8cf9 100644
--- a/services/actions/notifier_helper.go
+++ b/services/actions/notifier_helper.go
@@ -153,7 +153,7 @@ func notify(ctx context.Context, input *notifyInput) error {
}
for id, content := range workflows {
- run := actions_model.ActionRun{
+ run := &actions_model.ActionRun{
Title: strings.SplitN(commit.CommitMessage, "\n", 2)[0],
RepoID: input.Repo.ID,
OwnerID: input.Repo.OwnerID,
@@ -166,12 +166,19 @@ func notify(ctx context.Context, input *notifyInput) error {
EventPayload: string(p),
Status: actions_model.StatusWaiting,
}
+ if need, err := ifNeedApproval(ctx, run, input.Repo, input.Doer); err != nil {
+ log.Error("check if need approval for repo %d with user %d: %v", input.Repo.ID, input.Doer.ID, err)
+ continue
+ } else {
+ run.NeedApproval = need
+ }
+
jobs, err := jobparser.Parse(content)
if err != nil {
log.Error("jobparser.Parse: %v", err)
continue
}
- if err := actions_model.InsertRun(ctx, &run, jobs); err != nil {
+ if err := actions_model.InsertRun(ctx, run, jobs); err != nil {
log.Error("InsertRun: %v", err)
continue
}
@@ -234,3 +241,40 @@ func notifyPackage(ctx context.Context, sender *user_model.User, pd *packages_mo
}).
Notify(ctx)
}
+
+func ifNeedApproval(ctx context.Context, run *actions_model.ActionRun, repo *repo_model.Repository, user *user_model.User) (bool, error) {
+ // don't need approval if it's not a fork PR
+ if !run.IsForkPullRequest {
+ return false, nil
+ }
+
+ // always need approval if the user is restricted
+ if user.IsRestricted {
+ log.Trace("need approval because user %d is restricted", user.ID)
+ return true, nil
+ }
+
+ // don't need approval if the user can write
+ if perm, err := access_model.GetUserRepoPermission(ctx, repo, user); err != nil {
+ return false, fmt.Errorf("GetUserRepoPermission: %w", err)
+ } else if perm.CanWrite(unit_model.TypeActions) {
+ log.Trace("do not need approval because user %d can write", user.ID)
+ return false, nil
+ }
+
+ // don't need approval if the user has been approved before
+ if count, err := actions_model.CountRuns(ctx, actions_model.FindRunOptions{
+ RepoID: repo.ID,
+ TriggerUserID: user.ID,
+ Approved: true,
+ }); err != nil {
+ return false, fmt.Errorf("CountRuns: %w", err)
+ } else if count > 0 {
+ log.Trace("do not need approval because user %d has been approved before", user.ID)
+ return false, nil
+ }
+
+ // otherwise, need approval
+ log.Trace("need approval because it's the first time user %d triggered actions", user.ID)
+ return true, nil
+}
diff --git a/services/auth/source/oauth2/jwtsigningkey.go b/services/auth/source/oauth2/jwtsigningkey.go
index 93c157437..94feddbf6 100644
--- a/services/auth/source/oauth2/jwtsigningkey.go
+++ b/services/auth/source/oauth2/jwtsigningkey.go
@@ -9,7 +9,6 @@ import (
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
- "crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/pem"
@@ -25,6 +24,7 @@ import (
"code.gitea.io/gitea/modules/util"
"github.com/golang-jwt/jwt/v4"
+ "github.com/minio/sha256-simd"
ini "gopkg.in/ini.v1"
)
diff --git a/services/automerge/automerge.go b/services/automerge/automerge.go
index 74cfb8da8..994604764 100644
--- a/services/automerge/automerge.go
+++ b/services/automerge/automerge.go
@@ -230,7 +230,7 @@ func handlePull(pullID int64, sha string) {
return
}
- if err := pull_service.CheckPullMergable(ctx, doer, &perm, pr, false, false); err != nil {
+ if err := pull_service.CheckPullMergable(ctx, doer, &perm, pr, pull_service.MergeCheckTypeGeneral, false); err != nil {
if errors.Is(pull_service.ErrUserNotAllowedToMerge, err) {
log.Info("%-v was scheduled to automerge by an unauthorized user", pr)
return
diff --git a/services/convert/mirror.go b/services/convert/mirror.go
index 1dcfc9b64..f7a8e17fd 100644
--- a/services/convert/mirror.go
+++ b/services/convert/mirror.go
@@ -24,6 +24,7 @@ func ToPushMirror(pm *repo_model.PushMirror) (*api.PushMirror, error) {
LastUpdateUnix: pm.LastUpdateUnix.FormatLong(),
LastError: pm.LastError,
Interval: pm.Interval.String(),
+ SyncOnCommit: pm.SyncOnCommit,
}, nil
}
diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go
index ff0916f8e..e9645b5ab 100644
--- a/services/forms/repo_form.go
+++ b/services/forms/repo_form.go
@@ -190,6 +190,7 @@ func (f *RepoSettingForm) Validate(req *http.Request, errs binding.Errors) bindi
// ProtectBranchForm form for changing protected branch settings
type ProtectBranchForm struct {
RuleName string `binding:"Required"`
+ RuleID int64
EnablePush string
WhitelistUsers string
WhitelistTeams string
@@ -603,7 +604,7 @@ type MergePullRequestForm struct {
MergeMessageField string
MergeCommitID string // only used for manually-merged
HeadCommitID string `json:"head_commit_id,omitempty"`
- ForceMerge *bool `json:"force_merge,omitempty"`
+ ForceMerge bool `json:"force_merge,omitempty"`
MergeWhenChecksSucceed bool `json:"merge_when_checks_succeed,omitempty"`
DeleteBranchAfterMerge bool `json:"delete_branch_after_merge,omitempty"`
}
diff --git a/services/lfs/server.go b/services/lfs/server.go
index 320c8e728..217d45124 100644
--- a/services/lfs/server.go
+++ b/services/lfs/server.go
@@ -5,7 +5,6 @@ package lfs
import (
stdCtx "context"
- "crypto/sha256"
"encoding/base64"
"encoding/hex"
"errors"
@@ -32,6 +31,7 @@ import (
"code.gitea.io/gitea/modules/storage"
"github.com/golang-jwt/jwt/v4"
+ "github.com/minio/sha256-simd"
)
// requestContext contain variables from the HTTP request.
diff --git a/services/mailer/token/token.go b/services/mailer/token/token.go
index 8a5a762d6..aa7b56718 100644
--- a/services/mailer/token/token.go
+++ b/services/mailer/token/token.go
@@ -6,13 +6,14 @@ package token
import (
"context"
crypto_hmac "crypto/hmac"
- "crypto/sha256"
"encoding/base32"
"fmt"
"time"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/util"
+
+ "github.com/minio/sha256-simd"
)
// A token is a verifiable container describing an action.
diff --git a/services/pull/check.go b/services/pull/check.go
index 310ea2e71..02d901541 100644
--- a/services/pull/check.go
+++ b/services/pull/check.go
@@ -59,8 +59,16 @@ func AddToTaskQueue(pr *issues_model.PullRequest) {
}
}
+type MergeCheckType int
+
+const (
+ MergeCheckTypeGeneral MergeCheckType = iota // general merge checks for "merge", "rebase", "squash", etc
+ MergeCheckTypeManually // Manually Merged button (mark a PR as merged manually)
+ MergeCheckTypeAuto // Auto Merge (Scheduled Merge) After Checks Succeed
+)
+
// CheckPullMergable check if the pull mergable based on all conditions (branch protection, merge options, ...)
-func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *access_model.Permission, pr *issues_model.PullRequest, manuallMerge, force bool) error {
+func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *access_model.Permission, pr *issues_model.PullRequest, mergeCheckType MergeCheckType, adminSkipProtectionCheck bool) error {
return db.WithTx(stdCtx, func(ctx context.Context) error {
if pr.HasMerged {
return ErrHasMerged
@@ -80,8 +88,8 @@ func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *acce
return ErrUserNotAllowedToMerge
}
- if manuallMerge {
- // don't check rules to "auto merge", doer is going to mark this pull as merged manually
+ if mergeCheckType == MergeCheckTypeManually {
+ // if doer is doing "manually merge" (mark as merged manually), do not check anything
return nil
}
@@ -103,14 +111,25 @@ func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *acce
return err
}
- if !force {
- return err
+ // Now the branch protection check failed, check whether the failure could be skipped (skip by setting err = nil)
+
+ // * when doing Auto Merge (Scheduled Merge After Checks Succeed), skip the branch protection check
+ if mergeCheckType == MergeCheckTypeAuto {
+ err = nil
+ }
+
+ // * if the doer is admin, they could skip the branch protection check
+ if adminSkipProtectionCheck {
+ if isRepoAdmin, errCheckAdmin := access_model.IsUserRepoAdmin(ctx, pr.BaseRepo, doer); errCheckAdmin != nil {
+ 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
+ }
}
- if isRepoAdmin, err2 := access_model.IsUserRepoAdmin(ctx, pr.BaseRepo, doer); err2 != nil {
- log.Error("Unable to check if %-v is a repo admin in %-v: %v", doer, pr.BaseRepo, err2)
- return err2
- } else if !isRepoAdmin {
+ // If there is still a branch protection check error, return it
+ if err != nil {
return err
}
}
diff --git a/services/pull/merge.go b/services/pull/merge.go
index 3ac67d91b..ad428427c 100644
--- a/services/pull/merge.go
+++ b/services/pull/merge.go
@@ -533,7 +533,7 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode
if err := git.NewCommand(ctx, "commit").
AddArguments(signArgs...).
AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email).
- AddOptionValues("-m", message).
+ AddOptionFormat("--message=%s", message).
Run(&git.RunOpts{
Env: env,
Dir: tmpBasePath,
@@ -641,7 +641,7 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode
func commitAndSignNoAuthor(ctx context.Context, pr *issues_model.PullRequest, message string, signArgs git.TrustedCmdArgs, tmpBasePath string, env []string) error {
var outbuf, errbuf strings.Builder
- if err := git.NewCommand(ctx, "commit").AddArguments(signArgs...).AddOptionValues("-m", message).
+ if err := git.NewCommand(ctx, "commit").AddArguments(signArgs...).AddOptionFormat("--message=%s", message).
Run(&git.RunOpts{
Env: env,
Dir: tmpBasePath,
diff --git a/services/repository/files/tree.go b/services/repository/files/tree.go
index f4304ea63..0b1d30484 100644
--- a/services/repository/files/tree.go
+++ b/services/repository/files/tree.go
@@ -85,6 +85,11 @@ func GetTreeBySHA(ctx context.Context, repo *repo_model.Repository, gitRepo *git
if entries[e].IsDir() {
copy(treeURL[copyPos:], entries[e].ID.String())
tree.Entries[i].URL = string(treeURL)
+ } else if entries[e].IsSubModule() {
+ // In Github Rest API Version=2022-11-28, if a tree entry is a submodule,
+ // its url will be returned as an empty string.
+ // So the URL will be set to "" here.
+ tree.Entries[i].URL = ""
} else {
copy(blobURL[copyPos:], entries[e].ID.String())
tree.Entries[i].URL = string(blobURL)
diff --git a/services/webhook/deliver.go b/services/webhook/deliver.go
index effbe45e5..e389b1f9f 100644
--- a/services/webhook/deliver.go
+++ b/services/webhook/deliver.go
@@ -7,7 +7,6 @@ import (
"context"
"crypto/hmac"
"crypto/sha1"
- "crypto/sha256"
"crypto/tls"
"encoding/hex"
"fmt"
@@ -29,6 +28,7 @@ import (
webhook_module "code.gitea.io/gitea/modules/webhook"
"github.com/gobwas/glob"
+ "github.com/minio/sha256-simd"
)
// Deliver deliver hook task
diff --git a/services/webhook/notifier.go b/services/webhook/notifier.go
index ba6d968db..b023717cd 100644
--- a/services/webhook/notifier.go
+++ b/services/webhook/notifier.go
@@ -150,7 +150,6 @@ func (m *webhookNotifier) NotifyIssueChangeAssignee(ctx context.Context, doer *u
log.Error("LoadPullRequest failed: %v", err)
return
}
- issue.PullRequest.Issue = issue
apiPullRequest := &api.PullRequestPayload{
Index: issue.Index,
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil),
@@ -196,7 +195,6 @@ func (m *webhookNotifier) NotifyIssueChangeTitle(ctx context.Context, doer *user
log.Error("LoadPullRequest failed: %v", err)
return
}
- issue.PullRequest.Issue = issue
err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequest, &api.PullRequestPayload{
Action: api.HookIssueEdited,
Index: issue.Index,
@@ -328,7 +326,10 @@ func (m *webhookNotifier) NotifyIssueChangeContent(ctx context.Context, doer *us
mode, _ := access_model.AccessLevel(ctx, issue.Poster, issue.Repo)
var err error
if issue.IsPull {
- issue.PullRequest.Issue = issue
+ if err := issue.LoadPullRequest(ctx); err != nil {
+ log.Error("LoadPullRequest: %v", err)
+ return
+ }
err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequest, &api.PullRequestPayload{
Action: api.HookIssueEdited,
Index: issue.Index,