From 47246da8d3f50a02d11b77b3d402618b144aa720 Mon Sep 17 00:00:00 2001 From: Earl Warren <contact@earl-warren.org> Date: Sat, 14 Jan 2023 10:07:01 +0100 Subject: [PATCH] [BRANDING] [v1.20] define the forgejo webhook type templates/swagger/v1_json.tmpl updated with `make generate-swagger` (cherry picked from commit 88899c492efeedd138ba088a36b9c0bc733ead7b) (cherry picked from commit 7171bd9617c32c4911e3bdbc23c02a19e80d2465) (cherry picked from commit 1a742446c17aef9ca62fe75bfc0a388d40138154) (cherry picked from commit d7c189d7b2f9fea299a31adf068db969920ae39d) Conflicts: routers/web/web.go (cherry picked from commit cbdea868e41fb38ca491f8b449c3e525ec82d6b9) (cherry picked from commit 6cd150483b06e17aee023c0afd01a3f2460b3415) --- modules/setting/webhook.go | 2 +- modules/structs/hook.go | 2 +- modules/webhook/type.go | 1 + routers/web/repo/webhook.go | 28 +++++++++++++ routers/web/web.go | 2 + services/webhook/webhook.go | 4 +- templates/admin/hook_new.tmpl | 7 +++- templates/org/settings/hook_new.tmpl | 6 ++- .../repo/settings/webhook/base_list.tmpl | 5 ++- templates/repo/settings/webhook/forgejo.tmpl | 40 +++++++++++++++++++ templates/repo/settings/webhook/new.tmpl | 7 +++- templates/swagger/v1_json.tmpl | 1 + templates/user/settings/hook_new.tmpl | 4 +- tests/integration/links_test.go | 30 ++++++++++++++ 14 files changed, 127 insertions(+), 12 deletions(-) create mode 100644 templates/repo/settings/webhook/forgejo.tmpl diff --git a/modules/setting/webhook.go b/modules/setting/webhook.go index c01261dbbd..b56c55c439 100644 --- a/modules/setting/webhook.go +++ b/modules/setting/webhook.go @@ -35,7 +35,7 @@ func loadWebhookFrom(rootCfg ConfigProvider) { Webhook.DeliverTimeout = sec.Key("DELIVER_TIMEOUT").MustInt(5) Webhook.SkipTLSVerify = sec.Key("SKIP_TLS_VERIFY").MustBool() Webhook.AllowedHostList = sec.Key("ALLOWED_HOST_LIST").MustString("") - Webhook.Types = []string{"gitea", "gogs", "slack", "discord", "dingtalk", "telegram", "msteams", "feishu", "matrix", "wechatwork", "packagist"} + Webhook.Types = []string{"forgejo", "gitea", "gogs", "slack", "discord", "dingtalk", "telegram", "msteams", "feishu", "matrix", "wechatwork", "packagist"} Webhook.PagingNum = sec.Key("PAGING_NUM").MustInt(10) Webhook.ProxyURL = sec.Key("PROXY_URL").MustString("") if Webhook.ProxyURL != "" { diff --git a/modules/structs/hook.go b/modules/structs/hook.go index df5da6790f..5055561a4b 100644 --- a/modules/structs/hook.go +++ b/modules/structs/hook.go @@ -40,7 +40,7 @@ type CreateHookOptionConfig map[string]string // CreateHookOption options when create a hook type CreateHookOption struct { // required: true - // enum: dingtalk,discord,gitea,gogs,msteams,slack,telegram,feishu,wechatwork,packagist + // enum: forgejo,dingtalk,discord,gitea,gogs,msteams,slack,telegram,feishu,wechatwork,packagist Type string `json:"type" binding:"Required"` // required: true Config CreateHookOptionConfig `json:"config" binding:"Required"` diff --git a/modules/webhook/type.go b/modules/webhook/type.go index db4ab17931..fac5590e21 100644 --- a/modules/webhook/type.go +++ b/modules/webhook/type.go @@ -71,6 +71,7 @@ type HookType = string // Types of webhooks const ( + FORGEJO HookType = "forgejo" GITEA HookType = "gitea" GOGS HookType = "gogs" SLACK HookType = "slack" diff --git a/routers/web/repo/webhook.go b/routers/web/repo/webhook.go index f30588967e..aedbe27596 100644 --- a/routers/web/repo/webhook.go +++ b/routers/web/repo/webhook.go @@ -307,6 +307,34 @@ func editWebhook(ctx *context.Context, params webhookParams) { ctx.Redirect(fmt.Sprintf("%s/%d", orCtx.Link, w.ID)) } +// ForgejoHooksNewPost response for creating Forgejo webhook +func ForgejoHooksNewPost(ctx *context.Context) { + createWebhook(ctx, forgejoHookParams(ctx)) +} + +// ForgejoHooksEditPost response for editing Forgejo webhook +func ForgejoHooksEditPost(ctx *context.Context) { + editWebhook(ctx, forgejoHookParams(ctx)) +} + +func forgejoHookParams(ctx *context.Context) webhookParams { + form := web.GetForm(ctx).(*forms.NewWebhookForm) + + contentType := webhook.ContentTypeJSON + if webhook.HookContentType(form.ContentType) == webhook.ContentTypeForm { + contentType = webhook.ContentTypeForm + } + + return webhookParams{ + Type: webhook_module.FORGEJO, + URL: form.PayloadURL, + ContentType: contentType, + Secret: form.Secret, + HTTPMethod: form.HTTPMethod, + WebhookForm: form.WebhookForm, + } +} + // GiteaHooksNewPost response for creating Gitea webhook func GiteaHooksNewPost(ctx *context.Context) { createWebhook(ctx, giteaHookParams(ctx)) diff --git a/routers/web/web.go b/routers/web/web.go index 00ccff85f3..78a687055d 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -318,6 +318,7 @@ func RegisterRoutes(m *web.Route) { addWebhookAddRoutes := func() { m.Get("/{type}/new", repo.WebhooksNew) + m.Post("/forgejo/new", web.Bind(forms.NewWebhookForm{}), repo.ForgejoHooksNewPost) m.Post("/gitea/new", web.Bind(forms.NewWebhookForm{}), repo.GiteaHooksNewPost) m.Post("/gogs/new", web.Bind(forms.NewGogshookForm{}), repo.GogsHooksNewPost) m.Post("/slack/new", web.Bind(forms.NewSlackHookForm{}), repo.SlackHooksNewPost) @@ -332,6 +333,7 @@ func RegisterRoutes(m *web.Route) { } addWebhookEditRoutes := func() { + m.Post("/forgejo/{id}", web.Bind(forms.NewWebhookForm{}), repo.ForgejoHooksEditPost) m.Post("/gitea/{id}", web.Bind(forms.NewWebhookForm{}), repo.GiteaHooksEditPost) m.Post("/gogs/{id}", web.Bind(forms.NewGogshookForm{}), repo.GogsHooksEditPost) m.Post("/slack/{id}", web.Bind(forms.NewSlackHookForm{}), repo.SlackHooksEditPost) diff --git a/services/webhook/webhook.go b/services/webhook/webhook.go index b862d5bff1..bdbacd7512 100644 --- a/services/webhook/webhook.go +++ b/services/webhook/webhook.go @@ -69,7 +69,7 @@ var webhooks = map[webhook_module.HookType]*webhook{ // IsValidHookTaskType returns true if a webhook registered func IsValidHookTaskType(name string) bool { - if name == webhook_module.GITEA || name == webhook_module.GOGS { + if name == webhook_module.FORGEJO || name == webhook_module.GITEA || name == webhook_module.GOGS { return true } _, ok := webhooks[name] @@ -172,7 +172,7 @@ func PrepareWebhook(ctx context.Context, w *webhook_model.Webhook, event webhook // Avoid sending "0 new commits" to non-integration relevant webhooks (e.g. slack, discord, etc.). // Integration webhooks (e.g. drone) still receive the required data. if pushEvent, ok := p.(*api.PushPayload); ok && - w.Type != webhook_module.GITEA && w.Type != webhook_module.GOGS && + w.Type != webhook_module.FORGEJO && w.Type != webhook_module.GITEA && w.Type != webhook_module.GOGS && len(pushEvent.Commits) == 0 { return nil } diff --git a/templates/admin/hook_new.tmpl b/templates/admin/hook_new.tmpl index 0c018ff293..f15a1c20f4 100644 --- a/templates/admin/hook_new.tmpl +++ b/templates/admin/hook_new.tmpl @@ -14,8 +14,10 @@ {{.locale.Tr "admin.defaulthooks.update_webhook"}} {{end}} <div class="ui right"> - {{if eq .HookType "gitea"}} - <img width="26" height="26" src="{{AssetUrlPrefix}}/img/gitea.svg"> + {{if eq .HookType "forgejo"}} + <img width="26" height="26" src="{{AssetUrlPrefix}}/img/forgejo.svg"> + {{else if eq .HookType "gitea"}} + <img width="26" height="26" src="{{AssetUrlPrefix}}/img/gitea-original.svg"> {{else if eq .HookType "gogs"}} <img width="26" height="26" src="{{AssetUrlPrefix}}/img/gogs.ico"> {{else if eq .HookType "slack"}} @@ -40,6 +42,7 @@ </div> </h4> <div class="ui attached segment"> + {{template "repo/settings/webhook/forgejo" .}} {{template "repo/settings/webhook/gitea" .}} {{template "repo/settings/webhook/gogs" .}} {{template "repo/settings/webhook/slack" .}} diff --git a/templates/org/settings/hook_new.tmpl b/templates/org/settings/hook_new.tmpl index 4685225f4c..35c26c4465 100644 --- a/templates/org/settings/hook_new.tmpl +++ b/templates/org/settings/hook_new.tmpl @@ -9,8 +9,10 @@ <h4 class="ui top attached header"> {{if .PageIsSettingsHooksNew}}{{.locale.Tr "repo.settings.add_webhook"}}{{else}}{{.locale.Tr "repo.settings.update_webhook"}}{{end}} <div class="ui right"> - {{if eq .HookType "gitea"}} - <img width="26" height="26" src="{{AssetUrlPrefix}}/img/gitea.svg"> + {{if eq .HookType "forgejo"}} + <img width="26" height="26" src="{{AssetUrlPrefix}}/img/forgejo.svg"> + {{else if eq .HookType "gitea"}} + <img width="26" height="26" src="{{AssetUrlPrefix}}/img/gitea-original.svg"> {{else if eq .HookType "gogs"}} <img width="26" height="26" src="{{AssetUrlPrefix}}/img/gogs.ico"> {{else if eq .HookType "slack"}} diff --git a/templates/repo/settings/webhook/base_list.tmpl b/templates/repo/settings/webhook/base_list.tmpl index 61c5799513..6c69e3a2a0 100644 --- a/templates/repo/settings/webhook/base_list.tmpl +++ b/templates/repo/settings/webhook/base_list.tmpl @@ -4,8 +4,11 @@ <div class="ui floating1 jump dropdown"> <div class="ui primary tiny button">{{.locale.Tr "repo.settings.add_webhook"}}</div> <div class="menu"> + <a class="item" href="{{.BaseLinkNew}}/forgejo/new"> + <img width="20" height="20" src="{{AssetUrlPrefix}}/img/forgejo.svg">{{.locale.Tr "repo.settings.web_hook_name_forgejo"}} + </a> <a class="item" href="{{.BaseLinkNew}}/gitea/new"> - <img width="20" height="20" src="{{AssetUrlPrefix}}/img/gitea.svg">{{.locale.Tr "repo.settings.web_hook_name_gitea"}} + <img width="20" height="20" src="{{AssetUrlPrefix}}/img/gitea-original.svg">{{.locale.Tr "repo.settings.web_hook_name_gitea"}} </a> <a class="item" href="{{.BaseLinkNew}}/gogs/new"> <img width="20" height="20" src="{{AssetUrlPrefix}}/img/gogs.ico">{{.locale.Tr "repo.settings.web_hook_name_gogs"}} diff --git a/templates/repo/settings/webhook/forgejo.tmpl b/templates/repo/settings/webhook/forgejo.tmpl new file mode 100644 index 0000000000..0d733f3362 --- /dev/null +++ b/templates/repo/settings/webhook/forgejo.tmpl @@ -0,0 +1,40 @@ +{{if eq .HookType "forgejo"}} + <p>{{.locale.Tr "repo.settings.add_web_hook_desc" "https://docs.gitea.io/en-us/webhooks/" (.locale.Tr "repo.settings.web_hook_name_forgejo") | Str2html}}</p> + <form class="ui form" action="{{.BaseLink}}/forgejo/{{or .Webhook.ID "new"}}" method="post"> + {{template "base/disable_form_autofill"}} + {{.CsrfTokenHtml}} + <div class="required field {{if .Err_PayloadURL}}error{{end}}"> + <label for="payload_url">{{.locale.Tr "repo.settings.payload_url"}}</label> + <input id="payload_url" name="payload_url" type="url" value="{{.Webhook.URL}}" autofocus required> + </div> + <div class="field"> + <label>{{.locale.Tr "repo.settings.http_method"}}</label> + <div class="ui selection dropdown"> + <input type="hidden" id="http_method" name="http_method" value="{{if .Webhook.HTTPMethod}}{{.Webhook.HTTPMethod}}{{else}}POST{{end}}"> + <div class="default text"></div> + {{svg "octicon-triangle-down" 14 "dropdown icon"}} + <div class="menu"> + <div class="item" data-value="POST">POST</div> + <div class="item" data-value="GET">GET</div> + </div> + </div> + </div> + <div class="field"> + <label>{{.locale.Tr "repo.settings.content_type"}}</label> + <div class="ui selection dropdown"> + <input type="hidden" id="content_type" name="content_type" value="{{if .Webhook.ContentType}}{{.Webhook.ContentType}}{{else}}1{{end}}"> + <div class="default text"></div> + {{svg "octicon-triangle-down" 14 "dropdown icon"}} + <div class="menu"> + <div class="item" data-value="1">application/json</div> + <div class="item" data-value="2">application/x-www-form-urlencoded</div> + </div> + </div> + </div> + <div class="field {{if .Err_Secret}}error{{end}}"> + <label for="secret">{{.locale.Tr "repo.settings.secret"}}</label> + <input id="secret" name="secret" type="password" value="{{.Webhook.Secret}}" autocomplete="off"> + </div> + {{template "repo/settings/webhook/settings" .}} + </form> +{{end}} diff --git a/templates/repo/settings/webhook/new.tmpl b/templates/repo/settings/webhook/new.tmpl index 5102390db9..c0ee082e25 100644 --- a/templates/repo/settings/webhook/new.tmpl +++ b/templates/repo/settings/webhook/new.tmpl @@ -7,8 +7,10 @@ <h4 class="ui top attached header"> {{if .PageIsSettingsHooksNew}}{{.locale.Tr "repo.settings.add_webhook"}}{{else}}{{.locale.Tr "repo.settings.update_webhook"}}{{end}} <div class="ui right"> - {{if eq .HookType "gitea"}} - <img width="26" height="26" src="{{AssetUrlPrefix}}/img/gitea.svg"> + {{if eq .HookType "forgejo"}} + <img width="26" height="26" src="{{AssetUrlPrefix}}/img/forgejo.svg"> + {{else if eq .HookType "gitea"}} + <img width="26" height="26" src="{{AssetUrlPrefix}}/img/gitea-original.svg"> {{else if eq .HookType "gogs"}} <img width="26" height="26" src="{{AssetUrlPrefix}}/img/gogs.ico"> {{else if eq .HookType "slack"}} @@ -33,6 +35,7 @@ </div> </h4> <div class="ui attached segment"> + {{template "repo/settings/webhook/forgejo" .}} {{template "repo/settings/webhook/gitea" .}} {{template "repo/settings/webhook/gogs" .}} {{template "repo/settings/webhook/slack" .}} diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 440cd66399..ee694d5678 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -15550,6 +15550,7 @@ "type": { "type": "string", "enum": [ + "forgejo", "dingtalk", "discord", "gitea", diff --git a/templates/user/settings/hook_new.tmpl b/templates/user/settings/hook_new.tmpl index 20aaf65f62..95a9ff65b5 100644 --- a/templates/user/settings/hook_new.tmpl +++ b/templates/user/settings/hook_new.tmpl @@ -7,7 +7,9 @@ <h4 class="ui top attached header"> {{if .PageIsSettingsHooksNew}}{{.locale.Tr "repo.settings.add_webhook"}}{{else}}{{.locale.Tr "repo.settings.update_webhook"}}{{end}} <div class="ui right"> - {{if eq .HookType "gitea"}} + {{if eq .HookType "forgejo"}} + <img width="26" height="26" src="{{AssetUrlPrefix}}/img/forgejo.svg"> + {{else if eq .HookType "gitea"}} <img width="26" height="26" src="{{AssetUrlPrefix}}/img/gitea.svg"> {{else if eq .HookType "gogs"}} <img width="26" height="26" src="{{AssetUrlPrefix}}/img/gogs.ico"> diff --git a/tests/integration/links_test.go b/tests/integration/links_test.go index 9136f8f915..74d9fe20cb 100644 --- a/tests/integration/links_test.go +++ b/tests/integration/links_test.go @@ -173,3 +173,33 @@ func TestLinksLogin(t *testing.T) { testLinksAsUser("user2", t) } + +func TestRedirectsWebhooks(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + // + // A redirect means the route exists but not if it performs as intended. + // + for _, kind := range []string{"forgejo", "gitea"} { + redirects := []struct { + from string + to string + verb string + }{ + {from: "/user2/repo1/settings/hooks/" + kind + "/new", to: "/user/login", verb: "GET"}, + {from: "/user/settings/hooks/" + kind + "/new", to: "/user/login", verb: "GET"}, + {from: "/admin/system-hooks/" + kind + "/new", to: "/user/login", verb: "GET"}, + {from: "/admin/default-hooks/" + kind + "/new", to: "/user/login", verb: "GET"}, + {from: "/user2/repo1/settings/hooks/" + kind + "/new", to: "/", verb: "POST"}, + {from: "/admin/system-hooks/" + kind + "/new", to: "/", verb: "POST"}, + {from: "/admin/default-hooks/" + kind + "/new", to: "/", verb: "POST"}, + {from: "/user2/repo1/settings/hooks/" + kind + "/1", to: "/", verb: "POST"}, + {from: "/admin/hooks/" + kind + "/1", to: "/", verb: "POST"}, + } + for _, info := range redirects { + req := NewRequest(t, info.verb, info.from) + resp := MakeRequest(t, req, http.StatusSeeOther) + assert.EqualValues(t, path.Join(setting.AppSubURL, info.to), test.RedirectURL(resp), info.from) + } + } +}