Merge branch 'master' into client-default-settings
This commit is contained in:
		
						commit
						97e7ead5fd
					
				|  | @ -40,20 +40,12 @@ jobs: | ||||||
|         node-version: '14' |         node-version: '14' | ||||||
|         registry-url: 'https://registry.npmjs.org' |         registry-url: 'https://registry.npmjs.org' | ||||||
| 
 | 
 | ||||||
|     # prepare assets for go rice |     # prepare assets | ||||||
|     - name: Prepare assets |     - name: Prepare assets | ||||||
|       run: | |       run: | | ||||||
|         chmod +x ./prepare_assets.sh |         chmod +x ./prepare_assets.sh | ||||||
|         ./prepare_assets.sh |         ./prepare_assets.sh | ||||||
| 
 | 
 | ||||||
|     # get go rice tool |  | ||||||
|     - name: Get go rice tool |  | ||||||
|       run: go get github.com/GeertJohan/go.rice/rice |  | ||||||
| 
 |  | ||||||
|     # run go rice embed |  | ||||||
|     - name: Run go rice embed |  | ||||||
|       run: ${HOME}/go/bin/rice embed-go |  | ||||||
| 
 |  | ||||||
|     # build and make the releases |     # build and make the releases | ||||||
|     - name: Build and make the releases |     - name: Build and make the releases | ||||||
|       uses: wangyoucao577/go-release-action@master |       uses: wangyoucao577/go-release-action@master | ||||||
|  |  | ||||||
|  | @ -16,7 +16,6 @@ wireguard-ui | ||||||
| vendor/ | vendor/ | ||||||
| assets/ | assets/ | ||||||
| node_modules/ | node_modules/ | ||||||
| rice-box.go |  | ||||||
| 
 | 
 | ||||||
| # IDEs | # IDEs | ||||||
| .vscode | .vscode | ||||||
|  |  | ||||||
|  | @ -43,10 +43,6 @@ RUN mkdir -p assets/plugins && \ | ||||||
|     /build/node_modules/jquery-tags-input/ \ |     /build/node_modules/jquery-tags-input/ \ | ||||||
|     assets/plugins/ |     assets/plugins/ | ||||||
| 
 | 
 | ||||||
| # Get go modules and build tool |  | ||||||
| RUN go mod download && \ |  | ||||||
|     go get github.com/GeertJohan/go.rice/rice |  | ||||||
| 
 |  | ||||||
| # Add sources | # Add sources | ||||||
| COPY . /build | COPY . /build | ||||||
| 
 | 
 | ||||||
|  | @ -54,8 +50,7 @@ COPY . /build | ||||||
| RUN cp -r /build/custom/ assets/ | RUN cp -r /build/custom/ assets/ | ||||||
| 
 | 
 | ||||||
| # Build | # Build | ||||||
| RUN rice embed-go && \ | RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -ldflags="-X main.gitCommit=${COMMIT}" -a -o wg-ui . | ||||||
|     CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -ldflags="-X main.gitCommit=${COMMIT}" -a -o wg-ui . |  | ||||||
| 
 | 
 | ||||||
| # Release stage | # Release stage | ||||||
| FROM alpine:3.16 | FROM alpine:3.16 | ||||||
|  |  | ||||||
							
								
								
									
										16
									
								
								README.md
								
								
								
								
							
							
						
						
									
										16
									
								
								README.md
								
								
								
								
							|  | @ -203,6 +203,11 @@ or | ||||||
