From 3c155f1c97c991782c07262eedb8de74fa74c0f7 Mon Sep 17 00:00:00 2001 From: Christoph Haas Date: Tue, 6 Oct 2020 18:58:34 +0200 Subject: [PATCH] improve formatting and layout --- .env | 2 +- api/v1/status/status.go | 4 +- core/status.go | 30 +++++++----- model/status.go | 60 ++++++++++++++++++----- ui/src/components/Status.vue | 92 ++++++++++++++---------------------- 5 files changed, 107 insertions(+), 81 deletions(-) diff --git a/.env b/.env index c1aabe0..7a97ff7 100644 --- a/.env +++ b/.env @@ -41,6 +41,6 @@ OAUTH2_REDIRECT_URL=https://wg-gen-web-demo.127-0-0-1.fr OAUTH2_PROVIDER_NAME=fake # https://github.com/jamescun/wg-api integration, user and password (basic auth) are optional -WG_STATS_API=https://wg.example.digital/wg-api +WG_STATS_API= WG_STATS_API_USER= WG_STATS_API_PASS= \ No newline at end of file diff --git a/api/v1/status/status.go b/api/v1/status/status.go index 7d3124c..f5a16de 100644 --- a/api/v1/status/status.go +++ b/api/v1/status/status.go @@ -23,7 +23,7 @@ func readInterfaceStatus(c *gin.Context) { log.WithFields(log.Fields{ "err": err, }).Error("failed to read interface status") - c.AbortWithStatus(http.StatusInternalServerError) + c.AbortWithStatusJSON(http.StatusInternalServerError, err.Error()) return } @@ -36,7 +36,7 @@ func readClientStatus(c *gin.Context) { log.WithFields(log.Fields{ "err": err, }).Error("failed to read client status") - c.AbortWithStatus(http.StatusInternalServerError) + c.AbortWithStatusJSON(http.StatusInternalServerError, err.Error()) return } diff --git a/core/status.go b/core/status.go index e2fc54e..cbb4bfe 100644 --- a/core/status.go +++ b/core/status.go @@ -3,6 +3,7 @@ package core import ( "bytes" "encoding/json" + "errors" "io/ioutil" "net/http" "os" @@ -34,6 +35,10 @@ type apiResponse struct { func fetchWireGuardAPI(reqData apiRequest) (*apiResponse, error) { apiUrl := os.Getenv("WG_STATS_API") + if apiUrl == "" { + return nil, errors.New("Status API integration not configured") + } + apiClient := http.Client{ Timeout: time.Second * 2, // Timeout after 2 seconds } @@ -135,19 +140,22 @@ func ReadClientStatus() ([]*model.ClientStatus, error) { for i, peerIP := range peerIPs { peerAddresses[i] = peerIP.(string) } + peerHandshakeRelative := time.Since(peerHandshake) + peerActive := peerHandshakeRelative.Minutes() < 3 // TODO: we need a better detection... ping for example? newClientStatus := &model.ClientStatus{ - PublicKey: peer["public_key"].(string), - HasPresharedKey: peer["has_preshared_key"].(bool), - ProtocolVersion: int(peer["protocol_version"].(float64)), - Name: "UNKNOWN", - Email: "UNKNOWN", - Connected: false, - AllowedIPs: peerAddresses, - Endpoint: peer["endpoint"].(string), - LastHandshake: peerHandshake, - ReceivedBytes: int(peer["receive_bytes"].(float64)), - TransmittedBytes: int(peer["transmit_bytes"].(float64)), + PublicKey: peer["public_key"].(string), + HasPresharedKey: peer["has_preshared_key"].(bool), + ProtocolVersion: int(peer["protocol_version"].(float64)), + Name: "UNKNOWN", + Email: "UNKNOWN", + Connected: peerActive, + AllowedIPs: peerAddresses, + Endpoint: peer["endpoint"].(string), + LastHandshake: peerHandshake, + LastHandshakeRelative: peerHandshakeRelative, + ReceivedBytes: int(peer["receive_bytes"].(float64)), + TransmittedBytes: int(peer["transmit_bytes"].(float64)), } if withClientDetails { diff --git a/model/status.go b/model/status.go index 0f63917..1ac07dd 100644 --- a/model/status.go +++ b/model/status.go @@ -1,22 +1,60 @@ package model import ( + "encoding/json" + "fmt" "time" ) // ClientStatus structure type ClientStatus struct { - PublicKey string `json:"publicKey"` - HasPresharedKey bool `json:"hasPresharedKey"` - ProtocolVersion int `json:"protocolVersion"` - Name string `json:"name"` - Email string `json:"email"` - Connected bool `json:"connected"` - AllowedIPs []string `json:"allowedIPs"` - Endpoint string `json:"endpoint"` - LastHandshake time.Time `json:"lastHandshake"` - ReceivedBytes int `json:"receivedBytes"` - TransmittedBytes int `json:"transmittedBytes"` + PublicKey string `json:"publicKey"` + HasPresharedKey bool `json:"hasPresharedKey"` + ProtocolVersion int `json:"protocolVersion"` + Name string `json:"name"` + Email string `json:"email"` + Connected bool `json:"connected"` + AllowedIPs []string `json:"allowedIPs"` + Endpoint string `json:"endpoint"` + LastHandshake time.Time `json:"lastHandshake"` + LastHandshakeRelative time.Duration `json:"lastHandshakeRelative"` + ReceivedBytes int `json:"receivedBytes"` + TransmittedBytes int `json:"transmittedBytes"` +} + +func (c *ClientStatus) MarshalJSON() ([]byte, error) { + + duration := fmt.Sprintf("%v ago", c.LastHandshakeRelative) + if c.LastHandshakeRelative.Hours() > 5208 { // 24*7*31 = approx one month + duration = "more than a month ago" + } + return json.Marshal(&struct { + PublicKey string `json:"publicKey"` + HasPresharedKey bool `json:"hasPresharedKey"` + ProtocolVersion int `json:"protocolVersion"` + Name string `json:"name"` + Email string `json:"email"` + Connected bool `json:"connected"` + AllowedIPs []string `json:"allowedIPs"` + Endpoint string `json:"endpoint"` + LastHandshake time.Time `json:"lastHandshake"` + LastHandshakeRelative string `json:"lastHandshakeRelative"` + ReceivedBytes int `json:"receivedBytes"` + TransmittedBytes int `json:"transmittedBytes"` + }{ + PublicKey: c.PublicKey, + HasPresharedKey: c.HasPresharedKey, + ProtocolVersion: c.ProtocolVersion, + Name: c.Name, + Email: c.Email, + Connected: c.Connected, + AllowedIPs: c.AllowedIPs, + Endpoint: c.Endpoint, + LastHandshake: c.LastHandshake, + LastHandshakeRelative: duration, + ReceivedBytes: c.ReceivedBytes, + TransmittedBytes: c.TransmittedBytes, + }) } // InterfaceStatus structure diff --git a/ui/src/components/Status.vue b/ui/src/components/Status.vue index 88633f0..eb6f9f8 100644 --- a/ui/src/components/Status.vue +++ b/ui/src/components/Status.vue @@ -44,9 +44,19 @@ :items="clients" :search="search" > -