code.gitea.io/gitea@v1.21.7/routers/api/v1/repo/hook.go (about) 1 // Copyright 2014 The Gogs Authors. All rights reserved. 2 // Copyright 2020 The Gitea Authors. 3 // SPDX-License-Identifier: MIT 4 5 package repo 6 7 import ( 8 "net/http" 9 10 "code.gitea.io/gitea/models/perm" 11 access_model "code.gitea.io/gitea/models/perm/access" 12 "code.gitea.io/gitea/models/webhook" 13 "code.gitea.io/gitea/modules/context" 14 "code.gitea.io/gitea/modules/git" 15 "code.gitea.io/gitea/modules/setting" 16 api "code.gitea.io/gitea/modules/structs" 17 "code.gitea.io/gitea/modules/web" 18 webhook_module "code.gitea.io/gitea/modules/webhook" 19 "code.gitea.io/gitea/routers/api/v1/utils" 20 "code.gitea.io/gitea/services/convert" 21 webhook_service "code.gitea.io/gitea/services/webhook" 22 ) 23 24 // ListHooks list all hooks of a repository 25 func ListHooks(ctx *context.APIContext) { 26 // swagger:operation GET /repos/{owner}/{repo}/hooks repository repoListHooks 27 // --- 28 // summary: List the hooks in a repository 29 // produces: 30 // - application/json 31 // parameters: 32 // - name: owner 33 // in: path 34 // description: owner of the repo 35 // type: string 36 // required: true 37 // - name: repo 38 // in: path 39 // description: name of the repo 40 // type: string 41 // required: true 42 // - name: page 43 // in: query 44 // description: page number of results to return (1-based) 45 // type: integer 46 // - name: limit 47 // in: query 48 // description: page size of results 49 // type: integer 50 // responses: 51 // "200": 52 // "$ref": "#/responses/HookList" 53 // "404": 54 // "$ref": "#/responses/notFound" 55 56 opts := &webhook.ListWebhookOptions{ 57 ListOptions: utils.GetListOptions(ctx), 58 RepoID: ctx.Repo.Repository.ID, 59 } 60 61 count, err := webhook.CountWebhooksByOpts(opts) 62 if err != nil { 63 ctx.InternalServerError(err) 64 return 65 } 66 67 hooks, err := webhook.ListWebhooksByOpts(ctx, opts) 68 if err != nil { 69 ctx.InternalServerError(err) 70 return 71 } 72 73 apiHooks := make([]*api.Hook, len(hooks)) 74 for i := range hooks { 75 apiHooks[i], err = webhook_service.ToHook(ctx.Repo.RepoLink, hooks[i]) 76 if err != nil { 77 ctx.InternalServerError(err) 78 return 79 } 80 } 81 82 ctx.SetTotalCountHeader(count) 83 ctx.JSON(http.StatusOK, &apiHooks) 84 } 85 86 // GetHook get a repo's hook by id 87 func GetHook(ctx *context.APIContext) { 88 // swagger:operation GET /repos/{owner}/{repo}/hooks/{id} repository repoGetHook 89 // --- 90 // summary: Get a hook 91 // produces: 92 // - application/json 93 // parameters: 94 // - name: owner 95 // in: path 96 // description: owner of the repo 97 // type: string 98 // required: true 99 // - name: repo 100 // in: path 101 // description: name of the repo 102 // type: string 103 // required: true 104 // - name: id 105 // in: path 106 // description: id of the hook to get 107 // type: integer 108 // format: int64 109 // required: true 110 // responses: 111 // "200": 112 // "$ref": "#/responses/Hook" 113 // "404": 114 // "$ref": "#/responses/notFound" 115 116 repo := ctx.Repo 117 hookID := ctx.ParamsInt64(":id") 118 hook, err := utils.GetRepoHook(ctx, repo.Repository.ID, hookID) 119 if err != nil { 120 return 121 } 122 apiHook, err := webhook_service.ToHook(repo.RepoLink, hook) 123 if err != nil { 124 ctx.InternalServerError(err) 125 return 126 } 127 ctx.JSON(http.StatusOK, apiHook) 128 } 129 130 // TestHook tests a hook 131 func TestHook(ctx *context.APIContext) { 132 // swagger:operation POST /repos/{owner}/{repo}/hooks/{id}/tests repository repoTestHook 133 // --- 134 // summary: Test a push webhook 135 // produces: 136 // - application/json 137 // parameters: 138 // - name: owner 139 // in: path 140 // description: owner of the repo 141 // type: string 142 // required: true 143 // - name: repo 144 // in: path 145 // description: name of the repo 146 // type: string 147 // required: true 148 // - name: id 149 // in: path 150 // description: id of the hook to test 151 // type: integer 152 // format: int64 153 // required: true 154 // - name: ref 155 // in: query 156 // description: "The name of the commit/branch/tag, indicates which commit will be loaded to the webhook payload." 157 // type: string 158 // required: false 159 // responses: 160 // "204": 161 // "$ref": "#/responses/empty" 162 // "404": 163 // "$ref": "#/responses/notFound" 164 165 if ctx.Repo.Commit == nil { 166 // if repo does not have any commits, then don't send a webhook 167 ctx.Status(http.StatusNoContent) 168 return 169 } 170 171 ref := git.BranchPrefix + ctx.Repo.Repository.DefaultBranch 172 if r := ctx.FormTrim("ref"); r != "" { 173 ref = r 174 } 175 176 hookID := ctx.ParamsInt64(":id") 177 hook, err := utils.GetRepoHook(ctx, ctx.Repo.Repository.ID, hookID) 178 if err != nil { 179 return 180 } 181 182 commit := convert.ToPayloadCommit(ctx, ctx.Repo.Repository, ctx.Repo.Commit) 183 184 commitID := ctx.Repo.Commit.ID.String() 185 if err := webhook_service.PrepareWebhook(ctx, hook, webhook_module.HookEventPush, &api.PushPayload{ 186 Ref: ref, 187 Before: commitID, 188 After: commitID, 189 CompareURL: setting.AppURL + ctx.Repo.Repository.ComposeCompareURL(commitID, commitID), 190 Commits: []*api.PayloadCommit{commit}, 191 TotalCommits: 1, 192 HeadCommit: commit, 193 Repo: convert.ToRepo(ctx, ctx.Repo.Repository, access_model.Permission{AccessMode: perm.AccessModeNone}), 194 Pusher: convert.ToUserWithAccessMode(ctx, ctx.Doer, perm.AccessModeNone), 195 Sender: convert.ToUserWithAccessMode(ctx, ctx.Doer, perm.AccessModeNone), 196 }); err != nil { 197 ctx.Error(http.StatusInternalServerError, "PrepareWebhook: ", err) 198 return 199 } 200 201 ctx.Status(http.StatusNoContent) 202 } 203 204 // CreateHook create a hook for a repository 205 func CreateHook(ctx *context.APIContext) { 206 // swagger:operation POST /repos/{owner}/{repo}/hooks repository repoCreateHook 207 // --- 208 // summary: Create a hook 209 // consumes: 210 // - application/json 211 // produces: 212 // - application/json 213 // parameters: 214 // - name: owner 215 // in: path 216 // description: owner of the repo 217 // type: string 218 // required: true 219 // - name: repo 220 // in: path 221 // description: name of the repo 222 // type: string 223 // required: true 224 // - name: body 225 // in: body 226 // schema: 227 // "$ref": "#/definitions/CreateHookOption" 228 // responses: 229 // "201": 230 // "$ref": "#/responses/Hook" 231 // "404": 232 // "$ref": "#/responses/notFound" 233 234 utils.AddRepoHook(ctx, web.GetForm(ctx).(*api.CreateHookOption)) 235 } 236 237 // EditHook modify a hook of a repository 238 func EditHook(ctx *context.APIContext) { 239 // swagger:operation PATCH /repos/{owner}/{repo}/hooks/{id} repository repoEditHook 240 // --- 241 // summary: Edit a hook in a repository 242 // produces: 243 // - application/json 244 // parameters: 245 // - name: owner 246 // in: path 247 // description: owner of the repo 248 // type: string 249 // required: true 250 // - name: repo 251 // in: path 252 // description: name of the repo 253 // type: string 254 // required: true 255 // - name: id 256 // in: path 257 // description: index of the hook 258 // type: integer 259 // format: int64 260 // required: true 261 // - name: body 262 // in: body 263 // schema: 264 // "$ref": "#/definitions/EditHookOption" 265 // responses: 266 // "200": 267 // "$ref": "#/responses/Hook" 268 // "404": 269 // "$ref": "#/responses/notFound" 270 form := web.GetForm(ctx).(*api.EditHookOption) 271 hookID := ctx.ParamsInt64(":id") 272 utils.EditRepoHook(ctx, form, hookID) 273 } 274 275 // DeleteHook delete a hook of a repository 276 func DeleteHook(ctx *context.APIContext) { 277 // swagger:operation DELETE /repos/{owner}/{repo}/hooks/{id} repository repoDeleteHook 278 // --- 279 // summary: Delete a hook in a repository 280 // produces: 281 // - application/json 282 // parameters: 283 // - name: owner 284 // in: path 285 // description: owner of the repo 286 // type: string 287 // required: true 288 // - name: repo 289 // in: path 290 // description: name of the repo 291 // type: string 292 // required: true 293 // - name: id 294 // in: path 295 // description: id of the hook to delete 296 // type: integer 297 // format: int64 298 // required: true 299 // responses: 300 // "204": 301 // "$ref": "#/responses/empty" 302 // "404": 303 // "$ref": "#/responses/notFound" 304 if err := webhook.DeleteWebhookByRepoID(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")); err != nil { 305 if webhook.IsErrWebhookNotExist(err) { 306 ctx.NotFound() 307 } else { 308 ctx.Error(http.StatusInternalServerError, "DeleteWebhookByRepoID", err) 309 } 310 return 311 } 312 ctx.Status(http.StatusNoContent) 313 }