package server import ( "encoding/json" "errors" "net/http" "strconv" "github.com/go-chi/chi/v5" "git.wntrmute.dev/kyle/mcns/internal/db" ) type createRecordRequest struct { Name string `json:"name"` Type string `json:"type"` Value string `json:"value"` TTL int `json:"ttl"` } func listRecordsHandler(database *db.DB) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { zoneName := chi.URLParam(r, "zone") nameFilter := r.URL.Query().Get("name") typeFilter := r.URL.Query().Get("type") records, err := database.ListRecords(zoneName, nameFilter, typeFilter) if errors.Is(err, db.ErrNotFound) { writeError(w, http.StatusNotFound, "zone not found") return } if err != nil { writeError(w, http.StatusInternalServerError, "failed to list records") return } if records == nil { records = []db.Record{} } writeJSON(w, http.StatusOK, map[string]any{"records": records}) } } func getRecordHandler(database *db.DB) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { idStr := chi.URLParam(r, "id") id, err := strconv.ParseInt(idStr, 10, 64) if err != nil { writeError(w, http.StatusBadRequest, "invalid record ID") return } record, err := database.GetRecord(id) if errors.Is(err, db.ErrNotFound) { writeError(w, http.StatusNotFound, "record not found") return } if err != nil { writeError(w, http.StatusInternalServerError, "failed to get record") return } writeJSON(w, http.StatusOK, record) } } func createRecordHandler(database *db.DB) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { zoneName := chi.URLParam(r, "zone") var req createRecordRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, "invalid request body") return } if req.Name == "" { writeError(w, http.StatusBadRequest, "name is required") return } if req.Type == "" { writeError(w, http.StatusBadRequest, "type is required") return } if req.Value == "" { writeError(w, http.StatusBadRequest, "value is required") return } record, err := database.CreateRecord(zoneName, req.Name, req.Type, req.Value, req.TTL) if errors.Is(err, db.ErrNotFound) { writeError(w, http.StatusNotFound, "zone not found") return } if errors.Is(err, db.ErrConflict) { writeError(w, http.StatusConflict, err.Error()) return } if err != nil { writeError(w, http.StatusBadRequest, err.Error()) return } writeJSON(w, http.StatusCreated, record) } } func updateRecordHandler(database *db.DB) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { idStr := chi.URLParam(r, "id") id, err := strconv.ParseInt(idStr, 10, 64) if err != nil { writeError(w, http.StatusBadRequest, "invalid record ID") return } var req createRecordRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, "invalid request body") return } if req.Name == "" { writeError(w, http.StatusBadRequest, "name is required") return } if req.Type == "" { writeError(w, http.StatusBadRequest, "type is required") return } if req.Value == "" { writeError(w, http.StatusBadRequest, "value is required") return } record, err := database.UpdateRecord(id, req.Name, req.Type, req.Value, req.TTL) if errors.Is(err, db.ErrNotFound) { writeError(w, http.StatusNotFound, "record not found") return } if errors.Is(err, db.ErrConflict) { writeError(w, http.StatusConflict, err.Error()) return } if err != nil { writeError(w, http.StatusBadRequest, err.Error()) return } writeJSON(w, http.StatusOK, record) } } func deleteRecordHandler(database *db.DB) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { idStr := chi.URLParam(r, "id") id, err := strconv.ParseInt(idStr, 10, 64) if err != nil { writeError(w, http.StatusBadRequest, "invalid record ID") return } err = database.DeleteRecord(id) if errors.Is(err, db.ErrNotFound) { writeError(w, http.StatusNotFound, "record not found") return } if err != nil { writeError(w, http.StatusInternalServerError, "failed to delete record") return } w.WriteHeader(http.StatusNoContent) } }