Skip to content

Commit c001597

Browse files
authored
Support system hook API (#14537)
This add system hook API
1 parent 78e6b21 commit c001597

File tree

8 files changed

+450
-78
lines changed

8 files changed

+450
-78
lines changed

models/webhook/webhook.go

-76
Original file line numberDiff line numberDiff line change
@@ -463,41 +463,6 @@ func CountWebhooksByOpts(opts *ListWebhookOptions) (int64, error) {
463463
return db.GetEngine(db.DefaultContext).Where(opts.toCond()).Count(&Webhook{})
464464
}
465465

466-
// GetDefaultWebhooks returns all admin-default webhooks.
467-
func GetDefaultWebhooks(ctx context.Context) ([]*Webhook, error) {
468-
webhooks := make([]*Webhook, 0, 5)
469-
return webhooks, db.GetEngine(ctx).
470-
Where("repo_id=? AND org_id=? AND is_system_webhook=?", 0, 0, false).
471-
Find(&webhooks)
472-
}
473-
474-
// GetSystemOrDefaultWebhook returns admin system or default webhook by given ID.
475-
func GetSystemOrDefaultWebhook(id int64) (*Webhook, error) {
476-
webhook := &Webhook{ID: id}
477-
has, err := db.GetEngine(db.DefaultContext).
478-
Where("repo_id=? AND org_id=?", 0, 0).
479-
Get(webhook)
480-
if err != nil {
481-
return nil, err
482-
} else if !has {
483-
return nil, ErrWebhookNotExist{ID: id}
484-
}
485-
return webhook, nil
486-
}
487-
488-
// GetSystemWebhooks returns all admin system webhooks.
489-
func GetSystemWebhooks(ctx context.Context, isActive util.OptionalBool) ([]*Webhook, error) {
490-
webhooks := make([]*Webhook, 0, 5)
491-
if isActive.IsNone() {
492-
return webhooks, db.GetEngine(ctx).
493-
Where("repo_id=? AND org_id=? AND is_system_webhook=?", 0, 0, true).
494-
Find(&webhooks)
495-
}
496-
return webhooks, db.GetEngine(ctx).
497-
Where("repo_id=? AND org_id=? AND is_system_webhook=? AND is_active = ?", 0, 0, true, isActive.IsTrue()).
498-
Find(&webhooks)
499-
}
500-
501466
// UpdateWebhook updates information of webhook.
502467
func UpdateWebhook(w *Webhook) error {
503468
_, err := db.GetEngine(db.DefaultContext).ID(w.ID).AllCols().Update(w)
@@ -545,44 +510,3 @@ func DeleteWebhookByOrgID(orgID, id int64) error {
545510
OrgID: orgID,
546511
})
547512
}
548-
549-
// DeleteDefaultSystemWebhook deletes an admin-configured default or system webhook (where Org and Repo ID both 0)
550-
func DeleteDefaultSystemWebhook(id int64) error {
551-
ctx, committer, err := db.TxContext(db.DefaultContext)
552-
if err != nil {
553-
return err
554-
}
555-
defer committer.Close()
556-
557-
count, err := db.GetEngine(ctx).
558-
Where("repo_id=? AND org_id=?", 0, 0).
559-
Delete(&Webhook{ID: id})
560-
if err != nil {
561-
return err
562-
} else if count == 0 {
563-
return ErrWebhookNotExist{ID: id}
564-
}
565-
566-
if _, err := db.DeleteByBean(ctx, &HookTask{HookID: id}); err != nil {
567-
return err
568-
}
569-
570-
return committer.Commit()
571-
}
572-
573-
// CopyDefaultWebhooksToRepo creates copies of the default webhooks in a new repo
574-
func CopyDefaultWebhooksToRepo(ctx context.Context, repoID int64) error {
575-
ws, err := GetDefaultWebhooks(ctx)
576-
if err != nil {
577-
return fmt.Errorf("GetDefaultWebhooks: %w", err)
578-
}
579-
580-
for _, w := range ws {
581-
w.ID = 0
582-
w.RepoID = repoID
583-
if err := CreateWebhook(ctx, w); err != nil {
584-
return fmt.Errorf("CreateWebhook: %w", err)
585-
}
586-
}
587-
return nil
588-
}

