forgejo-federation/routers/api/v1/repo/issue_pin.go
Lunny Xiao 894d9b2836
Move context from modules to services (#29440)
Since `modules/context` has to depend on `models` and many other
packages, it should be moved from `modules/context` to
`services/context` according to design principles. There is no logic
code change on this PR, only move packages.

- Move `code.gitea.io/gitea/modules/context` to
`code.gitea.io/gitea/services/context`
- Move `code.gitea.io/gitea/modules/contexttest` to
`code.gitea.io/gitea/services/contexttest` because of depending on
context
- Move `code.gitea.io/gitea/modules/upload` to
`code.gitea.io/gitea/services/context/upload` because of depending on
context

(cherry picked from commit 29f149bd9f517225a3c9f1ca3fb0a7b5325af696)

Conflicts:
	routers/api/packages/alpine/alpine.go
	routers/api/v1/repo/issue_reaction.go
	routers/install/install.go
	routers/web/admin/config.go
	routers/web/passkey.go
	routers/web/repo/search.go
	routers/web/repo/setting/default_branch.go
	routers/web/user/home.go
	routers/web/user/profile.go
	tests/integration/editor_test.go
	tests/integration/integration_test.go
	tests/integration/mirror_push_test.go
	trivial context conflicts
	also modified all other occurrences in Forgejo specific files
2024-03-06 12:10:43 +08:00

315 lines
8.1 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.ParamsInt64(":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.ParamsInt64(":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.ParamsInt64(":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.ParamsInt64(":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, 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))
for i, currentIssue := range issues {
pr, err := currentIssue.GetPullRequest(ctx)
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetPullRequest", err)
return
}
if err = pr.LoadIssue(ctx); err != nil {
ctx.Error(http.StatusInternalServerError, "LoadIssue", err)
return
}
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)
}