mirror of
https://github.com/go-gitea/gitea
synced 2025-01-19 06:04:26 +00:00
Let API create and edit system webhooks, attempt 2 (#33180)
This PR fixes inconsistencies between system and default webhooks in the Gitea API. (See also #26418) - A system webhook is a webhook that captures events for all repositories. - A default webhook is copied to a new repository when it is created. Before this PR `POST /api/v1/admin/hooks/` creates default webhooks (if not configured otherwise) and `GET /api/v1/admin/hooks/` returns system webhooks. The PR introduces an optional query parameter to `GET /api/v1/admin/hooks/` to enable selecting if either default, system or both kind of webhooks should be retrieved. By default the flag is set to return system webhooks keep current behaviour. ## Examples ### System Webhooks #### Create ``` POST /api/v1/admin/hooks/ { "type": "gitea", "active": false, "branch_filter": "*", "events": [ "create", "..." ], "config": { "url": "http://...", "content_type": "json", "secret": "secret", "is_system_webhook": true // <-- controls hook type } } ``` #### List ``` GET/api/v1/admin/hooks?type=system //type argument is optional here since it's the default ``` #### Others The other relevant endpoints work as expected by referencing the hook by id ``` GET /api/v1/admin/hooks/:id PATCH /api/v1/admin/hooks/:id DELETE /api/v1/admin/hooks/:id ``` ### Default Webhooks #### Create ``` POST /api/v1/admin/hooks/ { "type": "gitea", "active": false, "branch_filter": "*", "events": [ "create", "..." ], "config": { "url": "http://...", "content_type": "json", "secret": "secret", "is_system_webhook": false // optional, as false is the default value } } ``` #### List ``` GET/api/v1/admin/hooks?type=default ``` #### Others The other relevant endpoints work as expected by referencing the hook by id ``` GET /api/v1/admin/hooks/:id PATCH /api/v1/admin/hooks/:id DELETE /api/v1/admin/hooks/:id ```
This commit is contained in:
parent
348b7074c8
commit
a90af22003
@ -22,6 +22,7 @@
|
|||||||
content_type: 1 # json
|
content_type: 1 # json
|
||||||
events: '{"push_only":false,"send_everything":false,"choose_events":false,"events":{"create":false,"push":true,"pull_request":true}}'
|
events: '{"push_only":false,"send_everything":false,"choose_events":false,"events":{"create":false,"push":true,"pull_request":true}}'
|
||||||
is_active: true
|
is_active: true
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 4
|
id: 4
|
||||||
repo_id: 2
|
repo_id: 2
|
||||||
@ -29,3 +30,23 @@
|
|||||||
content_type: 1 # json
|
content_type: 1 # json
|
||||||
events: '{"push_only":true,"branch_filter":"{master,feature*}"}'
|
events: '{"push_only":true,"branch_filter":"{master,feature*}"}'
|
||||||
is_active: true
|
is_active: true
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 5
|
||||||
|
repo_id: 0
|
||||||
|
owner_id: 0
|
||||||
|
url: www.example.com/url5
|
||||||
|
content_type: 1 # json
|
||||||
|
events: '{"push_only":true,"branch_filter":"{master,feature*}"}'
|
||||||
|
is_active: true
|
||||||
|
is_system_webhook: true
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 6
|
||||||
|
repo_id: 0
|
||||||
|
owner_id: 0
|
||||||
|
url: www.example.com/url6
|
||||||
|
content_type: 1 # json
|
||||||
|
events: '{"push_only":true,"branch_filter":"{master,feature*}"}'
|
||||||
|
is_active: true
|
||||||
|
is_system_webhook: false
|
||||||
|
@ -11,6 +11,19 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/optional"
|
"code.gitea.io/gitea/modules/optional"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GetSystemOrDefaultWebhooks returns webhooks by given argument or all if argument is missing.
|
||||||
|
func GetSystemOrDefaultWebhooks(ctx context.Context, isSystemWebhook optional.Option[bool]) ([]*Webhook, error) {
|
||||||
|
webhooks := make([]*Webhook, 0, 5)
|
||||||
|
if !isSystemWebhook.Has() {
|
||||||
|
return webhooks, db.GetEngine(ctx).Where("repo_id=? AND owner_id=?", 0, 0).
|
||||||
|
Find(&webhooks)
|
||||||
|
}
|
||||||
|
|
||||||
|
return webhooks, db.GetEngine(ctx).
|
||||||
|
Where("repo_id=? AND owner_id=? AND is_system_webhook=?", 0, 0, isSystemWebhook.Value()).
|
||||||
|
Find(&webhooks)
|
||||||
|
}
|
||||||
|
|
||||||
// GetDefaultWebhooks returns all admin-default webhooks.
|
// GetDefaultWebhooks returns all admin-default webhooks.
|
||||||
func GetDefaultWebhooks(ctx context.Context) ([]*Webhook, error) {
|
func GetDefaultWebhooks(ctx context.Context) ([]*Webhook, error) {
|
||||||
webhooks := make([]*Webhook, 0, 5)
|
webhooks := make([]*Webhook, 0, 5)
|
||||||
|
37
models/webhook/webhook_system_test.go
Normal file
37
models/webhook/webhook_system_test.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// Copyright 2017 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package webhook
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
"code.gitea.io/gitea/modules/optional"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetSystemOrDefaultWebhooks(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
hooks, err := GetSystemOrDefaultWebhooks(db.DefaultContext, optional.None[bool]())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
if assert.Len(t, hooks, 2) {
|
||||||
|
assert.Equal(t, int64(5), hooks[0].ID)
|
||||||
|
assert.Equal(t, int64(6), hooks[1].ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
hooks, err = GetSystemOrDefaultWebhooks(db.DefaultContext, optional.Some(true))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
if assert.Len(t, hooks, 1) {
|
||||||
|
assert.Equal(t, int64(5), hooks[0].ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
hooks, err = GetSystemOrDefaultWebhooks(db.DefaultContext, optional.Some(false))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
if assert.Len(t, hooks, 1) {
|
||||||
|
assert.Equal(t, int64(6), hooks[0].ID)
|
||||||
|
}
|
||||||
|
}
|
@ -34,11 +34,30 @@ func ListHooks(ctx *context.APIContext) {
|
|||||||
// in: query
|
// in: query
|
||||||
// description: page size of results
|
// description: page size of results
|
||||||
// type: integer
|
// type: integer
|
||||||
|
// - type: string
|
||||||
|
// enum:
|
||||||
|
// - system
|
||||||
|
// - default
|
||||||
|
// - all
|
||||||
|
// description: system, default or both kinds of webhooks
|
||||||
|
// name: type
|
||||||
|
// default: system
|
||||||
|
// in: query
|
||||||
|
//
|
||||||
// responses:
|
// responses:
|
||||||
// "200":
|
// "200":
|
||||||
// "$ref": "#/responses/HookList"
|
// "$ref": "#/responses/HookList"
|
||||||
|
|
||||||
sysHooks, err := webhook.GetSystemWebhooks(ctx, optional.None[bool]())
|
// for compatibility the default value is true
|
||||||
|
isSystemWebhook := optional.Some(true)
|
||||||
|
typeValue := ctx.FormString("type")
|
||||||
|
if typeValue == "default" {
|
||||||
|
isSystemWebhook = optional.Some(false)
|
||||||
|
} else if typeValue == "all" {
|
||||||
|
isSystemWebhook = optional.None[bool]()
|
||||||
|
}
|
||||||
|
|
||||||
|
sysHooks, err := webhook.GetSystemOrDefaultWebhooks(ctx, isSystemWebhook)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetSystemWebhooks", err)
|
ctx.Error(http.StatusInternalServerError, "GetSystemWebhooks", err)
|
||||||
return
|
return
|
||||||
|
12
templates/swagger/v1_json.tmpl
generated
12
templates/swagger/v1_json.tmpl
generated
@ -234,6 +234,18 @@
|
|||||||
"description": "page size of results",
|
"description": "page size of results",
|
||||||
"name": "limit",
|
"name": "limit",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enum": [
|
||||||
|
"system",
|
||||||
|
"default",
|
||||||
|
"all"
|
||||||
|
],
|
||||||
|
"type": "string",
|
||||||
|
"default": "system",
|
||||||
|
"description": "system, default or both kinds of webhooks",
|
||||||
|
"name": "type",
|
||||||
|
"in": "query"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user