models/webhook/webhook_system.go

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright 2021 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package webhook
5+
6+
import (
7+
"context"
8+
"fmt"
9+
10+
"code.gitea.io/gitea/models/db"
11+
"code.gitea.io/gitea/modules/util"
12+
)
13+
14+
// GetDefaultWebhooks returns all admin-default webhooks.
15+
func GetDefaultWebhooks(ctx context.Context) ([]*Webhook, error) {
16+
webhooks := make([]*Webhook, 0, 5)
17+
return webhooks, db.GetEngine(ctx).
18+
Where("repo_id=? AND org_id=? AND is_system_webhook=?", 0, 0, false).
19+
Find(&webhooks)
20+
}
21+
22+
// GetSystemOrDefaultWebhook returns admin system or default webhook by given ID.
23+
func GetSystemOrDefaultWebhook(ctx context.Context, id int64) (*Webhook, error) {
24+
webhook := &Webhook{ID: id}
25+
has, err := db.GetEngine(ctx).
26+
Where("repo_id=? AND org_id=?", 0, 0).
27+
Get(webhook)
28+
if err != nil {
29+
return nil, err
30+
} else if !has {
31+
return nil, ErrWebhookNotExist{ID: id}
32+
}
33+
return webhook, nil
34+
}
35+
36+
// GetSystemWebhooks returns all admin system webhooks.
37+
func GetSystemWebhooks(ctx context.Context, isActive util.OptionalBool) ([]*Webhook, error) {
38+
webhooks := make([]*Webhook, 0, 5)
39+
if isActive.IsNone() {
40+
return webhooks, db.GetEngine(ctx).
41+
Where("repo_id=? AND org_id=? AND is_system_webhook=?", 0, 0, true).
42+
Find(&webhooks)
43+
}
44+
return webhooks, db.GetEngine(ctx).
45+
Where("repo_id=? AND org_id=? AND is_system_webhook=? AND is_active = ?", 0, 0, true, isActive.IsTrue()).
46+
Find(&webhooks)
47+
}
48+
49+
// DeleteDefaultSystemWebhook deletes an admin-configured default or system webhook (where Org and Repo ID both 0)
50+
func DeleteDefaultSystemWebhook(ctx context.Context, id int64) error {
51+
return db.WithTx(ctx, func(ctx context.Context) error {
52+
count, err := db.GetEngine(ctx).
53+
Where("repo_id=? AND org_id=?", 0, 0).
54+
Delete(&Webhook{ID: id})
55+
if err != nil {
56+
return err
57+
} else if count == 0 {
58+
return ErrWebhookNotExist{ID: id}
59+
}
60+
61+
_, err = db.DeleteByBean(ctx, &HookTask{HookID: id})
62+
return err
63+
})
64+
}
65+
66+
// CopyDefaultWebhooksToRepo creates copies of the default webhooks in a new repo
67+
func CopyDefaultWebhooksToRepo(ctx context.Context, repoID int64) error {
68+
ws, err := GetDefaultWebhooks(ctx)
69+
if err != nil {
70+
return fmt.Errorf("GetDefaultWebhooks: %v", err)
71+
}
72+
73+
for _, w := range ws {
74+
w.ID = 0
75+
w.RepoID = repoID
76+
if err := CreateWebhook(ctx, w); err != nil {
77+
return fmt.Errorf("CreateWebhook: %v", err)
78+
}
79+
}
80+
return nil
81+
}

routers/api/v1/admin/hooks.go

