miniwol/web/web.go
2022-02-18 15:34:33 +01:00

109 lines
2.4 KiB
Go

package web
import (
"bytes"
"embed"
"errors"
"fmt"
"html/template"
"net/http"
"strings"
"time"
"git.ulra.eu/adro/miniwol/config"
"git.ulra.eu/adro/miniwol/lib"
"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, 200, "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")
}