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_comment.go 10 kB

9 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. // Copyright 2015 The Gogs 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. "time"
  8. "code.gitea.io/gitea/models"
  9. "code.gitea.io/gitea/modules/context"
  10. "code.gitea.io/gitea/modules/notification"
  11. api "code.gitea.io/gitea/modules/structs"
  12. )
  13. // ListIssueComments list all the comments of an issue
  14. func ListIssueComments(ctx *context.APIContext) {
  15. // swagger:operation GET /repos/{owner}/{repo}/issues/{index}/comments issue issueGetComments
  16. // ---
  17. // summary: List all comments on an issue
  18. // produces:
  19. // - application/json
  20. // parameters:
  21. // - name: owner
  22. // in: path
  23. // description: owner of the repo
  24. // type: string
  25. // required: true
  26. // - name: repo
  27. // in: path
  28. // description: name of the repo
  29. // type: string
  30. // required: true
  31. // - name: index
  32. // in: path
  33. // description: index of the issue
  34. // type: integer
  35. // format: int64
  36. // required: true
  37. // - name: since
  38. // in: query
  39. // description: if provided, only comments updated since the specified time are returned.
  40. // type: string
  41. // responses:
  42. // "200":
  43. // "$ref": "#/responses/CommentList"
  44. var since time.Time
  45. if len(ctx.Query("since")) > 0 {
  46. since, _ = time.Parse(time.RFC3339, ctx.Query("since"))
  47. }
  48. // comments,err:=models.GetCommentsByIssueIDSince(, since)
  49. issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
  50. if err != nil {
  51. ctx.Error(500, "GetRawIssueByIndex", err)
  52. return
  53. }
  54. issue.Repo = ctx.Repo.Repository
  55. comments, err := models.FindComments(models.FindCommentsOptions{
  56. IssueID: issue.ID,
  57. Since: since.Unix(),
  58. Type: models.CommentTypeComment,
  59. })
  60. if err != nil {
  61. ctx.Error(500, "FindComments", err)
  62. return
  63. }
  64. if err := models.CommentList(comments).LoadPosters(); err != nil {
  65. ctx.Error(500, "LoadPosters", err)
  66. return
  67. }
  68. apiComments := make([]*api.Comment, len(comments))
  69. for i, comment := range comments {
  70. comment.Issue = issue
  71. apiComments[i] = comments[i].APIFormat()
  72. }
  73. ctx.JSON(200, &apiComments)
  74. }
  75. // ListRepoIssueComments returns all issue-comments for a repo
  76. func ListRepoIssueComments(ctx *context.APIContext) {
  77. // swagger:operation GET /repos/{owner}/{repo}/issues/comments issue issueGetRepoComments
  78. // ---
  79. // summary: List all comments in a repository
  80. // produces:
  81. // - application/json
  82. // parameters:
  83. // - name: owner
  84. // in: path
  85. // description: owner of the repo
  86. // type: string
  87. // required: true
  88. // - name: repo
  89. // in: path
  90. // description: name of the repo
  91. // type: string
  92. // required: true
  93. // - name: since
  94. // in: query
  95. // description: if provided, only comments updated since the provided time are returned.
  96. // type: string
  97. // responses:
  98. // "200":
  99. // "$ref": "#/responses/CommentList"
  100. var since time.Time
  101. if len(ctx.Query("since")) > 0 {
  102. since, _ = time.Parse(time.RFC3339, ctx.Query("since"))
  103. }
  104. comments, err := models.FindComments(models.FindCommentsOptions{
  105. RepoID: ctx.Repo.Repository.ID,
  106. Since: since.Unix(),
  107. Type: models.CommentTypeComment,
  108. })
  109. if err != nil {
  110. ctx.Error(500, "FindComments", err)
  111. return
  112. }
  113. if err = models.CommentList(comments).LoadPosters(); err != nil {
  114. ctx.Error(500, "LoadPosters", err)
  115. return
  116. }
  117. apiComments := make([]*api.Comment, len(comments))
  118. if err := models.CommentList(comments).LoadIssues(); err != nil {
  119. ctx.Error(500, "LoadIssues", err)
  120. return
  121. }
  122. if err := models.CommentList(comments).LoadPosters(); err != nil {
  123. ctx.Error(500, "LoadPosters", err)
  124. return
  125. }
  126. if _, err := models.CommentList(comments).Issues().LoadRepositories(); err != nil {
  127. ctx.Error(500, "LoadRepositories", err)
  128. return
  129. }
  130. for i := range comments {
  131. apiComments[i] = comments[i].APIFormat()
  132. }
  133. ctx.JSON(200, &apiComments)
  134. }
  135. // CreateIssueComment create a comment for an issue
  136. func CreateIssueComment(ctx *context.APIContext, form api.CreateIssueCommentOption) {
  137. // swagger:operation POST /repos/{owner}/{repo}/issues/{index}/comments issue issueCreateComment
  138. // ---
  139. // summary: Add a comment to an issue
  140. // consumes:
  141. // - application/json
  142. // produces:
  143. // - application/json
  144. // parameters:
  145. // - name: owner
  146. // in: path
  147. // description: owner of the repo
  148. // type: string
  149. // required: true
  150. // - name: repo
  151. // in: path
  152. // description: name of the repo
  153. // type: string
  154. // required: true
  155. // - name: index
  156. // in: path
  157. // description: index of the issue
  158. // type: integer
  159. // format: int64
  160. // required: true
  161. // - name: body
  162. // in: body
  163. // schema:
  164. // "$ref": "#/definitions/CreateIssueCommentOption"
  165. // responses:
  166. // "201":
  167. // "$ref": "#/responses/Comment"
  168. issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
  169. if err != nil {
  170. ctx.Error(500, "GetIssueByIndex", err)
  171. return
  172. }
  173. if issue.IsLocked && !ctx.Repo.CanWrite(models.UnitTypeIssues) && !ctx.User.IsAdmin {
  174. ctx.Error(403, "CreateIssueComment", errors.New(ctx.Tr("repo.issues.comment_on_locked")))
  175. return
  176. }
  177. comment, err := models.CreateIssueComment(ctx.User, ctx.Repo.Repository, issue, form.Body, nil)
  178. if err != nil {
  179. ctx.Error(500, "CreateIssueComment", err)
  180. return
  181. }
  182. notification.NotifyCreateIssueComment(ctx.User, ctx.Repo.Repository, issue, comment)
  183. ctx.JSON(201, comment.APIFormat())
  184. }
  185. // EditIssueComment modify a comment of an issue
  186. func EditIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption) {
  187. // swagger:operation PATCH /repos/{owner}/{repo}/issues/comments/{id} issue issueEditComment
  188. // ---
  189. // summary: Edit a comment
  190. // consumes:
  191. // - application/json
  192. // produces:
  193. // - application/json
  194. // parameters:
  195. // - name: owner
  196. // in: path
  197. // description: owner of the repo
  198. // type: string
  199. // required: true
  200. // - name: repo
  201. // in: path
  202. // description: name of the repo
  203. // type: string
  204. // required: true
  205. // - name: id
  206. // in: path
  207. // description: id of the comment to edit
  208. // type: integer
  209. // format: int64
  210. // required: true
  211. // - name: body
  212. // in: body
  213. // schema:
  214. // "$ref": "#/definitions/EditIssueCommentOption"
  215. // responses:
  216. // "200":
  217. // "$ref": "#/responses/Comment"
  218. editIssueComment(ctx, form)
  219. }
  220. // EditIssueCommentDeprecated modify a comment of an issue
  221. func EditIssueCommentDeprecated(ctx *context.APIContext, form api.EditIssueCommentOption) {
  222. // swagger:operation PATCH /repos/{owner}/{repo}/issues/{index}/comments/{id} issue issueEditCommentDeprecated
  223. // ---
  224. // summary: Edit a comment
  225. // deprecated: true
  226. // consumes:
  227. // - application/json
  228. // produces:
  229. // - application/json
  230. // parameters:
  231. // - name: owner
  232. // in: path
  233. // description: owner of the repo
  234. // type: string
  235. // required: true
  236. // - name: repo
  237. // in: path
  238. // description: name of the repo
  239. // type: string
  240. // required: true
  241. // - name: index
  242. // in: path
  243. // description: this parameter is ignored
  244. // type: integer
  245. // required: true
  246. // - name: id
  247. // in: path
  248. // description: id of the comment to edit
  249. // type: integer
  250. // format: int64
  251. // required: true
  252. // - name: body
  253. // in: body
  254. // schema:
  255. // "$ref": "#/definitions/EditIssueCommentOption"
  256. // responses:
  257. // "200":
  258. // "$ref": "#/responses/Comment"
  259. editIssueComment(ctx, form)
  260. }
  261. func editIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption) {
  262. comment, err := models.GetCommentByID(ctx.ParamsInt64(":id"))
  263. if err != nil {
  264. if models.IsErrCommentNotExist(err) {
  265. ctx.NotFound(err)
  266. } else {
  267. ctx.Error(500, "GetCommentByID", err)
  268. }
  269. return
  270. }
  271. if !ctx.IsSigned || (ctx.User.ID != comment.PosterID && !ctx.Repo.IsAdmin()) {
  272. ctx.Status(403)
  273. return
  274. } else if comment.Type != models.CommentTypeComment {
  275. ctx.Status(204)
  276. return
  277. }
  278. oldContent := comment.Content
  279. comment.Content = form.Body
  280. if err := models.UpdateComment(ctx.User, comment, oldContent); err != nil {
  281. ctx.Error(500, "UpdateComment", err)
  282. return
  283. }
  284. notification.NotifyUpdateComment(ctx.User, comment, oldContent)
  285. ctx.JSON(200, comment.APIFormat())
  286. }
  287. // DeleteIssueComment delete a comment from an issue
  288. func DeleteIssueComment(ctx *context.APIContext) {
  289. // swagger:operation DELETE /repos/{owner}/{repo}/issues/comments/{id} issue issueDeleteComment
  290. // ---
  291. // summary: Delete a comment
  292. // parameters:
  293. // - name: owner
  294. // in: path
  295. // description: owner of the repo
  296. // type: string
  297. // required: true
  298. // - name: repo
  299. // in: path
  300. // description: name of the repo
  301. // type: string
  302. // required: true
  303. // - name: id
  304. // in: path
  305. // description: id of comment to delete
  306. // type: integer
  307. // format: int64
  308. // required: true
  309. // responses:
  310. // "204":
  311. // "$ref": "#/responses/empty"
  312. deleteIssueComment(ctx)
  313. }
  314. // DeleteIssueCommentDeprecated delete a comment from an issue
  315. func DeleteIssueCommentDeprecated(ctx *context.APIContext) {
  316. // swagger:operation DELETE /repos/{owner}/{repo}/issues/{index}/comments/{id} issue issueDeleteCommentDeprecated
  317. // ---
  318. // summary: Delete a comment
  319. // deprecated: true
  320. // parameters:
  321. // - name: owner
  322. // in: path
  323. // description: owner of the repo
  324. // type: string
  325. // required: true
  326. // - name: repo
  327. // in: path
  328. // description: name of the repo
  329. // type: string
  330. // required: true
  331. // - name: index
  332. // in: path
  333. // description: this parameter is ignored
  334. // type: integer
  335. // required: true
  336. // - name: id
  337. // in: path
  338. // description: id of comment to delete
  339. // type: integer
  340. // format: int64
  341. // required: true
  342. // responses:
  343. // "204":
  344. // "$ref": "#/responses/empty"
  345. deleteIssueComment(ctx)
  346. }
  347. func deleteIssueComment(ctx *context.APIContext) {
  348. comment, err := models.GetCommentByID(ctx.ParamsInt64(":id"))
  349. if err != nil {
  350. if models.IsErrCommentNotExist(err) {
  351. ctx.NotFound(err)
  352. } else {
  353. ctx.Error(500, "GetCommentByID", err)
  354. }
  355. return
  356. }
  357. if !ctx.IsSigned || (ctx.User.ID != comment.PosterID && !ctx.Repo.IsAdmin()) {
  358. ctx.Status(403)
  359. return
  360. } else if comment.Type != models.CommentTypeComment {
  361. ctx.Status(204)
  362. return
  363. }
  364. if err = models.DeleteComment(ctx.User, comment); err != nil {
  365. ctx.Error(500, "DeleteCommentByID", err)
  366. return
  367. }
  368. notification.NotifyDeleteComment(ctx.User, comment)
  369. ctx.Status(204)
  370. }