* 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 191a20a738
.
* 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>
tags/v1.12.0-dev
# Webhooks | # Webhooks | ||||
Gitea supports web hooks for repository events. This can be found in the settings | |||||
page `/:username/:reponame/settings/hooks`. All event pushes are POST requests. | |||||
The methods currently supported are: | |||||
Gitea supports web hooks for repository events. This can be configured in the settings | |||||
page `/:username/:reponame/settings/hooks` by a repository admin. Webhooks can also be configured on a per-organization and whole system basis. | |||||
All event pushes are POST requests. The methods currently supported are: | |||||
- Gitea | |||||
- Gitea (can also be a GET request) | |||||
- Gogs | - Gogs | ||||
- Slack | - Slack | ||||
- Discord | - Discord | ||||
- Dingtalk | - Dingtalk | ||||
- Telegram | - Telegram | ||||
- Microsoft Teams | - Microsoft Teams | ||||
- Feishu | |||||
### Event information | ### Event information | ||||
The following is an example of event information that will be sent by Gitea to | The following is an example of event information that will be sent by Gitea to | ||||
a Payload URL: | a Payload URL: | ||||
``` | ``` | ||||
X-GitHub-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 | X-GitHub-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473 | ||||
X-GitHub-Event: push | X-GitHub-Event: push |
NewMigration("remove dependencies from deleted repositories", purgeUnusedDependencies), | NewMigration("remove dependencies from deleted repositories", purgeUnusedDependencies), | ||||
// v130 -> v131 | // v130 -> v131 | ||||
NewMigration("Expand webhooks for more granularity", expandWebhooks), | NewMigration("Expand webhooks for more granularity", expandWebhooks), | ||||
// v131 -> v132 | |||||
NewMigration("Add IsSystemWebhook column to webhooks table", addSystemWebhookColumn), | |||||
} | } | ||||
// Migrate database to current version | // Migrate database to current version |
// Copyright 2020 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 migrations | |||||
import ( | |||||
"fmt" | |||||
"xorm.io/xorm" | |||||
) | |||||
func addSystemWebhookColumn(x *xorm.Engine) error { | |||||
type Webhook struct { | |||||
IsSystemWebhook bool `xorm:"NOT NULL DEFAULT false"` | |||||
} | |||||
if err := x.Sync2(new(Webhook)); err != nil { | |||||
return fmt.Errorf("Sync2: %v", err) | |||||
} | |||||
return nil | |||||
} |
// Webhook represents a web hook object. | // Webhook represents a web hook object. | ||||
type Webhook struct { | type Webhook struct { | ||||
ID int64 `xorm:"pk autoincr"` | |||||
RepoID int64 `xorm:"INDEX"` | |||||
OrgID int64 `xorm:"INDEX"` | |||||
URL string `xorm:"url TEXT"` | |||||
Signature string `xorm:"TEXT"` | |||||
HTTPMethod string `xorm:"http_method"` | |||||
ContentType HookContentType | |||||
Secret string `xorm:"TEXT"` | |||||
Events string `xorm:"TEXT"` | |||||
*HookEvent `xorm:"-"` | |||||
IsSSL bool `xorm:"is_ssl"` | |||||
IsActive bool `xorm:"INDEX"` | |||||
HookTaskType HookTaskType | |||||
Meta string `xorm:"TEXT"` // store hook-specific attributes | |||||
LastStatus HookStatus // Last delivery status | |||||
ID int64 `xorm:"pk autoincr"` | |||||
RepoID int64 `xorm:"INDEX"` // An ID of 0 indicates either a default or system webhook | |||||
OrgID int64 `xorm:"INDEX"` | |||||
IsSystemWebhook bool | |||||
URL string `xorm:"url TEXT"` | |||||
Signature string `xorm:"TEXT"` | |||||
HTTPMethod string `xorm:"http_method"` | |||||
ContentType HookContentType | |||||
Secret string `xorm:"TEXT"` | |||||
Events string `xorm:"TEXT"` | |||||
*HookEvent `xorm:"-"` | |||||
IsSSL bool `xorm:"is_ssl"` | |||||
IsActive bool `xorm:"INDEX"` | |||||
HookTaskType HookTaskType | |||||
Meta string `xorm:"TEXT"` // store hook-specific attributes | |||||
LastStatus HookStatus // Last delivery status | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | ||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | ||||
func GetDefaultWebhook(id int64) (*Webhook, error) { | func GetDefaultWebhook(id int64) (*Webhook, error) { | ||||
webhook := &Webhook{ID: id} | webhook := &Webhook{ID: id} | ||||
has, err := x. | has, err := x. | ||||
Where("repo_id=? AND org_id=?", 0, 0). | |||||
Where("repo_id=? AND org_id=? AND is_system_webhook=?", 0, 0, false). | |||||
Get(webhook) | Get(webhook) | ||||
if err != nil { | if err != nil { | ||||
return nil, err | return nil, err | ||||
func getDefaultWebhooks(e Engine) ([]*Webhook, error) { | func getDefaultWebhooks(e Engine) ([]*Webhook, error) { | ||||
webhooks := make([]*Webhook, 0, 5) | webhooks := make([]*Webhook, 0, 5) | ||||
return webhooks, e. | return webhooks, e. | ||||
Where("repo_id=? AND org_id=?", 0, 0). | |||||
Where("repo_id=? AND org_id=? AND is_system_webhook=?", 0, 0, false). | |||||
Find(&webhooks) | |||||
} | |||||
// GetSystemWebhook returns admin system webhook by given ID. | |||||
func GetSystemWebhook(id int64) (*Webhook, error) { | |||||
webhook := &Webhook{ID: id} | |||||
has, err := x. | |||||
Where("repo_id=? AND org_id=? AND is_system_webhook=?", 0, 0, true). | |||||
Get(webhook) | |||||
if err != nil { | |||||
return nil, err | |||||
} else if !has { | |||||
return nil, ErrWebhookNotExist{id} | |||||
} | |||||
return webhook, nil | |||||
} | |||||
// GetSystemWebhooks returns all admin system webhooks. | |||||
func GetSystemWebhooks() ([]*Webhook, error) { | |||||
return getSystemWebhooks(x) | |||||
} | |||||
func getSystemWebhooks(e Engine) ([]*Webhook, error) { | |||||
webhooks := make([]*Webhook, 0, 5) | |||||
return webhooks, e. | |||||
Where("repo_id=? AND org_id=? AND is_system_webhook=?", 0, 0, true). | |||||
Find(&webhooks) | Find(&webhooks) | ||||
} | } | ||||
}) | }) | ||||
} | } | ||||
// DeleteDefaultWebhook deletes an admin-default webhook by given ID. | |||||
func DeleteDefaultWebhook(id int64) error { | |||||
// DeleteDefaultSystemWebhook deletes an admin-configured default or system webhook (where Org and Repo ID both 0) | |||||
func DeleteDefaultSystemWebhook(id int64) error { | |||||
sess := x.NewSession() | sess := x.NewSession() | ||||
defer sess.Close() | defer sess.Close() | ||||
if err := sess.Begin(); err != nil { | if err := sess.Begin(); err != nil { |
ws = append(ws, orgHooks...) | ws = append(ws, orgHooks...) | ||||
} | } | ||||
// Add any admin-defined system webhooks | |||||
systemHooks, err := models.GetSystemWebhooks() | |||||
if err != nil { | |||||
return fmt.Errorf("GetSystemWebhooks: %v", err) | |||||
} | |||||
ws = append(ws, systemHooks...) | |||||
if len(ws) == 0 { | if len(ws) == 0 { | ||||
return nil | return nil | ||||
} | } |
organizations = Organizations | organizations = Organizations | ||||
repositories = Repositories | repositories = Repositories | ||||
hooks = Default Webhooks | hooks = Default Webhooks | ||||
systemhooks = System Webhooks | |||||
authentication = Authentication Sources | authentication = Authentication Sources | ||||
emails = User Emails | emails = User Emails | ||||
config = Configuration | config = Configuration | ||||
hooks.add_webhook = Add Default Webhook | hooks.add_webhook = Add Default Webhook | ||||
hooks.update_webhook = Update Default Webhook | hooks.update_webhook = Update Default Webhook | ||||
systemhooks.desc = Webhooks automatically make HTTP POST requests to a server when certain Gitea events trigger. Webhooks defined will act on all repositories on the system, so please consider any performance implications this may have. Read more in the <a target="_blank" rel="noopener" href="https://docs.gitea.io/en-us/webhooks/">webhooks guide</a>. | |||||
systemhooks.add_webhook = Add System Webhook | |||||
systemhooks.update_webhook = Update System Webhook | |||||
auths.auth_manage_panel = Authentication Source Management | auths.auth_manage_panel = Authentication Source Management | ||||
auths.new = Add Authentication Source | auths.new = Add Authentication Source | ||||
auths.name = Name | auths.name = Name |
) | ) | ||||
const ( | const ( | ||||
// tplAdminHooks template path for render hook settings | |||||
// tplAdminHooks template path to render hook settings | |||||
tplAdminHooks base.TplName = "admin/hooks" | 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 { | if err != nil { | ||||
ctx.ServerError("GetWebhooksDefaults", err) | |||||
ctx.ServerError("GetWebhooksAdmin", err) | |||||
return | return | ||||
} | } | ||||
ctx.HTML(200, tplAdminHooks) | 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()) | ctx.Flash.Error("DeleteDefaultWebhook: " + err.Error()) | ||||
} else { | } else { | ||||
ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success")) | 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", | |||||
}) | |||||
} | |||||
} | } |
} | } | ||||
type orgRepoCtx struct { | 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) { | func getOrgRepoCtx(ctx *context.Context) (*orgRepoCtx, error) { | ||||
if len(ctx.Repo.RepoLink) > 0 { | if len(ctx.Repo.RepoLink) > 0 { | ||||
return &orgRepoCtx{ | return &orgRepoCtx{ | ||||
} | } | ||||
if ctx.User.IsAdmin { | 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{ | 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 | }, nil | ||||
} | } | ||||
return | 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["PageIsAdminHooks"] = true | ||||
ctx.Data["PageIsAdminHooksNew"] = true | ctx.Data["PageIsAdminHooksNew"] = true | ||||
} else { | } else { | ||||
} | } | ||||
} | } | ||||
// 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["Title"] = ctx.Tr("repo.settings.add_webhook") | ||||
ctx.Data["PageIsSettingsHooks"] = true | ctx.Data["PageIsSettingsHooks"] = true | ||||
ctx.Data["PageIsSettingsHooksNew"] = true | ctx.Data["PageIsSettingsHooksNew"] = true | ||||
} | } | ||||
w := &models.Webhook{ | 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 { | if err := w.UpdateEvent(); err != nil { | ||||
ctx.ServerError("UpdateEvent", err) | ctx.ServerError("UpdateEvent", err) | ||||
} | } | ||||
w := &models.Webhook{ | 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 { | if err := w.UpdateEvent(); err != nil { | ||||
ctx.ServerError("UpdateEvent", err) | ctx.ServerError("UpdateEvent", err) | ||||
} | } | ||||
w := &models.Webhook{ | 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 { | if err := w.UpdateEvent(); err != nil { | ||||
ctx.ServerError("UpdateEvent", err) | ctx.ServerError("UpdateEvent", err) | ||||
} | } | ||||
w := &models.Webhook{ | 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 { | if err := w.UpdateEvent(); err != nil { | ||||
ctx.ServerError("UpdateEvent", err) | ctx.ServerError("UpdateEvent", err) | ||||
} | } | ||||
w := &models.Webhook{ | 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 { | if err := w.UpdateEvent(); err != nil { | ||||
ctx.ServerError("UpdateEvent", err) | ctx.ServerError("UpdateEvent", err) | ||||
} | } | ||||
w := &models.Webhook{ | 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 { | if err := w.UpdateEvent(); err != nil { | ||||
ctx.ServerError("UpdateEvent", err) | ctx.ServerError("UpdateEvent", err) | ||||
} | } | ||||
w := &models.Webhook{ | 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 { | if err := w.UpdateEvent(); err != nil { | ||||
ctx.ServerError("UpdateEvent", err) | ctx.ServerError("UpdateEvent", err) | ||||
} | } | ||||
w := &models.Webhook{ | 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 { | if err := w.UpdateEvent(); err != nil { | ||||
ctx.ServerError("UpdateEvent", err) | ctx.ServerError("UpdateEvent", err) | ||||
w, err = models.GetWebhookByRepoID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")) | w, err = models.GetWebhookByRepoID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")) | ||||
} else if orCtx.OrgID > 0 { | } else if orCtx.OrgID > 0 { | ||||
w, err = models.GetWebhookByOrgID(ctx.Org.Organization.ID, ctx.ParamsInt64(":id")) | w, err = models.GetWebhookByOrgID(ctx.Org.Organization.ID, ctx.ParamsInt64(":id")) | ||||
} else if orCtx.IsSystemWebhook { | |||||
w, err = models.GetSystemWebhook(ctx.ParamsInt64(":id")) | |||||
} else { | } else { | ||||
w, err = models.GetDefaultWebhook(ctx.ParamsInt64(":id")) | w, err = models.GetDefaultWebhook(ctx.ParamsInt64(":id")) | ||||
} | } |
m.Post("/delete", admin.DeleteRepo) | 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.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("/gogs/new", bindIgnErr(auth.NewGogshookForm{}), repo.GogsHooksNewPost) | ||||
m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost) | m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost) | ||||
m.Post("/discord/new", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksNewPost) | m.Post("/discord/new", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksNewPost) | ||||
m.Get("", org.Webhooks) | m.Get("", org.Webhooks) | ||||
m.Post("/delete", org.DeleteWebhook) | m.Post("/delete", org.DeleteWebhook) | ||||
m.Get("/:type/new", repo.WebhooksNew) | 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("/gogs/new", bindIgnErr(auth.NewGogshookForm{}), repo.GogsHooksNewPost) | ||||
m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost) | m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost) | ||||
m.Post("/discord/new", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksNewPost) | m.Post("/discord/new", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksNewPost) | ||||
m.Get("", repo.Webhooks) | m.Get("", repo.Webhooks) | ||||
m.Post("/delete", repo.DeleteWebhook) | m.Post("/delete", repo.DeleteWebhook) | ||||
m.Get("/:type/new", repo.WebhooksNew) | 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("/gogs/new", bindIgnErr(auth.NewGogshookForm{}), repo.GogsHooksNewPost) | ||||
m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost) | m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost) | ||||
m.Post("/discord/new", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksNewPost) | m.Post("/discord/new", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksNewPost) |
<a class="{{if .PageIsAdminHooks}}active{{end}} item" href="{{AppSubUrl}}/admin/hooks"> | <a class="{{if .PageIsAdminHooks}}active{{end}} item" href="{{AppSubUrl}}/admin/hooks"> | ||||
{{.i18n.Tr "admin.hooks"}} | {{.i18n.Tr "admin.hooks"}} | ||||
</a> | </a> | ||||
<a class="{{if .PageIsAdminSystemHooks}}active{{end}} item" href="{{AppSubUrl}}/admin/system-hooks"> | |||||
{{.i18n.Tr "admin.systemhooks"}} | |||||
</a> | |||||
<a class="{{if .PageIsAdminAuthentications}}active{{end}} item" href="{{AppSubUrl}}/admin/auths"> | <a class="{{if .PageIsAdminAuthentications}}active{{end}} item" href="{{AppSubUrl}}/admin/auths"> | ||||
{{.i18n.Tr "admin.authentication"}} | {{.i18n.Tr "admin.authentication"}} | ||||
</a> | </a> |