mirror of
https://github.com/ngoduykhanh/wireguard-ui.git
synced 2025-04-19 19:59:13 +03:00
*: allows for BASE_PATH configuration (#183)
This commit is contained in:
parent
90bb2851bf
commit
87b08a8f7c
13 changed files with 108 additions and 84 deletions
16
Dockerfile
16
Dockerfile
|
@ -13,8 +13,11 @@ RUN apk add --update --no-cache ${BUILD_DEPENDENCIES}
|
||||||
|
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
|
|
||||||
# Add sources
|
# Add dependencies
|
||||||
COPY . /build
|
COPY go.mod /build
|
||||||
|
COPY go.sum /build
|
||||||
|
COPY package.json /build
|
||||||
|
COPY yarn.lock /build
|
||||||
|
|
||||||
# Prepare assets
|
# Prepare assets
|
||||||
RUN yarn install --pure-lockfile --production && \
|
RUN yarn install --pure-lockfile --production && \
|
||||||
|
@ -39,13 +42,16 @@ RUN mkdir -p assets/plugins && \
|
||||||
/build/node_modules/jquery-tags-input/ \
|
/build/node_modules/jquery-tags-input/ \
|
||||||
assets/plugins/
|
assets/plugins/
|
||||||
|
|
||||||
# Move custom assets
|
|
||||||
RUN cp -r /build/custom/ assets/
|
|
||||||
|
|
||||||
# Get go modules and build tool
|
# Get go modules and build tool
|
||||||
RUN go mod download && \
|
RUN go mod download && \
|
||||||
go get github.com/GeertJohan/go.rice/rice
|
go get github.com/GeertJohan/go.rice/rice
|
||||||
|
|
||||||
|
# Add sources
|
||||||
|
COPY . /build
|
||||||
|
|
||||||
|
# Move custom assets
|
||||||
|
RUN cp -r /build/custom/ assets/
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
RUN rice embed-go && \
|
RUN rice embed-go && \
|
||||||
CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -a -o wg-ui .
|
CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -a -o wg-ui .
|
||||||
|
|
|
@ -35,6 +35,8 @@ Set the `SESSION_SECRET` environment variable to a random value.
|
||||||
|
|
||||||
To use custom `wg.conf` template set the `WG_CONF_TEMPLATE` environment variable to a path to such file. Make sure `wireguard-ui` will be able to work with it - use [default template](templates/wg.conf) for reference.
|
To use custom `wg.conf` template set the `WG_CONF_TEMPLATE` environment variable to a path to such file. Make sure `wireguard-ui` will be able to work with it - use [default template](templates/wg.conf) for reference.
|
||||||
|
|
||||||
|
Set the `BASE_PATH` environment variable if you run wireguard-ui under a subpath of your reverse proxy virtual host (e.g. /wireguard).
|
||||||
|
|
||||||
In order to sent the wireguard configuration to clients via email, set the following environment variables:
|
In order to sent the wireguard configuration to clients via email, set the following environment variables:
|
||||||
|
|
||||||
- using SendGrid API
|
- using SendGrid API
|
||||||
|
|
|
@ -26,7 +26,7 @@ function renderClientList(data) {
|
||||||
</div>
|
</div>
|
||||||
<div class="info-box-content">
|
<div class="info-box-content">
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<a href="/download?clientid=${obj.Client.id}" class="btn btn-outline-primary btn-sm">Download</a>
|
<a href="download?clientid=${obj.Client.id}" class="btn btn-outline-primary btn-sm">Download</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<button type="button" class="btn btn-outline-primary btn-sm" data-toggle="modal"
|
<button type="button" class="btn btn-outline-primary btn-sm" data-toggle="modal"
|
||||||
|
|
|
@ -53,7 +53,7 @@ func Login(db store.IStore) echo.HandlerFunc {
|
||||||
// TODO: refresh the token
|
// TODO: refresh the token
|
||||||
sess, _ := session.Get("session", c)
|
sess, _ := session.Get("session", c)
|
||||||
sess.Options = &sessions.Options{
|
sess.Options = &sessions.Options{
|
||||||
Path: "/",
|
Path: util.BasePath,
|
||||||
MaxAge: 86400,
|
MaxAge: 86400,
|
||||||
HttpOnly: true,
|
HttpOnly: true,
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ func Login(db store.IStore) echo.HandlerFunc {
|
||||||
func Logout() echo.HandlerFunc {
|
func Logout() echo.HandlerFunc {
|
||||||
return func(c echo.Context) error {
|
return func(c echo.Context) error {
|
||||||
clearSession(c)
|
clearSession(c)
|
||||||
return c.Redirect(http.StatusTemporaryRedirect, "/login")
|
return c.Redirect(http.StatusTemporaryRedirect, util.BasePath + "/login")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,9 @@ func ValidSession(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
if !isValidSession(c) {
|
if !isValidSession(c) {
|
||||||
nextURL := c.Request().URL
|
nextURL := c.Request().URL
|
||||||
if nextURL != nil && c.Request().Method == http.MethodGet {
|
if nextURL != nil && c.Request().Method == http.MethodGet {
|
||||||
return c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("/login?next=%s", c.Request().URL))
|
return c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf(util.BasePath + "/login?next=%s", c.Request().URL))
|
||||||
} else {
|
} else {
|
||||||
return c.Redirect(http.StatusTemporaryRedirect, "/login")
|
return c.Redirect(http.StatusTemporaryRedirect, util.BasePath + "/login")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return next(c)
|
return next(c)
|
||||||
|
|
60
main.go
60
main.go
|
@ -35,6 +35,7 @@ var (
|
||||||
flagEmailFromName string = "WireGuard UI"
|
flagEmailFromName string = "WireGuard UI"
|
||||||
flagSessionSecret string
|
flagSessionSecret string
|
||||||
flagWgConfTemplate string
|
flagWgConfTemplate string
|
||||||
|
flagBasePath string
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -62,6 +63,7 @@ func init() {
|
||||||
flag.StringVar(&flagEmailFromName, "email-from-name", util.LookupEnvOrString("EMAIL_FROM_NAME", flagEmailFromName), "'From' email name.")
|
flag.StringVar(&flagEmailFromName, "email-from-name", util.LookupEnvOrString("EMAIL_FROM_NAME", flagEmailFromName), "'From' email name.")
|
||||||
flag.StringVar(&flagSessionSecret, "session-secret", util.LookupEnvOrString("SESSION_SECRET", flagSessionSecret), "The key used to encrypt session cookies.")
|
flag.StringVar(&flagSessionSecret, "session-secret", util.LookupEnvOrString("SESSION_SECRET", flagSessionSecret), "The key used to encrypt session cookies.")
|
||||||
flag.StringVar(&flagWgConfTemplate, "wg-conf-template", util.LookupEnvOrString("WG_CONF_TEMPLATE", flagWgConfTemplate), "Path to custom wg.conf template.")
|
flag.StringVar(&flagWgConfTemplate, "wg-conf-template", util.LookupEnvOrString("WG_CONF_TEMPLATE", flagWgConfTemplate), "Path to custom wg.conf template.")
|
||||||
|
flag.StringVar(&flagBasePath, "base-path", util.LookupEnvOrString("BASE_PATH", flagBasePath), "The base path of the URL")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
// update runtime config
|
// update runtime config
|
||||||
|
@ -78,6 +80,7 @@ func init() {
|
||||||
util.EmailFromName = flagEmailFromName
|
util.EmailFromName = flagEmailFromName
|
||||||
util.SessionSecret = []byte(flagSessionSecret)
|
util.SessionSecret = []byte(flagSessionSecret)
|
||||||
util.WgConfTemplate = flagWgConfTemplate
|
util.WgConfTemplate = flagWgConfTemplate
|
||||||
|
util.BasePath = util.ParseBasePath(flagBasePath)
|
||||||
|
|
||||||
// print app information
|
// print app information
|
||||||
fmt.Println("Wireguard UI")
|
fmt.Println("Wireguard UI")
|
||||||
|
@ -93,7 +96,7 @@ func init() {
|
||||||
fmt.Println("Email from name\t:", util.EmailFromName)
|
fmt.Println("Email from name\t:", util.EmailFromName)
|
||||||
//fmt.Println("Session secret\t:", util.SessionSecret)
|
//fmt.Println("Session secret\t:", util.SessionSecret)
|
||||||
fmt.Println("Custom wg.conf\t:", util.WgConfTemplate)
|
fmt.Println("Custom wg.conf\t:", util.WgConfTemplate)
|
||||||
|
fmt.Println("Base path\t:", util.BasePath + "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -107,6 +110,7 @@ func main() {
|
||||||
// set app extra data
|
// set app extra data
|
||||||
extraData := make(map[string]string)
|
extraData := make(map[string]string)
|
||||||
extraData["appVersion"] = appVersion
|
extraData["appVersion"] = appVersion
|
||||||
|
extraData["basePath"] = util.BasePath
|
||||||
|
|
||||||
// create rice box for embedded template
|
// create rice box for embedded template
|
||||||
tmplBox := rice.MustFindBox("templates")
|
tmplBox := rice.MustFindBox("templates")
|
||||||
|
@ -117,11 +121,11 @@ func main() {
|
||||||
// register routes
|
// register routes
|
||||||
app := router.New(tmplBox, extraData, util.SessionSecret)
|
app := router.New(tmplBox, extraData, util.SessionSecret)
|
||||||
|
|
||||||
app.GET("/", handler.WireGuardClients(db), handler.ValidSession)
|
app.GET(util.BasePath, handler.WireGuardClients(db), handler.ValidSession)
|
||||||
|
|
||||||
if !util.DisableLogin {
|
if !util.DisableLogin {
|
||||||
app.GET("/login", handler.LoginPage())
|
app.GET(util.BasePath + "/login", handler.LoginPage())
|
||||||
app.POST("/login", handler.Login(db))
|
app.POST(util.BasePath + "/login", handler.Login(db))
|
||||||
}
|
}
|
||||||
|
|
||||||
var sendmail emailer.Emailer
|
var sendmail emailer.Emailer
|
||||||
|
@ -131,32 +135,32 @@ func main() {
|
||||||
sendmail = emailer.NewSmtpMail(util.SmtpHostname, util.SmtpPort, util.SmtpUsername, util.SmtpPassword, util.SmtpNoTLSCheck, util.SmtpAuthType, util.EmailFromName, util.EmailFrom)
|
sendmail = emailer.NewSmtpMail(util.SmtpHostname, util.SmtpPort, util.SmtpUsername, util.SmtpPassword, util.SmtpNoTLSCheck, util.SmtpAuthType, util.EmailFromName, util.EmailFrom)
|
||||||
}
|
}
|
||||||
|
|
||||||
app.GET("/_health", handler.Health())
|
app.GET(util.BasePath + "/_health", handler.Health())
|
||||||
app.GET("/logout", handler.Logout(), handler.ValidSession)
|
app.GET(util.BasePath + "/logout", handler.Logout(), handler.ValidSession)
|
||||||
app.POST("/new-client", handler.NewClient(db), handler.ValidSession)
|
app.POST(util.BasePath + "/new-client", handler.NewClient(db), handler.ValidSession)
|
||||||
app.POST("/update-client", handler.UpdateClient(db), handler.ValidSession)
|
app.POST(util.BasePath + "/update-client", handler.UpdateClient(db), handler.ValidSession)
|
||||||
app.POST("/email-client", handler.EmailClient(db, sendmail, defaultEmailSubject, defaultEmailContent), handler.ValidSession)
|
app.POST(util.BasePath + "/email-client", handler.EmailClient(db, sendmail, defaultEmailSubject, defaultEmailContent), handler.ValidSession)
|
||||||
app.POST("/client/set-status", handler.SetClientStatus(db), handler.ValidSession)
|
app.POST(util.BasePath + "/client/set-status", handler.SetClientStatus(db), handler.ValidSession)
|
||||||
app.POST("/remove-client", handler.RemoveClient(db), handler.ValidSession)
|
app.POST(util.BasePath + "/remove-client", handler.RemoveClient(db), handler.ValidSession)
|
||||||
app.GET("/download", handler.DownloadClient(db), handler.ValidSession)
|
app.GET(util.BasePath + "/download", handler.DownloadClient(db), handler.ValidSession)
|
||||||
app.GET("/wg-server", handler.WireGuardServer(db), handler.ValidSession)
|
app.GET(util.BasePath + "/wg-server", handler.WireGuardServer(db), handler.ValidSession)
|
||||||
app.POST("wg-server/interfaces", handler.WireGuardServerInterfaces(db), handler.ValidSession)
|
app.POST(util.BasePath + "/wg-server/interfaces", handler.WireGuardServerInterfaces(db), handler.ValidSession)
|
||||||
app.POST("wg-server/keypair", handler.WireGuardServerKeyPair(db), handler.ValidSession)
|
app.POST(util.BasePath + "/wg-server/keypair", handler.WireGuardServerKeyPair(db), handler.ValidSession)
|
||||||
app.GET("/global-settings", handler.GlobalSettings(db), handler.ValidSession)
|
app.GET(util.BasePath + "/global-settings", handler.GlobalSettings(db), handler.ValidSession)
|
||||||
app.POST("/global-settings", handler.GlobalSettingSubmit(db), handler.ValidSession)
|
app.POST(util.BasePath + "/global-settings", handler.GlobalSettingSubmit(db), handler.ValidSession)
|
||||||
app.GET("/status", handler.Status(db), handler.ValidSession)
|
app.GET(util.BasePath + "/status", handler.Status(db), handler.ValidSession)
|
||||||
app.GET("/api/clients", handler.GetClients(db), handler.ValidSession)
|
app.GET(util.BasePath + "/api/clients", handler.GetClients(db), handler.ValidSession)
|
||||||
app.GET("/api/client/:id", handler.GetClient(db), handler.ValidSession)
|
app.GET(util.BasePath + "/api/client/:id", handler.GetClient(db), handler.ValidSession)
|
||||||
app.GET("/api/machine-ips", handler.MachineIPAddresses(), handler.ValidSession)
|
app.GET(util.BasePath + "/api/machine-ips", handler.MachineIPAddresses(), handler.ValidSession)
|
||||||
app.GET("/api/suggest-client-ips", handler.SuggestIPAllocation(db), handler.ValidSession)
|
app.GET(util.BasePath + "/api/suggest-client-ips", handler.SuggestIPAllocation(db), handler.ValidSession)
|
||||||
app.GET("/api/apply-wg-config", handler.ApplyServerConfig(db, tmplBox), handler.ValidSession)
|
app.GET(util.BasePath + "/api/apply-wg-config", handler.ApplyServerConfig(db, tmplBox), handler.ValidSession)
|
||||||
app.GET("/wake_on_lan_hosts", handler.GetWakeOnLanHosts(db), handler.ValidSession)
|
app.GET(util.BasePath + "/wake_on_lan_hosts", handler.GetWakeOnLanHosts(db), handler.ValidSession)
|
||||||
app.POST("/wake_on_lan_host", handler.SaveWakeOnLanHost(db), handler.ValidSession)
|
app.POST(util.BasePath + "/wake_on_lan_host", handler.SaveWakeOnLanHost(db), handler.ValidSession)
|
||||||
app.DELETE("/wake_on_lan_host/:mac_address", handler.DeleteWakeOnHost(db), handler.ValidSession)
|
app.DELETE(util.BasePath + "/wake_on_lan_host/:mac_address", handler.DeleteWakeOnHost(db), handler.ValidSession)
|
||||||
app.PUT("/wake_on_lan_host/:mac_address", handler.WakeOnHost(db), handler.ValidSession)
|
app.PUT(util.BasePath + "/wake_on_lan_host/:mac_address", handler.WakeOnHost(db), handler.ValidSession)
|
||||||
|
|
||||||
// servers other static files
|
// servers other static files
|
||||||
app.GET("/static/*", echo.WrapHandler(http.StripPrefix("/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))
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,19 +10,19 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
<!-- Font Awesome -->
|
<!-- Font Awesome -->
|
||||||
<link rel="stylesheet" href="static/plugins/fontawesome-free/css/all.min.css">
|
<link rel="stylesheet" href="{{.basePath}}/static/plugins/fontawesome-free/css/all.min.css">
|
||||||
<!-- iCheck for checkboxes and radio inputs -->
|
<!-- iCheck for checkboxes and radio inputs -->
|
||||||
<link rel="stylesheet" href="static/plugins/icheck-bootstrap/icheck-bootstrap.min.css">
|
<link rel="stylesheet" href="{{.basePath}}/static/plugins/icheck-bootstrap/icheck-bootstrap.min.css">
|
||||||
<!-- Select2 -->
|
<!-- Select2 -->
|
||||||
<link rel="stylesheet" href="static/plugins/select2/css/select2.min.css">
|
<link rel="stylesheet" href="{{.basePath}}/static/plugins/select2/css/select2.min.css">
|
||||||
<!-- Toastr -->
|
<!-- Toastr -->
|
||||||
<link rel="stylesheet" href="static/plugins/toastr/toastr.min.css">
|
<link rel="stylesheet" href="{{.basePath}}/static/plugins/toastr/toastr.min.css">
|
||||||
<!-- Jquery Tags Input -->
|
<!-- Jquery Tags Input -->
|
||||||
<link rel="stylesheet" href="static/plugins/jquery-tags-input/dist/jquery.tagsinput.min.css">
|
<link rel="stylesheet" href="{{.basePath}}/static/plugins/jquery-tags-input/dist/jquery.tagsinput.min.css">
|
||||||
<!-- Ionicons -->
|
<!-- Ionicons -->
|
||||||
<link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
|
<link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
|
||||||
<!-- overlayScrollbars -->
|
<!-- overlayScrollbars -->
|
||||||
<link rel="stylesheet" href="static/dist/css/adminlte.min.css">
|
<link rel="stylesheet" href="{{.basePath}}/static/dist/css/adminlte.min.css">
|
||||||
<!-- Google Font: Source Sans Pro -->
|
<!-- Google Font: Source Sans Pro -->
|
||||||
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700" rel="stylesheet">
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@
|
||||||
data-target="#modal_apply_config"><i class="nav-icon fas fa-check"></i> Apply
|
data-target="#modal_apply_config"><i class="nav-icon fas fa-check"></i> Apply
|
||||||
Config</button>
|
Config</button>
|
||||||
{{if .baseData.CurrentUser}}
|
{{if .baseData.CurrentUser}}
|
||||||
<button onclick="location.href='/logout';" style="margin-left: 0.5em;" type="button"
|
<button onclick="location.href='{{.basePath}}/logout';" style="margin-left: 0.5em;" type="button"
|
||||||
class="btn btn-outline-danger btn-sm"><i class="nav-icon fas fa-sign-out-alt"></i> Logout</button>
|
class="btn btn-outline-danger btn-sm"><i class="nav-icon fas fa-sign-out-alt"></i> Logout</button>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -75,7 +75,7 @@
|
||||||
<!-- Main Sidebar Container -->
|
<!-- Main Sidebar Container -->
|
||||||
<aside class="main-sidebar sidebar-dark-primary elevation-4">
|
<aside class="main-sidebar sidebar-dark-primary elevation-4">
|
||||||
<!-- Brand Logo -->
|
<!-- Brand Logo -->
|
||||||
<a href="/" class="brand-link">
|
<a href="{{.basePath}}" class="brand-link">
|
||||||
<span class="brand-text"> WIREGUARD UI</span>
|
<span class="brand-text"> WIREGUARD UI</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@
|
||||||
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false">
|
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false">
|
||||||
<li class="nav-header">MAIN</li>
|
<li class="nav-header">MAIN</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="/" class="nav-link {{if eq .baseData.Active ""}}active{{end}}">
|
<a href="{{.basePath}}" class="nav-link {{if eq .baseData.Active ""}}active{{end}}">
|
||||||
<i class="nav-icon fas fa-user-secret"></i>
|
<i class="nav-icon fas fa-user-secret"></i>
|
||||||
<p>
|
<p>
|
||||||
Wireguard Clients
|
Wireguard Clients
|
||||||
|
@ -104,7 +104,7 @@
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="/wg-server" class="nav-link {{if eq .baseData.Active "wg-server" }}active{{end}}">
|
<a href="{{.basePath}}/wg-server" class="nav-link {{if eq .baseData.Active "wg-server" }}active{{end}}">
|
||||||
<i class="nav-icon fas fa-server"></i>
|
<i class="nav-icon fas fa-server"></i>
|
||||||
<p>
|
<p>
|
||||||
Wireguard Server
|
Wireguard Server
|
||||||
|
@ -113,7 +113,7 @@
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-header">SETTINGS</li>
|
<li class="nav-header">SETTINGS</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="/global-settings" class="nav-link {{if eq .baseData.Active "global-settings" }}active{{end}}">
|
<a href="{{.basePath}}/global-settings" class="nav-link {{if eq .baseData.Active "global-settings" }}active{{end}}">
|
||||||
<i class="nav-icon fas fa-cog"></i>
|
<i class="nav-icon fas fa-cog"></i>
|
||||||
<p>
|
<p>
|
||||||
Global Settings
|
Global Settings
|
||||||
|
@ -122,7 +122,7 @@
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-header">UTILITIES</li>
|
<li class="nav-header">UTILITIES</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="/status" class="nav-link {{if eq .baseData.Active "status" }}active{{end}}">
|
<a href="{{.basePath}}/status" class="nav-link {{if eq .baseData.Active "status" }}active{{end}}">
|
||||||
<i class="nav-icon fas fa-signal"></i>
|
<i class="nav-icon fas fa-signal"></i>
|
||||||
<p>
|
<p>
|
||||||
Status
|
Status
|
||||||
|
@ -130,7 +130,7 @@
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="/wake_on_lan_hosts" class="nav-link {{if eq .baseData.Active "wake_on_lan_hosts" }}active{{end}}">
|
<a href="{{.basePath}}/wake_on_lan_hosts" class="nav-link {{if eq .baseData.Active "wake_on_lan_hosts" }}active{{end}}">
|
||||||
<i class="nav-icon fas fa-solid fa-power-off"></i>
|
<i class="nav-icon fas fa-solid fa-power-off"></i>
|
||||||
<p>
|
<p>
|
||||||
WoL Hosts
|
WoL Hosts
|
||||||
|
@ -295,21 +295,21 @@
|
||||||
<!-- ./wrapper -->
|
<!-- ./wrapper -->
|
||||||
|
|
||||||
<!-- jQuery -->
|
<!-- jQuery -->
|
||||||
<script src="static/plugins/jquery/jquery.min.js"></script>
|
<script src="{{.basePath}}/static/plugins/jquery/jquery.min.js"></script>
|
||||||
<!-- Bootstrap 4 -->
|
<!-- Bootstrap 4 -->
|
||||||
<script src="static/plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
|
<script src="{{.basePath}}/static/plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
|
||||||
<!-- Select2 -->
|
<!-- Select2 -->
|
||||||
<script src="static/plugins/select2/js/select2.full.min.js"></script>
|
<script src="{{.basePath}}/static/plugins/select2/js/select2.full.min.js"></script>
|
||||||
<!-- jquery-validation -->
|
<!-- jquery-validation -->
|
||||||
<script src="static/plugins/jquery-validation/jquery.validate.min.js"></script>
|
<script src="{{.basePath}}/static/plugins/jquery-validation/jquery.validate.min.js"></script>
|
||||||
<!-- Toastr -->
|
<!-- Toastr -->
|
||||||
<script src="static/plugins/toastr/toastr.min.js"></script>
|
<script src="{{.basePath}}/static/plugins/toastr/toastr.min.js"></script>
|
||||||
<!-- Jquery Tags Input -->
|
<!-- Jquery Tags Input -->
|
||||||
<script src="static/plugins/jquery-tags-input/dist/jquery.tagsinput.min.js"></script>
|
<script src="{{.basePath}}/static/plugins/jquery-tags-input/dist/jquery.tagsinput.min.js"></script>
|
||||||
<!-- AdminLTE App -->
|
<!-- AdminLTE App -->
|
||||||
<script src="static/dist/js/adminlte.min.js"></script>
|
<script src="{{.basePath}}/static/dist/js/adminlte.min.js"></script>
|
||||||
<!-- Custom js -->
|
<!-- Custom js -->
|
||||||
<script src="static/custom/js/helper.js"></script>
|
<script src="{{.basePath}}/static/custom/js/helper.js"></script>
|
||||||
<script>
|
<script>
|
||||||
// initialize all tooltips
|
// initialize all tooltips
|
||||||
$(function () {
|
$(function () {
|
||||||
|
@ -322,7 +322,7 @@
|
||||||
$.ajax({
|
$.ajax({
|
||||||
cache: false,
|
cache: false,
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: '/api/client/' + client_id,
|
url: '{{.basePath}}/api/client/' + client_id,
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
success: function (resp) {
|
success: function (resp) {
|
||||||
|
@ -368,7 +368,7 @@
|
||||||
$.ajax({
|
$.ajax({
|
||||||
cache: false,
|
cache: false,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: '/new-client',
|
url: '{{.basePath}}/new-client',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
data: JSON.stringify(data),
|
data: JSON.stringify(data),
|
||||||
|
@ -393,7 +393,7 @@
|
||||||
$.ajax({
|
$.ajax({
|
||||||
cache: false,
|
cache: false,
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: '/api/suggest-client-ips',
|
url: '{{.basePath}}/api/suggest-client-ips',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
|
@ -495,7 +495,7 @@
|
||||||
$.ajax({
|
$.ajax({
|
||||||
cache: false,
|
cache: false,
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: '/api/apply-wg-config',
|
url: '{{.basePath}}/api/apply-wg-config',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
|
|
|
@ -189,7 +189,7 @@ Wireguard Clients
|
||||||
$.ajax({
|
$.ajax({
|
||||||
cache: false,
|
cache: false,
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: '/api/clients',
|
url: '{{.basePath}}/api/clients',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
|
@ -207,7 +207,7 @@ Wireguard Clients
|
||||||
$.ajax({
|
$.ajax({
|
||||||
cache: false,
|
cache: false,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: '/client/set-status',
|
url: '{{.basePath}}/client/set-status',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
data: JSON.stringify(data),
|
data: JSON.stringify(data),
|
||||||
|
@ -276,7 +276,7 @@ Wireguard Clients
|
||||||
$.ajax({
|
$.ajax({
|
||||||
cache: false,
|
cache: false,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: '/remove-client',
|
url: '{{.basePath}}/remove-client',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
data: JSON.stringify(data),
|
data: JSON.stringify(data),
|
||||||
|
@ -339,7 +339,7 @@ Wireguard Clients
|
||||||
$.ajax({
|
$.ajax({
|
||||||
cache: false,
|
cache: false,
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: '/api/client/' + client_id,
|
url: '{{.basePath}}/api/client/' + client_id,
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
success: function (resp) {
|
success: function (resp) {
|
||||||
|
@ -384,7 +384,7 @@ Wireguard Clients
|
||||||
$.ajax({
|
$.ajax({
|
||||||
cache: false,
|
cache: false,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: '/email-client',
|
url: '{{.basePath}}/email-client',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
data: JSON.stringify(data),
|
data: JSON.stringify(data),
|
||||||
|
@ -431,7 +431,7 @@ Wireguard Clients
|
||||||
$.ajax({
|
$.ajax({
|
||||||
cache: false,
|
cache: false,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: '/update-client',
|
url: '{{.basePath}}/update-client',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
data: JSON.stringify(data),
|
data: JSON.stringify(data),
|
||||||
|
@ -465,7 +465,7 @@ Wireguard Clients
|
||||||
$.ajax({
|
$.ajax({
|
||||||
cache: false,
|
cache: false,
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: '/api/client/' + client_id,
|
url: '{{.basePath}}/api/client/' + client_id,
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
success: function (resp) {
|
success: function (resp) {
|
||||||
|
@ -491,7 +491,7 @@ Wireguard Clients
|
||||||
$.ajax({
|
$.ajax({
|
||||||
cache: false,
|
cache: false,
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: '/api/client/' + client_id,
|
url: '{{.basePath}}/api/client/' + client_id,
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
success: function (resp) {
|
success: function (resp) {
|
||||||
|
|
|
@ -156,7 +156,7 @@ Global Settings
|
||||||
$.ajax({
|
$.ajax({
|
||||||
cache: false,
|
cache: false,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: '/global-settings',
|
url: '{{.basePath}}/global-settings',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
data: JSON.stringify(data),
|
data: JSON.stringify(data),
|
||||||
|
|
|
@ -9,13 +9,13 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
<!-- Font Awesome -->
|
<!-- Font Awesome -->
|
||||||
<link rel="stylesheet" href="static/plugins/fontawesome-free/css/all.min.css">
|
<link rel="stylesheet" href="{{.basePath}}/static/plugins/fontawesome-free/css/all.min.css">
|
||||||
<!-- Ionicons -->
|
<!-- Ionicons -->
|
||||||
<link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
|
<link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
|
||||||
<!-- icheck bootstrap -->
|
<!-- icheck bootstrap -->
|
||||||
<link rel="stylesheet" href="static/plugins/icheck-bootstrap/icheck-bootstrap.min.css">
|
<link rel="stylesheet" href="{{.basePath}}/static/plugins/icheck-bootstrap/icheck-bootstrap.min.css">
|
||||||
<!-- Theme style -->
|
<!-- Theme style -->
|
||||||
<link rel="stylesheet" href="static/dist/css/adminlte.min.css">
|
<link rel="stylesheet" href="{{.basePath}}/static/dist/css/adminlte.min.css">
|
||||||
<!-- Google Font: Source Sans Pro -->
|
<!-- Google Font: Source Sans Pro -->
|
||||||
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700" rel="stylesheet">
|
||||||
</head>
|
</head>
|
||||||
|
@ -71,11 +71,11 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- /.login-box -->
|
<!-- /.login-box -->
|
||||||
<!-- jQuery -->
|
<!-- jQuery -->
|
||||||
<script src="static/plugins/jquery/jquery.min.js"></script>
|
<script src="{{.basePath}}/static/plugins/jquery/jquery.min.js"></script>
|
||||||
<!-- Bootstrap 4 -->
|
<!-- Bootstrap 4 -->
|
||||||
<script src="static/plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
|
<script src="{{.basePath}}/static/plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
|
||||||
<!-- AdminLTE App -->
|
<!-- AdminLTE App -->
|
||||||
<script src="static/dist/js/adminlte.min.js"></script>
|
<script src="{{.basePath}}/static/dist/js/adminlte.min.js"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
<script>
|
<script>
|
||||||
|
@ -85,7 +85,7 @@
|
||||||
if (nextURL) {
|
if (nextURL) {
|
||||||
window.location.href = nextURL;
|
window.location.href = nextURL;
|
||||||
} else {
|
} else {
|
||||||
window.location.href = '/';
|
window.location.href = '/wireguard/';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -100,12 +100,11 @@
|
||||||
const username = $("#username").val();
|
const username = $("#username").val();
|
||||||
const password = $("#password").val();
|
const password = $("#password").val();
|
||||||
const data = {"username": username, "password": password}
|
const data = {"username": username, "password": password}
|
||||||
console.log(data);
|
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
cache: false,
|
cache: false,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: '/login',
|
url: '{{.basePath}}/login',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
data: JSON.stringify(data),
|
data: JSON.stringify(data),
|
||||||
|
|
|
@ -136,7 +136,7 @@ Wireguard Server Settings
|
||||||
$.ajax({
|
$.ajax({
|
||||||
cache: false,
|
cache: false,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: '/wg-server/interfaces',
|
url: '{{.basePath}}/wg-server/interfaces',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
data: JSON.stringify(data),
|
data: JSON.stringify(data),
|
||||||
|
@ -210,7 +210,7 @@ Wireguard Server Settings
|
||||||
$.ajax({
|
$.ajax({
|
||||||
cache: false,
|
cache: false,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
url: '/wg-server/keypair',
|
url: '{{.basePath}}/wg-server/keypair',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
|
|
|
@ -119,5 +119,5 @@
|
||||||
|
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "bottom_js"}}
|
{{define "bottom_js"}}
|
||||||
<script src="/static/custom/js/wake_on_lan_hosts.js"></script>
|
<script src="{{.basePath}}/static/custom/js/wake_on_lan_hosts.js"></script>
|
||||||
{{end}}
|
{{end}}
|
|
@ -1,5 +1,7 @@
|
||||||
package util
|
package util
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
// Runtime config
|
// Runtime config
|
||||||
var (
|
var (
|
||||||
DisableLogin bool
|
DisableLogin bool
|
||||||
|
@ -17,6 +19,7 @@ var (
|
||||||
EmailContent string
|
EmailContent string
|
||||||
SessionSecret []byte
|
SessionSecret []byte
|
||||||
WgConfTemplate string
|
WgConfTemplate string
|
||||||
|
BasePath string
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -32,3 +35,13 @@ const (
|
||||||
UsernameEnvVar = "WGUI_USERNAME"
|
UsernameEnvVar = "WGUI_USERNAME"
|
||||||
PasswordEnvVar = "WGUI_PASSWORD"
|
PasswordEnvVar = "WGUI_PASSWORD"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func ParseBasePath(basePath string) string {
|
||||||
|
if !strings.HasPrefix(basePath, "/") {
|
||||||
|
basePath = "/" + basePath
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(basePath, "/") {
|
||||||
|
basePath = strings.TrimSuffix(basePath, "/")
|
||||||
|
}
|
||||||
|
return basePath
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue