From 4b4472b0667e0155caea1eca7252a042ba30a936 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Fri, 9 Jan 2026 08:14:48 -0500 Subject: [PATCH 1/6] update tests with helper func to delete wg interfaces --- wireguard_test.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/wireguard_test.go b/wireguard_test.go index f5b9a18..0cbccf9 100644 --- a/wireguard_test.go +++ b/wireguard_test.go @@ -12,6 +12,7 @@ import ( ) func TestNew(t *testing.T) { + deleteAllWireguardInterfaces(t) user, err := user.Current() should.NotBeError(t, err) if user.Uid != "0" { @@ -182,3 +183,15 @@ func TestGet(t *testing.T) { should.BeError(t, err) }) } + +func deleteAllWireguardInterfaces(t *testing.T) { + t.Helper() + links, err := netlink.LinkList() + should.NotBeError(t, err) + for _, link := range links { + if link.Type() == "wireguard" { + err := netlink.LinkDel(link) + should.NotBeError(t, err) + } + } +} From a8c9c39ad81a020ca795b5af4f38bdada1c1f8e7 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Fri, 9 Jan 2026 08:23:09 -0500 Subject: [PATCH 2/6] updated session handling --- internal/server/keys.go | 8 +-- internal/server/networks.go | 28 ++-------- internal/server/page.go | 19 +++---- internal/server/router.go | 13 ++--- internal/server/router_test.go | 4 +- internal/server/sessions.go | 94 ++++++++++------------------------ internal/server/users.go | 68 ++++++------------------ 7 files changed, 64 insertions(+), 170 deletions(-) diff --git a/internal/server/keys.go b/internal/server/keys.go index bf080f5..ee08235 100644 --- a/internal/server/keys.go +++ b/internal/server/keys.go @@ -19,12 +19,8 @@ import ( ) func displayCreateKey(w http.ResponseWriter, r *http.Request) { - session := GetSession(w, r) - if session == nil { - displayLogin(w, r) - return - } - page := getPage(session.UserName) + session := GetSessionData(r) + page := getPage(session.Username) page.Page = "addKey" if err := templates.ExecuteTemplate(w, "addKey", page); err != nil { slog.Error("execute template", "template", "addKey", "page", page, "error", err) diff --git a/internal/server/networks.go b/internal/server/networks.go index 9f44bfd..3da41b6 100644 --- a/internal/server/networks.go +++ b/internal/server/networks.go @@ -16,17 +16,10 @@ import ( ) func displayAddNetwork(w http.ResponseWriter, r *http.Request) { - session := GetSession(w, r) - if session == nil { - displayLogin(w, r) - return - } - page := getPage(session.UserName) + session := GetSessionData(r) + page := getPage(session.Username) page.Page = "addNetwork" - if err := session.Session.Save(r, w); err != nil { - slog.Error("session save", "error", err) - } if err := templates.ExecuteTemplate(w, "addNetwork", page); err != nil { slog.Error("template", "name", "addnetwork", "error", err) } @@ -80,12 +73,8 @@ func addNetwork(w http.ResponseWriter, r *http.Request) { } func displayNetworks(w http.ResponseWriter, r *http.Request) { - session := GetSession(w, r) - if session == nil { - displayLogin(w, r) - return - } - page := getPage(session.UserName) + session := GetSessionData(r) + page := getPage(session.Username) networks, err := boltdb.GetAll[plexus.Network](networkTable) if err != nil { processError(w, http.StatusInternalServerError, err.Error()) @@ -93,7 +82,6 @@ func displayNetworks(w http.ResponseWriter, r *http.Request) { } page.Data = networks - session.Save(w, r) w.Header().Add("Hx-Trigger", "networkChange") if err := templates.ExecuteTemplate(w, "networks", page); err != nil { slog.Error("template", "name", "networks", "page", page, "error", err) @@ -148,11 +136,6 @@ func networkAddPeer(w http.ResponseWriter, r *http.Request) { } func networkDetails(w http.ResponseWriter, r *http.Request) { - session := GetSession(w, r) - if session == nil { - displayLogin(w, r) - return - } details := struct { Name string Peers []plexus.NetworkPeer @@ -187,9 +170,6 @@ func networkDetails(w http.ResponseWriter, r *http.Request) { } details.Name = networkName details.AvailablePeers = getAvailablePeers(network) - if err := session.Session.Save(r, w); err != nil { - slog.Error("session save", "error", err) - } if err := templates.ExecuteTemplate(w, "networkDetails", details); err != nil { slog.Error("template", "template", "networkDetails", "details", details, "error", err) } diff --git a/internal/server/page.go b/internal/server/page.go index 22b6c4f..2e221be 100644 --- a/internal/server/page.go +++ b/internal/server/page.go @@ -34,15 +34,13 @@ func init() { func displayMain(w http.ResponseWriter, r *http.Request) { page := initialize() page.NeedsLogin = true - session := GetSession(w, r) - if session != nil { - networks, err := boltdb.GetAll[plexus.Network](networkTable) - if err != nil { - slog.Error("get networks for main display", "error", err) - } - page.Data = networks - page.NeedsLogin = !session.LoggedIn + session := GetSession(r) + networks, err := boltdb.GetAll[plexus.Network](networkTable) + if err != nil { + slog.Error("get networks for main display", "error", err) } + page.Data = networks + page.NeedsLogin = session.IsNew slog.Info("display main page", "session", session, "page", page) if err := templates.ExecuteTemplate(w, "layout", page); err != nil { @@ -59,7 +57,8 @@ func login(w http.ResponseWriter, r *http.Request) { processError(w, http.StatusBadRequest, "invalid user") return } - NewSession(w, r, user, true, "networks") + user.Password = "" // clear password. + saveSession(w, r, user) slog.Debug("login", "user", user.Username) page := getPage(user.Username) @@ -94,8 +93,6 @@ func checkPassword(plain, hash *plexus.User) bool { func logout(w http.ResponseWriter, r *http.Request) { ClearSession(w, r) slog.Debug("logout") - // page := initialize() - // page.NeedsLogin = true http.Redirect(w, r, "/", http.StatusFound) } diff --git a/internal/server/router.go b/internal/server/router.go index 3c9ccdc..49e7d65 100644 --- a/internal/server/router.go +++ b/internal/server/router.go @@ -92,18 +92,11 @@ func processError(w http.ResponseWriter, status int, message string) { func auth(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - session := GetSession(w, r) - if session == nil { - displayLogin(w, r) + session := GetSession(r) + if session.IsNew { + http.Redirect(w, r, "/login/", http.StatusUnauthorized) return } - if !session.LoggedIn { - displayLogin(w, r) - return - } - if err := session.Session.Save(r, w); err != nil { - slog.Error("save session", "error", err) - } next.ServeHTTP(w, r) }) } diff --git a/internal/server/router_test.go b/internal/server/router_test.go index 1ac2ed1..0c6238b 100644 --- a/internal/server/router_test.go +++ b/internal/server/router_test.go @@ -44,8 +44,8 @@ func TestAuthFail(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/server/", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) - should.BeEqual(t, w.Code, http.StatusOK) + should.BeEqual(t, w.Code, http.StatusUnauthorized) body, err := io.ReadAll(w.Body) should.NotBeError(t, err) - should.ContainSubstring(t, string(body), "

Login Date: Fri, 9 Jan 2026 08:55:05 -0500 Subject: [PATCH 3/6] common func for rendering templates --- internal/server/keys.go | 8 ++------ internal/server/networks.go | 25 +++++-------------------- internal/server/page.go | 29 ++++++++++++++++++++--------- internal/server/peers.go | 8 ++------ internal/server/relay.go | 4 +--- internal/server/router.go | 32 -------------------------------- internal/server/server.go | 4 +--- internal/server/subnetrouter.go | 4 +--- internal/server/users.go | 16 ++++------------ 9 files changed, 36 insertions(+), 94 deletions(-) diff --git a/internal/server/keys.go b/internal/server/keys.go index ee08235..73dd7df 100644 --- a/internal/server/keys.go +++ b/internal/server/keys.go @@ -22,9 +22,7 @@ func displayCreateKey(w http.ResponseWriter, r *http.Request) { session := GetSessionData(r) page := getPage(session.Username) page.Page = "addKey" - if err := templates.ExecuteTemplate(w, "addKey", page); err != nil { - slog.Error("execute template", "template", "addKey", "page", page, "error", err) - } + render(w, "addKey", page) } func addKey(w http.ResponseWriter, r *http.Request) { @@ -83,9 +81,7 @@ func displayKeys(w http.ResponseWriter, _ *http.Request) { processError(w, http.StatusInternalServerError, err.Error()) return } - if err := templates.ExecuteTemplate(w, keyTable, keys); err != nil { - slog.Error("execute template", "template", keyTable, "keys", keys, "error", err) - } + render(w, keyTable, keys) } func deleteKey(w http.ResponseWriter, r *http.Request) { diff --git a/internal/server/networks.go b/internal/server/networks.go index 3da41b6..e96f926 100644 --- a/internal/server/networks.go +++ b/internal/server/networks.go @@ -20,9 +20,7 @@ func displayAddNetwork(w http.ResponseWriter, r *http.Request) { page := getPage(session.Username) page.Page = "addNetwork" - if err := templates.ExecuteTemplate(w, "addNetwork", page); err != nil { - slog.Error("template", "name", "addnetwork", "error", err) - } + render(w, "addNetwork", page) } func addNetwork(w http.ResponseWriter, r *http.Request) { @@ -83,9 +81,7 @@ func displayNetworks(w http.ResponseWriter, r *http.Request) { page.Data = networks w.Header().Add("Hx-Trigger", "networkChange") - if err := templates.ExecuteTemplate(w, "networks", page); err != nil { - slog.Error("template", "name", "networks", "page", page, "error", err) - } + render(w, "networks", page) } func networksSideBar(w http.ResponseWriter, _ *http.Request) { @@ -94,9 +90,7 @@ func networksSideBar(w http.ResponseWriter, _ *http.Request) { processError(w, http.StatusInternalServerError, err.Error()) return } - if err := templates.ExecuteTemplate(w, "sidebarNetworks", networks); err != nil { - slog.Error("sidebar", "networks", networks, "error", err) - } + render(w, "sidebarNetworks", networks) } func getAvailablePeers(network plexus.Network) []plexus.Peer { @@ -170,9 +164,7 @@ func networkDetails(w http.ResponseWriter, r *http.Request) { } details.Name = networkName details.AvailablePeers = getAvailablePeers(network) - if err := templates.ExecuteTemplate(w, "networkDetails", details); err != nil { - slog.Error("template", "template", "networkDetails", "details", details, "error", err) - } + render(w, "networkDetails", details) } func deleteNetwork(w http.ResponseWriter, r *http.Request) { @@ -278,14 +270,7 @@ func networkPeerDetails(w http.ResponseWriter, r *http.Request) { for _, peer := range network.Peers { if peer.WGPublicKey == peerID { peer.Connectivity *= 100 - if err := templates.ExecuteTemplate(w, "displayNetworkPeer", peer); err != nil { - slog.Error( - "template execute", - "template", "displayNetworkPeer", - "peer", peer, - "error", err, - ) - } + render(w, "displayNetworkPeer", peer) return } } diff --git a/internal/server/page.go b/internal/server/page.go index 2e221be..2a88fbd 100644 --- a/internal/server/page.go +++ b/internal/server/page.go @@ -1,8 +1,12 @@ package server import ( + "fmt" + "io" "log/slog" "net/http" + "path/filepath" + "runtime" "time" "github.com/devilcove/boltdb" @@ -43,9 +47,7 @@ func displayMain(w http.ResponseWriter, r *http.Request) { page.NeedsLogin = session.IsNew slog.Info("display main page", "session", session, "page", page) - if err := templates.ExecuteTemplate(w, "layout", page); err != nil { - slog.Error("display main", "template", "layout", "page", page, "error", err) - } + render(w, "layout", page) } func login(w http.ResponseWriter, r *http.Request) { @@ -64,9 +66,8 @@ func login(w http.ResponseWriter, r *http.Request) { page := getPage(user.Username) page.NeedsLogin = false page.Page = "networks" - if err := templates.ExecuteTemplate(w, "layout", page); err != nil { - slog.Error("execute template", "template", "layout", "page", page, "error", err) - } + saveSession(w, r, user) + render(w, "layout", page) } func validateUser(visitor *plexus.User) bool { @@ -137,8 +138,18 @@ func getPage(user any) Page { return pages[user.(string)] } -func displayLogin(w http.ResponseWriter, _ *http.Request) { - if err := templates.ExecuteTemplate(w, "layout", Page{NeedsLogin: true}); err != nil { - slog.Error("display login", "error", err) +func render(w io.Writer, template string, data any) { + if err := templates.ExecuteTemplate(w, template, data); err != nil { + slog.Error("render template", "caller", caller(2), + "name", template, "data", data, "error", err) + } +} + +func caller(depth int) string { + pc, file, no, ok := runtime.Caller(depth) + details := runtime.FuncForPC(pc) + if ok && details != nil { + return fmt.Sprintf("%s %s:%d", details.Name(), filepath.Base(file), no) } + return "unknown caller" } diff --git a/internal/server/peers.go b/internal/server/peers.go index 88df05c..2f0d0f0 100644 --- a/internal/server/peers.go +++ b/internal/server/peers.go @@ -27,9 +27,7 @@ func displayPeers(w http.ResponseWriter, _ *http.Request) { } displayPeers = append(displayPeers, peer) } - if err := templates.ExecuteTemplate(w, peerTable, displayPeers); err != nil { - slog.Error("template execute", "template", peerTable, "data", displayPeers, "error", err) - } + render(w, peerTable, displayPeers) } func peerDetails(w http.ResponseWriter, r *http.Request) { @@ -39,9 +37,7 @@ func peerDetails(w http.ResponseWriter, r *http.Request) { processError(w, http.StatusInternalServerError, err.Error()) return } - if err := templates.ExecuteTemplate(w, "peerDetails", peer); err != nil { - slog.Error("template execute", "template", "peerDetails", "data", peer, "error", err) - } + render(w, "peerDetails", peer) } func deletePeer(w http.ResponseWriter, r *http.Request) { diff --git a/internal/server/relay.go b/internal/server/relay.go index 25499a8..51e5cb1 100644 --- a/internal/server/relay.go +++ b/internal/server/relay.go @@ -34,9 +34,7 @@ func displayAddRelay(w http.ResponseWriter, r *http.Request) { } data.AvailablePeers = append(data.AvailablePeers, peer) } - if err := templates.ExecuteTemplate(w, "addRelayToNetwork", data); err != nil { - slog.Error("execute template", "template", "addRelayToNetwork", "data", data, "error", err) - } + render(w, "addRelayToNetwork", data) } func addRelay(w http.ResponseWriter, r *http.Request) { diff --git a/internal/server/router.go b/internal/server/router.go index 49e7d65..3f8cc2f 100644 --- a/internal/server/router.go +++ b/internal/server/router.go @@ -100,35 +100,3 @@ func auth(next http.Handler) http.Handler { next.ServeHTTP(w, r) }) } - -// func auth(c *gin.Context) { -// session := sessions.Default(c) -// loggedIn := session.Get("loggedin") -// if loggedIn == nil { -// slog.Info("not logged in display login page") -// page := getPage(nil) -// page.NeedsLogin = true -// if err := templates.ExecuteTemplate(w, "login", page) -// c.Abort() -// return -// } -// } - -// func weblogger() gin.HandlerFunc { -// return func(w http.ResponseWriter, r *http.Request) { -// start := time.Now() -// c.Next() -// status := c.Writer.Status() -// switch { -// case status >= 500: -// slog.Error("request", "Code", c.Writer.Status(), "method", c.Request.Method, -// "route", c.Request.URL.Path, "latency", time.Since(start), "client", c.ClientIP()) -// case status >= 400: -// slog.Warn("request", "Code", c.Writer.Status(), "method", c.Request.Method, -// "route", c.Request.URL.Path, "latency", time.Since(start), "client", c.ClientIP()) -// default: -// slog.Debug("request", "Code", c.Writer.Status(), "method", c.Request.Method, -// "route", c.Request.URL.Path, "latency", time.Since(start), "client", c.ClientIP()) -// } -// } -// } diff --git a/internal/server/server.go b/internal/server/server.go index 7feeccb..df1abcf 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -158,9 +158,7 @@ func getServer(w http.ResponseWriter, _ *http.Request) { } logs := string(out) server.Logs = strings.Split(logs, "\n") - if err := templates.ExecuteTemplate(w, "server", server); err != nil { - slog.Error("execute template", "template", "server", "data", server, "error", err) - } + render(w, "server", server) } func setLogLevel(w http.ResponseWriter, r *http.Request) { diff --git a/internal/server/subnetrouter.go b/internal/server/subnetrouter.go index 7ad4161..2117171 100644 --- a/internal/server/subnetrouter.go +++ b/internal/server/subnetrouter.go @@ -20,9 +20,7 @@ func displayAddRouter(w http.ResponseWriter, r *http.Request) { Router: r.PathValue("peer"), } slog.Debug("add router") - if err := templates.ExecuteTemplate(w, "addRouterToNetwork", data); err != nil { - slog.Error("execute template", "template", "addRouterToNetwork", "data", data, "error", err) - } + render(w, "addRouterToNetwork", data) } func addRouter(w http.ResponseWriter, r *http.Request) { diff --git a/internal/server/users.go b/internal/server/users.go index c17a248..49e9558 100644 --- a/internal/server/users.go +++ b/internal/server/users.go @@ -86,9 +86,7 @@ func getUsers(w http.ResponseWriter, r *http.Request) { user.Password = "" returnedUsers = append(returnedUsers, user) } - if err := templates.ExecuteTemplate(w, "users", returnedUsers); err != nil { - slog.Error("template execute", "template", "users", "data", returnedUsers, "error", err) - } + render(w, "users", returnedUsers) } func getUser(w http.ResponseWriter, r *http.Request) { @@ -113,9 +111,7 @@ func getUser(w http.ResponseWriter, r *http.Request) { return } user.Password = "" - if err := templates.ExecuteTemplate(w, "editUser", user); err != nil { - slog.Error("template execute", "template", "editUser", "data", user, "error", err) - } + render(w, "editUser", user) } func getCurrentUser(w http.ResponseWriter, r *http.Request) { @@ -126,9 +122,7 @@ func getCurrentUser(w http.ResponseWriter, r *http.Request) { processError(w, http.StatusBadRequest, "no such user "+err.Error()) return } - if err := templates.ExecuteTemplate(w, "editUser", user); err != nil { - slog.Error("template execute", "template", "editUser", "data", user, "error", err) - } + render(w, "editUser", user) } func deleteUser(w http.ResponseWriter, r *http.Request) { @@ -151,9 +145,7 @@ func displayAddUser(w http.ResponseWriter, r *http.Request) { processError(w, http.StatusUnauthorized, "admin rights required") return } - if err := templates.ExecuteTemplate(w, "newUser", nil); err != nil { - slog.Error("template execute", "template", "newUser", "data", "nil", "error", err) - } + render(w, "newUser", nil) } func addUser(w http.ResponseWriter, r *http.Request) { From 07f4f39290ce16c196d8205fca6aad889063371d Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Fri, 9 Jan 2026 09:14:36 -0500 Subject: [PATCH 4/6] update version for release --- app/plexus-agent/cmd/version.go | 4 +--- internal/agent/broker.go | 2 +- internal/agent/config.go | 2 +- internal/agent/register.go | 6 +++--- internal/server/config.go | 2 +- 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/app/plexus-agent/cmd/version.go b/app/plexus-agent/cmd/version.go index 8197dc8..a768491 100644 --- a/app/plexus-agent/cmd/version.go +++ b/app/plexus-agent/cmd/version.go @@ -26,8 +26,6 @@ import ( "github.com/spf13/cobra" ) -const version = "v0.4.0" - // versionCmd represents the version command. var versionCmd = &cobra.Command{ Use: "version", @@ -54,7 +52,7 @@ var versionCmd = &cobra.Command{ fmt.Printf("Agent: %s\n", response.Agent) fmt.Printf("Binary: ") } - fmt.Printf("%s: ", version) + fmt.Printf("%s: ", agent.Version) info, _ := debug.ReadBuildInfo() for _, setting := range info.Settings { if strings.Contains(setting.Key, "vcs") { diff --git a/internal/agent/broker.go b/internal/agent/broker.go index 549bf1b..baa03ae 100644 --- a/internal/agent/broker.go +++ b/internal/agent/broker.go @@ -285,7 +285,7 @@ func sendVersion(msg *nats.Msg, agentConn *nats.Conn) { } else { slog.Debug("not connected to server") } - response.Agent = version + ": " + response.Agent = Version + ": " info, _ := debug.ReadBuildInfo() for _, setting := range info.Settings { if strings.Contains(setting.Key, "vcs") { diff --git a/internal/agent/config.go b/internal/agent/config.go index f9d7553..7b5f40e 100644 --- a/internal/agent/config.go +++ b/internal/agent/config.go @@ -19,7 +19,7 @@ const ( connectivityTimeout = time.Minute * 3 endpointServerTimeout = time.Second * 30 networkNotMapped = "network not mapped to server" - version = "v0.4.0" + Version = "v0.4.1" networkTable = "networks" deviceTable = "devices" ) diff --git a/internal/agent/register.go b/internal/agent/register.go index b9b6808..92698c4 100644 --- a/internal/agent/register.go +++ b/internal/agent/register.go @@ -74,8 +74,8 @@ func handleRegistration(request *plexus.RegisterRequest) plexus.MessageResponse func newDevice() (Device, error) { device, err := boltdb.Get[Device]("self", deviceTable) if err == nil { - if device.Version != version { - device.Version = version + if device.Version != Version { + device.Version = Version if err := boltdb.Save(device, "self", deviceTable); err != nil { slog.Error("update self version", "error", err) } @@ -135,7 +135,7 @@ func createPeer() (*plexus.Peer, *wgtypes.Key, string, error) { WGPublicKey: pubKey.String(), PubNkey: nkey, Name: name, - Version: version, + Version: Version, Endpoint: stunAddr.IP, OS: runtime.GOOS, Updated: time.Now(), diff --git a/internal/server/config.go b/internal/server/config.go index f1997a6..8e73999 100644 --- a/internal/server/config.go +++ b/internal/server/config.go @@ -46,7 +46,7 @@ var ( ErrSecureBlankFQDN = errors.New("secure server requires FQDN") ErrSecureWithIP = errors.New("cannot use IP address with secure") ErrInValidEmail = errors.New("valid email address required") - version = "v0.4.0" + version = "v0.4.1" ) const ( From daf4d7b463c1d91505cf5d795450f4634bf3b3c0 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Fri, 9 Jan 2026 09:31:02 -0500 Subject: [PATCH 5/6] linting --- .golangci.yml | 4 ++++ internal/agent/handlers.go | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.golangci.yml b/.golangci.yml index c9e097f..dcfb251 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -18,6 +18,7 @@ linters: - noctx - noinlineerr - paralleltest + - prealloc - testpackage - wrapcheck - wsl @@ -77,5 +78,8 @@ formatters: enable: - gofumpt - golines + settings: + golines: + max-len: 120 exclusions: generated: lax diff --git a/internal/agent/handlers.go b/internal/agent/handlers.go index 6cc8607..0262606 100644 --- a/internal/agent/handlers.go +++ b/internal/agent/handlers.go @@ -160,7 +160,8 @@ func processLeave(request *plexus.LeaveRequest) plexus.MessageResponse { } serverConn := serverConn.Load() if serverConn != nil { - if err := Request(serverConn, self.WGPublicKey+plexus.LeaveNetwork, request, &response, NatsTimeout); err != nil { + if err := Request(serverConn, self.WGPublicKey+plexus.LeaveNetwork, + request, &response, NatsTimeout); err != nil { slog.Debug(err.Error()) return plexus.MessageResponse{Message: "error: " + err.Error()} } From 38df5927574fc0cf7da0926c272832f001708cc9 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Fri, 9 Jan 2026 09:49:11 -0500 Subject: [PATCH 6/6] networks details refresh --- internal/server/html/networks.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/server/html/networks.html b/internal/server/html/networks.html index c1a9824..6e1e80e 100644 --- a/internal/server/html/networks.html +++ b/internal/server/html/networks.html @@ -53,7 +53,7 @@

Add Network

{{end}} {{define "networkDetails"}} -
+