Compare commits

..

No commits in common. "fc16f8a108ae3c191a9dd93df429538e650d26c4" and "620e4281174882a39794a7b651c6d5318d65b44d" have entirely different histories.

46 changed files with 131 additions and 635 deletions

View file

@ -56,10 +56,6 @@ jobs:
- name: upload binaries to s3 - name: upload binaries to s3
run: | run: |
aws s3 sync dist/release s3://${{ secrets.AWS_S3_BUCKET }}/gitea/${{ steps.clean_name.outputs.branch }} --no-progress aws s3 sync dist/release s3://${{ secrets.AWS_S3_BUCKET }}/gitea/${{ steps.clean_name.outputs.branch }} --no-progress
- name: Install GH CLI
uses: dev-hanz-ops/install-gh-cli-action@v0.1.0
with:
gh-cli-version: 2.39.1
- name: create github release - name: create github release
run: | run: |
gh release create ${{ github.ref_name }} --title ${{ github.ref_name }} --draft --notes-from-tag dist/release/* gh release create ${{ github.ref_name }} --title ${{ github.ref_name }} --draft --notes-from-tag dist/release/*

View file

@ -58,13 +58,9 @@ jobs:
- name: upload binaries to s3 - name: upload binaries to s3
run: | run: |
aws s3 sync dist/release s3://${{ secrets.AWS_S3_BUCKET }}/gitea/${{ steps.clean_name.outputs.branch }} --no-progress aws s3 sync dist/release s3://${{ secrets.AWS_S3_BUCKET }}/gitea/${{ steps.clean_name.outputs.branch }} --no-progress
- name: Install GH CLI
uses: dev-hanz-ops/install-gh-cli-action@v0.1.0
with:
gh-cli-version: 2.39.1
- name: create github release - name: create github release
run: | run: |
gh release create ${{ github.ref_name }} --title ${{ github.ref_name }} --notes-from-tag dist/release/* gh release create ${{ github.ref_name }} --title ${{ github.ref_name }} --draft --notes-from-tag dist/release/*
env: env:
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
docker-rootful: docker-rootful:

View file

@ -1,15 +0,0 @@
pipeline:
nulo-container:
image: docker.io/woodpeckerci/plugin-docker-buildx
settings:
repo: gitea.nulo.in/nulo/forgejo
tag: v1.21.1-0
registry: https://gitea.nulo.in
username: Nulo
password:
from_secret: registry_secret
secrets: [REGISTRY_SECRET]
when:
branch: "nulo/release/v1.20"
event: "push"

View file

@ -4,33 +4,6 @@ This changelog goes through all the changes that have been made in each release
without substantial changes to our git log; to see the highlights of what has without substantial changes to our git log; to see the highlights of what has
been added to each release, please refer to the [blog](https://blog.gitea.com). been added to each release, please refer to the [blog](https://blog.gitea.com).
## [1.21.1](https://github.com/go-gitea/gitea/releases/tag/1.21.1) - 2023-11-26
* SECURITY
* Fix comment permissions (#28213) (#28216)
* BUGFIXES
* Fix delete-orphaned-repos (#28200) (#28202)
* Make CORS work for oauth2 handlers (#28184) (#28185)
* Fix missing buttons (#28179) (#28181)
* Fix no ActionTaskOutput table waring (#28149) (#28152)
* Fix empty action run title (#28113) (#28148)
* Use "is-loading" to avoid duplicate form submit for code comment (#28143) (#28147)
* Fix Matrix and MSTeams nil dereference (#28089) (#28105)
* Fix incorrect pgsql conn builder behavior (#28085) (#28098)
* Fix system config cache expiration timing (#28072) (#28090)
* Restricted users only see repos in orgs which their team was assigned to (#28025) (#28051)
* API
* Fix permissions for Token DELETE endpoint to match GET and POST (#27610) (#28099)
* ENHANCEMENTS
* Do not display search box when there's no packages yet (#28146) (#28159)
* Add missing `packages.cleanup.success` (#28129) (#28132)
* DOCS
* Docs: Replace deprecated IS_TLS_ENABLED mailer setting in email setup (#28205) (#28208)
* Fix the description about the default setting for action in quick start document (#28160) (#28168)
* Add guide page to actions when there's no workflows (#28145) (#28153)
* MISC
* Use full width for PR comparison (#28182) (#28186)
## [1.21.0](https://github.com/go-gitea/gitea/releases/tag/v1.21.0) - 2023-11-14 ## [1.21.0](https://github.com/go-gitea/gitea/releases/tag/v1.21.0) - 2023-11-14
* BREAKING * BREAKING

View file

@ -79,10 +79,10 @@ RUN addgroup \
-s /bin/bash \ -s /bin/bash \
-u 1000 \ -u 1000 \
-G git \ -G git \
_gitea && \ git && \
echo "_gitea:*" | chpasswd -e echo "git:*" | chpasswd -e
ENV USER _gitea ENV USER git
ENV GITEA_CUSTOM /data/gitea ENV GITEA_CUSTOM /data/gitea
VOLUME ["/data"] VOLUME ["/data"]

View file

@ -92,9 +92,10 @@ func CountUserGPGKeys(ctx context.Context, userID int64) (int64, error) {
return db.GetEngine(ctx).Where("owner_id=? AND primary_key_id=''", userID).Count(&GPGKey{}) return db.GetEngine(ctx).Where("owner_id=? AND primary_key_id=''", userID).Count(&GPGKey{})
} }
func GetGPGKeyForUserByID(ctx context.Context, ownerID, keyID int64) (*GPGKey, error) { // GetGPGKeyByID returns public key by given ID.
func GetGPGKeyByID(ctx context.Context, keyID int64) (*GPGKey, error) {
key := new(GPGKey) key := new(GPGKey)
has, err := db.GetEngine(ctx).Where("id=? AND owner_id=?", keyID, ownerID).Get(key) has, err := db.GetEngine(ctx).ID(keyID).Get(key)
if err != nil { if err != nil {
return nil, err return nil, err
} else if !has { } else if !has {
@ -224,7 +225,7 @@ func deleteGPGKey(ctx context.Context, keyID string) (int64, error) {
// DeleteGPGKey deletes GPG key information in database. // DeleteGPGKey deletes GPG key information in database.
func DeleteGPGKey(ctx context.Context, doer *user_model.User, id int64) (err error) { func DeleteGPGKey(ctx context.Context, doer *user_model.User, id int64) (err error) {
key, err := GetGPGKeyForUserByID(ctx, doer.ID, id) key, err := GetGPGKeyByID(ctx, id)
if err != nil { if err != nil {
if IsErrGPGKeyNotExist(err) { if IsErrGPGKeyNotExist(err) {
return nil return nil
@ -232,6 +233,11 @@ func DeleteGPGKey(ctx context.Context, doer *user_model.User, id int64) (err err
return fmt.Errorf("GetPublicKeyByID: %w", err) 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(ctx) ctx, committer, err := db.TxContext(ctx)
if err != nil { if err != nil {
return err return err

View file

@ -66,12 +66,3 @@
tree_path: "README.md" tree_path: "README.md"
created_unix: 946684812 created_unix: 946684812
invalidated: true 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

View file

@ -1021,7 +1021,6 @@ type FindCommentsOptions struct {
Type CommentType Type CommentType
IssueIDs []int64 IssueIDs []int64
Invalidated util.OptionalBool Invalidated util.OptionalBool
IsPull util.OptionalBool
} }
// ToConds implements FindOptions interface // ToConds implements FindOptions interface
@ -1056,9 +1055,6 @@ func (opts *FindCommentsOptions) ToConds() builder.Cond {
if !opts.Invalidated.IsNone() { if !opts.Invalidated.IsNone() {
cond = cond.And(builder.Eq{"comment.invalidated": opts.Invalidated.IsTrue()}) 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 return cond
} }
@ -1066,7 +1062,7 @@ func (opts *FindCommentsOptions) ToConds() builder.Cond {
func FindComments(ctx context.Context, opts *FindCommentsOptions) (CommentList, error) { func FindComments(ctx context.Context, opts *FindCommentsOptions) (CommentList, error) {
comments := make([]*Comment, 0, 10) comments := make([]*Comment, 0, 10)
sess := db.GetEngine(ctx).Where(opts.ToConds()) sess := db.GetEngine(ctx).Where(opts.ToConds())
if opts.RepoID > 0 || opts.IsPull != util.OptionalBoolNone { if opts.RepoID > 0 {
sess.Join("INNER", "issue", "issue.id = comment.issue_id") sess.Join("INNER", "issue", "issue.id = comment.issue_id")
} }

View file

@ -218,9 +218,9 @@ func GetIssueContentHistoryByID(dbCtx context.Context, id int64) (*ContentHistor
} }
// GetIssueContentHistoryAndPrev get a history and the previous non-deleted history (to compare) // GetIssueContentHistoryAndPrev get a history and the previous non-deleted history (to compare)
func GetIssueContentHistoryAndPrev(dbCtx context.Context, issueID, id int64) (history, prevHistory *ContentHistory, err error) { func GetIssueContentHistoryAndPrev(dbCtx context.Context, id int64) (history, prevHistory *ContentHistory, err error) {
history = &ContentHistory{} history = &ContentHistory{}
has, err := db.GetEngine(dbCtx).Where("id=? AND issue_id=?", id, issueID).Get(history) has, err := db.GetEngine(dbCtx).ID(id).Get(history)
if err != nil { if err != nil {
log.Error("failed to get issue content history %v. err=%v", id, err) log.Error("failed to get issue content history %v. err=%v", id, err)
return nil, nil, err return nil, nil, err

View file

@ -58,13 +58,13 @@ func TestContentHistory(t *testing.T) {
hasHistory2, _ := issues_model.HasIssueContentHistory(dbCtx, 10, 1) hasHistory2, _ := issues_model.HasIssueContentHistory(dbCtx, 10, 1)
assert.False(t, hasHistory2) assert.False(t, hasHistory2)
h6, h6Prev, _ := issues_model.GetIssueContentHistoryAndPrev(dbCtx, 10, 6) h6, h6Prev, _ := issues_model.GetIssueContentHistoryAndPrev(dbCtx, 6)
assert.EqualValues(t, 6, h6.ID) assert.EqualValues(t, 6, h6.ID)
assert.EqualValues(t, 5, h6Prev.ID) assert.EqualValues(t, 5, h6Prev.ID)
// soft-delete // soft-delete
_ = issues_model.SoftDeleteIssueContentHistory(dbCtx, 5) _ = issues_model.SoftDeleteIssueContentHistory(dbCtx, 5)
h6, h6Prev, _ = issues_model.GetIssueContentHistoryAndPrev(dbCtx, 10, 6) h6, h6Prev, _ = issues_model.GetIssueContentHistoryAndPrev(dbCtx, 6)
assert.EqualValues(t, 6, h6.ID) assert.EqualValues(t, 6, h6.ID)
assert.EqualValues(t, 4, h6Prev.ID) assert.EqualValues(t, 4, h6Prev.ID)

View file

@ -311,18 +311,6 @@ func GetProjectByID(ctx context.Context, id int64) (*Project, error) {
return p, nil 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 // UpdateProject updates project properties
func UpdateProject(ctx context.Context, p *Project) error { func UpdateProject(ctx context.Context, p *Project) error {
if !IsCardTypeValid(p.CardType) { if !IsCardTypeValid(p.CardType) {

View file

@ -207,21 +207,6 @@ func GetReleaseByID(ctx context.Context, id int64) (*Release, error) {
return rel, nil 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 // FindReleasesOptions describes the conditions to Find releases
type FindReleasesOptions struct { type FindReleasesOptions struct {
db.ListOptions db.ListOptions

View file

@ -392,40 +392,39 @@ func CreateWebhooks(ctx context.Context, ws []*Webhook) error {
return db.Insert(ctx, ws) return db.Insert(ctx, ws)
} }
// GetWebhookByID returns webhook of repository by given ID. // getWebhook uses argument bean as query condition,
func GetWebhookByID(ctx context.Context, id int64) (*Webhook, error) { // ID must be specified and do not assign unnecessary fields.
bean := new(Webhook) func getWebhook(bean *Webhook) (*Webhook, error) {
has, err := db.GetEngine(ctx).ID(id).Get(bean) has, err := db.GetEngine(db.DefaultContext).Get(bean)
if err != nil { if err != nil {
return nil, err return nil, err
} else if !has { } else if !has {
return nil, ErrWebhookNotExist{ID: id} return nil, ErrWebhookNotExist{ID: bean.ID}
} }
return bean, nil 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. // GetWebhookByRepoID returns webhook of repository by given ID.
func GetWebhookByRepoID(ctx context.Context, repoID, id int64) (*Webhook, error) { func GetWebhookByRepoID(repoID, id int64) (*Webhook, error) {
webhook := new(Webhook) return getWebhook(&Webhook{
has, err := db.GetEngine(ctx).Where("id=? AND repo_id=?", id, repoID).Get(webhook) ID: id,
if err != nil { RepoID: repoID,
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. // GetWebhookByOwnerID returns webhook of a user or organization by given ID.
func GetWebhookByOwnerID(ctx context.Context, ownerID, id int64) (*Webhook, error) { func GetWebhookByOwnerID(ownerID, id int64) (*Webhook, error) {
webhook := new(Webhook) return getWebhook(&Webhook{
has, err := db.GetEngine(ctx).Where("id=? AND owner_id=?", id, ownerID).Get(webhook) ID: id,
if err != nil { OwnerID: ownerID,
return nil, err })
} else if !has {
return nil, ErrWebhookNotExist{ID: id}
}
return webhook, nil
} }
// ListWebhookOptions are options to filter webhooks on ListWebhooksByOpts // ListWebhookOptions are options to filter webhooks on ListWebhooksByOpts
@ -483,20 +482,20 @@ func UpdateWebhookLastStatus(w *Webhook) error {
return err return err
} }
// DeleteWebhookByID uses argument bean as query condition, // deleteWebhook uses argument bean as query condition,
// ID must be specified and do not assign unnecessary fields. // ID must be specified and do not assign unnecessary fields.
func DeleteWebhookByID(ctx context.Context, id int64) (err error) { func deleteWebhook(bean *Webhook) (err error) {
ctx, committer, err := db.TxContext(ctx) ctx, committer, err := db.TxContext(db.DefaultContext)
if err != nil { if err != nil {
return err return err
} }
defer committer.Close() defer committer.Close()
if count, err := db.DeleteByID(ctx, id, new(Webhook)); err != nil { if count, err := db.DeleteByBean(ctx, bean); err != nil {
return err return err
} else if count == 0 { } else if count == 0 {
return ErrWebhookNotExist{ID: id} return ErrWebhookNotExist{ID: bean.ID}
} else if _, err = db.DeleteByBean(ctx, &HookTask{HookID: id}); err != nil { } else if _, err = db.DeleteByBean(ctx, &HookTask{HookID: bean.ID}); err != nil {
return err return err
} }
@ -504,17 +503,17 @@ func DeleteWebhookByID(ctx context.Context, id int64) (err error) {
} }
// DeleteWebhookByRepoID deletes webhook of repository by given ID. // DeleteWebhookByRepoID deletes webhook of repository by given ID.
func DeleteWebhookByRepoID(ctx context.Context, repoID, id int64) error { func DeleteWebhookByRepoID(repoID, id int64) error {
if _, err := GetWebhookByRepoID(ctx, repoID, id); err != nil { return deleteWebhook(&Webhook{
return err ID: id,
} RepoID: repoID,
return DeleteWebhookByID(ctx, id) })
} }
// DeleteWebhookByOwnerID deletes webhook of a user or organization by given ID. // DeleteWebhookByOwnerID deletes webhook of a user or organization by given ID.
func DeleteWebhookByOwnerID(ctx context.Context, ownerID, id int64) error { func DeleteWebhookByOwnerID(ownerID, id int64) error {
if _, err := GetWebhookByOwnerID(ctx, ownerID, id); err != nil { return deleteWebhook(&Webhook{
return err ID: id,
} OwnerID: ownerID,
return DeleteWebhookByID(ctx, id) })
} }

View file

@ -101,22 +101,22 @@ func TestCreateWebhook(t *testing.T) {
func TestGetWebhookByRepoID(t *testing.T) { func TestGetWebhookByRepoID(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase()) assert.NoError(t, unittest.PrepareTestDatabase())
hook, err := GetWebhookByRepoID(db.DefaultContext, 1, 1) hook, err := GetWebhookByRepoID(1, 1)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, int64(1), hook.ID) assert.Equal(t, int64(1), hook.ID)
_, err = GetWebhookByRepoID(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID) _, err = GetWebhookByRepoID(unittest.NonexistentID, unittest.NonexistentID)
assert.Error(t, err) assert.Error(t, err)
assert.True(t, IsErrWebhookNotExist(err)) assert.True(t, IsErrWebhookNotExist(err))
} }
func TestGetWebhookByOwnerID(t *testing.T) { func TestGetWebhookByOwnerID(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase()) assert.NoError(t, unittest.PrepareTestDatabase())
hook, err := GetWebhookByOwnerID(db.DefaultContext, 3, 3) hook, err := GetWebhookByOwnerID(3, 3)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, int64(3), hook.ID) assert.Equal(t, int64(3), hook.ID)
_, err = GetWebhookByOwnerID(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID) _, err = GetWebhookByOwnerID(unittest.NonexistentID, unittest.NonexistentID)
assert.Error(t, err) assert.Error(t, err)
assert.True(t, IsErrWebhookNotExist(err)) assert.True(t, IsErrWebhookNotExist(err))
} }
@ -174,10 +174,10 @@ func TestUpdateWebhook(t *testing.T) {
func TestDeleteWebhookByRepoID(t *testing.T) { func TestDeleteWebhookByRepoID(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase()) assert.NoError(t, unittest.PrepareTestDatabase())
unittest.AssertExistsAndLoadBean(t, &Webhook{ID: 2, RepoID: 1}) unittest.AssertExistsAndLoadBean(t, &Webhook{ID: 2, RepoID: 1})
assert.NoError(t, DeleteWebhookByRepoID(db.DefaultContext, 1, 2)) assert.NoError(t, DeleteWebhookByRepoID(1, 2))
unittest.AssertNotExistsBean(t, &Webhook{ID: 2, RepoID: 1}) unittest.AssertNotExistsBean(t, &Webhook{ID: 2, RepoID: 1})
err := DeleteWebhookByRepoID(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID) err := DeleteWebhookByRepoID(unittest.NonexistentID, unittest.NonexistentID)
assert.Error(t, err) assert.Error(t, err)
assert.True(t, IsErrWebhookNotExist(err)) assert.True(t, IsErrWebhookNotExist(err))
} }
@ -185,10 +185,10 @@ func TestDeleteWebhookByRepoID(t *testing.T) {
func TestDeleteWebhookByOwnerID(t *testing.T) { func TestDeleteWebhookByOwnerID(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase()) assert.NoError(t, unittest.PrepareTestDatabase())
unittest.AssertExistsAndLoadBean(t, &Webhook{ID: 3, OwnerID: 3}) unittest.AssertExistsAndLoadBean(t, &Webhook{ID: 3, OwnerID: 3})
assert.NoError(t, DeleteWebhookByOwnerID(db.DefaultContext, 3, 3)) assert.NoError(t, DeleteWebhookByOwnerID(3, 3))
unittest.AssertNotExistsBean(t, &Webhook{ID: 3, OwnerID: 3}) unittest.AssertNotExistsBean(t, &Webhook{ID: 3, OwnerID: 3})
err := DeleteWebhookByOwnerID(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID) err := DeleteWebhookByOwnerID(unittest.NonexistentID, unittest.NonexistentID)
assert.Error(t, err) assert.Error(t, err)
assert.True(t, IsErrWebhookNotExist(err)) assert.True(t, IsErrWebhookNotExist(err))
} }

View file

@ -1266,8 +1266,8 @@ func Routes() *web.Route {
m.Group("/{username}/{reponame}", func() { m.Group("/{username}/{reponame}", func() {
m.Group("/issues", func() { m.Group("/issues", func() {
m.Combo("").Get(repo.ListIssues). m.Combo("").Get(repo.ListIssues).
Post(reqToken(), mustNotBeArchived, bind(api.CreateIssueOption{}), reqRepoReader(unit.TypeIssues), repo.CreateIssue) Post(reqToken(), mustNotBeArchived, bind(api.CreateIssueOption{}), repo.CreateIssue)
m.Get("/pinned", reqRepoReader(unit.TypeIssues), repo.ListPinnedIssues) m.Get("/pinned", repo.ListPinnedIssues)
m.Group("/comments", func() { m.Group("/comments", func() {
m.Get("", repo.ListRepoIssueComments) m.Get("", repo.ListRepoIssueComments)
m.Group("/{id}", func() { m.Group("/{id}", func() {

View file

@ -301,7 +301,7 @@ func DeleteHook(ctx *context.APIContext) {
// "$ref": "#/responses/empty" // "$ref": "#/responses/empty"
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
if err := webhook.DeleteWebhookByRepoID(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")); err != nil { if err := webhook.DeleteWebhookByRepoID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")); err != nil {
if webhook.IsErrWebhookNotExist(err) { if webhook.IsErrWebhookNotExist(err) {
ctx.NotFound() ctx.NotFound()
} else { } else {

View file

@ -463,24 +463,6 @@ func ListIssues(ctx *context.APIContext) {
isPull = util.OptionalBoolNone 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 // FIXME: we should be more efficient here
createdByID := getUserIDForFilter(ctx, "created_by") createdByID := getUserIDForFilter(ctx, "created_by")
if ctx.Written() { if ctx.Written() {
@ -612,10 +594,6 @@ func GetIssue(ctx *context.APIContext) {
} }
return return
} }
if !ctx.Repo.CanReadIssuesOrPulls(issue.IsPull) {
ctx.NotFound()
return
}
ctx.JSON(http.StatusOK, convert.ToAPIIssue(ctx, issue)) ctx.JSON(http.StatusOK, convert.ToAPIIssue(ctx, issue))
} }

View file

@ -12,11 +12,9 @@ import (
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
access_model "code.gitea.io/gitea/models/perm/access" access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils" "code.gitea.io/gitea/routers/api/v1/utils"
"code.gitea.io/gitea/services/convert" "code.gitea.io/gitea/services/convert"
@ -73,11 +71,6 @@ func ListIssueComments(ctx *context.APIContext) {
ctx.Error(http.StatusInternalServerError, "GetRawIssueByIndex", err) ctx.Error(http.StatusInternalServerError, "GetRawIssueByIndex", err)
return return
} }
if !ctx.Repo.CanReadIssuesOrPulls(issue.IsPull) {
ctx.NotFound()
return
}
issue.Repo = ctx.Repo.Repository issue.Repo = ctx.Repo.Repository
opts := &issues_model.FindCommentsOptions{ opts := &issues_model.FindCommentsOptions{
@ -278,27 +271,12 @@ func ListRepoIssueComments(ctx *context.APIContext) {
return 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{ opts := &issues_model.FindCommentsOptions{
ListOptions: utils.GetListOptions(ctx), ListOptions: utils.GetListOptions(ctx),
RepoID: ctx.Repo.Repository.ID, RepoID: ctx.Repo.Repository.ID,
Type: issues_model.CommentTypeComment, Type: issues_model.CommentTypeComment,
Since: since, Since: since,
Before: before, Before: before,
IsPull: isPull,
} }
comments, err := issues_model.FindComments(ctx, opts) comments, err := issues_model.FindComments(ctx, opts)
@ -387,11 +365,6 @@ func CreateIssueComment(ctx *context.APIContext) {
return return
} }
if !ctx.Repo.CanReadIssuesOrPulls(issue.IsPull) {
ctx.NotFound()
return
}
if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) && !ctx.Doer.IsAdmin { 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"))) ctx.Error(http.StatusForbidden, "CreateIssueComment", errors.New(ctx.Tr("repo.issues.comment_on_locked")))
return return
@ -471,11 +444,6 @@ func GetIssueComment(ctx *context.APIContext) {
return return
} }
if !ctx.Repo.CanReadIssuesOrPulls(comment.Issue.IsPull) {
ctx.NotFound()
return
}
if comment.Type != issues_model.CommentTypeComment { if comment.Type != issues_model.CommentTypeComment {
ctx.Status(http.StatusNoContent) ctx.Status(http.StatusNoContent)
return return
@ -594,17 +562,7 @@ func editIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption)
return return
} }
if err := comment.LoadIssue(ctx); err != nil { if !ctx.IsSigned || (ctx.Doer.ID != comment.PosterID && !ctx.Repo.IsAdmin()) {
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) ctx.Status(http.StatusForbidden)
return return
} }
@ -718,17 +676,7 @@ func deleteIssueComment(ctx *context.APIContext) {
return return
} }
if err := comment.LoadIssue(ctx); err != nil { if !ctx.IsSigned || (ctx.Doer.ID != comment.PosterID && !ctx.Repo.IsAdmin()) {
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) ctx.Status(http.StatusForbidden)
return return
} else if comment.Type != issues_model.CommentTypeComment { } else if comment.Type != issues_model.CommentTypeComment {

View file

@ -352,10 +352,6 @@ func getIssueCommentSafe(ctx *context.APIContext) *issues_model.Comment {
return nil return nil
} }
if !ctx.Repo.CanReadIssuesOrPulls(comment.Issue.IsPull) {
return nil
}
comment.Issue.Repo = ctx.Repo.Repository comment.Issue.Repo = ctx.Repo.Repository
return comment return comment

View file

@ -63,12 +63,6 @@ func GetIssueCommentReactions(ctx *context.APIContext) {
if err := comment.LoadIssue(ctx); err != nil { if err := comment.LoadIssue(ctx); err != nil {
ctx.Error(http.StatusInternalServerError, "comment.LoadIssue", err) 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) { if !ctx.Repo.CanReadIssuesOrPulls(comment.Issue.IsPull) {
@ -198,19 +192,9 @@ func changeIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOp
return return
} }
if err = comment.LoadIssue(ctx); err != nil { err = comment.LoadIssue(ctx)
if err != nil {
ctx.Error(http.StatusInternalServerError, "comment.LoadIssue() failed", err) 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) { if comment.Issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(comment.Issue.IsPull) {

View file

@ -159,12 +159,6 @@ func GetDeployKey(ctx *context.APIContext) {
return return
} }
// this check make it more consistent
if key.RepoID != ctx.Repo.Repository.ID {
ctx.NotFound()
return
}
if err = key.GetContent(); err != nil { if err = key.GetContent(); err != nil {
ctx.Error(http.StatusInternalServerError, "GetContent", err) ctx.Error(http.StatusInternalServerError, "GetContent", err)
return return

View file

@ -49,12 +49,13 @@ func GetRelease(ctx *context.APIContext) {
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
id := ctx.ParamsInt64(":id") id := ctx.ParamsInt64(":id")
release, err := repo_model.GetReleaseForRepoByID(ctx, ctx.Repo.Repository.ID, id) release, err := repo_model.GetReleaseByID(ctx, id)
if err != nil && !repo_model.IsErrReleaseNotExist(err) { if err != nil && !repo_model.IsErrReleaseNotExist(err) {
ctx.Error(http.StatusInternalServerError, "GetReleaseForRepoByID", err) ctx.Error(http.StatusInternalServerError, "GetReleaseByID", err)
return return
} }
if err != nil && repo_model.IsErrReleaseNotExist(err) || release.IsTag { if err != nil && repo_model.IsErrReleaseNotExist(err) ||
release.IsTag || release.RepoID != ctx.Repo.Repository.ID {
ctx.NotFound() ctx.NotFound()
return return
} }
@ -314,12 +315,13 @@ func EditRelease(ctx *context.APIContext) {
form := web.GetForm(ctx).(*api.EditReleaseOption) form := web.GetForm(ctx).(*api.EditReleaseOption)
id := ctx.ParamsInt64(":id") id := ctx.ParamsInt64(":id")
rel, err := repo_model.GetReleaseForRepoByID(ctx, ctx.Repo.Repository.ID, id) rel, err := repo_model.GetReleaseByID(ctx, id)
if err != nil && !repo_model.IsErrReleaseNotExist(err) { if err != nil && !repo_model.IsErrReleaseNotExist(err) {
ctx.Error(http.StatusInternalServerError, "GetReleaseForRepoByID", err) ctx.Error(http.StatusInternalServerError, "GetReleaseByID", err)
return return
} }
if err != nil && repo_model.IsErrReleaseNotExist(err) || rel.IsTag { if err != nil && repo_model.IsErrReleaseNotExist(err) ||
rel.IsTag || rel.RepoID != ctx.Repo.Repository.ID {
ctx.NotFound() ctx.NotFound()
return return
} }
@ -391,16 +393,17 @@ func DeleteRelease(ctx *context.APIContext) {
// "$ref": "#/responses/empty" // "$ref": "#/responses/empty"
id := ctx.ParamsInt64(":id") id := ctx.ParamsInt64(":id")
rel, err := repo_model.GetReleaseForRepoByID(ctx, ctx.Repo.Repository.ID, id) rel, err := repo_model.GetReleaseByID(ctx, id)
if err != nil && !repo_model.IsErrReleaseNotExist(err) { if err != nil && !repo_model.IsErrReleaseNotExist(err) {
ctx.Error(http.StatusInternalServerError, "GetReleaseForRepoByID", err) ctx.Error(http.StatusInternalServerError, "GetReleaseByID", err)
return return
} }
if err != nil && repo_model.IsErrReleaseNotExist(err) || rel.IsTag { if err != nil && repo_model.IsErrReleaseNotExist(err) ||
rel.IsTag || rel.RepoID != ctx.Repo.Repository.ID {
ctx.NotFound() ctx.NotFound()
return return
} }
if err := release_service.DeleteReleaseByID(ctx, ctx.Repo.Repository, rel, ctx.Doer, false); err != nil { if err := release_service.DeleteReleaseByID(ctx, id, ctx.Doer, false); err != nil {
if models.IsErrProtectedTagName(err) { if models.IsErrProtectedTagName(err) {
ctx.Error(http.StatusMethodNotAllowed, "delTag", "user not allowed to delete protected tag") ctx.Error(http.StatusMethodNotAllowed, "delTag", "user not allowed to delete protected tag")
return return

View file

@ -17,23 +17,6 @@ import (
"code.gitea.io/gitea/services/convert" "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 // GetReleaseAttachment gets a single attachment of the release
func GetReleaseAttachment(ctx *context.APIContext) { func GetReleaseAttachment(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/releases/{id}/assets/{attachment_id} repository repoGetReleaseAttachment // swagger:operation GET /repos/{owner}/{repo}/releases/{id}/assets/{attachment_id} repository repoGetReleaseAttachment
@ -71,10 +54,6 @@ func GetReleaseAttachment(ctx *context.APIContext) {
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
releaseID := ctx.ParamsInt64(":id") releaseID := ctx.ParamsInt64(":id")
if !checkReleaseMatchRepo(ctx, releaseID) {
return
}
attachID := ctx.ParamsInt64(":attachment_id") attachID := ctx.ParamsInt64(":attachment_id")
attach, err := repo_model.GetAttachmentByID(ctx, attachID) attach, err := repo_model.GetAttachmentByID(ctx, attachID)
if err != nil { if err != nil {
@ -197,7 +176,13 @@ func CreateReleaseAttachment(ctx *context.APIContext) {
// Check if release exists an load release // Check if release exists an load release
releaseID := ctx.ParamsInt64(":id") releaseID := ctx.ParamsInt64(":id")
if !checkReleaseMatchRepo(ctx, releaseID) { release, err := repo_model.GetReleaseByID(ctx, releaseID)
if err != nil {
if repo_model.IsErrReleaseNotExist(err) {
ctx.NotFound()
return
}
ctx.Error(http.StatusInternalServerError, "GetReleaseByID", err)
return return
} }
@ -218,7 +203,7 @@ func CreateReleaseAttachment(ctx *context.APIContext) {
attach, err := attachment.UploadAttachment(file, setting.Repository.Release.AllowedTypes, header.Size, &repo_model.Attachment{ attach, err := attachment.UploadAttachment(file, setting.Repository.Release.AllowedTypes, header.Size, &repo_model.Attachment{
Name: filename, Name: filename,
UploaderID: ctx.Doer.ID, UploaderID: ctx.Doer.ID,
RepoID: ctx.Repo.Repository.ID, RepoID: release.RepoID,
ReleaseID: releaseID, ReleaseID: releaseID,
}) })
if err != nil { if err != nil {
@ -279,10 +264,6 @@ func EditReleaseAttachment(ctx *context.APIContext) {
// Check if release exists an load release // Check if release exists an load release
releaseID := ctx.ParamsInt64(":id") releaseID := ctx.ParamsInt64(":id")
if !checkReleaseMatchRepo(ctx, releaseID) {
return
}
attachID := ctx.ParamsInt64(":attachment_id") attachID := ctx.ParamsInt64(":attachment_id")
attach, err := repo_model.GetAttachmentByID(ctx, attachID) attach, err := repo_model.GetAttachmentByID(ctx, attachID)
if err != nil { if err != nil {
@ -347,10 +328,6 @@ func DeleteReleaseAttachment(ctx *context.APIContext) {
// Check if release exists an load release // Check if release exists an load release
releaseID := ctx.ParamsInt64(":id") releaseID := ctx.ParamsInt64(":id")
if !checkReleaseMatchRepo(ctx, releaseID) {
return
}
attachID := ctx.ParamsInt64(":attachment_id") attachID := ctx.ParamsInt64(":attachment_id")
attach, err := repo_model.GetAttachmentByID(ctx, attachID) attach, err := repo_model.GetAttachmentByID(ctx, attachID)
if err != nil { if err != nil {

View file

@ -112,7 +112,7 @@ func DeleteReleaseByTag(ctx *context.APIContext) {
return return
} }
if err = releaseservice.DeleteReleaseByID(ctx, ctx.Repo.Repository, release, ctx.Doer, false); err != nil { if err = releaseservice.DeleteReleaseByID(ctx, release.ID, ctx.Doer, false); err != nil {
if models.IsErrProtectedTagName(err) { if models.IsErrProtectedTagName(err) {
ctx.Error(http.StatusMethodNotAllowed, "delTag", "user not allowed to delete protected tag") ctx.Error(http.StatusMethodNotAllowed, "delTag", "user not allowed to delete protected tag")
return return

View file

@ -268,7 +268,7 @@ func DeleteTag(ctx *context.APIContext) {
return return
} }
if err = releaseservice.DeleteReleaseByID(ctx, ctx.Repo.Repository, tag, ctx.Doer, true); err != nil { if err = releaseservice.DeleteReleaseByID(ctx, tag.ID, ctx.Doer, true); err != nil {
if models.IsErrProtectedTagName(err) { if models.IsErrProtectedTagName(err) {
ctx.Error(http.StatusMethodNotAllowed, "delTag", "user not allowed to delete protected tag") ctx.Error(http.StatusMethodNotAllowed, "delTag", "user not allowed to delete protected tag")
return return

View file

@ -343,10 +343,6 @@ func GetOauth2Application(ctx *context.APIContext) {
} }
return return
} }
if app.UID != ctx.Doer.ID {
ctx.NotFound()
return
}
app.ClientSecret = "" app.ClientSecret = ""

View file

@ -112,7 +112,7 @@ func GetGPGKey(ctx *context.APIContext) {
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
key, err := asymkey_model.GetGPGKeyForUserByID(ctx, ctx.Doer.ID, ctx.ParamsInt64(":id")) key, err := asymkey_model.GetGPGKeyByID(ctx, ctx.ParamsInt64(":id"))
if err != nil { if err != nil {
if asymkey_model.IsErrGPGKeyNotExist(err) { if asymkey_model.IsErrGPGKeyNotExist(err) {
ctx.NotFound() ctx.NotFound()

View file

@ -62,11 +62,6 @@ func GetHook(ctx *context.APIContext) {
return return
} }
if !ctx.Doer.IsAdmin && hook.OwnerID != ctx.Doer.ID {
ctx.NotFound()
return
}
apiHook, err := webhook_service.ToHook(ctx.Doer.HomeLink(), hook) apiHook, err := webhook_service.ToHook(ctx.Doer.HomeLink(), hook)
if err != nil { if err != nil {
ctx.InternalServerError(err) ctx.InternalServerError(err)

View file

@ -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. // GetOwnerHook gets an user or organization webhook. Errors are written to ctx.
func GetOwnerHook(ctx *context.APIContext, ownerID, hookID int64) (*webhook.Webhook, error) { func GetOwnerHook(ctx *context.APIContext, ownerID, hookID int64) (*webhook.Webhook, error) {
w, err := webhook.GetWebhookByOwnerID(ctx, ownerID, hookID) w, err := webhook.GetWebhookByOwnerID(ownerID, hookID)
if err != nil { if err != nil {
if webhook.IsErrWebhookNotExist(err) { if webhook.IsErrWebhookNotExist(err) {
ctx.NotFound() 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` // GetRepoHook get a repo's webhook. If there is an error, write to `ctx`
// accordingly and return the error // accordingly and return the error
func GetRepoHook(ctx *context.APIContext, repoID, hookID int64) (*webhook.Webhook, error) { func GetRepoHook(ctx *context.APIContext, repoID, hookID int64) (*webhook.Webhook, error) {
w, err := webhook.GetWebhookByRepoID(ctx, repoID, hookID) w, err := webhook.GetWebhookByRepoID(repoID, hookID)
if err != nil { if err != nil {
if webhook.IsErrWebhookNotExist(err) { if webhook.IsErrWebhookNotExist(err) {
ctx.NotFound() 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. // DeleteOwnerHook deletes the hook owned by the owner.
func DeleteOwnerHook(ctx *context.APIContext, owner *user_model.User, hookID int64) { func DeleteOwnerHook(ctx *context.APIContext, owner *user_model.User, hookID int64) {
if err := webhook.DeleteWebhookByOwnerID(ctx, owner.ID, hookID); err != nil { if err := webhook.DeleteWebhookByOwnerID(owner.ID, hookID); err != nil {
if webhook.IsErrWebhookNotExist(err) { if webhook.IsErrWebhookNotExist(err) {
ctx.NotFound() ctx.NotFound()
} else { } else {

View file

@ -233,7 +233,7 @@ func Webhooks(ctx *context.Context) {
// DeleteWebhook response for delete webhook // DeleteWebhook response for delete webhook
func DeleteWebhook(ctx *context.Context) { func DeleteWebhook(ctx *context.Context) {
if err := webhook.DeleteWebhookByOwnerID(ctx, ctx.Org.Organization.ID, ctx.FormInt64("id")); err != nil { if err := webhook.DeleteWebhookByOwnerID(ctx.Org.Organization.ID, ctx.FormInt64("id")); err != nil {
ctx.Flash.Error("DeleteWebhookByOwnerID: " + err.Error()) ctx.Flash.Error("DeleteWebhookByOwnerID: " + err.Error())
} else { } else {
ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success")) ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success"))

View file

@ -3098,11 +3098,6 @@ func UpdateCommentContent(ctx *context.Context) {
return 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)) { if !ctx.IsSigned || (ctx.Doer.ID != comment.PosterID && !ctx.Repo.CanWriteIssuesOrPulls(comment.Issue.IsPull)) {
ctx.Error(http.StatusForbidden) ctx.Error(http.StatusForbidden)
return return
@ -3169,11 +3164,6 @@ func DeleteComment(ctx *context.Context) {
return 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)) { if !ctx.IsSigned || (ctx.Doer.ID != comment.PosterID && !ctx.Repo.CanWriteIssuesOrPulls(comment.Issue.IsPull)) {
ctx.Error(http.StatusForbidden) ctx.Error(http.StatusForbidden)
return return
@ -3300,11 +3290,6 @@ func ChangeCommentReaction(ctx *context.Context) {
return 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 !ctx.IsSigned || (ctx.Doer.ID != comment.PosterID && !ctx.Repo.CanReadIssuesOrPulls(comment.Issue.IsPull)) {
if log.IsTrace() { if log.IsTrace() {
if ctx.IsSigned { if ctx.IsSigned {
@ -3448,21 +3433,6 @@ func GetCommentAttachments(ctx *context.Context) {
return 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() { if !comment.Type.HasAttachmentSupport() {
ctx.ServerError("GetCommentAttachments", fmt.Errorf("comment type %v does not support attachments", comment.Type)) ctx.ServerError("GetCommentAttachments", fmt.Errorf("comment type %v does not support attachments", comment.Type))
return return

View file

@ -122,7 +122,7 @@ func GetContentHistoryDetail(ctx *context.Context) {
} }
historyID := ctx.FormInt64("history_id") historyID := ctx.FormInt64("history_id")
history, prevHistory, err := issues_model.GetIssueContentHistoryAndPrev(ctx, issue.ID, historyID) history, prevHistory, err := issues_model.GetIssueContentHistoryAndPrev(ctx, historyID)
if err != nil { if err != nil {
ctx.JSON(http.StatusNotFound, map[string]any{ ctx.JSON(http.StatusNotFound, map[string]any{
"message": "Can not find the content history", "message": "Can not find the content history",
@ -198,19 +198,11 @@ func SoftDeleteContentHistory(ctx *context.Context) {
log.Error("can not get comment for issue content history %v. err=%v", historyID, err) log.Error("can not get comment for issue content history %v. err=%v", historyID, err)
return return
} }
if comment.IssueID != issue.ID {
ctx.NotFound("CompareRepoID", issues_model.ErrCommentNotExist{})
return
}
} }
if history, err = issues_model.GetIssueContentHistoryByID(ctx, historyID); err != nil { if history, err = issues_model.GetIssueContentHistoryByID(ctx, historyID); err != nil {
log.Error("can not get issue content history %v. err=%v", historyID, err) log.Error("can not get issue content history %v. err=%v", historyID, err)
return return
} }
if history.IssueID != issue.ID {
ctx.NotFound("CompareRepoID", issues_model.ErrCommentNotExist{})
return
}
canSoftDelete := canSoftDeleteContentHistory(ctx, issue, comment, history) canSoftDelete := canSoftDeleteContentHistory(ctx, issue, comment, history)
if !canSoftDelete { if !canSoftDelete {

View file

@ -89,10 +89,6 @@ func IssuePinMove(ctx *context.Context) {
log.Error(err.Error()) log.Error(err.Error())
return return
} }
if issue.RepoID != ctx.Repo.Repository.ID {
ctx.NotFound("CompareRepoID", issues_model.ErrCommentNotExist{})
return
}
err = issue.MovePin(ctx, form.Position) err = issue.MovePin(ctx, form.Position)
if err != nil { if err != nil {

View file

@ -464,7 +464,7 @@ func AddBoardToProjectPost(ctx *context.Context) {
return return
} }
project, err := project_model.GetProjectForRepoByID(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":id")) project, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id"))
if err != nil { if err != nil {
if project_model.IsErrProjectNotExist(err) { if project_model.IsErrProjectNotExist(err) {
ctx.NotFound("", nil) ctx.NotFound("", nil)

View file

@ -615,27 +615,7 @@ func DeleteTag(ctx *context.Context) {
} }
func deleteReleaseOrTag(ctx *context.Context, isDelTag bool) { func deleteReleaseOrTag(ctx *context.Context, isDelTag bool) {
redirect := func() { if err := releaseservice.DeleteReleaseByID(ctx, ctx.FormInt64("id"), ctx.Doer, isDelTag); err != nil {
if isDelTag {
ctx.JSONRedirect(ctx.Repo.RepoLink + "/tags")
return
}
ctx.JSONRedirect(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) { if models.IsErrProtectedTagName(err) {
ctx.Flash.Error(ctx.Tr("repo.release.tag_name_protected")) ctx.Flash.Error(ctx.Tr("repo.release.tag_name_protected"))
} else { } else {
@ -649,5 +629,10 @@ func deleteReleaseOrTag(ctx *context.Context, isDelTag bool) {
} }
} }
redirect() if isDelTag {
ctx.JSONRedirect(ctx.Repo.RepoLink + "/tags")
return
}
ctx.JSONRedirect(ctx.Repo.RepoLink + "/releases")
} }

View file

@ -617,9 +617,9 @@ func checkWebhook(ctx *context.Context) (*ownerRepoCtx, *webhook.Webhook) {
var w *webhook.Webhook var w *webhook.Webhook
if orCtx.RepoID > 0 { if orCtx.RepoID > 0 {
w, err = webhook.GetWebhookByRepoID(ctx, orCtx.RepoID, ctx.ParamsInt64(":id")) w, err = webhook.GetWebhookByRepoID(orCtx.RepoID, ctx.ParamsInt64(":id"))
} else if orCtx.OwnerID > 0 { } else if orCtx.OwnerID > 0 {
w, err = webhook.GetWebhookByOwnerID(ctx, orCtx.OwnerID, ctx.ParamsInt64(":id")) w, err = webhook.GetWebhookByOwnerID(orCtx.OwnerID, ctx.ParamsInt64(":id"))
} else if orCtx.IsAdmin { } else if orCtx.IsAdmin {
w, err = webhook.GetSystemOrDefaultWebhook(ctx, ctx.ParamsInt64(":id")) w, err = webhook.GetSystemOrDefaultWebhook(ctx, ctx.ParamsInt64(":id"))
} }
@ -671,7 +671,7 @@ func WebHooksEdit(ctx *context.Context) {
// TestWebhook test if web hook is work fine // TestWebhook test if web hook is work fine
func TestWebhook(ctx *context.Context) { func TestWebhook(ctx *context.Context) {
hookID := ctx.ParamsInt64(":id") hookID := ctx.ParamsInt64(":id")
w, err := webhook.GetWebhookByRepoID(ctx, ctx.Repo.Repository.ID, hookID) w, err := webhook.GetWebhookByRepoID(ctx.Repo.Repository.ID, hookID)
if err != nil { if err != nil {
ctx.Flash.Error("GetWebhookByRepoID: " + err.Error()) ctx.Flash.Error("GetWebhookByRepoID: " + err.Error())
ctx.Status(http.StatusInternalServerError) ctx.Status(http.StatusInternalServerError)
@ -752,7 +752,7 @@ func ReplayWebhook(ctx *context.Context) {
// DeleteWebhook delete a webhook // DeleteWebhook delete a webhook
func DeleteWebhook(ctx *context.Context) { func DeleteWebhook(ctx *context.Context) {
if err := webhook.DeleteWebhookByRepoID(ctx, ctx.Repo.Repository.ID, ctx.FormInt64("id")); err != nil { if err := webhook.DeleteWebhookByRepoID(ctx.Repo.Repository.ID, ctx.FormInt64("id")); err != nil {
ctx.Flash.Error("DeleteWebhookByRepoID: " + err.Error()) ctx.Flash.Error("DeleteWebhookByRepoID: " + err.Error())
} else { } else {
ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success")) ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success"))

View file

@ -36,7 +36,7 @@ func Webhooks(ctx *context.Context) {
// DeleteWebhook response for delete webhook // DeleteWebhook response for delete webhook
func DeleteWebhook(ctx *context.Context) { func DeleteWebhook(ctx *context.Context) {
if err := webhook.DeleteWebhookByOwnerID(ctx, ctx.Doer.ID, ctx.FormInt64("id")); err != nil { if err := webhook.DeleteWebhookByOwnerID(ctx.Doer.ID, ctx.FormInt64("id")); err != nil {
ctx.Flash.Error("DeleteWebhookByOwnerID: " + err.Error()) ctx.Flash.Error("DeleteWebhookByOwnerID: " + err.Error())
} else { } else {
ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success")) ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success"))

View file

@ -291,7 +291,17 @@ func UpdateRelease(ctx context.Context, doer *user_model.User, gitRepo *git.Repo
} }
// DeleteReleaseByID deletes a release and corresponding Git tag by given ID. // DeleteReleaseByID deletes a release and corresponding Git tag by given ID.
func DeleteReleaseByID(ctx context.Context, repo *repo_model.Repository, rel *repo_model.Release, doer *user_model.User, delTag bool) error { 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)
}
if delTag { if delTag {
protectedTags, err := git_model.GetProtectedTags(ctx, rel.RepoID) protectedTags, err := git_model.GetProtectedTags(ctx, rel.RepoID)
if err != nil { if err != nil {
@ -324,19 +334,19 @@ func DeleteReleaseByID(ctx context.Context, repo *repo_model.Repository, rel *re
}, repository.NewPushCommits()) }, repository.NewPushCommits())
notify_service.DeleteRef(ctx, doer, repo, refName) notify_service.DeleteRef(ctx, doer, repo, refName)
if err := repo_model.DeleteReleaseByID(ctx, rel.ID); err != nil { if err := repo_model.DeleteReleaseByID(ctx, id); err != nil {
return fmt.Errorf("DeleteReleaseByID: %w", err) return fmt.Errorf("DeleteReleaseByID: %w", err)
} }
} else { } else {
rel.IsTag = true 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) return fmt.Errorf("Update: %w", err)
} }
} }
rel.Repo = repo rel.Repo = repo
if err := rel.LoadAttributes(ctx); err != nil { if err = rel.LoadAttributes(ctx); err != nil {
return fmt.Errorf("LoadAttributes: %w", err) return fmt.Errorf("LoadAttributes: %w", err)
} }

View file

@ -34,7 +34,7 @@ import (
// Deliver deliver hook task // Deliver deliver hook task
func Deliver(ctx context.Context, t *webhook_model.HookTask) error { func Deliver(ctx context.Context, t *webhook_model.HookTask) error {
w, err := webhook_model.GetWebhookByID(ctx, t.HookID) w, err := webhook_model.GetWebhookByID(t.HookID)
if err != nil { if err != nil {
return err return err
} }

View file

@ -36,14 +36,6 @@ func TestAPIGetCommentAttachment(t *testing.T) {
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: comment.Issue.RepoID}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: comment.Issue.RepoID})
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) 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) session := loginUser(t, repoOwner.Name)
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadIssue) 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) 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)

View file

@ -230,25 +230,12 @@ func TestAPIEditComment(t *testing.T) {
defer tests.PrepareTestEnv(t)() defer tests.PrepareTestEnv(t)()
const newCommentBody = "This is the new comment body" const newCommentBody = "This is the new comment body"
comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 8}, comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{},
unittest.Cond("type = ?", issues_model.CommentTypeComment)) unittest.Cond("type = ?", issues_model.CommentTypeComment))
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: comment.IssueID}) issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: comment.IssueID})
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID})
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) 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) token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeWriteIssue)
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d?token=%s", urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d?token=%s",
repoOwner.Name, repo.Name, comment.ID, token) repoOwner.Name, repo.Name, comment.ID, token)
@ -321,22 +308,12 @@ func TestAPIEditCommentWithDate(t *testing.T) {
func TestAPIDeleteComment(t *testing.T) { func TestAPIDeleteComment(t *testing.T) {
defer tests.PrepareTestEnv(t)() defer tests.PrepareTestEnv(t)()
comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 8}, comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{},
unittest.Cond("type = ?", issues_model.CommentTypeComment)) unittest.Cond("type = ?", issues_model.CommentTypeComment))
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: comment.IssueID}) issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: comment.IssueID})
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID})
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) 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) token := getUserToken(t, repoOwner.Name, auth_model.AccessTokenScopeWriteIssue)
req := NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/issues/comments/%d?token=%s", req := NewRequestf(t, "DELETE", "/api/v1/repos/%s/%s/issues/comments/%d?token=%s",
repoOwner.Name, repo.Name, comment.ID, token) repoOwner.Name, repo.Name, comment.ID, token)

View file

@ -12,7 +12,6 @@ import (
auth_model "code.gitea.io/gitea/models/auth" auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
@ -108,26 +107,6 @@ func TestAPICommentReactions(t *testing.T) {
}) })
MakeRequest(t, req, http.StatusOK) 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 // Add allowed reaction
req = NewRequestWithJSON(t, "POST", urlStr, &api.EditReactionOption{ req = NewRequestWithJSON(t, "POST", urlStr, &api.EditReactionOption{
Reaction: "+1", Reaction: "+1",

View file

@ -72,17 +72,6 @@ func TestCreateReadOnlyDeployKey(t *testing.T) {
Content: rawKeyBody.Key, Content: rawKeyBody.Key,
Mode: perm.AccessModeRead, 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) { func TestCreateReadWriteDeployKey(t *testing.T) {

View file

@ -206,106 +206,6 @@ func TestIssueCommentClose(t *testing.T) {
assert.Equal(t, "Description", val) 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 TestIssueCommentAttachment(t *testing.T) {
defer tests.PrepareTestEnv(t)()
const repoURL = "user2/repo1"
const content = "Test comment 4"
const status = ""
session := loginUser(t, "user2")
issueURL := testNewIssue(t, session, "user2", "repo1", "Title", "Description")
req := NewRequest(t, "GET", issueURL)
resp := session.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
link, exists := htmlDoc.doc.Find("#comment-form").Attr("action")
assert.True(t, exists, "The template has changed")
uuid := createAttachment(t, session, repoURL, "image.png", generateImg(), http.StatusOK)
commentCount := htmlDoc.doc.Find(".comment-list .comment .render-content").Length()
req = NewRequestWithValues(t, "POST", link, map[string]string{
"_csrf": htmlDoc.GetCSRF(),
"content": content,
"status": status,
"files": uuid,
})
resp = session.MakeRequest(t, req, http.StatusOK)
req = NewRequest(t, "GET", test.RedirectURL(resp))
resp = session.MakeRequest(t, req, http.StatusOK)
htmlDoc = NewHTMLParser(t, resp.Body)
val := htmlDoc.doc.Find(".comment-list .comment .render-content p").Eq(commentCount).Text()
assert.Equal(t, content, val)
idAttr, has := htmlDoc.doc.Find(".comment-list .comment").Eq(commentCount).Attr("id")
idStr := idAttr[strings.LastIndexByte(idAttr, '-')+1:]
assert.True(t, has)
id, err := strconv.Atoi(idStr)
assert.NoError(t, err)
assert.NotEqual(t, 0, id)
req = NewRequest(t, "GET", fmt.Sprintf("/%s/%s/comments/%d/attachments", "user2", "repo1", id))
session.MakeRequest(t, req, http.StatusOK)
// Using the ID of a comment that does not belong to the repository must fail
req = NewRequest(t, "GET", fmt.Sprintf("/%s/%s/comments/%d/attachments", "user5", "repo4", id))
session.MakeRequest(t, req, http.StatusNotFound)
}
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) { func TestIssueReaction(t *testing.T) {
defer tests.PrepareTestEnv(t)() defer tests.PrepareTestEnv(t)()
session := loginUser(t, "user2") session := loginUser(t, "user2")
@ -657,45 +557,3 @@ func TestUpdateIssueDeadline(t *testing.T) {
assert.EqualValues(t, "2022-04-06", apiIssue.Deadline.Format("2006-01-02")) assert.EqualValues(t, "2022-04-06", apiIssue.Deadline.Format("2006-01-02"))
} }
func TestIssuePinMove(t *testing.T) {
defer tests.PrepareTestEnv(t)()
session := loginUser(t, "user2")
issueURL, issue := testIssueWithBean(t, "user2", 1, "Title", "Content")
assert.EqualValues(t, 0, issue.PinOrder)
req := NewRequestWithValues(t, "POST", fmt.Sprintf("%s/pin", issueURL), map[string]string{
"_csrf": GetCSRF(t, session, issueURL),
})
session.MakeRequest(t, req, http.StatusOK)
issue = unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: issue.ID})
position := 1
assert.EqualValues(t, position, issue.PinOrder)
newPosition := 2
// Using the ID of an issue that does not belong to the repository must fail
{
session5 := loginUser(t, "user5")
movePinURL := "/user5/repo4/issues/move_pin?_csrf=" + GetCSRF(t, session5, issueURL)
req = NewRequestWithJSON(t, "POST", movePinURL, map[string]any{
"id": issue.ID,
"position": newPosition,
})
session5.MakeRequest(t, req, http.StatusNotFound)
issue = unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: issue.ID})
assert.EqualValues(t, position, issue.PinOrder)
}
movePinURL := issueURL[:strings.LastIndexByte(issueURL, '/')] + "/move_pin?_csrf=" + GetCSRF(t, session, issueURL)
req = NewRequestWithJSON(t, "POST", movePinURL, map[string]any{
"id": issue.ID,
"position": newPosition,
})
session.MakeRequest(t, req, http.StatusNoContent)
issue = unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: issue.ID})
assert.EqualValues(t, newPosition, issue.PinOrder)
}

View file

@ -88,7 +88,7 @@ func TestMirrorPull(t *testing.T) {
release, err := repo_model.GetRelease(db.DefaultContext, repo.ID, "v0.2") release, err := repo_model.GetRelease(db.DefaultContext, repo.ID, "v0.2")
assert.NoError(t, err) assert.NoError(t, err)
assert.NoError(t, release_service.DeleteReleaseByID(ctx, repo, release, user, true)) assert.NoError(t, release_service.DeleteReleaseByID(ctx, release.ID, user, true))
ok = mirror_service.SyncPullMirror(ctx, mirror.ID) ok = mirror_service.SyncPullMirror(ctx, mirror.ID)
assert.True(t, ok) assert.True(t, ok)

View file

@ -93,44 +93,6 @@ func TestCreateRelease(t *testing.T) {
checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.1", translation.NewLocale("en-US").Tr("repo.release.stable"), 4) checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.1", translation.NewLocale("en-US").Tr("repo.release.stable"), 4)
} }
func TestDeleteRelease(t *testing.T) {
defer tests.PrepareTestEnv(t)()
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 57, OwnerName: "user2", LowerName: "repo-release"})
release := unittest.AssertExistsAndLoadBean(t, &repo_model.Release{TagName: "v2.0"})
assert.False(t, release.IsTag)
// Using the ID of a comment that does not belong to the repository must fail
session5 := loginUser(t, "user5")
otherRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user5", LowerName: "repo4"})
req := NewRequestWithValues(t, "POST", fmt.Sprintf("%s/releases/delete?id=%d", otherRepo.Link(), release.ID), map[string]string{
"_csrf": GetCSRF(t, session5, otherRepo.Link()),
})
session5.MakeRequest(t, req, http.StatusNotFound)
session := loginUser(t, "user2")
req = NewRequestWithValues(t, "POST", fmt.Sprintf("%s/releases/delete?id=%d", repo.Link(), release.ID), map[string]string{
"_csrf": GetCSRF(t, session, repo.Link()),
})
session.MakeRequest(t, req, http.StatusOK)
release = unittest.AssertExistsAndLoadBean(t, &repo_model.Release{ID: release.ID})
if assert.True(t, release.IsTag) {
req = NewRequestWithValues(t, "POST", fmt.Sprintf("%s/tags/delete?id=%d", otherRepo.Link(), release.ID), map[string]string{
"_csrf": GetCSRF(t, session5, otherRepo.Link()),
})
session5.MakeRequest(t, req, http.StatusNotFound)
req = NewRequestWithValues(t, "POST", fmt.Sprintf("%s/tags/delete?id=%d", repo.Link(), release.ID), map[string]string{
"_csrf": GetCSRF(t, session, repo.Link()),
})
session.MakeRequest(t, req, http.StatusOK)
unittest.AssertNotExistsBean(t, &repo_model.Release{ID: release.ID})
}
}
func TestCreateReleasePreRelease(t *testing.T) { func TestCreateReleasePreRelease(t *testing.T) {
defer tests.PrepareTestEnv(t)() defer tests.PrepareTestEnv(t)()