Merge branch 'main' into lunny/issue_dev

This commit is contained in:
Lunny Xiao
2024-10-22 00:06:03 -07:00
214 changed files with 5900 additions and 810 deletions
+9 -1
View File
@@ -116,11 +116,20 @@ func (input *notifyInput) Notify(ctx context.Context) {
}
func notify(ctx context.Context, input *notifyInput) error {
shouldDetectSchedules := input.Event == webhook_module.HookEventPush && input.Ref.BranchName() == input.Repo.DefaultBranch
if input.Doer.IsActions() {
// avoiding triggering cyclically, for example:
// a comment of an issue will trigger the runner to add a new comment as reply,
// and the new comment will trigger the runner again.
log.Debug("ignore executing %v for event %v whose doer is %v", getMethod(ctx), input.Event, input.Doer.Name)
// we should update schedule tasks in this case, because
// 1. schedule tasks cannot be triggered by other events, so cyclic triggering will not occur
// 2. some schedule tasks may update the repo periodically, so the refs of schedule tasks need to be updated
if shouldDetectSchedules {
return DetectAndHandleSchedules(ctx, input.Repo)
}
return nil
}
if input.Repo.IsEmpty || input.Repo.IsArchived {
@@ -174,7 +183,6 @@ func notify(ctx context.Context, input *notifyInput) error {
var detectedWorkflows []*actions_module.DetectedWorkflow
actionsConfig := input.Repo.MustGetUnit(ctx, unit_model.TypeActions).ActionsConfig()
shouldDetectSchedules := input.Event == webhook_module.HookEventPush && input.Ref.BranchName() == input.Repo.DefaultBranch
workflows, schedules, err := actions_module.DetectWorkflows(gitRepo, commit,
input.Event,
input.Payload,
+12 -13
View File
@@ -7,7 +7,6 @@ import (
"context"
"fmt"
"os"
"strconv"
"strings"
issues_model "code.gitea.io/gitea/models/issues"
@@ -24,10 +23,10 @@ import (
// ProcReceive handle proc receive work
func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, opts *private.HookOptions) ([]private.HookProcReceiveRefResult, error) {
results := make([]private.HookProcReceiveRefResult, 0, len(opts.OldCommitIDs))
forcePush := opts.GitPushOptions.Bool(private.GitPushOptionForcePush)
topicBranch := opts.GitPushOptions["topic"]
forcePush, _ := strconv.ParseBool(opts.GitPushOptions["force-push"])
title := strings.TrimSpace(opts.GitPushOptions["title"])
description := strings.TrimSpace(opts.GitPushOptions["description"]) // TODO: Add more options?
description := strings.TrimSpace(opts.GitPushOptions["description"])
objectFormat := git.ObjectFormatFromName(repo.ObjectFormatName)
userName := strings.ToLower(opts.UserName)
@@ -56,19 +55,19 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.
}
baseBranchName := opts.RefFullNames[i].ForBranchName()
curentTopicBranch := ""
currentTopicBranch := ""
if !gitRepo.IsBranchExist(baseBranchName) {
// try match refs/for/<target-branch>/<topic-branch>
for p, v := range baseBranchName {
if v == '/' && gitRepo.IsBranchExist(baseBranchName[:p]) && p != len(baseBranchName)-1 {
curentTopicBranch = baseBranchName[p+1:]
currentTopicBranch = baseBranchName[p+1:]
baseBranchName = baseBranchName[:p]
break
}
}
}
if len(topicBranch) == 0 && len(curentTopicBranch) == 0 {
if len(topicBranch) == 0 && len(currentTopicBranch) == 0 {
results = append(results, private.HookProcReceiveRefResult{
OriginalRef: opts.RefFullNames[i],
OldOID: opts.OldCommitIDs[i],
@@ -78,18 +77,18 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.
continue
}
if len(curentTopicBranch) == 0 {
curentTopicBranch = topicBranch
if len(currentTopicBranch) == 0 {
currentTopicBranch = topicBranch
}
// because different user maybe want to use same topic,
// So it's better to make sure the topic branch name
// has user name prefix
// has username prefix
var headBranch string
if !strings.HasPrefix(curentTopicBranch, userName+"/") {
headBranch = userName + "/" + curentTopicBranch
if !strings.HasPrefix(currentTopicBranch, userName+"/") {
headBranch = userName + "/" + currentTopicBranch
} else {
headBranch = curentTopicBranch
headBranch = currentTopicBranch
}
pr, err := issues_model.GetUnmergedPullRequest(ctx, repo.ID, repo.ID, headBranch, baseBranchName, issues_model.PullRequestFlowAGit)
@@ -178,7 +177,7 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.
continue
}
if !forcePush {
if !forcePush.Value() {
output, _, err := git.NewCommand(ctx, "rev-list", "--max-count=1").
AddDynamicArguments(oldCommitID, "^"+opts.NewCommitIDs[i]).
RunStdString(&git.RunOpts{Dir: repo.RepoPath(), Env: os.Environ()})
+2 -2
View File
@@ -103,8 +103,8 @@ func handleSignIn(resp http.ResponseWriter, req *http.Request, sess SessionStore
middleware.SetLocaleCookie(resp, user.Language, 0)
// Clear whatever CSRF has right now, force to generate a new one
// force to generate a new CSRF token
if ctx := gitea_context.GetWebContext(req); ctx != nil {
ctx.Csrf.DeleteCookie(ctx)
ctx.Csrf.PrepareForSessionUser(ctx)
}
}
+4 -3
View File
@@ -35,9 +35,10 @@ type APIContext struct {
ContextUser *user_model.User // the user which is being visited, in most cases it differs from Doer
Repo *Repository
Org *APIOrganization
Package *Package
Repo *Repository
Org *APIOrganization
Package *Package
PublicOnly bool // Whether the request is for a public endpoint
}
func init() {
+1 -3
View File
@@ -129,10 +129,8 @@ func (c *csrfProtector) PrepareForSessionUser(ctx *Context) {
}
if needsNew {
// FIXME: actionId.
c.token = GenerateCsrfToken(c.opt.Secret, c.id, "POST", time.Now())
cookie := newCsrfCookie(&c.opt, c.token)
ctx.Resp.Header().Add("Set-Cookie", cookie.String())
ctx.Resp.Header().Add("Set-Cookie", newCsrfCookie(&c.opt, c.token).String())
}
ctx.Data["CsrfToken"] = c.token
+3
View File
@@ -58,6 +58,9 @@ func RequireRepoWriterOr(unitTypes ...unit.Type) func(ctx *Context) {
func RequireRepoReader(unitType unit.Type) func(ctx *Context) {
return func(ctx *Context) {
if !ctx.Repo.CanRead(unitType) {
if unitType == unit.TypeCode && canWriteAsMaintainer(ctx) {
return
}
if log.IsTrace() {
if ctx.IsSigned {
log.Trace("Permission Denied: User %-v cannot read %-v in Repo %-v\n"+
+13 -2
View File
@@ -374,7 +374,7 @@ func repoAssignment(ctx *Context, repo *repo_model.Repository) {
return
}
if !ctx.Repo.Permission.HasAnyUnitAccessOrEveryoneAccess() {
if !ctx.Repo.Permission.HasAnyUnitAccessOrEveryoneAccess() && !canWriteAsMaintainer(ctx) {
if ctx.FormString("go-get") == "1" {
EarlyResponseForGoGetMeta(ctx)
return
@@ -614,7 +614,10 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
}
}
isHomeOrSettings := ctx.Link == ctx.Repo.RepoLink || ctx.Link == ctx.Repo.RepoLink+"/settings" || strings.HasPrefix(ctx.Link, ctx.Repo.RepoLink+"/settings/")
isHomeOrSettings := ctx.Link == ctx.Repo.RepoLink ||
ctx.Link == ctx.Repo.RepoLink+"/settings" ||
strings.HasPrefix(ctx.Link, ctx.Repo.RepoLink+"/settings/") ||
ctx.Link == ctx.Repo.RepoLink+"/-/migrate/status"
// Disable everything when the repo is being created
if ctx.Repo.Repository.IsBeingCreated() || ctx.Repo.Repository.IsBroken() {
@@ -1055,3 +1058,11 @@ func GitHookService() func(ctx *Context) {
}
}
}
// canWriteAsMaintainer check if the doer can write to a branch as a maintainer
func canWriteAsMaintainer(ctx *Context) bool {
branchName := getRefNameFromPath(ctx.Repo, ctx.PathParam("*"), func(branchName string) bool {
return issues_model.CanMaintainerWriteToBranch(ctx, ctx.Repo.Permission, branchName, ctx.Doer)
})
return len(branchName) > 0
}
+6 -1
View File
@@ -760,10 +760,15 @@ func (g *GiteaLocalUploader) newPullRequest(pr *base.PullRequest) (*issues_model
pr.Updated = pr.Created
}
prTitle := pr.Title
if pr.IsDraft && !issues_model.HasWorkInProgressPrefix(pr.Title) {
prTitle = fmt.Sprintf("%s %s", setting.Repository.PullRequest.WorkInProgressPrefixes[0], pr.Title)
}
issue := issues_model.Issue{
RepoID: g.repo.ID,
Repo: g.repo,
Title: pr.Title,
Title: prTitle,
Index: pr.Number,
Content: pr.Content,
MilestoneID: milestoneID,
+1
View File
@@ -737,6 +737,7 @@ func (g *GithubDownloaderV3) GetPullRequests(page, perPage int) ([]*base.PullReq
PatchURL: pr.GetPatchURL(), // see below for SECURITY related issues here
Reactions: reactions,
ForeignIndex: int64(*pr.Number),
IsDraft: pr.GetDraft(),
})
// SECURITY: Ensure that the PR is safe
+1
View File
@@ -722,6 +722,7 @@ func (g *GitlabDownloader) GetPullRequests(page, perPage int) ([]*base.PullReque
PatchURL: pr.WebURL + ".patch",
ForeignIndex: int64(pr.IID),
Context: gitlabIssueContext{IsMergeRequest: true},
IsDraft: pr.Draft,
})
// SECURITY: Ensure that the PR is safe
+4 -4
View File
@@ -32,6 +32,10 @@ import (
// RenameUser renames a user
func RenameUser(ctx context.Context, u *user_model.User, newUserName string) error {
if newUserName == u.Name {
return nil
}
// Non-local users are not allowed to change their username.
if !u.IsOrganization() && !u.IsLocal() {
return user_model.ErrUserIsNotLocal{
@@ -40,10 +44,6 @@ func RenameUser(ctx context.Context, u *user_model.User, newUserName string) err
}
}
if newUserName == u.Name {
return nil
}
if err := user_model.IsUsableUsername(newUserName); err != nil {
return err
}
+3 -5
View File
@@ -114,12 +114,10 @@ func TestRenameUser(t *testing.T) {
})
t.Run("Non usable username", func(t *testing.T) {
usernames := []string{"--diff", "aa.png", ".well-known", "search", "aaa.atom"}
usernames := []string{"--diff", ".well-known", "gitea-actions", "aaa.atom", "aa.png"}
for _, username := range usernames {
t.Run(username, func(t *testing.T) {
assert.Error(t, user_model.IsUsableUsername(username))
assert.Error(t, RenameUser(db.DefaultContext, user, username))
})
assert.Error(t, user_model.IsUsableUsername(username), "non-usable username: %s", username)
assert.Error(t, RenameUser(db.DefaultContext, user, username), "non-usable username: %s", username)
}
})
+42 -32
View File
@@ -59,7 +59,7 @@ func (m *webhookNotifier) IssueClearLabels(ctx context.Context, doer *user_model
err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequestLabel, &api.PullRequestPayload{
Action: api.HookIssueLabelCleared,
Index: issue.Index,
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil),
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, doer),
Repository: convert.ToRepo(ctx, issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil),
})
@@ -150,7 +150,7 @@ func (m *webhookNotifier) IssueChangeAssignee(ctx context.Context, doer *user_mo
}
apiPullRequest := &api.PullRequestPayload{
Index: issue.Index,
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil),
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, doer),
Repository: convert.ToRepo(ctx, issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil),
}
@@ -201,7 +201,7 @@ func (m *webhookNotifier) IssueChangeTitle(ctx context.Context, doer *user_model
From: oldTitle,
},
},
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil),
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, doer),
Repository: convert.ToRepo(ctx, issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil),
})
@@ -236,7 +236,7 @@ func (m *webhookNotifier) IssueChangeStatus(ctx context.Context, doer *user_mode
// Merge pull request calls issue.changeStatus so we need to handle separately.
apiPullRequest := &api.PullRequestPayload{
Index: issue.Index,
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil),
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, doer),
Repository: convert.ToRepo(ctx, issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil),
CommitID: commitID,
@@ -307,7 +307,7 @@ func (m *webhookNotifier) NewPullRequest(ctx context.Context, pull *issues_model
if err := PrepareWebhooks(ctx, EventSource{Repository: pull.Issue.Repo}, webhook_module.HookEventPullRequest, &api.PullRequestPayload{
Action: api.HookIssueOpened,
Index: pull.Issue.Index,
PullRequest: convert.ToAPIPullRequest(ctx, pull, nil),
PullRequest: convert.ToAPIPullRequest(ctx, pull, pull.Issue.Poster),
Repository: convert.ToRepo(ctx, pull.Issue.Repo, permission),
Sender: convert.ToUser(ctx, pull.Issue.Poster, nil),
}); err != nil {
@@ -336,7 +336,7 @@ func (m *webhookNotifier) IssueChangeContent(ctx context.Context, doer *user_mod
From: oldContent,
},
},
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil),
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, doer),
Repository: convert.ToRepo(ctx, issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil),
})
@@ -375,17 +375,20 @@ func (m *webhookNotifier) UpdateComment(ctx context.Context, doer *user_model.Us
}
var eventType webhook_module.HookEventType
var pullRequest *api.PullRequest
if c.Issue.IsPull {
eventType = webhook_module.HookEventPullRequestComment
pullRequest = convert.ToAPIPullRequest(ctx, c.Issue.PullRequest, doer)
} else {
eventType = webhook_module.HookEventIssueComment
}
permission, _ := access_model.GetUserRepoPermission(ctx, c.Issue.Repo, doer)
if err := PrepareWebhooks(ctx, EventSource{Repository: c.Issue.Repo}, eventType, &api.IssueCommentPayload{
Action: api.HookIssueCommentEdited,
Issue: convert.ToAPIIssue(ctx, doer, c.Issue),
Comment: convert.ToAPIComment(ctx, c.Issue.Repo, c),
Action: api.HookIssueCommentEdited,
Issue: convert.ToAPIIssue(ctx, doer, c.Issue),
PullRequest: pullRequest,
Comment: convert.ToAPIComment(ctx, c.Issue.Repo, c),
Changes: &api.ChangesPayload{
Body: &api.ChangesFromPayload{
From: oldContent,
@@ -403,20 +406,23 @@ func (m *webhookNotifier) CreateIssueComment(ctx context.Context, doer *user_mod
issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User,
) {
var eventType webhook_module.HookEventType
var pullRequest *api.PullRequest
if issue.IsPull {
eventType = webhook_module.HookEventPullRequestComment
pullRequest = convert.ToAPIPullRequest(ctx, issue.PullRequest, doer)
} else {
eventType = webhook_module.HookEventIssueComment
}
permission, _ := access_model.GetUserRepoPermission(ctx, repo, doer)
if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, eventType, &api.IssueCommentPayload{
Action: api.HookIssueCommentCreated,
Issue: convert.ToAPIIssue(ctx, doer, issue),
Comment: convert.ToAPIComment(ctx, repo, comment),
Repository: convert.ToRepo(ctx, repo, permission),
Sender: convert.ToUser(ctx, doer, nil),
IsPull: issue.IsPull,
Action: api.HookIssueCommentCreated,
Issue: convert.ToAPIIssue(ctx, doer, issue),
PullRequest: pullRequest,
Comment: convert.ToAPIComment(ctx, repo, comment),
Repository: convert.ToRepo(ctx, repo, permission),
Sender: convert.ToUser(ctx, doer, nil),
IsPull: issue.IsPull,
}); err != nil {
log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
}
@@ -440,20 +446,23 @@ func (m *webhookNotifier) DeleteComment(ctx context.Context, doer *user_model.Us
}
var eventType webhook_module.HookEventType
var pullRequest *api.PullRequest
if comment.Issue.IsPull {
eventType = webhook_module.HookEventPullRequestComment
pullRequest = convert.ToAPIPullRequest(ctx, comment.Issue.PullRequest, doer)
} else {
eventType = webhook_module.HookEventIssueComment
}
permission, _ := access_model.GetUserRepoPermission(ctx, comment.Issue.Repo, doer)
if err := PrepareWebhooks(ctx, EventSource{Repository: comment.Issue.Repo}, eventType, &api.IssueCommentPayload{
Action: api.HookIssueCommentDeleted,
Issue: convert.ToAPIIssue(ctx, doer, comment.Issue),
Comment: convert.ToAPIComment(ctx, comment.Issue.Repo, comment),
Repository: convert.ToRepo(ctx, comment.Issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil),
IsPull: comment.Issue.IsPull,
Action: api.HookIssueCommentDeleted,
Issue: convert.ToAPIIssue(ctx, doer, comment.Issue),
PullRequest: pullRequest,
Comment: convert.ToAPIComment(ctx, comment.Issue.Repo, comment),
Repository: convert.ToRepo(ctx, comment.Issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil),
IsPull: comment.Issue.IsPull,
}); err != nil {
log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
}
@@ -525,7 +534,7 @@ func (m *webhookNotifier) IssueChangeLabels(ctx context.Context, doer *user_mode
err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequestLabel, &api.PullRequestPayload{
Action: api.HookIssueLabelUpdated,
Index: issue.Index,
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil),
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, doer),
Repository: convert.ToRepo(ctx, issue.Repo, access_model.Permission{AccessMode: perm.AccessModeOwner}),
Sender: convert.ToUser(ctx, doer, nil),
})
@@ -567,7 +576,7 @@ func (m *webhookNotifier) IssueChangeMilestone(ctx context.Context, doer *user_m
err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequestMilestone, &api.PullRequestPayload{
Action: hookAction,
Index: issue.Index,
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil),
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, doer),
Repository: convert.ToRepo(ctx, issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil),
})
@@ -640,7 +649,7 @@ func (*webhookNotifier) MergePullRequest(ctx context.Context, doer *user_model.U
// Merge pull request calls issue.changeStatus so we need to handle separately.
apiPullRequest := &api.PullRequestPayload{
Index: pr.Issue.Index,
PullRequest: convert.ToAPIPullRequest(ctx, pr, nil),
PullRequest: convert.ToAPIPullRequest(ctx, pr, doer),
Repository: convert.ToRepo(ctx, pr.Issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil),
Action: api.HookIssueClosed,
@@ -668,7 +677,7 @@ func (m *webhookNotifier) PullRequestChangeTargetBranch(ctx context.Context, doe
From: oldBranch,
},
},
PullRequest: convert.ToAPIPullRequest(ctx, pr, nil),
PullRequest: convert.ToAPIPullRequest(ctx, pr, doer),
Repository: convert.ToRepo(ctx, issue.Repo, mode),
Sender: convert.ToUser(ctx, doer, nil),
}); err != nil {
@@ -703,11 +712,12 @@ func (m *webhookNotifier) PullRequestReview(ctx context.Context, pr *issues_mode
return
}
if err := PrepareWebhooks(ctx, EventSource{Repository: review.Issue.Repo}, reviewHookType, &api.PullRequestPayload{
Action: api.HookIssueReviewed,
Index: review.Issue.Index,
PullRequest: convert.ToAPIPullRequest(ctx, pr, nil),
Repository: convert.ToRepo(ctx, review.Issue.Repo, permission),
Sender: convert.ToUser(ctx, review.Reviewer, nil),
Action: api.HookIssueReviewed,
Index: review.Issue.Index,
PullRequest: convert.ToAPIPullRequest(ctx, pr, review.Reviewer),
RequestedReviewer: convert.ToUser(ctx, review.Reviewer, nil),
Repository: convert.ToRepo(ctx, review.Issue.Repo, permission),
Sender: convert.ToUser(ctx, review.Reviewer, nil),
Review: &api.ReviewPayload{
Type: string(reviewHookType),
Content: review.Content,
@@ -729,7 +739,7 @@ func (m *webhookNotifier) PullRequestReviewRequest(ctx context.Context, doer *us
}
apiPullRequest := &api.PullRequestPayload{
Index: issue.Index,
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil),
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, doer),
RequestedReviewer: convert.ToUser(ctx, reviewer, nil),
Repository: convert.ToRepo(ctx, issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil),
@@ -774,7 +784,7 @@ func (m *webhookNotifier) PullRequestSynchronized(ctx context.Context, doer *use
if err := PrepareWebhooks(ctx, EventSource{Repository: pr.Issue.Repo}, webhook_module.HookEventPullRequestSync, &api.PullRequestPayload{
Action: api.HookIssueSynchronized,
Index: pr.Issue.Index,
PullRequest: convert.ToAPIPullRequest(ctx, pr, nil),
PullRequest: convert.ToAPIPullRequest(ctx, pr, doer),
Repository: convert.ToRepo(ctx, pr.Issue.Repo, access_model.Permission{AccessMode: perm.AccessModeOwner}),
Sender: convert.ToUser(ctx, doer, nil),
}); err != nil {