lists.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package main
  2. import (
  3. "fmt"
  4. "net/http"
  5. "strconv"
  6. "github.com/gofrs/uuid"
  7. "github.com/knadh/listmonk/models"
  8. "github.com/lib/pq"
  9. "github.com/labstack/echo"
  10. )
  11. type listsWrap struct {
  12. Results []models.List `json:"results"`
  13. Total int `json:"total"`
  14. PerPage int `json:"per_page"`
  15. Page int `json:"page"`
  16. }
  17. // handleGetLists handles retrieval of lists.
  18. func handleGetLists(c echo.Context) error {
  19. var (
  20. app = c.Get("app").(*App)
  21. out listsWrap
  22. pg = getPagination(c.QueryParams(), 20, 50)
  23. listID, _ = strconv.Atoi(c.Param("id"))
  24. single = false
  25. )
  26. // Fetch one list.
  27. if listID > 0 {
  28. single = true
  29. }
  30. err := app.queries.GetLists.Select(&out.Results, listID, pg.Offset, pg.Limit)
  31. if err != nil {
  32. app.log.Printf("error fetching lists: %v", err)
  33. return echo.NewHTTPError(http.StatusInternalServerError,
  34. fmt.Sprintf("Error fetching lists: %s", pqErrMsg(err)))
  35. }
  36. if single && len(out.Results) == 0 {
  37. return echo.NewHTTPError(http.StatusBadRequest, "List not found.")
  38. }
  39. if len(out.Results) == 0 {
  40. return c.JSON(http.StatusOK, okResp{[]struct{}{}})
  41. }
  42. // Replace null tags.
  43. for i, v := range out.Results {
  44. if v.Tags == nil {
  45. out.Results[i].Tags = make(pq.StringArray, 0)
  46. }
  47. }
  48. if single {
  49. return c.JSON(http.StatusOK, okResp{out.Results[0]})
  50. }
  51. // Meta.
  52. out.Total = out.Results[0].Total
  53. out.Page = pg.Page
  54. out.PerPage = pg.PerPage
  55. return c.JSON(http.StatusOK, okResp{out})
  56. }
  57. // handleCreateList handles list creation.
  58. func handleCreateList(c echo.Context) error {
  59. var (
  60. app = c.Get("app").(*App)
  61. o = models.List{}
  62. )
  63. if err := c.Bind(&o); err != nil {
  64. return err
  65. }
  66. // Validate.
  67. if !strHasLen(o.Name, 1, stdInputMaxLen) {
  68. return echo.NewHTTPError(http.StatusBadRequest,
  69. "Invalid length for the name field.")
  70. }
  71. uu, err := uuid.NewV4()
  72. if err != nil {
  73. app.log.Printf("error generating UUID: %v", err)
  74. return echo.NewHTTPError(http.StatusInternalServerError, "Error generating UUID")
  75. }
  76. // Insert and read ID.
  77. var newID int
  78. o.UUID = uu.String()
  79. if err := app.queries.CreateList.Get(&newID,
  80. o.UUID,
  81. o.Name,
  82. o.Type,
  83. o.Optin,
  84. pq.StringArray(normalizeTags(o.Tags))); err != nil {
  85. app.log.Printf("error creating list: %v", err)
  86. return echo.NewHTTPError(http.StatusInternalServerError,
  87. fmt.Sprintf("Error creating list: %s", pqErrMsg(err)))
  88. }
  89. // Hand over to the GET handler to return the last insertion.
  90. c.SetParamNames("id")
  91. c.SetParamValues(fmt.Sprintf("%d", newID))
  92. return c.JSON(http.StatusOK, handleGetLists(c))
  93. }
  94. // handleUpdateList handles list modification.
  95. func handleUpdateList(c echo.Context) error {
  96. var (
  97. app = c.Get("app").(*App)
  98. id, _ = strconv.Atoi(c.Param("id"))
  99. )
  100. if id < 1 {
  101. return echo.NewHTTPError(http.StatusBadRequest, "Invalid ID.")
  102. }
  103. // Incoming params.
  104. var o models.List
  105. if err := c.Bind(&o); err != nil {
  106. return err
  107. }
  108. res, err := app.queries.UpdateList.Exec(id,
  109. o.Name, o.Type, o.Optin, pq.StringArray(normalizeTags(o.Tags)))
  110. if err != nil {
  111. app.log.Printf("error updating list: %v", err)
  112. return echo.NewHTTPError(http.StatusBadRequest,
  113. fmt.Sprintf("Error updating list: %s", pqErrMsg(err)))
  114. }
  115. if n, _ := res.RowsAffected(); n == 0 {
  116. return echo.NewHTTPError(http.StatusBadRequest, "List not found.")
  117. }
  118. return handleGetLists(c)
  119. }
  120. // handleDeleteLists handles deletion deletion,
  121. // either a single one (ID in the URI), or a list.
  122. func handleDeleteLists(c echo.Context) error {
  123. var (
  124. app = c.Get("app").(*App)
  125. id, _ = strconv.ParseInt(c.Param("id"), 10, 64)
  126. ids pq.Int64Array
  127. )
  128. if id < 1 && len(ids) == 0 {
  129. return echo.NewHTTPError(http.StatusBadRequest, "Invalid ID.")
  130. }
  131. if id > 0 {
  132. ids = append(ids, id)
  133. }
  134. if _, err := app.queries.DeleteLists.Exec(ids); err != nil {
  135. app.log.Printf("error deleting lists: %v", err)
  136. return echo.NewHTTPError(http.StatusInternalServerError,
  137. fmt.Sprintf("Error deleting: %v", err))
  138. }
  139. return c.JSON(http.StatusOK, okResp{true})
  140. }