[GITEA] DELETE /repos/{owner}/{repo}/pulls/{index}/reviews/{id}/comments/{comment}

* reuse deleteIssueComment by adding the commentType parameter
* ensure tests start with a PR with no random reviews from fixtures

Refs: https://codeberg.org/forgejo/forgejo/issues/2109
(cherry picked from commit 5b90ab77f67e4c0ac17d8b1101453d7790fa45d2)
(cherry picked from commit 28ecd6f5a67891788ad4d989311050df55deb008)
(cherry picked from commit 24870cf133153f0fdefb76df58fe074ae6aef7c0)
This commit is contained in:
Earl Warren 2024-01-16 10:28:09 +00:00
parent 8eaa8aeaf9
commit 0b503e5e86
No known key found for this signature in database
GPG key ID: 0579CB2928A78A00
5 changed files with 156 additions and 6 deletions

View file

@ -1265,7 +1265,11 @@ func Routes() *web.Route {
m.Combo(""). m.Combo("").
Get(repo.GetPullReviewComments). Get(repo.GetPullReviewComments).
Post(reqToken(), bind(api.CreatePullReviewCommentOptions{}), repo.CreatePullReviewComment) Post(reqToken(), bind(api.CreatePullReviewCommentOptions{}), repo.CreatePullReviewComment)
m.Get("/{comment}", commentAssignment("comment"), repo.GetPullReviewComment) m.Group("/{comment}", func() {
m.Combo("").
Get(repo.GetPullReviewComment).
Delete(reqToken(), repo.DeletePullReviewComment)
}, commentAssignment("comment"))
}) })
m.Post("/dismissals", reqToken(), bind(api.DismissPullReviewOptions{}), repo.DismissPullReview) m.Post("/dismissals", reqToken(), bind(api.DismissPullReviewOptions{}), repo.DismissPullReview)
m.Post("/undismissals", reqToken(), repo.UnDismissPullReview) m.Post("/undismissals", reqToken(), repo.UnDismissPullReview)

View file

@ -624,7 +624,7 @@ func DeleteIssueComment(ctx *context.APIContext) {
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
deleteIssueComment(ctx) deleteIssueComment(ctx, issues_model.CommentTypeComment)
} }
// DeleteIssueCommentDeprecated delete a comment from an issue // DeleteIssueCommentDeprecated delete a comment from an issue
@ -663,16 +663,16 @@ func DeleteIssueCommentDeprecated(ctx *context.APIContext) {
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
deleteIssueComment(ctx) deleteIssueComment(ctx, issues_model.CommentTypeComment)
} }
func deleteIssueComment(ctx *context.APIContext) { func deleteIssueComment(ctx *context.APIContext, commentType issues_model.CommentType) {
comment := ctx.Comment comment := ctx.Comment
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.Status(http.StatusForbidden) ctx.Status(http.StatusForbidden)
return return
} else if comment.Type != issues_model.CommentTypeComment { } else if comment.Type != commentType {
ctx.Status(http.StatusNoContent) ctx.Status(http.StatusNoContent)
return return
} }

View file