+174
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
// Copyright 2021 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package admin
5+
6+
import (
7+
"net/http"
8+
9+
"code.gitea.io/gitea/models/webhook"
10+
"code.gitea.io/gitea/modules/context"
11+
"code.gitea.io/gitea/modules/setting"
12+
api "code.gitea.io/gitea/modules/structs"
13+
"code.gitea.io/gitea/modules/util"
14+
"code.gitea.io/gitea/modules/web"
15+
"code.gitea.io/gitea/routers/api/v1/utils"
16+
webhook_service "code.gitea.io/gitea/services/webhook"
17+
)
18+
19+
// ListHooks list system's webhooks
20+
func ListHooks(ctx *context.APIContext) {
21+
// swagger:operation GET /admin/hooks admin adminListHooks
22+
// ---
23+
// summary: List system's webhooks
24+
// produces:
25+
// - application/json
26+
// parameters:
27+
// - name: page
28+
// in: query
29+
// description: page number of results to return (1-based)
30+
// type: integer
31+
// - name: limit
32+
// in: query
33+
// description: page size of results
34+
// type: integer
35+
// responses:
36+
// "200":
37+
// "$ref": "#/responses/HookList"
38+
39+
sysHooks, err := webhook.GetSystemWebhooks(ctx, util.OptionalBoolNone)
40+
if err != nil {
41+
ctx.Error(http.StatusInternalServerError, "GetSystemWebhooks", err)
42+
return
43+
}
44+
hooks := make([]*api.Hook, len(sysHooks))
45+
for i, hook := range sysHooks {
46+
h, err := webhook_service.ToHook(setting.AppURL+"/admin", hook)
47+
if err != nil {
48+
ctx.Error(http.StatusInternalServerError, "convert.ToHook", err)
49+
return
50+
}
51+
hooks[i] = h
52+
}
53+
ctx.JSON(http.StatusOK, hooks)
54+
}
55+
56+
// GetHook get an organization's hook by id
57+
func GetHook(ctx *context.APIContext) {
58+
// swagger:operation GET /admin/hooks/{id} admin adminGetHook
59+
// ---
60+
// summary: Get a hook
61+
// produces:
62+
// - application/json
63+
// parameters:
64+
// - name: id
65+
// in: path
66+
// description: id of the hook to get
67+
// type: integer
68+
// format: int64
69+
// required: true
70+
// responses:
71+
// "200":
72+
// "$ref": "#/responses/Hook"
73+
74+
hookID := ctx.ParamsInt64(":id")
75+
hook, err := webhook.GetSystemOrDefaultWebhook(ctx, hookID)
76+
if err != nil {
77+
ctx.Error(http.StatusInternalServerError, "GetSystemOrDefaultWebhook", err)
78+
return
79+
}
80+
h, err := webhook_service.ToHook("/admin/", hook)
81+
if err != nil {
82+
ctx.Error(http.StatusInternalServerError, "convert.ToHook", err)
83+
return
84+
}
85+
ctx.JSON(http.StatusOK, h)
86+
}
87+
88+
// CreateHook create a hook for an organization
89+
func CreateHook(ctx *context.APIContext) {
90+
// swagger:operation POST /admin/hooks admin adminCreateHook
91+
// ---
92+
// summary: Create a hook
93+
// consumes:
94+
// - application/json
95+
// produces:
96+
// - application/json
97+
// parameters:
98+
// - name: body
99+
// in: body
100+
// required: true
101+
// schema:
102+
// "$ref": "#/definitions/CreateHookOption"
103+
// responses:
104+
// "201":
105+
// "$ref": "#/responses/Hook"
106+
107+
form := web.GetForm(ctx).(*api.CreateHookOption)
108+
// TODO in body params
109+
if !utils.CheckCreateHookOption(ctx, form) {
110+
return
111+
}
112+
utils.AddSystemHook(ctx, form)
113+
}
114+
115+
// EditHook modify a hook of a repository
116+
func EditHook(ctx *context.APIContext) {
117+
// swagger:operation PATCH /admin/hooks/{id} admin adminEditHook
118+
// ---
119+
// summary: Update a hook
120+
// consumes:
121+
// - application/json
122+
// produces:
123+
// - application/json
124+
// parameters:
125+
// - name: id
126+
// in: path
127+
// description: id of the hook to update
128+
// type: integer
129+
// format: int64
130+
// required: true
131+
// - name: body
132+
// in: body
133+
// schema:
134+
// "$ref": "#/definitions/EditHookOption"
135+
// responses:
136+
// "200":
137+
// "$ref": "#/responses/Hook"
138+
139+
form := web.GetForm(ctx).(*api.EditHookOption)
140+
141+
// TODO in body params
142+
hookID := ctx.ParamsInt64(":id")
143+
utils.EditSystemHook(ctx, form, hookID)
144+
}
145+
146+
// DeleteHook delete a system hook
147+
func DeleteHook(ctx *context.APIContext) {
148+
// swagger:operation DELETE /amdin/hooks/{id} admin adminDeleteHook
149+
// ---
150+
// summary: Delete a hook
151+
// produces:
152+
// - application/json
153+
// parameters:
154+
// - name: id
155+
// in: path
156+
// description: id of the hook to delete
157+
// type: integer
158+
// format: int64
159+
// required: true
160+
// responses:
161+
// "204":
162+
// "$ref": "#/responses/empty"
163+
164+
hookID := ctx.ParamsInt64(":id")
165+
if err := webhook.DeleteDefaultSystemWebhook(ctx, hookID); err != nil {
166+
if webhook.IsErrWebhookNotExist(err) {
167+
ctx.NotFound()
168+
} else {
169+
ctx.Error(http.StatusInternalServerError, "DeleteDefaultSystemWebhook", err)
170+
}
171+
return
172+
}
173+
ctx.Status(http.StatusNoContent)
174+
}

routers/api/v1/api.go

+7
Original file line numberDiff line numberDiff line change
@@ -1222,6 +1222,13 @@ func Routes(ctx gocontext.Context) *web.Route {
12221222
m.Post("/{username}/{reponame}", admin.AdoptRepository)
12231223
m.Delete("/{username}/{reponame}", admin.DeleteUnadoptedRepository)
12241224
})
1225+
m.Group("/hooks", func() {
1226+
m.Combo("").Get(admin.ListHooks).
1227+
Post(bind(api.CreateHookOption{}), admin.CreateHook)
1228+
m.Combo("/{id}").Get(admin.GetHook).
1229+
Patch(bind(api.EditHookOption{}), admin.EditHook).
1230+
Delete(admin.DeleteHook)
1231+
})
12251232
}, reqToken(auth_model.AccessTokenScopeSudo), reqSiteAdmin())
12261233

12271234
m.Group("/topics", func() {

0 commit comments

Comments
 (0)