Generate QR code
This commit is contained in:
		
							parent
							
								
									59e1a9e377
								
							
						
					
					
						commit
						c4e846ccd4
					
				
							
								
								
									
										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> | ||||
|  |  | |||
|  | @ -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…
	
		Reference in New Issue