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.
 
 
 
 

165 lines
4.4 KiB

  1. package controller
  2. import (
  3. "context"
  4. "encoding/json"
  5. "log/slog"
  6. "net/http"
  7. "strconv"
  8. "github.com/AFASystems/presence/internal/pkg/api/response"
  9. "github.com/AFASystems/presence/internal/pkg/kafkaclient"
  10. "github.com/AFASystems/presence/internal/pkg/model"
  11. "github.com/AFASystems/presence/internal/pkg/validation"
  12. "github.com/gorilla/mux"
  13. "github.com/segmentio/kafka-go"
  14. "gorm.io/gorm"
  15. )
  16. func SendKafkaMessage(writer *kafka.Writer, value *model.ApiUpdate, context context.Context) error {
  17. valueStr, err := json.Marshal(&value)
  18. if err != nil {
  19. slog.Error("error encoding", "error", err)
  20. return err
  21. }
  22. msg := kafka.Message{
  23. Value: valueStr,
  24. }
  25. if err := kafkaclient.Write(context, writer, msg); err != nil {
  26. slog.Error("error sending kafka message", "error", err)
  27. return err
  28. }
  29. return nil
  30. }
  31. func TrackerAdd(db *gorm.DB, writer *kafka.Writer, context context.Context) http.HandlerFunc {
  32. return func(w http.ResponseWriter, r *http.Request) {
  33. var tracker model.Tracker
  34. if err := json.NewDecoder(r.Body).Decode(&tracker); err != nil {
  35. response.BadRequest(w, "invalid request body")
  36. return
  37. }
  38. if err := validation.Struct(&tracker); err != nil {
  39. response.BadRequest(w, err.Error())
  40. return
  41. }
  42. if err := db.WithContext(context).Create(&tracker).Error; err != nil {
  43. response.InternalError(w, "failed to create tracker", err)
  44. return
  45. }
  46. apiUpdate := model.ApiUpdate{
  47. Method: "POST",
  48. ID: tracker.ID,
  49. MAC: tracker.MAC,
  50. }
  51. if err := SendKafkaMessage(writer, &apiUpdate, context); err != nil {
  52. slog.Error("error sending Kafka POST message", "err", err)
  53. response.InternalError(w, "failed to publish tracker update", err)
  54. return
  55. }
  56. response.JSON(w, http.StatusCreated, map[string]string{"status": "created"})
  57. }
  58. }
  59. func TrackerList(db *gorm.DB, context context.Context) http.HandlerFunc {
  60. return func(w http.ResponseWriter, r *http.Request) {
  61. query := r.URL.Query()
  62. lStr := query.Get("limit")
  63. if lStr == "" {
  64. lStr = "100"
  65. }
  66. limit, err := strconv.Atoi(lStr)
  67. if err != nil {
  68. slog.Error("invalid limit parameter", "value", lStr)
  69. response.BadRequest(w, "invalid limit parameter")
  70. return
  71. }
  72. oStr := query.Get("offset")
  73. if oStr == "" {
  74. oStr = "0"
  75. }
  76. offset, err := strconv.Atoi(oStr)
  77. if err != nil {
  78. slog.Error("invalid offset parameter", "value", oStr)
  79. response.BadRequest(w, "invalid offset parameter")
  80. return
  81. }
  82. var list []model.Tracker
  83. if err := db.WithContext(context).Limit(limit).Offset(offset).Find(&list).Error; err != nil {
  84. response.InternalError(w, "failed to list trackers", err)
  85. return
  86. }
  87. response.JSON(w, http.StatusOK, list)
  88. }
  89. }
  90. func TrackerUpdate(db *gorm.DB, context context.Context) http.HandlerFunc {
  91. return func(w http.ResponseWriter, r *http.Request) {
  92. var tracker model.Tracker
  93. if err := json.NewDecoder(r.Body).Decode(&tracker); err != nil {
  94. response.BadRequest(w, "invalid request body")
  95. return
  96. }
  97. if err := validation.Struct(&tracker); err != nil {
  98. response.BadRequest(w, err.Error())
  99. return
  100. }
  101. id := tracker.ID
  102. if err := db.WithContext(context).First(&model.Tracker{}, "id = ?", id).Error; err != nil {
  103. response.NotFound(w, "tracker not found")
  104. return
  105. }
  106. if err := db.WithContext(context).Save(&tracker).Error; err != nil {
  107. response.InternalError(w, "failed to update tracker", err)
  108. return
  109. }
  110. response.JSON(w, http.StatusOK, map[string]string{"status": "updated"})
  111. }
  112. }
  113. func TrackerDelete(db *gorm.DB, writer *kafka.Writer, context context.Context) http.HandlerFunc {
  114. return func(w http.ResponseWriter, r *http.Request) {
  115. id := mux.Vars(r)["id"]
  116. var tracker model.Tracker
  117. if err := db.WithContext(context).First(&tracker, "id = ?", id).Error; err != nil {
  118. response.NotFound(w, "tracker not found")
  119. return
  120. }
  121. res := db.WithContext(context).Delete(&model.Tracker{}, "id = ?", id)
  122. if res.RowsAffected == 0 {
  123. response.NotFound(w, "tracker not found")
  124. return
  125. }
  126. if res.Error != nil {
  127. response.InternalError(w, "failed to delete tracker", res.Error)
  128. return
  129. }
  130. apiUpdate := model.ApiUpdate{
  131. Method: "DELETE",
  132. MAC: tracker.MAC,
  133. }
  134. slog.Info("sending DELETE tracker message", "id", id)
  135. if err := SendKafkaMessage(writer, &apiUpdate, context); err != nil {
  136. slog.Error("error sending Kafka DELETE message", "err", err)
  137. response.InternalError(w, "failed to publish tracker deletion", err)
  138. return
  139. }
  140. response.JSON(w, http.StatusOK, map[string]string{"status": "deleted"})
  141. }
  142. }