14.04.2026 Update
This commit is contained in:
@@ -6,9 +6,9 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"alpine-router/clients"
|
||||
"alpine-router/config"
|
||||
"alpine-router/dhcp"
|
||||
"nano-router/clients"
|
||||
"nano-router/config"
|
||||
"nano-router/dhcp"
|
||||
)
|
||||
|
||||
func HandleClients(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -42,13 +42,14 @@ func HandleClientUpdate(w http.ResponseWriter, r *http.Request) {
|
||||
Hostname string `json:"hostname"`
|
||||
Blocked bool `json:"blocked"`
|
||||
StaticIP string `json:"static_ip"`
|
||||
Policy string `json:"policy"` // "disabled" | "direct" | "vpn" | ""
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
fail(w, http.StatusBadRequest, "invalid json: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := updateClient(mac, req.Hostname, req.Blocked, req.StaticIP); err != nil {
|
||||
if err := updateClient(mac, req.Hostname, req.Blocked, req.StaticIP, req.Policy); err != nil {
|
||||
fail(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
@@ -58,7 +59,88 @@ func HandleClientUpdate(w http.ResponseWriter, r *http.Request) {
|
||||
ok(w, map[string]string{"message": "updated"})
|
||||
}
|
||||
|
||||
func updateClient(mac, hostname string, blocked bool, staticIP string) error {
|
||||
// HandleClientPolicyDefault handles GET/POST for the default client routing policy.
|
||||
func HandleClientPolicyDefault(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
cfg, err := config.Load()
|
||||
if err != nil {
|
||||
fail(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
ok(w, map[string]string{"default": cfg.ClientPolicy.Default})
|
||||
|
||||
case http.MethodPost:
|
||||
var req struct {
|
||||
Default string `json:"default"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
fail(w, http.StatusBadRequest, "invalid json: "+err.Error())
|
||||
return
|
||||
}
|
||||
if req.Default != "disabled" && req.Default != "direct" && req.Default != "vpn" {
|
||||
fail(w, http.StatusBadRequest, "invalid policy: must be disabled, direct, or vpn")
|
||||
return
|
||||
}
|
||||
cfg, err := config.Load()
|
||||
if err != nil {
|
||||
fail(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
cfg.ClientPolicy.Default = req.Default
|
||||
if err := config.Save(cfg); err != nil {
|
||||
fail(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
go applyBlockedFirewall()
|
||||
ok(w, map[string]string{"default": req.Default})
|
||||
|
||||
default:
|
||||
fail(w, http.StatusMethodNotAllowed, "method not allowed")
|
||||
}
|
||||
}
|
||||
|
||||
// HandleClientPolicyApplyAll sets the given policy on every known device.
|
||||
func HandleClientPolicyApplyAll(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
fail(w, http.StatusMethodNotAllowed, "method not allowed")
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
Policy string `json:"policy"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
fail(w, http.StatusBadRequest, "invalid json: "+err.Error())
|
||||
return
|
||||
}
|
||||
if req.Policy != "disabled" && req.Policy != "direct" && req.Policy != "vpn" {
|
||||
fail(w, http.StatusBadRequest, "invalid policy: must be disabled, direct, or vpn")
|
||||
return
|
||||
}
|
||||
|
||||
cfg, err := config.Load()
|
||||
if err != nil {
|
||||
fail(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
for i := range cfg.KnownDevices {
|
||||
cfg.KnownDevices[i].Policy = req.Policy
|
||||
// Keep Blocked flag consistent: disabled policy means blocked.
|
||||
cfg.KnownDevices[i].Blocked = req.Policy == "disabled"
|
||||
}
|
||||
|
||||
if err := config.Save(cfg); err != nil {
|
||||
fail(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
go applyBlockedFirewall()
|
||||
ok(w, map[string]int{"updated": len(cfg.KnownDevices)})
|
||||
}
|
||||
|
||||
func updateClient(mac, hostname string, blocked bool, staticIP, policy string) error {
|
||||
cfg, err := config.Load()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -67,9 +149,11 @@ func updateClient(mac, hostname string, blocked bool, staticIP string) error {
|
||||
found := false
|
||||
for i := range cfg.KnownDevices {
|
||||
if cfg.KnownDevices[i].MAC == mac {
|
||||
cfg.KnownDevices[i].Blocked = blocked
|
||||
cfg.KnownDevices[i].Hostname = hostname
|
||||
cfg.KnownDevices[i].StaticIP = staticIP
|
||||
cfg.KnownDevices[i].Policy = policy
|
||||
// Derive Blocked from policy for backward compatibility.
|
||||
cfg.KnownDevices[i].Blocked = policy == "disabled"
|
||||
found = true
|
||||
break
|
||||
}
|
||||
@@ -79,15 +163,15 @@ func updateClient(mac, hostname string, blocked bool, staticIP string) error {
|
||||
cfg.KnownDevices = append(cfg.KnownDevices, config.KnownDevice{
|
||||
MAC: mac,
|
||||
Hostname: hostname,
|
||||
Blocked: blocked,
|
||||
StaticIP: staticIP,
|
||||
Policy: policy,
|
||||
Blocked: policy == "disabled",
|
||||
})
|
||||
}
|
||||
|
||||
return config.Save(cfg)
|
||||
}
|
||||
|
||||
|
||||
func applyDHCPStaticBindings() {
|
||||
if !dhcp.IsInstalled() {
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user