Skip to content

Commit 93db076

Browse files
committed
webui: re-read console/netbrowse shortcuts on full page load
These two shortcuts are toggleable in the configuration but were only detected once at login and baked into the session, so disabling them didn't drop the topbar icon / user-menu entry until re-login. Refresh just those two from running-config on full page loads (htmx swaps and pollers, which never re-draw them, are skipped), so toggling takes effect on the next reload without logging out. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
1 parent 322811d commit 93db076

4 files changed

Lines changed: 28 additions & 6 deletions

File tree

src/webui/internal/auth/login.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,7 @@ func (h *LoginHandler) DoLogin(w http.ResponseWriter, r *http.Request) {
7979
// The external web-app shortcuts (console/ttyd, netbrowse) are
8080
// config-gated; fold them into the same feature map so templates gate
8181
// on .Capabilities.Has "console" / "netbrowse".
82-
console, netbrowse := handlers.DetectWebShortcuts(ctx, h.RC)
83-
caps.Features()["console"] = console
84-
caps.Features()["netbrowse"] = netbrowse
82+
handlers.ApplyWebShortcuts(ctx, h.RC, caps.Features())
8583
// The User's Guide is bundled at build time (a filesystem check, not
8684
// config); gate the Help entry on its presence.
8785
caps.Features()["docs"] = handlers.DetectDocs()

src/webui/internal/handlers/capabilities.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,14 @@ func DetectWebShortcuts(ctx context.Context, rc restconf.Fetcher) (console, netb
109109
return cfg.Web.Console.Enabled, cfg.Web.Netbrowse.Enabled
110110
}
111111

112+
// ApplyWebShortcuts writes the console/netbrowse capability flags into features
113+
// from running-config. These two are the only config-toggleable shortcuts, so
114+
// keeping the keys in one place lets both login (baking into the session) and
115+
// the per-page-load refresh share them.
116+
func ApplyWebShortcuts(ctx context.Context, rc restconf.Fetcher, features map[string]bool) {
117+
features["console"], features["netbrowse"] = DetectWebShortcuts(ctx, rc)
118+
}
119+
112120
func DetectCapabilities(ctx context.Context, rc restconf.Fetcher) *Capabilities {
113121
var lib yangLibrary
114122
if err := rc.Get(ctx, "/data/ietf-yang-library:yang-library", &lib); err != nil {

src/webui/internal/server/middleware.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
package server
44

55
import (
6+
"maps"
67
"net/http"
78
"net/url"
89
"strings"
@@ -19,7 +20,7 @@ const cookieName = "session"
1920
// the token up in the in-memory store, and attaches the session's
2021
// credentials to the context. Unauthenticated requests are
2122
// redirected to /login (or get a 401 if the request comes from HTMX).
22-
func authMiddleware(store *auth.SessionStore, next http.Handler) http.Handler {
23+
func authMiddleware(store *auth.SessionStore, rc restconf.Fetcher, next http.Handler) http.Handler {
2324
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2425
if isPublicPath(r.URL.Path) {
2526
next.ServeHTTP(w, r)
@@ -38,11 +39,13 @@ func authMiddleware(store *auth.SessionStore, next http.Handler) http.Handler {
3839
return
3940
}
4041

42+
polling := isPollingPath(r.URL.Path)
43+
4144
// Sliding window: extend the session on user-driven requests.
4245
// Background polling endpoints are excluded so an idle user
4346
// (just leaving the dashboard open in a tab) still hits the
4447
// timeout.
45-
if !isPollingPath(r.URL.Path) {
48+
if !polling {
4649
store.Refresh(cookie.Value)
4750
}
4851

@@ -51,6 +54,19 @@ func authMiddleware(store *auth.SessionStore, next http.Handler) http.Handler {
5154
Password: password,
5255
})
5356
ctx = security.WithToken(ctx, csrf)
57+
58+
// The console / netbrowse shortcuts are toggleable in running-config at
59+
// runtime, unlike the other (per-boot) capabilities baked into the
60+
// session at login. Re-read them on full page loads — the only time
61+
// the topbar/user-menu that host them re-render — so toggling takes
62+
// effect on reload without re-login. htmx fragment swaps and pollers
63+
// never re-draw them, so they're skipped (no read per request).
64+
fullPageLoad := !polling && r.Header.Get("HX-Request") != "true"
65+
if rc != nil && fullPageLoad {
66+
features = maps.Clone(features) // don't mutate the shared session map
67+
handlers.ApplyWebShortcuts(ctx, rc, features)
68+
}
69+
5470
ctx = handlers.ContextWithCapabilities(ctx, handlers.NewCapabilities(features))
5571
next.ServeHTTP(w, r.WithContext(ctx))
5672
})

src/webui/internal/server/server.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ func New(
480480
mux.HandleFunc("GET /status/tree/children", statusTreeH.TreeChildren)
481481
mux.HandleFunc("GET /status/tree/node", statusTreeH.TreeNode)
482482

483-
handler := authMiddleware(store, mux)
483+
handler := authMiddleware(store, rc, mux)
484484
handler = csrfMiddleware(handler)
485485
handler = securityHeadersMiddleware(handler)
486486
return handler, nil

0 commit comments

Comments
 (0)