Skip to content
3 changes: 3 additions & 0 deletions models/webhook/hooktask.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const (
HookEventPullRequestReviewRejected HookEventType = "pull_request_review_rejected"
HookEventPullRequestReviewComment HookEventType = "pull_request_review_comment"
HookEventPullRequestSync HookEventType = "pull_request_sync"
HookEventWiki HookEventType = "wiki"
HookEventRepository HookEventType = "repository"
HookEventRelease HookEventType = "release"
HookEventPackage HookEventType = "package"
Expand Down Expand Up @@ -76,6 +77,8 @@ func (h HookEventType) Event() string {
return "pull_request_rejected"
case HookEventPullRequestReviewComment:
return "pull_request_comment"
case HookEventWiki:
return "wiki"
case HookEventRepository:
return "repository"
case HookEventRelease:
Expand Down
8 changes: 8 additions & 0 deletions models/webhook/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ type HookEvents struct {
PullRequestComment bool `json:"pull_request_comment"`
PullRequestReview bool `json:"pull_request_review"`
PullRequestSync bool `json:"pull_request_sync"`
Wiki bool `json:"wiki"`
Repository bool `json:"repository"`
Release bool `json:"release"`
Package bool `json:"package"`
Expand Down Expand Up @@ -328,6 +329,12 @@ func (w *Webhook) HasPullRequestSyncEvent() bool {
(w.ChooseEvents && w.HookEvents.PullRequestSync)
}

// HasWikiEvent returns true if hook enabled wiki event.
func (w *Webhook) HasWikiEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvent.Wiki)
}

// HasReleaseEvent returns if hook enabled release event.
func (w *Webhook) HasReleaseEvent() bool {
return w.SendEverything ||
Expand Down Expand Up @@ -373,6 +380,7 @@ func (w *Webhook) EventCheckers() []struct {
{w.HasPullRequestRejectedEvent, HookEventPullRequestReviewRejected},
{w.HasPullRequestCommentEvent, HookEventPullRequestReviewComment},
{w.HasPullRequestSyncEvent, HookEventPullRequestSync},
{w.HasWikiEvent, HookEventWiki},
{w.HasRepositoryEvent, HookEventRepository},
{w.HasReleaseEvent, HookEventRelease},
{w.HasPackageEvent, HookEventPackage},
Expand Down
2 changes: 1 addition & 1 deletion models/webhook/webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func TestWebhook_EventsArray(t *testing.T) {
"issues", "issue_assign", "issue_label", "issue_milestone", "issue_comment",
"pull_request", "pull_request_assign", "pull_request_label", "pull_request_milestone",
"pull_request_comment", "pull_request_review_approved", "pull_request_review_rejected",
"pull_request_review_comment", "pull_request_sync", "repository", "release",
"pull_request_review_comment", "pull_request_sync", "wiki", "repository", "release",
"package",
},
(&Webhook{
Expand Down
3 changes: 3 additions & 0 deletions modules/notification/base/notifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ type Notifier interface {
issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User)
NotifyUpdateComment(*user_model.User, *issues_model.Comment, string)
NotifyDeleteComment(*user_model.User, *issues_model.Comment)
NotifyNewWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string)
NotifyEditWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update is a better word than Edit here imo

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also thought about that when naming it. There is an "UpdateRelease" and an "UpdateComment", so It would be consistent with that. But this is the only place where I find the word "Update", there are other "synonyms" in use like "Change", which makes semantically more sense in that cases. So I don't "break the rule" in naming the notifier for editing a wiki page EditWikiPage to keep it semantically consistent. Take a look at all the notifiers (here). The names follow semantic names instead of consistent "CRUD"-like names. If EditWikiPage should be renamed to UpdateWikiPage, I also need to rename NewWikiPage to CreateWikiPage to bring it in line with some other actions. What do you think @lunny?

NotifyDeleteWikiPage(doer *user_model.User, repo *repo_model.Repository, page string)
NotifyNewRelease(rel *models.Release)
NotifyUpdateRelease(doer *user_model.User, rel *models.Release)
NotifyDeleteRelease(doer *user_model.User, rel *models.Release)
Expand Down
12 changes: 12 additions & 0 deletions modules/notification/base/null.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,18 @@ func (*NullNotifier) NotifyUpdateComment(doer *user_model.User, c *issues_model.
func (*NullNotifier) NotifyDeleteComment(doer *user_model.User, c *issues_model.Comment) {
}

// NotifyNewWikiPage places a place holder function
func (*NullNotifier) NotifyNewWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) {
}

// NotifyEditWikiPage places a place holder function
func (*NullNotifier) NotifyEditWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) {
}

// NotifyDeleteWikiPage places a place holder function
func (*NullNotifier) NotifyDeleteWikiPage(doer *user_model.User, repo *repo_model.Repository, page string) {
}

// NotifyNewRelease places a place holder function
func (*NullNotifier) NotifyNewRelease(rel *models.Release) {
}
Expand Down
21 changes: 21 additions & 0 deletions modules/notification/notification.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,27 @@ func NewContext() {
RegisterNotifier(mirror.NewNotifier())
}

// NotifyNewWikiPage notifies creating new wiki pages to notifiers
func NotifyNewWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) {
for _, notifier := range notifiers {
notifier.NotifyNewWikiPage(doer, repo, page, comment)
}
}

// NotifyEditWikiPage notifies editing or renaming wiki pages to notifiers
func NotifyEditWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) {
for _, notifier := range notifiers {
notifier.NotifyEditWikiPage(doer, repo, page, comment)
}
}

// NotifyDeleteWikiPage notifies deleting wiki pages to notifiers
func NotifyDeleteWikiPage(doer *user_model.User, repo *repo_model.Repository, page string) {
for _, notifier := range notifiers {
notifier.NotifyDeleteWikiPage(doer, repo, page)
}
}

// NotifyCreateIssueComment notifies issue comment related message to notifiers
func NotifyCreateIssueComment(doer *user_model.User, repo *repo_model.Repository,
issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User,
Expand Down
38 changes: 38 additions & 0 deletions modules/notification/webhook/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,44 @@ func (m *webhookNotifier) NotifyDeleteComment(doer *user_model.User, comment *is
}
}

func (m *webhookNotifier) NotifyNewWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) {
// Add to hook queue for created wiki page.
if err := webhook_services.PrepareWebhooks(repo, webhook.HookEventWiki, &api.WikiPayload{
Action: api.HookWikiCreated,
Repository: convert.ToRepo(repo, perm.AccessModeOwner),
Sender: convert.ToUser(doer, nil),
Page: page,
Comment: comment,
}); err != nil {
log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err)
}
}

