diff options
author | James Lakin <jamesorlakin@users.noreply.github.com> | 2020-03-08 22:08:05 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-09 00:08:05 +0200 |
commit | a9f4489bbcb7b406721582bfc3bbd7e7c7f2a04f (patch) | |
tree | 23ec6f541ffbdecb932a124c8f029a07f89bf204 /routers | |
parent | b8551f8532ef7b98cdd8522440b3ff20f39b49f5 (diff) | |
download | gitea-a9f4489bbcb7b406721582bfc3bbd7e7c7f2a04f.tar.gz gitea-a9f4489bbcb7b406721582bfc3bbd7e7c7f2a04f.zip |
System-wide webhooks (#10546)
* Create system webhook column (and migration)
* Create system webhook DB methods
Based on the default webhook ones
* Modify router to handle system webhooks and default ones
* Remove old unused admin nav template
* Adjust orgRepoCtx to differentiate system and default webhook URLs
* Assign IsSystemWebhook when creating webhooks
* Correctly use booleans for IsSystemWebhook
* Use system webhooks when preparing webhooks for payload
* Add UI and locale changes
* Use router params to differentiate admin hook pages
* Fix deleting admin webhooks and rename method
* Add clarity to webhook docs
* Revert "Remove old unused admin nav template"
This reverts commit 191a20a7389fe5f6256b0ad6aafd04b9b0e295c5.
* Rename WebHooksNewPost to GiteaHooksNewPost for clarity
* Reintroduce blank line lost during merge conflict
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Lauris BH <lauris@nix.lv>
Diffstat (limited to 'routers')
-rw-r--r-- | routers/admin/hooks.go | 49 | ||||
-rw-r--r-- | routers/repo/webhook.go | 179 | ||||
-rw-r--r-- | routers/routes/routes.go | 12 |
3 files changed, 142 insertions, 98 deletions
diff --git a/routers/admin/hooks.go b/routers/admin/hooks.go index b80ed3cc3c..4697c4d933 100644 --- a/routers/admin/hooks.go +++ b/routers/admin/hooks.go @@ -12,20 +12,32 @@ import ( ) const ( - // tplAdminHooks template path for render hook settings + // tplAdminHooks template path to render hook settings tplAdminHooks base.TplName = "admin/hooks" ) -// DefaultWebhooks render admin-default webhook list page -func DefaultWebhooks(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("admin.hooks") - ctx.Data["PageIsAdminHooks"] = true - ctx.Data["BaseLink"] = setting.AppSubURL + "/admin/hooks" - ctx.Data["Description"] = ctx.Tr("admin.hooks.desc") +// DefaultOrSystemWebhooks renders both admin default and system webhook list pages +func DefaultOrSystemWebhooks(ctx *context.Context) { + var ws []*models.Webhook + var err error + + // Are we looking at default webhooks? + if ctx.Params(":configType") == "hooks" { + ctx.Data["Title"] = ctx.Tr("admin.hooks") + ctx.Data["Description"] = ctx.Tr("admin.hooks.desc") + ctx.Data["PageIsAdminHooks"] = true + ctx.Data["BaseLink"] = setting.AppSubURL + "/admin/hooks" + ws, err = models.GetDefaultWebhooks() + } else { + ctx.Data["Title"] = ctx.Tr("admin.systemhooks") + ctx.Data["Description"] = ctx.Tr("admin.systemhooks.desc") + ctx.Data["PageIsAdminSystemHooks"] = true + ctx.Data["BaseLink"] = setting.AppSubURL + "/admin/system-hooks" + ws, err = models.GetSystemWebhooks() + } - ws, err := models.GetDefaultWebhooks() if err != nil { - ctx.ServerError("GetWebhooksDefaults", err) + ctx.ServerError("GetWebhooksAdmin", err) return } @@ -33,15 +45,22 @@ func DefaultWebhooks(ctx *context.Context) { ctx.HTML(200, tplAdminHooks) } -// DeleteDefaultWebhook response for delete admin-default webhook -func DeleteDefaultWebhook(ctx *context.Context) { - if err := models.DeleteDefaultWebhook(ctx.QueryInt64("id")); err != nil { +// DeleteDefaultOrSystemWebhook handler to delete an admin-defined system or default webhook +func DeleteDefaultOrSystemWebhook(ctx *context.Context) { + if err := models.DeleteDefaultSystemWebhook(ctx.QueryInt64("id")); err != nil { ctx.Flash.Error("DeleteDefaultWebhook: " + err.Error()) } else { ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success")) } - ctx.JSON(200, map[string]interface{}{ - "redirect": setting.AppSubURL + "/admin/hooks", - }) + // Are we looking at default webhooks? + if ctx.Params(":configType") == "hooks" { + ctx.JSON(200, map[string]interface{}{ + "redirect": setting.AppSubURL + "/admin/hooks", + }) + } else { + ctx.JSON(200, map[string]interface{}{ + "redirect": setting.AppSubURL + "/admin/system-hooks", + }) + } } diff --git a/routers/repo/webhook.go b/routers/repo/webhook.go index cf6ff27542..94c610fe54 100644 --- a/routers/repo/webhook.go +++ b/routers/repo/webhook.go @@ -49,14 +49,15 @@ func Webhooks(ctx *context.Context) { } type orgRepoCtx struct { - OrgID int64 - RepoID int64 - IsAdmin bool - Link string - NewTemplate base.TplName + OrgID int64 + RepoID int64 + IsAdmin bool + IsSystemWebhook bool + Link string + NewTemplate base.TplName } -// getOrgRepoCtx determines whether this is a repo, organization, or admin context. +// getOrgRepoCtx determines whether this is a repo, organization, or admin (both default and system) context. func getOrgRepoCtx(ctx *context.Context) (*orgRepoCtx, error) { if len(ctx.Repo.RepoLink) > 0 { return &orgRepoCtx{ @@ -75,10 +76,21 @@ func getOrgRepoCtx(ctx *context.Context) (*orgRepoCtx, error) { } if ctx.User.IsAdmin { + // Are we looking at default webhooks? + if ctx.Params(":configType") == "hooks" { + return &orgRepoCtx{ + IsAdmin: true, + Link: path.Join(setting.AppSubURL, "/admin/hooks"), + NewTemplate: tplAdminHookNew, + }, nil + } + + // Must be system webhooks instead return &orgRepoCtx{ - IsAdmin: true, - Link: path.Join(setting.AppSubURL, "/admin/hooks"), - NewTemplate: tplAdminHookNew, + IsAdmin: true, + IsSystemWebhook: true, + Link: path.Join(setting.AppSubURL, "/admin/system-hooks"), + NewTemplate: tplAdminHookNew, }, nil } @@ -105,7 +117,10 @@ func WebhooksNew(ctx *context.Context) { return } - if orCtx.IsAdmin { + if orCtx.IsAdmin && orCtx.IsSystemWebhook { + ctx.Data["PageIsAdminSystemHooks"] = true + ctx.Data["PageIsAdminSystemHooksNew"] = true + } else if orCtx.IsAdmin { ctx.Data["PageIsAdminHooks"] = true ctx.Data["PageIsAdminHooksNew"] = true } else { @@ -159,8 +174,8 @@ func ParseHookEvent(form auth.WebhookForm) *models.HookEvent { } } -// WebHooksNewPost response for creating webhook -func WebHooksNewPost(ctx *context.Context, form auth.NewWebhookForm) { +// GiteaHooksNewPost response for creating Gitea webhook +func GiteaHooksNewPost(ctx *context.Context, form auth.NewWebhookForm) { ctx.Data["Title"] = ctx.Tr("repo.settings.add_webhook") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksNew"] = true @@ -185,15 +200,16 @@ func WebHooksNewPost(ctx *context.Context, form auth.NewWebhookForm) { } w := &models.Webhook{ - RepoID: orCtx.RepoID, - URL: form.PayloadURL, - HTTPMethod: form.HTTPMethod, - ContentType: contentType, - Secret: form.Secret, - HookEvent: ParseHookEvent(form.WebhookForm), - IsActive: form.Active, - HookTaskType: models.GITEA, - OrgID: orCtx.OrgID, + RepoID: orCtx.RepoID, + URL: form.PayloadURL, + HTTPMethod: form.HTTPMethod, + ContentType: contentType, + Secret: form.Secret, + HookEvent: ParseHookEvent(form.WebhookForm), + IsActive: form.Active, + HookTaskType: models.GITEA, + OrgID: orCtx.OrgID, + IsSystemWebhook: orCtx.IsSystemWebhook, } if err := w.UpdateEvent(); err != nil { ctx.ServerError("UpdateEvent", err) @@ -238,14 +254,15 @@ func newGogsWebhookPost(ctx *context.Context, form auth.NewGogshookForm, kind mo } w := &models.Webhook{ - RepoID: orCtx.RepoID, - URL: form.PayloadURL, - ContentType: contentType, - Secret: form.Secret, - HookEvent: ParseHookEvent(form.WebhookForm), - IsActive: form.Active, - HookTaskType: kind, - OrgID: orCtx.OrgID, + RepoID: orCtx.RepoID, + URL: form.PayloadURL, + ContentType: contentType, + Secret: form.Secret, + HookEvent: ParseHookEvent(form.WebhookForm), + IsActive: form.Active, + HookTaskType: kind, + OrgID: orCtx.OrgID, + IsSystemWebhook: orCtx.IsSystemWebhook, } if err := w.UpdateEvent(); err != nil { ctx.ServerError("UpdateEvent", err) @@ -287,14 +304,15 @@ func DiscordHooksNewPost(ctx *context.Context, form auth.NewDiscordHookForm) { } w := &models.Webhook{ - RepoID: orCtx.RepoID, - URL: form.PayloadURL, - ContentType: models.ContentTypeJSON, - HookEvent: ParseHookEvent(form.WebhookForm), - IsActive: form.Active, - HookTaskType: models.DISCORD, - Meta: string(meta), - OrgID: orCtx.OrgID, + RepoID: orCtx.RepoID, + URL: form.PayloadURL, + ContentType: models.ContentTypeJSON, + HookEvent: ParseHookEvent(form.WebhookForm), + IsActive: form.Active, + HookTaskType: models.DISCORD, + Meta: string(meta), + OrgID: orCtx.OrgID, + IsSystemWebhook: orCtx.IsSystemWebhook, } if err := w.UpdateEvent(); err != nil { ctx.ServerError("UpdateEvent", err) @@ -327,14 +345,15 @@ func DingtalkHooksNewPost(ctx *context.Context, form auth.NewDingtalkHookForm) { } w := &models.Webhook{ - RepoID: orCtx.RepoID, - URL: form.PayloadURL, - ContentType: models.ContentTypeJSON, - HookEvent: ParseHookEvent(form.WebhookForm), - IsActive: form.Active, - HookTaskType: models.DINGTALK, - Meta: "", - OrgID: orCtx.OrgID, + RepoID: orCtx.RepoID, + URL: form.PayloadURL, + ContentType: models.ContentTypeJSON, + HookEvent: ParseHookEvent(form.WebhookForm), + IsActive: form.Active, + HookTaskType: models.DINGTALK, + Meta: "", + OrgID: orCtx.OrgID, + IsSystemWebhook: orCtx.IsSystemWebhook, } if err := w.UpdateEvent(); err != nil { ctx.ServerError("UpdateEvent", err) @@ -376,14 +395,15 @@ func TelegramHooksNewPost(ctx *context.Context, form auth.NewTelegramHookForm) { } w := &models.Webhook{ - RepoID: orCtx.RepoID, - URL: fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage?chat_id=%s", form.BotToken, form.ChatID), - ContentType: models.ContentTypeJSON, - HookEvent: ParseHookEvent(form.WebhookForm), - IsActive: form.Active, - HookTaskType: models.TELEGRAM, - Meta: string(meta), - OrgID: orCtx.OrgID, + RepoID: orCtx.RepoID, + URL: fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage?chat_id=%s", form.BotToken, form.ChatID), + ContentType: models.ContentTypeJSON, + HookEvent: ParseHookEvent(form.WebhookForm), + IsActive: form.Active, + HookTaskType: models.TELEGRAM, + Meta: string(meta), + OrgID: orCtx.OrgID, + IsSystemWebhook: orCtx.IsSystemWebhook, } if err := w.UpdateEvent(); err != nil { ctx.ServerError("UpdateEvent", err) @@ -416,14 +436,15 @@ func MSTeamsHooksNewPost(ctx *context.Context, form auth.NewMSTeamsHookForm) { } w := &models.Webhook{ - RepoID: orCtx.RepoID, - URL: form.PayloadURL, - ContentType: models.ContentTypeJSON, - HookEvent: ParseHookEvent(form.WebhookForm), - IsActive: form.Active, - HookTaskType: models.MSTEAMS, - Meta: "", - OrgID: orCtx.OrgID, + RepoID: orCtx.RepoID, + URL: form.PayloadURL, + ContentType: models.ContentTypeJSON, + HookEvent: ParseHookEvent(form.WebhookForm), + IsActive: form.Active, + HookTaskType: models.MSTEAMS, + Meta: "", + OrgID: orCtx.OrgID, + IsSystemWebhook: orCtx.IsSystemWebhook, } if err := w.UpdateEvent(); err != nil { ctx.ServerError("UpdateEvent", err) @@ -473,14 +494,15 @@ func SlackHooksNewPost(ctx *context.Context, form auth.NewSlackHookForm) { } w := &models.Webhook{ - RepoID: orCtx.RepoID, - URL: form.PayloadURL, - ContentType: models.ContentTypeJSON, - HookEvent: ParseHookEvent(form.WebhookForm), - IsActive: form.Active, - HookTaskType: models.SLACK, - Meta: string(meta), - OrgID: orCtx.OrgID, + RepoID: orCtx.RepoID, + URL: form.PayloadURL, + ContentType: models.ContentTypeJSON, + HookEvent: ParseHookEvent(form.WebhookForm), + IsActive: form.Active, + HookTaskType: models.SLACK, + Meta: string(meta), + OrgID: orCtx.OrgID, + IsSystemWebhook: orCtx.IsSystemWebhook, } if err := w.UpdateEvent(); err != nil { ctx.ServerError("UpdateEvent", err) @@ -513,14 +535,15 @@ func FeishuHooksNewPost(ctx *context.Context, form auth.NewFeishuHookForm) { } w := &models.Webhook{ - RepoID: orCtx.RepoID, - URL: form.PayloadURL, - ContentType: models.ContentTypeJSON, - HookEvent: ParseHookEvent(form.WebhookForm), - IsActive: form.Active, - HookTaskType: models.FEISHU, - Meta: "", - OrgID: orCtx.OrgID, + RepoID: orCtx.RepoID, + URL: form.PayloadURL, + ContentType: models.ContentTypeJSON, + HookEvent: ParseHookEvent(form.WebhookForm), + IsActive: form.Active, + HookTaskType: models.FEISHU, + Meta: "", + OrgID: orCtx.OrgID, + IsSystemWebhook: orCtx.IsSystemWebhook, } if err := w.UpdateEvent(); err != nil { ctx.ServerError("UpdateEvent", err) @@ -549,6 +572,8 @@ func checkWebhook(ctx *context.Context) (*orgRepoCtx, *models.Webhook) { w, err = models.GetWebhookByRepoID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")) } else if orCtx.OrgID > 0 { w, err = models.GetWebhookByOrgID(ctx.Org.Organization.ID, ctx.ParamsInt64(":id")) + } else if orCtx.IsSystemWebhook { + w, err = models.GetSystemWebhook(ctx.ParamsInt64(":id")) } else { w, err = models.GetDefaultWebhook(ctx.ParamsInt64(":id")) } diff --git a/routers/routes/routes.go b/routers/routes/routes.go index 0b0b4e05a3..093edcd920 100644 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -458,11 +458,11 @@ func RegisterRoutes(m *macaron.Macaron) { m.Post("/delete", admin.DeleteRepo) }) - m.Group("/hooks", func() { - m.Get("", admin.DefaultWebhooks) - m.Post("/delete", admin.DeleteDefaultWebhook) + m.Group("/^:configType(hooks|system-hooks)$", func() { + m.Get("", admin.DefaultOrSystemWebhooks) + m.Post("/delete", admin.DeleteDefaultOrSystemWebhook) m.Get("/:type/new", repo.WebhooksNew) - m.Post("/gitea/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost) + m.Post("/gitea/new", bindIgnErr(auth.NewWebhookForm{}), repo.GiteaHooksNewPost) m.Post("/gogs/new", bindIgnErr(auth.NewGogshookForm{}), repo.GogsHooksNewPost) m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost) m.Post("/discord/new", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksNewPost) @@ -569,7 +569,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("", org.Webhooks) m.Post("/delete", org.DeleteWebhook) m.Get("/:type/new", repo.WebhooksNew) - m.Post("/gitea/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost) + m.Post("/gitea/new", bindIgnErr(auth.NewWebhookForm{}), repo.GiteaHooksNewPost) m.Post("/gogs/new", bindIgnErr(auth.NewGogshookForm{}), repo.GogsHooksNewPost) m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost) m.Post("/discord/new", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksNewPost) @@ -635,7 +635,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("", repo.Webhooks) m.Post("/delete", repo.DeleteWebhook) m.Get("/:type/new", repo.WebhooksNew) - m.Post("/gitea/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost) + m.Post("/gitea/new", bindIgnErr(auth.NewWebhookForm{}), repo.GiteaHooksNewPost) m.Post("/gogs/new", bindIgnErr(auth.NewGogshookForm{}), repo.GogsHooksNewPost) m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost) m.Post("/discord/new", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksNewPost) |