feat: ent ORM, admin UI, client auth, Fyne GUI, Windows/MSI packaging

This commit is contained in:
kannn
2026-05-29 08:58:22 +00:00
Unverified
parent 8563a5fc74
commit a0a42a4966
81 changed files with 17144 additions and 89 deletions
+107
View File
@@ -0,0 +1,107 @@
<div class="toolbar">
<h1>Settings</h1>
<div class="spacer"></div>
{{if .Saved}}
<span style="font-size:12px;color:var(--fg2)">Saved. Restart to apply.</span>
{{end}}
</div>
<form hx-post="/admin/settings" hx-target="body" hx-push-url="true">
<div style="border:1px solid var(--border);padding:20px;margin-bottom:16px">
<h2 style="font-size:12px;font-weight:600;letter-spacing:.3px;color:var(--fg2);margin-bottom:16px;text-transform:uppercase">Server</h2>
<div class="grid-2" style="margin-bottom:0">
<div><label style="display:block;font-size:12px;color:var(--fg2);margin-bottom:4px">Bind Address</label><input type="text" name="bind_addr" value="{{.Config.BindAddr}}"></div>
<div><label style="display:block;font-size:12px;color:var(--fg2);margin-bottom:4px">Bind Port</label><input type="number" name="bind_port" value="{{.Config.BindPort}}"></div>
<div><label style="display:block;font-size:12px;color:var(--fg2);margin-bottom:4px">Proxy Bind Address</label><input type="text" name="proxy_bind_addr" value="{{.Config.ProxyBindAddr}}"></div>
<div></div>
</div>
</div>
<div style="border:1px solid var(--border);padding:20px;margin-bottom:16px">
<h2 style="font-size:12px;font-weight:600;letter-spacing:.3px;color:var(--fg2);margin-bottom:16px;text-transform:uppercase">Dashboard</h2>
<div class="grid-2" style="margin-bottom:0">
<div><label style="display:block;font-size:12px;color:var(--fg2);margin-bottom:4px">Address</label><input type="text" name="dashboard_addr" value="{{.Config.WebServer.Addr}}"></div>
<div><label style="display:block;font-size:12px;color:var(--fg2);margin-bottom:4px">Port</label><input type="number" name="dashboard_port" value="{{.Config.WebServer.Port}}"></div>
<div><label style="display:block;font-size:12px;color:var(--fg2);margin-bottom:4px">Username</label><input type="text" name="dashboard_user" value="{{.Config.WebServer.User}}" autocomplete="off"></div>
<div><label style="display:block;font-size:12px;color:var(--fg2);margin-bottom:4px">Password</label><input type="text" name="dashboard_password" value="{{.Config.WebServer.Password}}" autocomplete="off"></div>
</div>
</div>
<div style="border:1px solid var(--border);padding:20px;margin-bottom:16px">
<h2 style="font-size:12px;font-weight:600;letter-spacing:.3px;color:var(--fg2);margin-bottom:16px;text-transform:uppercase">Authentication</h2>
<div class="grid-2" style="margin-bottom:0">
<div><label style="display:block;font-size:12px;color:var(--fg2);margin-bottom:4px">Auth Method</label>
<select name="auth_method">
<option value="token"{{if eq .Config.Auth.Method "token"}} selected{{end}}>Token</option>
<option value="oidc"{{if eq .Config.Auth.Method "oidc"}} selected{{end}}>OIDC</option>
</select>
</div>
<div><label style="display:block;font-size:12px;color:var(--fg2);margin-bottom:4px">Token</label><input type="text" name="auth_token" value="{{.Config.Auth.Token}}" autocomplete="off"></div>
</div>
</div>
<div style="border:1px solid var(--border);padding:20px;margin-bottom:16px">
<h2 style="font-size:12px;font-weight:600;letter-spacing:.3px;color:var(--fg2);margin-bottom:16px;text-transform:uppercase">HTTP / VHost</h2>
<div class="grid-2" style="margin-bottom:0">
<div><label style="display:block;font-size:12px;color:var(--fg2);margin-bottom:4px">VHost HTTP Port</label><input type="number" name="vhost_http_port" value="{{.Config.VhostHTTPPort}}" placeholder="0 = disabled"></div>
<div><label style="display:block;font-size:12px;color:var(--fg2);margin-bottom:4px">VHost HTTPS Port</label><input type="number" name="vhost_https_port" value="{{.Config.VhostHTTPSPort}}" placeholder="0 = disabled"></div>
<div><label style="display:block;font-size:12px;color:var(--fg2);margin-bottom:4px">Subdomain Host</label><input type="text" name="subdomain_host" value="{{.Config.SubDomainHost}}"></div>
<div></div>
</div>
</div>
<div style="border:1px solid var(--border);padding:20px;margin-bottom:16px">
<h2 style="font-size:12px;font-weight:600;letter-spacing:.3px;color:var(--fg2);margin-bottom:16px;text-transform:uppercase">Transport</h2>
<div class="grid-2" style="margin-bottom:0">
<div style="display:flex;align-items:center;gap:8px;padding-top:20px">
<input type="checkbox" name="tcp_mux" value="true" style="width:auto"{{if .Config.Transport.TCPMux}} checked{{end}}>
<label style="font-size:13px">TCP Multiplexing</label>
</div>
<div><label style="display:block;font-size:12px;color:var(--fg2);margin-bottom:4px">Max Pool Count</label><input type="number" name="max_pool_count" value="{{.Config.Transport.MaxPoolCount}}" placeholder="0 = unlimited"></div>
</div>
</div>
<div style="border:1px solid var(--border);padding:20px;margin-bottom:16px">
<h2 style="font-size:12px;font-weight:600;letter-spacing:.3px;color:var(--fg2);margin-bottom:16px;text-transform:uppercase">Logging</h2>
<div class="grid-2" style="margin-bottom:0">
<div><label style="display:block;font-size:12px;color:var(--fg2);margin-bottom:4px">Output</label>
<select name="log_to">
<option value="console"{{if eq .Config.Log.To "console"}} selected{{end}}>Console</option>
<option value="file"{{if eq .Config.Log.To "file"}} selected{{end}}>File</option>
</select>
</div>
<div><label style="display:block;font-size:12px;color:var(--fg2);margin-bottom:4px">Level</label>
<select name="log_level">
<option value="trace"{{if eq .Config.Log.Level "trace"}} selected{{end}}>Trace</option>
<option value="debug"{{if eq .Config.Log.Level "debug"}} selected{{end}}>Debug</option>
<option value="info"{{if eq .Config.Log.Level "info"}} selected{{end}}>Info</option>
<option value="warn"{{if eq .Config.Log.Level "warn"}} selected{{end}}>Warn</option>
<option value="error"{{if eq .Config.Log.Level "error"}} selected{{end}}>Error</option>
</select>
</div>
<div><label style="display:block;font-size:12px;color:var(--fg2);margin-bottom:4px">Max Days</label><input type="number" name="log_max_days" value="{{.Config.Log.MaxDays}}"></div>
<div></div>
</div>
</div>
<div style="border:1px solid var(--border);padding:20px;margin-bottom:16px">
<h2 style="font-size:12px;font-weight:600;letter-spacing:.3px;color:var(--fg2);margin-bottom:16px;text-transform:uppercase">Extra Ports</h2>
<div class="grid-2" style="margin-bottom:0">
<div><label style="display:block;font-size:12px;color:var(--fg2);margin-bottom:4px">KCP Bind Port</label><input type="number" name="kcp_bind_port" value="{{.Config.KCPBindPort}}" placeholder="0 = disabled"></div>
<div><label style="display:block;font-size:12px;color:var(--fg2);margin-bottom:4px">QUIC Bind Port</label><input type="number" name="quic_bind_port" value="{{.Config.QUICBindPort}}" placeholder="0 = disabled"></div>
</div>
</div>
<div style="border:1px solid var(--border);padding:20px;margin-bottom:16px">
<h2 style="font-size:12px;font-weight:600;letter-spacing:.3px;color:var(--fg2);margin-bottom:16px;text-transform:uppercase">Misc</h2>
<div style="display:flex;align-items:center;gap:8px;margin-bottom:16px">
<input type="checkbox" name="enable_prometheus" value="true" style="width:auto"{{if .Config.EnablePrometheus}} checked{{end}}>
<label style="font-size:13px">Enable Prometheus Metrics</label>
</div>
</div>
<div class="toolbar" style="margin-top:24px">
<button type="submit">Save Configuration</button>
<a href="/admin/dashboard" class="btn btn-outline" hx-get="/admin/dashboard" hx-target="#main-content" hx-push-url="true">Cancel</a>
</div>
</form>