mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-22 01:13:00 +02:00
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>
This commit is contained in:
@@ -79,9 +79,7 @@ func (h *LoginHandler) DoLogin(w http.ResponseWriter, r *http.Request) {
|
||||
// The external web-app shortcuts (console/ttyd, netbrowse) are
|
||||
// config-gated; fold them into the same feature map so templates gate
|
||||
// on .Capabilities.Has "console" / "netbrowse".
|
||||
console, netbrowse := handlers.DetectWebShortcuts(ctx, h.RC)
|
||||
caps.Features()["console"] = console
|
||||
caps.Features()["netbrowse"] = netbrowse
|
||||
handlers.ApplyWebShortcuts(ctx, h.RC, caps.Features())
|
||||
// The User's Guide is bundled at build time (a filesystem check, not
|
||||
// config); gate the Help entry on its presence.
|
||||
caps.Features()["docs"] = handlers.DetectDocs()
|
||||
|
||||
@@ -109,6 +109,14 @@ func DetectWebShortcuts(ctx context.Context, rc restconf.Fetcher) (console, netb
|
||||
return cfg.Web.Console.Enabled, cfg.Web.Netbrowse.Enabled
|
||||
}
|
||||
|
||||
// ApplyWebShortcuts writes the console/netbrowse capability flags into features
|
||||
// from running-config. These two are the only config-toggleable shortcuts, so
|
||||
// keeping the keys in one place lets both login (baking into the session) and
|
||||
// the per-page-load refresh share them.
|
||||
func ApplyWebShortcuts(ctx context.Context, rc restconf.Fetcher, features map[string]bool) {
|
||||
features["console"], features["netbrowse"] = DetectWebShortcuts(ctx, rc)
|
||||
}
|
||||
|
||||
func DetectCapabilities(ctx context.Context, rc restconf.Fetcher) *Capabilities {
|
||||
var lib yangLibrary
|
||||
if err := rc.Get(ctx, "/data/ietf-yang-library:yang-library", &lib); err != nil {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"maps"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
@@ -19,7 +20,7 @@ const cookieName = "session"
|
||||
// the token up in the in-memory store, and attaches the session's
|
||||
// credentials to the context. Unauthenticated requests are
|
||||
// redirected to /login (or get a 401 if the request comes from HTMX).
|
||||
func authMiddleware(store *auth.SessionStore, next http.Handler) http.Handler {
|
||||
func authMiddleware(store *auth.SessionStore, rc restconf.Fetcher, next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if isPublicPath(r.URL.Path) {
|
||||
next.ServeHTTP(w, r)
|
||||
@@ -38,11 +39,13 @@ func authMiddleware(store *auth.SessionStore, next http.Handler) http.Handler {
|
||||
return
|
||||
}
|
||||
|
||||
polling := isPollingPath(r.URL.Path)
|
||||
|
||||
// Sliding window: extend the session on user-driven requests.
|
||||
// Background polling endpoints are excluded so an idle user
|
||||
// (just leaving the dashboard open in a tab) still hits the
|
||||
// timeout.
|
||||
if !isPollingPath(r.URL.Path) {
|
||||
if !polling {
|
||||
store.Refresh(cookie.Value)
|
||||
}
|
||||
|
||||
@@ -51,6 +54,19 @@ func authMiddleware(store *auth.SessionStore, next http.Handler) http.Handler {
|
||||
Password: password,
|
||||
})
|
||||
ctx = security.WithToken(ctx, csrf)
|
||||
|
||||
// The console / netbrowse shortcuts are toggleable in running-config at
|
||||
// runtime, unlike the other (per-boot) capabilities baked into the
|
||||
// session at login. Re-read them on full page loads — the only time
|
||||
// the topbar/user-menu that host them re-render — so toggling takes
|
||||
// effect on reload without re-login. htmx fragment swaps and pollers
|
||||
// never re-draw them, so they're skipped (no read per request).
|
||||
fullPageLoad := !polling && r.Header.Get("HX-Request") != "true"
|
||||
if rc != nil && fullPageLoad {
|
||||
features = maps.Clone(features) // don't mutate the shared session map
|
||||
handlers.ApplyWebShortcuts(ctx, rc, features)
|
||||
}
|
||||
|
||||
ctx = handlers.ContextWithCapabilities(ctx, handlers.NewCapabilities(features))
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
})
|
||||
|
||||
@@ -480,7 +480,7 @@ func New(
|
||||
mux.HandleFunc("GET /status/tree/children", statusTreeH.TreeChildren)
|
||||
mux.HandleFunc("GET /status/tree/node", statusTreeH.TreeNode)
|
||||
|
||||
handler := authMiddleware(store, mux)
|
||||
handler := authMiddleware(store, rc, mux)
|
||||
handler = csrfMiddleware(handler)
|
||||
handler = securityHeadersMiddleware(handler)
|
||||
return handler, nil
|
||||
|
||||
Reference in New Issue
Block a user