diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..b976e44 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,17 @@ +# EditorConfig is awesome: https://editorconfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +indent_style = space +indent_size = 2 +insert_final_newline = true + +[*.go] +indent_style = tab + +[Makefile] +indent_style = tab diff --git a/auth/auth.go b/auth/auth.go index bb7d881..d4206c4 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -5,16 +5,18 @@ import ( "errors" "fmt" "github.com/1f349/lavender/database" + "html/template" "net/http" ) type Factor byte const ( - // FactorAuthorized defines the "authorized" state of a session - FactorAuthorized Factor = iota - FactorFirst - FactorSecond + // FactorUnauthorized defines the "unauthorized" state of a session + FactorUnauthorized Factor = iota + FactorBasic + FactorExtended + FactorSudo ) type Provider interface { @@ -25,18 +27,20 @@ type Provider interface { // Name defines a string value for the provider, useful for template switching Name() string - // RenderData stores values to send to the templating function - RenderData(ctx context.Context, req *http.Request, user *database.User, data map[string]any) error + // RenderTemplate returns HTML to embed in the page template + RenderTemplate(ctx context.Context, req *http.Request, user *database.User) (template.HTML, error) // AttemptLogin processes the login request AttemptLogin(ctx context.Context, req *http.Request, user *database.User) error } var ( - // ErrRequiresSecondFactor notifies the ServeHTTP function to ask for another factor - ErrRequiresSecondFactor = errors.New("requires second factor") - // ErrRequiresPreviousFactor is a generic error for providers which require a previous factor - ErrRequiresPreviousFactor = errors.New("requires previous factor") + // ErrRequiresBasicFactor notifies the ServeHTTP function to ask for another factor + ErrRequiresBasicFactor = errors.New("requires basic factor") + // ErrRequiresExtendedFactor is a generic error for providers which require a previous factor + ErrRequiresExtendedFactor = errors.New("requires extended factor") + + ErrRequiresSudoFactor = errors.New("requires sudo factor") // ErrUserDoesNotSupportFactor is a generic error for providers with are unable to support the user ErrUserDoesNotSupportFactor = errors.New("user does not support factor") ) diff --git a/auth/login.go b/auth/login.go index 65baa65..f58ae2e 100644 --- a/auth/login.go +++ b/auth/login.go @@ -19,7 +19,7 @@ type BasicLogin struct { DB basicLoginDB } -func (b *BasicLogin) Factor() Factor { return FactorFirst } +func (b *BasicLogin) Factor() Factor { return FactorBasic } func (b *BasicLogin) Name() string { return "basic" } diff --git a/auth/oauth.go b/auth/oauth.go index 8a6406e..8c4eddc 100644 --- a/auth/oauth.go +++ b/auth/oauth.go @@ -32,7 +32,7 @@ func (o OAuthLogin) Init() { o.flow = cache.New[string, flowStateData]() } -func (o OAuthLogin) Factor() Factor { return FactorFirst } +func (o OAuthLogin) Factor() Factor { return FactorBasic } func (o OAuthLogin) Name() string { return "oauth" } diff --git a/auth/otp.go b/auth/otp.go index 27b209a..5a1e5d5 100644 --- a/auth/otp.go +++ b/auth/otp.go @@ -23,7 +23,7 @@ type OtpLogin struct { DB otpLoginDB } -func (o *OtpLogin) Factor() Factor { return FactorSecond } +func (o *OtpLogin) Factor() Factor { return FactorExtended } func (o *OtpLogin) Name() string { return "basic" } diff --git a/auth/passkey.go b/auth/passkey.go index 9b61a8a..ec9ba11 100644 --- a/auth/passkey.go +++ b/auth/passkey.go @@ -16,7 +16,7 @@ type PasskeyLogin struct { DB passkeyLoginDB } -func (p *PasskeyLogin) Factor() Factor { return FactorFirst } +func (p *PasskeyLogin) Factor() Factor { return FactorBasic } func (p *PasskeyLogin) Name() string { return "passkey" } diff --git a/server/login.go b/server/login.go index e64db9c..3e8a25f 100644 --- a/server/login.go +++ b/server/login.go @@ -49,7 +49,7 @@ func (h *httpServer) testAuthSources(req *http.Request, user *database.User, fac if i.Factor()&factor == 0 { continue } - err := i.RenderData(req.Context(), req, user, data) + err := i.RenderTemplate(req.Context(), req, user, data) authSource[i.Name()] = err == nil clear(data) } @@ -76,14 +76,14 @@ func (h *httpServer) loginGet(rw http.ResponseWriter, req *http.Request, _ httpr return } - fmt.Printf("%#v\n", h.testAuthSources(req, userPtr, auth2.FactorFirst)) + fmt.Printf("%#v\n", h.testAuthSources(req, userPtr, auth2.FactorBasic)) web.RenderPageTemplate(rw, "login-memory", map[string]any{ "ServiceName": h.conf.ServiceName, "LoginName": cookie.Value, "Redirect": req.URL.Query().Get("redirect"), "Source": "start", - "Auth": h.testAuthSources(req, userPtr, auth2.FactorFirst), + "Auth": h.testAuthSources(req, userPtr, auth2.FactorBasic), }) return } @@ -94,7 +94,7 @@ func (h *httpServer) loginGet(rw http.ResponseWriter, req *http.Request, _ httpr "LoginName": "", "Redirect": req.URL.Query().Get("redirect"), "Source": "start", - "Auth": h.testAuthSources(req, nil, auth2.FactorFirst), + "Auth": h.testAuthSources(req, nil, auth2.FactorBasic), }) } diff --git a/web/.editorconfig b/web/.editorconfig new file mode 100644 index 0000000..d7a5ca0 --- /dev/null +++ b/web/.editorconfig @@ -0,0 +1,6 @@ +# EditorConfig is awesome: https://editorconfig.org + +# Matches multiple files with brace expansion notation +# Set default charset +[*.js] +charset = utf-8 diff --git a/web/src/components/Header.astro b/web/src/components/Header.astro new file mode 100644 index 0000000..c6ee9d8 --- /dev/null +++ b/web/src/components/Header.astro @@ -0,0 +1,3 @@ +
+

[[.ServiceName]]

+
diff --git a/web/src/layouts/Layout.astro b/web/src/layouts/Layout.astro index 1810971..c5d3a06 100644 --- a/web/src/layouts/Layout.astro +++ b/web/src/layouts/Layout.astro @@ -17,7 +17,9 @@ const { title } = Astro.props; {title} - +
+ +