Add admin dashboard at / with bearer-token overview API

This commit is contained in:
2026-10-25 15:12:33 +08:00
parent 4acf226455
commit f5fcdd7bbb
9 changed files with 545 additions and 10 deletions
+15
View File
@@ -7,6 +7,7 @@ import (
"io/fs"
"os"
"path/filepath"
"sort"
"sync"
"time"
)
@@ -25,6 +26,7 @@ type storedTunnel struct {
ID string `json:"id"`
Hostname string `json:"hostname"`
TokenHash string `json:"tokenHash"`
CreatedAt string `json:"createdAt,omitempty"`
Certificate *storedCert `json:"certificate,omitempty"`
}
@@ -125,6 +127,7 @@ func (s *Store) createTunnel(domain string) (storedTunnel, string, error) {
t := storedTunnel{
ID: slug(),
TokenHash: hashToken(token),
CreatedAt: time.Now().UTC().Format(time.RFC3339),
}
t.Hostname = t.ID + "." + domain
s.mu.Lock()
@@ -141,6 +144,18 @@ func (s *Store) get(id string) (storedTunnel, bool) {
return t, ok
}
// Tunnels returns every tunnel, sorted by hostname (for the admin dashboard).
func (s *Store) Tunnels() []storedTunnel {
s.mu.Lock()
defer s.mu.Unlock()
out := make([]storedTunnel, 0, len(s.data.Tunnels))
for _, t := range s.data.Tunnels {
out = append(out, t)
}
sort.Slice(out, func(i, j int) bool { return out[i].Hostname < out[j].Hostname })
return out
}
// bindCSR records the issued certificate for the tunnel. The CSR is kept so a
// renewal (and a resumed provision) can be answered without a new bind.
func (s *Store) bindCertificate(id string, cert storedCert) error {