mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-06-24 18:10:52 +00:00
backport #28213 This PR will fix some missed checks for private repositories' data on web routes and API routes.
This commit is contained in:
parent
7f81110461
commit
bc3d8bff73
41 changed files with 441 additions and 129 deletions
|
@ -1258,8 +1258,8 @@ func Routes() *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() {
|
||||
|
|
|
@ -301,7 +301,7 @@ func DeleteHook(ctx *context.APIContext) {
|
|||
// "$ref": "#/responses/empty"
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
if err := webhook.DeleteWebhookByRepoID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")); err != nil {
|
||||
if err := webhook.DeleteWebhookByRepoID(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")); err != nil {
|
||||
if webhook.IsErrWebhookNotExist(err) {
|
||||
ctx.NotFound()
|
||||
} else {
|
||||
|
|
|
@ -462,6 +462,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() {
|
||||
|
@ -593,6 +611,10 @@ func GetIssue(ctx *context.APIContext) {
|
|||
}
|
||||
return
|
||||
}
|
||||
if !ctx.Repo.CanReadIssuesOrPulls(issue.IsPull) {
|
||||
ctx.NotFound()
|
||||
return
|
||||
}
|
||||
ctx.JSON(http.StatusOK, convert.ToAPIIssue(ctx, issue))
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
@ -71,6 +73,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{
|
||||
|
@ -271,12 +278,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)
|
||||
|
@ -365,6 +387,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
|
||||
|
@ -434,6 +461,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
|
||||
|
@ -552,7 +584,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
|
||||
}
|
||||
|
@ -655,7 +697,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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -61,6 +61,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) {
|
||||
|
@ -190,9 +196,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) {
|
||||
|
|
|
@ -159,6 +159,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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
@ -315,13 +314,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
|
||||
}
|
||||
|
@ -393,17 +391,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
|
||||
|
|
|
@ -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
|
||||
|
@ -54,6 +71,10 @@ func GetReleaseAttachment(ctx *context.APIContext) {
|
|||
// "$ref": "#/responses/notFound"
|
||||
|
||||
releaseID := ctx.ParamsInt64(":id")
|
||||
if !checkReleaseMatchRepo(ctx, releaseID) {
|
||||
return
|
||||
}
|
||||
|
||||
attachID := ctx.ParamsInt64(":attachment_id")
|
||||
attach, err := repo_model.GetAttachmentByID(ctx, attachID)
|
||||
if err != nil {
|
||||
|
@ -176,13 +197,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
|
||||
}
|
||||
|
||||
|
@ -203,7 +218,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 {
|
||||
|
@ -264,6 +279,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 {
|
||||
|
@ -328,6 +347,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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -268,7 +268,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
|
||||
|
|
|
@ -343,6 +343,10 @@ func GetOauth2Application(ctx *context.APIContext) {
|
|||
}
|
||||
return
|
||||
}
|
||||
if app.UID != ctx.Doer.ID {
|
||||
ctx.NotFound()
|
||||
return
|
||||
}
|
||||
|
||||
app.ClientSecret = ""
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ func GetGPGKey(ctx *context.APIContext) {
|
|||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
|
||||
key, err := asymkey_model.GetGPGKeyByID(ctx, ctx.ParamsInt64(":id"))
|
||||
key, err := asymkey_model.GetGPGKeyForUserByID(ctx, ctx.Doer.ID, ctx.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
if asymkey_model.IsErrGPGKeyNotExist(err) {
|
||||
ctx.NotFound()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -53,7 +53,7 @@ func ListOwnerHooks(ctx *context.APIContext, owner *user_model.User) {
|
|||
|
||||
// GetOwnerHook gets an user or organization webhook. Errors are written to ctx.
|
||||
func GetOwnerHook(ctx *context.APIContext, ownerID, hookID int64) (*webhook.Webhook, error) {
|
||||
w, err := webhook.GetWebhookByOwnerID(ownerID, hookID)
|
||||
w, err := webhook.GetWebhookByOwnerID(ctx, ownerID, hookID)
|
||||
if err != nil {
|
||||
if webhook.IsErrWebhookNotExist(err) {
|
||||
ctx.NotFound()
|
||||
|
@ -68,7 +68,7 @@ func GetOwnerHook(ctx *context.APIContext, ownerID, hookID int64) (*webhook.Webh
|
|||
// GetRepoHook get a repo's webhook. If there is an error, write to `ctx`
|
||||
// accordingly and return the error
|
||||
func GetRepoHook(ctx *context.APIContext, repoID, hookID int64) (*webhook.Webhook, error) {
|
||||
w, err := webhook.GetWebhookByRepoID(repoID, hookID)
|
||||
w, err := webhook.GetWebhookByRepoID(ctx, repoID, hookID)
|
||||
if err != nil {
|
||||
if webhook.IsErrWebhookNotExist(err) {
|
||||
ctx.NotFound()
|
||||
|
@ -401,7 +401,7 @@ func editHook(ctx *context.APIContext, form *api.EditHookOption, w *webhook.Webh
|
|||
|
||||
// DeleteOwnerHook deletes the hook owned by the owner.
|
||||
func DeleteOwnerHook(ctx *context.APIContext, owner *user_model.User, hookID int64) {
|
||||
if err := webhook.DeleteWebhookByOwnerID(owner.ID, hookID); err != nil {
|
||||
if err := webhook.DeleteWebhookByOwnerID(ctx, owner.ID, hookID); err != nil {
|
||||
if webhook.IsErrWebhookNotExist(err) {
|
||||
ctx.NotFound()
|
||||
} else {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue