Files
NexaVPN/backend/internal/servicecatalog/handler.go
nessi 6cf49ff3e0 feat: add service catalog management with policy integration for domain-based resource access control
Add ServiceCatalogItem type and services CRUD API endpoints (list, create, update, delete). Extend Policy type to include services array with domain, upstream_ip, proxy_ip, and ports metadata.

Add ServicesPage component with table view and create/edit modals for managing service definitions. Include service name, domain, proxy, and upstream columns with port parsing logic.

Integrate service selection
2026-03-18 13:09:54 +01:00

79 lines
2.1 KiB
Go

package servicecatalog
import (
"encoding/json"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/google/uuid"
"nexavpn/backend/internal/apiutil"
)
type Handler struct {
service *CatalogService
}
func NewHandler(service *CatalogService) *Handler {
return &Handler{service: service}
}
func (h *Handler) List(w http.ResponseWriter, r *http.Request) {
items, err := h.service.List(r.Context())
if err != nil {
apiutil.Error(w, http.StatusInternalServerError, "services_list_failed", "unable to list services")
return
}
apiutil.JSON(w, http.StatusOK, items)
}
func (h *Handler) Create(w http.ResponseWriter, r *http.Request) {
var input CreateRequest
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
apiutil.Error(w, http.StatusBadRequest, "invalid_json", "invalid request body")
return
}
item, err := h.service.Create(r.Context(), input)
if err != nil {
apiutil.Error(w, http.StatusInternalServerError, "service_create_failed", "unable to create service")
return
}
apiutil.JSON(w, http.StatusCreated, item)
}
func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
serviceID, err := uuid.Parse(chi.URLParam(r, "id"))
if err != nil {
apiutil.Error(w, http.StatusBadRequest, "invalid_service_id", "invalid service id")
return
}
var input UpdateRequest
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
apiutil.Error(w, http.StatusBadRequest, "invalid_json", "invalid request body")
return
}
item, err := h.service.Update(r.Context(), serviceID, input)
if err != nil {
apiutil.Error(w, http.StatusInternalServerError, "service_update_failed", "unable to update service")
return
}
apiutil.JSON(w, http.StatusOK, item)
}
func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {
serviceID, err := uuid.Parse(chi.URLParam(r, "id"))
if err != nil {
apiutil.Error(w, http.StatusBadRequest, "invalid_service_id", "invalid service id")
return
}
if err := h.service.Delete(r.Context(), serviceID); err != nil {
apiutil.Error(w, http.StatusInternalServerError, "service_delete_failed", "unable to delete service")
return
}
apiutil.JSON(w, http.StatusOK, map[string]any{"ok": true})
}