my_access.html was never added to router.go's template map, so echo's Render fell through and produced Internal Server Error for every user.
179 lines
5.7 KiB
Go
179 lines
5.7 KiB
Go
package router
|
|
|
|
import (
|
|
"errors"
|
|
"html"
|
|
"io"
|
|
"io/fs"
|
|
"reflect"
|
|
"strings"
|
|
"text/template"
|
|
|
|
"github.com/gorilla/sessions"
|
|
"github.com/labstack/echo-contrib/session"
|
|
"github.com/labstack/echo/v4"
|
|
"github.com/labstack/echo/v4/middleware"
|
|
"github.com/labstack/gommon/log"
|
|
"github.com/ngoduykhanh/wireguard-ui/util"
|
|
)
|
|
|
|
// TemplateRegistry is a custom html/template renderer for Echo framework
|
|
type TemplateRegistry struct {
|
|
templates map[string]*template.Template
|
|
extraData map[string]interface{}
|
|
}
|
|
|
|
// Render e.Renderer interface
|
|
func (t *TemplateRegistry) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
|
|
tmpl, ok := t.templates[name]
|
|
if !ok {
|
|
err := errors.New("Template not found -> " + name)
|
|
return err
|
|
}
|
|
|
|
// inject more app data information. E.g. appVersion
|
|
if reflect.TypeOf(data).Kind() == reflect.Map {
|
|
for k, v := range t.extraData {
|
|
data.(map[string]interface{})[k] = v
|
|
}
|
|
|
|
data.(map[string]interface{})["client_defaults"] = util.ClientDefaultsFromEnv()
|
|
}
|
|
|
|
// login page does not need the base layout
|
|
if name == "login.html" {
|
|
return tmpl.Execute(w, data)
|
|
}
|
|
|
|
return tmpl.ExecuteTemplate(w, "base.html", data)
|
|
}
|
|
|
|
// New function
|
|
func New(tmplDir fs.FS, extraData map[string]interface{}, secret [64]byte) *echo.Echo {
|
|
e := echo.New()
|
|
|
|
cookiePath := util.GetCookiePath()
|
|
|
|
cookieStore := sessions.NewCookieStore(secret[:32], secret[32:])
|
|
cookieStore.Options.Path = cookiePath
|
|
cookieStore.Options.HttpOnly = true
|
|
cookieStore.MaxAge(86400 * 7)
|
|
|
|
e.Use(session.Middleware(cookieStore))
|
|
|
|
// read html template file to string
|
|
tmplBaseString, err := util.StringFromEmbedFile(tmplDir, "base.html")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
tmplLoginString, err := util.StringFromEmbedFile(tmplDir, "login.html")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
tmplProfileString, err := util.StringFromEmbedFile(tmplDir, "profile.html")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
tmplClientsString, err := util.StringFromEmbedFile(tmplDir, "clients.html")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
tmplGlobalSettingsString, err := util.StringFromEmbedFile(tmplDir, "global_settings.html")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
tmplUsersSettingsString, err := util.StringFromEmbedFile(tmplDir, "users_settings.html")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
tmplStatusString, err := util.StringFromEmbedFile(tmplDir, "status.html")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
tmplWakeOnLanHostsString, err := util.StringFromEmbedFile(tmplDir, "wake_on_lan_hosts.html")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
aboutPageString, err := util.StringFromEmbedFile(tmplDir, "about.html")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
tmplServersString, err := util.StringFromEmbedFile(tmplDir, "servers.html")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
tmplServerClientsString, err := util.StringFromEmbedFile(tmplDir, "server_clients.html")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
tmplFirewallListsString, err := util.StringFromEmbedFile(tmplDir, "firewall_lists.html")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
tmplMyAccessString, err := util.StringFromEmbedFile(tmplDir, "my_access.html")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// create template list
|
|
funcs := template.FuncMap{
|
|
"StringsJoin": strings.Join,
|
|
"attrescaper": html.EscapeString,
|
|
}
|
|
templates := make(map[string]*template.Template)
|
|
templates["login.html"] = template.Must(template.New("login").Funcs(funcs).Parse(tmplLoginString))
|
|
templates["profile.html"] = template.Must(template.New("profile").Funcs(funcs).Parse(tmplBaseString + tmplProfileString))
|
|
templates["clients.html"] = template.Must(template.New("clients").Funcs(funcs).Parse(tmplBaseString + tmplClientsString))
|
|
templates["global_settings.html"] = template.Must(template.New("global_settings").Funcs(funcs).Parse(tmplBaseString + tmplGlobalSettingsString))
|
|
templates["users_settings.html"] = template.Must(template.New("users_settings").Funcs(funcs).Parse(tmplBaseString + tmplUsersSettingsString))
|
|
templates["status.html"] = template.Must(template.New("status").Funcs(funcs).Parse(tmplBaseString + tmplStatusString))
|
|
templates["wake_on_lan_hosts.html"] = template.Must(template.New("wake_on_lan_hosts").Funcs(funcs).Parse(tmplBaseString + tmplWakeOnLanHostsString))
|
|
templates["about.html"] = template.Must(template.New("about").Funcs(funcs).Parse(tmplBaseString + aboutPageString))
|
|
templates["servers.html"] = template.Must(template.New("servers").Funcs(funcs).Parse(tmplBaseString + tmplServersString))
|
|
templates["server_clients.html"] = template.Must(template.New("server_clients").Funcs(funcs).Parse(tmplBaseString + tmplServerClientsString))
|
|
templates["firewall_lists.html"] = template.Must(template.New("firewall_lists").Funcs(funcs).Parse(tmplBaseString + tmplFirewallListsString))
|
|
templates["my_access.html"] = template.Must(template.New("my_access").Funcs(funcs).Parse(tmplBaseString + tmplMyAccessString))
|
|
|
|
lvl, err := util.ParseLogLevel(util.LookupEnvOrString(util.LogLevel, "INFO"))
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
logConfig := middleware.DefaultLoggerConfig
|
|
logConfig.Skipper = func(c echo.Context) bool {
|
|
resp := c.Response()
|
|
if resp.Status >= 500 && lvl > log.ERROR { // do not log if response is 5XX but log level is higher than ERROR
|
|
return true
|
|
} else if resp.Status >= 400 && lvl > log.WARN { // do not log if response is 4XX but log level is higher than WARN
|
|
return true
|
|
} else if lvl > log.DEBUG { // do not log if log level is higher than DEBUG
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
e.Logger.SetLevel(lvl)
|
|
e.Pre(middleware.RemoveTrailingSlash())
|
|
e.Use(middleware.LoggerWithConfig(logConfig))
|
|
e.HideBanner = true
|
|
e.HidePort = lvl > log.INFO // hide the port output if the log level is higher than INFO
|
|
e.Validator = NewValidator()
|
|
e.Renderer = &TemplateRegistry{
|
|
templates: templates,
|
|
extraData: extraData,
|
|
}
|
|
|
|
return e
|
|
}
|