Move to echo

This commit is contained in:
Daniel Ponte 2022-09-30 14:37:40 -04:00
parent 9ba1abec07
commit ac3328ab00
6 changed files with 84 additions and 189 deletions

18
go.mod
View file

@ -2,11 +2,23 @@ module dynatron.me/x/blasphem
go 1.18 go 1.18
require github.com/spf13/cobra v1.5.0 require (
github.com/gorilla/websocket v1.5.0
github.com/labstack/echo/v4 v4.9.0
github.com/spf13/cobra v1.5.0
gopkg.in/yaml.v3 v3.0.1
)
require ( require (
github.com/gorilla/websocket v1.5.0 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/labstack/gommon v0.3.1 // indirect
github.com/mattn/go-colorable v0.1.11 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.5 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.1 // indirect
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f // indirect
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b // indirect
golang.org/x/text v0.3.7 // indirect
) )

33
go.sum
View file

@ -1,14 +1,47 @@
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/labstack/echo/v4 v4.9.0 h1:wPOF1CE6gvt/kmbMR4dGzWvHMPT+sAEUJOwOTtvITVY=
github.com/labstack/echo/v4 v4.9.0/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=
github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o=
github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b h1:1VkfZQv42XQlA/jchYumAnv1UPo6RgF9rJFkTgZIxO4=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
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/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View file

@ -2,7 +2,23 @@ package frontend
import ( import (
"embed" "embed"
"io/fs"
"net/http"
) )
//go:embed frontend/hass_frontend //go:embed frontend/hass_frontend
var Root embed.FS var root embed.FS
var RootFS fs.FS
var FSHandler http.Handler
func init() {
var err error
RootFS, err = fs.Sub(root, "frontend/hass_frontend")
if err != nil {
panic(err)
}
FSHandler = http.FileServer(http.FS(RootFS))
}

View file

@ -1,161 +0,0 @@
package server
import (
"crypto/rand"
"encoding/hex"
"encoding/json"
"io"
"net/http"
)
type AuthProvider interface {
ProviderName() string
ProviderID() *string
ProviderType() string
}
type AuthProviderBase struct {
Name string `json:"name"`
ID *string `json:"id"`
Type string `json:"type"`
}
func (bp *AuthProviderBase) ProviderName() string { return bp.Name }
func (bp *AuthProviderBase) ProviderID() *string { return bp.ID }
func (bp *AuthProviderBase) ProviderType() string { return bp.Type }
type LocalProvider struct {
AuthProviderBase
}
var HomeAssistant = "homeassistant"
func hassProvider() *LocalProvider {
return &LocalProvider{
AuthProviderBase: AuthProviderBase{
Name: "Home Assistant Local",
Type: HomeAssistant,
},
}
}
// TODO: make this configurable
func (s *Server) providersHandler(w http.ResponseWriter, r *http.Request) {
providers := []AuthProvider{
hassProvider(),
}
rjs, err := json.Marshal(providers)
if err != nil {
panic(err)
}
logRequest(http.StatusOK, r)
w.Header()["Content-Type"] = []string{"application/json"}
_, err = w.Write(rjs)
if err != nil {
panic(err)
}
}
func (s *Server) authorizeHandler(w http.ResponseWriter, r *http.Request) {
authPage, err := s.rootFS.Open("authorize.html")
if err != nil {
panic(err)
}
defer authPage.Close()
logRequest(http.StatusOK, r)
_, err = io.Copy(w, authPage)
if err != nil {
panic(err)
}
}
type flowRequest struct {
ClientID string `json:"client_id"`
Handler []*string `json:"handler"`
RedirectURI string `json:"redirect_uri"`
}
type FlowSchemaItem struct {
Type string `json:"type"`
Name string `json:"name"`
Required bool `json:"required"`
}
type FlowType string
const (
TypeForm FlowType = "form"
)
type FlowID string
type Step string
const (
StepInit Step = "init"
)
type flowResponse struct {
Type FlowType `json:"type"`
ID FlowID `json:"flow_id"`
Handler []*string `json:"handler"`
StepID Step `json:"step_id"`
Schema []FlowSchemaItem `json:"data_schema"`
Errors []string `json:"errors"`
DescPlace *string `json:"description_placeholders"`
LastStep *string `json:"last_step"`
}
func GenFlowID() FlowID {
b := make([]byte, 16)
if _, err := rand.Read(b); err != nil {
panic(err)
}
return FlowID(hex.EncodeToString(b))
}
func (s *Server) loginFlowHandler(w http.ResponseWriter, r *http.Request) {
var flowReq flowRequest
err := json.NewDecoder(r.Body).Decode(&flowReq)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
resp := flowResponse{
Type: TypeForm,
ID: GenFlowID(),
StepID: StepInit,
Schema: []FlowSchemaItem{
{
Type: "string",
Name: "username",
Required: true,
},
{
Type: "string",
Name: "password",
Required: true,
},
},
Handler: []*string{
&HomeAssistant,
nil,
},
Errors: []string{},
}
w.Header()["Content-Type"] = []string{"application/json"}
respByte, err := json.Marshal(&resp)
_, err = w.Write(respByte)
if err != nil {
panic(err)
}
}

