[BRANDING] 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)
(cherry picked from commit 47246da8d3f50a02d11b77b3d402618b144aa720)
(cherry picked from commit f2aa0e6b769d432e627798bcf294b04b7d253213)
(cherry picked from commit 5a4fc69a16de8d6199ea24198299297ef7a3587b)
(cherry picked from commit 48e444ca09c22f930514a01846b0c8bc3cef35ab)
(cherry picked from commit 888e53781175d8d977f66d78991bd66563fcddfb)
(cherry picked from commit 5121f493c99f19d8050aa09224ac3532b4100ec7)
(cherry picked from commit 9394e55fdf80bf3d7bf8b2aba561ad44a84e3913)
(cherry picked from commit 3a2ce51768de65892e3ec73596e3862354c9502e)
(cherry picked from commit 719ead3a651f12afbb59c856914b0085e5cee157)
(cherry picked from commit 83e6f82e2aea619a3cd502e133773d33c0e60133)
(cherry picked from commit 494a429b21c6234be38b9e3db0f930fbb8118205)
(cherry picked from commit d30c90c0abf0cea6437719da34824ae176385fdd)
(cherry picked from commit 3c83b325c45b2baba5b941df8b5938838e68a52c)
(cherry picked from commit 470bffae63433e867edb1eb5b37744ad9d984124)
(cherry picked from commit 1d659217197d4aa74daf569d8b2752f841fc6c22)
(cherry picked from commit c101c2e0b921f4d93b217ff4e91ee6e28deec60c)
This commit is contained in:
Earl Warren 2023-01-14 10:07:01 +01:00
parent 7635da25dc
commit 02ba08ca84
No known key found for this signature in database
GPG key ID: 0579CB2928A78A00
14 changed files with 127 additions and 12 deletions

View file

@ -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 != "" {

View file

@ -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"`

View file

@ -72,6 +72,7 @@ type HookType = string
// Types of webhooks
const (
FORGEJO HookType = "forgejo"
GITEA HookType = "gitea"
GOGS HookType = "gogs"
SLACK HookType = "slack"

View file

@ -309,6 +309,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))

View file

@ -286,6 +286,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)
@ -300,6 +301,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)

View file

@ -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
}

View file

@ -11,8 +11,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"}}
@ -37,6 +39,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" .}}

View file

@ -3,8 +3,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"}}

View file

@ -4,8 +4,11 @@
<div class="ui 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"}}

View file

@ -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}}

View file

@ -3,8 +3,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"}}
@ -29,6 +31,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" .}}

View file

@ -16735,6 +16735,7 @@
"type": {
"type": "string",
"enum": [
"forgejo",
"dingtalk",
"discord",
"gitea",

View file

@ -4,7 +4,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">

View file

@ -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)
}
}
}