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  }