mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-23 11:34:01 +09:00
Backport #39885 by @basavaraj-sm05 Several `/repos/{owner}/{repo}/issues/{index}/...` API endpoints load the issue by index without checking `CanReadIssuesOrPulls(issue.IsPull)`, unlike `GetIssue`, `ListIssueComments` and `GetIssueReactions`. The route group's `mustEnableIssuesOrPulls` passes when the caller can read either unit, so someone who can read issues but not pull requests (a team with only the Issues unit, or per-unit anonymous access on a public repo) can read a pull request's whole conversation through `/timeline`, plus its labels, subscribers, attachments and tracked times, and can subscribe to it. The reverse holds for issues. These handlers now return 404 in that case, like their siblings. Co-authored-by: Basavaraj S m <basavaraj@digiscrypt.com> Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
co-authored by
Basavaraj S m
silverwind
wxiaoguang
parent
3996c2c520
commit
3e5256b6ca
@@ -513,17 +513,12 @@ func GetIssue(ctx *context.APIContext) {
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
issue, err := issues_model.GetIssueWithAttrsByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
if issues_model.IsErrIssueNotExist(err) {
|
||||
ctx.APIErrorNotFound()
|
||||
} else {
|
||||
ctx.APIErrorInternal(err)
|
||||
}
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
if !ctx.Repo.Permission.CanReadIssuesOrPulls(issue.IsPull) {
|
||||
ctx.APIErrorNotFound()
|
||||
if err := issue.LoadAttributes(ctx); err != nil {
|
||||
ctx.APIErrorInternal(err)
|
||||
return
|
||||
}
|
||||
ctx.JSON(http.StatusOK, convert.ToAPIIssue(ctx, ctx.Doer, issue))
|
||||
@@ -698,19 +693,13 @@ func EditIssue(ctx *context.APIContext) {
|
||||
// "$ref": "#/responses/repoArchivedError"
|
||||
|
||||
form := web.GetForm[*api.EditIssueOption](ctx)
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
if issues_model.IsErrIssueNotExist(err) {
|
||||
ctx.APIErrorNotFound()
|
||||
} else {
|
||||
ctx.APIErrorInternal(err)
|
||||
}
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
issue.Repo = ctx.Repo.Repository
|
||||
canWrite := ctx.Repo.Permission.CanWriteIssuesOrPulls(issue.IsPull)
|
||||
|
||||
err = issue.LoadAttributes(ctx)
|
||||
err := issue.LoadAttributes(ctx)
|
||||
if err != nil {
|
||||
ctx.APIErrorInternal(err)
|
||||
return
|
||||
@@ -901,13 +890,12 @@ func DeleteIssue(ctx *context.APIContext) {
|
||||
// "$ref": "#/responses/notFound"
|
||||
// "423":
|
||||
// "$ref": "#/responses/repoArchivedError"
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
ctx.APIErrorAuto(err)
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = issue_service.DeleteIssue(ctx, ctx.Doer, issue); err != nil {
|
||||
if err := issue_service.DeleteIssue(ctx, ctx.Doer, issue); err != nil {
|
||||
ctx.APIErrorInternal(err)
|
||||
return
|
||||
}
|
||||
@@ -953,13 +941,8 @@ func UpdateIssueDeadline(ctx *context.APIContext) {
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
form := web.GetForm[*api.EditDeadlineOption](ctx)
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
if issues_model.IsErrIssueNotExist(err) {
|
||||
ctx.APIErrorNotFound()
|
||||
} else {
|
||||
ctx.APIErrorInternal(err)
|
||||
}
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -999,3 +982,17 @@ func closeOrReopenIssue(ctx *context.APIContext, issue *issues_model.Issue, stat
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getRepoIssueByIndexForDoer(ctx *context.APIContext, index int64) *issues_model.Issue {
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, index)
|
||||
if err != nil {
|
||||
ctx.APIErrorAuto(err)
|
||||
return nil
|
||||
}
|
||||
if !ctx.Repo.Permission.CanReadIssuesOrPulls(issue.IsPull) {
|
||||
ctx.APIErrorNotFound()
|
||||
return nil
|
||||
}
|
||||
issue.Repo = ctx.Repo.Repository
|
||||
return issue
|
||||
}
|
||||
|
||||
@@ -146,14 +146,8 @@ func CheckIssueAssignee(ctx *context.APIContext) {
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
ctx.APIErrorAuto(err)
|
||||
return
|
||||
}
|
||||
|
||||
if !ctx.Repo.Permission.CanReadIssuesOrPulls(issue.IsPull) {
|
||||
ctx.APIErrorNotFound()
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -187,9 +181,8 @@ func checkAssignableUser(ctx *context.APIContext, assigneeName string, repo *rep
|
||||
}
|
||||
|
||||
func updateIssueAssignees(ctx *context.APIContext, opts api.IssueAssigneesOption, isAdd bool) {
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
ctx.APIErrorAuto(err)
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ func GetIssueAttachment(ctx *context.APIContext) {
|
||||
// "404":
|
||||
// "$ref": "#/responses/error"
|
||||
|
||||
issue := getIssueFromContext(ctx)
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
@@ -100,7 +100,7 @@ func ListIssueAttachments(ctx *context.APIContext) {
|
||||
// "404":
|
||||
// "$ref": "#/responses/error"
|
||||
|
||||
issue := getIssueFromContext(ctx)
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
@@ -163,7 +163,7 @@ func CreateIssueAttachment(ctx *context.APIContext) {
|
||||
// "423":
|
||||
// "$ref": "#/responses/repoArchivedError"
|
||||
|
||||
issue := getIssueFromContext(ctx)
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
@@ -333,20 +333,8 @@ func DeleteIssueAttachment(ctx *context.APIContext) {
|
||||
ctx.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func getIssueFromContext(ctx *context.APIContext) *issues_model.Issue {
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
ctx.APIErrorAuto(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
issue.Repo = ctx.Repo.Repository
|
||||
|
||||
return issue
|
||||
}
|
||||
|
||||
func getIssueAttachmentSafeWrite(ctx *context.APIContext) *repo_model.Attachment {
|
||||
issue := getIssueFromContext(ctx)
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -69,17 +69,10 @@ func ListIssueComments(ctx *context.APIContext) {
|
||||
ctx.APIError(http.StatusUnprocessableEntity, err.Error())
|
||||
return
|
||||
}
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
ctx.APIErrorInternal(err)
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
if !ctx.Repo.Permission.CanReadIssuesOrPulls(issue.IsPull) {
|
||||
ctx.APIErrorNotFound()
|
||||
return
|
||||
}
|
||||
|
||||
issue.Repo = ctx.Repo.Repository
|
||||
|
||||
opts := &issues_model.FindCommentsOptions{
|
||||
IssueID: issue.ID,
|
||||
@@ -173,12 +166,10 @@ func ListIssueCommentsAndTimeline(ctx *context.APIContext) {
|
||||
ctx.APIError(http.StatusUnprocessableEntity, err.Error())
|
||||
return
|
||||
}
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
ctx.APIErrorInternal(err)
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
issue.Repo = ctx.Repo.Repository
|
||||
|
||||
opts := &issues_model.FindCommentsOptions{
|
||||
ListOptions: utils.GetListOptions(ctx),
|
||||
@@ -381,14 +372,8 @@ func CreateIssueComment(ctx *context.APIContext) {
|
||||
// "$ref": "#/responses/repoArchivedError"
|
||||
|
||||
form := web.GetForm[*api.CreateIssueCommentOption](ctx)
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
ctx.APIErrorInternal(err)
|
||||
return
|
||||
}
|
||||
|
||||
if !ctx.Repo.Permission.CanReadIssuesOrPulls(issue.IsPull) {
|
||||
ctx.APIErrorNotFound()
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
perm_model "gitea.dev/models/perm"
|
||||
access_model "gitea.dev/models/perm/access"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/models/unit"
|
||||
"gitea.dev/models/unittest"
|
||||
"gitea.dev/services/context"
|
||||
"gitea.dev/services/contexttest"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestIssueReadEndpointsRequireUnitPermission(t *testing.T) {
|
||||
unittest.PrepareTestEnv(t)
|
||||
|
||||
for name, handler := range map[string]func(*context.APIContext){
|
||||
"timeline": ListIssueCommentsAndTimeline,
|
||||
"labels": ListIssueLabels,
|
||||
"subscribers": GetIssueSubscribers,
|
||||
"attachments": ListIssueAttachments,
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
request := func(index string) int {
|
||||
ctx, resp := contexttest.MockAPIContext(t, "user2/repo1")
|
||||
contexttest.LoadRepo(t, ctx, 1)
|
||||
ctx.Repo.Permission = access_model.Permission{}
|
||||
ctx.Repo.Permission.SetUnitsWithDefaultAccessMode([]*repo_model.RepoUnit{{Type: unit.TypeIssues}}, perm_model.AccessModeRead)
|
||||
ctx.SetPathParam("index", index)
|
||||
handler(ctx)
|
||||
return resp.Code
|
||||
}
|
||||
assert.Equal(t, http.StatusOK, request("1"))
|
||||
assert.Equal(t, http.StatusNotFound, request("2"))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -61,15 +61,8 @@ func GetIssueDependencies(ctx *context.APIContext) {
|
||||
return
|
||||
}
|
||||
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
ctx.APIErrorAuto(err)
|
||||
return
|
||||
}
|
||||
|
||||
// 1. We must be able to read this issue
|
||||
if !ctx.Repo.Permission.CanReadIssuesOrPulls(issue.IsPull) {
|
||||
ctx.APIErrorNotFound()
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -79,7 +72,7 @@ func GetIssueDependencies(ctx *context.APIContext) {
|
||||
|
||||
blockerIssues := make([]*issues_model.Issue, 0, min(listOptions.PageSize, setting.API.MaxResponseItems))
|
||||
|
||||
// 2. Get the issues this issue depends on, i.e. the `<#b>`: `<issue> <- <#b>`
|
||||
// Get the issues this issue depends on, i.e. the `<#b>`: `<issue> <- <#b>`
|
||||
blockersInfo, total, err := issue.BlockedByDependencies(ctx, listOptions)
|
||||
if err != nil {
|
||||
ctx.APIErrorInternal(err)
|
||||
@@ -177,7 +170,7 @@ func CreateIssueDependency(ctx *context.APIContext) {
|
||||
// "$ref": "#/responses/repoArchivedError"
|
||||
|
||||
// We want to make <:index> depend on <Form>, i.e. <:index> is the target
|
||||
target := getParamsIssue(ctx)
|
||||
target := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
@@ -238,7 +231,7 @@ func RemoveIssueDependency(ctx *context.APIContext) {
|
||||
// "$ref": "#/responses/repoArchivedError"
|
||||
|
||||
// We want to make <:index> depend on <Form>, i.e. <:index> is the target
|
||||
target := getParamsIssue(ctx)
|
||||
target := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
@@ -303,16 +296,11 @@ func GetIssueBlocks(ctx *context.APIContext) {
|
||||
// We need to list the issues that DEPEND on this issue not the other way round
|
||||
// Therefore whether dependencies are enabled or not in this repository is potentially irrelevant.
|
||||
|
||||
issue := getParamsIssue(ctx)
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
if !ctx.Repo.Permission.CanReadIssuesOrPulls(issue.IsPull) {
|
||||
ctx.APIErrorNotFound()
|
||||
return
|
||||
}
|
||||
|
||||
page := max(ctx.FormInt("page"), 1)
|
||||
limit := ctx.FormInt("limit")
|
||||
if limit <= 1 {
|
||||
@@ -399,7 +387,7 @@ func CreateIssueBlocking(ctx *context.APIContext) {
|
||||
// "404":
|
||||
// description: the issue does not exist
|
||||
|
||||
dependency := getParamsIssue(ctx)
|
||||
dependency := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
@@ -456,7 +444,7 @@ func RemoveIssueBlocking(ctx *context.APIContext) {
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
dependency := getParamsIssue(ctx)
|
||||
dependency := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
@@ -480,16 +468,6 @@ func RemoveIssueBlocking(ctx *context.APIContext) {
|
||||
ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, ctx.Doer, dependency))
|
||||
}
|
||||
|
||||
func getParamsIssue(ctx *context.APIContext) *issues_model.Issue {
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
ctx.APIErrorAuto(err)
|
||||
return nil
|
||||
}
|
||||
issue.Repo = ctx.Repo.Repository
|
||||
return issue
|
||||
}
|
||||
|
||||
func getFormIssue(ctx *context.APIContext, form *api.IssueMeta) *issues_model.Issue {
|
||||
var repo *repo_model.Repository
|
||||
if form.Owner != ctx.Repo.Repository.OwnerName || form.Name != ctx.Repo.Repository.Name {
|
||||
|
||||
@@ -47,13 +47,8 @@ func ListIssueLabels(ctx *context.APIContext) {
|
||||
// "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.APIErrorNotFound()
|
||||
} else {
|
||||
ctx.APIErrorInternal(err)
|
||||
}
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -167,13 +162,8 @@ func DeleteIssueLabel(ctx *context.APIContext) {
|
||||
// "423":
|
||||
// "$ref": "#/responses/repoArchivedError"
|
||||
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
if issues_model.IsErrIssueNotExist(err) {
|
||||
ctx.APIErrorNotFound()
|
||||
} else {
|
||||
ctx.APIErrorInternal(err)
|
||||
}
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -292,13 +282,8 @@ func ClearIssueLabels(ctx *context.APIContext) {
|
||||
// "423":
|
||||
// "$ref": "#/responses/repoArchivedError"
|
||||
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
if issues_model.IsErrIssueNotExist(err) {
|
||||
ctx.APIErrorNotFound()
|
||||
} else {
|
||||
ctx.APIErrorInternal(err)
|
||||
}
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -316,14 +301,9 @@ func ClearIssueLabels(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
func prepareForReplaceOrAdd(ctx *context.APIContext, form api.IssueLabelsOption) (*issues_model.Issue, []*issues_model.Label, error) {
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
if issues_model.IsErrIssueNotExist(err) {
|
||||
ctx.APIErrorNotFound()
|
||||
} else {
|
||||
ctx.APIErrorInternal(err)
|
||||
}
|
||||
return nil, nil, err
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return nil, nil, errors.New("issue not found")
|
||||
}
|
||||
|
||||
if !ctx.Repo.Permission.CanWriteIssuesOrPulls(issue.IsPull) {
|
||||
|
||||
@@ -51,9 +51,8 @@ func LockIssue(ctx *context.APIContext) {
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
reason := web.GetForm[*api.LockIssueOption](ctx).Reason
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
ctx.APIErrorAuto(err)
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -70,7 +69,7 @@ func LockIssue(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
issue.Repo = ctx.Repo.Repository
|
||||
err = issues_model.LockIssue(ctx, opt)
|
||||
err := issues_model.LockIssue(ctx, opt)
|
||||
if err != nil {
|
||||
ctx.APIErrorInternal(err)
|
||||
return
|
||||
@@ -114,9 +113,8 @@ func UnlockIssue(ctx *context.APIContext) {
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
ctx.APIErrorAuto(err)
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -132,7 +130,7 @@ func UnlockIssue(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
issue.Repo = ctx.Repo.Repository
|
||||
err = issues_model.UnlockIssue(ctx, opt)
|
||||
err := issues_model.UnlockIssue(ctx, opt)
|
||||
if err != nil {
|
||||
ctx.APIErrorInternal(err)
|
||||
return
|
||||
|
||||
@@ -41,20 +41,13 @@ func PinIssue(ctx *context.APIContext) {
|
||||
// "$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.APIErrorNotFound()
|
||||
} else if issues_model.IsErrIssueMaxPinReached(err) {
|
||||
ctx.APIError(http.StatusBadRequest, err.Error())
|
||||
} else {
|
||||
ctx.APIErrorInternal(err)
|
||||
}
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
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)
|
||||
err := issue.LoadRepo(ctx)
|
||||
if err != nil {
|
||||
ctx.APIErrorInternal(err)
|
||||
return
|
||||
@@ -98,18 +91,13 @@ func UnpinIssue(ctx *context.APIContext) {
|
||||
// "$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.APIErrorNotFound()
|
||||
} else {
|
||||
ctx.APIErrorInternal(err)
|
||||
}
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
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)
|
||||
err := issue.LoadRepo(ctx)
|
||||
if err != nil {
|
||||
ctx.APIErrorInternal(err)
|
||||
return
|
||||
@@ -159,17 +147,12 @@ func MoveIssuePin(ctx *context.APIContext) {
|
||||
// "$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.APIErrorNotFound()
|
||||
} else {
|
||||
ctx.APIErrorInternal(err)
|
||||
}
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = issues_model.MovePin(ctx, issue, ctx.PathParamInt("position"))
|
||||
err := issues_model.MovePin(ctx, issue, ctx.PathParamInt("position"))
|
||||
if err != nil {
|
||||
ctx.APIErrorInternal(err)
|
||||
return
|
||||
|
||||
@@ -172,13 +172,8 @@ func DeleteIssueStopwatch(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
func prepareIssueForStopwatch(ctx *context.APIContext) *issues_model.Issue {
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
if issues_model.IsErrIssueNotExist(err) {
|
||||
ctx.APIErrorNotFound()
|
||||
} else {
|
||||
ctx.APIErrorInternal(err)
|
||||
}
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -104,14 +104,8 @@ func DelIssueSubscription(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
func setIssueSubscription(ctx *context.APIContext, watch bool) {
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
if issues_model.IsErrIssueNotExist(err) {
|
||||
ctx.APIErrorNotFound()
|
||||
} else {
|
||||
ctx.APIErrorInternal(err)
|
||||
}
|
||||
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -185,14 +179,8 @@ func CheckIssueSubscription(ctx *context.APIContext) {
|
||||
// "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.APIErrorNotFound()
|
||||
} else {
|
||||
ctx.APIErrorInternal(err)
|
||||
}
|
||||
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -251,14 +239,8 @@ func GetIssueSubscribers(ctx *context.APIContext) {
|
||||
// "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.APIErrorNotFound()
|
||||
} else {
|
||||
ctx.APIErrorInternal(err)
|
||||
}
|
||||
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -75,9 +75,8 @@ func ListTrackedTimes(ctx *context.APIContext) {
|
||||
ctx.APIErrorNotFound("timetracker is disabled")
|
||||
return
|
||||
}
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
ctx.APIErrorAuto(err)
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -100,6 +99,7 @@ func ListTrackedTimes(ctx *context.APIContext) {
|
||||
opts.UserID = user.ID
|
||||
}
|
||||
|
||||
var err error
|
||||
if opts.CreatedBeforeUnix, opts.CreatedAfterUnix, err = context.GetQueryBeforeSince(ctx.Base); err != nil {
|
||||
ctx.APIError(http.StatusUnprocessableEntity, err.Error())
|
||||
return
|
||||
@@ -200,9 +200,8 @@ func AddTime(ctx *context.APIContext) {
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
form := web.GetForm[*api.AddTimeOption](ctx)
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
ctx.APIErrorAuto(err)
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -219,6 +218,7 @@ func AddTime(ctx *context.APIContext) {
|
||||
if form.User != "" {
|
||||
if (ctx.IsUserRepoAdmin() && ctx.Doer.Name != form.User) || ctx.Doer.IsAdmin {
|
||||
// allow only RepoAdmin, Admin and User to add time
|
||||
var err error
|
||||
user, err = user_model.GetUserByName(ctx, form.User)
|
||||
if err != nil {
|
||||
ctx.APIErrorAuto(err)
|
||||
@@ -280,9 +280,8 @@ func ResetIssueTime(ctx *context.APIContext) {
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
ctx.APIErrorAuto(err)
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -295,7 +294,7 @@ func ResetIssueTime(ctx *context.APIContext) {
|
||||
return
|
||||
}
|
||||
|
||||
err = issues_model.DeleteIssueUserTimes(ctx, issue, ctx.Doer)
|
||||
err := issues_model.DeleteIssueUserTimes(ctx, issue, ctx.Doer)
|
||||
if err != nil {
|
||||
if db.IsErrNotExist(err) {
|
||||
ctx.APIError(http.StatusNotFound, err.Error())
|
||||
@@ -349,9 +348,8 @@ func DeleteTime(ctx *context.APIContext) {
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
ctx.APIErrorAuto(err)
|
||||
issue := getRepoIssueByIndexForDoer(ctx, ctx.PathParamInt64("index"))
|
||||
if issue == nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user