package ghl import ( "context" "encoding/json" "io" "log/slog" "net/http" "time" "github.com/go-chi/chi/v5" ) // LocationConfigStore is the store interface used by AdminHandler. type LocationConfigStore interface { UpdateSenderID(ctx context.Context, locationID, senderID string) error } // AdminHandler exposes internal management endpoints. // All routes require a valid Authorization: Bearer header. type AdminHandler struct { adminKey string store LocationConfigStore } func NewAdminHandler(adminKey string, store LocationConfigStore) *AdminHandler { return &AdminHandler{adminKey: adminKey, store: store} } // HandleSetSenderID sets or clears the per-location Cast sender ID. // // PUT /api/admin/locations/{locationId}/sender-id // Authorization: Bearer // {"sender_id":"CAST"} func (h *AdminHandler) HandleSetSenderID(w http.ResponseWriter, r *http.Request) { if h.adminKey == "" || r.Header.Get("Authorization") != "Bearer "+h.adminKey { http.Error(w, "unauthorized", http.StatusUnauthorized) return } locationID := chi.URLParam(r, "locationId") if locationID == "" { http.Error(w, "missing locationId", http.StatusBadRequest) return } body, err := io.ReadAll(io.LimitReader(r.Body, 1024)) if err != nil { http.Error(w, "failed to read body", http.StatusBadRequest) return } var payload struct { SenderID string `json:"sender_id"` } if err := json.Unmarshal(body, &payload); err != nil { http.Error(w, "invalid JSON", http.StatusBadRequest) return } ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second) defer cancel() if err := h.store.UpdateSenderID(ctx, locationID, payload.SenderID); err != nil { slog.Error("admin: failed to update sender_id", "location_id", locationID, "err", err) if err.Error() == "location not found" { http.Error(w, "location not found", http.StatusNotFound) return } http.Error(w, "internal error", http.StatusInternalServerError) return } slog.Info("admin: sender_id updated", "location_id", locationID, "sender_id", payload.SenderID) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(`{"ok":true}`)) }