Move to echo
This commit is contained in:
parent
9ba1abec07
commit
ac3328ab00
6 changed files with 84 additions and 189 deletions
18
go.mod
18
go.mod
|
@ -2,11 +2,23 @@ module dynatron.me/x/blasphem
|
|||
|
||||
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 (
|
||||
github.com/gorilla/websocket v1.5.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
|
||||
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
33
go.sum
|
@ -1,14 +1,47 @@
|
|||
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/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
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/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/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
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/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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
|
@ -2,7 +2,23 @@ package frontend
|
|||
|
||||
import (
|
||||
"embed"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
//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))
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -6,14 +6,18 @@ import (
|
|||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
|
||||
"dynatron.me/x/blasphem/pkg/auth"
|
||||
"dynatron.me/x/blasphem/pkg/bus"
|
||||
"dynatron.me/x/blasphem/pkg/config"
|
||||
"dynatron.me/x/blasphem/pkg/frontend"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
*echo.Echo
|
||||
*bus.Bus
|
||||
*http.Server
|
||||
auth.Authenticator
|
||||
rootFS fs.FS
|
||||
wg sync.WaitGroup
|
||||
cfg *config.Config
|
||||
|
@ -42,28 +46,18 @@ func logRequest(status int, r *http.Request) {
|
|||
}
|
||||
|
||||
func New(cfg *config.Config) (s *Server, err error) {
|
||||
|
||||
mux := http.NewServeMux()
|
||||
|
||||
s = &Server{
|
||||
Bus: bus.New(),
|
||||
Server: &http.Server{
|
||||
Addr: cfg.Server.Bind,
|
||||
Handler: mux,
|
||||
},
|
||||
Echo: echo.New(),
|
||||
cfg: cfg,
|
||||
}
|
||||
s.Echo.Debug = true
|
||||
s.Echo.HideBanner = true
|
||||
|
||||
s.rootFS, err = fs.Sub(frontend.Root, "frontend/hass_frontend")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
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)
|
||||
s.GET("/", echo.WrapHandler(frontend.FSHandler))
|
||||
s.GET("/api/websocket", s.wsHandler)
|
||||
s.GET("/auth/authorize", s.AuthorizeHandler)
|
||||
s.GET("/auth/providers", s.ProvidersHandler)
|
||||
s.POST("/auth/login_flow", s.LoginFlowHandler)
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
@ -71,7 +65,7 @@ func New(cfg *config.Config) (s *Server, err error) {
|
|||
func (s *Server) Go() error {
|
||||
s.wg.Add(1)
|
||||
go func() {
|
||||
err := s.ListenAndServe()
|
||||
err := s.Start(s.cfg.Server.Bind)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
var upgrader = websocket.Upgrader{
|
||||
|
@ -12,8 +13,8 @@ var upgrader = websocket.Upgrader{
|
|||
WriteBufferSize: 1024,
|
||||
}
|
||||
|
||||
func (s *Server) wsHandler(w http.ResponseWriter, req *http.Request) {
|
||||
func (s *Server) wsHandler(c echo.Context) error {
|
||||
log.Println("WebSocket")
|
||||
//conn, err := upgrader.Upgrade(w, req, nil)
|
||||
panic("not implemented")
|
||||
return errors.New("not handled")
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue