summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--models/webhook/webhook.go76
-rw-r--r--models/webhook/webhook_system.go81
-rw-r--r--routers/api/v1/admin/hooks.go174
-rw-r--r--routers/api/v1/api.go7
-rw-r--r--routers/api/v1/utils/hook.go38
-rw-r--r--routers/web/admin/hooks.go2
-rw-r--r--routers/web/repo/webhook.go2
-rw-r--r--templates/swagger/v1_json.tmpl148
8 files changed, 450 insertions, 78 deletions
diff --git a/models/webhook/webhook.go b/models/webhook/webhook.go
index c24404c42c..64119f1494 100644
--- a/models/webhook/webhook.go
+++ b/models/webhook/webhook.go
@@ -463,41 +463,6 @@ func CountWebhooksByOpts(opts *ListWebhookOptions) (int64, error) {
return db.GetEngine(db.DefaultContext).Where(opts.toCond()).Count(&Webhook{})
}
-// GetDefaultWebhooks returns all admin-default webhooks.
-func GetDefaultWebhooks(ctx context.Context) ([]*Webhook, error) {
- webhooks := make([]*Webhook, 0, 5)
- return webhooks, db.GetEngine(ctx).
- Where("repo_id=? AND org_id=? AND is_system_webhook=?", 0, 0, false).
- Find(&webhooks)
-}
-
-// GetSystemOrDefaultWebhook returns admin system or default webhook by given ID.
-func GetSystemOrDefaultWebhook(id int64) (*Webhook, error) {
- webhook := &Webhook{ID: id}
- has, err := db.GetEngine(db.DefaultContext).
- Where("repo_id=? AND org_id=?", 0, 0).
- Get(webhook)
- if err != nil {
- return nil, err
- } else if !has {
- return nil, ErrWebhookNotExist{ID: id}
- }
- return webhook, nil
-}
-
-// GetSystemWebhooks returns all admin system webhooks.
-func GetSystemWebhooks(ctx context.Context, isActive util.OptionalBool) ([]*Webhook, error) {
- webhooks := make([]*Webhook, 0, 5)
- if isActive.IsNone() {
- return webhooks, db.GetEngine(ctx).
- Where("repo_id=? AND org_id=? AND is_system_webhook=?", 0, 0, true).
- Find(&webhooks)
- }
- return webhooks, db.GetEngine(ctx).
- Where("repo_id=? AND org_id=? AND is_system_webhook=? AND is_active = ?", 0, 0, true, isActive.IsTrue()).
- Find(&webhooks)
-}
-
// UpdateWebhook updates information of webhook.
func UpdateWebhook(w *Webhook) error {
_, err := db.GetEngine(db.DefaultContext).ID(w.ID).AllCols().Update(w)
@@ -545,44 +510,3 @@ func DeleteWebhookByOrgID(orgID, id int64) error {
OrgID: orgID,
})
}
-
-// DeleteDefaultSystemWebhook deletes an admin-configured default or system webhook (where Org and Repo ID both 0)
-func DeleteDefaultSystemWebhook(id int64) error {
- ctx, committer, err := db.TxContext(db.DefaultContext)
- if err != nil {
- return err
- }
- defer committer.Close()
-
- count, err := db.GetEngine(ctx).
- Where("repo_id=? AND org_id=?", 0, 0).
- Delete(&Webhook{ID: id})
- if err != nil {
- return err
- } else if count == 0 {
- return ErrWebhookNotExist{ID: id}
- }
-
- if _, err := db.DeleteByBean(ctx, &HookTask{HookID: id}); err != nil {
- return err
- }
-
- return committer.Commit()
-}
-
-// CopyDefaultWebhooksToRepo creates copies of the default webhooks in a new repo
-func CopyDefaultWebhooksToRepo(ctx context.Context, repoID int64) error {
- ws, err := GetDefaultWebhooks(ctx)
- if err != nil {
- return fmt.Errorf("GetDefaultWebhooks: %w", err)
- }
-
- for _, w := range ws {
- w.ID = 0
- w.RepoID = repoID
- if err := CreateWebhook(ctx, w); err != nil {
- return fmt.Errorf("CreateWebhook: %w", err)
- }
- }
- return nil
-}
diff --git a/models/webhook/webhook_system.go b/models/webhook/webhook_system.go
new file mode 100644
index 0000000000..21dc0406a0
--- /dev/null
+++ b/models/webhook/webhook_system.go
@@ -0,0 +1,81 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package webhook
+
+import (
+ "context"
+ "fmt"
+
+ "code.gitea.io/gitea/models/db"
+ "code.gitea.io/gitea/modules/util"
+)
+
+// GetDefaultWebhooks returns all admin-default webhooks.
+func GetDefaultWebhooks(ctx context.Context) ([]*Webhook, error) {
+ webhooks := make([]*Webhook, 0, 5)
+ return webhooks, db.GetEngine(ctx).
+ Where("repo_id=? AND org_id=? AND is_system_webhook=?", 0, 0, false).
+ Find(&webhooks)
+}
+
+// GetSystemOrDefaultWebhook returns admin system or default webhook by given ID.
+func GetSystemOrDefaultWebhook(ctx context.Context, id int64) (*Webhook, error) {
+ webhook := &Webhook{ID: id}
+ has, err := db.GetEngine(ctx).
+ Where("repo_id=? AND org_id=?", 0, 0).
+ Get(webhook)
+ if err != nil {
+ return nil, err
+ } else if !has {
+ return nil, ErrWebhookNotExist{ID: id}
+ }
+ return webhook, nil
+}
+
+// GetSystemWebhooks returns all admin system webhooks.
+func GetSystemWebhooks(ctx context.Context, isActive util.OptionalBool) ([]*Webhook, error) {
+ webhooks := make([]*Webhook, 0, 5)
+ if isActive.IsNone() {
+ return webhooks, db.GetEngine(ctx).
+ Where("repo_id=? AND org_id=? AND is_system_webhook=?", 0, 0, true).
+ Find(&webhooks)
+ }
+ return webhooks, db.GetEngine(ctx).
+ Where("repo_id=? AND org_id=? AND is_system_webhook=? AND is_active = ?", 0, 0, true, isActive.IsTrue()).
+ Find(&webhooks)
+}
+
+// DeleteDefaultSystemWebhook deletes an admin-configured default or system webhook (where Org and Repo ID both 0)
+func DeleteDefaultSystemWebhook(ctx context.Context, id int64) error {
+ return db.WithTx(ctx, func(ctx context.Context) error {
+ count, err := db.GetEngine(ctx).
+ Where("repo_id=? AND org_id=?", 0, 0).
+ Delete(&Webhook{ID: id})
+ if err != nil {
+ return err
+ } else if count == 0 {
+ return ErrWebhookNotExist{ID: id}
+ }
+
+ _, err = db.DeleteByBean(ctx, &HookTask{HookID: id})
+ return err
+ })
+}
+
+// CopyDefaultWebhooksToRepo creates copies of the default webhooks in a new repo
+func CopyDefaultWebhooksToRepo(ctx context.Context, repoID int64) error {
+ ws, err := GetDefaultWebhooks(ctx)
+ if err != nil {
+ return fmt.Errorf("GetDefaultWebhooks: %v", err)
+ }
+
+ for _, w := range ws {
+ w.ID = 0
+ w.RepoID = repoID
+ if err := CreateWebhook(ctx, w); err != nil {
+ return fmt.Errorf("CreateWebhook: %v", err)
+ }
+ }
+ return nil
+}
diff --git a/routers/api/v1/admin/hooks.go b/routers/api/v1/admin/hooks.go
new file mode 100644
index 0000000000..2aed4139f3
--- /dev/null
+++ b/routers/api/v1/admin/hooks.go
@@ -0,0 +1,174 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package admin
+
+import (
+ "net/http"
+
+ "code.gitea.io/gitea/models/webhook"
+ "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/setting"
+ api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/routers/api/v1/utils"
+ webhook_service "code.gitea.io/gitea/services/webhook"
+)
+
+// ListHooks list system's webhooks
+func ListHooks(ctx *context.APIContext) {
+ // swagger:operation GET /admin/hooks admin adminListHooks
+ // ---
+ // summary: List system's webhooks
+ // produces:
+ // - application/json
+ // parameters:
+ // - name: page
+ // in: query
+ // description: page number of results to return (1-based)
+ // type: integer
+ // - name: limit
+ // in: query
+ // description: page size of results
+ // type: integer
+ // responses:
+ // "200":
+ // "$ref": "#/responses/HookList"
+
+ sysHooks, err := webhook.GetSystemWebhooks(ctx, util.OptionalBoolNone)
+ if err != nil {
+ ctx.Error(http.StatusInternalServerError, "GetSystemWebhooks", err)
+ return
+ }
+ hooks := make([]*api.Hook, len(sysHooks))
+ for i, hook := range sysHooks {
+ h, err := webhook_service.ToHook(setting.AppURL+"/admin", hook)
+ if err != nil {
+ ctx.Error(http.StatusInternalServerError, "convert.ToHook", err)
+ return
+ }
+ hooks[i] = h
+ }
+ ctx.JSON(http.StatusOK, hooks)
+}
+
+// GetHook get an organization's hook by id
+func GetHook(ctx *context.APIContext) {
+ // swagger:operation GET /admin/hooks/{id} admin adminGetHook
+ // ---
+ // summary: Get a hook
+ // produces:
+ // - application/json
+ // parameters:
+ // - name: id
+ // in: path
+ // description: id of the hook to get
+ // type: integer
+ // format: int64
+ // required: true
+ // responses:
+ // "200":
+ // "$ref": "#/responses/Hook"
+
+ hookID := ctx.ParamsInt64(":id")
+ hook, err := webhook.GetSystemOrDefaultWebhook(ctx, hookID)
+ if err != nil {
+ ctx.Error(http.StatusInternalServerError, "GetSystemOrDefaultWebhook", err)
+ return
+ }
+ h, err := webhook_service.ToHook("/admin/", hook)
+ if err != nil {
+ ctx.Error(http.StatusInternalServerError, "convert.ToHook", err)
+ return
+ }
+ ctx.JSON(http.StatusOK, h)
+}
+
+// CreateHook create a hook for an organization
+func CreateHook(ctx *context.APIContext) {
+ // swagger:operation POST /admin/hooks admin adminCreateHook
+ // ---
+ // summary: Create a hook
+ // consumes:
+ // - application/json
+ // produces:
+ // - application/json
+ // parameters:
+ // - name: body
+ // in: body
+ // required: true
+ // schema:
+ // "$ref": "#/definitions/CreateHookOption"
+ // responses:
+ // "201":
+ // "$ref": "#/responses/Hook"
+
+ form := web.GetForm(ctx).(*api.CreateHookOption)
+ // TODO in body params
+ if !utils.CheckCreateHookOption(ctx, form) {
+ return
+ }
+ utils.AddSystemHook(ctx, form)
+}
+
+// EditHook modify a hook of a repository
+func EditHook(ctx *context.APIContext) {
+ // swagger:operation PATCH /admin/hooks/{id} admin adminEditHook
+ // ---
+ // summary: Update a hook
+ // consumes:
+ // - application/json
+ // produces:
+ // - application/json
+ // parameters:
+ // - name: id
+ // in: path
+ // description: id of the hook to update
+ // type: integer
+ // format: int64
+ // required: true
+ // - name: body
+ // in: body
+ // schema:
+ // "$ref": "#/definitions/EditHookOption"
+ // responses:
+ // "200":
+ // "$ref": "#/responses/Hook"
+
+ form := web.GetForm(ctx).(*api.EditHookOption)
+
+ // TODO in body params
+ hookID := ctx.ParamsInt64(":id")
+ utils.EditSystemHook(ctx, form, hookID)
+}
+
+// DeleteHook delete a system hook
+func DeleteHook(ctx *context.APIContext) {
+ // swagger:operation DELETE /amdin/hooks/{id} admin adminDeleteHook
+ // ---
+ // summary: Delete a hook
+ // produces:
+ // - application/json
+ // parameters:
+ // - name: id
+ // in: path
+ // description: id of the hook to delete
+ // type: integer
+ // format: int64
+ // required: true
+ // responses:
+ // "204":
+ // "$ref": "#/responses/empty"
+
+ hookID := ctx.ParamsInt64(":id")
+ if err := webhook.DeleteDefaultSystemWebhook(ctx, hookID); err != nil {
+ if webhook.IsErrWebhookNotExist(err) {
+ ctx.NotFound()
+ } else {
+ ctx.Error(http.StatusInternalServerError, "DeleteDefaultSystemWebhook", err)
+ }
+ return
+ }
+ ctx.Status(http.StatusNoContent)
+}
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index 21bc2e2de4..eef2a64244 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -1222,6 +1222,13 @@ func Routes(ctx gocontext.Context) *web.Route {
m.Post("/{username}/{reponame}", admin.AdoptRepository)
m.Delete("/{username}/{reponame}", admin.DeleteUnadoptedRepository)
})
+ m.Group("/hooks", func() {
+ m.Combo("").Get(admin.ListHooks).
+ Post(bind(api.CreateHookOption{}), admin.CreateHook)
+ m.Combo("/{id}").Get(admin.GetHook).
+ Patch(bind(api.EditHookOption{}), admin.EditHook).
+ Delete(admin.DeleteHook)
+ })
}, reqToken(auth_model.AccessTokenScopeSudo), reqSiteAdmin())
m.Group("/topics", func() {
diff --git a/routers/api/v1/utils/hook.go b/routers/api/v1/utils/hook.go
index 44fba22b5a..f6aaf74aff 100644
--- a/routers/api/v1/utils/hook.go
+++ b/routers/api/v1/utils/hook.go
@@ -11,6 +11,7 @@ import (
"code.gitea.io/gitea/models/webhook"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/json"
+ "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
webhook_module "code.gitea.io/gitea/modules/webhook"
@@ -67,6 +68,19 @@ func CheckCreateHookOption(ctx *context.APIContext, form *api.CreateHookOption)
return true
}
+// AddSystemHook add a system hook
+func AddSystemHook(ctx *context.APIContext, form *api.CreateHookOption) {
+ hook, ok := addHook(ctx, form, 0, 0)
+ if ok {
+ h, err := webhook_service.ToHook(setting.AppSubURL+"/admin", hook)
+ if err != nil {
+ ctx.Error(http.StatusInternalServerError, "convert.ToHook", err)
+ return
+ }
+ ctx.JSON(http.StatusCreated, h)
+ }
+}
+
// AddOrgHook add a hook to an organization. Writes to `ctx` accordingly
func AddOrgHook(ctx *context.APIContext, form *api.CreateHookOption) {
org := ctx.Org.Organization
@@ -196,6 +210,30 @@ func addHook(ctx *context.APIContext, form *api.CreateHookOption, orgID, repoID
return w, true
}
+// EditSystemHook edit system webhook `w` according to `form`. Writes to `ctx` accordingly
+func EditSystemHook(ctx *context.APIContext, form *api.EditHookOption, hookID int64) {
+ hook, err := webhook.GetSystemOrDefaultWebhook(ctx, hookID)
+ if err != nil {
+ ctx.Error(http.StatusInternalServerError, "GetSystemOrDefaultWebhook", err)
+ return
+ }
+ if !editHook(ctx, form, hook) {
+ ctx.Error(http.StatusInternalServerError, "editHook", err)
+ return
+ }
+ updated, err := webhook.GetSystemOrDefaultWebhook(ctx, hookID)
+ if err != nil {
+ ctx.Error(http.StatusInternalServerError, "GetSystemOrDefaultWebhook", err)
+ return
+ }
+ h, err := webhook_service.ToHook(setting.AppURL+"/admin", updated)
+ if err != nil {
+ ctx.Error(http.StatusInternalServerError, "convert.ToHook", err)
+ return
+ }
+ ctx.JSON(http.StatusOK, h)
+}
+
// EditOrgHook edit webhook `w` according to `form`. Writes to `ctx` accordingly
func EditOrgHook(ctx *context.APIContext, form *api.EditHookOption, hookID int64) {
org := ctx.Org.Organization
diff --git a/routers/web/admin/hooks.go b/routers/web/admin/hooks.go
index e8db9a3ded..57cf5f49e5 100644
--- a/routers/web/admin/hooks.go
+++ b/routers/web/admin/hooks.go
@@ -60,7 +60,7 @@ func DefaultOrSystemWebhooks(ctx *context.Context) {
// DeleteDefaultOrSystemWebhook handler to delete an admin-defined system or default webhook
func DeleteDefaultOrSystemWebhook(ctx *context.Context) {
- if err := webhook.DeleteDefaultSystemWebhook(ctx.FormInt64("id")); err != nil {
+ if err := webhook.DeleteDefaultSystemWebhook(ctx, ctx.FormInt64("id")); err != nil {
ctx.Flash.Error("DeleteDefaultWebhook: " + err.Error())
} else {
ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success"))
diff --git a/routers/web/repo/webhook.go b/routers/web/repo/webhook.go
index 96261af674..d3826c3f3d 100644
--- a/routers/web/repo/webhook.go
+++ b/routers/web/repo/webhook.go
@@ -591,7 +591,7 @@ func checkWebhook(ctx *context.Context) (*orgRepoCtx, *webhook.Webhook) {
} else if orCtx.OrgID > 0 {
w, err = webhook.GetWebhookByOrgID(ctx.Org.Organization.ID, ctx.ParamsInt64(":id"))
} else if orCtx.IsAdmin {
- w, err = webhook.GetSystemOrDefaultWebhook(ctx.ParamsInt64(":id"))
+ w, err = webhook.GetSystemOrDefaultWebhook(ctx, ctx.ParamsInt64(":id"))
}
if err != nil || w == nil {
if webhook.IsErrWebhookNotExist(err) {
diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl
index cd64b7070f..726b771cfc 100644
--- a/templates/swagger/v1_json.tmpl
+++ b/templates/swagger/v1_json.tmpl
@@ -138,6 +138,127 @@
}
}
},
+ "/admin/hooks": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "List system's webhooks",
+ "operationId": "adminListHooks",
+ "parameters": [
+ {
+ "type": "integer",
+ "description": "page number of results to return (1-based)",
+ "name": "page",
+ "in": "query"
+ },
+ {
+ "type": "integer",
+ "description": "page size of results",
+ "name": "limit",
+ "in": "query"
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/HookList"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "Create a hook",
+ "operationId": "adminCreateHook",
+ "parameters": [
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/CreateHookOption"
+ }
+ }
+ ],
+ "responses": {
+ "201": {
+ "$ref": "#/responses/Hook"
+ }
+ }
+ }
+ },
+ "/admin/hooks/{id}": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "Get a hook",
+ "operationId": "adminGetHook",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the hook to get",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Hook"
+ }
+ }
+ },
+ "patch": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "Update a hook",
+ "operationId": "adminEditHook",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the hook to update",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/EditHookOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/Hook"
+ }
+ }
+ }
+ },
"/admin/orgs": {
"get": {
"produces": [
@@ -601,6 +722,33 @@
}
}
},
+ "/amdin/hooks/{id}": {
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "admin"
+ ],
+ "summary": "Delete a hook",
+ "operationId": "adminDeleteHook",
+ "parameters": [
+ {
+ "type": "integer",
+ "format": "int64",
+ "description": "id of the hook to delete",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ }
+ }
+ }
+ },
"/markdown": {
"post": {
"consumes": [