dns_handlers.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. package api
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "os"
  6. "os/exec"
  7. "strings"
  8. "debtik/internal/dns"
  9. )
  10. // handleGetDNSSettings returns the current router DNS configuration.
  11. func (s *Server) handleGetDNSSettings(w http.ResponseWriter, r *http.Request) {
  12. if s.dnsMgr == nil {
  13. writeError(w, http.StatusServiceUnavailable, "DNS manager not initialized")
  14. return
  15. }
  16. settings := s.dnsMgr.GetSettings()
  17. writeJSON(w, http.StatusOK, settings)
  18. }
  19. // handleSaveDNSSettings updates the router DNS configuration.
  20. func (s *Server) handleSaveDNSSettings(w http.ResponseWriter, r *http.Request) {
  21. if s.dnsMgr == nil {
  22. writeError(w, http.StatusServiceUnavailable, "DNS manager not initialized")
  23. return
  24. }
  25. var req dns.DNSSettings
  26. if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
  27. writeError(w, http.StatusBadRequest, "invalid request body")
  28. return
  29. }
  30. if err := s.dnsMgr.SaveSettings(req); err != nil {
  31. writeError(w, http.StatusBadRequest, err.Error())
  32. return
  33. }
  34. writeJSON(w, http.StatusOK, map[string]any{
  35. "success": true,
  36. "settings": s.dnsMgr.GetSettings(),
  37. })
  38. }
  39. // handleListDNSStatic returns all static DNS host mappings.
  40. func (s *Server) handleListDNSStatic(w http.ResponseWriter, r *http.Request) {
  41. if s.dnsMgr == nil {
  42. writeError(w, http.StatusServiceUnavailable, "DNS manager not initialized")
  43. return
  44. }
  45. records := s.dnsMgr.ListStaticRecords()
  46. writeJSON(w, http.StatusOK, records)
  47. }
  48. // handleSaveDNSStatic adds or updates a static DNS record.
  49. func (s *Server) handleSaveDNSStatic(w http.ResponseWriter, r *http.Request) {
  50. if s.dnsMgr == nil {
  51. writeError(w, http.StatusServiceUnavailable, "DNS manager not initialized")
  52. return
  53. }
  54. var rec dns.StaticRecord
  55. if err := json.NewDecoder(r.Body).Decode(&rec); err != nil {
  56. writeError(w, http.StatusBadRequest, "invalid request body")
  57. return
  58. }
  59. if err := s.dnsMgr.SaveStaticRecord(rec); err != nil {
  60. writeError(w, http.StatusBadRequest, err.Error())
  61. return
  62. }
  63. writeJSON(w, http.StatusOK, map[string]any{
  64. "success": true,
  65. "record": rec,
  66. })
  67. }
  68. // handleDeleteDNSStatic deletes a static DNS record by ID.
  69. func (s *Server) handleDeleteDNSStatic(w http.ResponseWriter, r *http.Request) {
  70. if s.dnsMgr == nil {
  71. writeError(w, http.StatusServiceUnavailable, "DNS manager not initialized")
  72. return
  73. }
  74. id := r.PathValue("id")
  75. if id == "" {
  76. writeError(w, http.StatusBadRequest, "record ID is required")
  77. return
  78. }
  79. if err := s.dnsMgr.DeleteStaticRecord(id); err != nil {
  80. writeError(w, http.StatusNotFound, err.Error())
  81. return
  82. }
  83. writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": id})
  84. }
  85. // handleSetDNSStaticState toggles enabled/disabled state of a static DNS record.
  86. func (s *Server) handleSetDNSStaticState(w http.ResponseWriter, r *http.Request) {
  87. if s.dnsMgr == nil {
  88. writeError(w, http.StatusServiceUnavailable, "DNS manager not initialized")
  89. return
  90. }
  91. id := r.PathValue("id")
  92. var req struct {
  93. Disabled bool `json:"disabled"`
  94. }
  95. if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
  96. writeError(w, http.StatusBadRequest, "invalid request body")
  97. return
  98. }
  99. if err := s.dnsMgr.ToggleStaticRecord(id, req.Disabled); err != nil {
  100. writeError(w, http.StatusInternalServerError, err.Error())
  101. return
  102. }
  103. writeJSON(w, http.StatusOK, map[string]any{"success": true, "id": id, "disabled": req.Disabled})
  104. }
  105. // handleFlushDNSCache flushes the local DNS cache.
  106. func (s *Server) handleFlushDNSCache(w http.ResponseWriter, r *http.Request) {
  107. if s.dnsMgr == nil {
  108. writeError(w, http.StatusServiceUnavailable, "DNS manager not initialized")
  109. return
  110. }
  111. if err := s.dnsMgr.FlushCache(); err != nil {
  112. writeError(w, http.StatusInternalServerError, err.Error())
  113. return
  114. }
  115. writeJSON(w, http.StatusOK, map[string]any{"success": true, "message": "DNS cache flushed successfully"})
  116. }
  117. // handleGetDNSStatus returns live DNS forwarder and resolv.conf status.
  118. func (s *Server) handleGetDNSStatus(w http.ResponseWriter, r *http.Request) {
  119. if s.dnsMgr == nil {
  120. writeError(w, http.StatusServiceUnavailable, "DNS manager not initialized")
  121. return
  122. }
  123. status := s.dnsMgr.GetStatus()
  124. writeJSON(w, http.StatusOK, status)
  125. }
  126. // handleGetSystemSettings returns hostname, timezone, and appliance info.
  127. func (s *Server) handleGetSystemSettings(w http.ResponseWriter, r *http.Request) {
  128. hostname, _ := os.Hostname()
  129. tz := "UTC"
  130. if out, err := exec.Command("timedatectl", "show", "--property=Timezone", "--value").Output(); err == nil {
  131. tz = strings.TrimSpace(string(out))
  132. } else if data, err := os.ReadFile("/etc/timezone"); err == nil {
  133. tz = strings.TrimSpace(string(data))
  134. }
  135. writeJSON(w, http.StatusOK, map[string]any{
  136. "hostname": hostname,
  137. "timezone": tz,
  138. })
  139. }
  140. // handleSaveSystemSettings updates hostname and/or timezone.
  141. func (s *Server) handleSaveSystemSettings(w http.ResponseWriter, r *http.Request) {
  142. var req struct {
  143. Hostname string `json:"hostname"`
  144. Timezone string `json:"timezone"`
  145. }
  146. if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
  147. writeError(w, http.StatusBadRequest, "invalid request body")
  148. return
  149. }
  150. if req.Hostname != "" {
  151. h := strings.TrimSpace(req.Hostname)
  152. if err := exec.Command("hostnamectl", "set-hostname", h).Run(); err != nil {
  153. _ = os.WriteFile("/etc/hostname", []byte(h+"\n"), 0644)
  154. }
  155. }
  156. if req.Timezone != "" {
  157. tz := strings.TrimSpace(req.Timezone)
  158. _ = exec.Command("timedatectl", "set-timezone", tz).Run()
  159. }
  160. curH, _ := os.Hostname()
  161. writeJSON(w, http.StatusOK, map[string]any{
  162. "success": true,
  163. "hostname": curH,
  164. "timezone": req.Timezone,
  165. })
  166. }