diff --git a/go.mod b/go.mod index d109de9..aae12dc 100644 --- a/go.mod +++ b/go.mod @@ -30,6 +30,7 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/dustin/go-humanize v1.0.1 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-kit/kit v0.12.0 // indirect diff --git a/go.sum b/go.sum index 13ef60a..fdd90dc 100644 --- a/go.sum +++ b/go.sum @@ -174,6 +174,8 @@ github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= diff --git a/http/api/client.go b/http/api/client.go index 65d62da..3392513 100644 --- a/http/api/client.go +++ b/http/api/client.go @@ -7,9 +7,11 @@ import ( "github.com/gin-gonic/gin" "os" "strings" + "wireguard-dashboard/client" "wireguard-dashboard/http/param" "wireguard-dashboard/model/entity" "wireguard-dashboard/model/template_data" + "wireguard-dashboard/model/vo" "wireguard-dashboard/queues" "wireguard-dashboard/repository" "wireguard-dashboard/utils" @@ -245,3 +247,52 @@ func (clients) GenerateQrCode(c *gin.Context) { "qrCode": png, }) } + +// Status +// @description: 获取客户端状态信息,链接状态等 +// @receiver clients +// @param c +func (clients) Status(c *gin.Context) { + var p param.ClientStatusList + if err := c.ShouldBind(&p); err != nil { + utils.GinResponse(c).FailedWithErr("参数错误", err) + return + } + + // 使用sdk拉取一下客户端信息 + devices, err := client.WireguardClient.Devices() + if err != nil { + utils.GinResponse(c).FailedWithErr("获取客户端信息失败", err) + return + } + + var data []vo.ClientStatus + // 遍历客户端数据,并渲染数据信息 + for _, d := range devices { + for _, p := range d.Peers { + clientInfo, err := repository.Client().GetByPublicKey(p.PublicKey.String()) + if err != nil { + log.Errorf("没有找到公钥匹配的客户端: %s", p.PublicKey.String()) + continue + } + var ipAllocation string + for _, iaip := range p.AllowedIPs { + ipAllocation += iaip.String() + "," + } + ipAllocation = strings.TrimRight(ipAllocation, ",") + isOnline := p.LastHandshakeTime.Minute() < 1 + data = append(data, vo.ClientStatus{ + Name: clientInfo.Name, + Email: clientInfo.Email, + IpAllocation: ipAllocation, + Endpoint: p.Endpoint.String(), + Received: utils.FlowCalculation().Parse(p.ReceiveBytes), + Transmitted: utils.FlowCalculation().Parse(p.TransmitBytes), + IsOnline: isOnline, + LastHandShake: p.LastHandshakeTime.Format("2006-01-02 15:04:05"), + }) + } + } + + utils.GinResponse(c).OKWithData(data) +} diff --git a/http/param/client.go b/http/param/client.go index ca60c3a..07733d3 100644 --- a/http/param/client.go +++ b/http/param/client.go @@ -8,6 +8,12 @@ type ClientList struct { page } +// ClientStatusList +// @description: 客户端状态列表 +type ClientStatusList struct { + page +} + // SaveClient // @description: 新增/编辑客户端 type SaveClient struct { diff --git a/model/vo/client.go b/model/vo/client.go index 347261c..ef09616 100644 --- a/model/vo/client.go +++ b/model/vo/client.go @@ -26,3 +26,14 @@ type Client struct { CreatedAt entity.JsonTime `json:"createAt"` UpdatedAt entity.JsonTime `json:"updatedAt"` } + +type ClientStatus struct { + Name string `json:"name"` + Email string `json:"email"` + IpAllocation string `json:"IpAllocation"` + Endpoint string `json:"endpoint"` + Received string `json:"received"` + Transmitted string `json:"transmitted"` + IsOnline bool `json:"isOnline"` // 是否在线 1 - 在线 | 0 - 不在线 + LastHandShake string `json:"lastHandShake"` +} diff --git a/repository/client.go b/repository/client.go index 2382730..c7bc0c8 100644 --- a/repository/client.go +++ b/repository/client.go @@ -162,8 +162,16 @@ func (r clientRepo) Delete(id string) (err error) { // @return err func (r clientRepo) GetById(id string) (data entity.Client, err error) { err = r.Model(&entity.Client{}).Where("id = ?", id).Preload("Server").First(&data).Error - if err != nil { - return - } + return +} + +// GetByPublicKey +// @description: 根据公钥获取客户端信息 +// @receiver r +// @param publicKey +// @return data +// @return err +func (r clientRepo) GetByPublicKey(publicKey string) (data entity.Client, err error) { + err = r.Model(&entity.Client{}).Where("keys->$.publicKey = ?", publicKey).Preload("Server").First(&data).Error return } diff --git a/utils/flow_calculation.go b/utils/flow_calculation.go new file mode 100644 index 0000000..7292056 --- /dev/null +++ b/utils/flow_calculation.go @@ -0,0 +1,22 @@ +package utils + +import ( + "github.com/dustin/go-humanize" + "math/big" +) + +type flowCalculation struct{} + +func FlowCalculation() flowCalculation { + return flowCalculation{} +} + +// Parse +// @description: 解析流量,序列化为字符串 +// @receiver flowCalculation +// @param b +// @return string +func (flowCalculation) Parse(b int64) string { + b2 := big.Int{} + return humanize.BigBytes(b2.SetInt64(b)) +} diff --git a/utils/flow_calculation_test.go b/utils/flow_calculation_test.go new file mode 100644 index 0000000..8aa49d8 --- /dev/null +++ b/utils/flow_calculation_test.go @@ -0,0 +1,11 @@ +package utils + +import ( + "fmt" + "testing" +) + +func TestParse(t *testing.T) { + f := FlowCalculation() + fmt.Println(f.Parse(13030000000)) +}