From 76185edd7668165429f008156251d1bb84e61973 Mon Sep 17 00:00:00 2001 From: 6543 <24977596+6543@users.noreply.github.com> Date: Sat, 2 Nov 2019 23:47:25 +0100 Subject: [PATCH 01/23] FIX download diff/patch from commit (#8792) * send fix * restart CI * us Commit only when available * CI.redo() * more specific if statement Co-Authored-By: mrsdizzie --- templates/repo/diff/options_dropdown.tmpl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/templates/repo/diff/options_dropdown.tmpl b/templates/repo/diff/options_dropdown.tmpl index 9fca069f0a..4bc6a3b994 100644 --- a/templates/repo/diff/options_dropdown.tmpl +++ b/templates/repo/diff/options_dropdown.tmpl @@ -3,7 +3,12 @@ From 61a3eae923f60c2ab84d3cbb8ed9c155817c37bd Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Sat, 2 Nov 2019 22:49:35 +0000 Subject: [PATCH 02/23] [skip ci] Updated translations via Crowdin --- options/locale/locale_tr-TR.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini index ac93db57c0..4ad9ff39bc 100644 --- a/options/locale/locale_tr-TR.ini +++ b/options/locale/locale_tr-TR.ini @@ -701,6 +701,7 @@ editor.no_changes_to_show=Gösterilecek değişiklik yok. editor.fail_to_update_file=Şu hata ile '%s' dosyasını güncelleme/oluşturma başarısız oldu: %v editor.add_subdir=Bir dizin ekle… editor.unable_to_upload_files=Şu hata ile dosyalar '%s' 'a yüklenemedi: %v +editor.upload_file_is_locked='%s' dosyası %s tarafından kilitlendi. editor.upload_files_to_dir=Dosyaları '%s' 'a yükle editor.cannot_commit_to_protected_branch=Korunan '%s' dalına işleme yapılamıyor. From fe7a6d9bfcbcf53bfe2d24f4d8e7463c897b9389 Mon Sep 17 00:00:00 2001 From: 6543 <24977596+6543@users.noreply.github.com> Date: Sun, 3 Nov 2019 01:54:39 +0100 Subject: [PATCH 03/23] [Fix] Checkbox at RepoSettings Protected Branch (#8799) * add missing "d" * CI.redo() --- templates/repo/settings/protected_branch.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/repo/settings/protected_branch.tmpl b/templates/repo/settings/protected_branch.tmpl index a50765c4b4..4b401b5131 100644 --- a/templates/repo/settings/protected_branch.tmpl +++ b/templates/repo/settings/protected_branch.tmpl @@ -132,7 +132,7 @@ {{range $.branch_status_check_contexts}} - + {{.}} {{if $.is_context_required}}{{if call $.is_context_required .}}
Required
{{end}}{{end}} From 022d2d8beb6297016ed26b0090c6a4a4ac404437 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 3 Nov 2019 14:59:26 +0800 Subject: [PATCH 04/23] Move push commits events to notification (#8783) * Move push commits events to notification * Update modules/notification/base/null.go Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> --- modules/notification/base/notifier.go | 2 ++ modules/notification/base/null.go | 4 ++++ modules/notification/notification.go | 7 +++++++ modules/notification/webhook/webhook.go | 23 +++++++++++++++++++++++ modules/repofiles/action.go | 18 ++---------------- services/mirror/sync.go | 23 +++-------------------- 6 files changed, 41 insertions(+), 36 deletions(-) diff --git a/modules/notification/base/notifier.go b/modules/notification/base/notifier.go index b0e7b4cae8..ff865f19cf 100644 --- a/modules/notification/base/notifier.go +++ b/modules/notification/base/notifier.go @@ -40,4 +40,6 @@ type Notifier interface { NotifyNewRelease(rel *models.Release) NotifyUpdateRelease(doer *models.User, rel *models.Release) NotifyDeleteRelease(doer *models.User, rel *models.Release) + + NotifyPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *models.PushCommits) } diff --git a/modules/notification/base/null.go b/modules/notification/base/null.go index 3524a53c15..c10e1b6340 100644 --- a/modules/notification/base/null.go +++ b/modules/notification/base/null.go @@ -106,3 +106,7 @@ func (*NullNotifier) NotifyCreateRepository(doer *models.User, u *models.User, r // NotifyMigrateRepository places a place holder function func (*NullNotifier) NotifyMigrateRepository(doer *models.User, u *models.User, repo *models.Repository) { } + +// NotifyPushCommits notifies commits pushed to notifiers +func (*NullNotifier) NotifyPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *models.PushCommits) { +} diff --git a/modules/notification/notification.go b/modules/notification/notification.go index 70b1541e35..6532f9d614 100644 --- a/modules/notification/notification.go +++ b/modules/notification/notification.go @@ -183,3 +183,10 @@ func NotifyMigrateRepository(doer *models.User, u *models.User, repo *models.Rep notifier.NotifyMigrateRepository(doer, u, repo) } } + +// NotifyPushCommits notifies commits pushed to notifiers +func NotifyPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *models.PushCommits) { + for _, notifier := range notifiers { + notifier.NotifyPushCommits(pusher, repo, refName, oldCommitID, newCommitID, commits) + } +} diff --git a/modules/notification/webhook/webhook.go b/modules/notification/webhook/webhook.go index a969ad74f7..13d33e1011 100644 --- a/modules/notification/webhook/webhook.go +++ b/modules/notification/webhook/webhook.go @@ -8,6 +8,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/notification/base" + "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" webhook_module "code.gitea.io/gitea/modules/webhook" ) @@ -461,3 +462,25 @@ func (m *webhookNotifier) NotifyIssueChangeMilestone(doer *models.User, issue *m log.Error("PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err) } } + +func (m *webhookNotifier) NotifyPushCommits(pusher *models.User, repo *models.Repository, refName, oldCommitID, newCommitID string, commits *models.PushCommits) { + apiPusher := pusher.APIFormat() + apiCommits, err := commits.ToAPIPayloadCommits(repo.RepoPath(), repo.HTMLURL()) + if err != nil { + log.Error("commits.ToAPIPayloadCommits failed: %v", err) + return + } + + if err := webhook_module.PrepareWebhooks(repo, models.HookEventPush, &api.PushPayload{ + Ref: refName, + Before: oldCommitID, + After: newCommitID, + CompareURL: setting.AppURL + commits.CompareURL, + Commits: apiCommits, + Repo: repo.APIFormat(models.AccessModeOwner), + Pusher: apiPusher, + Sender: apiPusher, + }); err != nil { + log.Error("PrepareWebhooks: %v", err) + } +} diff --git a/modules/repofiles/action.go b/modules/repofiles/action.go index 79f6406c53..e5f6bf8718 100644 --- a/modules/repofiles/action.go +++ b/modules/repofiles/action.go @@ -12,6 +12,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/notification" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/webhook" @@ -190,22 +191,7 @@ func CommitRepoAction(opts CommitRepoActionOptions) error { } if isHookEventPush { - commits, err := opts.Commits.ToAPIPayloadCommits(repo.RepoPath(), repo.HTMLURL()) - if err != nil { - return err - } - if err = webhook.PrepareWebhooks(repo, models.HookEventPush, &api.PushPayload{ - Ref: opts.RefFullName, - Before: opts.OldCommitID, - After: opts.NewCommitID, - CompareURL: setting.AppURL + opts.Commits.CompareURL, - Commits: commits, - Repo: apiRepo, - Pusher: apiPusher, - Sender: apiPusher, - }); err != nil { - return fmt.Errorf("PrepareWebhooks: %v", err) - } + notification.NotifyPushCommits(pusher, repo, opts.RefFullName, opts.OldCommitID, opts.NewCommitID, opts.Commits) } return nil diff --git a/services/mirror/sync.go b/services/mirror/sync.go index a9ce189c03..ba9e896dd5 100644 --- a/services/mirror/sync.go +++ b/services/mirror/sync.go @@ -9,9 +9,8 @@ import ( "fmt" "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/notification" "code.gitea.io/gitea/modules/setting" - api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/webhook" ) func syncAction(opType models.ActionType, repo *models.Repository, refName string, data []byte) error { @@ -45,25 +44,9 @@ func SyncPushAction(repo *models.Repository, opts SyncPushActionOptions) error { opts.Commits.Commits = opts.Commits.Commits[:setting.UI.FeedMaxCommitNum] } - apiCommits, err := opts.Commits.ToAPIPayloadCommits(repo.RepoPath(), repo.HTMLURL()) - if err != nil { - return err - } - opts.Commits.CompareURL = repo.ComposeCompareURL(opts.OldCommitID, opts.NewCommitID) - apiPusher := repo.MustOwner().APIFormat() - if err := webhook.PrepareWebhooks(repo, models.HookEventPush, &api.PushPayload{ - Ref: opts.RefName, - Before: opts.OldCommitID, - After: opts.NewCommitID, - CompareURL: setting.AppURL + opts.Commits.CompareURL, - Commits: apiCommits, - Repo: repo.APIFormat(models.AccessModeOwner), - Pusher: apiPusher, - Sender: apiPusher, - }); err != nil { - return fmt.Errorf("PrepareWebhooks: %v", err) - } + + notification.NotifyPushCommits(repo.MustOwner(), repo, opts.RefName, opts.OldCommitID, opts.NewCommitID, opts.Commits) data, err := json.Marshal(opts.Commits) if err != nil { From dce22efbee6a04b8c19348dac831cd88b18ac07c Mon Sep 17 00:00:00 2001 From: mrsdizzie Date: Sun, 3 Nov 2019 06:08:18 -0500 Subject: [PATCH 05/23] Fix SSH2 conditonal in key parsing code (#8806) Avoid out of bounds error by using strings.HasPrefix to check for starting SSH2 text rather than assuming user input has at least 31 characters. Add tests for bad input as well. Fixes #8800 --- models/ssh_key.go | 2 +- models/ssh_key_test.go | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/models/ssh_key.go b/models/ssh_key.go index 69699f24c1..f441c3e42c 100644 --- a/models/ssh_key.go +++ b/models/ssh_key.go @@ -107,7 +107,7 @@ func parseKeyString(content string) (string, error) { var keyType, keyContent, keyComment string - if content[:len(ssh2keyStart)] == ssh2keyStart { + if strings.HasPrefix(content, ssh2keyStart) { // Parse SSH2 file format. // Transform all legal line endings to a single "\n". diff --git a/models/ssh_key_test.go b/models/ssh_key_test.go index 4bb612a671..95cd4eeb1a 100644 --- a/models/ssh_key_test.go +++ b/models/ssh_key_test.go @@ -131,6 +131,19 @@ AAAAC3NzaC1lZDI1NTE5AAAAICV0MGX/W9IvLA4FXpIuUcdDcbj5KX4syHgsTy7soVgf _, err := CheckPublicKeyString(test.content) assert.NoError(t, err) } + + for _, invalidKeys := range []struct { + content string + }{ + {"test"}, + {"---- NOT A REAL KEY ----"}, + {"bad\nkey"}, + {"\t\t:)\t\r\n"}, + {"\r\ntest \r\ngitea\r\n\r\n"}, + } { + _, err := CheckPublicKeyString(invalidKeys.content) + assert.Error(t, err) + } } func Test_calcFingerprint(t *testing.T) { From 7971b05d2b96e45a4ee3954a39a7db9b9bbb807f Mon Sep 17 00:00:00 2001 From: David Svantesson Date: Sun, 3 Nov 2019 15:46:32 +0100 Subject: [PATCH 06/23] Fix API deadline removal (#8759) * Handle deadline is zero (to remove deadline) * Better API documentation for issue deadline. * Add parameter to unset due date. * Update pull edit API comment --- go.mod | 2 -- modules/structs/issue.go | 3 ++- modules/structs/pull.go | 3 ++- routers/api/v1/repo/issue.go | 13 ++++++++++--- routers/api/v1/repo/pull.go | 15 +++++++++++---- templates/swagger/v1_json.tmpl | 10 +++++++++- 6 files changed, 34 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 7e920ac032..02f0c46f22 100644 --- a/go.mod +++ b/go.mod @@ -69,8 +69,6 @@ require ( github.com/mattn/go-sqlite3 v1.11.0 github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75 github.com/microcosm-cc/bluemonday v0.0.0-20161012083705-f77f16ffc87a - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.1 // indirect github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae // indirect github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5 diff --git a/modules/structs/issue.go b/modules/structs/issue.go index bd39f9ea44..b27c757faa 100644 --- a/modules/structs/issue.go +++ b/modules/structs/issue.go @@ -99,7 +99,8 @@ type EditIssueOption struct { Milestone *int64 `json:"milestone"` State *string `json:"state"` // swagger:strfmt date-time - Deadline *time.Time `json:"due_date"` + Deadline *time.Time `json:"due_date"` + RemoveDeadline *bool `json:"unset_due_date"` } // EditDeadlineOption options for creating a deadline diff --git a/modules/structs/pull.go b/modules/structs/pull.go index 722d245afc..c4ec7d416a 100644 --- a/modules/structs/pull.go +++ b/modules/structs/pull.go @@ -88,5 +88,6 @@ type EditPullRequestOption struct { Labels []int64 `json:"labels"` State *string `json:"state"` // swagger:strfmt date-time - Deadline *time.Time `json:"due_date"` + Deadline *time.Time `json:"due_date"` + RemoveDeadline *bool `json:"unset_due_date"` } diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go index 1534c45df0..186e66cb8f 100644 --- a/routers/api/v1/repo/issue.go +++ b/routers/api/v1/repo/issue.go @@ -458,9 +458,16 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) { issue.Content = *form.Body } - // Update the deadline - if form.Deadline != nil && ctx.Repo.CanWrite(models.UnitTypeIssues) { - deadlineUnix := timeutil.TimeStamp(form.Deadline.Unix()) + // Update or remove the deadline, only if set and allowed + if (form.Deadline != nil || form.RemoveDeadline != nil) && ctx.Repo.CanWrite(models.UnitTypeIssues) { + var deadlineUnix timeutil.TimeStamp + + if (form.RemoveDeadline == nil || !*form.RemoveDeadline) && !form.Deadline.IsZero() { + deadline := time.Date(form.Deadline.Year(), form.Deadline.Month(), form.Deadline.Day(), + 23, 59, 59, 0, form.Deadline.Location()) + deadlineUnix = timeutil.TimeStamp(deadline.Unix()) + } + if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil { ctx.Error(500, "UpdateIssueDeadline", err) return diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index 9264c00cec..6d86105a15 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -8,6 +8,7 @@ import ( "fmt" "net/http" "strings" + "time" "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/auth" @@ -326,7 +327,7 @@ func CreatePullRequest(ctx *context.APIContext, form api.CreatePullRequestOption func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) { // swagger:operation PATCH /repos/{owner}/{repo}/pulls/{index} repository repoEditPullRequest // --- - // summary: Update a pull request + // summary: Update a pull request. If using deadline only the date will be taken into account, and time of day ignored. // consumes: // - application/json // produces: @@ -385,9 +386,15 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) { issue.Content = form.Body } - // Update Deadline - if form.Deadline != nil { - deadlineUnix := timeutil.TimeStamp(form.Deadline.Unix()) + // Update or remove deadline if set + if form.Deadline != nil || form.RemoveDeadline != nil { + var deadlineUnix timeutil.TimeStamp + if (form.RemoveDeadline == nil || !*form.RemoveDeadline) && !form.Deadline.IsZero() { + deadline := time.Date(form.Deadline.Year(), form.Deadline.Month(), form.Deadline.Day(), + 23, 59, 59, 0, form.Deadline.Location()) + deadlineUnix = timeutil.TimeStamp(deadline.Unix()) + } + if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil { ctx.Error(500, "UpdateIssueDeadline", err) return diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 41e5353ea7..17b8eab6c5 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -4715,7 +4715,7 @@ "tags": [ "repository" ], - "summary": "Update a pull request", + "summary": "Update a pull request. If using deadline only the date will be taken into account, and time of day ignored.", "operationId": "repoEditPullRequest", "parameters": [ { @@ -8532,6 +8532,10 @@ "title": { "type": "string", "x-go-name": "Title" + }, + "unset_due_date": { + "type": "boolean", + "x-go-name": "RemoveDeadline" } }, "x-go-package": "code.gitea.io/gitea/modules/structs" @@ -8660,6 +8664,10 @@ "title": { "type": "string", "x-go-name": "Title" + }, + "unset_due_date": { + "type": "boolean", + "x-go-name": "RemoveDeadline" } }, "x-go-package": "code.gitea.io/gitea/modules/structs" From 491887d44132b8103ed0d753f95ecd43d600adba Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 4 Nov 2019 04:59:09 +0800 Subject: [PATCH 07/23] Move actions to notification (#8785) --- modules/notification/action/action.go | 77 +++++++++++++++++++++++++ modules/notification/notification.go | 2 + modules/notification/webhook/webhook.go | 36 ++++++++++++ services/issue/issue.go | 15 ----- services/pull/pull.go | 25 +------- 5 files changed, 118 insertions(+), 37 deletions(-) create mode 100644 modules/notification/action/action.go diff --git a/modules/notification/action/action.go b/modules/notification/action/action.go new file mode 100644 index 0000000000..15228f65e7 --- /dev/null +++ b/modules/notification/action/action.go @@ -0,0 +1,77 @@ +// Copyright 2019 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package action + +import ( + "fmt" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/notification/base" +) + +type actionNotifier struct { + base.NullNotifier +} + +var ( + _ base.Notifier = &actionNotifier{} +) + +// NewNotifier create a new webhookNotifier notifier +func NewNotifier() base.Notifier { + return &actionNotifier{} +} + +func (a *actionNotifier) NotifyNewIssue(issue *models.Issue) { + if err := issue.LoadPoster(); err != nil { + log.Error("issue.LoadPoster: %v", err) + return + } + if err := issue.LoadRepo(); err != nil { + log.Error("issue.LoadRepo: %v", err) + return + } + repo := issue.Repo + + if err := models.NotifyWatchers(&models.Action{ + ActUserID: issue.Poster.ID, + ActUser: issue.Poster, + OpType: models.ActionCreateIssue, + Content: fmt.Sprintf("%d|%s", issue.Index, issue.Title), + RepoID: repo.ID, + Repo: repo, + IsPrivate: repo.IsPrivate, + }); err != nil { + log.Error("NotifyWatchers: %v", err) + } +} + +func (a *actionNotifier) NotifyNewPullRequest(pull *models.PullRequest) { + if err := pull.LoadIssue(); err != nil { + log.Error("pull.LoadIssue: %v", err) + return + } + if err := pull.Issue.LoadRepo(); err != nil { + log.Error("pull.Issue.LoadRepo: %v", err) + return + } + if err := pull.Issue.LoadPoster(); err != nil { + log.Error("pull.Issue.LoadPoster: %v", err) + return + } + + if err := models.NotifyWatchers(&models.Action{ + ActUserID: pull.Issue.Poster.ID, + ActUser: pull.Issue.Poster, + OpType: models.ActionCreatePullRequest, + Content: fmt.Sprintf("%d|%s", pull.Issue.Index, pull.Issue.Title), + RepoID: pull.Issue.Repo.ID, + Repo: pull.Issue.Repo, + IsPrivate: pull.Issue.Repo.IsPrivate, + }); err != nil { + log.Error("NotifyWatchers: %v", err) + } +} diff --git a/modules/notification/notification.go b/modules/notification/notification.go index 6532f9d614..1fd3022940 100644 --- a/modules/notification/notification.go +++ b/modules/notification/notification.go @@ -7,6 +7,7 @@ package notification import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/notification/action" "code.gitea.io/gitea/modules/notification/base" "code.gitea.io/gitea/modules/notification/indexer" "code.gitea.io/gitea/modules/notification/mail" @@ -33,6 +34,7 @@ func NewContext() { } RegisterNotifier(indexer.NewNotifier()) RegisterNotifier(webhook.NewNotifier()) + RegisterNotifier(action.NewNotifier()) } // NotifyCreateIssueComment notifies issue comment related message to notifiers diff --git a/modules/notification/webhook/webhook.go b/modules/notification/webhook/webhook.go index 13d33e1011..7d28c1c8b9 100644 --- a/modules/notification/webhook/webhook.go +++ b/modules/notification/webhook/webhook.go @@ -10,6 +10,7 @@ import ( "code.gitea.io/gitea/modules/notification/base" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/webhook" webhook_module "code.gitea.io/gitea/modules/webhook" ) @@ -251,6 +252,15 @@ func (m *webhookNotifier) NotifyIssueChangeStatus(doer *models.User, issue *mode } func (m *webhookNotifier) NotifyNewIssue(issue *models.Issue) { + if err := issue.LoadRepo(); err != nil { + log.Error("issue.LoadRepo: %v", err) + return + } + if err := issue.LoadPoster(); err != nil { + log.Error("issue.LoadPoster: %v", err) + return + } + mode, _ := models.AccessLevel(issue.Poster, issue.Repo) if err := webhook_module.PrepareWebhooks(issue.Repo, models.HookEventIssues, &api.IssuePayload{ Action: api.HookIssueOpened, @@ -263,6 +273,32 @@ func (m *webhookNotifier) NotifyNewIssue(issue *models.Issue) { } } +func (m *webhookNotifier) NotifyNewPullRequest(pull *models.PullRequest) { + if err := pull.LoadIssue(); err != nil { + log.Error("pull.LoadIssue: %v", err) + return + } + if err := pull.Issue.LoadRepo(); err != nil { + log.Error("pull.Issue.LoadRepo: %v", err) + return + } + if err := pull.Issue.LoadPoster(); err != nil { + log.Error("pull.Issue.LoadPoster: %v", err) + return + } + + mode, _ := models.AccessLevel(pull.Issue.Poster, pull.Issue.Repo) + if err := webhook.PrepareWebhooks(pull.Issue.Repo, models.HookEventPullRequest, &api.PullRequestPayload{ + Action: api.HookIssueOpened, + Index: pull.Issue.Index, + PullRequest: pull.APIFormat(), + Repository: pull.Issue.Repo.APIFormat(mode), + Sender: pull.Issue.Poster.APIFormat(), + }); err != nil { + log.Error("PrepareWebhooks: %v", err) + } +} + func (m *webhookNotifier) NotifyIssueChangeContent(doer *models.User, issue *models.Issue, oldContent string) { mode, _ := models.AccessLevel(issue.Poster, issue.Repo) var err error diff --git a/services/issue/issue.go b/services/issue/issue.go index ee2f176a43..aa06ba4097 100644 --- a/services/issue/issue.go +++ b/services/issue/issue.go @@ -5,10 +5,7 @@ package issue import ( - "fmt" - "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/notification" ) @@ -24,18 +21,6 @@ func NewIssue(repo *models.Repository, issue *models.Issue, labelIDs []int64, uu } } - if err := models.NotifyWatchers(&models.Action{ - ActUserID: issue.Poster.ID, - ActUser: issue.Poster, - OpType: models.ActionCreateIssue, - Content: fmt.Sprintf("%d|%s", issue.Index, issue.Title), - RepoID: repo.ID, - Repo: repo, - IsPrivate: repo.IsPrivate, - }); err != nil { - log.Error("NotifyWatchers: %v", err) - } - notification.NotifyNewIssue(issue) return nil diff --git a/services/pull/pull.go b/services/pull/pull.go index 0a4c4a7eee..20939c397f 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -10,6 +10,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/notification" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/webhook" issue_service "code.gitea.io/gitea/services/issue" @@ -27,30 +28,10 @@ func NewPullRequest(repo *models.Repository, pull *models.Issue, labelIDs []int6 } } - if err := models.NotifyWatchers(&models.Action{ - ActUserID: pull.Poster.ID, - ActUser: pull.Poster, - OpType: models.ActionCreatePullRequest, - Content: fmt.Sprintf("%d|%s", pull.Index, pull.Title), - RepoID: repo.ID, - Repo: repo, - IsPrivate: repo.IsPrivate, - }); err != nil { - log.Error("NotifyWatchers: %v", err) - } - pr.Issue = pull pull.PullRequest = pr - mode, _ := models.AccessLevel(pull.Poster, repo) - if err := webhook.PrepareWebhooks(repo, models.HookEventPullRequest, &api.PullRequestPayload{ - Action: api.HookIssueOpened, - Index: pull.Index, - PullRequest: pr.APIFormat(), - Repository: repo.APIFormat(mode), - Sender: pull.Poster.APIFormat(), - }); err != nil { - log.Error("PrepareWebhooks: %v", err) - } + + notification.NotifyNewPullRequest(pr) return nil } From a966a0298ea1a545c383541ca4e72c61de1ed59e Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 4 Nov 2019 06:13:25 +0800 Subject: [PATCH 08/23] Move more webhook codes from models to webhook module (#8802) * Move more webhook codes from models to webhook module --- models/webhook.go | 27 ---------- models/webhook_test.go | 12 ----- .../webhook/dingtalk.go | 29 +++++----- .../webhook/discord.go | 53 +++++++++++-------- .../webhook/msteams.go | 35 ++++++------ .../webhook/slack.go | 39 +++++++++----- .../webhook/telegram.go | 37 ++++++++----- modules/webhook/webhook.go | 10 ++-- modules/webhook/webhook_test.go | 12 +++++ routers/api/v1/convert/convert.go | 3 +- routers/api/v1/utils/hook.go | 5 +- routers/repo/webhook.go | 18 +++---- 12 files changed, 145 insertions(+), 135 deletions(-) rename models/webhook_dingtalk.go => modules/webhook/dingtalk.go (95%) rename models/webhook_discord.go => modules/webhook/discord.go (92%) rename models/webhook_msteams.go => modules/webhook/msteams.go (96%) rename models/webhook_slack.go => modules/webhook/slack.go (93%) rename models/webhook_telegram.go => modules/webhook/telegram.go (93%) diff --git a/models/webhook.go b/models/webhook.go index d3a8b52d86..7eb17caaf6 100644 --- a/models/webhook.go +++ b/models/webhook.go @@ -118,33 +118,6 @@ func (w *Webhook) AfterLoad() { } } -// GetSlackHook returns slack metadata -func (w *Webhook) GetSlackHook() *SlackMeta { - s := &SlackMeta{} - if err := json.Unmarshal([]byte(w.Meta), s); err != nil { - log.Error("webhook.GetSlackHook(%d): %v", w.ID, err) - } - return s -} - -// GetDiscordHook returns discord metadata -func (w *Webhook) GetDiscordHook() *DiscordMeta { - s := &DiscordMeta{} - if err := json.Unmarshal([]byte(w.Meta), s); err != nil { - log.Error("webhook.GetDiscordHook(%d): %v", w.ID, err) - } - return s -} - -// GetTelegramHook returns telegram metadata -func (w *Webhook) GetTelegramHook() *TelegramMeta { - s := &TelegramMeta{} - if err := json.Unmarshal([]byte(w.Meta), s); err != nil { - log.Error("webhook.GetTelegramHook(%d): %v", w.ID, err) - } - return s -} - // History returns history of webhook by given conditions. func (w *Webhook) History(page int) ([]*HookTask, error) { return HookTasks(w.ID, page) diff --git a/models/webhook_test.go b/models/webhook_test.go index 7bdaadc5ae..0fd9b245ca 100644 --- a/models/webhook_test.go +++ b/models/webhook_test.go @@ -24,18 +24,6 @@ func TestIsValidHookContentType(t *testing.T) { assert.False(t, IsValidHookContentType("invalid")) } -func TestWebhook_GetSlackHook(t *testing.T) { - w := &Webhook{ - Meta: `{"channel": "foo", "username": "username", "color": "blue"}`, - } - slackHook := w.GetSlackHook() - assert.Equal(t, *slackHook, SlackMeta{ - Channel: "foo", - Username: "username", - Color: "blue", - }) -} - func TestWebhook_History(t *testing.T) { assert.NoError(t, PrepareTestDatabase()) webhook := AssertExistsAndLoadBean(t, &Webhook{ID: 1}).(*Webhook) diff --git a/models/webhook_dingtalk.go b/modules/webhook/dingtalk.go similarity index 95% rename from models/webhook_dingtalk.go rename to modules/webhook/dingtalk.go index 1c6c0a83b8..b6d58f55cf 100644 --- a/models/webhook_dingtalk.go +++ b/modules/webhook/dingtalk.go @@ -2,13 +2,14 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package models +package webhook import ( "encoding/json" "fmt" "strings" + "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/git" api "code.gitea.io/gitea/modules/structs" @@ -184,7 +185,7 @@ func getDingtalkIssuesPayload(p *api.IssuePayload) (*DingtalkPayload, error) { func getDingtalkIssueCommentPayload(p *api.IssueCommentPayload) (*DingtalkPayload, error) { title := fmt.Sprintf("#%d: %s", p.Issue.Index, p.Issue.Title) - url := fmt.Sprintf("%s/issues/%d#%s", p.Repository.HTMLURL, p.Issue.Index, CommentHashTag(p.Comment.ID)) + url := fmt.Sprintf("%s/issues/%d#%s", p.Repository.HTMLURL, p.Issue.Index, models.CommentHashTag(p.Comment.ID)) var content string switch p.Action { case api.HookIssueCommentCreated: @@ -286,7 +287,7 @@ func getDingtalkPullRequestPayload(p *api.PullRequestPayload) (*DingtalkPayload, }, nil } -func getDingtalkPullRequestApprovalPayload(p *api.PullRequestPayload, event HookEventType) (*DingtalkPayload, error) { +func getDingtalkPullRequestApprovalPayload(p *api.PullRequestPayload, event models.HookEventType) (*DingtalkPayload, error) { var text, title string switch p.Action { case api.HookIssueSynchronized: @@ -392,29 +393,29 @@ func getDingtalkReleasePayload(p *api.ReleasePayload) (*DingtalkPayload, error) } // GetDingtalkPayload converts a ding talk webhook into a DingtalkPayload -func GetDingtalkPayload(p api.Payloader, event HookEventType, meta string) (*DingtalkPayload, error) { +func GetDingtalkPayload(p api.Payloader, event models.HookEventType, meta string) (*DingtalkPayload, error) { s := new(DingtalkPayload) switch event { - case HookEventCreate: + case models.HookEventCreate: return getDingtalkCreatePayload(p.(*api.CreatePayload)) - case HookEventDelete: + case models.HookEventDelete: return getDingtalkDeletePayload(p.(*api.DeletePayload)) - case HookEventFork: + case models.HookEventFork: return getDingtalkForkPayload(p.(*api.ForkPayload)) - case HookEventIssues: + case models.HookEventIssues: return getDingtalkIssuesPayload(p.(*api.IssuePayload)) - case HookEventIssueComment: + case models.HookEventIssueComment: return getDingtalkIssueCommentPayload(p.(*api.IssueCommentPayload)) - case HookEventPush: + case models.HookEventPush: return getDingtalkPushPayload(p.(*api.PushPayload)) - case HookEventPullRequest: + case models.HookEventPullRequest: return getDingtalkPullRequestPayload(p.(*api.PullRequestPayload)) - case HookEventPullRequestApproved, HookEventPullRequestRejected, HookEventPullRequestComment: + case models.HookEventPullRequestApproved, models.HookEventPullRequestRejected, models.HookEventPullRequestComment: return getDingtalkPullRequestApprovalPayload(p.(*api.PullRequestPayload), event) - case HookEventRepository: + case models.HookEventRepository: return getDingtalkRepositoryPayload(p.(*api.RepositoryPayload)) - case HookEventRelease: + case models.HookEventRelease: return getDingtalkReleasePayload(p.(*api.ReleasePayload)) } diff --git a/models/webhook_discord.go b/modules/webhook/discord.go similarity index 92% rename from models/webhook_discord.go rename to modules/webhook/discord.go index 32039edc9d..f92157a1ab 100644 --- a/models/webhook_discord.go +++ b/modules/webhook/discord.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package models +package webhook import ( "encoding/json" @@ -11,7 +11,9 @@ import ( "strconv" "strings" + "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" ) @@ -63,6 +65,15 @@ type ( } ) +// GetDiscordHook returns discord metadata +func GetDiscordHook(w *models.Webhook) *DiscordMeta { + s := &DiscordMeta{} + if err := json.Unmarshal([]byte(w.Meta), s); err != nil { + log.Error("webhook.GetDiscordHook(%d): %v", w.ID, err) + } + return s +} + func color(clr string) int { if clr != "" { clr = strings.TrimLeft(clr, "#") @@ -288,7 +299,7 @@ func getDiscordIssuesPayload(p *api.IssuePayload, meta *DiscordMeta) (*DiscordPa func getDiscordIssueCommentPayload(p *api.IssueCommentPayload, discord *DiscordMeta) (*DiscordPayload, error) { title := fmt.Sprintf("#%d: %s", p.Issue.Index, p.Issue.Title) - url := fmt.Sprintf("%s/issues/%d#%s", p.Repository.HTMLURL, p.Issue.Index, CommentHashTag(p.Comment.ID)) + url := fmt.Sprintf("%s/issues/%d#%s", p.Repository.HTMLURL, p.Issue.Index, models.CommentHashTag(p.Comment.ID)) content := "" var color int switch p.Action { @@ -421,7 +432,7 @@ func getDiscordPullRequestPayload(p *api.PullRequestPayload, meta *DiscordMeta) }, nil } -func getDiscordPullRequestApprovalPayload(p *api.PullRequestPayload, meta *DiscordMeta, event HookEventType) (*DiscordPayload, error) { +func getDiscordPullRequestApprovalPayload(p *api.PullRequestPayload, meta *DiscordMeta, event models.HookEventType) (*DiscordPayload, error) { var text, title string var color int switch p.Action { @@ -435,11 +446,11 @@ func getDiscordPullRequestApprovalPayload(p *api.PullRequestPayload, meta *Disco text = p.Review.Content switch event { - case HookEventPullRequestApproved: + case models.HookEventPullRequestApproved: color = greenColor - case HookEventPullRequestRejected: + case models.HookEventPullRequestRejected: color = redColor - case HookEventPullRequestComment: + case models.HookEventPullRequestComment: color = greyColor default: color = yellowColor @@ -534,7 +545,7 @@ func getDiscordReleasePayload(p *api.ReleasePayload, meta *DiscordMeta) (*Discor } // GetDiscordPayload converts a discord webhook into a DiscordPayload -func GetDiscordPayload(p api.Payloader, event HookEventType, meta string) (*DiscordPayload, error) { +func GetDiscordPayload(p api.Payloader, event models.HookEventType, meta string) (*DiscordPayload, error) { s := new(DiscordPayload) discord := &DiscordMeta{} @@ -543,40 +554,40 @@ func GetDiscordPayload(p api.Payloader, event HookEventType, meta string) (*Disc } switch event { - case HookEventCreate: + case models.HookEventCreate: return getDiscordCreatePayload(p.(*api.CreatePayload), discord) - case HookEventDelete: + case models.HookEventDelete: return getDiscordDeletePayload(p.(*api.DeletePayload), discord) - case HookEventFork: + case models.HookEventFork: return getDiscordForkPayload(p.(*api.ForkPayload), discord) - case HookEventIssues: + case models.HookEventIssues: return getDiscordIssuesPayload(p.(*api.IssuePayload), discord) - case HookEventIssueComment: + case models.HookEventIssueComment: return getDiscordIssueCommentPayload(p.(*api.IssueCommentPayload), discord) - case HookEventPush: + case models.HookEventPush: return getDiscordPushPayload(p.(*api.PushPayload), discord) - case HookEventPullRequest: + case models.HookEventPullRequest: return getDiscordPullRequestPayload(p.(*api.PullRequestPayload), discord) - case HookEventPullRequestRejected, HookEventPullRequestApproved, HookEventPullRequestComment: + case models.HookEventPullRequestRejected, models.HookEventPullRequestApproved, models.HookEventPullRequestComment: return getDiscordPullRequestApprovalPayload(p.(*api.PullRequestPayload), discord, event) - case HookEventRepository: + case models.HookEventRepository: return getDiscordRepositoryPayload(p.(*api.RepositoryPayload), discord) - case HookEventRelease: + case models.HookEventRelease: return getDiscordReleasePayload(p.(*api.ReleasePayload), discord) } return s, nil } -func parseHookPullRequestEventType(event HookEventType) (string, error) { +func parseHookPullRequestEventType(event models.HookEventType) (string, error) { switch event { - case HookEventPullRequestApproved: + case models.HookEventPullRequestApproved: return "approved", nil - case HookEventPullRequestRejected: + case models.HookEventPullRequestRejected: return "rejected", nil - case HookEventPullRequestComment: + case models.HookEventPullRequestComment: return "comment", nil default: diff --git a/models/webhook_msteams.go b/modules/webhook/msteams.go similarity index 96% rename from models/webhook_msteams.go rename to modules/webhook/msteams.go index e8cdcca3ca..2636e29983 100644 --- a/models/webhook_msteams.go +++ b/modules/webhook/msteams.go @@ -2,13 +2,14 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package models +package webhook import ( "encoding/json" "fmt" "strings" + "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/git" api "code.gitea.io/gitea/modules/structs" ) @@ -357,7 +358,7 @@ func getMSTeamsIssuesPayload(p *api.IssuePayload) (*MSTeamsPayload, error) { func getMSTeamsIssueCommentPayload(p *api.IssueCommentPayload) (*MSTeamsPayload, error) { title := fmt.Sprintf("#%d: %s", p.Issue.Index, p.Issue.Title) - url := fmt.Sprintf("%s/issues/%d#%s", p.Repository.HTMLURL, p.Issue.Index, CommentHashTag(p.Comment.ID)) + url := fmt.Sprintf("%s/issues/%d#%s", p.Repository.HTMLURL, p.Issue.Index, models.CommentHashTag(p.Comment.ID)) content := "" var color int switch p.Action { @@ -530,7 +531,7 @@ func getMSTeamsPullRequestPayload(p *api.PullRequestPayload) (*MSTeamsPayload, e }, nil } -func getMSTeamsPullRequestApprovalPayload(p *api.PullRequestPayload, event HookEventType) (*MSTeamsPayload, error) { +func getMSTeamsPullRequestApprovalPayload(p *api.PullRequestPayload, event models.HookEventType) (*MSTeamsPayload, error) { var text, title string var color int switch p.Action { @@ -544,11 +545,11 @@ func getMSTeamsPullRequestApprovalPayload(p *api.PullRequestPayload, event HookE text = p.Review.Content switch event { - case HookEventPullRequestApproved: + case models.HookEventPullRequestApproved: color = greenColor - case HookEventPullRequestRejected: + case models.HookEventPullRequestRejected: color = redColor - case HookEventPullRequestComment: + case models.HookEventPullRequestComment: color = greyColor default: color = yellowColor @@ -699,29 +700,29 @@ func getMSTeamsReleasePayload(p *api.ReleasePayload) (*MSTeamsPayload, error) { } // GetMSTeamsPayload converts a MSTeams webhook into a MSTeamsPayload -func GetMSTeamsPayload(p api.Payloader, event HookEventType, meta string) (*MSTeamsPayload, error) { +func GetMSTeamsPayload(p api.Payloader, event models.HookEventType, meta string) (*MSTeamsPayload, error) { s := new(MSTeamsPayload) switch event { - case HookEventCreate: + case models.HookEventCreate: return getMSTeamsCreatePayload(p.(*api.CreatePayload)) - case HookEventDelete: + case models.HookEventDelete: return getMSTeamsDeletePayload(p.(*api.DeletePayload)) - case HookEventFork: + case models.HookEventFork: return getMSTeamsForkPayload(p.(*api.ForkPayload)) - case HookEventIssues: + case models.HookEventIssues: return getMSTeamsIssuesPayload(p.(*api.IssuePayload)) - case HookEventIssueComment: + case models.HookEventIssueComment: return getMSTeamsIssueCommentPayload(p.(*api.IssueCommentPayload)) - case HookEventPush: + case models.HookEventPush: return getMSTeamsPushPayload(p.(*api.PushPayload)) - case HookEventPullRequest: + case models.HookEventPullRequest: return getMSTeamsPullRequestPayload(p.(*api.PullRequestPayload)) - case HookEventPullRequestRejected, HookEventPullRequestApproved, HookEventPullRequestComment: + case models.HookEventPullRequestRejected, models.HookEventPullRequestApproved, models.HookEventPullRequestComment: return getMSTeamsPullRequestApprovalPayload(p.(*api.PullRequestPayload), event) - case HookEventRepository: + case models.HookEventRepository: return getMSTeamsRepositoryPayload(p.(*api.RepositoryPayload)) - case HookEventRelease: + case models.HookEventRelease: return getMSTeamsReleasePayload(p.(*api.ReleasePayload)) } diff --git a/models/webhook_slack.go b/modules/webhook/slack.go similarity index 93% rename from models/webhook_slack.go rename to modules/webhook/slack.go index 9c179bb24a..7d844bfa50 100644 --- a/models/webhook_slack.go +++ b/modules/webhook/slack.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package models +package webhook import ( "encoding/json" @@ -10,7 +10,9 @@ import ( "fmt" "strings" + "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" ) @@ -23,6 +25,15 @@ type SlackMeta struct { Color string `json:"color"` } +// GetSlackHook returns slack metadata +func GetSlackHook(w *models.Webhook) *SlackMeta { + s := &SlackMeta{} + if err := json.Unmarshal([]byte(w.Meta), s); err != nil { + log.Error("webhook.GetSlackHook(%d): %v", w.ID, err) + } + return s +} + // SlackPayload contains the information about the slack channel type SlackPayload struct { Channel string `json:"channel"` @@ -181,7 +192,7 @@ func getSlackIssuesPayload(p *api.IssuePayload, slack *SlackMeta) (*SlackPayload func getSlackIssueCommentPayload(p *api.IssueCommentPayload, slack *SlackMeta) (*SlackPayload, error) { senderLink := SlackLinkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName) - titleLink := SlackLinkFormatter(fmt.Sprintf("%s/issues/%d#%s", p.Repository.HTMLURL, p.Issue.Index, CommentHashTag(p.Comment.ID)), + titleLink := SlackLinkFormatter(fmt.Sprintf("%s/issues/%d#%s", p.Repository.HTMLURL, p.Issue.Index, models.CommentHashTag(p.Comment.ID)), fmt.Sprintf("#%d %s", p.Issue.Index, p.Issue.Title)) var text, title, attachmentText string switch p.Action { @@ -335,7 +346,7 @@ func getSlackPullRequestPayload(p *api.PullRequestPayload, slack *SlackMeta) (*S }, nil } -func getSlackPullRequestApprovalPayload(p *api.PullRequestPayload, slack *SlackMeta, event HookEventType) (*SlackPayload, error) { +func getSlackPullRequestApprovalPayload(p *api.PullRequestPayload, slack *SlackMeta, event models.HookEventType) (*SlackPayload, error) { senderLink := SlackLinkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName) titleLink := SlackLinkFormatter(fmt.Sprintf("%s/pulls/%d", p.Repository.HTMLURL, p.Index), fmt.Sprintf("#%d %s", p.Index, p.PullRequest.Title)) @@ -388,7 +399,7 @@ func getSlackRepositoryPayload(p *api.RepositoryPayload, slack *SlackMeta) (*Sla } // GetSlackPayload converts a slack webhook into a SlackPayload -func GetSlackPayload(p api.Payloader, event HookEventType, meta string) (*SlackPayload, error) { +func GetSlackPayload(p api.Payloader, event models.HookEventType, meta string) (*SlackPayload, error) { s := new(SlackPayload) slack := &SlackMeta{} @@ -397,25 +408,25 @@ func GetSlackPayload(p api.Payloader, event HookEventType, meta string) (*SlackP } switch event { - case HookEventCreate: + case models.HookEventCreate: return getSlackCreatePayload(p.(*api.CreatePayload), slack) - case HookEventDelete: + case models.HookEventDelete: return getSlackDeletePayload(p.(*api.DeletePayload), slack) - case HookEventFork: + case models.HookEventFork: return getSlackForkPayload(p.(*api.ForkPayload), slack) - case HookEventIssues: + case models.HookEventIssues: return getSlackIssuesPayload(p.(*api.IssuePayload), slack) - case HookEventIssueComment: + case models.HookEventIssueComment: return getSlackIssueCommentPayload(p.(*api.IssueCommentPayload), slack) - case HookEventPush: + case models.HookEventPush: return getSlackPushPayload(p.(*api.PushPayload), slack) - case HookEventPullRequest: + case models.HookEventPullRequest: return getSlackPullRequestPayload(p.(*api.PullRequestPayload), slack) - case HookEventPullRequestRejected, HookEventPullRequestApproved, HookEventPullRequestComment: + case models.HookEventPullRequestRejected, models.HookEventPullRequestApproved, models.HookEventPullRequestComment: return getSlackPullRequestApprovalPayload(p.(*api.PullRequestPayload), slack, event) - case HookEventRepository: + case models.HookEventRepository: return getSlackRepositoryPayload(p.(*api.RepositoryPayload), slack) - case HookEventRelease: + case models.HookEventRelease: return getSlackReleasePayload(p.(*api.ReleasePayload), slack) } diff --git a/models/webhook_telegram.go b/modules/webhook/telegram.go similarity index 93% rename from models/webhook_telegram.go rename to modules/webhook/telegram.go index ead669dd08..4e67b22954 100644 --- a/models/webhook_telegram.go +++ b/modules/webhook/telegram.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. -package models +package webhook import ( "encoding/json" @@ -10,7 +10,9 @@ import ( "html" "strings" + "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" api "code.gitea.io/gitea/modules/structs" ) @@ -30,6 +32,15 @@ type ( } ) +// GetTelegramHook returns telegram metadata +func GetTelegramHook(w *models.Webhook) *TelegramMeta { + s := &TelegramMeta{} + if err := json.Unmarshal([]byte(w.Meta), s); err != nil { + log.Error("webhook.GetTelegramHook(%d): %v", w.ID, err) + } + return s +} + // SetSecret sets the telegram secret func (p *TelegramPayload) SetSecret(_ string) {} @@ -169,7 +180,7 @@ func getTelegramIssuesPayload(p *api.IssuePayload) (*TelegramPayload, error) { } func getTelegramIssueCommentPayload(p *api.IssueCommentPayload) (*TelegramPayload, error) { - url := fmt.Sprintf("%s/issues/%d#%s", p.Repository.HTMLURL, p.Issue.Index, CommentHashTag(p.Comment.ID)) + url := fmt.Sprintf("%s/issues/%d#%s", p.Repository.HTMLURL, p.Issue.Index, models.CommentHashTag(p.Comment.ID)) title := fmt.Sprintf(`#%d %s`, url, p.Issue.Index, html.EscapeString(p.Issue.Title)) var text string switch p.Action { @@ -214,7 +225,7 @@ func getTelegramPullRequestPayload(p *api.PullRequestPayload) (*TelegramPayload, p.PullRequest.HTMLURL, p.Index, p.PullRequest.Title) text = p.PullRequest.Body case api.HookIssueAssigned: - list, err := MakeAssigneeList(&Issue{ID: p.PullRequest.ID}) + list, err := models.MakeAssigneeList(&models.Issue{ID: p.PullRequest.ID}) if err != nil { return &TelegramPayload{}, err } @@ -297,27 +308,27 @@ func getTelegramReleasePayload(p *api.ReleasePayload) (*TelegramPayload, error) } // GetTelegramPayload converts a telegram webhook into a TelegramPayload -func GetTelegramPayload(p api.Payloader, event HookEventType, meta string) (*TelegramPayload, error) { +func GetTelegramPayload(p api.Payloader, event models.HookEventType, meta string) (*TelegramPayload, error) { s := new(TelegramPayload) switch event { - case HookEventCreate: + case models.HookEventCreate: return getTelegramCreatePayload(p.(*api.CreatePayload)) - case HookEventDelete: + case models.HookEventDelete: return getTelegramDeletePayload(p.(*api.DeletePayload)) - case HookEventFork: + case models.HookEventFork: return getTelegramForkPayload(p.(*api.ForkPayload)) - case HookEventIssues: + case models.HookEventIssues: return getTelegramIssuesPayload(p.(*api.IssuePayload)) - case HookEventIssueComment: + case models.HookEventIssueComment: return getTelegramIssueCommentPayload(p.(*api.IssueCommentPayload)) - case HookEventPush: + case models.HookEventPush: return getTelegramPushPayload(p.(*api.PushPayload)) - case HookEventPullRequest: + case models.HookEventPullRequest: return getTelegramPullRequestPayload(p.(*api.PullRequestPayload)) - case HookEventRepository: + case models.HookEventRepository: return getTelegramRepositoryPayload(p.(*api.RepositoryPayload)) - case HookEventRelease: + case models.HookEventRelease: return getTelegramReleasePayload(p.(*api.ReleasePayload)) } diff --git a/modules/webhook/webhook.go b/modules/webhook/webhook.go index 623a475df9..410e47461f 100644 --- a/modules/webhook/webhook.go +++ b/modules/webhook/webhook.go @@ -90,27 +90,27 @@ func prepareWebhook(w *models.Webhook, repo *models.Repository, event models.Hoo // Use separate objects so modifications won't be made on payload on non-Gogs/Gitea type hooks. switch w.HookTaskType { case models.SLACK: - payloader, err = models.GetSlackPayload(p, event, w.Meta) + payloader, err = GetSlackPayload(p, event, w.Meta) if err != nil { return fmt.Errorf("GetSlackPayload: %v", err) } case models.DISCORD: - payloader, err = models.GetDiscordPayload(p, event, w.Meta) + payloader, err = GetDiscordPayload(p, event, w.Meta) if err != nil { return fmt.Errorf("GetDiscordPayload: %v", err) } case models.DINGTALK: - payloader, err = models.GetDingtalkPayload(p, event, w.Meta) + payloader, err = GetDingtalkPayload(p, event, w.Meta) if err != nil { return fmt.Errorf("GetDingtalkPayload: %v", err) } case models.TELEGRAM: - payloader, err = models.GetTelegramPayload(p, event, w.Meta) + payloader, err = GetTelegramPayload(p, event, w.Meta) if err != nil { return fmt.Errorf("GetTelegramPayload: %v", err) } case models.MSTEAMS: - payloader, err = models.GetMSTeamsPayload(p, event, w.Meta) + payloader, err = GetMSTeamsPayload(p, event, w.Meta) if err != nil { return fmt.Errorf("GetMSTeamsPayload: %v", err) } diff --git a/modules/webhook/webhook_test.go b/modules/webhook/webhook_test.go index c944bc477d..e88e67e9bf 100644 --- a/modules/webhook/webhook_test.go +++ b/modules/webhook/webhook_test.go @@ -12,6 +12,18 @@ import ( "github.com/stretchr/testify/assert" ) +func TestWebhook_GetSlackHook(t *testing.T) { + w := &models.Webhook{ + Meta: `{"channel": "foo", "username": "username", "color": "blue"}`, + } + slackHook := GetSlackHook(w) + assert.Equal(t, *slackHook, SlackMeta{ + Channel: "foo", + Username: "username", + Color: "blue", + }) +} + func TestPrepareWebhooks(t *testing.T) { assert.NoError(t, models.PrepareTestDatabase()) diff --git a/routers/api/v1/convert/convert.go b/routers/api/v1/convert/convert.go index 07456f8dd6..6da53d6275 100644 --- a/routers/api/v1/convert/convert.go +++ b/routers/api/v1/convert/convert.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/webhook" "github.com/unknwon/com" ) @@ -166,7 +167,7 @@ func ToHook(repoLink string, w *models.Webhook) *api.Hook { "content_type": w.ContentType.Name(), } if w.HookTaskType == models.SLACK { - s := w.GetSlackHook() + s := webhook.GetSlackHook(w) config["channel"] = s.Channel config["username"] = s.Username config["icon_url"] = s.IconURL diff --git a/routers/api/v1/utils/hook.go b/routers/api/v1/utils/hook.go index 7903d58334..6f72e99b71 100644 --- a/routers/api/v1/utils/hook.go +++ b/routers/api/v1/utils/hook.go @@ -12,6 +12,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/webhook" "code.gitea.io/gitea/routers/api/v1/convert" "code.gitea.io/gitea/routers/utils" @@ -129,7 +130,7 @@ func addHook(ctx *context.APIContext, form *api.CreateHookOption, orgID, repoID return nil, false } - meta, err := json.Marshal(&models.SlackMeta{ + meta, err := json.Marshal(&webhook.SlackMeta{ Channel: strings.TrimSpace(channel), Username: form.Config["username"], IconURL: form.Config["icon_url"], @@ -203,7 +204,7 @@ func editHook(ctx *context.APIContext, form *api.EditHookOption, w *models.Webho if w.HookTaskType == models.SLACK { if channel, ok := form.Config["channel"]; ok { - meta, err := json.Marshal(&models.SlackMeta{ + meta, err := json.Marshal(&webhook.SlackMeta{ Channel: channel, Username: form.Config["username"], IconURL: form.Config["icon_url"], diff --git a/routers/repo/webhook.go b/routers/repo/webhook.go index a6bd3af264..9ae15882c1 100644 --- a/routers/repo/webhook.go +++ b/routers/repo/webhook.go @@ -268,7 +268,7 @@ func DiscordHooksNewPost(ctx *context.Context, form auth.NewDiscordHookForm) { return } - meta, err := json.Marshal(&models.DiscordMeta{ + meta, err := json.Marshal(&webhook.DiscordMeta{ Username: form.Username, IconURL: form.IconURL, }) @@ -357,7 +357,7 @@ func TelegramHooksNewPost(ctx *context.Context, form auth.NewTelegramHookForm) { return } - meta, err := json.Marshal(&models.TelegramMeta{ + meta, err := json.Marshal(&webhook.TelegramMeta{ BotToken: form.BotToken, ChatID: form.ChatID, }) @@ -452,7 +452,7 @@ func SlackHooksNewPost(ctx *context.Context, form auth.NewSlackHookForm) { return } - meta, err := json.Marshal(&models.SlackMeta{ + meta, err := json.Marshal(&webhook.SlackMeta{ Channel: strings.TrimSpace(form.Channel), Username: form.Username, IconURL: form.IconURL, @@ -515,11 +515,11 @@ func checkWebhook(ctx *context.Context) (*orgRepoCtx, *models.Webhook) { ctx.Data["HookType"] = w.HookTaskType.Name() switch w.HookTaskType { case models.SLACK: - ctx.Data["SlackHook"] = w.GetSlackHook() + ctx.Data["SlackHook"] = webhook.GetSlackHook(w) case models.DISCORD: - ctx.Data["DiscordHook"] = w.GetDiscordHook() + ctx.Data["DiscordHook"] = webhook.GetDiscordHook(w) case models.TELEGRAM: - ctx.Data["TelegramHook"] = w.GetTelegramHook() + ctx.Data["TelegramHook"] = webhook.GetTelegramHook(w) } ctx.Data["History"], err = w.History(1) @@ -646,7 +646,7 @@ func SlackHooksEditPost(ctx *context.Context, form auth.NewSlackHookForm) { return } - meta, err := json.Marshal(&models.SlackMeta{ + meta, err := json.Marshal(&webhook.SlackMeta{ Channel: strings.TrimSpace(form.Channel), Username: form.Username, IconURL: form.IconURL, @@ -690,7 +690,7 @@ func DiscordHooksEditPost(ctx *context.Context, form auth.NewDiscordHookForm) { return } - meta, err := json.Marshal(&models.DiscordMeta{ + meta, err := json.Marshal(&webhook.DiscordMeta{ Username: form.Username, IconURL: form.IconURL, }) @@ -763,7 +763,7 @@ func TelegramHooksEditPost(ctx *context.Context, form auth.NewTelegramHookForm) ctx.HTML(200, orCtx.NewTemplate) return } - meta, err := json.Marshal(&models.TelegramMeta{ + meta, err := json.Marshal(&webhook.TelegramMeta{ BotToken: form.BotToken, ChatID: form.ChatID, }) From 2282c659ddab12dc4ffd505585a3b39b59c14908 Mon Sep 17 00:00:00 2001 From: Ramon Fischer Date: Mon, 4 Nov 2019 05:42:30 +0100 Subject: [PATCH 09/23] Explicity indicate the socket unit to use the service unit "gitea.service" (#8804) * rename socket file, make example more precise, use long parameter name * correct path * use the correct path to the configuration file according to the documentation * rename the socket unit back to 'gitea.main.socket', explicitly indicate that the socket unit should use the service file 'gitea.service' --- contrib/systemd/gitea.service | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contrib/systemd/gitea.service b/contrib/systemd/gitea.service index b5aa6ffcb5..a69588893b 100644 --- a/contrib/systemd/gitea.service +++ b/contrib/systemd/gitea.service @@ -30,7 +30,8 @@ After=network.target ## PartOf=gitea.service ## ## [Socket] -## ListenStream= +## Service=gitea.service +## ListenStream= ## NoDelay=true ## ## [Install] @@ -53,7 +54,7 @@ WorkingDirectory=/var/lib/gitea/ # If using unix socket: Tells Systemd to create /run/gitea folder to home gitea.sock # Manual cration would vanish after reboot. #RuntimeDirectory=gitea -ExecStart=/usr/local/bin/gitea web -c /etc/gitea/app.ini +ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini Restart=always Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea # If you want to bind Gitea to a port below 1024, uncomment From ee5249889d7f9f3fbda4aa87dd3202753ed595cb Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Mon, 4 Nov 2019 04:52:17 +0000 Subject: [PATCH 10/23] [skip ci] Updated translations via Crowdin --- options/locale/locale_ja-JP.ini | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini index 3e25b16eee..c26bbfd4a6 100644 --- a/options/locale/locale_ja-JP.ini +++ b/options/locale/locale_ja-JP.ini @@ -741,6 +741,7 @@ editor.no_changes_to_show=表示する変更箇所はありません。 editor.fail_to_update_file=ファイル '%s' を作成または変更できませんでした: %v editor.add_subdir=ディレクトリを追加… editor.unable_to_upload_files='%s' へファイルをアップロードすることができませんでした: %v +editor.upload_file_is_locked=%[2]s がファイル '%[1]s' をロックしています。 editor.upload_files_to_dir='%s' にファイルをアップロード editor.cannot_commit_to_protected_branch=保護されたブランチ '%s' にコミットすることはできません。 @@ -1379,8 +1380,20 @@ settings.unarchive.success=リポジトリのアーカイブを解除しまし settings.unarchive.error=リポジトリのアーカイブ解除でエラーが発生しました。 詳細はログを確認してください。 settings.update_avatar_success=リポジトリのアバターを更新しました。 settings.lfs=LFS +settings.lfs_filelist=このリポジトリに含まれているLFSファイル +settings.lfs_no_lfs_files=このリポジトリにLFSファイルはありません +settings.lfs_findcommits=コミットを検索 +settings.lfs_lfs_file_no_commits=このLFSファイルに関するコミットはありません settings.lfs_delete=LFSファイル(OID %s)の削除 settings.lfs_delete_warning=LFSファイルを削除すると、チェックアウトのときに 'object does not exist' エラーが発生するかもしれません。 よろしいですか? +settings.lfs_findpointerfiles=ポインタファイルを検索 +settings.lfs_pointers.found=%d件のblobポインタ - 登録済 %d件、未登録 %d件 (実体ファイルなし %d件) +settings.lfs_pointers.sha=Blob SHA +settings.lfs_pointers.oid=OID +settings.lfs_pointers.inRepo=Repo内 +settings.lfs_pointers.exists=実体ファイルあり +settings.lfs_pointers.accessible=ユーザーがアクセス可 +settings.lfs_pointers.associateAccessible=アクセス可能な%d件のOIDを登録 diff.browse_source=ソースを参照 diff.parent=親 From 0471aae348ea9e225ceaaa9049e0d40ece972877 Mon Sep 17 00:00:00 2001 From: Wenxuan Zhao Date: Mon, 4 Nov 2019 02:20:12 -0800 Subject: [PATCH 11/23] Fix: remove duplicated signed commit icons (#8820) Signed-off-by: Wenxuan Zhao --- templates/repo/commits_list.tmpl | 65 ++++++++++++++++---------------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/templates/repo/commits_list.tmpl b/templates/repo/commits_list.tmpl index 177c434724..dee9dab2b5 100644 --- a/templates/repo/commits_list.tmpl +++ b/templates/repo/commits_list.tmpl @@ -13,56 +13,55 @@ {{range $r}} - {{$userName := .Author.Name}} + {{$userName := .Author.Name}} {{if .User}} {{if .User.FullName}} - {{$userName = .User.FullName}} + {{$userName = .User.FullName}} {{end}} -   {{$userName}} +   {{$userName}} {{else}}   {{$userName}} {{end}} - {{$class := "ui sha label"}} - {{if .Signature}} - {{$class = (printf "%s%s" $class " isSigned")}} - {{if .Verification.Verified}} - {{$class = (printf "%s%s" $class " isVerified")}} - {{else if .Verification.Warning}} - {{$class = (printf "%s%s" $class " isWarning")}} - {{end}} - {{end}} - {{if $.Reponame}} - - {{else}} - - {{end}} + {{$class := "ui sha label"}} + {{if .Signature}} + {{$class = (printf "%s%s" $class " isSigned")}} + {{if .Verification.Verified}} + {{$class = (printf "%s%s" $class " isVerified")}} + {{else if .Verification.Warning}} + {{$class = (printf "%s%s" $class " isWarning")}} + {{end}} + {{end}} + {{if $.Reponame}} + + {{else}} + + {{end}} {{ShortSha .ID.String}} {{if .Signature}}
{{if .Verification.Verified}} - {{if ne .Verification.SigningUser.ID 0}} - - {{else}} - - - - - {{end}} + + {{else}} + + + + + {{end}} {{else if .Verification.Warning}} - - {{else}} + + {{else}} {{end}}
{{end}} - {{if $.Reponame}} -
- {{else}} - - {{end}} + {{if $.Reponame}} + + {{else}} + + {{end}} @@ -73,7 +72,7 @@ {{end}} {{if eq (CommitType .) "SignCommitWithStatuses"}} - {{template "repo/commit_status" .Status}} + {{template "repo/commit_status" .Status}} {{end}} {{if IsMultilineCommitMessage .Message}} From 3fb9e3afe36e72f855272eb6c43d47824e414117 Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Mon, 4 Nov 2019 10:23:49 +0000 Subject: [PATCH 12/23] [skip ci] Updated translations via Crowdin --- options/locale/locale_ja-JP.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini index c26bbfd4a6..47b4f37f63 100644 --- a/options/locale/locale_ja-JP.ini +++ b/options/locale/locale_ja-JP.ini @@ -741,7 +741,7 @@ editor.no_changes_to_show=表示する変更箇所はありません。 editor.fail_to_update_file=ファイル '%s' を作成または変更できませんでした: %v editor.add_subdir=ディレクトリを追加… editor.unable_to_upload_files='%s' へファイルをアップロードすることができませんでした: %v -editor.upload_file_is_locked=%[2]s がファイル '%[1]s' をロックしています。 +editor.upload_file_is_locked=ファイル '%[1]s' は %[2]s がロックしています。 editor.upload_files_to_dir='%s' にファイルをアップロード editor.cannot_commit_to_protected_branch=保護されたブランチ '%s' にコミットすることはできません。 From 86a44f6b48cf4e814452a71d97e42e486237a307 Mon Sep 17 00:00:00 2001 From: Lauris BH Date: Mon, 4 Nov 2019 21:10:37 +0200 Subject: [PATCH 13/23] Fix new user form for non-local users (#8826) --- routers/admin/users.go | 20 +++++++++++--------- templates/admin/user/new.tmpl | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/routers/admin/users.go b/routers/admin/users.go index fdc4e0e371..2284f21838 100644 --- a/routers/admin/users.go +++ b/routers/admin/users.go @@ -79,12 +79,11 @@ func NewUserPost(ctx *context.Context, form auth.AdminCreateUserForm) { } u := &models.User{ - Name: form.UserName, - Email: form.Email, - Passwd: form.Password, - IsActive: true, - LoginType: models.LoginPlain, - MustChangePassword: form.MustChangePassword, + Name: form.UserName, + Email: form.Email, + Passwd: form.Password, + IsActive: true, + LoginType: models.LoginPlain, } if len(form.LoginType) > 0 { @@ -95,9 +94,12 @@ func NewUserPost(ctx *context.Context, form auth.AdminCreateUserForm) { u.LoginName = form.LoginName } } - if !password.IsComplexEnough(form.Password) { - ctx.RenderWithErr(ctx.Tr("form.password_complexity"), tplUserNew, &form) - return + if u.LoginType == models.LoginPlain { + if !password.IsComplexEnough(form.Password) { + ctx.RenderWithErr(ctx.Tr("form.password_complexity"), tplUserNew, &form) + return + } + u.MustChangePassword = form.MustChangePassword } if err := models.CreateUser(u); err != nil { switch { diff --git a/templates/admin/user/new.tmpl b/templates/admin/user/new.tmpl index b9e326e734..06b7d70efe 100644 --- a/templates/admin/user/new.tmpl +++ b/templates/admin/user/new.tmpl @@ -42,7 +42,7 @@ -
+
From 8d8aecd3cfe842fa9024af0bf568063859741cd9 Mon Sep 17 00:00:00 2001 From: 6543 <24977596+6543@users.noreply.github.com> Date: Tue, 5 Nov 2019 01:12:58 +0100 Subject: [PATCH 14/23] README: Update Screenshots and Badges in ZH (#8813) * use relative instead of absolute paths * update badges of ZH readme * update screenshots * use