Login flow success

This commit is contained in:
Daniel Ponte 2022-10-26 18:27:24 -04:00
parent 963f4020b7
commit fb9ecb0509
5 changed files with 50 additions and 8 deletions

1
go.mod
View file

@ -12,6 +12,7 @@ require (
require ( require (
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jinzhu/copier v0.3.5 // indirect
github.com/labstack/gommon v0.3.1 // indirect github.com/labstack/gommon v0.3.1 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-isatty v0.0.14 // indirect

2
go.sum
View file

@ -11,6 +11,8 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm
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/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg=
github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
github.com/labstack/echo/v4 v4.6.1/go.mod h1:RnjgMWNDB9g/HucVWhQYNQP9PvbYf6adqftqryo7s9k= github.com/labstack/echo/v4 v4.6.1/go.mod h1:RnjgMWNDB9g/HucVWhQYNQP9PvbYf6adqftqryo7s9k=
github.com/labstack/echo/v4 v4.9.0 h1:wPOF1CE6gvt/kmbMR4dGzWvHMPT+sAEUJOwOTtvITVY= 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/echo/v4 v4.9.0/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=

View file

@ -6,6 +6,7 @@ import (
"net/http" "net/http"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"github.com/rs/zerolog/log"
"dynatron.me/x/blasphem/pkg/frontend" "dynatron.me/x/blasphem/pkg/frontend"
"dynatron.me/x/blasphem/pkg/storage" "dynatron.me/x/blasphem/pkg/storage"
@ -110,6 +111,7 @@ func (a *Authenticator) Check(f *Flow, rm map[string]interface{}) error {
success := p.ValidateCreds(rm) success := p.ValidateCreds(rm)
if success { if success {
log.Info().Str("user", rm["username"].(string)).Msg("Login success")
return nil return nil
} }
} }

View file

@ -7,7 +7,10 @@ import (
"strings" "strings"
"time" "time"
"github.com/jinzhu/copier"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"dynatron.me/x/blasphem/internal/common"
) )
type FlowStore map[FlowID]*Flow type FlowStore map[FlowID]*Flow
@ -28,6 +31,7 @@ type FlowType string
const ( const (
TypeForm FlowType = "form" TypeForm FlowType = "form"
TypeCreateEntry FlowType = "create_entry"
) )
type FlowID string type FlowID string
@ -41,18 +45,18 @@ type Flow struct {
Type FlowType `json:"type"` Type FlowType `json:"type"`
ID FlowID `json:"flow_id"` ID FlowID `json:"flow_id"`
Handler []*string `json:"handler"` Handler []*string `json:"handler"`
StepID Step `json:"step_id"` StepID *Step `json:"step_id,omitempty"`
Schema []FlowSchemaItem `json:"data_schema"` Schema []FlowSchemaItem `json:"data_schema"`
Errors interface{} `json:"errors"` Errors interface{} `json:"errors"`
DescPlace *string `json:"description_placeholders"` DescPlace *string `json:"description_placeholders"`
LastStep *string `json:"last_step"` LastStep *string `json:"last_step"`
request *FlowRequest request *FlowRequest
age time.Time ctime time.Time
} }
func (f *Flow) touch() { func (f *Flow) touch() {
f.age = time.Now() f.ctime = time.Now()
} }
func genFlowID() FlowID { func genFlowID() FlowID {
@ -77,7 +81,7 @@ const cullAge = time.Minute * 30
func (fs FlowStore) cull() { func (fs FlowStore) cull() {
for k, v := range fs { for k, v := range fs {
if time.Now().Sub(v.age) > cullAge { if time.Now().Sub(v.ctime) > cullAge {
delete(fs, k) delete(fs, k)
} }
} }
@ -113,7 +117,7 @@ func (a *Authenticator) NewFlow(r *FlowRequest) *Flow {
flow := &Flow{ flow := &Flow{
Type: TypeForm, Type: TypeForm,
ID: genFlowID(), ID: genFlowID(),
StepID: StepInit, StepID: stepPtr(StepInit),
Schema: sch, Schema: sch,
Handler: r.Handler, Handler: r.Handler,
Errors: []string{}, Errors: []string{},
@ -126,8 +130,19 @@ func (a *Authenticator) NewFlow(r *FlowRequest) *Flow {
return flow return flow
} }
func stepPtr(s Step) *Step { return &s }
func (f *Flow) redirect(c echo.Context) {
c.Request().Header.Set("Location", f.request.RedirectURI)
}
func (f *Flow) progress(a *Authenticator, c echo.Context) error { func (f *Flow) progress(a *Authenticator, c echo.Context) error {
switch f.StepID { if f.StepID == nil {
c.Logger().Error("stepID is nil")
return c.String(http.StatusInternalServerError, "No Step ID")
}
switch *f.StepID {
case StepInit: case StepInit:
rm := make(map[string]interface{}) rm := make(map[string]interface{})
@ -146,9 +161,24 @@ func (f *Flow) progress(a *Authenticator, c echo.Context) error {
err = a.Check(f, rm) err = a.Check(f, rm)
switch err { switch err {
case nil: case nil:
var finishedFlow struct {
ID FlowID `json:"flow_id"`
Handler []*string `json:"handler"`
Result string `json:"result"`
Title string `json:"title"`
Type FlowType `json:"type"`
Version int `json:"version"`
}
// TODO: setup the session. delete the flow. // TODO: setup the session. delete the flow.
a.Flows.Remove(f) a.Flows.Remove(f)
return c.String(http.StatusOK, "login success!") copier.Copy(&finishedFlow, f)
finishedFlow.Type = TypeCreateEntry
finishedFlow.Title = common.AppName
finishedFlow.Version = 1
f.redirect(c)
return c.JSON(http.StatusCreated, &finishedFlow)
case ErrInvalidHandler: case ErrInvalidHandler:
return c.String(http.StatusNotFound, err.Error()) return c.String(http.StatusNotFound, err.Error())
case ErrInvalidAuth: case ErrInvalidAuth:
@ -211,6 +241,12 @@ func (a *Authenticator) LoginFlowHandler(c echo.Context) error {
return c.String(http.StatusNotFound, "no such flow") return c.String(http.StatusNotFound, "no such flow")
} }
if time.Now().Sub(flow.ctime) > cullAge {
a.Flows.Remove(flow)
return c.String(http.StatusGone, "flow timed out")
}
return flow.progress(a, c) return flow.progress(a, c)
} }

View file

@ -16,6 +16,7 @@ type User struct {
Password string `json:"password"` Password string `json:"password"`
Username string `json:"username"` Username string `json:"username"`
} }
type HomeAssistantProvider struct { type HomeAssistantProvider struct {
AuthProviderBase `json:"-"` AuthProviderBase `json:"-"`
Users []User `json:"users"` Users []User `json:"users"`