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.

205 lines
5.0 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. package api
  2. import (
  3. "github.com/gin-gonic/gin"
  4. "github.com/gissleh/stufflog/database"
  5. "github.com/gissleh/stufflog/internal/auth"
  6. "github.com/gissleh/stufflog/internal/generate"
  7. "github.com/gissleh/stufflog/internal/slerrors"
  8. "github.com/gissleh/stufflog/models"
  9. "github.com/gissleh/stufflog/services"
  10. "sort"
  11. "strings"
  12. "time"
  13. )
  14. func Task(g *gin.RouterGroup, db database.Database) {
  15. l := services.Loader{DB: db}
  16. g.GET("/", handler("tasks", func(c *gin.Context) (interface{}, error) {
  17. filter := models.TaskFilter{}
  18. if setting := c.Query("active"); setting != "" {
  19. active := setting == "true"
  20. filter.Active = &active
  21. }
  22. if setting := c.Query("expiring"); setting != "" {
  23. expiring := setting == "true"
  24. filter.Expiring = &expiring
  25. }
  26. tasks, err := l.ListTasks(c, filter)
  27. if err != nil {
  28. return nil, err
  29. }
  30. sort.Sort(
  31. models.TaskSorter{
  32. Fields: strings.Split(c.Query("sort"), ","),
  33. Data: tasks,
  34. },
  35. )
  36. return tasks, nil
  37. }))
  38. g.GET("/:id", handler("task", func(c *gin.Context) (interface{}, error) {
  39. return l.FindTask(c, c.Param("id"))
  40. }))
  41. g.POST("/", handler("task", func(c *gin.Context) (interface{}, error) {
  42. createdTime := time.Now()
  43. task := models.Task{}
  44. err := c.BindJSON(&task)
  45. if err != nil {
  46. return nil, slerrors.BadRequest("Invalid JSON")
  47. }
  48. if task.EndTime != nil && task.EndTime.Before(createdTime) {
  49. return nil, slerrors.BadRequest("Task end time must be later than current time.")
  50. }
  51. if task.ItemAmount <= 0 {
  52. return nil, slerrors.BadRequest("Item amount cannot be zero or negative.")
  53. }
  54. project, err := l.FindProject(c.Request.Context(), task.ProjectID)
  55. if err != nil {
  56. return nil, err
  57. }
  58. item, err := l.FindItem(c.Request.Context(), task.ItemID)
  59. if err != nil {
  60. return nil, err
  61. }
  62. task.ID = generate.TaskID()
  63. task.UserID = auth.UserID(c)
  64. task.CreatedTime = time.Now().UTC()
  65. task.ItemID = item.ID
  66. task.ProjectID = project.ID
  67. err = db.Tasks().Insert(c.Request.Context(), task)
  68. if err != nil {
  69. return nil, err
  70. }
  71. return &models.TaskResult{
  72. Task: task,
  73. Logs: []*models.LogWithSecondaryItem{},
  74. Item: &item.Item,
  75. CompletedAmount: 0,
  76. }, nil
  77. }))
  78. g.PUT("/:id", handler("task", func(c *gin.Context) (interface{}, error) {
  79. update := models.TaskUpdate{}
  80. err := c.BindJSON(&update)
  81. if err != nil {
  82. return nil, slerrors.BadRequest("Invalid JSON")
  83. }
  84. task, err := l.FindTask(c.Request.Context(), c.Param("id"))
  85. if err != nil {
  86. return nil, err
  87. }
  88. if update.ProjectID != nil && *update.ProjectID != task.ProjectID {
  89. project, err := l.FindProject(c.Request.Context(), *update.ProjectID)
  90. if err != nil {
  91. return nil, slerrors.NotFound("Destination project")
  92. }
  93. // Delete any links that would have been ran over.
  94. err = db.Tasks().DeleteLink(c.Request.Context(), models.TaskLink{
  95. TaskID: task.ID,
  96. ProjectID: project.ID,
  97. })
  98. if err != nil {
  99. return nil, slerrors.BadRequest(err.Error())
  100. }
  101. task.ProjectID = project.ID
  102. }
  103. task.Update(update)
  104. if task.EndTime != nil && task.EndTime.Before(task.CreatedTime) {
  105. return nil, slerrors.BadRequest("Task end time must be later than it was created.")
  106. }
  107. if task.ItemAmount <= 0 {
  108. return nil, slerrors.BadRequest("Item amount cannot be zero or negative.")
  109. }
  110. err = db.Tasks().Update(c.Request.Context(), task.Task)
  111. if err != nil {
  112. return nil, err
  113. }
  114. return task, nil
  115. }))
  116. g.PUT("/:id/link/:project_id", handler("taskLink", func(c *gin.Context) (interface{}, error) {
  117. task, err := l.FindTask(c.Request.Context(), c.Param("id"))
  118. if err != nil {
  119. return nil, err
  120. }
  121. project, err := l.FindProject(c.Request.Context(), c.Param("project_id"))
  122. if err != nil {
  123. return nil, err
  124. }
  125. if task.ProjectID == project.ID {
  126. return nil, slerrors.BadRequest("You cannot link a task within its own project")
  127. }
  128. err = db.Tasks().CreateLink(c.Request.Context(), models.TaskLink{
  129. TaskID: task.ID,
  130. ProjectID: project.ID,
  131. })
  132. return &models.TaskLink{
  133. TaskID: task.ID,
  134. ProjectID: project.ID,
  135. }, nil
  136. }))
  137. g.DELETE("/:id/link/:project_id", handler("taskLink", func(c *gin.Context) (interface{}, error) {
  138. task, err := l.FindTask(c.Request.Context(), c.Param("id"))
  139. if err != nil {
  140. return nil, err
  141. }
  142. project, err := l.FindProject(c.Request.Context(), c.Param("project_id"))
  143. if err != nil {
  144. return nil, err
  145. }
  146. err = db.Tasks().DeleteLink(c.Request.Context(), models.TaskLink{
  147. TaskID: task.ID,
  148. ProjectID: project.ID,
  149. })
  150. if err != nil {
  151. return nil, err
  152. }
  153. return &models.TaskLink{
  154. TaskID: task.ID,
  155. ProjectID: project.ID,
  156. }, nil
  157. }))
  158. g.DELETE("/:id", handler("task", func(c *gin.Context) (interface{}, error) {
  159. task, err := l.FindTask(c.Request.Context(), c.Param("id"))
  160. if err != nil {
  161. return nil, err
  162. }
  163. if len(task.Logs) > 0 {
  164. return nil, slerrors.Forbidden("cannot delete tasks with logs.")
  165. }
  166. err = db.Tasks().Delete(c.Request.Context(), task.Task)
  167. if err != nil {
  168. return nil, err
  169. }
  170. return task, nil
  171. }))
  172. }