[API] Add Reactions (#9220)
* reject reactions wich ar not allowed * dont duble check CreateReaction now throw ErrForbiddenIssueReaction * add /repos/{owner}/{repo}/issues/comments/{id}/reactions endpoint * add Find Functions * fix some swagger stuff + add issue reaction endpoints + GET ReactionList now use FindReactions... * explicite Issue Only Reaction for FindReactionsOptions with "-1" commentID * load issue; load user ... * return error again * swagger def canged after LINT * check if user has ben loaded * add Tests * better way of comparing results * add suggestion * use different issue for test (dont interfear with integration test) * test dont compare Location on timeCompare * TEST: add forbidden dubble add * add comments in code to explain * add settings.UI.ReactionsMap so if !setting.UI.ReactionsMap[opts.Type] workstokarchuk/v1.17
parent
ee7df7ba8c
commit
37e10d4543
@ -0,0 +1,145 @@ |
|||||||
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package integrations |
||||||
|
|
||||||
|
import ( |
||||||
|
"fmt" |
||||||
|
"net/http" |
||||||
|
"testing" |
||||||
|
"time" |
||||||
|
|
||||||
|
"code.gitea.io/gitea/models" |
||||||
|
api "code.gitea.io/gitea/modules/structs" |
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert" |
||||||
|
) |
||||||
|
|
||||||
|
func TestAPIIssuesReactions(t *testing.T) { |
||||||
|
defer prepareTestEnv(t)() |
||||||
|
|
||||||
|
issue := models.AssertExistsAndLoadBean(t, &models.Issue{ID: 1}).(*models.Issue) |
||||||
|
_ = issue.LoadRepo() |
||||||
|
owner := models.AssertExistsAndLoadBean(t, &models.User{ID: issue.Repo.OwnerID}).(*models.User) |
||||||
|
|
||||||
|
session := loginUser(t, owner.Name) |
||||||
|
token := getTokenForLoggedInUser(t, session) |
||||||
|
|
||||||
|
user1 := models.AssertExistsAndLoadBean(t, &models.User{ID: 1}).(*models.User) |
||||||
|
user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User) |
||||||
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/reactions?token=%s", |
||||||
|
owner.Name, issue.Repo.Name, issue.Index, token) |
||||||
|
|
||||||
|
//Try to add not allowed reaction
|
||||||
|
req := NewRequestWithJSON(t, "POST", urlStr, &api.EditReactionOption{ |
||||||
|
Reaction: "wrong", |
||||||
|
}) |
||||||
|
resp := session.MakeRequest(t, req, http.StatusForbidden) |
||||||
|
|
||||||
|
//Delete not allowed reaction
|
||||||
|
req = NewRequestWithJSON(t, "DELETE", urlStr, &api.EditReactionOption{ |
||||||
|
Reaction: "zzz", |
||||||
|
}) |
||||||
|
resp = session.MakeRequest(t, req, http.StatusOK) |
||||||
|
|
||||||
|
//Add allowed reaction
|
||||||
|
req = NewRequestWithJSON(t, "POST", urlStr, &api.EditReactionOption{ |
||||||
|
Reaction: "rocket", |
||||||
|
}) |
||||||
|
resp = session.MakeRequest(t, req, http.StatusCreated) |
||||||
|
var apiNewReaction api.ReactionResponse |
||||||
|
DecodeJSON(t, resp, &apiNewReaction) |
||||||
|
|
||||||
|
//Add existing reaction
|
||||||
|
resp = session.MakeRequest(t, req, http.StatusForbidden) |
||||||
|
|
||||||
|
//Get end result of reaction list of issue #1
|
||||||
|
req = NewRequestf(t, "GET", urlStr) |
||||||
|
resp = session.MakeRequest(t, req, http.StatusOK) |
||||||
|
var apiReactions []*api.ReactionResponse |
||||||
|
DecodeJSON(t, resp, &apiReactions) |
||||||
|
expectResponse := make(map[int]api.ReactionResponse) |
||||||
|
expectResponse[0] = api.ReactionResponse{ |
||||||
|
User: user1.APIFormat(), |
||||||
|
Reaction: "zzz", |
||||||
|
Created: time.Unix(1573248002, 0), |
||||||
|
} |
||||||
|
expectResponse[1] = api.ReactionResponse{ |
||||||
|
User: user2.APIFormat(), |
||||||
|
Reaction: "eyes", |
||||||
|
Created: time.Unix(1573248003, 0), |
||||||
|
} |
||||||
|
expectResponse[2] = apiNewReaction |
||||||
|
assert.Len(t, apiReactions, 3) |
||||||
|
for i, r := range apiReactions { |
||||||
|
assert.Equal(t, expectResponse[i].Reaction, r.Reaction) |
||||||
|
assert.Equal(t, expectResponse[i].Created.Unix(), r.Created.Unix()) |
||||||
|
assert.Equal(t, expectResponse[i].User.ID, r.User.ID) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func TestAPICommentReactions(t *testing.T) { |
||||||
|
defer prepareTestEnv(t)() |
||||||
|
|
||||||
|
comment := models.AssertExistsAndLoadBean(t, &models.Comment{ID: 2}).(*models.Comment) |
||||||
|
_ = comment.LoadIssue() |
||||||
|
issue := comment.Issue |
||||||
|
_ = issue.LoadRepo() |
||||||
|
owner := models.AssertExistsAndLoadBean(t, &models.User{ID: issue.Repo.OwnerID}).(*models.User) |
||||||
|
|
||||||
|
session := loginUser(t, owner.Name) |
||||||
|
token := getTokenForLoggedInUser(t, session) |
||||||
|
|
||||||
|
user1 := models.AssertExistsAndLoadBean(t, &models.User{ID: 1}).(*models.User) |
||||||
|
user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User) |
||||||
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/comments/%d/reactions?token=%s", |
||||||
|
owner.Name, issue.Repo.Name, comment.ID, token) |
||||||
|
|
||||||
|
//Try to add not allowed reaction
|
||||||
|
req := NewRequestWithJSON(t, "POST", urlStr, &api.EditReactionOption{ |
||||||
|
Reaction: "wrong", |
||||||
|
}) |
||||||
|
resp := session.MakeRequest(t, req, http.StatusForbidden) |
||||||
|
|
||||||
|
//Delete none existing reaction
|
||||||
|
req = NewRequestWithJSON(t, "DELETE", urlStr, &api.EditReactionOption{ |
||||||
|
Reaction: "eyes", |
||||||
|
}) |
||||||
|
resp = session.MakeRequest(t, req, http.StatusOK) |
||||||
|
|
||||||
|
//Add allowed reaction
|
||||||
|
req = NewRequestWithJSON(t, "POST", urlStr, &api.EditReactionOption{ |
||||||
|
Reaction: "+1", |
||||||
|
}) |
||||||
|
resp = session.MakeRequest(t, req, http.StatusCreated) |
||||||
|
var apiNewReaction api.ReactionResponse |
||||||
|
DecodeJSON(t, resp, &apiNewReaction) |
||||||
|
|
||||||
|
//Add existing reaction
|
||||||
|
resp = session.MakeRequest(t, req, http.StatusForbidden) |
||||||
|
|
||||||
|
//Get end result of reaction list of issue #1
|
||||||
|
req = NewRequestf(t, "GET", urlStr) |
||||||
|
resp = session.MakeRequest(t, req, http.StatusOK) |
||||||
|
var apiReactions []*api.ReactionResponse |
||||||
|
DecodeJSON(t, resp, &apiReactions) |
||||||
|
expectResponse := make(map[int]api.ReactionResponse) |
||||||
|
expectResponse[0] = api.ReactionResponse{ |
||||||
|
User: user2.APIFormat(), |
||||||
|
Reaction: "laugh", |
||||||
|
Created: time.Unix(1573248004, 0), |
||||||
|
} |
||||||
|
expectResponse[1] = api.ReactionResponse{ |
||||||
|
User: user1.APIFormat(), |
||||||
|
Reaction: "laugh", |
||||||
|
Created: time.Unix(1573248005, 0), |
||||||
|
} |
||||||
|
expectResponse[2] = apiNewReaction |
||||||
|
assert.Len(t, apiReactions, 3) |
||||||
|
for i, r := range apiReactions { |
||||||
|
assert.Equal(t, expectResponse[i].Reaction, r.Reaction) |
||||||
|
assert.Equal(t, expectResponse[i].Created.Unix(), r.Created.Unix()) |
||||||
|
assert.Equal(t, expectResponse[i].User.ID, r.User.ID) |
||||||
|
} |
||||||
|
} |
@ -1 +1,39 @@ |
|||||||
[] # empty |
- |
||||||
|
id: 1 #issue reaction |
||||||
|
type: zzz # not allowed reaction (added before allowed reaction list has changed) |
||||||
|
issue_id: 1 |
||||||
|
comment_id: 0 |
||||||
|
user_id: 2 |
||||||
|
created_unix: 1573248001 |
||||||
|
|
||||||
|
- |
||||||
|
id: 2 #issue reaction |
||||||
|
type: zzz # not allowed reaction (added before allowed reaction list has changed) |
||||||
|
issue_id: 1 |
||||||
|
comment_id: 0 |
||||||
|
user_id: 1 |
||||||
|
created_unix: 1573248002 |
||||||
|
|
||||||
|
- |
||||||
|
id: 3 #issue reaction |
||||||
|
type: eyes # allowed reaction |
||||||
|
issue_id: 1 |
||||||
|
comment_id: 0 |
||||||
|
user_id: 2 |
||||||
|
created_unix: 1573248003 |
||||||
|
|
||||||
|
- |
||||||
|
id: 4 #comment reaction |
||||||
|
type: laugh # allowed reaction |
||||||
|
issue_id: 1 |
||||||
|
comment_id: 2 |
||||||
|
user_id: 2 |
||||||
|
created_unix: 1573248004 |
||||||
|
|
||||||
|
- |
||||||
|
id: 5 #comment reaction |
||||||
|
type: laugh # allowed reaction |
||||||
|
issue_id: 1 |
||||||
|
comment_id: 2 |
||||||
|
user_id: 1 |
||||||
|
created_unix: 1573248005 |
||||||
|
@ -0,0 +1,22 @@ |
|||||||
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package structs |
||||||
|
|
||||||
|
import ( |
||||||
|
"time" |
||||||
|
) |
||||||
|
|
||||||
|
// EditReactionOption contain the reaction type
|
||||||
|
type EditReactionOption struct { |
||||||
|
Reaction string `json:"content"` |
||||||
|
} |
||||||
|
|
||||||
|
// ReactionResponse contain one reaction
|
||||||
|
type ReactionResponse struct { |
||||||
|
User *User `json:"user"` |
||||||
|
Reaction string `json:"content"` |
||||||
|
// swagger:strfmt date-time
|
||||||
|
Created time.Time `json:"created_at"` |
||||||
|
} |
@ -0,0 +1,394 @@ |
|||||||
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package repo |
||||||
|
|
||||||
|
import ( |
||||||
|
"errors" |
||||||
|
|
||||||
|
"code.gitea.io/gitea/models" |
||||||
|
"code.gitea.io/gitea/modules/context" |
||||||
|
api "code.gitea.io/gitea/modules/structs" |
||||||
|
) |
||||||
|
|
||||||
|
// GetIssueCommentReactions list reactions of a issue comment
|
||||||
|
func GetIssueCommentReactions(ctx *context.APIContext) { |
||||||
|
// swagger:operation GET /repos/{owner}/{repo}/issues/comments/{id}/reactions issue issueGetCommentReactions
|
||||||
|
// ---
|
||||||
|
// summary: Get a list reactions of a issue comment
|
||||||
|
// consumes:
|
||||||
|
// - application/json
|
||||||
|
// 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: id
|
||||||
|
// in: path
|
||||||
|
// description: id of the comment to edit
|
||||||
|
// type: integer
|
||||||
|
// format: int64
|
||||||
|
// required: true
|
||||||
|
// responses:
|
||||||
|
// "200":
|
||||||
|
// "$ref": "#/responses/ReactionResponseList"
|
||||||
|
comment, err := models.GetCommentByID(ctx.ParamsInt64(":id")) |
||||||
|
if err != nil { |
||||||
|
if models.IsErrCommentNotExist(err) { |
||||||
|
ctx.NotFound(err) |
||||||
|
} else { |
||||||
|
ctx.Error(500, "GetCommentByID", err) |
||||||
|
} |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
if !ctx.Repo.CanRead(models.UnitTypeIssues) && !ctx.User.IsAdmin { |
||||||
|
ctx.Error(403, "GetIssueCommentReactions", errors.New("no permission to get reactions")) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
reactions, err := models.FindCommentReactions(comment) |
||||||
|
if err != nil { |
||||||
|
ctx.Error(500, "FindIssueReactions", err) |
||||||
|
return |
||||||
|
} |
||||||
|
_, err = reactions.LoadUsers() |
||||||
|
if err != nil { |
||||||
|
ctx.Error(500, "ReactionList.LoadUsers()", err) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
var result []api.ReactionResponse |
||||||
|
for _, r := range reactions { |
||||||
|
result = append(result, api.ReactionResponse{ |
||||||
|
User: r.User.APIFormat(), |
||||||
|
Reaction: r.Type, |
||||||
|
Created: r.CreatedUnix.AsTime(), |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
ctx.JSON(200, result) |
||||||
|
} |
||||||
|
|
||||||
|
// PostIssueCommentReaction add a reaction to a comment of a issue
|
||||||
|
func PostIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOption) { |
||||||
|
// swagger:operation POST /repos/{owner}/{repo}/issues/comments/{id}/reactions issue issuePostCommentReaction
|
||||||
|
// ---
|
||||||
|
// summary: Add a reaction to a comment of a issue comment
|
||||||
|
// consumes:
|
||||||
|
// - application/json
|
||||||
|
// 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: id
|
||||||
|
// in: path
|
||||||
|
// description: id of the comment to edit
|
||||||
|
// type: integer
|
||||||
|
// format: int64
|
||||||
|
// required: true
|
||||||
|
// - name: content
|
||||||
|
// in: body
|
||||||
|
// schema:
|
||||||
|
// "$ref": "#/definitions/EditReactionOption"
|
||||||
|
// responses:
|
||||||
|
// "201":
|
||||||
|
// "$ref": "#/responses/ReactionResponse"
|
||||||
|
changeIssueCommentReaction(ctx, form, true) |
||||||
|
} |
||||||
|
|
||||||
|
// DeleteIssueCommentReaction list reactions of a issue comment
|
||||||
|
func DeleteIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOption) { |
||||||
|
// swagger:operation DELETE /repos/{owner}/{repo}/issues/comments/{id}/reactions issue issueDeleteCommentReaction
|
||||||
|
// ---
|
||||||
|
// summary: Remove a reaction from a comment of a issue comment
|
||||||
|
// consumes:
|
||||||
|
// - application/json
|
||||||
|
// 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: id
|
||||||
|
// in: path
|
||||||
|
// description: id of the comment to edit
|
||||||
|
// type: integer
|
||||||
|
// format: int64
|
||||||
|
// required: true
|
||||||
|
// - name: content
|
||||||
|
// in: body
|
||||||
|
// schema:
|
||||||
|
// "$ref": "#/definitions/EditReactionOption"
|
||||||
|
// responses:
|
||||||
|
// "200":
|
||||||
|
// "$ref": "#/responses/empty"
|
||||||
|
changeIssueCommentReaction(ctx, form, false) |
||||||
|
} |
||||||
|
|
||||||
|
func changeIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOption, isCreateType bool) { |
||||||
|
comment, err := models.GetCommentByID(ctx.ParamsInt64(":id")) |
||||||
|
if err != nil { |
||||||
|
if models.IsErrCommentNotExist(err) { |
||||||
|
ctx.NotFound(err) |
||||||
|
} else { |
||||||
|
ctx.Error(500, "GetCommentByID", err) |
||||||
|
} |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
err = comment.LoadIssue() |
||||||
|
if err != nil { |
||||||
|
ctx.Error(500, "comment.LoadIssue() failed", err) |
||||||
|
} |
||||||
|
|
||||||
|
if comment.Issue.IsLocked && !ctx.Repo.CanWrite(models.UnitTypeIssues) && !ctx.User.IsAdmin { |
||||||
|
ctx.Error(403, "ChangeIssueCommentReaction", errors.New("no permission to change reaction")) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
if isCreateType { |
||||||
|
// PostIssueCommentReaction part
|
||||||
|
reaction, err := models.CreateCommentReaction(ctx.User, comment.Issue, comment, form.Reaction) |
||||||
|
if err != nil { |
||||||
|
if models.IsErrForbiddenIssueReaction(err) { |
||||||
|
ctx.Error(403, err.Error(), err) |
||||||
|
} else { |
||||||
|
ctx.Error(500, "CreateCommentReaction", err) |
||||||
|
} |
||||||
|
return |
||||||
|
} |
||||||
|
_, err = reaction.LoadUser() |
||||||
|
if err != nil { |
||||||
|
ctx.Error(500, "Reaction.LoadUser()", err) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
ctx.JSON(201, api.ReactionResponse{ |
||||||
|
User: reaction.User.APIFormat(), |
||||||
|
Reaction: reaction.Type, |
||||||
|
Created: reaction.CreatedUnix.AsTime(), |
||||||
|
}) |
||||||
|
} else { |
||||||
|
// DeleteIssueCommentReaction part
|
||||||
|
err = models.DeleteCommentReaction(ctx.User, comment.Issue, comment, form.Reaction) |
||||||
|
if err != nil { |
||||||
|
ctx.Error(500, "DeleteCommentReaction", err) |
||||||
|
return |
||||||
|
} |
||||||
|
ctx.Status(200) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// GetIssueReactions list reactions of a issue comment
|
||||||
|
func GetIssueReactions(ctx *context.APIContext) { |
||||||
|
// swagger:operation GET /repos/{owner}/{repo}/issues/{index}/reactions issue issueGetIssueReactions
|
||||||
|
// ---
|
||||||
|
// summary: Get a list reactions of a issue
|
||||||
|
// consumes:
|
||||||
|
// - application/json
|
||||||
|
// 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 issue
|
||||||
|
// type: integer
|
||||||
|
// format: int64
|
||||||
|
// required: true
|
||||||
|
// responses:
|
||||||
|
// "200":
|
||||||
|
// "$ref": "#/responses/ReactionResponseList"
|
||||||
|
issue, err := models.GetIssueWithAttrsByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) |
||||||
|
if err != nil { |
||||||
|
if models.IsErrIssueNotExist(err) { |
||||||
|
ctx.NotFound() |
||||||
|
} else { |
||||||
|
ctx.Error(500, "GetIssueByIndex", err) |
||||||
|
} |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
if !ctx.Repo.CanRead(models.UnitTypeIssues) && !ctx.User.IsAdmin { |
||||||
|
ctx.Error(403, "GetIssueReactions", errors.New("no permission to get reactions")) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
reactions, err := models.FindIssueReactions(issue) |
||||||
|
if err != nil { |
||||||
|
ctx.Error(500, "FindIssueReactions", err) |
||||||
|
return |
||||||
|
} |
||||||
|
_, err = reactions.LoadUsers() |
||||||
|
if err != nil { |
||||||
|
ctx.Error(500, "ReactionList.LoadUsers()", err) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
var result []api.ReactionResponse |
||||||
|
for _, r := range reactions { |
||||||
|
result = append(result, api.ReactionResponse{ |
||||||
|
User: r.User.APIFormat(), |
||||||
|
Reaction: r.Type, |
||||||
|
Created: r.CreatedUnix.AsTime(), |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
ctx.JSON(200, result) |
||||||
|
} |
||||||
|
|
||||||
|
// PostIssueReaction add a reaction to a comment of a issue
|
||||||
|
func PostIssueReaction(ctx *context.APIContext, form api.EditReactionOption) { |
||||||
|
// swagger:operation POST /repos/{owner}/{repo}/issues/{index}/reactions issue issuePostIssueReaction
|
||||||
|
// ---
|
||||||
|
// summary: Add a reaction to a comment of a issue
|
||||||
|
// consumes:
|
||||||
|
// - application/json
|
||||||
|
// 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 issue
|
||||||
|
// type: integer
|
||||||
|
// format: int64
|
||||||
|
// required: true
|
||||||
|
// - name: content
|
||||||
|
// in: body
|
||||||
|
// schema:
|
||||||
|
// "$ref": "#/definitions/EditReactionOption"
|
||||||
|
// responses:
|
||||||
|
// "201":
|
||||||
|
// "$ref": "#/responses/ReactionResponse"
|
||||||
|
changeIssueReaction(ctx, form, true) |
||||||
|
} |
||||||
|
|
||||||
|
// DeleteIssueReaction list reactions of a issue comment
|
||||||
|
func DeleteIssueReaction(ctx *context.APIContext, form api.EditReactionOption) { |
||||||
|
// swagger:operation DELETE /repos/{owner}/{repo}/issues/{index}/reactions issue issueDeleteIssueReaction
|
||||||
|
// ---
|
||||||
|
// summary: Remove a reaction from a comment of a issue
|
||||||
|
// consumes:
|
||||||
|
// - application/json
|
||||||
|
// 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 issue
|
||||||
|
// type: integer
|
||||||
|
// format: int64
|
||||||
|
// required: true
|
||||||
|
// - name: content
|
||||||
|
// in: body
|
||||||
|
// schema:
|
||||||
|
// "$ref": "#/definitions/EditReactionOption"
|
||||||
|
// responses:
|
||||||
|
// "200":
|
||||||
|
// "$ref": "#/responses/empty"
|
||||||
|
changeIssueReaction(ctx, form, false) |
||||||
|
} |
||||||
|
|
||||||
|
func changeIssueReaction(ctx *context.APIContext, form api.EditReactionOption, isCreateType bool) { |
||||||
|
issue, err := models.GetIssueWithAttrsByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) |
||||||
|
if err != nil { |
||||||
|
if models.IsErrIssueNotExist(err) { |
||||||
|
ctx.NotFound() |
||||||
|
} else { |
||||||
|
ctx.Error(500, "GetIssueByIndex", err) |
||||||
|
} |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
if issue.IsLocked && !ctx.Repo.CanWrite(models.UnitTypeIssues) && !ctx.User.IsAdmin { |
||||||
|
ctx.Error(403, "ChangeIssueCommentReaction", errors.New("no permission to change reaction")) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
if isCreateType { |
||||||
|
// PostIssueReaction part
|
||||||
|
reaction, err := models.CreateIssueReaction(ctx.User, issue, form.Reaction) |
||||||
|
if err != nil { |
||||||
|
if models.IsErrForbiddenIssueReaction(err) { |
||||||
|
ctx.Error(403, err.Error(), err) |
||||||
|
} else { |
||||||
|
ctx.Error(500, "CreateCommentReaction", err) |
||||||
|
} |
||||||
|
return |
||||||
|
} |
||||||
|
_, err = reaction.LoadUser() |
||||||
|
if err != nil { |
||||||
|
ctx.Error(500, "Reaction.LoadUser()", err) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
ctx.JSON(201, api.ReactionResponse{ |
||||||
|
User: reaction.User.APIFormat(), |
||||||
|
Reaction: reaction.Type, |
||||||
|
Created: reaction.CreatedUnix.AsTime(), |
||||||
|
}) |
||||||
|
} else { |
||||||
|
// DeleteIssueReaction part
|
||||||
|
err = models.DeleteIssueReaction(ctx.User, issue, form.Reaction) |
||||||
|
if err != nil { |
||||||
|
ctx.Error(500, "DeleteIssueReaction", err) |
||||||
|
return |
||||||
|
} |
||||||
|
ctx.Status(200) |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue