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>
This commit is contained in:
parent
b8551f8532
commit
a9f4489bbc
10 changed files with 232 additions and 122 deletions
|
@ -15,24 +15,24 @@ menu:
|
||||||
|
|
||||||
# Webhooks
|
# Webhooks
|
||||||
|
|
||||||
Gitea supports web hooks for repository events. This can be found in the settings
|
Gitea supports web hooks for repository events. This can be configured in the settings
|
||||||
page `/:username/:reponame/settings/hooks`. All event pushes are POST requests.
|
page `/:username/:reponame/settings/hooks` by a repository admin. Webhooks can also be configured on a per-organization and whole system basis.
|
||||||
The methods currently supported are:
|
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
|
||||||
|
|
|
@ -194,6 +194,8 @@ var migrations = []Migration{
|
||||||
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
|
||||||
|
|
22
models/migrations/v131.go
Normal file
22
models/migrations/v131.go
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// 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
|
||||||
|
}
|
|
@ -99,21 +99,22 @@ const (
|
||||||
|
|
||||||
// Webhook represents a web hook object.
|
// Webhook represents a web hook object.
|
||||||
type Webhook struct {
|
type Webhook struct {
|
||||||
ID int64 `xorm:"pk autoincr"`
|
ID int64 `xorm:"pk autoincr"`
|
||||||
RepoID int64 `xorm:"INDEX"`
|
RepoID int64 `xorm:"INDEX"` // An ID of 0 indicates either a default or system webhook
|
||||||
OrgID int64 `xorm:"INDEX"`
|
OrgID int64 `xorm:"INDEX"`
|
||||||
URL string `xorm:"url TEXT"`
|
IsSystemWebhook bool
|
||||||
Signature string `xorm:"TEXT"`
|
URL string `xorm:"url TEXT"`
|
||||||
HTTPMethod string `xorm:"http_method"`
|
Signature string `xorm:"TEXT"`
|
||||||
ContentType HookContentType
|
HTTPMethod string `xorm:"http_method"`
|
||||||
Secret string `xorm:"TEXT"`
|
ContentType HookContentType
|
||||||
Events string `xorm:"TEXT"`
|
Secret string `xorm:"TEXT"`
|
||||||
*HookEvent `xorm:"-"`
|
Events string `xorm:"TEXT"`
|
||||||
IsSSL bool `xorm:"is_ssl"`
|
*HookEvent `xorm:"-"`
|
||||||
IsActive bool `xorm:"INDEX"`
|
IsSSL bool `xorm:"is_ssl"`
|
||||||
HookTaskType HookTaskType
|
IsActive bool `xorm:"INDEX"`
|
||||||
Meta string `xorm:"TEXT"` // store hook-specific attributes
|
HookTaskType HookTaskType
|
||||||
LastStatus HookStatus // Last delivery status
|
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"`
|
||||||
|
@ -401,7 +402,7 @@ func GetWebhooksByOrgID(orgID int64, listOptions ListOptions) ([]*Webhook, error
|
||||||
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
|
||||||
|
@ -419,7 +420,33 @@ func GetDefaultWebhooks() ([]*Webhook, error) {
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,8 +498,8 @@ func DeleteWebhookByOrgID(orgID, id int64) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteDefaultWebhook deletes an admin-default webhook by given ID.
|
// DeleteDefaultSystemWebhook deletes an admin-configured default or system webhook (where Org and Repo ID both 0)
|
||||||
func DeleteDefaultWebhook(id int64) error {
|
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 {
|
||||||
|
|
|
@ -181,6 +181,13 @@ func prepareWebhooks(repo *models.Repository, event models.HookEventType, p api.
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -1753,6 +1753,7 @@ users = User Accounts
|
||||||
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
|
||||||
|
@ -1889,6 +1890,10 @@ hooks.desc = Webhooks automatically make HTTP POST requests to a server when cer
|
||||||
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
|
||||||
|
|
|
@ -12,20 +12,32 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
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
|
// DefaultOrSystemWebhooks renders both admin default and system webhook list pages
|
||||||
func DefaultWebhooks(ctx *context.Context) {
|
func DefaultOrSystemWebhooks(ctx *context.Context) {
|
||||||
ctx.Data["Title"] = ctx.Tr("admin.hooks")
|
var ws []*models.Webhook
|
||||||
ctx.Data["PageIsAdminHooks"] = true
|
var err error
|
||||||
ctx.Data["BaseLink"] = setting.AppSubURL + "/admin/hooks"
|
|
||||||
ctx.Data["Description"] = ctx.Tr("admin.hooks.desc")
|
// 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,15 +45,22 @@ func DefaultWebhooks(ctx *context.Context) {
|
||||||
ctx.HTML(200, tplAdminHooks)
|
ctx.HTML(200, tplAdminHooks)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteDefaultWebhook response for delete admin-default webhook
|
// DeleteDefaultOrSystemWebhook handler to delete an admin-defined system or default webhook
|
||||||
func DeleteDefaultWebhook(ctx *context.Context) {
|
func DeleteDefaultOrSystemWebhook(ctx *context.Context) {
|
||||||
if err := models.DeleteDefaultWebhook(ctx.QueryInt64("id")); err != nil {
|
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{}{
|
// Are we looking at default webhooks?
|
||||||
"redirect": setting.AppSubURL + "/admin/hooks",
|
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",
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,14 +49,15 @@ func Webhooks(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type orgRepoCtx struct {
|
type orgRepoCtx struct {
|
||||||
OrgID int64
|
OrgID int64
|
||||||
RepoID int64
|
RepoID int64
|
||||||
IsAdmin bool
|
IsAdmin bool
|
||||||
Link string
|
IsSystemWebhook bool
|
||||||
NewTemplate base.TplName
|
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{
|
||||||
|
@ -75,10 +76,21 @@ func getOrgRepoCtx(ctx *context.Context) (*orgRepoCtx, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
IsAdmin: true,
|
||||||
Link: path.Join(setting.AppSubURL, "/admin/hooks"),
|
IsSystemWebhook: true,
|
||||||
NewTemplate: tplAdminHookNew,
|
Link: path.Join(setting.AppSubURL, "/admin/system-hooks"),
|
||||||
|
NewTemplate: tplAdminHookNew,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +117,10 @@ func WebhooksNew(ctx *context.Context) {
|
||||||
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 {
|
||||||
|
@ -159,8 +174,8 @@ func ParseHookEvent(form auth.WebhookForm) *models.HookEvent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebHooksNewPost response for creating webhook
|
// GiteaHooksNewPost response for creating Gitea webhook
|
||||||
func WebHooksNewPost(ctx *context.Context, form auth.NewWebhookForm) {
|
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
|
||||||
|
@ -185,15 +200,16 @@ func WebHooksNewPost(ctx *context.Context, form auth.NewWebhookForm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w := &models.Webhook{
|
w := &models.Webhook{
|
||||||
RepoID: orCtx.RepoID,
|
RepoID: orCtx.RepoID,
|
||||||
URL: form.PayloadURL,
|
URL: form.PayloadURL,
|
||||||
HTTPMethod: form.HTTPMethod,
|
HTTPMethod: form.HTTPMethod,
|
||||||
ContentType: contentType,
|
ContentType: contentType,
|
||||||
Secret: form.Secret,
|
Secret: form.Secret,
|
||||||
HookEvent: ParseHookEvent(form.WebhookForm),
|
HookEvent: ParseHookEvent(form.WebhookForm),
|
||||||
IsActive: form.Active,
|
IsActive: form.Active,
|
||||||
HookTaskType: models.GITEA,
|
HookTaskType: models.GITEA,
|
||||||
OrgID: orCtx.OrgID,
|
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)
|
||||||
|
@ -238,14 +254,15 @@ func newGogsWebhookPost(ctx *context.Context, form auth.NewGogshookForm, kind mo
|
||||||
}
|
}
|
||||||
|
|
||||||
w := &models.Webhook{
|
w := &models.Webhook{
|
||||||
RepoID: orCtx.RepoID,
|
RepoID: orCtx.RepoID,
|
||||||
URL: form.PayloadURL,
|
URL: form.PayloadURL,
|
||||||
ContentType: contentType,
|
ContentType: contentType,
|
||||||
Secret: form.Secret,
|
Secret: form.Secret,
|
||||||
HookEvent: ParseHookEvent(form.WebhookForm),
|
HookEvent: ParseHookEvent(form.WebhookForm),
|
||||||
IsActive: form.Active,
|
IsActive: form.Active,
|
||||||
HookTaskType: kind,
|
HookTaskType: kind,
|
||||||
OrgID: orCtx.OrgID,
|
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)
|
||||||
|
@ -287,14 +304,15 @@ func DiscordHooksNewPost(ctx *context.Context, form auth.NewDiscordHookForm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w := &models.Webhook{
|
w := &models.Webhook{
|
||||||
RepoID: orCtx.RepoID,
|
RepoID: orCtx.RepoID,
|
||||||
URL: form.PayloadURL,
|
URL: form.PayloadURL,
|
||||||
ContentType: models.ContentTypeJSON,
|
ContentType: models.ContentTypeJSON,
|
||||||
HookEvent: ParseHookEvent(form.WebhookForm),
|
HookEvent: ParseHookEvent(form.WebhookForm),
|
||||||
IsActive: form.Active,
|
IsActive: form.Active,
|
||||||
HookTaskType: models.DISCORD,
|
HookTaskType: models.DISCORD,
|
||||||
Meta: string(meta),
|
Meta: string(meta),
|
||||||
OrgID: orCtx.OrgID,
|
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)
|
||||||
|
@ -327,14 +345,15 @@ func DingtalkHooksNewPost(ctx *context.Context, form auth.NewDingtalkHookForm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w := &models.Webhook{
|
w := &models.Webhook{
|
||||||
RepoID: orCtx.RepoID,
|
RepoID: orCtx.RepoID,
|
||||||
URL: form.PayloadURL,
|
URL: form.PayloadURL,
|
||||||
ContentType: models.ContentTypeJSON,
|
ContentType: models.ContentTypeJSON,
|
||||||
HookEvent: ParseHookEvent(form.WebhookForm),
|
HookEvent: ParseHookEvent(form.WebhookForm),
|
||||||
IsActive: form.Active,
|
IsActive: form.Active,
|
||||||
HookTaskType: models.DINGTALK,
|
HookTaskType: models.DINGTALK,
|
||||||
Meta: "",
|
Meta: "",
|
||||||
OrgID: orCtx.OrgID,
|
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)
|
||||||
|
@ -376,14 +395,15 @@ func TelegramHooksNewPost(ctx *context.Context, form auth.NewTelegramHookForm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w := &models.Webhook{
|
w := &models.Webhook{
|
||||||
RepoID: orCtx.RepoID,
|
RepoID: orCtx.RepoID,
|
||||||
URL: fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage?chat_id=%s", form.BotToken, form.ChatID),
|
URL: fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage?chat_id=%s", form.BotToken, form.ChatID),
|
||||||
ContentType: models.ContentTypeJSON,
|
ContentType: models.ContentTypeJSON,
|
||||||
HookEvent: ParseHookEvent(form.WebhookForm),
|
HookEvent: ParseHookEvent(form.WebhookForm),
|
||||||
IsActive: form.Active,
|
IsActive: form.Active,
|
||||||
HookTaskType: models.TELEGRAM,
|
HookTaskType: models.TELEGRAM,
|
||||||
Meta: string(meta),
|
Meta: string(meta),
|
||||||
OrgID: orCtx.OrgID,
|
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)
|
||||||
|
@ -416,14 +436,15 @@ func MSTeamsHooksNewPost(ctx *context.Context, form auth.NewMSTeamsHookForm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w := &models.Webhook{
|
w := &models.Webhook{
|
||||||
RepoID: orCtx.RepoID,
|
RepoID: orCtx.RepoID,
|
||||||
URL: form.PayloadURL,
|
URL: form.PayloadURL,
|
||||||
ContentType: models.ContentTypeJSON,
|
ContentType: models.ContentTypeJSON,
|
||||||
HookEvent: ParseHookEvent(form.WebhookForm),
|
HookEvent: ParseHookEvent(form.WebhookForm),
|
||||||
IsActive: form.Active,
|
IsActive: form.Active,
|
||||||
HookTaskType: models.MSTEAMS,
|
HookTaskType: models.MSTEAMS,
|
||||||
Meta: "",
|
Meta: "",
|
||||||
OrgID: orCtx.OrgID,
|
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)
|
||||||
|
@ -473,14 +494,15 @@ func SlackHooksNewPost(ctx *context.Context, form auth.NewSlackHookForm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w := &models.Webhook{
|
w := &models.Webhook{
|
||||||
RepoID: orCtx.RepoID,
|
RepoID: orCtx.RepoID,
|
||||||
URL: form.PayloadURL,
|
URL: form.PayloadURL,
|
||||||
ContentType: models.ContentTypeJSON,
|
ContentType: models.ContentTypeJSON,
|
||||||
HookEvent: ParseHookEvent(form.WebhookForm),
|
HookEvent: ParseHookEvent(form.WebhookForm),
|
||||||
IsActive: form.Active,
|
IsActive: form.Active,
|
||||||
HookTaskType: models.SLACK,
|
HookTaskType: models.SLACK,
|
||||||
Meta: string(meta),
|
Meta: string(meta),
|
||||||
OrgID: orCtx.OrgID,
|
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)
|
||||||
|
@ -513,14 +535,15 @@ func FeishuHooksNewPost(ctx *context.Context, form auth.NewFeishuHookForm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w := &models.Webhook{
|
w := &models.Webhook{
|
||||||
RepoID: orCtx.RepoID,
|
RepoID: orCtx.RepoID,
|
||||||
URL: form.PayloadURL,
|
URL: form.PayloadURL,
|
||||||
ContentType: models.ContentTypeJSON,
|
ContentType: models.ContentTypeJSON,
|
||||||
HookEvent: ParseHookEvent(form.WebhookForm),
|
HookEvent: ParseHookEvent(form.WebhookForm),
|
||||||
IsActive: form.Active,
|
IsActive: form.Active,
|
||||||
HookTaskType: models.FEISHU,
|
HookTaskType: models.FEISHU,
|
||||||
Meta: "",
|
Meta: "",
|
||||||
OrgID: orCtx.OrgID,
|
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)
|
||||||
|
@ -549,6 +572,8 @@ func checkWebhook(ctx *context.Context) (*orgRepoCtx, *models.Webhook) {
|
||||||
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"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -458,11 +458,11 @@ func RegisterRoutes(m *macaron.Macaron) {
|
||||||
m.Post("/delete", admin.DeleteRepo)
|
m.Post("/delete", admin.DeleteRepo)
|
||||||
})
|
})
|
||||||
|
|
||||||
m.Group("/hooks", func() {
|
m.Group("/^:configType(hooks|system-hooks)$", func() {
|
||||||
m.Get("", admin.DefaultWebhooks)
|
m.Get("", admin.DefaultOrSystemWebhooks)
|
||||||
m.Post("/delete", admin.DeleteDefaultWebhook)
|
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)
|
||||||
|
@ -569,7 +569,7 @@ func RegisterRoutes(m *macaron.Macaron) {
|
||||||
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)
|
||||||
|
@ -635,7 +635,7 @@ func RegisterRoutes(m *macaron.Macaron) {
|
||||||
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)
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
<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>
|
||||||
|
|
Loading…
Reference in a new issue