gitea源码

issue_stopwatch.go 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. // Copyright 2019 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package repo
  4. import (
  5. "net/http"
  6. issues_model "code.gitea.io/gitea/models/issues"
  7. "code.gitea.io/gitea/routers/api/v1/utils"
  8. "code.gitea.io/gitea/services/context"
  9. "code.gitea.io/gitea/services/convert"
  10. )
  11. // StartIssueStopwatch creates a stopwatch for the given issue.
  12. func StartIssueStopwatch(ctx *context.APIContext) {
  13. // swagger:operation POST /repos/{owner}/{repo}/issues/{index}/stopwatch/start issue issueStartStopWatch
  14. // ---
  15. // summary: Start stopwatch on an issue.
  16. // consumes:
  17. // - application/json
  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 to create the stopwatch on
  34. // type: integer
  35. // format: int64
  36. // required: true
  37. // responses:
  38. // "201":
  39. // "$ref": "#/responses/empty"
  40. // "403":
  41. // description: Not repo writer, user does not have rights to toggle stopwatch
  42. // "404":
  43. // "$ref": "#/responses/notFound"
  44. // "409":
  45. // description: Cannot start a stopwatch again if it already exists
  46. issue := prepareIssueForStopwatch(ctx)
  47. if ctx.Written() {
  48. return
  49. }
  50. if ok, err := issues_model.CreateIssueStopwatch(ctx, ctx.Doer, issue); err != nil {
  51. ctx.APIErrorInternal(err)
  52. return
  53. } else if !ok {
  54. ctx.APIError(http.StatusConflict, "cannot start a stopwatch again if it already exists")
  55. return
  56. }
  57. ctx.Status(http.StatusCreated)
  58. }
  59. // StopIssueStopwatch stops a stopwatch for the given issue.
  60. func StopIssueStopwatch(ctx *context.APIContext) {
  61. // swagger:operation POST /repos/{owner}/{repo}/issues/{index}/stopwatch/stop issue issueStopStopWatch
  62. // ---
  63. // summary: Stop an issue's existing stopwatch.
  64. // consumes:
  65. // - application/json
  66. // produces:
  67. // - application/json
  68. // parameters:
  69. // - name: owner
  70. // in: path
  71. // description: owner of the repo
  72. // type: string
  73. // required: true
  74. // - name: repo
  75. // in: path
  76. // description: name of the repo
  77. // type: string
  78. // required: true
  79. // - name: index
  80. // in: path
  81. // description: index of the issue to stop the stopwatch on
  82. // type: integer
  83. // format: int64
  84. // required: true
  85. // responses:
  86. // "201":
  87. // "$ref": "#/responses/empty"
  88. // "403":
  89. // description: Not repo writer, user does not have rights to toggle stopwatch
  90. // "404":
  91. // "$ref": "#/responses/notFound"
  92. // "409":
  93. // description: Cannot stop a non-existent stopwatch
  94. issue := prepareIssueForStopwatch(ctx)
  95. if ctx.Written() {
  96. return
  97. }
  98. if ok, err := issues_model.FinishIssueStopwatch(ctx, ctx.Doer, issue); err != nil {
  99. ctx.APIErrorInternal(err)
  100. return
  101. } else if !ok {
  102. ctx.APIError(http.StatusConflict, "cannot stop a non-existent stopwatch")
  103. return
  104. }
  105. ctx.Status(http.StatusCreated)
  106. }
  107. // DeleteIssueStopwatch delete a specific stopwatch
  108. func DeleteIssueStopwatch(ctx *context.APIContext) {
  109. // swagger:operation DELETE /repos/{owner}/{repo}/issues/{index}/stopwatch/delete issue issueDeleteStopWatch
  110. // ---
  111. // summary: Delete an issue's existing stopwatch.
  112. // consumes:
  113. // - application/json
  114. // produces:
  115. // - application/json
  116. // parameters:
  117. // - name: owner
  118. // in: path
  119. // description: owner of the repo
  120. // type: string
  121. // required: true
  122. // - name: repo
  123. // in: path
  124. // description: name of the repo
  125. // type: string
  126. // required: true
  127. // - name: index
  128. // in: path
  129. // description: index of the issue to stop the stopwatch on
  130. // type: integer
  131. // format: int64
  132. // required: true
  133. // responses:
  134. // "204":
  135. // "$ref": "#/responses/empty"
  136. // "403":
  137. // description: Not repo writer, user does not have rights to toggle stopwatch
  138. // "404":
  139. // "$ref": "#/responses/notFound"
  140. // "409":
  141. // description: Cannot cancel a non-existent stopwatch
  142. issue := prepareIssueForStopwatch(ctx)
  143. if ctx.Written() {
  144. return
  145. }
  146. if ok, err := issues_model.CancelStopwatch(ctx, ctx.Doer, issue); err != nil {
  147. ctx.APIErrorInternal(err)
  148. return
  149. } else if !ok {
  150. ctx.APIError(http.StatusConflict, "cannot cancel a non-existent stopwatch")
  151. return
  152. }
  153. ctx.Status(http.StatusNoContent)
  154. }
  155. func prepareIssueForStopwatch(ctx *context.APIContext) *issues_model.Issue {
  156. issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
  157. if err != nil {
  158. if issues_model.IsErrIssueNotExist(err) {
  159. ctx.APIErrorNotFound()
  160. } else {
  161. ctx.APIErrorInternal(err)
  162. }
  163. return nil
  164. }
  165. if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) {
  166. ctx.Status(http.StatusForbidden)
  167. return nil
  168. }
  169. if !ctx.Repo.CanUseTimetracker(ctx, issue, ctx.Doer) {
  170. ctx.Status(http.StatusForbidden)
  171. return nil
  172. }
  173. return issue
  174. }
  175. // GetStopwatches get all stopwatches
  176. func GetStopwatches(ctx *context.APIContext) {
  177. // swagger:operation GET /user/stopwatches user userGetStopWatches
  178. // ---
  179. // summary: Get list of all existing stopwatches
  180. // parameters:
  181. // - name: page
  182. // in: query
  183. // description: page number of results to return (1-based)
  184. // type: integer
  185. // - name: limit
  186. // in: query
  187. // description: page size of results
  188. // type: integer
  189. // consumes:
  190. // - application/json
  191. // produces:
  192. // - application/json
  193. // responses:
  194. // "200":
  195. // "$ref": "#/responses/StopWatchList"
  196. sws, err := issues_model.GetUserStopwatches(ctx, ctx.Doer.ID, utils.GetListOptions(ctx))
  197. if err != nil {
  198. ctx.APIErrorInternal(err)
  199. return
  200. }
  201. count, err := issues_model.CountUserStopwatches(ctx, ctx.Doer.ID)
  202. if err != nil {
  203. ctx.APIErrorInternal(err)
  204. return
  205. }
  206. apiSWs, err := convert.ToStopWatches(ctx, sws)
  207. if err != nil {
  208. ctx.APIErrorInternal(err)
  209. return
  210. }
  211. ctx.SetTotalCountHeader(count)
  212. ctx.JSON(http.StatusOK, apiSWs)
  213. }