Skip to content

Commit 9f20fe6

Browse files
authored
Show apply config button only when needed (ngoduykhanh#292)
1 parent 6dd5590 commit 9f20fe6

File tree

9 files changed

+144
-7
lines changed

9 files changed

+144
-7
lines changed

go.mod

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ require (
1919
github.com/sendgrid/sendgrid-go v3.10.0+incompatible
2020
github.com/skip2/go-qrcode v0.0.0-20191027152451-9434209cb086
2121
github.com/xhit/go-simple-mail/v2 v2.10.0
22-
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e
22+
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
23+
golang.org/x/mod v0.7.0
2324
//golang.zx2c4.com/wireguard v0.0.20200121 // indirect
2425
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210803171230-4253848d036c
2526
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect

go.sum

+20-4
Original file line numberDiff line numberDiff line change
@@ -157,20 +157,26 @@ github.com/valyala/fasttemplate v1.1.0 h1:RZqt0yGBsps8NGvLSGW804QQqCUYYLsaOjTVHy
157157
github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
158158
github.com/xhit/go-simple-mail/v2 v2.10.0 h1:nib6RaJ4qVh5HD9UE9QJqnUZyWp3upv+Z6CFxaMj0V8=
159159
github.com/xhit/go-simple-mail/v2 v2.10.0/go.mod h1:kA1XbQfCI4JxQ9ccSN6VFyIEkkugOm7YiPkA5hKiQn4=
160+
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
160161
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
161162
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
162163
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
163164
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
164165
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
165166
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
166167
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
167-
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e h1:8foAy0aoO5GkqCvAEJ4VC4P3zksTg4X4aJCDpZzmgQI=
168168
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
169+
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
170+
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
171+
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
172+
golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA=
173+
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
169174
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
170175
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
171176
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
172177
golang.org/x/net v0.0.0-20190607181551-461777fb6f67/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
173178
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
179+
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
174180
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
175181
golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
176182
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -181,11 +187,13 @@ golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v
181187
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
182188
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
183189
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
184-
golang.org/x/net v0.0.0-20210504132125-bbd867fde50d h1:nTDGCTeAu2LhcsHTRzjyIUbZHCJ4QePArsm27Hka0UM=
185190
golang.org/x/net v0.0.0-20210504132125-bbd867fde50d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
191+
golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
192+
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
186193
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
187194
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
188195
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
196+
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
189197
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
190198
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
191199
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -215,19 +223,27 @@ golang.org/x/sys v0.0.0-20210216163648-f7da38b97c65/go.mod h1:h1NjWce9XRLGQEsW7w
215223
golang.org/x/sys v0.0.0-20210309040221-94ec62e08169/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
216224
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
217225
golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
226+
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
218227
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
219228
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
220-
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b h1:1VkfZQv42XQlA/jchYumAnv1UPo6RgF9rJFkTgZIxO4=
221229
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
230+
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
231+
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
232+
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
222233
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
223234
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
235+
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
224236
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
225237
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
226238
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
227-
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
228239
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
240+
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
241+
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
229242
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
230243
golang.org/x/tools v0.0.0-20190608022120-eacb66d2a7c3/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
244+
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
245+
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
246+
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
231247
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
232248
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
233249
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

handler/routes.go

+20
Original file line numberDiff line numberDiff line change
@@ -983,11 +983,31 @@ func ApplyServerConfig(db store.IStore, tmplBox *rice.Box) echo.HandlerFunc {
983983
false, fmt.Sprintf("Cannot apply server config: %v", err),
984984
})
985985
}
986+
987+
err = util.UpdateHashes(db)
988+
if err != nil {
989+
log.Error("Cannot update hashes: ", err)
990+
return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{
991+
false, fmt.Sprintf("Cannot update hashes: %v", err),
992+
})
993+
}
986994

987995
return c.JSON(http.StatusOK, jsonHTTPResponse{true, "Applied server config successfully"})
988996
}
989997
}
990998

