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/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/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()} } 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 ( 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"}} -
+
diff --git a/internal/server/keys.go b/internal/server/keys.go index bf080f5..73dd7df 100644 --- a/internal/server/keys.go +++ b/internal/server/keys.go @@ -19,16 +19,10 @@ 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) - } + render(w, "addKey", page) } func addKey(w http.ResponseWriter, r *http.Request) { @@ -87,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 9f44bfd..e96f926 100644 --- a/internal/server/networks.go +++ b/internal/server/networks.go @@ -16,20 +16,11 @@ 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) - } + render(w, "addNetwork", page) } func addNetwork(w http.ResponseWriter, r *http.Request) { @@ -80,12 +71,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,11 +80,8 @@ 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) - } + render(w, "networks", page) } func networksSideBar(w http.ResponseWriter, _ *http.Request) { @@ -106,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 { @@ -148,11 +130,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,12 +164,7 @@ 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) - } + render(w, "networkDetails", details) } func deleteNetwork(w http.ResponseWriter, r *http.Request) { @@ -298,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 22b6c4f..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" @@ -34,20 +38,16 @@ 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 { - slog.Error("display main", "template", "layout", "page", page, "error", err) - } + render(w, "layout", page) } func login(w http.ResponseWriter, r *http.Request) { @@ -59,15 +59,15 @@ 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) 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 { @@ -94,8 +94,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) } @@ -140,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 3c9ccdc..3f8cc2f 100644 --- a/internal/server/router.go +++ b/internal/server/router.go @@ -92,50 +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) }) } - -// 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/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