Generate QR code

This commit is contained in:
Khanh Ngo 2020-04-18 21:42:53 +07:00
parent 59e1a9e377
commit c4e846ccd4
No known key found for this signature in database
GPG key ID: D5FAA6A16150E49E
6 changed files with 77 additions and 12 deletions

1
go.mod
View file

@ -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
)

2
go.sum
View file

@ -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=

View file

@ -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,
})
}
}

View file

@ -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
}

View file

@ -15,31 +15,31 @@ Dashboard
<div class="container-fluid">
<h5 class="mt-4 mb-2">Wireguard Clients</h5>
<div class="row">
{{range .clients}}
{{range .clientDataList}}
<div class="col-sm-6">
<div class="info-box">
<img
src="https://wg-gen-web-demo.127-0-0-1.fr/api/v1.0/client/a69b9f3f-556f-4f2a-8020-55bdd4479841/config?qrcode=true" />
src="{{ .QRCode }}" />
<div class="info-box-content">
<div class="btn-group">
<button type="button" class="btn btn-outline-success btn-sm">Download</button>
<button type="button" class="btn btn-outline-primary btn-sm">Edit</button>
<button type="button" class="btn btn-outline-warning btn-sm">Disable</button>
<button type="button" class="btn btn-outline-danger btn-sm" data-toggle="modal" data-target="#modal_remove_client" data-clientid="{{ .ID }}" data-clientname="{{ .Name }}">Remove</button>
<button type="button" class="btn btn-outline-danger btn-sm" data-toggle="modal" data-target="#modal_remove_client" data-clientid="{{ .Client.ID }}" data-clientname="{{ .Client.Name }}">Remove</button>
</div>
<hr>
<span class="info-box-text"><i class="fas fa-user"></i> {{ .Name }}</span>
<span class="info-box-text"><i class="fas fa-envelope"></i> {{ .Email }}</span>
<span class="info-box-text"><i class="fas fa-user"></i> {{ .Client.Name }}</span>
<span class="info-box-text"><i class="fas fa-envelope"></i> {{ .Client.Email }}</span>
<span class="info-box-text"><i class="fas fa-clock"></i>
{{ .CreatedAt.Format "2 Jan 2006 15:04" }}</span>
{{ .Client.CreatedAt.Format "2 Jan 2006 15:04" }}</span>
<span class="info-box-text"><i class="fas fa-history"></i>
{{ .UpdatedAt.Format "2 Jan 2006 15:04" }}</span>
{{ .Client.UpdatedAt.Format "2 Jan 2006 15:04" }}</span>
<span class="info-box-text"><strong>IP Allocation</strong></span>
{{range .AllocatedIPs}}
{{range .Client.AllocatedIPs}}
<small class="badge badge-secondary"></i>{{.}}</small>
{{end}}
<span class="info-box-text"><strong>Allowed IPs</strong></span>
{{range .AllowedIPs}}
{{range .Client.AllowedIPs}}
<small class="badge badge-secondary"></i>{{.}}</small>
{{end}}
</div>

40
util/util.go Normal file
View file

@ -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
}