From c4e846ccd4ba31fd6b4741632e74102270e8cf23 Mon Sep 17 00:00:00 2001 From: Khanh Ngo Date: Sat, 18 Apr 2020 21:42:53 +0700 Subject: [PATCH] Generate QR code --- go.mod | 1 + go.sum | 2 ++ handler/routes.go | 22 +++++++++++++++++++--- model/client.go | 6 ++++++ templates/home.html | 18 +++++++++--------- util/util.go | 40 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 77 insertions(+), 12 deletions(-) create mode 100644 util/util.go diff --git a/go.mod b/go.mod index c6855d4..c2c9d91 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/leodido/go-urn v1.2.0 // indirect github.com/rs/xid v1.2.1 github.com/sdomino/scribble v0.0.0-20191024200645-4116320640ba + github.com/skip2/go-qrcode v0.0.0-20191027152451-9434209cb086 golang.zx2c4.com/wireguard/wgctrl v0.0.0-20200324154536-ceff61240acf gopkg.in/go-playground/validator.v9 v9.31.0 ) diff --git a/go.sum b/go.sum index 8483930..803f7a8 100644 --- a/go.sum +++ b/go.sum @@ -36,6 +36,8 @@ github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/sdomino/scribble v0.0.0-20191024200645-4116320640ba h1:8QAc9wFAf2b/9cAXskm0wBylObZ0bTpRcaP7ThjLPVQ= github.com/sdomino/scribble v0.0.0-20191024200645-4116320640ba/go.mod h1:W6zxGUBCXRR5QugSd/nFcFVmwoGnvpjiNY/JwT03Wew= +github.com/skip2/go-qrcode v0.0.0-20191027152451-9434209cb086 h1:RYiqpb2ii2Z6J4x0wxK46kvPBbFuZcdhS+CIztmYgZs= +github.com/skip2/go-qrcode v0.0.0-20191027152451-9434209cb086/go.mod h1:PLPIyL7ikehBD1OAjmKKiOEhbvWyHGaNDjquXMcYABo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= diff --git a/handler/routes.go b/handler/routes.go index f36fc7c..19e9ae8 100644 --- a/handler/routes.go +++ b/handler/routes.go @@ -2,15 +2,18 @@ package handler import ( "encoding/json" + "encoding/base64" "net/http" "time" "github.com/labstack/echo/v4" "github.com/ngoduykhanh/wireguard-ui/model" + "github.com/ngoduykhanh/wireguard-ui/util" "github.com/sdomino/scribble" "github.com/labstack/gommon/log" "github.com/rs/xid" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" + "github.com/skip2/go-qrcode" ) // Home handler @@ -28,18 +31,31 @@ func Home() echo.HandlerFunc { log.Error("Cannot fetch clients from database: ", err) } - clients := []model.Client{} + clientDataList := []model.ClientData{} for _, f := range records { client := model.Client{} + clientData := model.ClientData{} + + // get client info if err := json.Unmarshal([]byte(f), &client); err != nil { log.Error("Cannot decode client json structure: ", err) } - clients = append(clients, client) + clientData.Client = &client + + // generate client qrcode image in base64 + png, err := qrcode.Encode(util.BuildClientConfig(client), qrcode.Medium, 256) + if err != nil { + log.Error("Cannot generate QRCode: ", err) + } + clientData.QRCode = "data:image/png;base64," + base64.StdEncoding.EncodeToString([]byte(png)) + + // create the list of clients and their qrcode data + clientDataList = append(clientDataList, clientData) } return c.Render(http.StatusOK, "home.html", map[string]interface{}{ "name": "Khanh", - "clients": clients, + "clientDataList": clientDataList, }) } } diff --git a/model/client.go b/model/client.go index 09fc5e3..a737b4e 100644 --- a/model/client.go +++ b/model/client.go @@ -17,3 +17,9 @@ type Client struct { CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } + +// ClientData includes the Client and extra data +type ClientData struct { + Client *Client + QRCode string +} diff --git a/templates/home.html b/templates/home.html index 6ab82c1..8c34402 100644 --- a/templates/home.html +++ b/templates/home.html @@ -15,31 +15,31 @@ Dashboard
Wireguard Clients
- {{range .clients}} + {{range .clientDataList}}
+ src="{{ .QRCode }}" />
- +

- {{ .Name }} - {{ .Email }} + {{ .Client.Name }} + {{ .Client.Email }} - {{ .CreatedAt.Format "2 Jan 2006 15:04" }} + {{ .Client.CreatedAt.Format "2 Jan 2006 15:04" }} - {{ .UpdatedAt.Format "2 Jan 2006 15:04" }} + {{ .Client.UpdatedAt.Format "2 Jan 2006 15:04" }} IP Allocation - {{range .AllocatedIPs}} + {{range .Client.AllocatedIPs}} {{.}} {{end}} Allowed IPs - {{range .AllowedIPs}} + {{range .Client.AllowedIPs}} {{.}} {{end}}
diff --git a/util/util.go b/util/util.go new file mode 100644 index 0000000..d4182cf --- /dev/null +++ b/util/util.go @@ -0,0 +1,40 @@ +package util + +import ( + "fmt" + "strings" + + "github.com/ngoduykhanh/wireguard-ui/model" +) + +const wgConfigDNS = "1.1.1.1, 8.8.8.8" +const wgConfigPersistentKeepalive = 15 +const wgConfigEndpoint = "wireguard.example.com:56231" +const wgConfigServerPublicKey = "/OKCBc8PxIqCpgqlE9G1kSaTecdAvYf3loEwFj6MXDc=" + +// BuildClientConfig to create wireguard client config string +func BuildClientConfig(client model.Client) string { + // Interface section + clientAddress := fmt.Sprintf("Address = %s", strings.Join(client.AllocatedIPs, ",")) + clientPrivateKey := fmt.Sprintf("PrivateKey = %s", client.PrivateKey) + clientDNS := fmt.Sprintf("DNS = %s", wgConfigDNS) + + // Peer section + peerPublicKey := fmt.Sprintf("PublicKey = %s", wgConfigServerPublicKey) + peerAllowedIPs := fmt.Sprintf("AllowedIPs = %s", strings.Join(client.AllowedIPs, ",")) + peerEndpoint := fmt.Sprintf("Endpoint = %s", wgConfigEndpoint) + peerPersistentKeepalive := fmt.Sprintf("PersistentKeepalive = %d", wgConfigPersistentKeepalive) + + // build the config as string + strConfig := "[Interface]\n" + + clientAddress + "\n" + + clientPrivateKey + "\n" + + clientDNS + "\n\n" + + "[Peer]" + "\n" + + peerPublicKey + "\n" + + peerAllowedIPs + "\n" + + peerEndpoint + "\n" + + peerPersistentKeepalive + "\n" + + return strConfig +}