summaryrefslogtreecommitdiffstats
path: root/routers/api/v1/repo/issue_reaction.go
diff options
context:
space:
mode:
authorDaniel Baumann <daniel@debian.org>2024-10-18 20:33:49 +0200
committerDaniel Baumann <daniel@debian.org>2024-10-18 20:33:49 +0200
commitdd136858f1ea40ad3c94191d647487fa4f31926c (patch)
tree58fec94a7b2a12510c9664b21793f1ed560c6518 /routers/api/v1/repo/issue_reaction.go
parentInitial commit. (diff)
downloadforgejo-upstream/9.0.0.tar.xz
forgejo-upstream/9.0.0.zip
Adding upstream version 9.0.0.HEADupstream/9.0.0upstreamdebian
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to 'routers/api/v1/repo/issue_reaction.go')
-rw-r--r--routers/api/v1/repo/issue_reaction.go424
1 files changed, 424 insertions, 0 deletions
diff --git a/routers/api/v1/repo/issue_reaction.go b/routers/api/v1/repo/issue_reaction.go
new file mode 100644
index 0000000..c395255
--- /dev/null
+++ b/routers/api/v1/repo/issue_reaction.go
@@ -0,0 +1,424 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package repo
+
+import (
+ "errors"
+ "net/http"
+
+ issues_model "code.gitea.io/gitea/models/issues"
+ user_model "code.gitea.io/gitea/models/user"
+ api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/routers/api/v1/utils"
+ "code.gitea.io/gitea/services/context"
+ "code.gitea.io/gitea/services/convert"
+ issue_service "code.gitea.io/gitea/services/issue"
+)
+
+// GetIssueCommentReactions list reactions of a comment from an issue
+func GetIssueCommentReactions(ctx *context.APIContext) {
+ // swagger:operation GET /repos/{owner}/{repo}/issues/comments/{id}/reactions issue issueGetCommentReactions
+ // ---
+ // summary: Get a list of reactions from a comment of an 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: id
+ // in: path
+ // description: id of the comment to edit
+ // type: integer
+ // format: int64
+ // required: true
+ // responses:
+ // "200":
+ // "$ref": "#/responses/ReactionList"
+ // "403":
+ // "$ref": "#/responses/forbidden"
+ // "404":
+ // "$ref": "#/responses/notFound"
+
+ comment := ctx.Comment
+
+ reactions, _, err := issues_model.FindCommentReactions(ctx, comment.IssueID, comment.ID)
+ if err != nil {
+ ctx.Error(http.StatusInternalServerError, "FindCommentReactions", err)
+ return
+ }
+ _, err = reactions.LoadUsers(ctx, ctx.Repo.Repository)
+ if err != nil {
+ ctx.Error(http.StatusInternalServerError, "ReactionList.LoadUsers()", err)
+ return
+ }
+
+ var result []api.Reaction
+ for _, r := range reactions {
+ result = append(result, api.Reaction{
+ User: convert.ToUser(ctx, r.User, ctx.Doer),
+ Reaction: r.Type,
+ Created: r.CreatedUnix.AsTime(),
+ })
+ }
+
+ ctx.JSON(http.StatusOK, result)
+}
+
+// PostIssueCommentReaction add a reaction to a comment of an issue
+func PostIssueCommentReaction(ctx *context.APIContext) {
+ // swagger:operation POST /repos/{owner}/{repo}/issues/comments/{id}/reactions issue issuePostCommentReaction
+ // ---
+ // summary: Add a reaction to a comment of an 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: 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/Reaction"
+ // "201":
+ // "$ref": "#/responses/Reaction"
+ // "403":
+ // "$ref": "#/responses/forbidden"
+ // "404":
+ // "$ref": "#/responses/notFound"
+
+ form := web.GetForm(ctx).(*api.EditReactionOption)
+
+ changeIssueCommentReaction(ctx, *form, true)
+}
+
+// DeleteIssueCommentReaction remove a reaction from a comment of an issue
+func DeleteIssueCommentReaction(ctx *context.APIContext) {
+ // swagger:operation DELETE /repos/{owner}/{repo}/issues/comments/{id}/reactions issue issueDeleteCommentReaction
+ // ---
+ // summary: Remove a reaction from a comment of an 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: 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"
+ // "403":
+ // "$ref": "#/responses/forbidden"
+ // "404":
+ // "$ref": "#/responses/notFound"
+
+ form := web.GetForm(ctx).(*api.EditReactionOption)
+
+ changeIssueCommentReaction(ctx, *form, false)
+}
+
+func changeIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOption, isCreateType bool) {
+ comment := ctx.Comment
+
+ if comment.Issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(comment.Issue.IsPull) {
+ ctx.Error(http.StatusForbidden, "ChangeIssueCommentReaction", errors.New("no permission to change reaction"))
+ return
+ }
+
+ if isCreateType {
+ // PostIssueCommentReaction part
+ reaction, err := issue_service.CreateCommentReaction(ctx, ctx.Doer, comment.Issue, comment, form.Reaction)
+ if err != nil {
+ if issues_model.IsErrForbiddenIssueReaction(err) || errors.Is(err, user_model.ErrBlockedByUser) {
+ ctx.Error(http.StatusForbidden, err.Error(), err)
+ } else if issues_model.IsErrReactionAlreadyExist(err) {
+ ctx.JSON(http.StatusOK, api.Reaction{
+ User: convert.ToUser(ctx, ctx.Doer, ctx.Doer),
+ Reaction: reaction.Type,
+ Created: reaction.CreatedUnix.AsTime(),
+ })
+ } else {
+ ctx.Error(http.StatusInternalServerError, "CreateCommentReaction", err)
+ }
+ return
+ }
+
+ ctx.JSON(http.StatusCreated, api.Reaction{
+ User: convert.ToUser(ctx, ctx.Doer, ctx.Doer),
+ Reaction: reaction.Type,
+ Created: reaction.CreatedUnix.AsTime(),
+ })
+ } else {
+ // DeleteIssueCommentReaction part
+ err := issues_model.DeleteCommentReaction(ctx, ctx.Doer.ID, comment.Issue.ID, comment.ID, form.Reaction)
+ if err != nil {
+ ctx.Error(http.StatusInternalServerError, "DeleteCommentReaction", err)
+ return
+ }
+ // ToDo respond 204
+ ctx.Status(http.StatusOK)
+ }
+}
+
+// GetIssueReactions list reactions of an issue
+func GetIssueReactions(ctx *context.APIContext) {
+ // swagger:operation GET /repos/{owner}/{repo}/issues/{index}/reactions issue issueGetIssueReactions
+ // ---
+ // summary: Get a list reactions of an 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: page
+ // in: query
+ // description: page number of results to return (1-based)
+ // type: integer
+ // - name: limit
+ // in: query
+ // description: page size of results
+ // type: integer
+ // responses:
+ // "200":
+ // "$ref": "#/responses/ReactionList"
+ // "403":
+ // "$ref": "#/responses/forbidden"
+ // "404":
+ // "$ref": "#/responses/notFound"
+
+ issue, err := issues_model.GetIssueWithAttrsByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
+ if err != nil {
+ if issues_model.IsErrIssueNotExist(err) {
+ ctx.NotFound()
+ } else {
+ ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err)
+ }
+ return
+ }
+
+ if !ctx.Repo.CanReadIssuesOrPulls(issue.IsPull) {
+ ctx.Error(http.StatusForbidden, "GetIssueReactions", errors.New("no permission to get reactions"))
+ return
+ }
+
+ reactions, count, err := issues_model.FindIssueReactions(ctx, issue.ID, utils.GetListOptions(ctx))
+ if err != nil {
+ ctx.Error(http.StatusInternalServerError, "FindIssueReactions", err)
+ return
+ }
+ _, err = reactions.LoadUsers(ctx, ctx.Repo.Repository)
+ if err != nil {
+ ctx.Error(http.StatusInternalServerError, "ReactionList.LoadUsers()", err)
+ return
+ }
+
+ var result []api.Reaction
+ for _, r := range reactions {
+ result = append(result, api.Reaction{
+ User: convert.ToUser(ctx, r.User, ctx.Doer),
+ Reaction: r.Type,
+ Created: r.CreatedUnix.AsTime(),
+ })
+ }
+
+ ctx.SetTotalCountHeader(count)
+ ctx.JSON(http.StatusOK, result)
+}
+
+// PostIssueReaction add a reaction to an issue
+func PostIssueReaction(ctx *context.APIContext) {
+ // swagger:operation POST /repos/{owner}/{repo}/issues/{index}/reactions issue issuePostIssueReaction
+ // ---
+ // summary: Add a reaction to an 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/Reaction"
+ // "201":
+ // "$ref": "#/responses/Reaction"
+ // "403":
+ // "$ref": "#/responses/forbidden"
+ // "404":
+ // "$ref": "#/responses/notFound"
+ form := web.GetForm(ctx).(*api.EditReactionOption)
+ changeIssueReaction(ctx, *form, true)
+}
+
+// DeleteIssueReaction remove a reaction from an issue
+func DeleteIssueReaction(ctx *context.APIContext) {
+ // swagger:operation DELETE /repos/{owner}/{repo}/issues/{index}/reactions issue issueDeleteIssueReaction
+ // ---
+ // summary: Remove a reaction from an 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"
+ // "403":
+ // "$ref": "#/responses/forbidden"
+ // "404":
+ // "$ref": "#/responses/notFound"
+ form := web.GetForm(ctx).(*api.EditReactionOption)
+ changeIssueReaction(ctx, *form, false)
+}
+
+func changeIssueReaction(ctx *context.APIContext, form api.EditReactionOption, isCreateType bool) {
+ issue, err := issues_model.GetIssueWithAttrsByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
+ if err != nil {
+ if issues_model.IsErrIssueNotExist(err) {
+ ctx.NotFound()
+ } else {
+ ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err)
+ }
+ return
+ }
+
+ if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) {
+ ctx.Error(http.StatusForbidden, "ChangeIssueCommentReaction", errors.New("no permission to change reaction"))
+ return
+ }
+
+ if isCreateType {
+ // PostIssueReaction part
+ reaction, err := issue_service.CreateIssueReaction(ctx, ctx.Doer, issue, form.Reaction)
+ if err != nil {
+ if issues_model.IsErrForbiddenIssueReaction(err) || errors.Is(err, user_model.ErrBlockedByUser) {
+ ctx.Error(http.StatusForbidden, err.Error(), err)
+ } else if issues_model.IsErrReactionAlreadyExist(err) {
+ ctx.JSON(http.StatusOK, api.Reaction{
+ User: convert.ToUser(ctx, ctx.Doer, ctx.Doer),
+ Reaction: reaction.Type,
+ Created: reaction.CreatedUnix.AsTime(),
+ })
+ } else {
+ ctx.Error(http.StatusInternalServerError, "CreateCommentReaction", err)
+ }
+ return
+ }
+
+ ctx.JSON(http.StatusCreated, api.Reaction{
+ User: convert.ToUser(ctx, ctx.Doer, ctx.Doer),
+ Reaction: reaction.Type,
+ Created: reaction.CreatedUnix.AsTime(),
+ })
+ } else {
+ // DeleteIssueReaction part
+ err = issues_model.DeleteIssueReaction(ctx, ctx.Doer.ID, issue.ID, form.Reaction)
+ if err != nil {
+ ctx.Error(http.StatusInternalServerError, "DeleteIssueReaction", err)
+ return
+ }
+ // ToDo respond 204
+ ctx.Status(http.StatusOK)
+ }
+}