func (m *webhookNotifier) NotifyEditWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) {
// Add to hook queue for edit wiki page.
if err := webhook_services.PrepareWebhooks(repo, webhook.HookEventWiki, &api.WikiPayload{
Action: api.HookWikiEdited,
Repository: convert.ToRepo(repo, perm.AccessModeOwner),
Sender: convert.ToUser(doer, nil),
Page: page,
Comment: comment,
}); err != nil {
log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err)
}
}

func (m *webhookNotifier) NotifyDeleteWikiPage(doer *user_model.User, repo *repo_model.Repository, page string) {
// Add to hook queue for edit wiki page.
if err := webhook_services.PrepareWebhooks(repo, webhook.HookEventWiki, &api.WikiPayload{
Action: api.HookWikiDeleted,
Repository: convert.ToRepo(repo, perm.AccessModeOwner),
Sender: convert.ToUser(doer, nil),
Page: page,
}); err != nil {
log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err)
}
}

func (m *webhookNotifier) NotifyIssueChangeLabels(doer *user_model.User, issue *issues_model.Issue,
addedLabels, removedLabels []*issues_model.Label,
) {
Expand Down
33 changes: 33 additions & 0 deletions modules/structs/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,39 @@ type ReviewPayload struct {
Content string `json:"content"`
}

// __ __.__ __ .__
// / \ / \__| | _|__|
// \ \/\/ / | |/ / |
// \ /| | <| |
// \__/\ / |__|__|_ \__|
// \/ \/

// HookWikiAction an action that happens to a wiki page
type HookWikiAction string

const (
// HookWikiCreated created
HookWikiCreated HookWikiAction = "created"
// HookWikiEdited edited
HookWikiEdited HookWikiAction = "edited"
// HookWikiDeleted deleted
HookWikiDeleted HookWikiAction = "deleted"
)

// WikiPayload payload for repository webhooks
type WikiPayload struct {
Action HookWikiAction `json:"action"`
Repository *Repository `json:"repository"`
Sender *User `json:"sender"`
Page string `json:"page"`
Comment string `json:"comment"`
}

// JSONPayload JSON representation of the payload
func (p *WikiPayload) JSONPayload() ([]byte, error) {
return json.MarshalIndent(p, "", " ")
}

//__________ .__ __
//\______ \ ____ ______ ____ _____|__|/ |_ ___________ ___.__.
// | _// __ \\____ \ / _ \/ ___/ \ __\/ _ \_ __ < | |
Expand Down
2 changes: 2 additions & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -1951,6 +1951,8 @@ settings.event_delete = Delete
settings.event_delete_desc = Branch or tag deleted.
settings.event_fork = Fork
settings.event_fork_desc = Repository forked.
settings.event_wiki = Wiki
settings.event_wiki_desc = Wiki page created, renamed, edited or deleted.
settings.event_release = Release
settings.event_release_desc = Release published, updated or deleted in a repository.
settings.event_push = Push
Expand Down
5 changes: 5 additions & 0 deletions routers/api/v1/repo/wiki.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/convert"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/notification"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
Expand Down Expand Up @@ -85,6 +86,7 @@ func NewWikiPage(ctx *context.APIContext) {
wikiPage := getWikiPage(ctx, wikiName)

if !ctx.Written() {
notification.NotifyNewWikiPage(ctx.Doer, ctx.Repo.Repository, wikiName, form.Message)
ctx.JSON(http.StatusCreated, wikiPage)
}
}
Expand Down Expand Up @@ -152,6 +154,7 @@ func EditWikiPage(ctx *context.APIContext) {
wikiPage := getWikiPage(ctx, newWikiName)

if !ctx.Written() {
notification.NotifyEditWikiPage(ctx.Doer, ctx.Repo.Repository, newWikiName, form.Message)
ctx.JSON(http.StatusOK, wikiPage)
}
}
Expand Down Expand Up @@ -242,6 +245,8 @@ func DeleteWikiPage(ctx *context.APIContext) {
return
}

notification.NotifyDeleteWikiPage(ctx.Doer, ctx.Repo.Repository, wikiName)

ctx.Status(http.StatusNoContent)
}

Expand Down
2 changes: 2 additions & 0 deletions routers/api/v1/utils/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ func addHook(ctx *context.APIContext, form *api.CreateHookOption, orgID, repoID
PullRequestComment: pullHook(form.Events, string(webhook.HookEventPullRequestComment)),
PullRequestReview: pullHook(form.Events, "pull_request_review"),
PullRequestSync: pullHook(form.Events, string(webhook.HookEventPullRequestSync)),
Wiki: util.IsStringInSlice(string(webhook.HookEventWiki), form.Events, true),
Repository: util.IsStringInSlice(string(webhook.HookEventRepository), form.Events, true),
Release: util.IsStringInSlice(string(webhook.HookEventRelease), form.Events, true),
},
Expand Down Expand Up @@ -249,6 +250,7 @@ func editHook(ctx *context.APIContext, form *api.EditHookOption, w *webhook.Webh
w.Delete = util.IsStringInSlice(string(webhook.HookEventDelete), form.Events, true)
w.Fork = util.IsStringInSlice(string(webhook.HookEventFork), form.Events, true)
w.Repository = util.IsStringInSlice(string(webhook.HookEventRepository), form.Events, true)
w.Wiki = util.IsStringInSlice(string(webhook.HookEventWiki), form.Events, true)
w.Release = util.IsStringInSlice(string(webhook.HookEventRelease), form.Events, true)
w.BranchFilter = form.BranchFilter

Expand Down
1 change: 1 addition & 0 deletions routers/web/repo/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ func ParseHookEvent(form forms.WebhookForm) *webhook.HookEvent {
PullRequestComment: form.PullRequestComment,
PullRequestReview: form.PullRequestReview,
PullRequestSync: form.PullRequestSync,
Wiki: form.Wiki,
Repository: form.Repository,
Package: form.Package,
},
Expand Down
7 changes: 7 additions & 0 deletions routers/web/repo/wiki.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/notification"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
Expand Down Expand Up @@ -705,6 +706,8 @@ func NewWikiPost(ctx *context.Context) {
return
}

notification.NotifyNewWikiPage(ctx.Doer, ctx.Repo.Repository, wikiName, form.Message)

ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + wiki_service.NameToSubURL(wikiName))
}

Expand Down Expand Up @@ -747,6 +750,8 @@ func EditWikiPost(ctx *context.Context) {
return
}

notification.NotifyEditWikiPage(ctx.Doer, ctx.Repo.Repository, newWikiName, form.Message)

ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + wiki_service.NameToSubURL(newWikiName))
}

Expand All @@ -762,6 +767,8 @@ func DeleteWikiPagePost(ctx *context.Context) {
return
}

notification.NotifyDeleteWikiPage(ctx.Doer, ctx.Repo.Repository, wikiName)

ctx.JSON(http.StatusOK, map[string]interface{}{
"redirect": ctx.Repo.RepoLink + "/wiki/",
})
Expand Down
13 changes: 7 additions & 6 deletions services/forms/repo_form.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,12 +215,12 @@ func (f *ProtectBranchForm) Validate(req *http.Request, errs binding.Errors) bin
return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
}

