platform: modularize api/gui, add docs-tests-web foundation, and refresh root config
This commit is contained in:
108
selective-vpn-api/app/transport_bootstrap_bypass_state.go
Normal file
108
selective-vpn-api/app/transport_bootstrap_bypass_state.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/netip"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func loadTransportBootstrapState() transportBootstrapState {
|
||||
st := transportBootstrapState{Version: transportBootstrapStateVersion}
|
||||
data, err := os.ReadFile(transportBootstrapStatePath)
|
||||
if err != nil {
|
||||
return st
|
||||
}
|
||||
if err := json.Unmarshal(data, &st); err != nil {
|
||||
return transportBootstrapState{Version: transportBootstrapStateVersion}
|
||||
}
|
||||
return normalizeTransportBootstrapState(st)
|
||||
}
|
||||
|
||||
func saveTransportBootstrapState(st transportBootstrapState) error {
|
||||
st = normalizeTransportBootstrapState(st)
|
||||
st.Version = transportBootstrapStateVersion
|
||||
st.UpdatedAt = time.Now().UTC().Format(time.RFC3339)
|
||||
|
||||
data, err := json.MarshalIndent(st, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Dir(transportBootstrapStatePath), 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
tmp := transportBootstrapStatePath + ".tmp"
|
||||
if err := os.WriteFile(tmp, data, 0o644); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Rename(tmp, transportBootstrapStatePath)
|
||||
}
|
||||
|
||||
func normalizeTransportBootstrapState(st transportBootstrapState) transportBootstrapState {
|
||||
st.Version = transportBootstrapStateVersion
|
||||
if len(st.Clients) == 0 {
|
||||
st.Clients = nil
|
||||
return st
|
||||
}
|
||||
out := make(map[string][]string, len(st.Clients))
|
||||
for rawID, rawIPs := range st.Clients {
|
||||
id := sanitizeID(rawID)
|
||||
if id == "" {
|
||||
continue
|
||||
}
|
||||
ips := normalizeBootstrapIPv4List(rawIPs)
|
||||
if len(ips) == 0 {
|
||||
continue
|
||||
}
|
||||
out[id] = ips
|
||||
}
|
||||
if len(out) == 0 {
|
||||
st.Clients = nil
|
||||
return st
|
||||
}
|
||||
st.Clients = out
|
||||
return st
|
||||
}
|
||||
|
||||
func normalizeBootstrapIPv4List(in []string) []string {
|
||||
seen := map[string]struct{}{}
|
||||
out := make([]string, 0, len(in))
|
||||
for _, raw := range in {
|
||||
ip := strings.TrimSpace(raw)
|
||||
addr, err := netip.ParseAddr(ip)
|
||||
if err != nil || !addr.Is4() {
|
||||
continue
|
||||
}
|
||||
key := addr.String()
|
||||
if _, ok := seen[key]; ok {
|
||||
continue
|
||||
}
|
||||
seen[key] = struct{}{}
|
||||
out = append(out, key)
|
||||
}
|
||||
sort.Strings(out)
|
||||
return out
|
||||
}
|
||||
|
||||
func dedupeStrings(in []string) []string {
|
||||
if len(in) == 0 {
|
||||
return nil
|
||||
}
|
||||
seen := map[string]struct{}{}
|
||||
out := make([]string, 0, len(in))
|
||||
for _, raw := range in {
|
||||
v := strings.TrimSpace(raw)
|
||||
if v == "" {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[v]; ok {
|
||||
continue
|
||||
}
|
||||
seen[v] = struct{}{}
|
||||
out = append(out, v)
|
||||
}
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user