| docker compose build --build-arg=COMMIT=$(git rev-parse --short HEAD) | docker compose build --build-arg=COMMIT=$(git rev-parse --short HEAD) | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
|  | :information_source: A container image is avaialble on [Docker Hub](https://hub.docker.com/r/ngoduykhanh/wireguard-ui) which you can pull and use  | ||||||
|  | ``` | ||||||
|  | docker pull ngoduykhanh/wireguard-ui | ||||||
|  | ```` | ||||||
|  | 
 | ||||||
| ### Build binary file | ### Build binary file | ||||||
| 
 | 
 | ||||||
| Prepare the assets directory | Prepare the assets directory | ||||||
|  | @ -211,18 +216,9 @@ Prepare the assets directory | ||||||
| ./prepare_assets.sh | ./prepare_assets.sh | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| Then you can embed resources by generating Go source code | Then build your executable | ||||||
| 
 |  | ||||||
| ```sh |  | ||||||
| rice embed-go |  | ||||||
| go build -o wireguard-ui |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| Or, append resources to executable as zip file |  | ||||||
| 
 |  | ||||||
| ```sh | ```sh | ||||||
| go build -o wireguard-ui | go build -o wireguard-ui | ||||||
| rice append --exec wireguard-ui |  | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ## License | ## License | ||||||
|  |  | ||||||
							
								
								
									
										3
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										3
									
								
								go.mod
								
								
								
								
							|  | @ -1,9 +1,8 @@ | ||||||
| module github.com/ngoduykhanh/wireguard-ui | module github.com/ngoduykhanh/wireguard-ui | ||||||
| 
 | 
 | ||||||
| go 1.14 | go 1.16 | ||||||
| 
 | 
 | ||||||
| require ( | require ( | ||||||
| 	github.com/GeertJohan/go.rice v1.0.2 |  | ||||||
| 	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 | ||||||
|  |  | ||||||
							
								
								
									
										9
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										9
									
								
								go.sum
								
								
								
								
							|  | @ -1,8 +1,4 @@ | ||||||
| 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/go.mod h1:af5vUNlDNkCjOZeSGFgIJxDje9qdjsO6hshx0gTmZt4= |  | ||||||
| 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/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= | ||||||
| github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw= | github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw= | ||||||
|  | @ -12,8 +8,6 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r | ||||||
| github.com/casbin/casbin/v2 v2.0.0/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= | github.com/casbin/casbin/v2 v2.0.0/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= | ||||||
| github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= | github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= | ||||||
| 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/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E= |  | ||||||
| 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,7 +46,6 @@ 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/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= | ||||||
| github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw= | github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw= | ||||||
|  | @ -109,7 +102,6 @@ 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/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= | ||||||
| github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||||||
|  | @ -252,7 +244,6 @@ golang.zx2c4.com/wireguard v0.0.0-20210427022245-097af6e1351b/go.mod h1:a057zjmo | ||||||
| golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210803171230-4253848d036c h1:ADNrRDI5NR23/TUCnEmlLZLt4u9DnZ2nwRkPrAcFvto= | golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210803171230-4253848d036c h1:ADNrRDI5NR23/TUCnEmlLZLt4u9DnZ2nwRkPrAcFvto= | ||||||
| golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210803171230-4253848d036c/go.mod h1:+1XihzyZUBJcSc5WO9SwNA7v26puQwOEDwanaxfNXPQ= | golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210803171230-4253848d036c/go.mod h1:+1XihzyZUBJcSc5WO9SwNA7v26puQwOEDwanaxfNXPQ= | ||||||
| gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= | ||||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= |  | ||||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||||
| gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= | gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= | ||||||
| gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= | gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= | ||||||
|  |  | ||||||
|  | @ -5,13 +5,13 @@ import ( | ||||||
| 	"encoding/base64" | 	"encoding/base64" | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"io/fs" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"os" | 	"os" | ||||||
| 	"sort" | 	"sort" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	rice "github.com/GeertJohan/go.rice" |  | ||||||
| 	"github.com/gorilla/sessions" | 	"github.com/gorilla/sessions" | ||||||
| 	"github.com/labstack/echo-contrib/session" | 	"github.com/labstack/echo-contrib/session" | ||||||
| 	"github.com/labstack/echo/v4" | 	"github.com/labstack/echo/v4" | ||||||
|  | @ -994,7 +994,7 @@ func SuggestIPAllocation(db store.IStore) echo.HandlerFunc { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ApplyServerConfig handler to write config file and restart Wireguard server
 | // ApplyServerConfig handler to write config file and restart Wireguard server
 | ||||||
| func ApplyServerConfig(db store.IStore, tmplBox *rice.Box) echo.HandlerFunc { | func ApplyServerConfig(db store.IStore, tmplDir fs.FS) echo.HandlerFunc { | ||||||
| 	return func(c echo.Context) error { | 	return func(c echo.Context) error { | ||||||
| 
 | 
 | ||||||
| 		server, err := db.GetServer() | 		server, err := db.GetServer() | ||||||
|  | @ -1022,7 +1022,7 @@ func ApplyServerConfig(db store.IStore, tmplBox *rice.Box) echo.HandlerFunc { | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// Write config file
 | 		// Write config file
 | ||||||
| 		err = util.WriteWireGuardServerConfig(tmplBox, server, clients, users, settings) | 		err = util.WriteWireGuardServerConfig(tmplDir, server, clients, users, settings) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Error("Cannot apply server config: ", err) | 			log.Error("Cannot apply server config: ", err) | ||||||
| 			return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{ | 			return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{ | ||||||
|  | @ -1062,4 +1062,3 @@ func AboutPage() echo.HandlerFunc { | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 |  | ||||||
|  |  | ||||||
							
								
								
									
										38
									
								
								main.go
								
								
								
								
							
							
						
						
									
										38
									
								
								main.go
								
								
								
								
							|  | @ -1,16 +1,17 @@ | ||||||
| package main | package main | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"embed" | ||||||
| 	"flag" | 	"flag" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"github.com/labstack/echo/v4" | 	"github.com/labstack/echo/v4" | ||||||
| 	"github.com/labstack/gommon/log" | 	"github.com/labstack/gommon/log" | ||||||
| 	"github.com/ngoduykhanh/wireguard-ui/store" | 	"github.com/ngoduykhanh/wireguard-ui/store" | ||||||
|  | 	"io/fs" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"os" | 	"os" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	rice "github.com/GeertJohan/go.rice" |  | ||||||
| 	"github.com/ngoduykhanh/wireguard-ui/emailer" | 	"github.com/ngoduykhanh/wireguard-ui/emailer" | ||||||
| 	"github.com/ngoduykhanh/wireguard-ui/handler" | 	"github.com/ngoduykhanh/wireguard-ui/handler" | ||||||
| 	"github.com/ngoduykhanh/wireguard-ui/router" | 	"github.com/ngoduykhanh/wireguard-ui/router" | ||||||
|  | @ -51,6 +52,16 @@ const ( | ||||||
| ` | ` | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | // embed the "templates" directory
 | ||||||
|  | //
 | ||||||
|  | //go:embed templates/*
 | ||||||
|  | var embeddedTemplates embed.FS | ||||||
|  | 
 | ||||||
|  | // embed the "assets" directory
 | ||||||
|  | //
 | ||||||
|  | //go:embed assets/*
 | ||||||
|  | var embeddedAssets embed.FS | ||||||
|  | 
 | ||||||
| func init() { | func init() { | ||||||
| 
 | 
 | ||||||
| 	// command-line flags and env variables
 | 	// command-line flags and env variables
 | ||||||
|  | @ -122,17 +133,15 @@ func main() { | ||||||
| 	extraData["gitCommit"] = gitCommit | 	extraData["gitCommit"] = gitCommit | ||||||
| 	extraData["basePath"] = util.BasePath | 	extraData["basePath"] = util.BasePath | ||||||
| 
 | 
 | ||||||
| 	// create rice box for embedded template
 | 	// strip the "templates/" prefix from the embedded directory so files can be read by their direct name (e.g.
 | ||||||
| 	tmplBox := rice.MustFindBox("templates") | 	// "base.html" instead of "templates/base.html")
 | ||||||
| 
 | 	tmplDir, _ := fs.Sub(fs.FS(embeddedTemplates), "templates") | ||||||
| 	// rice file server for assets. "assets" is the folder where the files come from.
 |  | ||||||
| 	assetHandler := http.FileServer(rice.MustFindBox("assets").HTTPBox()) |  | ||||||
| 
 | 
 | ||||||
| 	// create the wireguard config on start, if it doesn't exist
 | 	// create the wireguard config on start, if it doesn't exist
 | ||||||
| 	initServerConfig(db, tmplBox) | 	initServerConfig(db, tmplDir) | ||||||
| 
 | 
 | ||||||
| 	// register routes
 | 	// register routes
 | ||||||
| 	app := router.New(tmplBox, extraData, util.SessionSecret) | 	app := router.New(tmplDir, extraData, util.SessionSecret) | ||||||
| 
 | 
 | ||||||
| 	app.GET(util.BasePath, handler.WireGuardClients(db), handler.ValidSession) | 	app.GET(util.BasePath, handler.WireGuardClients(db), handler.ValidSession) | ||||||
| 
 | 
 | ||||||
|  | @ -170,7 +179,6 @@ func main() { | ||||||
| 	app.POST(util.BasePath+"/wg-server/interfaces", handler.WireGuardServerInterfaces(db), handler.ValidSession, handler.ContentTypeJson, handler.NeedsAdmin) | 	app.POST(util.BasePath+"/wg-server/interfaces", handler.WireGuardServerInterfaces(db), handler.ValidSession, handler.ContentTypeJson, handler.NeedsAdmin) | ||||||
| 	app.POST(util.BasePath+"/wg-server/keypair", handler.WireGuardServerKeyPair(db), handler.ValidSession, handler.ContentTypeJson, handler.NeedsAdmin) | 	app.POST(util.BasePath+"/wg-server/keypair", handler.WireGuardServerKeyPair(db), handler.ValidSession, handler.ContentTypeJson, handler.NeedsAdmin) | ||||||
| 	app.GET(util.BasePath+"/global-settings", handler.GlobalSettings(db), handler.ValidSession, handler.NeedsAdmin) | 	app.GET(util.BasePath+"/global-settings", handler.GlobalSettings(db), handler.ValidSession, handler.NeedsAdmin) | ||||||
| 
 |  | ||||||
| 	app.POST(util.BasePath+"/global-settings", handler.GlobalSettingSubmit(db), handler.ValidSession, handler.ContentTypeJson, handler.NeedsAdmin) | 	app.POST(util.BasePath+"/global-settings", handler.GlobalSettingSubmit(db), handler.ValidSession, handler.ContentTypeJson, handler.NeedsAdmin) | ||||||
| 	app.POST(util.BasePath+"/client-default-settings", handler.ClientDefaultSettingsSubmit(db), handler.ValidSession, handler.ContentTypeJson, handler.NeedsAdmin) | 	app.POST(util.BasePath+"/client-default-settings", handler.ClientDefaultSettingsSubmit(db), handler.ValidSession, handler.ContentTypeJson, handler.NeedsAdmin) | ||||||
| 	app.GET(util.BasePath+"/client-default-settings", handler.ClientDefaultSettings(db), handler.ValidSession, handler.NeedsAdmin) | 	app.GET(util.BasePath+"/client-default-settings", handler.ClientDefaultSettings(db), handler.ValidSession, handler.NeedsAdmin) | ||||||
|  | @ -180,19 +188,23 @@ func main() { | ||||||
| 	app.GET(util.BasePath+"/api/client/:id", handler.GetClient(db), handler.ValidSession) | 	app.GET(util.BasePath+"/api/client/:id", handler.GetClient(db), handler.ValidSession) | ||||||
| 	app.GET(util.BasePath+"/api/machine-ips", handler.MachineIPAddresses(), handler.ValidSession) | 	app.GET(util.BasePath+"/api/machine-ips", handler.MachineIPAddresses(), handler.ValidSession) | ||||||
| 	app.GET(util.BasePath+"/api/suggest-client-ips", handler.SuggestIPAllocation(db), handler.ValidSession) | 	app.GET(util.BasePath+"/api/suggest-client-ips", handler.SuggestIPAllocation(db), handler.ValidSession) | ||||||
| 	app.POST(util.BasePath+"/api/apply-wg-config", handler.ApplyServerConfig(db, tmplBox), handler.ValidSession, handler.ContentTypeJson) | 	app.POST(util.BasePath+"/api/apply-wg-config", handler.ApplyServerConfig(db, tmplDir), handler.ValidSession, handler.ContentTypeJson) | ||||||
| 	app.GET(util.BasePath+"/wake_on_lan_hosts", handler.GetWakeOnLanHosts(db), handler.ValidSession) | 	app.GET(util.BasePath+"/wake_on_lan_hosts", handler.GetWakeOnLanHosts(db), handler.ValidSession) | ||||||
| 	app.POST(util.BasePath+"/wake_on_lan_host", handler.SaveWakeOnLanHost(db), handler.ValidSession, handler.ContentTypeJson) | 	app.POST(util.BasePath+"/wake_on_lan_host", handler.SaveWakeOnLanHost(db), handler.ValidSession, handler.ContentTypeJson) | ||||||
| 	app.DELETE(util.BasePath+"/wake_on_lan_host/:mac_address", handler.DeleteWakeOnHost(db), handler.ValidSession, handler.ContentTypeJson) | 	app.DELETE(util.BasePath+"/wake_on_lan_host/:mac_address", handler.DeleteWakeOnHost(db), handler.ValidSession, handler.ContentTypeJson) | ||||||
| 	app.PUT(util.BasePath+"/wake_on_lan_host/:mac_address", handler.WakeOnHost(db), handler.ValidSession, handler.ContentTypeJson) | 	app.PUT(util.BasePath+"/wake_on_lan_host/:mac_address", handler.WakeOnHost(db), handler.ValidSession, handler.ContentTypeJson) | ||||||
| 
 | 
 | ||||||
| 	// servers other static files
 | 	// strip the "assets/" prefix from the embedded directory so files can be called directly without the "assets/"
 | ||||||
|  | 	// prefix
 | ||||||
|  | 	assetsDir, _ := fs.Sub(fs.FS(embeddedAssets), "assets") | ||||||
|  | 	assetHandler := http.FileServer(http.FS(assetsDir)) | ||||||
|  | 	// serves other static files
 | ||||||
| 	app.GET(util.BasePath+"/static/*", echo.WrapHandler(http.StripPrefix(util.BasePath+"/static/", assetHandler))) | 	app.GET(util.BasePath+"/static/*", echo.WrapHandler(http.StripPrefix(util.BasePath+"/static/", assetHandler))) | ||||||
| 
 | 
 | ||||||
| 	app.Logger.Fatal(app.Start(util.BindAddress)) | 	app.Logger.Fatal(app.Start(util.BindAddress)) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func initServerConfig(db store.IStore, tmplBox *rice.Box) { | func initServerConfig(db store.IStore, tmplDir fs.FS) { | ||||||
| 	settings, err := db.GetGlobalSettings() | 	settings, err := db.GetGlobalSettings() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Fatalf("Cannot get global settings: ", err) | 		log.Fatalf("Cannot get global settings: ", err) | ||||||
|  | @ -219,7 +231,7 @@ func initServerConfig(db store.IStore, tmplBox *rice.Box) { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// write config file
 | 	// write config file
 | ||||||
| 	err = util.WriteWireGuardServerConfig(tmplBox, server, clients, users, settings) | 	err = util.WriteWireGuardServerConfig(tmplDir, server, clients, users, settings) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Fatalf("Cannot create server config: ", err) | 		log.Fatalf("Cannot create server config: ", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -3,11 +3,11 @@ package router | ||||||
| import ( | import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"io" | 	"io" | ||||||
|  | 	"io/fs" | ||||||
| 	"reflect" | 	"reflect" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"text/template" | 	"text/template" | ||||||
| 
 | 
 | ||||||
| 	rice "github.com/GeertJohan/go.rice" |  | ||||||
| 	"github.com/gorilla/sessions" | 	"github.com/gorilla/sessions" | ||||||
| 	"github.com/labstack/echo-contrib/session" | 	"github.com/labstack/echo-contrib/session" | ||||||
| 	"github.com/labstack/echo/v4" | 	"github.com/labstack/echo/v4" | ||||||
|  | @ -48,62 +48,62 @@ func (t *TemplateRegistry) Render(w io.Writer, name string, data interface{}, c | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // New function
 | // New function
 | ||||||
| func New(tmplBox *rice.Box, extraData map[string]string, secret []byte) *echo.Echo { | func New(tmplDir fs.FS, extraData map[string]string, secret []byte) *echo.Echo { | ||||||
| 	e := echo.New() | 	e := echo.New() | ||||||
| 	e.Use(session.Middleware(sessions.NewCookieStore(secret))) | 	e.Use(session.Middleware(sessions.NewCookieStore(secret))) | ||||||
| 
 | 
 | ||||||
| 	// read html template file to string
 | 	// read html template file to string
 | ||||||
| 	tmplBaseString, err := tmplBox.String("base.html") | 	tmplBaseString, err := util.StringFromEmbedFile(tmplDir, "base.html") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Fatal(err) | 		log.Fatal(err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	tmplLoginString, err := tmplBox.String("login.html") | 	tmplLoginString, err := util.StringFromEmbedFile(tmplDir, "login.html") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Fatal(err) | 		log.Fatal(err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	tmplProfileString, err := tmplBox.String("profile.html") | 	tmplProfileString, err := util.StringFromEmbedFile(tmplDir, "profile.html") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Fatal(err) | 		log.Fatal(err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	tmplClientsString, err := tmplBox.String("clients.html") | 	tmplClientsString, err := util.StringFromEmbedFile(tmplDir, "clients.html") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Fatal(err) | 		log.Fatal(err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	tmplServerString, err := tmplBox.String("server.html") | 	tmplServerString, err := util.StringFromEmbedFile(tmplDir, "server.html") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Fatal(err) | 		log.Fatal(err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	tmplGlobalSettingsString, err := tmplBox.String("global_settings.html") | 	tmplGlobalSettingsString, err := util.StringFromEmbedFile(tmplDir, "global_settings.html") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Fatal(err) | 		log.Fatal(err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	tmplClientDefaultSettingsString, err := tmplBox.String("client_default_settings.html") | 	tmplClientDefaultSettingsString, err := util.StringFromEmbedFile("client_default_settings.html") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Fatal(err) | 		log.Fatal(err) | ||||||
| 	} | 	} | ||||||
|    |    | ||||||
| 	tmplUsersSettingsString, err := tmplBox.String("users_settings.html") | 	tmplUsersSettingsString, err := util.StringFromEmbedFile(tmplDir, "users_settings.html") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Fatal(err) | 		log.Fatal(err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	tmplStatusString, err := tmplBox.String("status.html") | 	tmplStatusString, err := util.StringFromEmbedFile(tmplDir, "status.html") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Fatal(err) | 		log.Fatal(err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	tmplWakeOnLanHostsString, err := tmplBox.String("wake_on_lan_hosts.html") | 	tmplWakeOnLanHostsString, err := util.StringFromEmbedFile(tmplDir, "wake_on_lan_hosts.html") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Fatal(err) | 		log.Fatal(err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	aboutPageString, err := tmplBox.String("about.html") | 	aboutPageString, err := util.StringFromEmbedFile(tmplDir, "about.html") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Fatal(err) | 		log.Fatal(err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -56,13 +56,15 @@ | ||||||
|                         </button> |                         </button> | ||||||
|                     </div> |                     </div> | ||||||
|                 </div> |                 </div> | ||||||
|                 <select name="status-selector" id="status-selector" class="form-control selectpicker show-tick" style="margin-left: 10px"> |                 <div class="form-group form-group-sm"> | ||||||
|                     <option value="All">All</option> |                     <select name="status-selector" id="status-selector" class="custom-select form-control-navbar" style="margin-left: 0.5em; height: 90%; font-size: 14px;"> | ||||||
|                     <option value="Enabled">Enabled</option> |                         <option value="All">All</option> | ||||||
|                     <option value="Disabled">Disabled</option> |                         <option value="Enabled">Enabled</option> | ||||||
|                     <option value="Connected">Connected</option> |                         <option value="Disabled">Disabled</option> | ||||||
|                     <option value="Disconnected">Disconnected</option> |                         <option value="Connected">Connected</option> | ||||||
|                 </select> |                         <option value="Disconnected">Disconnected</option> | ||||||
|  |                     </select> | ||||||
|  |                 </div> | ||||||
|             </form> |             </form> | ||||||
| 
 | 
 | ||||||
|             <!-- Right navbar links --> |             <!-- Right navbar links --> | ||||||
|  |  | ||||||
|  | @ -481,7 +481,9 @@ Wireguard Clients | ||||||
|                 cache: false, |                 cache: false, | ||||||
|                 method: 'GET', |                 method: 'GET', | ||||||
|                 url: '{{.basePath}}/api/client/' + client_id, |                 url: '{{.basePath}}/api/client/' + client_id, | ||||||
|                 data: JSON.stringify(data), |                 data: { | ||||||
|  |                     qrCodeIncludeFwMark: include_fwmark | ||||||
|  |                 }, | ||||||
|                 dataType: 'json', |                 dataType: 'json', | ||||||
|                 contentType: "application/json", |                 contentType: "application/json", | ||||||
|                 success: function (resp) { |                 success: function (resp) { | ||||||
|  |  | ||||||
|  | @ -42,7 +42,7 @@ Users Settings | ||||||
|                     </div> |                     </div> | ||||||
|                     <div class="form-group"> |                     <div class="form-group"> | ||||||
|                         <label for="_user_password" class="control-label">Password</label> |                         <label for="_user_password" class="control-label">Password</label> | ||||||
|                         <input type="text" class="form-control" id="_user_password" name="_user_password" value="" |                         <input type="password" class="form-control" id="_user_password" name="_user_password" value="" | ||||||
|                                placeholder="Leave empty to keep the password unchanged"> |                                placeholder="Leave empty to keep the password unchanged"> | ||||||
|                     </div> |                     </div> | ||||||
|                     <div class="form-group"> |                     <div class="form-group"> | ||||||
|  |  | ||||||
							
								
								
									
										22
									
								
								util/util.go
								
								
								
								
							
							
						
						
									
										22
									
								
								util/util.go
								
								
								
								
							|  | @ -7,6 +7,7 @@ import ( | ||||||
| 	"github.com/ngoduykhanh/wireguard-ui/store" | 	"github.com/ngoduykhanh/wireguard-ui/store" | ||||||
| 	"golang.org/x/mod/sumdb/dirhash" | 	"golang.org/x/mod/sumdb/dirhash" | ||||||
| 	"io" | 	"io" | ||||||
|  | 	"io/fs" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"net" | 	"net" | ||||||
| 	"os" | 	"os" | ||||||
|  | @ -17,7 +18,6 @@ import ( | ||||||
| 	"text/template" | 	"text/template" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	rice "github.com/GeertJohan/go.rice" |  | ||||||
| 	externalip "github.com/glendc/go-external-ip" | 	externalip "github.com/glendc/go-external-ip" | ||||||
| 	"github.com/labstack/gommon/log" | 	"github.com/labstack/gommon/log" | ||||||
| 	"github.com/ngoduykhanh/wireguard-ui/model" | 	"github.com/ngoduykhanh/wireguard-ui/model" | ||||||
|  | @ -400,7 +400,7 @@ func ValidateIPAllocation(serverAddresses []string, ipAllocatedList []string, ip | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // WriteWireGuardServerConfig to write Wireguard server config. e.g. wg0.conf
 | // WriteWireGuardServerConfig to write Wireguard server config. e.g. wg0.conf
 | ||||||
| func WriteWireGuardServerConfig(tmplBox *rice.Box, serverConfig model.Server, clientDataList []model.ClientData, usersList []model.User, globalSettings model.GlobalSetting) error { | func WriteWireGuardServerConfig(tmplDir fs.FS, serverConfig model.Server, clientDataList []model.ClientData, usersList []model.User, globalSettings model.GlobalSetting) error { | ||||||
| 	var tmplWireguardConf string | 	var tmplWireguardConf string | ||||||
| 
 | 
 | ||||||
| 	// if set, read wg.conf template from WgConfTemplate
 | 	// if set, read wg.conf template from WgConfTemplate
 | ||||||
|  | @ -412,7 +412,7 @@ func WriteWireGuardServerConfig(tmplBox *rice.Box, serverConfig model.Server, cl | ||||||
| 		tmplWireguardConf = string(fileContentBytes) | 		tmplWireguardConf = string(fileContentBytes) | ||||||
| 	} else { | 	} else { | ||||||
| 		// read default wg.conf template file to string
 | 		// read default wg.conf template file to string
 | ||||||
| 		fileContent, err := tmplBox.String("wg.conf") | 		fileContent, err := StringFromEmbedFile(tmplDir, "wg.conf") | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
|  | @ -483,6 +483,18 @@ func LookupEnvOrStrings(key string, defaultVal []string) []string { | ||||||
| 	return defaultVal | 	return defaultVal | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func StringFromEmbedFile(embed fs.FS, filename string) (string, error) { | ||||||
|  | 	file, err := embed.Open(filename) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  | 	content, err := io.ReadAll(file) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  | 	return string(content), nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func ParseLogLevel(lvl string) (log.Lvl, error) { | func ParseLogLevel(lvl string) (log.Lvl, error) { | ||||||
| 	switch strings.ToLower(lvl) { | 	switch strings.ToLower(lvl) { | ||||||
| 	case "debug": | 	case "debug": | ||||||
|  | @ -520,11 +532,11 @@ func HashesChanged(db store.IStore) bool { | ||||||
| 	newClient, newServer := GetCurrentHash(db) | 	newClient, newServer := GetCurrentHash(db) | ||||||
| 
 | 
 | ||||||
| 	if oldClient != newClient { | 	if oldClient != newClient { | ||||||
| 		fmt.Println("Hash for client differs") | 		//fmt.Println("Hash for client differs")
 | ||||||
| 		return true | 		return true | ||||||
| 	} | 	} | ||||||
| 	if oldServer != newServer { | 	if oldServer != newServer { | ||||||
| 		fmt.Println("Hash for server differs") | 		//fmt.Println("Hash for server differs")
 | ||||||
| 		return true | 		return true | ||||||
| 	} | 	} | ||||||
| 	return false | 	return false | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue