Files
CaddyProxyManager/backend/internal/api/handler/hosts.go
Pacerino 2bc7cd5a98 [Backend] Wire providers/auth into API and add startup bootstrap
Route host changes through the selected Caddy provider, add auth routes
and the frontend-dir serving toggle, seed a default admin user on first
run, and validate space/comma separated domain lists via a custom
validator. Includes validator tests.
2026-06-14 02:35:28 +02:00

168 lines
4.6 KiB
Go

package handler
import (
"encoding/json"
"net/http"
h "github.com/Pacerino/CaddyProxyManager/internal/api/http"
"github.com/Pacerino/CaddyProxyManager/internal/caddy"
"github.com/Pacerino/CaddyProxyManager/internal/database"
"github.com/Pacerino/CaddyProxyManager/internal/jobqueue"
"gorm.io/gorm"
)
// GetHosts will return a list of Hosts
// Route: GET /hosts
func (s Handler) GetHosts() func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
var hosts []database.Host
if err := s.DB.Preload("Upstreams").Find(&hosts).Error; err != nil {
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
}
h.ResultResponseJSON(w, r, http.StatusOK, hosts)
}
}
// GetHost will return a single Host
// Route: GET /hosts/{hostID}
func (s Handler) GetHost() func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
var err error
var hostID int
var host database.Host
if hostID, err = getURLParamInt(r, "hostID"); err != nil {
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
return
}
if err = s.DB.Where("id = ?", hostID).Preload("Upstreams").First(&host).Error; err != nil {
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
} else {
h.ResultResponseJSON(w, r, http.StatusOK, host)
}
}
}
// CreateHost will create a Host
// Route: POST /hosts
func (s Handler) CreateHost() func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
var newHost database.Host
err := json.NewDecoder(r.Body).Decode(&newHost)
if err != nil {
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
return
}
if err := validate.Struct(newHost); err != nil {
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
return
}
result := s.DB.Create(&newHost)
if result.Error != nil {
h.ResultErrorJSON(w, r, http.StatusBadRequest, result.Error.Error(), nil)
return
}
provider, err := caddy.GetProvider()
if err != nil {
h.ResultErrorJSON(w, r, http.StatusInternalServerError, err.Error(), nil)
return
}
if err := jobqueue.AddJob(jobqueue.Job{
Name: "CaddyConfigureHost",
Action: func() error {
return provider.WriteHost(newHost)
},
}); err != nil {
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
return
}
h.ResultResponseJSON(w, r, http.StatusOK, newHost)
}
}
// UpdateHost updates a host
// Route: PUT /hosts
func (s Handler) UpdateHost() func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
var newHost database.Host
err := json.NewDecoder(r.Body).Decode(&newHost)
if err != nil {
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
return
}
if err := validate.Struct(newHost); err != nil {
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
return
}
provider, err := caddy.GetProvider()
if err != nil {
h.ResultErrorJSON(w, r, http.StatusInternalServerError, err.Error(), nil)
return
}
if err := jobqueue.AddJob(jobqueue.Job{
Name: "CaddyConfigureHost",
Action: func() error {
return provider.WriteHost(newHost)
},
}); err != nil {
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
return
}
result := s.DB.Session(&gorm.Session{FullSaveAssociations: true}).Save(&newHost)
if result.Error != nil {
h.ResultErrorJSON(w, r, http.StatusBadRequest, result.Error.Error(), nil)
return
}
h.ResultResponseJSON(w, r, http.StatusOK, newHost)
}
}
// DeleteHost removes a host
// Route: DELETE /hosts/{hostID}
func (s Handler) DeleteHost() func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
var err error
var hostID int
if hostID, err = getURLParamInt(r, "hostID"); err != nil {
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
return
}
provider, err := caddy.GetProvider()
if err != nil {
h.ResultErrorJSON(w, r, http.StatusInternalServerError, err.Error(), nil)
return
}
if err := jobqueue.AddJob(jobqueue.Job{
Name: "CaddyConfigureHost",
Action: func() error {
return provider.RemoveHost(hostID)
},
}); err != nil {
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
return
}
result := s.DB.Delete(&database.Host{}, hostID)
if result.Error != nil {
h.ResultErrorJSON(w, r, http.StatusBadRequest, result.Error.Error(), nil)
return
}
if result.RowsAffected > 0 {
h.ResultResponseJSON(w, r, http.StatusOK, true)
} else {
h.ResultErrorJSON(w, r, http.StatusBadRequest, h.ErrIDNotFound.Error(), nil)
}
}
}