// __ __ ___. .__ .__ __
// / \ / \ ____\_ |__ | |__ | |__ ____ | | __
// \ \/\/ // __ \| __ \| | \| | \ / _ \| |/ /
// \ /\ ___/| \_\ \ Y \ Y ( <_> ) <
// \__/\ / \___ >___ /___| /___| /\____/|__|_ \
// \/ \/ \/ \/ \/ \/
// __ __ ___. .__ __
// / \ / \ ____\_ |__ | |__ ____ ____ | | __
// \ \/\/ // __ \| __ \| | \ / _ \ / _ \| |/ /
// \ /\ ___/| \_\ \ Y ( <_> | <_> ) <
// \__/\ / \___ >___ /___| /\____/ \____/|__|_ \
// \/ \/ \/ \/ \/

// WebhookForm form for changing web hook
type WebhookForm struct {
Expand All @@ -242,6 +242,7 @@ type WebhookForm struct {
PullRequestComment bool
PullRequestReview bool
PullRequestSync bool
Wiki bool
Repository bool
Package bool
Active bool
Expand Down
8 changes: 8 additions & 0 deletions services/webhook/dingtalk.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,14 @@ func (d *DingtalkPayload) Issue(p *api.IssuePayload) (api.Payloader, error) {
return createDingtalkPayload(issueTitle, text+"\r\n\r\n"+attachmentText, "view issue", p.Issue.HTMLURL), nil
}

// Wiki implements PayloadConvertor Wiki method
func (d *DingtalkPayload) Wiki(p *api.WikiPayload) (api.Payloader, error) {
text, _, _ := getWikiPayloadInfo(p, noneLinkFormatter, true)
url := p.Repository.HTMLURL + "/wiki/" + url.PathEscape(p.Page)

return createDingtalkPayload(text, text, "view wiki", url), nil
}

// IssueComment implements PayloadConvertor IssueComment method
func (d *DingtalkPayload) IssueComment(p *api.IssueCommentPayload) (api.Payloader, error) {
text, issueTitle, _ := getIssueCommentPayloadInfo(p, noneLinkFormatter, true)
Expand Down
38 changes: 38 additions & 0 deletions services/webhook/dingtalk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,44 @@ func TestDingTalkPayload(t *testing.T) {
assert.Equal(t, "http://localhost:3000/test/repo", parseRealSingleURL(pl.(*DingtalkPayload).ActionCard.SingleURL))
})

t.Run("Wiki", func(t *testing.T) {
p := wikiTestPayload()

d := new(DingtalkPayload)
p.Action = api.HookWikiCreated
pl, err := d.Wiki(p)
require.NoError(t, err)
require.NotNil(t, pl)
require.IsType(t, &DingtalkPayload{}, pl)

assert.Equal(t, "[test/repo] New wiki page 'index' (Wiki change comment) by user1", pl.(*DingtalkPayload).ActionCard.Text)
assert.Equal(t, "[test/repo] New wiki page 'index' (Wiki change comment) by user1", pl.(*DingtalkPayload).ActionCard.Title)
assert.Equal(t, "view wiki", pl.(*DingtalkPayload).ActionCard.SingleTitle)
assert.Equal(t, "http://localhost:3000/test/repo/wiki/index", parseRealSingleURL(pl.(*DingtalkPayload).ActionCard.SingleURL))

p.Action = api.HookWikiEdited
pl, err = d.Wiki(p)
require.NoError(t, err)
require.NotNil(t, pl)
require.IsType(t, &DingtalkPayload{}, pl)

assert.Equal(t, "[test/repo] Wiki page 'index' edited (Wiki change comment) by user1", pl.(*DingtalkPayload).ActionCard.Text)
assert.Equal(t, "[test/repo] Wiki page 'index' edited (Wiki change comment) by user1", pl.(*DingtalkPayload).ActionCard.Title)
assert.Equal(t, "view wiki", pl.(*DingtalkPayload).ActionCard.SingleTitle)
assert.Equal(t, "http://localhost:3000/test/repo/wiki/index", parseRealSingleURL(pl.(*DingtalkPayload).ActionCard.SingleURL))

p.Action = api.HookWikiDeleted
pl, err = d.Wiki(p)
require.NoError(t, err)
require.NotNil(t, pl)
require.IsType(t, &DingtalkPayload{}, pl)

assert.Equal(t, "[test/repo] Wiki page 'index' deleted by user1", pl.(*DingtalkPayload).ActionCard.Text)
assert.Equal(t, "[test/repo] Wiki page 'index' deleted by user1", pl.(*DingtalkPayload).ActionCard.Title)
assert.Equal(t, "view wiki", pl.(*DingtalkPayload).ActionCard.SingleTitle)
assert.Equal(t, "http://localhost:3000/test/repo/wiki/index", parseRealSingleURL(pl.(*DingtalkPayload).ActionCard.SingleURL))
})

t.Run("Release", func(t *testing.T) {
p := pullReleaseTestPayload()

Expand Down
Loading