@ -1014,6 +1014,53 @@ func UnDismissPullReview(ctx *context.APIContext) {
dismissReview(ctx, "", false, false) dismissReview(ctx, "", false, false)
} }
// DeletePullReviewComment delete a pull review comment
func DeletePullReviewComment(ctx *context.APIContext) {
// swagger:operation DELETE /repos/{owner}/{repo}/pulls/{index}/reviews/{id}/comments/{comment} repository repoDeletePullReviewComment
// ---
// summary: Delete a pull review comment
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: owner of the repo
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repo
// type: string
// required: true
// - name: index
// in: path
// description: index of the pull request
// type: integer
// format: int64
// required: true
// - name: id
// in: path
// description: id of the review
// type: integer
// format: int64
// required: true
// - name: comment
// in: path
// description: id of the comment
// type: integer
// format: int64
// required: true
// responses:
// "204":
// "$ref": "#/responses/empty"
// "403":
// "$ref": "#/responses/forbidden"
// "404":
// "$ref": "#/responses/notFound"
deleteIssueComment(ctx, issues_model.CommentTypeCode)
}
func dismissReview(ctx *context.APIContext, msg string, isDismiss, dismissPriors bool) { func dismissReview(ctx *context.APIContext, msg string, isDismiss, dismissPriors bool) {
if !ctx.Repo.IsAdmin() { if !ctx.Repo.IsAdmin() {
ctx.Error(http.StatusForbidden, "", "Must be repo admin") ctx.Error(http.StatusForbidden, "", "Must be repo admin")

View file

@ -11666,6 +11666,67 @@
"$ref": "#/responses/notFound" "$ref": "#/responses/notFound"
} }
} }
},
"delete": {
"produces": [
"application/json"
],
"tags": [
"repository"
],
"summary": "Delete a pull review comment",
"operationId": "repoDeletePullReviewComment",
"parameters": [
{
"type": "string",
"description": "owner of the repo",
"name": "owner",
"in": "path",
"required": true
},
{
"type": "string",
"description": "name of the repo",
"name": "repo",
"in": "path",
"required": true
},
{
"type": "integer",
"format": "int64",
"description": "index of the pull request",
"name": "index",
"in": "path",
"required": true
},
{
"type": "integer",
"format": "int64",
"description": "id of the review",
"name": "id",
"in": "path",
"required": true
},
{
"type": "integer",
"format": "int64",
"description": "id of the comment",
"name": "comment",
"in": "path",
"required": true
}
],
"responses": {
"204": {
"$ref": "#/responses/empty"
},
"403": {
"$ref": "#/responses/forbidden"
},
"404": {
"$ref": "#/responses/notFound"
}
}
} }
}, },
"/repos/{owner}/{repo}/pulls/{index}/reviews/{id}/dismissals": { "/repos/{owner}/{repo}/pulls/{index}/reviews/{id}/dismissals": {

View file

@ -21,7 +21,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestAPIPullReviewCreateComment(t *testing.T) { func TestAPIPullReviewCreateDeleteComment(t *testing.T) {
defer tests.PrepareTestEnv(t)() defer tests.PrepareTestEnv(t)()
pullIssue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 3}) pullIssue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 3})
assert.NoError(t, pullIssue.LoadAttributes(db.DefaultContext)) assert.NoError(t, pullIssue.LoadAttributes(db.DefaultContext))
@ -47,6 +47,30 @@ func TestAPIPullReviewCreateComment(t *testing.T) {
var review api.PullReview var review api.PullReview
var reviewLine int64 = 1 var reviewLine int64 = 1
// cleanup
{
session := loginUser(t, "user1")
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAll)
req := NewRequestf(t, http.MethodGet, "/api/v1/repos/%s/pulls/%d/reviews", repo.FullName(), pullIssue.Index).AddTokenAuth(token)
resp := MakeRequest(t, req, http.StatusOK)
var reviews []*api.PullReview
DecodeJSON(t, resp, &reviews)
for _, review := range reviews {
req := NewRequestf(t, http.MethodDelete, "/api/v1/repos/%s/pulls/%d/reviews/%d", repo.FullName(), pullIssue.Index, review.ID).
AddTokenAuth(token)
MakeRequest(t, req, http.StatusNoContent)
}
}
requireReviewCount := func(count int) {
req := NewRequestf(t, http.MethodGet, "/api/v1/repos/%s/pulls/%d/reviews", repo.FullName(), pullIssue.Index).AddTokenAuth(token)
resp := MakeRequest(t, req, http.StatusOK)
var reviews []*api.PullReview
DecodeJSON(t, resp, &reviews)
require.EqualValues(t, count, len(reviews))
}
{ {
req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/pulls/%d/reviews", repo.FullName(), pullIssue.Index), &api.CreatePullReviewOptions{ req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/pulls/%d/reviews", repo.FullName(), pullIssue.Index), &api.CreatePullReviewOptions{
Body: "body1", Body: "body1",
@ -66,6 +90,7 @@ func TestAPIPullReviewCreateComment(t *testing.T) {
DecodeJSON(t, resp, &getReview) DecodeJSON(t, resp, &getReview)
require.EqualValues(t, getReview, review) require.EqualValues(t, getReview, review)
} }
requireReviewCount(1)
newCommentBody := "first new line" newCommentBody := "first new line"
var reviewComment api.PullReviewComment var reviewComment api.PullReviewComment
@ -95,11 +120,24 @@ func TestAPIPullReviewCreateComment(t *testing.T) {
assert.EqualValues(t, reviewComment, comment) assert.EqualValues(t, reviewComment, comment)
} }
{
req := NewRequestf(t, http.MethodDelete, "/api/v1/repos/%s/pulls/%d/reviews/%d/comments/%d", repo.FullName(), pullIssue.Index, review.ID, reviewComment.ID).
AddTokenAuth(token)
MakeRequest(t, req, http.StatusNoContent)
}
{
req := NewRequestf(t, http.MethodGet, "/api/v1/repos/%s/pulls/%d/reviews/%d/comments/%d", repo.FullName(), pullIssue.Index, review.ID, reviewComment.ID).
AddTokenAuth(token)
MakeRequest(t, req, http.StatusNotFound)
}
{ {
req := NewRequestf(t, http.MethodDelete, "/api/v1/repos/%s/pulls/%d/reviews/%d", repo.FullName(), pullIssue.Index, review.ID). req := NewRequestf(t, http.MethodDelete, "/api/v1/repos/%s/pulls/%d/reviews/%d", repo.FullName(), pullIssue.Index, review.ID).
AddTokenAuth(token) AddTokenAuth(token)
MakeRequest(t, req, http.StatusNoContent) MakeRequest(t, req, http.StatusNoContent)
} }
requireReviewCount(0)
}) })
} }
} }