mirror of
https://github.com/ngoduykhanh/wireguard-ui.git
synced 2025-04-19 19:59:13 +03:00
Generate QR code
This commit is contained in:
parent
59e1a9e377
commit
c4e846ccd4
6 changed files with 77 additions and 12 deletions
1
go.mod
1
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
|
||||
)
|
||||
|
|
2
go.sum
2
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=
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
40
util/util.go
Normal 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
|
||||
}
|
Loading…
Add table
Reference in a new issue