You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

issue_reaction.go 12 kB

API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
5 years ago
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
5 years ago
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
5 years ago
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. // Copyright 2019 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package repo
  5. import (
  6. "errors"
  7. "net/http"
  8. "code.gitea.io/gitea/models"
  9. "code.gitea.io/gitea/modules/context"
  10. "code.gitea.io/gitea/modules/convert"
  11. api "code.gitea.io/gitea/modules/structs"
  12. "code.gitea.io/gitea/routers/api/v1/utils"
  13. )
  14. // GetIssueCommentReactions list reactions of a comment from an issue
  15. func GetIssueCommentReactions(ctx *context.APIContext) {
  16. // swagger:operation GET /repos/{owner}/{repo}/issues/comments/{id}/reactions issue issueGetCommentReactions
  17. // ---
  18. // summary: Get a list of reactions from a comment of an issue
  19. // consumes:
  20. // - application/json
  21. // produces:
  22. // - application/json
  23. // parameters:
  24. // - name: owner
  25. // in: path
  26. // description: owner of the repo
  27. // type: string
  28. // required: true
  29. // - name: repo
  30. // in: path
  31. // description: name of the repo
  32. // type: string
  33. // required: true
  34. // - name: id
  35. // in: path
  36. // description: id of the comment to edit
  37. // type: integer
  38. // format: int64
  39. // required: true
  40. // responses:
  41. // "200":
  42. // "$ref": "#/responses/ReactionList"
  43. // "403":
  44. // "$ref": "#/responses/forbidden"
  45. comment, err := models.GetCommentByID(ctx.ParamsInt64(":id"))
  46. if err != nil {
  47. if models.IsErrCommentNotExist(err) {
  48. ctx.NotFound(err)
  49. } else {
  50. ctx.Error(http.StatusInternalServerError, "GetCommentByID", err)
  51. }
  52. return
  53. }
  54. if !ctx.Repo.CanRead(models.UnitTypeIssues) {
  55. ctx.Error(http.StatusForbidden, "GetIssueCommentReactions", errors.New("no permission to get reactions"))
  56. return
  57. }
  58. reactions, err := models.FindCommentReactions(comment)
  59. if err != nil {
  60. ctx.Error(http.StatusInternalServerError, "FindIssueReactions", err)
  61. return
  62. }
  63. _, err = reactions.LoadUsers(ctx.Repo.Repository)
  64. if err != nil {
  65. ctx.Error(http.StatusInternalServerError, "ReactionList.LoadUsers()", err)
  66. return
  67. }
  68. var result []api.Reaction
  69. for _, r := range reactions {
  70. result = append(result, api.Reaction{
  71. User: convert.ToUser(r.User, ctx.IsSigned, false),
  72. Reaction: r.Type,
  73. Created: r.CreatedUnix.AsTime(),
  74. })
  75. }
  76. ctx.JSON(http.StatusOK, result)
  77. }
  78. // PostIssueCommentReaction add a reaction to a comment of an issue
  79. func PostIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOption) {
  80. // swagger:operation POST /repos/{owner}/{repo}/issues/comments/{id}/reactions issue issuePostCommentReaction
  81. // ---
  82. // summary: Add a reaction to a comment of an issue
  83. // consumes:
  84. // - application/json
  85. // produces:
  86. // - application/json
  87. // parameters:
  88. // - name: owner
  89. // in: path
  90. // description: owner of the repo
  91. // type: string
  92. // required: true
  93. // - name: repo
  94. // in: path
  95. // description: name of the repo
  96. // type: string
  97. // required: true
  98. // - name: id
  99. // in: path
  100. // description: id of the comment to edit
  101. // type: integer
  102. // format: int64
  103. // required: true
  104. // - name: content
  105. // in: body
  106. // schema:
  107. // "$ref": "#/definitions/EditReactionOption"
  108. // responses:
  109. // "200":
  110. // "$ref": "#/responses/Reaction"
  111. // "201":
  112. // "$ref": "#/responses/Reaction"
  113. // "403":
  114. // "$ref": "#/responses/forbidden"
  115. changeIssueCommentReaction(ctx, form, true)
  116. }
  117. // DeleteIssueCommentReaction remove a reaction from a comment of an issue
  118. func DeleteIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOption) {
  119. // swagger:operation DELETE /repos/{owner}/{repo}/issues/comments/{id}/reactions issue issueDeleteCommentReaction
  120. // ---
  121. // summary: Remove a reaction from a comment of an issue
  122. // consumes:
  123. // - application/json
  124. // produces:
  125. // - application/json
  126. // parameters:
  127. // - name: owner
  128. // in: path
  129. // description: owner of the repo
  130. // type: string
  131. // required: true
  132. // - name: repo
  133. // in: path
  134. // description: name of the repo
  135. // type: string
  136. // required: true
  137. // - name: id
  138. // in: path
  139. // description: id of the comment to edit
  140. // type: integer
  141. // format: int64
  142. // required: true
  143. // - name: content
  144. // in: body
  145. // schema:
  146. // "$ref": "#/definitions/EditReactionOption"
  147. // responses:
  148. // "200":
  149. // "$ref": "#/responses/empty"
  150. // "403":
  151. // "$ref": "#/responses/forbidden"
  152. changeIssueCommentReaction(ctx, form, false)
  153. }
  154. func changeIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOption, isCreateType bool) {
  155. comment, err := models.GetCommentByID(ctx.ParamsInt64(":id"))
  156. if err != nil {
  157. if models.IsErrCommentNotExist(err) {
  158. ctx.NotFound(err)
  159. } else {
  160. ctx.Error(http.StatusInternalServerError, "GetCommentByID", err)
  161. }
  162. return
  163. }
  164. err = comment.LoadIssue()
  165. if err != nil {
  166. ctx.Error(http.StatusInternalServerError, "comment.LoadIssue() failed", err)
  167. }
  168. if comment.Issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(comment.Issue.IsPull) {
  169. ctx.Error(http.StatusForbidden, "ChangeIssueCommentReaction", errors.New("no permission to change reaction"))
  170. return
  171. }
  172. if isCreateType {
  173. // PostIssueCommentReaction part
  174. reaction, err := models.CreateCommentReaction(ctx.User, comment.Issue, comment, form.Reaction)
  175. if err != nil {
  176. if models.IsErrForbiddenIssueReaction(err) {
  177. ctx.Error(http.StatusForbidden, err.Error(), err)
  178. } else if models.IsErrReactionAlreadyExist(err) {
  179. ctx.JSON(http.StatusOK, api.Reaction{
  180. User: convert.ToUser(ctx.User, true, true),
  181. Reaction: reaction.Type,
  182. Created: reaction.CreatedUnix.AsTime(),
  183. })
  184. } else {
  185. ctx.Error(http.StatusInternalServerError, "CreateCommentReaction", err)
  186. }
  187. return
  188. }
  189. ctx.JSON(http.StatusCreated, api.Reaction{
  190. User: convert.ToUser(ctx.User, true, true),
  191. Reaction: reaction.Type,
  192. Created: reaction.CreatedUnix.AsTime(),
  193. })
  194. } else {
  195. // DeleteIssueCommentReaction part
  196. err = models.DeleteCommentReaction(ctx.User, comment.Issue, comment, form.Reaction)
  197. if err != nil {
  198. ctx.Error(http.StatusInternalServerError, "DeleteCommentReaction", err)
  199. return
  200. }
  201. //ToDo respond 204
  202. ctx.Status(http.StatusOK)
  203. }
  204. }
  205. // GetIssueReactions list reactions of an issue
  206. func GetIssueReactions(ctx *context.APIContext) {
  207. // swagger:operation GET /repos/{owner}/{repo}/issues/{index}/reactions issue issueGetIssueReactions
  208. // ---
  209. // summary: Get a list reactions of an issue
  210. // consumes:
  211. // - application/json
  212. // produces:
  213. // - application/json
  214. // parameters:
  215. // - name: owner
  216. // in: path
  217. // description: owner of the repo
  218. // type: string
  219. // required: true
  220. // - name: repo
  221. // in: path
  222. // description: name of the repo
  223. // type: string
  224. // required: true
  225. // - name: index
  226. // in: path
  227. // description: index of the issue
  228. // type: integer
  229. // format: int64
  230. // required: true
  231. // - name: page
  232. // in: query
  233. // description: page number of results to return (1-based)
  234. // type: integer
  235. // - name: limit
  236. // in: query
  237. // description: page size of results
  238. // type: integer
  239. // responses:
  240. // "200":
  241. // "$ref": "#/responses/ReactionList"
  242. // "403":
  243. // "$ref": "#/responses/forbidden"
  244. issue, err := models.GetIssueWithAttrsByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
  245. if err != nil {
  246. if models.IsErrIssueNotExist(err) {
  247. ctx.NotFound()
  248. } else {
  249. ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err)
  250. }
  251. return
  252. }
  253. if !ctx.Repo.CanRead(models.UnitTypeIssues) {
  254. ctx.Error(http.StatusForbidden, "GetIssueReactions", errors.New("no permission to get reactions"))
  255. return
  256. }
  257. reactions, err := models.FindIssueReactions(issue, utils.GetListOptions(ctx))
  258. if err != nil {
  259. ctx.Error(http.StatusInternalServerError, "FindIssueReactions", err)
  260. return
  261. }
  262. _, err = reactions.LoadUsers(ctx.Repo.Repository)
  263. if err != nil {
  264. ctx.Error(http.StatusInternalServerError, "ReactionList.LoadUsers()", err)
  265. return
  266. }
  267. var result []api.Reaction
  268. for _, r := range reactions {
  269. result = append(result, api.Reaction{
  270. User: convert.ToUser(r.User, ctx.IsSigned, false),
  271. Reaction: r.Type,
  272. Created: r.CreatedUnix.AsTime(),
  273. })
  274. }
  275. ctx.JSON(http.StatusOK, result)
  276. }
  277. // PostIssueReaction add a reaction to an issue
  278. func PostIssueReaction(ctx *context.APIContext, form api.EditReactionOption) {
  279. // swagger:operation POST /repos/{owner}/{repo}/issues/{index}/reactions issue issuePostIssueReaction
  280. // ---
  281. // summary: Add a reaction to an issue
  282. // consumes:
  283. // - application/json
  284. // produces:
  285. // - application/json
  286. // parameters:
  287. // - name: owner
  288. // in: path
  289. // description: owner of the repo
  290. // type: string
  291. // required: true
  292. // - name: repo
  293. // in: path
  294. // description: name of the repo
  295. // type: string
  296. // required: true
  297. // - name: index
  298. // in: path
  299. // description: index of the issue
  300. // type: integer
  301. // format: int64
  302. // required: true
  303. // - name: content
  304. // in: body
  305. // schema:
  306. // "$ref": "#/definitions/EditReactionOption"
  307. // responses:
  308. // "200":
  309. // "$ref": "#/responses/Reaction"
  310. // "201":
  311. // "$ref": "#/responses/Reaction"
  312. // "403":
  313. // "$ref": "#/responses/forbidden"
  314. changeIssueReaction(ctx, form, true)
  315. }
  316. // DeleteIssueReaction remove a reaction from an issue
  317. func DeleteIssueReaction(ctx *context.APIContext, form api.EditReactionOption) {
  318. // swagger:operation DELETE /repos/{owner}/{repo}/issues/{index}/reactions issue issueDeleteIssueReaction
  319. // ---
  320. // summary: Remove a reaction from an issue
  321. // consumes:
  322. // - application/json
  323. // produces:
  324. // - application/json
  325. // parameters:
  326. // - name: owner
  327. // in: path
  328. // description: owner of the repo
  329. // type: string
  330. // required: true
  331. // - name: repo
  332. // in: path
  333. // description: name of the repo
  334. // type: string
  335. // required: true
  336. // - name: index
  337. // in: path
  338. // description: index of the issue
  339. // type: integer
  340. // format: int64
  341. // required: true
  342. // - name: content
  343. // in: body
  344. // schema:
  345. // "$ref": "#/definitions/EditReactionOption"
  346. // responses:
  347. // "200":
  348. // "$ref": "#/responses/empty"
  349. // "403":
  350. // "$ref": "#/responses/forbidden"
  351. changeIssueReaction(ctx, form, false)
  352. }
  353. func changeIssueReaction(ctx *context.APIContext, form api.EditReactionOption, isCreateType bool) {
  354. issue, err := models.GetIssueWithAttrsByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
  355. if err != nil {
  356. if models.IsErrIssueNotExist(err) {
  357. ctx.NotFound()
  358. } else {
  359. ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err)
  360. }
  361. return
  362. }
  363. if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) {
  364. ctx.Error(http.StatusForbidden, "ChangeIssueCommentReaction", errors.New("no permission to change reaction"))
  365. return
  366. }
  367. if isCreateType {
  368. // PostIssueReaction part
  369. reaction, err := models.CreateIssueReaction(ctx.User, issue, form.Reaction)
  370. if err != nil {
  371. if models.IsErrForbiddenIssueReaction(err) {
  372. ctx.Error(http.StatusForbidden, err.Error(), err)
  373. } else if models.IsErrReactionAlreadyExist(err) {
  374. ctx.JSON(http.StatusOK, api.Reaction{
  375. User: convert.ToUser(ctx.User, true, true),
  376. Reaction: reaction.Type,
  377. Created: reaction.CreatedUnix.AsTime(),
  378. })
  379. } else {
  380. ctx.Error(http.StatusInternalServerError, "CreateCommentReaction", err)
  381. }
  382. return
  383. }
  384. ctx.JSON(http.StatusCreated, api.Reaction{
  385. User: convert.ToUser(ctx.User, true, true),
  386. Reaction: reaction.Type,
  387. Created: reaction.CreatedUnix.AsTime(),
  388. })
  389. } else {
  390. // DeleteIssueReaction part
  391. err = models.DeleteIssueReaction(ctx.User, issue, form.Reaction)
  392. if err != nil {
  393. ctx.Error(http.StatusInternalServerError, "DeleteIssueReaction", err)
  394. return
  395. }
  396. //ToDo respond 204
  397. ctx.Status(http.StatusOK)
  398. }
  399. }