View file

@ -6,14 +6,18 @@ import (
"net/http" "net/http"
"sync" "sync"
"github.com/labstack/echo/v4"
"dynatron.me/x/blasphem/pkg/auth"
"dynatron.me/x/blasphem/pkg/bus" "dynatron.me/x/blasphem/pkg/bus"
"dynatron.me/x/blasphem/pkg/config" "dynatron.me/x/blasphem/pkg/config"
"dynatron.me/x/blasphem/pkg/frontend" "dynatron.me/x/blasphem/pkg/frontend"
) )
type Server struct { type Server struct {
*echo.Echo
*bus.Bus *bus.Bus
*http.Server auth.Authenticator
rootFS fs.FS rootFS fs.FS
wg sync.WaitGroup wg sync.WaitGroup
cfg *config.Config cfg *config.Config
@ -42,28 +46,18 @@ func logRequest(status int, r *http.Request) {
} }
func New(cfg *config.Config) (s *Server, err error) { func New(cfg *config.Config) (s *Server, err error) {
mux := http.NewServeMux()
s = &Server{ s = &Server{
Bus: bus.New(), Echo: echo.New(),
Server: &http.Server{ cfg: cfg,
Addr: cfg.Server.Bind,
Handler: mux,
},
cfg: cfg,
} }
s.Echo.Debug = true
s.Echo.HideBanner = true
s.rootFS, err = fs.Sub(frontend.Root, "frontend/hass_frontend") s.GET("/", echo.WrapHandler(frontend.FSHandler))
if err != nil { s.GET("/api/websocket", s.wsHandler)
return nil, err s.GET("/auth/authorize", s.AuthorizeHandler)
} s.GET("/auth/providers", s.ProvidersHandler)
s.POST("/auth/login_flow", s.LoginFlowHandler)
mux.HandleFunc("/api/websocket", s.wsHandler)
mux.Handle("/", logHandler(http.FileServer(http.FS(s.rootFS))))
mux.HandleFunc("/auth/authorize", s.authorizeHandler)
mux.HandleFunc("/auth/providers", s.providersHandler)
mux.HandleFunc("/auth/login_flow", s.loginFlowHandler)
return s, nil return s, nil
} }
@ -71,7 +65,7 @@ func New(cfg *config.Config) (s *Server, err error) {
func (s *Server) Go() error { func (s *Server) Go() error {
s.wg.Add(1) s.wg.Add(1)
go func() { go func() {
err := s.ListenAndServe() err := s.Start(s.cfg.Server.Bind)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }

View file

@ -1,10 +1,11 @@
package server package server
import ( import (
"errors"
"log" "log"
"net/http"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/labstack/echo/v4"
) )
var upgrader = websocket.Upgrader{ var upgrader = websocket.Upgrader{
@ -12,8 +13,8 @@ var upgrader = websocket.Upgrader{
WriteBufferSize: 1024, WriteBufferSize: 1024,
} }
func (s *Server) wsHandler(w http.ResponseWriter, req *http.Request) { func (s *Server) wsHandler(c echo.Context) error {
log.Println("WebSocket") log.Println("WebSocket")
//conn, err := upgrader.Upgrade(w, req, nil) //conn, err := upgrader.Upgrade(w, req, nil)
panic("not implemented") return errors.New("not handled")
} }