diff options
author | René 'Necoro' Neumann <necoro@necoro.eu> | 2024-10-17 00:27:08 +0200 |
---|---|---|
committer | René 'Necoro' Neumann <necoro@necoro.eu> | 2024-10-17 00:27:08 +0200 |
commit | 869fb9691f877116d5b15a92de006d0daf4d70e5 (patch) | |
tree | 2493c72172d5817ec9deec36229a84b687eb3190 /pages | |
parent | 6fc180ba6d9bc5c32340466988d9e26f8d6e3c5c (diff) | |
download | gosten-869fb9691f877116d5b15a92de006d0daf4d70e5.tar.gz gosten-869fb9691f877116d5b15a92de006d0daf4d70e5.tar.bz2 gosten-869fb9691f877116d5b15a92de006d0daf4d70e5.zip |
Restructure and change to chi as muxing framework
Diffstat (limited to '')
-rw-r--r-- | pages/login.go (renamed from auth.go) | 81 | ||||
-rw-r--r-- | pages/logout.go | 15 | ||||
-rw-r--r-- | pages/page.go | 58 | ||||
-rw-r--r-- | pages/pages.go | 26 |
4 files changed, 136 insertions, 44 deletions
@@ -1,9 +1,12 @@ -package main +package pages import ( "context" "database/sql" "errors" + "gosten/csrf" + "gosten/form" + "gosten/session" "log" "net/http" "net/url" @@ -20,9 +23,9 @@ const ( func RequireAuth(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - s := session(r) + s := session.From(r) - if !s.s.IsNew && s.Authenticated { + if !s.IsNew() && s.Authenticated { u, err := Q.GetUserById(r.Context(), s.UserID) if err == nil { // authenticated --> done @@ -43,6 +46,33 @@ func RequireAuth(next http.Handler) http.Handler { }) } +type User struct { + Name string `form:"options=required,autofocus"` + Password string `form:"type=password;options=required"` + RememberMe bool `form:"type=checkbox;value=y;options=checked"` + Errors []error `form:"-"` + csrf.Csrf +} + +func showLoginPage(w http.ResponseWriter, u User) { + showTemplate(w, "login", u) +} + +func Login() http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + if session.From(r).Authenticated { + http.Redirect(w, r, "/", http.StatusFound) + } + u := User{} + u.SetCsrfField(r) + showLoginPage(w, u) + } +} + +func userId(r *http.Request) int32 { + return r.Context().Value(userContextKey{}).(int32) +} + func checkLogin(ctx context.Context, user User) (bool, int32) { dbUser, err := Q.GetUserByName(ctx, user.Name) if err == nil { @@ -61,19 +91,19 @@ func checkLogin(ctx context.Context, user User) (bool, int32) { return true, dbUser.ID } -func handleLogin(w http.ResponseWriter, r *http.Request) { +func HandleLogin(w http.ResponseWriter, r *http.Request) { u := User{} - parseForm(r, &u) + form.Parse(r, &u) ok, userId := checkLogin(r.Context(), u) if !ok { - u.Errors = []error{fieldError{"Password", "Invalid"}} + u.Errors = []error{form.FieldError{Field: "Password", Issue: "Invalid"}} showLoginPage(w, u) return } - s := session(r) + s := session.From(r) if u.RememberMe { s.MaxAge(sessionDuration) // 1 week } else { @@ -91,40 +121,3 @@ func handleLogin(w http.ResponseWriter, r *http.Request) { } http.Redirect(w, r, next, http.StatusFound) } - -func handleLogout() http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - s := session(r) - s.Invalidate() - s.Save(w, r) - - http.Redirect(w, r, "/", http.StatusFound) - } -} - -type User struct { - Name string `form:"options=required,autofocus"` - Password string `form:"type=password;options=required"` - RememberMe bool `form:"type=checkbox;value=y;options=checked"` - Errors []error `form:"-"` - Csrf -} - -func showLoginPage(w http.ResponseWriter, u User) { - showTemplate(w, "login", u) -} - -func loginPage() http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - if session(r).Authenticated { - http.Redirect(w, r, "/", http.StatusFound) - } - u := User{} - u.SetCsrfField(r) - showLoginPage(w, u) - } -} - -func userId(r *http.Request) int32 { - return r.Context().Value(userContextKey{}).(int32) -} diff --git a/pages/logout.go b/pages/logout.go new file mode 100644 index 0000000..dad0e1a --- /dev/null +++ b/pages/logout.go @@ -0,0 +1,15 @@ +package pages + +import ( + "gosten/session" + "net/http" +) + +func Logout() http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + s := session.From(r) + s.Invalidate() + s.Save(w, r) + http.Redirect(w, r, "/", http.StatusFound) + } +} diff --git a/pages/page.go b/pages/page.go new file mode 100644 index 0000000..25c2331 --- /dev/null +++ b/pages/page.go @@ -0,0 +1,58 @@ +package pages + +import ( + "context" + "gosten/model" + "gosten/templ" + "log" + "net/http" + + "github.com/go-chi/chi/v5" +) + +var Q *model.Queries + +func Connect(tx model.DBTX) { + Q = model.New(tx) +} + +type Page interface { + http.Handler +} + +type dataFunc func(r *http.Request, uid int32) any + +type simplePage struct { + dataFn dataFunc + template string +} + +func (p simplePage) ServeHTTP(w http.ResponseWriter, r *http.Request) { + input := p.dataFn(r, userId(r)) + p.showTemplate(w, input) +} + +func simpleByQuery[T any](tpl string, query func(ctx context.Context, id int32) (T, error)) Page { + dataFn := func(r *http.Request, uid int32) any { + d, _ := query(r.Context(), uid) + return d + } + return simple(tpl, dataFn) +} + +func simple(tpl string, dataFn dataFunc) Page { + p := simplePage{dataFn, tpl} + r := chi.NewRouter() + r.Get("/", p.ServeHTTP) + return r +} + +func showTemplate(w http.ResponseWriter, tpl string, data any) { + if err := templ.Lookup(tpl).Execute(w, data); err != nil { + log.Panicf("Executing '%s' with %+v: %v", tpl, data, err) + } +} + +func (p simplePage) showTemplate(w http.ResponseWriter, data any) { + showTemplate(w, p.template, data) +} diff --git a/pages/pages.go b/pages/pages.go new file mode 100644 index 0000000..e965bdd --- /dev/null +++ b/pages/pages.go @@ -0,0 +1,26 @@ +package pages + +import ( + "net/http" +) + +func Init() Page { + return simple("index", func(r *http.Request, uid int32) any { + u, _ := Q.GetUserById(r.Context(), uid) + return u.Name + }) +} + +func Recur() Page { + return simpleByQuery("recur", Q.GetRecurExpenses) +} + +func Categories() Page { + return simpleByQuery("categories", Q.GetCategoriesOrdered) +} + +func NotFound() http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + showTemplate(w, "404", r.RequestURI) + } +} |