mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	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:
		@@ -15,24 +15,24 @@ menu:
 | 
			
		||||
 | 
			
		||||
# 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
 | 
			
		||||
- Slack
 | 
			
		||||
- Discord
 | 
			
		||||
- Dingtalk
 | 
			
		||||
- Telegram
 | 
			
		||||
- Microsoft Teams
 | 
			
		||||
- Feishu
 | 
			
		||||
 | 
			
		||||
### Event information
 | 
			
		||||
 | 
			
		||||
The following is an example of event information that will be sent by Gitea to
 | 
			
		||||
a Payload URL:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
X-GitHub-Delivery: f6266f16-1bf3-46a5-9ea4-602e06ead473
 | 
			
		||||
X-GitHub-Event: push
 | 
			
		||||
 
 | 
			
		||||
@@ -194,6 +194,8 @@ var migrations = []Migration{
 | 
			
		||||
	NewMigration("remove dependencies from deleted repositories", purgeUnusedDependencies),
 | 
			
		||||
	// v130 -> v131
 | 
			
		||||
	NewMigration("Expand webhooks for more granularity", expandWebhooks),
 | 
			
		||||
	// v131 -> v132
 | 
			
		||||
	NewMigration("Add IsSystemWebhook column to webhooks table", addSystemWebhookColumn),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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.
 | 
			
		||||
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"`
 | 
			
		||||
	UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
 | 
			
		||||
@@ -401,7 +402,7 @@ func GetWebhooksByOrgID(orgID int64, listOptions ListOptions) ([]*Webhook, error
 | 
			
		||||
func GetDefaultWebhook(id int64) (*Webhook, error) {
 | 
			
		||||
	webhook := &Webhook{ID: id}
 | 
			
		||||
	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)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
@@ -419,7 +420,33 @@ func GetDefaultWebhooks() ([]*Webhook, error) {
 | 
			
		||||
func getDefaultWebhooks(e Engine) ([]*Webhook, error) {
 | 
			
		||||
	webhooks := make([]*Webhook, 0, 5)
 | 
			
		||||
	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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -471,8 +498,8 @@ func DeleteWebhookByOrgID(orgID, id int64) error {
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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()
 | 
			
		||||
	defer sess.Close()
 | 
			
		||||
	if err := sess.Begin(); err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -181,6 +181,13 @@ func prepareWebhooks(repo *models.Repository, event models.HookEventType, p api.
 | 
			
		||||
		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 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -1753,6 +1753,7 @@ users = User Accounts
 | 
			
		||||
organizations = Organizations
 | 
			
		||||
repositories = Repositories
 | 
			
		||||
hooks = Default Webhooks
 | 
			
		||||
systemhooks = System Webhooks
 | 
			
		||||
authentication = Authentication Sources
 | 
			
		||||
emails = User Emails
 | 
			
		||||
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.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.new = Add Authentication Source
 | 
			
		||||
auths.name = Name
 | 
			
		||||
 
 | 
			
		||||
@@ -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",
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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"))
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,9 @@
 | 
			
		||||
	<a class="{{if .PageIsAdminHooks}}active{{end}} item" href="{{AppSubUrl}}/admin/hooks">
 | 
			
		||||
		{{.i18n.Tr "admin.hooks"}}
 | 
			
		||||
	</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">
 | 
			
		||||
		{{.i18n.Tr "admin.authentication"}}
 | 
			
		||||
	</a>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user