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 9fca069f0a42..4bc6a3b99434 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 ac93db57c02a..4ad9ff39bcbb 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 a50765c4b479..4b401b513162 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 b0e7b4cae827..ff865f19cf84 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 3524a53c1554..c10e1b634045 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 70b1541e3525..6532f9d614aa 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 a969ad74f793..13d33e10114f 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 79f6406c535d..e5f6bf871879 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 a9ce189c0301..ba9e896dd50e 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 69699f24c1d9..f441c3e42c0f 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 4bb612a67176..95cd4eeb1a2f 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 7e920ac03208..02f0c46f22e1 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 bd39f9ea444b..b27c757faa52 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 722d245afc49..c4ec7d416a9b 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 1534c45df0a0..186e66cb8f8c 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 9264c00cec61..6d86105a15d1 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 41e5353ea73b..17b8eab6c5e2 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 000000000000..15228f65e75a --- /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 6532f9d614aa..1fd30229406b 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 13d33e10114f..7d28c1c8b983 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 ee2f176a4337..aa06ba409730 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 0a4c4a7eeeca..20939c397fa4 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 d3a8b52d86a0..7eb17caaf666 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 7bdaadc5ae95..0fd9b245caf9 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 1c6c0a83b8b3..b6d58f55cfea 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 32039edc9d5a..f92157a1ab4f 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 e8cdcca3ca21..2636e299830c 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 9c179bb24a07..7d844bfa5064 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 ead669dd0823..4e67b22954a3 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 623a475df9b7..410e47461fe6 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 c944bc477d3b..e88e67e9bfef 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 07456f8dd687..6da53d62750c 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 7903d58334ac..6f72e99b714a 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 a6bd3af264a3..9ae15882c148 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 b5aa6ffcb5ca..a69588893b29 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 3e25b16eee56..c26bbfd4a665 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 177c434724ff..dee9dab2b53b 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 c26bbfd4a665..47b4f37f6367 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 fdc4e0e371b4..2284f21838c6 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 b9e326e73495..06b7d70efe35 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