108 lines
2.3 KiB
Go
108 lines
2.3 KiB
Go
package web
|
|
|
|
import (
|
|
"bytes"
|
|
"embed"
|
|
"errors"
|
|
"fmt"
|
|
"html/template"
|
|
"miniwol/config"
|
|
"miniwol/lib"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/labstack/echo/v4"
|
|
"golang.org/x/crypto/bcrypt"
|
|
)
|
|
|
|
//go:embed template/*
|
|
var templateFS embed.FS
|
|
var templates *template.Template
|
|
|
|
func init() {
|
|
var err error
|
|
|
|
templates, err = template.ParseFS(templateFS, "template/*.html.tmpl")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func Run() error {
|
|
e := echo.New()
|
|
|
|
e.GET("/", index)
|
|
e.POST("/auth", auth)
|
|
e.POST("/wake", withAuth(wake))
|
|
|
|
return e.Start(config.Config.Server)
|
|
}
|
|
|
|
func Page(c echo.Context, code int, title string, page string, data interface{}) error {
|
|
var contentBuffer bytes.Buffer
|
|
err := templates.ExecuteTemplate(&contentBuffer, page, data)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var pageBuffer bytes.Buffer
|
|
err = templates.ExecuteTemplate(&pageBuffer, "page.html.tmpl", struct {
|
|
Title string
|
|
Content template.HTML
|
|
}{
|
|
Title: title,
|
|
Content: template.HTML(contentBuffer.String()),
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return c.HTML(code, pageBuffer.String())
|
|
}
|
|
|
|
// Handlers
|
|
func index(c echo.Context) error {
|
|
session, err := c.Cookie("session")
|
|
if err != nil || checkAuth(session.Value) != nil {
|
|
return Page(c, 401, "Login", "login.html.tmpl", nil)
|
|
} else {
|
|
return Page(c, 200, "Device", "device.html.tmpl", config.Config)
|
|
}
|
|
}
|
|
|
|
func auth(c echo.Context) error {
|
|
password := c.FormValue("password")
|
|
if bcrypt.CompareHashAndPassword([]byte(config.Config.PassHash), []byte(password)) != nil {
|
|
return c.String(401, "Wrong Password")
|
|
}
|
|
token := uuid.New().String()
|
|
sessions[token] = time.Now().Add(time.Second * time.Duration(config.Config.SessionTTL*60))
|
|
c.SetCookie(&http.Cookie{
|
|
Name: "session",
|
|
Value: token,
|
|
Path: "/",
|
|
Secure: true,
|
|
HttpOnly: true,
|
|
SameSite: http.SameSiteStrictMode,
|
|
Expires: sessions[token],
|
|
})
|
|
return c.Redirect(http.StatusSeeOther, "/")
|
|
}
|
|
|
|
func wake(c echo.Context) error {
|
|
for i, device := range config.Config.Device {
|
|
if c.FormValue("alias") == device.Alias && c.FormValue("index") == fmt.Sprint(i) {
|
|
if !strings.Contains(device.IP, ":") {
|
|
device.IP += ":9"
|
|
}
|
|
err := lib.SendPacket(":0", device.IP, device.MAC)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return c.Redirect(http.StatusSeeOther, "/")
|
|
}
|
|
}
|
|
return errors.New("device not found")
|
|
}
|