999+
1000+
// GetHashesChanges handler returns if database hashes have changed
1001+
func GetHashesChanges(db store.IStore) echo.HandlerFunc {
1002+
return func(c echo.Context) error {
1003+
if util.HashesChanged(db) {
1004+
return c.JSON(http.StatusOK, jsonHTTPResponse{true, "Hashes changed"})
1005+
} else {
1006+
return c.JSON(http.StatusOK, jsonHTTPResponse{false, "Hashes not changed"})
1007+
}
1008+
}
1009+
}
1010+
9911011
// AboutPage handler
9921012
func AboutPage() echo.HandlerFunc {
9931013
return func(c echo.Context) error {

main.go

+1
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ func main() {
152152
sendmail = emailer.NewSmtpMail(util.SmtpHostname, util.SmtpPort, util.SmtpUsername, util.SmtpPassword, util.SmtpNoTLSCheck, util.SmtpAuthType, util.EmailFromName, util.EmailFrom, util.SmtpEncryption)
153153
}
154154

155+
app.GET(util.BasePath+"/test-hash", handler.GetHashesChanges(db), handler.ValidSession)
155156
app.GET(util.BasePath+"/about", handler.AboutPage())
156157
app.GET(util.BasePath+"/_health", handler.Health())
157158
app.GET(util.BasePath+"/favicon", handler.Favicon())

model/misc.go

+6
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,9 @@ type BaseData struct {
1212
CurrentUser string
1313
Admin bool
1414
}
15+
16+
// ClientServerHashes struct, to save hashes to detect changes
17+
type ClientServerHashes struct {
18+
Client string `json:"client"`
19+
Server string `json:"server"`
20+
}

store/jsondb/jsondb.go

+24-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ func (o *JsonDB) Init() error {
4242
var serverInterfacePath string = path.Join(serverPath, "interfaces.json")
4343
var serverKeyPairPath string = path.Join(serverPath, "keypair.json")
4444
var globalSettingPath string = path.Join(serverPath, "global_settings.json")
45-
var userPath string = path.Join(o.dbPath, "users")
45+
var hashesPath string = path.Join(serverPath, "hashes.json")
46+
var userPath string = path.Join(serverPath, "users.json")
47+
4648
// create directories if they do not exist
4749
if _, err := os.Stat(clientPath); os.IsNotExist(err) {
4850
os.MkdirAll(clientPath, os.ModePerm)
@@ -104,6 +106,14 @@ func (o *JsonDB) Init() error {
104106
globalSetting.UpdatedAt = time.Now().UTC()
105107
o.conn.Write("server", "global_settings", globalSetting)
106108
}
109+
110+
// hashes
111+
if _, err := os.Stat(hashesPath); os.IsNotExist(err) {
112+
clientServerHashes := new(model.ClientServerHashes)
113+
clientServerHashes.Client = "none"
114+
clientServerHashes.Server = "none"
115+
o.conn.Write("server", "hashes", clientServerHashes)
116+
}
107117

108118
// user info
109119
results, err := o.conn.ReadAll("users")
@@ -295,3 +305,16 @@ func (o *JsonDB) SaveServerKeyPair(serverKeyPair model.ServerKeypair) error {
295305
func (o *JsonDB) SaveGlobalSettings(globalSettings model.GlobalSetting) error {
296306
return o.conn.Write("server", "global_settings", globalSettings)
297307
}
308+
309+
func (o *JsonDB) GetPath() string {
310+
return o.dbPath
311+
}
312+
313+
func (o *JsonDB) GetHashes() (model.ClientServerHashes, error) {
314+
hashes := model.ClientServerHashes{}
315+
return hashes, o.conn.Read("server", "hashes", &hashes)
316+
}
317+
318+
func (o *JsonDB) SaveHashes(hashes model.ClientServerHashes) error {
319+
return o.conn.Write("server", "hashes", hashes)
320+
}

store/store.go

+3
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,7 @@ type IStore interface {
2424
DeleteWakeOnHostLanHost(macAddress string) error
2525
SaveWakeOnLanHost(host model.WakeOnLanHost) error
2626
DeleteWakeOnHost(host model.WakeOnLanHost) error
27+
GetPath() string
28+
SaveHashes(hashes model.ClientServerHashes) error
29+
GetHashes() (model.ClientServerHashes, error)
2730
}

templates/base.html

+27-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
<button style="margin-left: 0.5em;" type="button" class="btn btn-outline-primary btn-sm" data-toggle="modal"
6464
data-target="#modal_new_client"><i class="nav-icon fas fa-plus"></i> New
6565
Client</button>
66-
<button style="margin-left: 0.5em;" type="button" class="btn btn-outline-danger btn-sm" data-toggle="modal"
66+
<button id="apply-config-button" style="margin-left: 0.5em; display: none;" type="button" class="btn btn-outline-danger btn-sm" data-toggle="modal"
6767
data-target="#modal_apply_config"><i class="nav-icon fas fa-check"></i> Apply
6868
Config</button>
6969
{{if .baseData.CurrentUser}}
@@ -351,6 +351,32 @@ <h1>{{template "page_title" .}}</h1>
351351
$('[data-toggle="tooltip"]').tooltip()
352352
})
353353

354+
$(document).ready(function () {
355+
356+
$.ajax({
357+
cache: false,
358+
method: 'GET',
359+
url: '{{.basePath}}/test-hash',
360+
dataType: 'json',
361+
contentType: "application/json",
362+
success: function(data) {
363+
if (data.status) {
364+
$("#apply-config-button").show()
365+
}
366+
else
367+
{
368+
$("#apply-config-button").hide()
369+
}
370+
},
371+
error: function(jqXHR, exception) {
372+
const responseJson = jQuery.parseJSON(jqXHR.responseText);
373+
toastr.error(responseJson['message']);
374+
}
375+
});
376+
377+
});
378+
379+
354380
// populateClient function for render new client info
355381
// on the client page.
356382
function populateClient(client_id) {

util/util.go

+41
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@ import (
44
"encoding/json"
55
"errors"
66
"fmt"
7+
"github.com/ngoduykhanh/wireguard-ui/store"
8+
"golang.org/x/mod/sumdb/dirhash"
9+
"io"
710
"io/ioutil"
811
"net"
912
"os"
13+
"path"
14+
"path/filepath"
1015
"strconv"
1116
"strings"
1217
"text/template"
@@ -463,3 +468,39 @@ func LookupEnvOrStrings(key string, defaultVal []string) []string {
463468
}
464469
return defaultVal
465470
}
471+
472+
// GetCurrentHash returns current hashes
473+
func GetCurrentHash(db store.IStore) (string, string) {
474+
hashClients, _ := dirhash.HashDir(path.Join(db.GetPath(), "clients"), "prefix", dirhash.Hash1)
475+
files := append([]string(nil), "prefix/global_settings.json", "prefix/interfaces.json", "prefix/keypair.json")
476+
477+
osOpen := func(name string) (io.ReadCloser, error) {
478+
return os.Open(filepath.Join(path.Join(db.GetPath(), "server"), strings.TrimPrefix(name, "prefix")))
479+
}
480+
hashServer, _ := dirhash.Hash1(files, osOpen)
481+
482+
return hashClients, hashServer
483+
}
484+
485+
func HashesChanged(db store.IStore) bool {
486+
old, _ := db.GetHashes()
487+
oldClient := old.Client
488+
oldServer := old.Server
489+
newClient, newServer := GetCurrentHash(db)
490+
491+
if oldClient != newClient {
492+
fmt.Println("Hash for client differs")
493+
return true
494+
}
495+
if oldServer != newServer {
496+
fmt.Println("Hash for server differs")
497+
return true
498+
}
499+
return false
500+
}
501+
502+
func UpdateHashes(db store.IStore) error {
503+
var clientServerHashes model.ClientServerHashes
504+
clientServerHashes.Client, clientServerHashes.Server = GetCurrentHash(db)
505+
return db.SaveHashes(clientServerHashes)
506+
}

0 commit comments

Comments
 (0)