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

issue_stopwatch.go 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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. )
  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, err := prepareIssueStopwatch(ctx, false)
  47. if err != nil {
  48. return
  49. }
  50. if err := models.CreateOrStopIssueStopwatch(ctx.User, issue); err != nil {
  51. ctx.Error(http.StatusInternalServerError, "CreateOrStopIssueStopwatch", err)
  52. return
  53. }
  54. ctx.Status(http.StatusCreated)
  55. }
  56. // StopIssueStopwatch stops a stopwatch for the given issue.
  57. func StopIssueStopwatch(ctx *context.APIContext) {
  58. // swagger:operation POST /repos/{owner}/{repo}/issues/{index}/stopwatch/stop issue issueStopStopWatch
  59. // ---
  60. // summary: Stop an issue's existing stopwatch.
  61. // consumes:
  62. // - application/json
  63. // produces:
  64. // - application/json
  65. // parameters:
  66. // - name: owner
  67. // in: path
  68. // description: owner of the repo
  69. // type: string
  70. // required: true
  71. // - name: repo
  72. // in: path
  73. // description: name of the repo
  74. // type: string
  75. // required: true
  76. // - name: index
  77. // in: path
  78. // description: index of the issue to stop the stopwatch on
  79. // type: integer
  80. // format: int64
  81. // required: true
  82. // responses:
  83. // "201":
  84. // "$ref": "#/responses/empty"
  85. // "403":
  86. // description: Not repo writer, user does not have rights to toggle stopwatch
  87. // "404":
  88. // "$ref": "#/responses/notFound"
  89. // "409":
  90. // description: Cannot stop a non existent stopwatch
  91. issue, err := prepareIssueStopwatch(ctx, true)
  92. if err != nil {
  93. return
  94. }
  95. if err := models.CreateOrStopIssueStopwatch(ctx.User, issue); err != nil {
  96. ctx.Error(http.StatusInternalServerError, "CreateOrStopIssueStopwatch", err)
  97. return
  98. }
  99. ctx.Status(http.StatusCreated)
  100. }
  101. // DeleteIssueStopwatch delete a specific stopwatch
  102. func DeleteIssueStopwatch(ctx *context.APIContext) {
  103. // swagger:operation DELETE /repos/{owner}/{repo}/issues/{index}/stopwatch/delete issue issueDeleteStopWatch
  104. // ---
  105. // summary: Delete an issue's existing stopwatch.
  106. // consumes:
  107. // - application/json
  108. // produces:
  109. // - application/json
  110. // parameters:
  111. // - name: owner
  112. // in: path
  113. // description: owner of the repo
  114. // type: string
  115. // required: true
  116. // - name: repo
  117. // in: path
  118. // description: name of the repo
  119. // type: string
  120. // required: true
  121. // - name: index
  122. // in: path
  123. // description: index of the issue to stop the stopwatch on
  124. // type: integer
  125. // format: int64
  126. // required: true
  127. // responses:
  128. // "204":
  129. // "$ref": "#/responses/empty"
  130. // "403":
  131. // description: Not repo writer, user does not have rights to toggle stopwatch
  132. // "404":
  133. // "$ref": "#/responses/notFound"
  134. // "409":
  135. // description: Cannot cancel a non existent stopwatch
  136. issue, err := prepareIssueStopwatch(ctx, true)
  137. if err != nil {
  138. return
  139. }
  140. if err := models.CancelStopwatch(ctx.User, issue); err != nil {
  141. ctx.Error(http.StatusInternalServerError, "CancelStopwatch", err)
  142. return
  143. }
  144. ctx.Status(http.StatusNoContent)
  145. }
  146. func prepareIssueStopwatch(ctx *context.APIContext, shouldExist bool) (*models.Issue, error) {
  147. issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
  148. if err != nil {
  149. if models.IsErrIssueNotExist(err) {
  150. ctx.NotFound()
  151. } else {
  152. ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err)
  153. }
  154. return nil, err
  155. }
  156. if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) {
  157. ctx.Status(http.StatusForbidden)
  158. return nil, errors.New("Unable to write to PRs")
  159. }
  160. if !ctx.Repo.CanUseTimetracker(issue, ctx.User) {
  161. ctx.Status(http.StatusForbidden)
  162. return nil, errors.New("Cannot use time tracker")
  163. }
  164. if models.StopwatchExists(ctx.User.ID, issue.ID) != shouldExist {
  165. if shouldExist {
  166. ctx.Error(http.StatusConflict, "StopwatchExists", "cannot stop/cancel a non existent stopwatch")
  167. err = errors.New("cannot stop/cancel a non existent stopwatch")
  168. } else {
  169. ctx.Error(http.StatusConflict, "StopwatchExists", "cannot start a stopwatch again if it already exists")
  170. err = errors.New("cannot start a stopwatch again if it already exists")
  171. }
  172. return nil, err
  173. }
  174. return issue, nil
  175. }
  176. // GetStopwatches get all stopwatches
  177. func GetStopwatches(ctx *context.APIContext) {
  178. // swagger:operation GET /user/stopwatches user userGetStopWatches
  179. // ---
  180. // summary: Get list of all existing stopwatches
  181. // consumes:
  182. // - application/json
  183. // produces:
  184. // - application/json
  185. // responses:
  186. // "200":
  187. // "$ref": "#/responses/StopWatchList"
  188. sws, err := models.GetUserStopwatches(ctx.User.ID)
  189. if err != nil {
  190. ctx.Error(http.StatusInternalServerError, "GetUserStopwatches", err)
  191. return
  192. }
  193. apiSWs, err := sws.APIFormat()
  194. if err != nil {
  195. ctx.Error(http.StatusInternalServerError, "APIFormat", err)
  196. return
  197. }
  198. ctx.JSON(http.StatusOK, apiSWs)
  199. }