ops_settings_handler.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. package admin
  2. import (
  3. "net/http"
  4. "github.com/Wei-Shaw/sub2api/internal/pkg/response"
  5. "github.com/Wei-Shaw/sub2api/internal/server/middleware"
  6. "github.com/Wei-Shaw/sub2api/internal/service"
  7. "github.com/gin-gonic/gin"
  8. )
  9. // GetEmailNotificationConfig returns Ops email notification config (DB-backed).
  10. // GET /api/v1/admin/ops/email-notification/config
  11. func (h *OpsHandler) GetEmailNotificationConfig(c *gin.Context) {
  12. if h.opsService == nil {
  13. response.Error(c, http.StatusServiceUnavailable, "Ops service not available")
  14. return
  15. }
  16. if err := h.opsService.RequireMonitoringEnabled(c.Request.Context()); err != nil {
  17. response.ErrorFrom(c, err)
  18. return
  19. }
  20. cfg, err := h.opsService.GetEmailNotificationConfig(c.Request.Context())
  21. if err != nil {
  22. response.Error(c, http.StatusInternalServerError, "Failed to get email notification config")
  23. return
  24. }
  25. response.Success(c, cfg)
  26. }
  27. // UpdateEmailNotificationConfig updates Ops email notification config (DB-backed).
  28. // PUT /api/v1/admin/ops/email-notification/config
  29. func (h *OpsHandler) UpdateEmailNotificationConfig(c *gin.Context) {
  30. if h.opsService == nil {
  31. response.Error(c, http.StatusServiceUnavailable, "Ops service not available")
  32. return
  33. }
  34. if err := h.opsService.RequireMonitoringEnabled(c.Request.Context()); err != nil {
  35. response.ErrorFrom(c, err)
  36. return
  37. }
  38. var req service.OpsEmailNotificationConfigUpdateRequest
  39. if err := c.ShouldBindJSON(&req); err != nil {
  40. response.BadRequest(c, "Invalid request body")
  41. return
  42. }
  43. updated, err := h.opsService.UpdateEmailNotificationConfig(c.Request.Context(), &req)
  44. if err != nil {
  45. // Most failures here are validation errors from request payload; treat as 400.
  46. response.Error(c, http.StatusBadRequest, err.Error())
  47. return
  48. }
  49. response.Success(c, updated)
  50. }
  51. // GetAlertRuntimeSettings returns Ops alert evaluator runtime settings (DB-backed).
  52. // GET /api/v1/admin/ops/runtime/alert
  53. func (h *OpsHandler) GetAlertRuntimeSettings(c *gin.Context) {
  54. if h.opsService == nil {
  55. response.Error(c, http.StatusServiceUnavailable, "Ops service not available")
  56. return
  57. }
  58. if err := h.opsService.RequireMonitoringEnabled(c.Request.Context()); err != nil {
  59. response.ErrorFrom(c, err)
  60. return
  61. }
  62. cfg, err := h.opsService.GetOpsAlertRuntimeSettings(c.Request.Context())
  63. if err != nil {
  64. response.Error(c, http.StatusInternalServerError, "Failed to get alert runtime settings")
  65. return
  66. }
  67. response.Success(c, cfg)
  68. }
  69. // UpdateAlertRuntimeSettings updates Ops alert evaluator runtime settings (DB-backed).
  70. // PUT /api/v1/admin/ops/runtime/alert
  71. func (h *OpsHandler) UpdateAlertRuntimeSettings(c *gin.Context) {
  72. if h.opsService == nil {
  73. response.Error(c, http.StatusServiceUnavailable, "Ops service not available")
  74. return
  75. }
  76. if err := h.opsService.RequireMonitoringEnabled(c.Request.Context()); err != nil {
  77. response.ErrorFrom(c, err)
  78. return
  79. }
  80. var req service.OpsAlertRuntimeSettings
  81. if err := c.ShouldBindJSON(&req); err != nil {
  82. response.BadRequest(c, "Invalid request body")
  83. return
  84. }
  85. updated, err := h.opsService.UpdateOpsAlertRuntimeSettings(c.Request.Context(), &req)
  86. if err != nil {
  87. response.Error(c, http.StatusBadRequest, err.Error())
  88. return
  89. }
  90. response.Success(c, updated)
  91. }
  92. // GetRuntimeLogConfig returns runtime log config (DB-backed).
  93. // GET /api/v1/admin/ops/runtime/logging
  94. func (h *OpsHandler) GetRuntimeLogConfig(c *gin.Context) {
  95. if h.opsService == nil {
  96. response.Error(c, http.StatusServiceUnavailable, "Ops service not available")
  97. return
  98. }
  99. if err := h.opsService.RequireMonitoringEnabled(c.Request.Context()); err != nil {
  100. response.ErrorFrom(c, err)
  101. return
  102. }
  103. cfg, err := h.opsService.GetRuntimeLogConfig(c.Request.Context())
  104. if err != nil {
  105. response.Error(c, http.StatusInternalServerError, "Failed to get runtime log config")
  106. return
  107. }
  108. response.Success(c, cfg)
  109. }
  110. // UpdateRuntimeLogConfig updates runtime log config and applies changes immediately.
  111. // PUT /api/v1/admin/ops/runtime/logging
  112. func (h *OpsHandler) UpdateRuntimeLogConfig(c *gin.Context) {
  113. if h.opsService == nil {
  114. response.Error(c, http.StatusServiceUnavailable, "Ops service not available")
  115. return
  116. }
  117. if err := h.opsService.RequireMonitoringEnabled(c.Request.Context()); err != nil {
  118. response.ErrorFrom(c, err)
  119. return
  120. }
  121. var req service.OpsRuntimeLogConfig
  122. if err := c.ShouldBindJSON(&req); err != nil {
  123. response.BadRequest(c, "Invalid request body")
  124. return
  125. }
  126. subject, ok := middleware.GetAuthSubjectFromContext(c)
  127. if !ok || subject.UserID <= 0 {
  128. response.Error(c, http.StatusUnauthorized, "Unauthorized")
  129. return
  130. }
  131. updated, err := h.opsService.UpdateRuntimeLogConfig(c.Request.Context(), &req, subject.UserID)
  132. if err != nil {
  133. response.Error(c, http.StatusBadRequest, err.Error())
  134. return
  135. }
  136. response.Success(c, updated)
  137. }
  138. // ResetRuntimeLogConfig removes runtime override and falls back to env/yaml baseline.
  139. // POST /api/v1/admin/ops/runtime/logging/reset
  140. func (h *OpsHandler) ResetRuntimeLogConfig(c *gin.Context) {
  141. if h.opsService == nil {
  142. response.Error(c, http.StatusServiceUnavailable, "Ops service not available")
  143. return
  144. }
  145. if err := h.opsService.RequireMonitoringEnabled(c.Request.Context()); err != nil {
  146. response.ErrorFrom(c, err)
  147. return
  148. }
  149. subject, ok := middleware.GetAuthSubjectFromContext(c)
  150. if !ok || subject.UserID <= 0 {
  151. response.Error(c, http.StatusUnauthorized, "Unauthorized")
  152. return
  153. }
  154. updated, err := h.opsService.ResetRuntimeLogConfig(c.Request.Context(), subject.UserID)
  155. if err != nil {
  156. response.Error(c, http.StatusBadRequest, err.Error())
  157. return
  158. }
  159. response.Success(c, updated)
  160. }
  161. // GetAdvancedSettings returns Ops advanced settings (DB-backed).
  162. // GET /api/v1/admin/ops/advanced-settings
  163. func (h *OpsHandler) GetAdvancedSettings(c *gin.Context) {
  164. if h.opsService == nil {
  165. response.Error(c, http.StatusServiceUnavailable, "Ops service not available")
  166. return
  167. }
  168. if err := h.opsService.RequireMonitoringEnabled(c.Request.Context()); err != nil {
  169. response.ErrorFrom(c, err)
  170. return
  171. }
  172. cfg, err := h.opsService.GetOpsAdvancedSettings(c.Request.Context())
  173. if err != nil {
  174. response.Error(c, http.StatusInternalServerError, "Failed to get advanced settings")
  175. return
  176. }
  177. response.Success(c, cfg)
  178. }
  179. // UpdateAdvancedSettings updates Ops advanced settings (DB-backed).
  180. // PUT /api/v1/admin/ops/advanced-settings
  181. func (h *OpsHandler) UpdateAdvancedSettings(c *gin.Context) {
  182. if h.opsService == nil {
  183. response.Error(c, http.StatusServiceUnavailable, "Ops service not available")
  184. return
  185. }
  186. if err := h.opsService.RequireMonitoringEnabled(c.Request.Context()); err != nil {
  187. response.ErrorFrom(c, err)
  188. return
  189. }
  190. var req service.OpsAdvancedSettings
  191. if err := c.ShouldBindJSON(&req); err != nil {
  192. response.BadRequest(c, "Invalid request body")
  193. return
  194. }
  195. updated, err := h.opsService.UpdateOpsAdvancedSettings(c.Request.Context(), &req)
  196. if err != nil {
  197. response.Error(c, http.StatusBadRequest, err.Error())
  198. return
  199. }
  200. response.Success(c, updated)
  201. }
  202. // GetMetricThresholds returns Ops metric thresholds (DB-backed).
  203. // GET /api/v1/admin/ops/settings/metric-thresholds
  204. func (h *OpsHandler) GetMetricThresholds(c *gin.Context) {
  205. if h.opsService == nil {
  206. response.Error(c, http.StatusServiceUnavailable, "Ops service not available")
  207. return
  208. }
  209. if err := h.opsService.RequireMonitoringEnabled(c.Request.Context()); err != nil {
  210. response.ErrorFrom(c, err)
  211. return
  212. }
  213. cfg, err := h.opsService.GetMetricThresholds(c.Request.Context())
  214. if err != nil {
  215. response.Error(c, http.StatusInternalServerError, "Failed to get metric thresholds")
  216. return
  217. }
  218. response.Success(c, cfg)
  219. }
  220. // UpdateMetricThresholds updates Ops metric thresholds (DB-backed).
  221. // PUT /api/v1/admin/ops/settings/metric-thresholds
  222. func (h *OpsHandler) UpdateMetricThresholds(c *gin.Context) {
  223. if h.opsService == nil {
  224. response.Error(c, http.StatusServiceUnavailable, "Ops service not available")
  225. return
  226. }
  227. if err := h.opsService.RequireMonitoringEnabled(c.Request.Context()); err != nil {
  228. response.ErrorFrom(c, err)
  229. return
  230. }
  231. var req service.OpsMetricThresholds
  232. if err := c.ShouldBindJSON(&req); err != nil {
  233. response.BadRequest(c, "Invalid request body")
  234. return
  235. }
  236. updated, err := h.opsService.UpdateMetricThresholds(c.Request.Context(), &req)
  237. if err != nil {
  238. response.Error(c, http.StatusBadRequest, err.Error())
  239. return
  240. }
  241. response.Success(c, updated)
  242. }