Initial vibeproxy implementation
Self-contained HTTP/HTTPS/TCP/UDP reverse proxy manager written in Go, with SQLite storage, a Bootstrap 5 admin UI (Go templates, no JS framework), and a REST API under /api/v1. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QTXFrNP1imCW7jtfL5SZrw
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/owen/vibeproxy/internal/database"
|
||||
)
|
||||
|
||||
type settingsDTO struct {
|
||||
ACMEEmail string `json:"acme_email"`
|
||||
ACMEStaging bool `json:"acme_staging"`
|
||||
ACMERenewalWindowDays int `json:"acme_renewal_window_days"`
|
||||
CertStoragePath string `json:"cert_storage_path"`
|
||||
LogRetentionDays int `json:"log_retention_days"`
|
||||
TrustedProxyCIDRs []string `json:"trusted_proxy_cidrs"`
|
||||
BackupEnabled bool `json:"backup_enabled"`
|
||||
BackupIntervalHours int `json:"backup_interval_hours"`
|
||||
BackupRetentionCount int `json:"backup_retention_count"`
|
||||
BackupPath string `json:"backup_path"`
|
||||
}
|
||||
|
||||
func (a *API) getSettings(w http.ResponseWriter, r *http.Request) {
|
||||
s := a.store.Current().Settings
|
||||
writeJSON(w, http.StatusOK, settingsDTO{
|
||||
ACMEEmail: s.ACMEEmail,
|
||||
ACMEStaging: s.ACMEStaging,
|
||||
ACMERenewalWindowDays: s.ACMERenewalWindowDays,
|
||||
CertStoragePath: s.CertStoragePath,
|
||||
LogRetentionDays: s.LogRetentionDays,
|
||||
TrustedProxyCIDRs: s.TrustedProxyCIDRs,
|
||||
BackupEnabled: s.BackupEnabled,
|
||||
BackupIntervalHours: s.BackupIntervalHours,
|
||||
BackupRetentionCount: s.BackupRetentionCount,
|
||||
BackupPath: s.BackupPath,
|
||||
})
|
||||
}
|
||||
|
||||
func (a *API) updateSettings(w http.ResponseWriter, r *http.Request) {
|
||||
var dto settingsDTO
|
||||
if !decodeJSON(w, r, &dto) {
|
||||
return
|
||||
}
|
||||
kv := map[string]string{
|
||||
"acme_email": dto.ACMEEmail,
|
||||
"acme_staging": strconv.FormatBool(dto.ACMEStaging),
|
||||
"acme_renewal_window_days": strconv.Itoa(dto.ACMERenewalWindowDays),
|
||||
"cert_storage_path": dto.CertStoragePath,
|
||||
"log_retention_days": strconv.Itoa(dto.LogRetentionDays),
|
||||
"trusted_proxy_cidrs": strings.Join(dto.TrustedProxyCIDRs, ","),
|
||||
"backup_enabled": strconv.FormatBool(dto.BackupEnabled),
|
||||
"backup_interval_hours": strconv.Itoa(dto.BackupIntervalHours),
|
||||
"backup_retention_count": strconv.Itoa(dto.BackupRetentionCount),
|
||||
"backup_path": dto.BackupPath,
|
||||
}
|
||||
for k, v := range kv {
|
||||
if err := database.SetSetting(a.db, k, v); err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
a.reload(r)
|
||||
audit(a.db, r, "settings_changed", "settings", "")
|
||||
writeJSON(w, http.StatusOK, dto)
|
||||
}
|
||||
Reference in New Issue
Block a user