Added optional checkbox FwMark in QRCode modal

This commit is contained in:
Yuriy Vlasov 2022-11-27 15:49:43 +02:00
parent 887bc778df
commit eaabb30989
8 changed files with 94 additions and 31 deletions

2
go.mod
View file

@ -3,7 +3,7 @@ module github.com/ngoduykhanh/wireguard-ui
go 1.14 go 1.14
require ( require (
github.com/GeertJohan/go.rice v1.0.2 github.com/GeertJohan/go.rice v1.0.3
github.com/glendc/go-external-ip v0.0.0-20170425150139-139229dcdddd github.com/glendc/go-external-ip v0.0.0-20170425150139-139229dcdddd
github.com/go-playground/universal-translator v0.17.0 // indirect github.com/go-playground/universal-translator v0.17.0 // indirect
github.com/gorilla/sessions v1.2.0 github.com/gorilla/sessions v1.2.0

8
go.sum
View file

@ -1,7 +1,11 @@
github.com/GeertJohan/go.incremental v1.0.0 h1:7AH+pY1XUgQE4Y1HcXYaMqAI0m9yrFqo/jt0CW30vsg=
github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0=
github.com/GeertJohan/go.rice v1.0.2 h1:PtRw+Tg3oa3HYwiDBZyvOJ8LdIyf6lAovJJtr7YOAYk= github.com/GeertJohan/go.rice v1.0.2 h1:PtRw+Tg3oa3HYwiDBZyvOJ8LdIyf6lAovJJtr7YOAYk=
github.com/GeertJohan/go.rice v1.0.2/go.mod h1:af5vUNlDNkCjOZeSGFgIJxDje9qdjsO6hshx0gTmZt4= github.com/GeertJohan/go.rice v1.0.2/go.mod h1:af5vUNlDNkCjOZeSGFgIJxDje9qdjsO6hshx0gTmZt4=
github.com/GeertJohan/go.rice v1.0.3 h1:k5viR+xGtIhF61125vCE1cmJ5957RQGXG6dmbaWZSmI=
github.com/GeertJohan/go.rice v1.0.3/go.mod h1:XVdrU4pW00M4ikZed5q56tPf1v2KwnIKeIdc9CBYNt4=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw=
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@ -14,6 +18,8 @@ github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE
github.com/coreos/bbolt v1.3.1-coreos.6.0.20180223184059-4f5275f4ebbf/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/bbolt v1.3.1-coreos.6.0.20180223184059-4f5275f4ebbf/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/daaku/go.zipexe v1.0.0 h1:VSOgZtH418pH9L16hC/JrgSNJbbAL26pj7lmD1+CGdY= github.com/daaku/go.zipexe v1.0.0 h1:VSOgZtH418pH9L16hC/JrgSNJbbAL26pj7lmD1+CGdY=
github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E= github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E=
github.com/daaku/go.zipexe v1.0.2 h1:Zg55YLYTr7M9wjKn8SY/WcpuuEi+kR2u4E8RhvpyXmk=
github.com/daaku/go.zipexe v1.0.2/go.mod h1:5xWogtqlYnfBXkSB1o9xysukNP9GTvaNkqzUZbt3Bw8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -52,6 +58,7 @@ github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/z
github.com/jcelliott/lumber v0.0.0-20160324203708-dd349441af25 h1:EFT6MH3igZK/dIVqgGbTqWVvkZ7wJ5iGN03SVtvvdd8= github.com/jcelliott/lumber v0.0.0-20160324203708-dd349441af25 h1:EFT6MH3igZK/dIVqgGbTqWVvkZ7wJ5iGN03SVtvvdd8=
github.com/jcelliott/lumber v0.0.0-20160324203708-dd349441af25/go.mod h1:sWkGw/wsaHtRsT9zGQ/WyJCotGWG/Anow/9hsAcBWRw= github.com/jcelliott/lumber v0.0.0-20160324203708-dd349441af25/go.mod h1:sWkGw/wsaHtRsT9zGQ/WyJCotGWG/Anow/9hsAcBWRw=
github.com/jessevdk/go-flags v0.0.0-20150816100521-1acbbaff2f34/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v0.0.0-20150816100521-1acbbaff2f34/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/josharian/native v0.0.0-20200817173448-b6b71def0850 h1:uhL5Gw7BINiiPAo24A2sxkcDI0Jt/sqp1v5xQCniEFA= github.com/josharian/native v0.0.0-20200817173448-b6b71def0850 h1:uhL5Gw7BINiiPAo24A2sxkcDI0Jt/sqp1v5xQCniEFA=
github.com/josharian/native v0.0.0-20200817173448-b6b71def0850/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/josharian/native v0.0.0-20200817173448-b6b71def0850/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
@ -109,6 +116,7 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nkovacs/streamquote v1.0.0 h1:PmVIV08Zlx2lZK5fFZlMZ04eHcDTIFJCv/5/0twVUow=
github.com/nkovacs/streamquote v1.0.0/go.mod h1:BN+NaZ2CmdKqUuTUXUEm9j95B2TRbpOWpxbJYzzgUsc= github.com/nkovacs/streamquote v1.0.0/go.mod h1:BN+NaZ2CmdKqUuTUXUEm9j95B2TRbpOWpxbJYzzgUsc=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=

View file

@ -138,7 +138,15 @@ func GetClient(db store.IStore) echo.HandlerFunc {
return func(c echo.Context) error { return func(c echo.Context) error {
clientID := c.Param("id") clientID := c.Param("id")
clientData, err := db.GetClientByID(clientID, true) qrCodeIncludeFwMark := c.QueryParam("qrCodeIncludeFwMark")
qrCodeSettings := model.QRCodeSettings{
Enabled: true,
IncludeDNS: true,
IncludeFwMark: qrCodeIncludeFwMark == "true",
IncludeMTU: true,
}
clientData, err := db.GetClientByID(clientID, qrCodeSettings)
if err != nil { if err != nil {
return c.JSON(http.StatusNotFound, jsonHTTPResponse{false, "Client not found"}) return c.JSON(http.StatusNotFound, jsonHTTPResponse{false, "Client not found"})
} }
@ -257,7 +265,13 @@ func EmailClient(db store.IStore, mailer emailer.Emailer, emailSubject, emailCon
c.Bind(&payload) c.Bind(&payload)
// TODO validate email // TODO validate email
clientData, err := db.GetClientByID(payload.ID, true) qrCodeSettings := model.QRCodeSettings{
Enabled: true,
IncludeDNS: true,
IncludeFwMark: true,
IncludeMTU: true,
}
clientData, err := db.GetClientByID(payload.ID, qrCodeSettings)
if err != nil { if err != nil {
log.Errorf("Cannot generate client id %s config file for downloading: %v", payload.ID, err) log.Errorf("Cannot generate client id %s config file for downloading: %v", payload.ID, err)
return c.JSON(http.StatusNotFound, jsonHTTPResponse{false, "Client not found"}) return c.JSON(http.StatusNotFound, jsonHTTPResponse{false, "Client not found"})
@ -304,7 +318,7 @@ func UpdateClient(db store.IStore) echo.HandlerFunc {
c.Bind(&_client) c.Bind(&_client)
// validate client existence // validate client existence
clientData, err := db.GetClientByID(_client.ID, false) clientData, err := db.GetClientByID(_client.ID, model.QRCodeSettings{Enabled: false})
if err != nil { if err != nil {
return c.JSON(http.StatusNotFound, jsonHTTPResponse{false, "Client not found"}) return c.JSON(http.StatusNotFound, jsonHTTPResponse{false, "Client not found"})
} }
@ -368,7 +382,7 @@ func SetClientStatus(db store.IStore) echo.HandlerFunc {
clientID := data["id"].(string) clientID := data["id"].(string)
status := data["status"].(bool) status := data["status"].(bool)
clientdata, err := db.GetClientByID(clientID, false) clientdata, err := db.GetClientByID(clientID, model.QRCodeSettings{Enabled: false})
if err != nil { if err != nil {
return c.JSON(http.StatusNotFound, jsonHTTPResponse{false, err.Error()}) return c.JSON(http.StatusNotFound, jsonHTTPResponse{false, err.Error()})
} }
@ -393,7 +407,7 @@ func DownloadClient(db store.IStore) echo.HandlerFunc {
return c.JSON(http.StatusNotFound, jsonHTTPResponse{false, "Missing clientid parameter"}) return c.JSON(http.StatusNotFound, jsonHTTPResponse{false, "Missing clientid parameter"})
} }
clientData, err := db.GetClientByID(clientID, false) clientData, err := db.GetClientByID(clientID, model.QRCodeSettings{Enabled: false})
if err != nil { if err != nil {
log.Errorf("Cannot generate client id %s config file for downloading: %v", clientID, err) log.Errorf("Cannot generate client id %s config file for downloading: %v", clientID, err)
return c.JSON(http.StatusNotFound, jsonHTTPResponse{false, "Client not found"}) return c.JSON(http.StatusNotFound, jsonHTTPResponse{false, "Client not found"})

View file

@ -26,3 +26,10 @@ type ClientData struct {
Client *Client Client *Client
QRCode string QRCode string
} }
type QRCodeSettings struct {
Enabled bool
IncludeDNS bool
IncludeFwMark bool
IncludeMTU bool
}

View file

@ -190,7 +190,7 @@ func (o *JsonDB) GetClients(hasQRCode bool) ([]model.ClientData, error) {
return clients, nil return clients, nil
} }
func (o *JsonDB) GetClientByID(clientID string, hasQRCode bool) (model.ClientData, error) { func (o *JsonDB) GetClientByID(clientID string, qrCodeSettings model.QRCodeSettings) (model.ClientData, error) {
client := model.Client{} client := model.Client{}
clientData := model.ClientData{} clientData := model.ClientData{}
@ -200,9 +200,17 @@ func (o *JsonDB) GetClientByID(clientID string, hasQRCode bool) (model.ClientDat
} }
// generate client qrcode image in base64 // generate client qrcode image in base64
if hasQRCode && client.PrivateKey != "" { if qrCodeSettings.Enabled && client.PrivateKey != "" {
server, _ := o.GetServer() server, _ := o.GetServer()
globalSettings, _ := o.GetGlobalSettings() globalSettings, _ := o.GetGlobalSettings()
client := client
client.UseServerDNS = qrCodeSettings.IncludeDNS
if !qrCodeSettings.IncludeMTU {
globalSettings.MTU = 0
}
if !qrCodeSettings.IncludeFwMark {
globalSettings.ForwardMark = ""
}
png, err := qrcode.Encode(util.BuildClientConfig(client, server, globalSettings), qrcode.Medium, 256) png, err := qrcode.Encode(util.BuildClientConfig(client, server, globalSettings), qrcode.Medium, 256)
if err == nil { if err == nil {

View file

@ -10,7 +10,7 @@ type IStore interface {
GetGlobalSettings() (model.GlobalSetting, error) GetGlobalSettings() (model.GlobalSetting, error)
GetServer() (model.Server, error) GetServer() (model.Server, error)
GetClients(hasQRCode bool) ([]model.ClientData, error) GetClients(hasQRCode bool) ([]model.ClientData, error)
GetClientByID(clientID string, hasQRCode bool) (model.ClientData, error) GetClientByID(clientID string, qrCode model.QRCodeSettings) (model.ClientData, error)
SaveClient(client model.Client) error SaveClient(client model.Client) error
DeleteClient(clientID string) error DeleteClient(clientID string) error
SaveServerInterface(serverInterface model.ServerInterface) error SaveServerInterface(serverInterface model.ServerInterface) error

View file

@ -68,7 +68,18 @@ Wireguard Clients
<span aria-hidden="true">&times;</span> <span aria-hidden="true">&times;</span>
</button> </button>
</div> </div>
<img id="qr_code" class="w-100" style="image-rendering: pixelated;" src="" alt="QR code" /> <div class="modal-body">
<input type="hidden" id="qr_client_id" name="qr_client_id">
<img id="qr_code" class="w-100" style="image-rendering: pixelated;" src="" alt="QR code" />
<div class="form-group">
<div class="icheck-primary d-inline">
<input type="checkbox" id="qr_include_fwmark" onchange="regenerateQRCode()">
<label for="qr_include_fwmark">
Include FwMark
</label>
</div>
</div>
</div>
</div> </div>
<!-- /.modal-content --> <!-- /.modal-content -->
</div> </div>
@ -376,6 +387,37 @@ Wireguard Clients
}); });
}); });
// regenerateQRCode function for regenerating QR Code adding/removing some parts of configuration because of compatibility issues with some clients
function regenerateQRCode() {
const client_id = $("#qr_client_id").val();
const QRCodeImg = $("#qr_code");
let include_fwmark = false;
if ($("#qr_include_fwmark").is(':checked')){
include_fwmark = true;
}
QRCodeImg.hide();
$.ajax({
cache: false,
method: 'GET',
url: '{{.basePath}}/api/client/' + client_id,
data: {
qrCodeIncludeFwMark: include_fwmark
},
dataType: 'json',
contentType: "application/json",
success: function (resp) {
const client = resp.Client;
$(".modal-title").text("Scan QR Code for " + client.name + " profile");
QRCodeImg.attr('src', resp.QRCode).show();
},
error: function (jqXHR, exception) {
const responseJson = jQuery.parseJSON(jqXHR.responseText);
toastr.error(responseJson['message']);
}
});
}
// submitEmailClient function for sending an email to the client with the configuration // submitEmailClient function for sending an email to the client with the configuration
function submitEmailClient() { function submitEmailClient() {
const client_id = $("#e_client_id").val(); const client_id = $("#e_client_id").val();
@ -453,7 +495,7 @@ Wireguard Clients
const formId = $(form).attr('id'); const formId = $(form).attr('id');
if (formId === "frm_edit_client") { if (formId === "frm_edit_client") {
submitEditClient(); submitEditClient();
}else if (formId === "frm_email_client") { } else if (formId === "frm_email_client") {
submitEmailClient(); submitEmailClient();
} }
} }
@ -486,31 +528,14 @@ Wireguard Clients
let modal = $(this); let modal = $(this);
const button = $(event.relatedTarget); const button = $(event.relatedTarget);
const client_id = button.data('clientid'); const client_id = button.data('clientid');
const QRCodeImg = modal.find("#qr_code");
QRCodeImg.hide();
$.ajax({
cache: false,
method: 'GET',
url: '{{.basePath}}/api/client/' + client_id,
dataType: 'json',
contentType: "application/json",
success: function (resp) {
const client = resp.Client;
modal.find(".modal-title").text("Scan QR Code for " + client.name + " profile"); modal.find("#qr_client_id").val(client_id);
QRCodeImg.attr('src', resp.QRCode).show(); regenerateQRCode();
},
error: function (jqXHR, exception) {
const responseJson = jQuery.parseJSON(jqXHR.responseText);
toastr.error(responseJson['message']);
}
});
}); });
$(document).ready(function () { $(document).ready(function () {
$.validator.setDefaults({ $.validator.setDefaults({
submitHandler: function (form) { submitHandler: function (form) {
//submitEditClient();
submitHandler(form); submitHandler(form);
} }
}); });
@ -563,6 +588,7 @@ Wireguard Clients
$(element).removeClass('is-invalid'); $(element).removeClass('is-invalid');
} }
}); });
//
}); });
</script> </script>
{{end}} {{end}}

View file

@ -61,7 +61,7 @@ func BuildClientConfig(client model.Client, server model.Server, setting model.G
} }
forwardMark := "" forwardMark := ""
if setting.ForwardMark != "" && setting.ForwardMark != DefaultForwardMark { if setting.ForwardMark != "" {
forwardMark = fmt.Sprintf("FwMark = %s\n", setting.ForwardMark) forwardMark = fmt.Sprintf("FwMark = %s\n", setting.ForwardMark)
} }