mirror of
https://github.com/go-gitea/gitea
synced 2025-01-10 17:54:27 +00:00
2a828e2798
In history (from some legacy frameworks), both `:name` and `name` are supported as path path name, `:name` is an alias to `name`. To make code consistent, now we should only use `name` but not `:name`. Also added panic check in related functions to make sure the name won't be abused in case some downstreams still use them.
310 lines
8.0 KiB
Go
310 lines
8.0 KiB
Go
// Copyright 2023 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package repo
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
issues_model "code.gitea.io/gitea/models/issues"
|
|
api "code.gitea.io/gitea/modules/structs"
|
|
"code.gitea.io/gitea/services/context"
|
|
"code.gitea.io/gitea/services/convert"
|
|
)
|
|
|
|
// PinIssue pins a issue
|
|
func PinIssue(ctx *context.APIContext) {
|
|
// swagger:operation POST /repos/{owner}/{repo}/issues/{index}/pin issue pinIssue
|
|
// ---
|
|
// summary: Pin an Issue
|
|
// parameters:
|
|
// - name: owner
|
|
// in: path
|
|
// description: owner of the repo
|
|
// type: string
|
|
// required: true
|
|
// - name: repo
|
|
// in: path
|
|
// description: name of the repo
|
|
// type: string
|
|
// required: true
|
|
// - name: index
|
|
// in: path
|
|
// description: index of issue to pin
|
|
// type: integer
|
|
// format: int64
|
|
// required: true
|
|
// responses:
|
|
// "204":
|
|
// "$ref": "#/responses/empty"
|
|
// "403":
|
|
// "$ref": "#/responses/forbidden"
|
|
// "404":
|
|
// "$ref": "#/responses/notFound"
|
|
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
|
if err != nil {
|
|
if issues_model.IsErrIssueNotExist(err) {
|
|
ctx.NotFound()
|
|
} else if issues_model.IsErrIssueMaxPinReached(err) {
|
|
ctx.Error(http.StatusBadRequest, "MaxPinReached", err)
|
|
} else {
|
|
ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
// If we don't do this, it will crash when trying to add the pin event to the comment history
|
|
err = issue.LoadRepo(ctx)
|
|
if err != nil {
|
|
ctx.Error(http.StatusInternalServerError, "LoadRepo", err)
|
|
return
|
|
}
|
|
|
|
err = issue.Pin(ctx, ctx.Doer)
|
|
if err != nil {
|
|
ctx.Error(http.StatusInternalServerError, "PinIssue", err)
|
|
return
|
|
}
|
|
|
|
ctx.Status(http.StatusNoContent)
|
|
}
|
|
|
|
// UnpinIssue unpins a Issue
|
|
func UnpinIssue(ctx *context.APIContext) {
|
|
// swagger:operation DELETE /repos/{owner}/{repo}/issues/{index}/pin issue unpinIssue
|
|
// ---
|
|
// summary: Unpin an Issue
|
|
// parameters:
|
|
// - name: owner
|
|
// in: path
|
|
// description: owner of the repo
|
|
// type: string
|
|
// required: true
|
|
// - name: repo
|
|
// in: path
|
|
// description: name of the repo
|
|
// type: string
|
|
// required: true
|
|
// - name: index
|
|
// in: path
|
|
// description: index of issue to unpin
|
|
// type: integer
|
|
// format: int64
|
|
// required: true
|
|
// responses:
|
|
// "204":
|
|
// "$ref": "#/responses/empty"
|
|
// "403":
|
|
// "$ref": "#/responses/forbidden"
|
|
// "404":
|
|
// "$ref": "#/responses/notFound"
|
|
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
|
if err != nil {
|
|
if issues_model.IsErrIssueNotExist(err) {
|
|
ctx.NotFound()
|
|
} else {
|
|
ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
// If we don't do this, it will crash when trying to add the unpin event to the comment history
|
|
err = issue.LoadRepo(ctx)
|
|
if err != nil {
|
|
ctx.Error(http.StatusInternalServerError, "LoadRepo", err)
|
|
return
|
|
}
|
|
|
|
err = issue.Unpin(ctx, ctx.Doer)
|
|
if err != nil {
|
|
ctx.Error(http.StatusInternalServerError, "UnpinIssue", err)
|
|
return
|
|
}
|
|
|
|
ctx.Status(http.StatusNoContent)
|
|
}
|
|
|
|
// MoveIssuePin moves a pinned Issue to a new Position
|
|
func MoveIssuePin(ctx *context.APIContext) {
|
|
// swagger:operation PATCH /repos/{owner}/{repo}/issues/{index}/pin/{position} issue moveIssuePin
|
|
// ---
|
|
// summary: Moves the Pin to the given Position
|
|
// parameters:
|
|
// - name: owner
|
|
// in: path
|
|
// description: owner of the repo
|
|
// type: string
|
|
// required: true
|
|
// - name: repo
|
|
// in: path
|
|
// description: name of the repo
|
|
// type: string
|
|
// required: true
|
|
// - name: index
|
|
// in: path
|
|
// description: index of issue
|
|
// type: integer
|
|
// format: int64
|
|
// required: true
|
|
// - name: position
|
|
// in: path
|
|
// description: the new position
|
|
// type: integer
|
|
// format: int64
|
|
// required: true
|
|
// responses:
|
|
// "204":
|
|
// "$ref": "#/responses/empty"
|
|
// "403":
|
|
// "$ref": "#/responses/forbidden"
|
|
// "404":
|
|
// "$ref": "#/responses/notFound"
|
|
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
|
if err != nil {
|
|
if issues_model.IsErrIssueNotExist(err) {
|
|
ctx.NotFound()
|
|
} else {
|
|
ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
err = issue.MovePin(ctx, int(ctx.PathParamInt64("position")))
|
|
if err != nil {
|
|
ctx.Error(http.StatusInternalServerError, "MovePin", err)
|
|
return
|
|
}
|
|
|
|
ctx.Status(http.StatusNoContent)
|
|
}
|
|
|
|
// ListPinnedIssues returns a list of all pinned Issues
|
|
func ListPinnedIssues(ctx *context.APIContext) {
|
|
// swagger:operation GET /repos/{owner}/{repo}/issues/pinned repository repoListPinnedIssues
|
|
// ---
|
|
// summary: List a repo's pinned issues
|
|
// produces:
|
|
// - application/json
|
|
// parameters:
|
|
// - name: owner
|
|
// in: path
|
|
// description: owner of the repo
|
|
// type: string
|
|
// required: true
|
|
// - name: repo
|
|
// in: path
|
|
// description: name of the repo
|
|
// type: string
|
|
// required: true
|
|
// responses:
|
|
// "200":
|
|
// "$ref": "#/responses/IssueList"
|
|
// "404":
|
|
// "$ref": "#/responses/notFound"
|
|
issues, err := issues_model.GetPinnedIssues(ctx, ctx.Repo.Repository.ID, false)
|
|
if err != nil {
|
|
ctx.Error(http.StatusInternalServerError, "LoadPinnedIssues", err)
|
|
return
|
|
}
|
|
|
|
ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, ctx.Doer, issues))
|
|
}
|
|
|
|
// ListPinnedPullRequests returns a list of all pinned PRs
|
|
func ListPinnedPullRequests(ctx *context.APIContext) {
|
|
// swagger:operation GET /repos/{owner}/{repo}/pulls/pinned repository repoListPinnedPullRequests
|
|
// ---
|
|
// summary: List a repo's pinned pull requests
|
|
// produces:
|
|
// - application/json
|
|
// parameters:
|
|
// - name: owner
|
|
// in: path
|
|
// description: owner of the repo
|
|
// type: string
|
|
// required: true
|
|
// - name: repo
|
|
// in: path
|
|
// description: name of the repo
|
|
// type: string
|
|
// required: true
|
|
// responses:
|
|
// "200":
|
|
// "$ref": "#/responses/PullRequestList"
|
|
// "404":
|
|
// "$ref": "#/responses/notFound"
|
|
issues, err := issues_model.GetPinnedIssues(ctx, ctx.Repo.Repository.ID, true)
|
|
if err != nil {
|
|
ctx.Error(http.StatusInternalServerError, "LoadPinnedPullRequests", err)
|
|
return
|
|
}
|
|
|
|
apiPrs := make([]*api.PullRequest, len(issues))
|
|
if err := issues.LoadPullRequests(ctx); err != nil {
|
|
ctx.Error(http.StatusInternalServerError, "LoadPullRequests", err)
|
|
return
|
|
}
|
|
for i, currentIssue := range issues {
|
|
pr := currentIssue.PullRequest
|
|
if err = pr.LoadAttributes(ctx); err != nil {
|
|
ctx.Error(http.StatusInternalServerError, "LoadAttributes", err)
|
|
return
|
|
}
|
|
|
|
if err = pr.LoadBaseRepo(ctx); err != nil {
|
|
ctx.Error(http.StatusInternalServerError, "LoadBaseRepo", err)
|
|
return
|
|
}
|
|
|
|
if err = pr.LoadHeadRepo(ctx); err != nil {
|
|
ctx.Error(http.StatusInternalServerError, "LoadHeadRepo", err)
|
|
return
|
|
}
|
|
|
|
apiPrs[i] = convert.ToAPIPullRequest(ctx, pr, ctx.Doer)
|
|
}
|
|
|
|
ctx.JSON(http.StatusOK, &apiPrs)
|
|
}
|
|
|
|
// AreNewIssuePinsAllowed returns if new issues pins are allowed
|
|
func AreNewIssuePinsAllowed(ctx *context.APIContext) {
|
|
// swagger:operation GET /repos/{owner}/{repo}/new_pin_allowed repository repoNewPinAllowed
|
|
// ---
|
|
// summary: Returns if new Issue Pins are allowed
|
|
// produces:
|
|
// - application/json
|
|
// parameters:
|
|
// - name: owner
|
|
// in: path
|
|
// description: owner of the repo
|
|
// type: string
|
|
// required: true
|
|
// - name: repo
|
|
// in: path
|
|
// description: name of the repo
|
|
// type: string
|
|
// required: true
|
|
// responses:
|
|
// "200":
|
|
// "$ref": "#/responses/RepoNewIssuePinsAllowed"
|
|
// "404":
|
|
// "$ref": "#/responses/notFound"
|
|
pinsAllowed := api.NewIssuePinsAllowed{}
|
|
var err error
|
|
|
|
pinsAllowed.Issues, err = issues_model.IsNewPinAllowed(ctx, ctx.Repo.Repository.ID, false)
|
|
if err != nil {
|
|
ctx.Error(http.StatusInternalServerError, "IsNewIssuePinAllowed", err)
|
|
return
|
|
}
|
|
|
|
pinsAllowed.PullRequests, err = issues_model.IsNewPinAllowed(ctx, ctx.Repo.Repository.ID, true)
|
|
if err != nil {
|
|
ctx.Error(http.StatusInternalServerError, "IsNewPullRequestPinAllowed", err)
|
|
return
|
|
}
|
|
|
|
ctx.JSON(http.StatusOK, pinsAllowed)
|
|
}
|