aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--models/asymkey/gpg_key.go11
-rw-r--r--models/fixtures/comment.yml9
-rw-r--r--models/fixtures/issue.yml2
-rw-r--r--models/issues/comment.go6
-rw-r--r--models/issues/content_history.go4
-rw-r--r--models/issues/content_history_test.go4
-rw-r--r--models/project/project.go12
-rw-r--r--models/repo/release.go15
-rw-r--r--models/webhook/webhook.go67
-rw-r--r--routers/api/v1/api.go4
-rw-r--r--routers/api/v1/repo/issue.go22
-rw-r--r--routers/api/v1/repo/issue_comment.go56
-rw-r--r--routers/api/v1/repo/issue_comment_attachment.go4
-rw-r--r--routers/api/v1/repo/issue_reaction.go20
-rw-r--r--routers/api/v1/repo/key.go6
-rw-r--r--routers/api/v1/repo/release.go23
-rw-r--r--routers/api/v1/repo/release_attachment.go39
-rw-r--r--routers/api/v1/repo/release_tags.go2
-rw-r--r--routers/api/v1/repo/tag.go2
-rw-r--r--routers/api/v1/user/app.go4
-rw-r--r--routers/api/v1/user/gpg_key.go2
-rw-r--r--routers/api/v1/user/hook.go5
-rw-r--r--routers/web/repo/issue.go30
-rw-r--r--routers/web/repo/issue_content_history.go2
-rw-r--r--routers/web/repo/projects.go2
-rw-r--r--routers/web/repo/release.go37
-rw-r--r--services/release/release.go18
-rw-r--r--services/webhook/deliver.go2
-rw-r--r--tests/integration/api_comment_attachment_test.go8
-rw-r--r--tests/integration/api_comment_test.go27
-rw-r--r--tests/integration/api_issue_reaction_test.go21
-rw-r--r--tests/integration/api_keys_test.go11
-rw-r--r--tests/integration/api_nodeinfo_test.go2
-rw-r--r--tests/integration/issue_test.go50
-rw-r--r--tests/integration/mirror_pull_test.go2
35 files changed, 422 insertions, 109 deletions
diff --git a/models/asymkey/gpg_key.go b/models/asymkey/gpg_key.go
index be019184eb..9437210213 100644
--- a/models/asymkey/gpg_key.go
+++ b/models/asymkey/gpg_key.go
@@ -93,9 +93,9 @@ func CountUserGPGKeys(userID int64) (int64, error) {
}
// GetGPGKeyByID returns public key by given ID.
-func GetGPGKeyByID(keyID int64) (*GPGKey, error) {
+func GetGPGKeyForUserByID(ownerID, keyID int64) (*GPGKey, error) {
key := new(GPGKey)
- has, err := db.GetEngine(db.DefaultContext).ID(keyID).Get(key)
+ has, err := db.GetEngine(db.DefaultContext).Where("id=? AND owner_id=?", keyID, ownerID).Get(key)
if err != nil {
return nil, err
} else if !has {
@@ -225,7 +225,7 @@ func deleteGPGKey(ctx context.Context, keyID string) (int64, error) {
// DeleteGPGKey deletes GPG key information in database.
func DeleteGPGKey(doer *user_model.User, id int64) (err error) {
- key, err := GetGPGKeyByID(id)
+ key, err := GetGPGKeyForUserByID(doer.ID, id)
if err != nil {
if IsErrGPGKeyNotExist(err) {
return nil
@@ -233,11 +233,6 @@ func DeleteGPGKey(doer *user_model.User, id int64) (err error) {
return fmt.Errorf("GetPublicKeyByID: %w", err)
}
- // Check if user has access to delete this key.
- if !doer.IsAdmin && doer.ID != key.OwnerID {
- return ErrGPGKeyAccessDenied{doer.ID, key.ID}
- }
-
ctx, committer, err := db.TxContext(db.DefaultContext)
if err != nil {
return err
diff --git a/models/fixtures/comment.yml b/models/fixtures/comment.yml
index bd64680c8c..17586caa21 100644
--- a/models/fixtures/comment.yml
+++ b/models/fixtures/comment.yml
@@ -66,3 +66,12 @@
tree_path: "README.md"
created_unix: 946684812
invalidated: true
+
+-
+ id: 8
+ type: 0 # comment
+ poster_id: 2
+ issue_id: 4 # in repo_id 2
+ content: "comment in private pository"
+ created_unix: 946684811
+ updated_unix: 946684811
diff --git a/models/fixtures/issue.yml b/models/fixtures/issue.yml
index 174345ff5a..18c5b8c7ee 100644
--- a/models/fixtures/issue.yml
+++ b/models/fixtures/issue.yml
@@ -61,7 +61,7 @@
priority: 0
is_closed: true
is_pull: false
- num_comments: 0
+ num_comments: 1
created_unix: 946684830
updated_unix: 978307200
is_locked: false
diff --git a/models/issues/comment.go b/models/issues/comment.go
index 303c23916b..521becd2a0 100644
--- a/models/issues/comment.go
+++ b/models/issues/comment.go
@@ -1014,6 +1014,7 @@ type FindCommentsOptions struct {
Type CommentType
IssueIDs []int64
Invalidated util.OptionalBool
+ IsPull util.OptionalBool
}
// ToConds implements FindOptions interface
@@ -1048,6 +1049,9 @@ func (opts *FindCommentsOptions) ToConds() builder.Cond {
if !opts.Invalidated.IsNone() {
cond = cond.And(builder.Eq{"comment.invalidated": opts.Invalidated.IsTrue()})
}
+ if opts.IsPull != util.OptionalBoolNone {
+ cond = cond.And(builder.Eq{"issue.is_pull": opts.IsPull.IsTrue()})
+ }
return cond
}
@@ -1055,7 +1059,7 @@ func (opts *FindCommentsOptions) ToConds() builder.Cond {
func FindComments(ctx context.Context, opts *FindCommentsOptions) (CommentList, error) {
comments := make([]*Comment, 0, 10)
sess := db.GetEngine(ctx).Where(opts.ToConds())
- if opts.RepoID > 0 {
+ if opts.RepoID > 0 || opts.IsPull != util.OptionalBoolNone {
sess.Join("INNER", "issue", "issue.id = comment.issue_id")
}
diff --git a/models/issues/content_history.go b/models/issues/content_history.go
index cc06b184d7..8c333bc6dd 100644
--- a/models/issues/content_history.go
+++ b/models/issues/content_history.go
@@ -218,9 +218,9 @@ func GetIssueContentHistoryByID(dbCtx context.Context, id int64) (*ContentHistor
}
// GetIssueContentHistoryAndPrev get a history and the previous non-deleted history (to compare)
-func GetIssueContentHistoryAndPrev(dbCtx context.Context, id int64) (history, prevHistory *ContentHistory, err error) {
+func GetIssueContentHistoryAndPrev(dbCtx context.Context, issueID, id int64) (history, prevHistory *ContentHistory, err error) {
history = &ContentHistory{}
- has, err := db.GetEngine(dbCtx).ID(id).Get(history)
+ has, err := db.GetEngine(dbCtx).Where("id=? AND issue_id=?", id, issueID).Get(history)
if err != nil {
log.Error("failed to get issue content history %v. err=%v", id, err)
return nil, nil, err
diff --git a/models/issues/content_history_test.go b/models/issues/content_history_test.go
index 7d52f1bcc6..9cb7f7d8e5 100644
--- a/models/issues/content_history_test.go
+++ b/models/issues/content_history_test.go
@@ -58,13 +58,13 @@ func TestContentHistory(t *testing.T) {
hasHistory2, _ := issues_model.HasIssueContentHistory(dbCtx, 10, 1)
assert.False(t, hasHistory2)
- h6, h6Prev, _ := issues_model.GetIssueContentHistoryAndPrev(dbCtx, 6)
+ h6, h6Prev, _ := issues_model.GetIssueContentHistoryAndPrev(dbCtx, 10, 6)
assert.EqualValues(t, 6, h6.ID)
assert.EqualValues(t, 5, h6Prev.ID)
// soft-delete
_ = issues_model.SoftDeleteIssueContentHistory(dbCtx, 5)
- h6, h6Prev, _ = issues_model.GetIssueContentHistoryAndPrev(dbCtx, 6)
+ h6, h6Prev, _ = issues_model.GetIssueContentHistoryAndPrev(dbCtx, 10, 6)
assert.EqualValues(t, 6, h6.ID)
assert.EqualValues(t, 4, h6Prev.ID)
diff --git a/models/project/project.go b/models/project/project.go
index 17348a9443..0b4ea54584 100644
--- a/models/project/project.go
+++ b/models/project/project.go
@@ -306,6 +306,18 @@ func GetProjectByID(ctx context.Context, id int64) (*Project, error) {
return p, nil
}
+// GetProjectForRepoByID returns the projects in a repository
+func GetProjectForRepoByID(ctx context.Context, repoID, id int64) (*Project, error) {
+ p := new(Project)
+ has, err := db.GetEngine(ctx).Where("id=? AND repo_id=?", id, repoID).Get(p)
+ if err != nil {
+ return nil, err
+ } else if !has {
+ return nil, ErrProjectNotExist{ID: id}
+ }
+ return p, nil
+}
+
// UpdateProject updates project properties
func UpdateProject(ctx context.Context, p *Project) error {
if !IsCardTypeValid(p.CardType) {
diff --git a/models/repo/release.go b/models/repo/release.go
index cc55fd1da7..62e2a560a2 100644
--- a/models/repo/release.go
+++ b/models/repo/release.go
@@ -201,6 +201,21 @@ func GetReleaseByID(ctx context.Context, id int64) (*Release, error) {
return rel, nil
}
+// GetReleaseForRepoByID returns release with given ID.
+func GetReleaseForRepoByID(ctx context.Context, repoID, id int64) (*Release, error) {
+ rel := new(Release)
+ has, err := db.GetEngine(ctx).
+ Where("id=? AND repo_id=?", id, repoID).
+ Get(rel)
+ if err != nil {
+ return nil, err
+ } else if !has {
+ return nil, ErrReleaseNotExist{id, ""}
+ }
+
+ return rel, nil
+}
+
// FindReleasesOptions describes the conditions to Find releases
type FindReleasesOptions struct {
db.ListOptions
diff --git a/models/webhook/webhook.go b/models/webhook/webhook.go
index fc2bbed083..c42268cc49 100644
--- a/models/webhook/webhook.go
+++ b/models/webhook/webhook.go
@@ -392,39 +392,40 @@ func CreateWebhooks(ctx context.Context, ws []*Webhook) error {
return db.Insert(ctx, ws)
}
-// getWebhook uses argument bean as query condition,
-// ID must be specified and do not assign unnecessary fields.
-func getWebhook(bean *Webhook) (*Webhook, error) {
- has, err := db.GetEngine(db.DefaultContext).Get(bean)
+// GetWebhookByID returns webhook of repository by given ID.
+func GetWebhookByID(ctx context.Context, id int64) (*Webhook, error) {
+ bean := new(Webhook)
+ has, err := db.GetEngine(ctx).ID(id).Get(bean)
if err != nil {
return nil, err
} else if !has {
- return nil, ErrWebhookNotExist{ID: bean.ID}
+ return nil, ErrWebhookNotExist{ID: id}
}
return bean, nil
}
-// GetWebhookByID returns webhook of repository by given ID.
-func GetWebhookByID(id int64) (*Webhook, error) {
- return getWebhook(&Webhook{
- ID: id,
- })
-}
-
// GetWebhookByRepoID returns webhook of repository by given ID.
func GetWebhookByRepoID(repoID, id int64) (*Webhook, error) {
- return getWebhook(&Webhook{
- ID: id,
- RepoID: repoID,
- })
+ webhook := new(Webhook)
+ has, err := db.GetEngine(db.DefaultContext).Where("id=? AND repo_id=?", id, repoID).Get(webhook)
+ if err != nil {
+ return nil, err
+ } else if !has {
+ return nil, ErrWebhookNotExist{ID: id}
+ }
+ return webhook, nil
}
// GetWebhookByOwnerID returns webhook of a user or organization by given ID.
func GetWebhookByOwnerID(ownerID, id int64) (*Webhook, error) {
- return getWebhook(&Webhook{
- ID: id,
- OwnerID: ownerID,
- })
+ webhook := new(Webhook)
+ has, err := db.GetEngine(db.DefaultContext).Where("id=? AND owner_id=?", id, ownerID).Get(webhook)
+ if err != nil {
+ return nil, err
+ } else if !has {
+ return nil, ErrWebhookNotExist{ID: id}
+ }
+ return webhook, nil
}
// ListWebhookOptions are options to filter webhooks on ListWebhooksByOpts
@@ -482,20 +483,20 @@ func UpdateWebhookLastStatus(w *Webhook) error {
return err
}
-// deleteWebhook uses argument bean as query condition,
+// DeleteWebhookByID uses argument bean as query condition,
// ID must be specified and do not assign unnecessary fields.
-func deleteWebhook(bean *Webhook) (err error) {
+func DeleteWebhookByID(id int64) (err error) {
ctx, committer, err := db.TxContext(db.DefaultContext)
if err != nil {
return err
}
defer committer.Close()
- if count, err := db.DeleteByBean(ctx, bean); err != nil {
+ if count, err := db.DeleteByID(ctx, id, new(Webhook)); err != nil {
return err
} else if count == 0 {
- return ErrWebhookNotExist{ID: bean.ID}
- } else if _, err = db.DeleteByBean(ctx, &HookTask{HookID: bean.ID}); err != nil {
+ return ErrWebhookNotExist{ID: id}
+ } else if _, err = db.DeleteByBean(ctx, &HookTask{HookID: id}); err != nil {
return err
}
@@ -504,16 +505,16 @@ func deleteWebhook(bean *Webhook) (err error) {
// DeleteWebhookByRepoID deletes webhook of repository by given ID.
func DeleteWebhookByRepoID(repoID, id int64) error {
- return deleteWebhook(&Webhook{
- ID: id,
- RepoID: repoID,
- })
+ if _, err := GetWebhookByRepoID(repoID, id); err != nil {
+ return err
+ }
+ return DeleteWebhookByID(id)
}
// DeleteWebhookByOwnerID deletes webhook of a user or organization by given ID.
func DeleteWebhookByOwnerID(ownerID, id int64) error {
- return deleteWebhook(&Webhook{
- ID: id,
- OwnerID: ownerID,
- })
+ if _, err := GetWebhookByOwnerID(ownerID, id); err != nil {
+ return err
+ }
+ return DeleteWebhookByID(id)
}
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index 6d55e8c223..6cb1790f3e 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -1148,8 +1148,8 @@ func Routes(ctx gocontext.Context) *web.Route {
m.Group("/{username}/{reponame}", func() {
m.Group("/issues", func() {
m.Combo("").Get(repo.ListIssues).
- Post(reqToken(), mustNotBeArchived, bind(api.CreateIssueOption{}), repo.CreateIssue)
- m.Get("/pinned", repo.ListPinnedIssues)
+ Post(reqToken(), mustNotBeArchived, bind(api.CreateIssueOption{}), reqRepoReader(unit.TypeIssues), repo.CreateIssue)
+ m.Get("/pinned", reqRepoReader(unit.TypeIssues), repo.ListPinnedIssues)
m.Group("/comments", func() {
m.Get("", repo.ListRepoIssueComments)
m.Group("/{id}", func() {
diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go
index 49252f7a4b..cda792c00c 100644
--- a/routers/api/v1/repo/issue.go
+++ b/routers/api/v1/repo/issue.go
@@ -451,6 +451,24 @@ func ListIssues(ctx *context.APIContext) {
isPull = util.OptionalBoolNone
}
+ if isPull != util.OptionalBoolNone && !ctx.Repo.CanReadIssuesOrPulls(isPull.IsTrue()) {
+ ctx.NotFound()
+ return
+ }
+
+ if isPull == util.OptionalBoolNone {
+ canReadIssues := ctx.Repo.CanRead(unit.TypeIssues)
+ canReadPulls := ctx.Repo.CanRead(unit.TypePullRequests)
+ if !canReadIssues && !canReadPulls {
+ ctx.NotFound()
+ return
+ } else if !canReadIssues {
+ isPull = util.OptionalBoolTrue
+ } else if !canReadPulls {
+ isPull = util.OptionalBoolFalse
+ }
+ }
+
// FIXME: we should be more efficient here
createdByID := getUserIDForFilter(ctx, "created_by")
if ctx.Written() {
@@ -561,6 +579,10 @@ func GetIssue(ctx *context.APIContext) {
}
return
}
+ if !ctx.Repo.CanReadIssuesOrPulls(issue.IsPull) {
+ ctx.NotFound()
+ return
+ }
ctx.JSON(http.StatusOK, convert.ToAPIIssue(ctx, issue))
}
diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go
index c2392126db..a898d1ecf0 100644
--- a/routers/api/v1/repo/issue_comment.go
+++ b/routers/api/v1/repo/issue_comment.go
@@ -12,9 +12,11 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
"code.gitea.io/gitea/services/convert"
@@ -69,6 +71,11 @@ func ListIssueComments(ctx *context.APIContext) {
ctx.Error(http.StatusInternalServerError, "GetRawIssueByIndex", err)
return
}
+ if !ctx.Repo.CanReadIssuesOrPulls(issue.IsPull) {
+ ctx.NotFound()
+ return
+ }
+
issue.Repo = ctx.Repo.Repository
opts := &issues_model.FindCommentsOptions{
@@ -265,12 +272,27 @@ func ListRepoIssueComments(ctx *context.APIContext) {
return
}
+ var isPull util.OptionalBool
+ canReadIssue := ctx.Repo.CanRead(unit.TypeIssues)
+ canReadPull := ctx.Repo.CanRead(unit.TypePullRequests)
+ if canReadIssue && canReadPull {
+ isPull = util.OptionalBoolNone
+ } else if canReadIssue {
+ isPull = util.OptionalBoolFalse
+ } else if canReadPull {
+ isPull = util.OptionalBoolTrue
+ } else {
+ ctx.NotFound()
+ return
+ }
+
opts := &issues_model.FindCommentsOptions{
ListOptions: utils.GetListOptions(ctx),
RepoID: ctx.Repo.Repository.ID,
Type: issues_model.CommentTypeComment,
Since: since,
Before: before,
+ IsPull: isPull,
}
comments, err := issues_model.FindComments(ctx, opts)
@@ -357,6 +379,11 @@ func CreateIssueComment(ctx *context.APIContext) {
return
}
+ if !ctx.Repo.CanReadIssuesOrPulls(issue.IsPull) {
+ ctx.NotFound()
+ return
+ }
+
if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) && !ctx.Doer.IsAdmin {
ctx.Error(http.StatusForbidden, "CreateIssueComment", errors.New(ctx.Tr("repo.issues.comment_on_locked")))
return
@@ -426,6 +453,11 @@ func GetIssueComment(ctx *context.APIContext) {
return
}
+ if !ctx.Repo.CanReadIssuesOrPulls(comment.Issue.IsPull) {
+ ctx.NotFound()
+ return
+ }
+
if comment.Type != issues_model.CommentTypeComment {
ctx.Status(http.StatusNoContent)
return
@@ -544,7 +576,17 @@ func editIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption)
return
}
- if !ctx.IsSigned || (ctx.Doer.ID != comment.PosterID && !ctx.Repo.IsAdmin()) {
+ if err := comment.LoadIssue(ctx); err != nil {
+ ctx.Error(http.StatusInternalServerError, "LoadIssue", err)
+ return
+ }
+
+ if comment.Issue.RepoID != ctx.Repo.Repository.ID {
+ ctx.Status(http.StatusNotFound)
+ return
+ }
+
+ if !ctx.IsSigned || (ctx.Doer.ID != comment.PosterID && !ctx.Repo.CanWriteIssuesOrPulls(comment.Issue.IsPull)) {
ctx.Status(http.StatusForbidden)
return
}
@@ -647,7 +689,17 @@ func deleteIssueComment(ctx *context.APIContext) {
return
}
- if !ctx.IsSigned || (ctx.Doer.ID != comment.PosterID && !ctx.Repo.IsAdmin()) {
+ if err := comment.LoadIssue(ctx); err != nil {
+ ctx.Error(http.StatusInternalServerError, "LoadIssue", err)
+ return
+ }
+
+ if comment.Issue.RepoID != ctx.Repo.Repository.ID {
+ ctx.Status(http.StatusNotFound)
+ return
+ }
+
+ if !ctx.IsSigned || (ctx.Doer.ID != comment.PosterID && !ctx.Repo.CanWriteIssuesOrPulls(comment.Issue.IsPull)) {
ctx.Status(http.StatusForbidden)
return
} else if comment.Type != issues_model.CommentTypeComment {
diff --git a/routers/api/v1/repo/issue_comment_attachment.go b/routers/api/v1/repo/issue_comment_attachment.go
index 121e3f10e0..0a85116927 100644
--- a/routers/api/v1/repo/issue_comment_attachment.go
+++ b/routers/api/v1/repo/issue_comment_attachment.go
@@ -325,6 +325,10 @@ func getIssueCommentSafe(ctx *context.APIContext) *issues_model.Comment {
return nil
}
+ if !ctx.Repo.CanReadIssuesOrPulls(comment.Issue.IsPull) {
+ return nil
+ }
+
comment.Issue.Repo = ctx.Repo.Repository
return comment
diff --git a/routers/api/v1/repo/issue_reaction.go b/routers/api/v1/repo/issue_reaction.go
index 921f6e53f9..00cf79f086 100644
--- a/routers/api/v1/repo/issue_reaction.go
+++ b/routers/api/v1/repo/issue_reaction.go
@@ -59,6 +59,12 @@ func GetIssueCommentReactions(ctx *context.APIContext) {
if err := comment.LoadIssue(ctx); err != nil {
ctx.Error(http.StatusInternalServerError, "comment.LoadIssue", err)
+ return
+ }
+
+ if comment.Issue.RepoID != ctx.Repo.Repository.ID {
+ ctx.NotFound()
+ return
}
if !ctx.Repo.CanReadIssuesOrPulls(comment.Issue.IsPull) {
@@ -184,9 +190,19 @@ func changeIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOp
return
}
- err = comment.LoadIssue(ctx)
- if err != nil {
+ if err = comment.LoadIssue(ctx); err != nil {
ctx.Error(http.StatusInternalServerError, "comment.LoadIssue() failed", err)
+ return
+ }
+
+ if comment.Issue.RepoID != ctx.Repo.Repository.ID {
+ ctx.NotFound()
+ return
+ }
+
+ if !ctx.Repo.CanReadIssuesOrPulls(comment.Issue.IsPull) {
+ ctx.NotFound()
+ return
}
if comment.Issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(comment.Issue.IsPull) {
diff --git a/routers/api/v1/repo/key.go b/routers/api/v1/repo/key.go
index 824880880a..7b2151f2f8 100644
--- a/routers/api/v1/repo/key.go
+++ b/routers/api/v1/repo/key.go
@@ -155,6 +155,12 @@ func GetDeployKey(ctx *context.APIContext) {
return
}
+ // this check make it more consistent
+ if key.RepoID != ctx.Repo.Repository.ID {
+ ctx.NotFound()
+ return
+ }
+
if err = key.GetContent(); err != nil {
ctx.Error(http.StatusInternalServerError, "GetContent", err)
return
diff --git a/routers/api/v1/repo/release.go b/routers/api/v1/repo/release.go
index af7199d1d6..ae940d7278 100644
--- a/routers/api/v1/repo/release.go
+++ b/routers/api/v1/repo/release.go
@@ -49,13 +49,12 @@ func GetRelease(ctx *context.APIContext) {
// "$ref": "#/responses/notFound"
id := ctx.ParamsInt64(":id")
- release, err := repo_model.GetReleaseByID(ctx, id)
+ release, err := repo_model.GetReleaseForRepoByID(ctx, ctx.Repo.Repository.ID, id)
if err != nil && !repo_model.IsErrReleaseNotExist(err) {
- ctx.Error(http.StatusInternalServerError, "GetReleaseByID", err)
+ ctx.Error(http.StatusInternalServerError, "GetReleaseForRepoByID", err)
return
}
- if err != nil && repo_model.IsErrReleaseNotExist(err) ||
- release.IsTag || release.RepoID != ctx.Repo.Repository.ID {
+ if err != nil && repo_model.IsErrReleaseNotExist(err) || release.IsTag {
ctx.NotFound()
return
}
@@ -313,13 +312,12 @@ func EditRelease(ctx *context.APIContext) {
form := web.GetForm(ctx).(*api.EditReleaseOption)
id := ctx.ParamsInt64(":id")
- rel, err := repo_model.GetReleaseByID(ctx, id)
+ rel, err := repo_model.GetReleaseForRepoByID(ctx, ctx.Repo.Repository.ID, id)
if err != nil && !repo_model.IsErrReleaseNotExist(err) {
- ctx.Error(http.StatusInternalServerError, "GetReleaseByID", err)
+ ctx.Error(http.StatusInternalServerError, "GetReleaseForRepoByID", err)
return
}
- if err != nil && repo_model.IsErrReleaseNotExist(err) ||
- rel.IsTag || rel.RepoID != ctx.Repo.Repository.ID {
+ if err != nil && repo_model.IsErrReleaseNotExist(err) || rel.IsTag {
ctx.NotFound()
return
}
@@ -391,17 +389,16 @@ func DeleteRelease(ctx *context.APIContext) {
// "$ref": "#/responses/empty"
id := ctx.ParamsInt64(":id")
- rel, err := repo_model.GetReleaseByID(ctx, id)
+ rel, err := repo_model.GetReleaseForRepoByID(ctx, ctx.Repo.Repository.ID, id)
if err != nil && !repo_model.IsErrReleaseNotExist(err) {
- ctx.Error(http.StatusInternalServerError, "GetReleaseByID", err)
+ ctx.Error(http.StatusInternalServerError, "GetReleaseForRepoByID", err)
return
}
- if err != nil && repo_model.IsErrReleaseNotExist(err) ||
- rel.IsTag || rel.RepoID != ctx.Repo.Repository.ID {
+ if err != nil && repo_model.IsErrReleaseNotExist(err) || rel.IsTag {
ctx.NotFound()
return
}
- if err := release_service.DeleteReleaseByID(ctx, id, ctx.Doer, false); err != nil {
+ if err := release_service.DeleteReleaseByID(ctx, ctx.Repo.Repository, rel, ctx.Doer, false); err != nil {
if models.IsErrProtectedTagName(err) {
ctx.Error(http.StatusMethodNotAllowed, "delTag", "user not allowed to delete protected tag")
return
diff --git a/routers/api/v1/repo/release_attachment.go b/routers/api/v1/repo/release_attachment.go
index a7d73acceb..8d2eb6b61e 100644
--- a/routers/api/v1/repo/release_attachment.go
+++ b/routers/api/v1/repo/release_attachment.go
@@ -17,6 +17,23 @@ import (
"code.gitea.io/gitea/services/convert"
)
+func checkReleaseMatchRepo(ctx *context.APIContext, releaseID int64) bool {
+ release, err := repo_model.GetReleaseByID(ctx, releaseID)
+ if err != nil {
+ if repo_model.IsErrReleaseNotExist(err) {
+ ctx.NotFound()
+ return false
+ }
+ ctx.Error(http.StatusInternalServerError, "GetReleaseByID", err)
+ return false
+ }
+ if release.RepoID != ctx.Repo.Repository.ID {
+ ctx.NotFound()
+ return false
+ }
+ return true
+}
+
// GetReleaseAttachment gets a single attachment of the release
func GetReleaseAttachment(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/releases/{id}/assets/{attachment_id} repository repoGetReleaseAttachment
@@ -52,6 +69,10 @@ func GetReleaseAttachment(ctx *context.APIContext) {
// "$ref": "#/responses/Attachment"
releaseID := ctx.ParamsInt64(":id")
+ if !checkReleaseMatchRepo(ctx, releaseID) {
+ return
+ }
+
attachID := ctx.ParamsInt64(":attachment_id")
attach, err := repo_model.GetAttachmentByID(ctx, attachID)
if err != nil {
@@ -170,13 +191,7 @@ func CreateReleaseAttachment(ctx *context.APIContext) {
// Check if release exists an load release
releaseID := ctx.ParamsInt64(":id")
- release, err := repo_model.GetReleaseByID(ctx, releaseID)
- if err != nil {
- if repo_model.IsErrReleaseNotExist(err) {
- ctx.NotFound()
- return
- }
- ctx.Error(http.StatusInternalServerError, "GetReleaseByID", err)
+ if !checkReleaseMatchRepo(ctx, releaseID) {
return
}
@@ -197,7 +212,7 @@ func CreateReleaseAttachment(ctx *context.APIContext) {
attach, err := attachment.UploadAttachment(file, setting.Repository.Release.AllowedTypes, header.Size, &repo_model.Attachment{
Name: filename,
UploaderID: ctx.Doer.ID,
- RepoID: release.RepoID,
+ RepoID: ctx.Repo.Repository.ID,
ReleaseID: releaseID,
})
if err != nil {
@@ -256,6 +271,10 @@ func EditReleaseAttachment(ctx *context.APIContext) {
// Check if release exists an load release
releaseID := ctx.ParamsInt64(":id")
+ if !checkReleaseMatchRepo(ctx, releaseID) {
+ return
+ }
+
attachID := ctx.ParamsInt64(":attachment_id")
attach, err := repo_model.GetAttachmentByID(ctx, attachID)
if err != nil {
@@ -318,6 +337,10 @@ func DeleteReleaseAttachment(ctx *context.APIContext) {
// Check if release exists an load release
releaseID := ctx.ParamsInt64(":id")
+ if !checkReleaseMatchRepo(ctx, releaseID) {
+ return
+ }
+
attachID := ctx.ParamsInt64(":attachment_id")
attach, err := repo_model.GetAttachmentByID(ctx, attachID)
if err != nil {
diff --git a/routers/api/v1/repo/release_tags.go b/routers/api/v1/repo/release_tags.go
index a03edfafcf..b7442e4b56 100644
--- a/routers/api/v1/repo/release_tags.go
+++ b/routers/api/v1/repo/release_tags.go
@@ -112,7 +112,7 @@ func DeleteReleaseByTag(ctx *context.APIContext) {
return
}
- if err = releaseservice.DeleteReleaseByID(ctx, release.ID, ctx.Doer, false); err != nil {
+ if err = releaseservice.DeleteReleaseByID(ctx, ctx.Repo.Repository, release, ctx.Doer, false); err != nil {
if models.IsErrProtectedTagName(err) {
ctx.Error(http.StatusMethodNotAllowed, "delTag", "user not allowed to delete protected tag")
return
diff --git a/routers/api/v1/repo/tag.go b/routers/api/v1/repo/tag.go
index b28b6b0b91..6473cd606b 100644
--- a/routers/api/v1/repo/tag.go
+++ b/routers/api/v1/repo/tag.go
@@ -264,7 +264,7 @@ func DeleteTag(ctx *context.APIContext) {
return
}
- if err = releaseservice.DeleteReleaseByID(ctx, tag.ID, ctx.Doer, true); err != nil {
+ if err = releaseservice.DeleteReleaseByID(ctx, ctx.Repo.Repository, tag, ctx.Doer, true); err != nil {
if models.IsErrProtectedTagName(err) {
ctx.Error(http.StatusMethodNotAllowed, "delTag", "user not allowed to delete protected tag")
return
diff --git a/routers/api/v1/user/app.go b/routers/api/v1/user/app.go
index f89d53945f..a5f5a94f8e 100644
--- a/routers/api/v1/user/app.go
+++ b/routers/api/v1/user/app.go
@@ -337,6 +337,10 @@ func GetOauth2Application(ctx *context.APIContext) {
}
return
}
+ if app.UID != ctx.Doer.ID {
+ ctx.NotFound()
+ return
+ }
app.ClientSecret = ""
diff --git a/routers/api/v1/user/gpg_key.go b/routers/api/v1/user/gpg_key.go
index 84327cc92a..97acd0306f 100644
--- a/routers/api/v1/user/gpg_key.go
+++ b/routers/api/v1/user/gpg_key.go
@@ -110,7 +110,7 @@ func GetGPGKey(ctx *context.APIContext) {
// "404":
// "$ref": "#/responses/notFound"
- key, err := asymkey_model.GetGPGKeyByID(ctx.ParamsInt64(":id"))
+ key, err := asymkey_model.GetGPGKeyForUserByID(ctx.Doer.ID, ctx.ParamsInt64(":id"))
if err != nil {
if asymkey_model.IsErrGPGKeyNotExist(err) {
ctx.NotFound()
diff --git a/routers/api/v1/user/hook.go b/routers/api/v1/user/hook.go
index 50be519c81..e87385e4a2 100644
--- a/routers/api/v1/user/hook.go
+++ b/routers/api/v1/user/hook.go
@@ -62,6 +62,11 @@ func GetHook(ctx *context.APIContext) {
return
}
+ if !ctx.Doer.IsAdmin && hook.OwnerID != ctx.Doer.ID {
+ ctx.NotFound()
+ return
+ }
+
apiHook, err := webhook_service.ToHook(ctx.Doer.HomeLink(), hook)
if err != nil {
ctx.InternalServerError(err)
diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go
index f629a90476..99f3500c6f 100644
--- a/routers/web/repo/issue.go
+++ b/routers/web/repo/issue.go
@@ -2968,6 +2968,11 @@ func UpdateCommentContent(ctx *context.Context) {
return
}
+ if comment.Issue.RepoID != ctx.Repo.Repository.ID {
+ ctx.NotFound("CompareRepoID", issues_model.ErrCommentNotExist{})
+ return
+ }
+
if !ctx.IsSigned || (ctx.Doer.ID != comment.PosterID && !ctx.Repo.CanWriteIssuesOrPulls(comment.Issue.IsPull)) {
ctx.Error(http.StatusForbidden)
return
@@ -3034,6 +3039,11 @@ func DeleteComment(ctx *context.Context) {
return
}
+ if comment.Issue.RepoID != ctx.Repo.Repository.ID {
+ ctx.NotFound("CompareRepoID", issues_model.ErrCommentNotExist{})
+ return
+ }
+
if !ctx.IsSigned || (ctx.Doer.ID != comment.PosterID && !ctx.Repo.CanWriteIssuesOrPulls(comment.Issue.IsPull)) {
ctx.Error(http.StatusForbidden)
return
@@ -3160,6 +3170,11 @@ func ChangeCommentReaction(ctx *context.Context) {
return
}
+ if comment.Issue.RepoID != ctx.Repo.Repository.ID {
+ ctx.NotFound("CompareRepoID", issues_model.ErrCommentNotExist{})
+ return
+ }
+
if !ctx.IsSigned || (ctx.Doer.ID != comment.PosterID && !ctx.Repo.CanReadIssuesOrPulls(comment.Issue.IsPull)) {
if log.IsTrace() {
if ctx.IsSigned {
@@ -3303,6 +3318,21 @@ func GetCommentAttachments(ctx *context.Context) {
return
}
+ if err := comment.LoadIssue(ctx); err != nil {
+ ctx.NotFoundOrServerError("LoadIssue", issues_model.IsErrIssueNotExist, err)
+ return
+ }
+
+ if comment.Issue.RepoID != ctx.Repo.Repository.ID {
+ ctx.NotFound("CompareRepoID", issues_model.ErrCommentNotExist{})
+ return
+ }
+
+ if !ctx.Repo.Permission.CanReadIssuesOrPulls(comment.Issue.IsPull) {
+ ctx.NotFound("CanReadIssuesOrPulls", issues_model.ErrCommentNotExist{})
+ return
+ }
+
if !comment.Type.HasAttachmentSupport() {
ctx.ServerError("GetCommentAttachments", fmt.Errorf("comment type %v does not support attachments", comment.Type))
return
diff --git a/routers/web/repo/issue_content_history.go b/routers/web/repo/issue_content_history.go
index 3dd7725c21..b6345e434c 100644
--- a/routers/web/repo/issue_content_history.go
+++ b/routers/web/repo/issue_content_history.go
@@ -118,7 +118,7 @@ func GetContentHistoryDetail(ctx *context.Context) {
}
historyID := ctx.FormInt64("history_id")
- history, prevHistory, err := issues_model.GetIssueContentHistoryAndPrev(ctx, historyID)
+ history, prevHistory, err := issues_model.GetIssueContentHistoryAndPrev(ctx, issue.ID, historyID)
if err != nil {
ctx.JSON(http.StatusNotFound, map[string]any{
"message": "Can not find the content history",
diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go
index 1574c90c02..67a71a64cb 100644
--- a/routers/web/repo/projects.go
+++ b/routers/web/repo/projects.go
@@ -467,7 +467,7 @@ func AddBoardToProjectPost(ctx *context.Context) {
return
}
- project, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id"))
+ project, err := project_model.GetProjectForRepoByID(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":id"))
if err != nil {
if project_model.IsErrProjectNotExist(err) {
ctx.NotFound("", nil)
diff --git a/routers/web/repo/release.go b/routers/web/repo/release.go
index 8dc78079e2..44622c5eb3 100644
--- a/routers/web/repo/release.go
+++ b/routers/web/repo/release.go
@@ -592,7 +592,31 @@ func DeleteTag(ctx *context.Context) {
}
func deleteReleaseOrTag(ctx *context.Context, isDelTag bool) {
- if err := releaseservice.DeleteReleaseByID(ctx, ctx.FormInt64("id"), ctx.Doer, isDelTag); err != nil {
+ redirect := func() {
+ if isDelTag {
+ ctx.JSON(http.StatusOK, map[string]any{
+ "redirect": ctx.Repo.RepoLink + "/tags",
+ })
+ return
+ }
+
+ ctx.JSON(http.StatusOK, map[string]any{
+ "redirect": ctx.Repo.RepoLink + "/releases",
+ })
+ }
+
+ rel, err := repo_model.GetReleaseForRepoByID(ctx, ctx.Repo.Repository.ID, ctx.FormInt64("id"))
+ if err != nil {
+ if repo_model.IsErrReleaseNotExist(err) {
+ ctx.NotFound("GetReleaseForRepoByID", err)
+ } else {
+ ctx.Flash.Error("DeleteReleaseByID: " + err.Error())
+ redirect()
+ }
+ return
+ }
+
+ if err := releaseservice.DeleteReleaseByID(ctx, ctx.Repo.Repository, rel, ctx.Doer, isDelTag); err != nil {
if models.IsErrProtectedTagName(err) {
ctx.Flash.Error(ctx.Tr("repo.release.tag_name_protected"))
} else {
@@ -606,14 +630,5 @@ func deleteReleaseOrTag(ctx *context.Context, isDelTag bool) {
}
}
- if isDelTag {
- ctx.JSON(http.StatusOK, map[string]any{
- "redirect": ctx.Repo.RepoLink + "/tags",
- })
- return
- }
-
- ctx.JSON(http.StatusOK, map[string]any{
- "redirect": ctx.Repo.RepoLink + "/releases",
- })
+ redirect()
}
diff --git a/services/release/release.go b/services/release/release.go
index c1190305b6..08f99a98f9 100644
--- a/services/release/release.go
+++ b/services/release/release.go
@@ -291,17 +291,7 @@ func UpdateRelease(doer *user_model.User, gitRepo *git.Repository, rel *repo_mod
}
// DeleteReleaseByID deletes a release and corresponding Git tag by given ID.
-func DeleteReleaseByID(ctx context.Context, id int64, doer *user_model.User, delTag bool) error {
- rel, err := repo_model.GetReleaseByID(ctx, id)
- if err != nil {
- return fmt.Errorf("GetReleaseByID: %w", err)
- }
-
- repo, err := repo_model.GetRepositoryByID(ctx, rel.RepoID)
- if err != nil {
- return fmt.Errorf("GetRepositoryByID: %w", err)
- }
-
+func DeleteReleaseByID(ctx context.Context, repo *repo_model.Repository, rel *repo_model.Release, doer *user_model.User, delTag bool) error {
if delTag {
protectedTags, err := git_model.GetProtectedTags(ctx, rel.RepoID)
if err != nil {
@@ -334,19 +324,19 @@ func DeleteReleaseByID(ctx context.Context, id int64, doer *user_model.User, del
}, repository.NewPushCommits())
notification.NotifyDeleteRef(ctx, doer, repo, refName)
- if err := repo_model.DeleteReleaseByID(ctx, id); err != nil {
+ if err := repo_model.DeleteReleaseByID(ctx, rel.ID); err != nil {
return fmt.Errorf("DeleteReleaseByID: %w", err)
}
} else {
rel.IsTag = true
- if err = repo_model.UpdateRelease(ctx, rel); err != nil {
+ if err := repo_model.UpdateRelease(ctx, rel); err != nil {
return fmt.Errorf("Update: %w", err)
}
}
rel.Repo = repo
- if err = rel.LoadAttributes(ctx); err != nil {
+ if err := rel.LoadAttributes(ctx); err != nil {
return fmt.Errorf("LoadAttributes: %w", err)
}
diff --git a/services/webhook/deliver.go b/services/webhook/deliver.go
index 176ba83e67..22b06a7f13 100644
--- a/services/webhook/deliver.go
+++ b/services/webhook/deliver.go
@@ -34,7 +34,7 @@ import (
// Deliver deliver hook task
func Deliver(ctx context.Context, t *webhook_model.HookTask) error {
- w, err := webhook_model.GetWebhookByID(t.HookID)
+ w, err := webhook_model.GetWebhookByID(ctx, t.HookID)
if err != nil {
return err
}
diff --git a/tests/integration/api_comment_attachment_test.go b/tests/integration/api_comment_attachment_test.go
index e211376c3c..95a7a81eb4 100644
--- a/tests/integration/api_comment_attachment_test.go
+++ b/tests/integration/api_comment_attachment_test.go
@@ -35,6 +35,14 @@ func TestAPIGetCommentAttachment(t *testing.T) {
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: comment.Issue.RepoID})
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ t.Run("UnrelatedCommentID", func(t *testing.T) {
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
+ repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeWriteIssue)
+ req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/comments/%d/assets/%d?token=%s", repoOwner.Name, repo.Name, comment.ID, attachment.ID, token)
+ MakeRequest(t, req, http.StatusNotFound)
+ })
+
session := loginUser(t, repoOwner.Name)
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadIssue)
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues/comments/%d/assets/%d?token=%s", repoOwner.Name, repo.Name, comment.ID, attachment.ID, token)
diff --git a/tests/integration/api_comment_test.go b/tests/integration/api_comment_test.go
index ee648210e5..1074493da4 100644
--- a/tests/integration/api_comment_test.go
+++ b/tests/integration/api_comment_test.go
@@ -140,12 +140,25 @@ func TestAPIEditComment(t *testing.T) {
defer tests.PrepareTestEnv(t)()
const newCommentBody = "This is the new comment body"
- comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{},
+ comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 8},
unittest.Cond("type = ?", issues_model.CommentTypeComment))
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: comment.IssueID})
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID})
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ t.Run("UnrelatedCommentID", func(t *testing.T) {
+ // Using the ID of a comment that does not belong to the repository must fail
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
+ repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeWriteIssue)
+ urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d?token=%s",
+ repoOwner.Name, repo.Name, comment.ID, token)
+ req := NewRequestWithValues(t, "PATCH", urlStr, map[string]string{
+ "body": newCommentBody,
+ })
+ MakeRequest(t, req, http.StatusNotFound)
+ })
+
token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeWriteIssue)
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d?token=%s",
repoOwner.Name, repo.Name, comment.ID, token)
@@ -164,12 +177,22 @@ func TestAPIEditComment(t *testing.T) {
func TestAPIDeleteComment(t *testing.T) {
defer tests.PrepareTestEnv(t)()
- comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{},
+ comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 8},
unittest.Cond("type = ?", issues_model.CommentTypeComment))
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: comment.IssueID})
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID})
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ t.Run("UnrelatedCommentID", func(t *testing.T) {
+ // Using the ID of a comment that does not belong to the repository must fail
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
+ repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeWriteIssue)
+ req := NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/issues/comments/%d?token=%s",
+ repoOwner.Name, repo.Name, comment.ID, token)
+ MakeRequest(t, req, http.StatusNotFound)
+ })
+
token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeWriteIssue)
req := NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/issues/comments/%d?token=%s",
repoOwner.Name, repo.Name, comment.ID, token)
diff --git a/tests/integration/api_issue_reaction_test.go b/tests/integration/api_issue_reaction_test.go
index 7d3ee2d154..124d729353 100644
--- a/tests/integration/api_issue_reaction_test.go
+++ b/tests/integration/api_issue_reaction_test.go
@@ -12,6 +12,7 @@ import (
auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
+ repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
api "code.gitea.io/gitea/modules/structs"
@@ -107,6 +108,26 @@ func TestAPICommentReactions(t *testing.T) {
})
MakeRequest(t, req, http.StatusOK)
+ t.Run("UnrelatedCommentID", func(t *testing.T) {
+ // Using the ID of a comment that does not belong to the repository must fail
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
+ repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
+ token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeWriteIssue)
+ urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d/reactions?token=%s",
+ repoOwner.Name, repo.Name, comment.ID, token)
+ req = NewRequestWithJSON(t, "POST", urlStr, &api.EditReactionOption{
+ Reaction: "+1",
+ })
+ MakeRequest(t, req, http.StatusNotFound)
+ req = NewRequestWithJSON(t, "DELETE", urlStr, &api.EditReactionOption{
+ Reaction: "+1",
+ })
+ MakeRequest(t, req, http.StatusNotFound)
+
+ req = NewRequestf(t, "GET", urlStr)
+ MakeRequest(t, req, http.StatusNotFound)
+ })
+
// Add allowed reaction
req = NewRequestWithJSON(t, "POST", urlStr, &api.EditReactionOption{
Reaction: "+1",
diff --git a/tests/integration/api_keys_test.go b/tests/integration/api_keys_test.go
index 238c3cb823..03d28c9126 100644
--- a/tests/integration/api_keys_test.go
+++ b/tests/integration/api_keys_test.go
@@ -72,6 +72,17 @@ func TestCreateReadOnlyDeployKey(t *testing.T) {
Content: rawKeyBody.Key,
Mode: perm.AccessModeRead,
})
+
+ // Using the ID of a key that does not belong to the repository must fail
+ {
+ req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/keys/%d?token=%s", repoOwner.Name, repo.Name, newDeployKey.ID, token))
+ MakeRequest(t, req, http.StatusOK)
+
+ session5 := loginUser(t, "user5")
+ token5 := getTokenForLoggedInUser(t, session5, auth_model.AccessTokenScopeWriteRepository)
+ req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/user5/repo4/keys/%d?token=%s", newDeployKey.ID, token5))
+ MakeRequest(t, req, http.StatusNotFound)
+ }
}
func TestCreateReadWriteDeployKey(t *testing.T) {
diff --git a/tests/integration/api_nodeinfo_test.go b/tests/integration/api_nodeinfo_test.go
index bc2f11a7f2..f5c3ab2aa2 100644
--- a/tests/integration/api_nodeinfo_test.go
+++ b/tests/integration/api_nodeinfo_test.go
@@ -35,6 +35,6 @@ func TestNodeinfo(t *testing.T) {
assert.Equal(t, "gitea", nodeinfo.Software.Name)
assert.Equal(t, 25, nodeinfo.Usage.Users.Total)
assert.Equal(t, 18, nodeinfo.Usage.LocalPosts)
- assert.Equal(t, 2, nodeinfo.Usage.LocalComments)
+ assert.Equal(t, 3, nodeinfo.Usage.LocalComments)
})
}
diff --git a/tests/integration/issue_test.go b/tests/integration/issue_test.go
index 7cf2c5a899..251c758bfb 100644
--- a/tests/integration/issue_test.go
+++ b/tests/integration/issue_test.go
@@ -205,6 +205,56 @@ func TestIssueCommentClose(t *testing.T) {
assert.Equal(t, "Description", val)
}
+func TestIssueCommentDelete(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+ session := loginUser(t, "user2")
+ issueURL := testNewIssue(t, session, "user2", "repo1", "Title", "Description")
+ comment1 := "Test comment 1"
+ commentID := testIssueAddComment(t, session, issueURL, comment1, "")
+ comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: commentID})
+ assert.Equal(t, comment1, comment.Content)
+
+ // Using the ID of a comment that does not belong to the repository must fail
+ req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/comments/%d/delete", "user5", "repo4", commentID), map[string]string{
+ "_csrf": GetCSRF(t, session, issueURL),
+ })
+ session.MakeRequest(t, req, http.StatusNotFound)
+ req = NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/comments/%d/delete", "user2", "repo1", commentID), map[string]string{
+ "_csrf": GetCSRF(t, session, issueURL),
+ })
+ session.MakeRequest(t, req, http.StatusOK)
+ unittest.AssertNotExistsBean(t, &issues_model.Comment{ID: commentID})
+}
+
+func TestIssueCommentUpdate(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+ session := loginUser(t, "user2")
+ issueURL := testNewIssue(t, session, "user2", "repo1", "Title", "Description")
+ comment1 := "Test comment 1"
+ commentID := testIssueAddComment(t, session, issueURL, comment1, "")
+
+ comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: commentID})
+ assert.Equal(t, comment1, comment.Content)
+
+ modifiedContent := comment.Content + "MODIFIED"
+
+ // Using the ID of a comment that does not belong to the repository must fail
+ req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/comments/%d", "user5", "repo4", commentID), map[string]string{
+ "_csrf": GetCSRF(t, session, issueURL),
+ "content": modifiedContent,
+ })
+ session.MakeRequest(t, req, http.StatusNotFound)
+
+ req = NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/comments/%d", "user2", "repo1", commentID), map[string]string{
+ "_csrf": GetCSRF(t, session, issueURL),
+ "content": modifiedContent,
+ })
+ session.MakeRequest(t, req, http.StatusOK)
+
+ comment = unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: commentID})
+ assert.Equal(t, modifiedContent, comment.Content)
+}
+
func TestIssueReaction(t *testing.T) {
defer tests.PrepareTestEnv(t)()
session := loginUser(t, "user2")
diff --git a/tests/integration/mirror_pull_test.go b/tests/integration/mirror_pull_test.go
index 1bd91a48b5..c250069212 100644
--- a/tests/integration/mirror_pull_test.go
+++ b/tests/integration/mirror_pull_test.go
@@ -87,7 +87,7 @@ func TestMirrorPull(t *testing.T) {
release, err := repo_model.GetRelease(repo.ID, "v0.2")
assert.NoError(t, err)
- assert.NoError(t, release_service.DeleteReleaseByID(ctx, release.ID, user, true))
+ assert.NoError(t, release_service.DeleteReleaseByID(ctx, repo, release, user, true))
ok = mirror_service.SyncPullMirror(ctx, mirror.ID)
assert.True(t, ok)