From 0cc6abe03b1534c8424f8aeb30237947f6f8e2d9 Mon Sep 17 00:00:00 2001 From: Teajey <21069848+Teajey@users.noreply.github.com> Date: Sat, 26 Oct 2024 12:30:11 +0900 Subject: [PATCH] feat: improvements - better error presentation - public wishlist view --- auth/auth.go | 3 + auth/login_get.go | 60 +++++++++++++++----- auth/login_post.go | 15 +++-- auth/redirect_with_error.go | 17 ++++++ auth/register.go | 70 ++++++++++++++++++++++-- context/context.go | 23 +++----- context/foreign_wishlist.go | 42 ++++++++++---- context/home.go | 5 +- db/user.go | 10 ++++ error/page.go | 17 ++++++ hashpword/main.go | 23 ++++++++ main.go | 4 +- session/session.go | 25 +++++++++ templates/base.gotmpl | 14 +++++ templates/error_page.gotmpl | 17 ++++++ templates/foreign_wishlist.gotmpl | 4 +- templates/home.gotmpl | 2 +- templates/login.gotmpl | 13 +++-- templates/public_foreign_wishlist.gotmpl | 37 +++++++++++++ templates/register.go | 9 --- templates/register.gotmpl | 20 +++++-- templates/templates.go | 21 +++++-- 22 files changed, 377 insertions(+), 74 deletions(-) create mode 100644 auth/redirect_with_error.go create mode 100644 error/page.go create mode 100644 hashpword/main.go create mode 100644 session/session.go create mode 100644 templates/error_page.gotmpl create mode 100644 templates/public_foreign_wishlist.gotmpl delete mode 100644 templates/register.go diff --git a/auth/auth.go b/auth/auth.go index ffea72c..7df46f6 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -1,6 +1,7 @@ package auth import ( + "encoding/gob" "log" "net/http" @@ -41,6 +42,8 @@ func (auth *AuthMiddleware) ExpectUser(r *http.Request) *db.User { } func NewAuthMiddleware(protectedHandler http.Handler, publicHandler http.Handler) *AuthMiddleware { + gob.Register(&RegisterProps{}) + gob.Register(&LoginProps{}) store := sessions.NewCookieStore([]byte(env.JwtSecret)) store.Options.MaxAge = 86_400 return &AuthMiddleware{store, protectedHandler, publicHandler} diff --git a/auth/login_get.go b/auth/login_get.go index 0add6f5..1627bac 100644 --- a/auth/login_get.go +++ b/auth/login_get.go @@ -1,28 +1,62 @@ package auth import ( + sesh "lishwist/session" "lishwist/templates" - "log" "net/http" ) -type LoginGetProps struct { +type LoginProps struct { + GeneralError string SuccessfulRegistration bool + Username templates.InputProps + Password templates.InputProps +} + +func NewLoginProps() LoginProps { + return LoginProps{ + Username: templates.InputProps{ + Name: "username", + Required: true, + }, + Password: templates.InputProps{ + Name: "password", + Type: "password", + Required: true, + }, + } } func (auth *AuthMiddleware) Login(w http.ResponseWriter, r *http.Request) { session, _ := auth.Store.Get(r, "lishwist_user") - successfulReg, ok := session.Values["successful_registration"].(bool) - if ok { - delete(session.Values, "successful_registration") - if err := session.Save(r, w); err != nil { - log.Println("Couldn't save session:", err) - http.Error(w, "Something went wrong. Error code: Zuko", http.StatusInternalServerError) - return - } + + props := NewLoginProps() + + flash, err := sesh.GetFirstFlash(w, r, session, "login_props") + if err != nil { + http.Error(w, "Something went wrong. Error code: Zuko", http.StatusInternalServerError) + return } - templates.Execute(w, "login.gotmpl", LoginGetProps{ - SuccessfulRegistration: successfulReg, - }) + flashProps, ok := flash.(*LoginProps) + if ok { + props.Username.Value = flashProps.Username.Value + + props.GeneralError = flashProps.GeneralError + props.Username.Error = flashProps.Username.Error + props.Password.Error = flashProps.Password.Error + } + + flash, err = sesh.GetFirstFlash(w, r, session, "successful_registration") + if err != nil { + http.Error(w, "Something went wrong. Error code: Zuko", http.StatusInternalServerError) + return + } + + successfulReg, _ := flash.(bool) + if successfulReg { + props.SuccessfulRegistration = true + } + + templates.Execute(w, "login.gotmpl", props) } diff --git a/auth/login_post.go b/auth/login_post.go index bdb64b0..920b539 100644 --- a/auth/login_post.go +++ b/auth/login_post.go @@ -18,29 +18,36 @@ func (auth *AuthMiddleware) LoginPost(w http.ResponseWriter, r *http.Request) { username := r.Form.Get("username") password := r.Form.Get("password") + props := NewLoginProps() + props.Username.Value = username + user, err := db.GetUserByName(username) if user == nil || err != nil { time.Sleep(time.Second) - http.Error(w, "Username or password invalid", http.StatusUnauthorized) + props.GeneralError = "Username or password invalid" + auth.RedirectWithFlash(w, r, "/", "login_props", &props) return } passHash, err := user.GetPassHash() if err != nil { - http.Error(w, "Something went wrong. Error code: Momo", http.StatusInternalServerError) + props.GeneralError = "Something went wrong. Error code: Momo" + auth.RedirectWithFlash(w, r, "/", "login_props", &props) return } err = bcrypt.CompareHashAndPassword(passHash, []byte(password)) if err != nil { - http.Error(w, "Username or password invalid", http.StatusUnauthorized) + props.GeneralError = "Username or password invalid" + auth.RedirectWithFlash(w, r, "/", "login_props", &props) return } session, err := auth.Store.Get(r, "lishwist_user") if err != nil { log.Println("Couldn't get jwt:", err) - http.Error(w, "Something went wrong. Error code: Sokka", http.StatusInternalServerError) + props.GeneralError = "Something went wrong. Error code: Sokka" + auth.RedirectWithFlash(w, r, "/", "login_props", &props) return } session.Values["authorized"] = true diff --git a/auth/redirect_with_error.go b/auth/redirect_with_error.go new file mode 100644 index 0000000..0bb00d5 --- /dev/null +++ b/auth/redirect_with_error.go @@ -0,0 +1,17 @@ +package auth + +import ( + "log" + "net/http" +) + +func (auth *AuthMiddleware) RedirectWithFlash(w http.ResponseWriter, r *http.Request, url string, key string, flash any) { + session, _ := auth.Store.Get(r, "lishwist_user") + session.AddFlash(flash, key) + if err := session.Save(r, w); err != nil { + log.Println("Couldn't save session:", err) + http.Error(w, "Something went wrong. Error code: Zuko", http.StatusInternalServerError) + return + } + http.Redirect(w, r, url, http.StatusSeeOther) +} diff --git a/auth/register.go b/auth/register.go index d275cce..e59a6d4 100644 --- a/auth/register.go +++ b/auth/register.go @@ -5,10 +5,61 @@ import ( "net/http" "lishwist/db" + "lishwist/templates" "golang.org/x/crypto/bcrypt" ) +type RegisterProps struct { + GeneralError string + Username templates.InputProps + Password templates.InputProps + ConfirmPassword templates.InputProps +} + +func NewRegisterProps() RegisterProps { + return RegisterProps{ + GeneralError: "", + Username: templates.InputProps{ + Name: "username", + Required: true, + }, + Password: templates.InputProps{ + Type: "password", + Name: "newPassword", + Required: true, + MinLength: 5, + }, + ConfirmPassword: templates.InputProps{ + Type: "password", + Name: "confirmPassword", + Required: true, + }, + } +} + +func (auth *AuthMiddleware) Register(w http.ResponseWriter, r *http.Request) { + props := NewRegisterProps() + + session, _ := auth.Store.Get(r, "lishwist_user") + if flashes := session.Flashes("register_props"); len(flashes) > 0 { + flashProps, _ := flashes[0].(*RegisterProps) + props.Username.Value = flashProps.Username.Value + + props.GeneralError = flashProps.GeneralError + props.Username.Error = flashProps.Username.Error + props.ConfirmPassword.Error = flashProps.ConfirmPassword.Error + } + + if err := session.Save(r, w); err != nil { + log.Println("Couldn't save session:", err) + http.Error(w, "Something went wrong. Error code: Zuko", http.StatusInternalServerError) + return + } + + templates.Execute(w, "register.gotmpl", props) +} + func (auth *AuthMiddleware) RegisterPost(w http.ResponseWriter, r *http.Request) { if err := r.ParseForm(); err != nil { http.Error(w, "Couldn't parse form", http.StatusBadRequest) @@ -19,31 +70,40 @@ func (auth *AuthMiddleware) RegisterPost(w http.ResponseWriter, r *http.Request) newPassword := r.Form.Get("newPassword") confirmPassword := r.Form.Get("confirmPassword") + props := NewRegisterProps() + props.Username.Value = username + props.Password.Value = newPassword + props.ConfirmPassword.Value = confirmPassword + existingUser, _ := db.GetUserByName(username) if existingUser != nil { - http.Error(w, "Username is taken", http.StatusBadRequest) + props.Username.Error = "Username is taken" + auth.RedirectWithFlash(w, r, "/register", "register_props", &props) return } if newPassword != confirmPassword { - http.Error(w, "passwords didn't match", http.StatusBadRequest) + props.ConfirmPassword.Error = "Password didn't match" + auth.RedirectWithFlash(w, r, "/register", "register_props", &props) return } hashedPasswordBytes, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.MinCost) if err != nil { - http.Error(w, "Something went wrong. Error code: Aang", http.StatusInternalServerError) + props.GeneralError = "Something went wrong. Error code: Aang" + auth.RedirectWithFlash(w, r, "/register", "register_props", &props) return } _, err = db.CreateUser(username, hashedPasswordBytes) if err != nil { - http.Error(w, "Something went wrong. Error code: Ozai", http.StatusInternalServerError) + props.GeneralError = "Something went wrong. Error code: Ozai" + auth.RedirectWithFlash(w, r, "/register", "register_props", &props) return } session, _ := auth.Store.Get(r, "lishwist_user") - session.Values["successful_registration"] = true + session.AddFlash(true, "successful_registration") if err := session.Save(r, w); err != nil { log.Println("Couldn't save session:", err) http.Error(w, "Something went wrong. Error code: Zuko", http.StatusInternalServerError) diff --git a/context/context.go b/context/context.go index ba0482e..6d2336e 100644 --- a/context/context.go +++ b/context/context.go @@ -2,7 +2,7 @@ package context import ( "lishwist/auth" - "log" + "lishwist/error" "net/http" ) @@ -19,8 +19,7 @@ func (ctx *Context) WishlistAdd(w http.ResponseWriter, r *http.Request) { newGiftName := r.Form.Get("gift_name") err := user.AddGift(newGiftName) if err != nil { - log.Printf("Failed to add gift: %s\n", err) - http.Error(w, "Failed to add gift.", http.StatusInternalServerError) + error.Page(w, "Failed to add gift.", http.StatusInternalServerError, err) return } http.Redirect(w, r, "/", http.StatusSeeOther) @@ -35,8 +34,7 @@ func (ctx *Context) WishlistDelete(w http.ResponseWriter, r *http.Request) { targets := r.Form["gift"] err := user.RemoveGifts(targets...) if err != nil { - log.Printf("Failed to remove gifts: %s\n", err) - http.Error(w, "Failed to remove gifts.", http.StatusInternalServerError) + error.Page(w, "Failed to remove gifts.", http.StatusInternalServerError, err) return } http.Redirect(w, r, "/", http.StatusSeeOther) @@ -45,7 +43,7 @@ func (ctx *Context) WishlistDelete(w http.ResponseWriter, r *http.Request) { func (ctx *Context) ForeignWishlistPost(w http.ResponseWriter, r *http.Request) { user := ctx.Auth.ExpectUser(r) if err := r.ParseForm(); err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) + error.Page(w, "Failed to parse form...", http.StatusBadRequest, err) return } userReference := r.PathValue("userReference") @@ -55,27 +53,25 @@ func (ctx *Context) ForeignWishlistPost(w http.ResponseWriter, r *http.Request) unclaims := r.Form["claimed"] err := user.ClaimGifts(claims, unclaims) if err != nil { - http.Error(w, "Failed to update claim...", http.StatusInternalServerError) + error.Page(w, "Failed to update claim...", http.StatusInternalServerError, err) return } case "complete": claims := r.Form["claimed"] err := user.CompleteGifts(claims) if err != nil { - log.Printf("Failed to complete gifts: %s\n", err) - http.Error(w, "Failed to complete gifts...", http.StatusInternalServerError) + error.Page(w, "Failed to complete gifts...", http.StatusInternalServerError, nil) return } case "add": giftName := r.Form.Get("gift_name") if giftName == "" { - http.Error(w, "Gift name not provided", http.StatusBadRequest) + error.Page(w, "Gift name not provided", http.StatusBadRequest, nil) return } err := user.AddGiftToUser(userReference, giftName) if err != nil { - log.Printf("Failed to add gift idea to other user: %s\n", err) - http.Error(w, "Failed to add gift idea to other user...", http.StatusInternalServerError) + error.Page(w, "Failed to add gift idea to other user...", http.StatusInternalServerError, err) return } case "delete": @@ -84,8 +80,7 @@ func (ctx *Context) ForeignWishlistPost(w http.ResponseWriter, r *http.Request) gifts := append(claims, unclaims...) err := user.RemoveGifts(gifts...) if err != nil { - log.Printf("Failed to remove gift idea for other user: %s\n", err) - http.Error(w, "Failed to remove gift idea for other user...", http.StatusInternalServerError) + error.Page(w, "Failed to remove gift idea for other user...", http.StatusInternalServerError, err) return } default: diff --git a/context/foreign_wishlist.go b/context/foreign_wishlist.go index 0c153e4..d27f4a5 100644 --- a/context/foreign_wishlist.go +++ b/context/foreign_wishlist.go @@ -2,16 +2,15 @@ package context import ( "lishwist/db" + "lishwist/error" "lishwist/templates" - "log" "net/http" ) -type ForeignWishlistProps struct { +type foreignWishlistProps struct { CurrentUserId string CurrentUserName string Username string - UserReference string Gifts []db.Gift } @@ -19,25 +18,48 @@ func (ctx *Context) ForeignWishlist(w http.ResponseWriter, r *http.Request) { userReference := r.PathValue("userReference") user := ctx.Auth.ExpectUser(r) if user.Reference == userReference { - http.Error(w, "You can't view your own list, silly ;)", http.StatusForbidden) + http.Redirect(w, r, "/", http.StatusSeeOther) return } otherUser, err := db.GetUserByReference(userReference) if err != nil { - log.Printf("An error occurred while fetching a user: %s\n", err) - http.Error(w, "An error occurred while fetching this user :(", http.StatusInternalServerError) + error.Page(w, "An error occurred while fetching this user :(", http.StatusInternalServerError, err) return } if otherUser == nil { - http.Error(w, "User not found", http.StatusNotFound) + error.Page(w, "User not found", http.StatusNotFound, err) return } gifts, err := user.GetOtherUserGifts(userReference) if err != nil { - log.Printf("An error occurred while fetching %s's wishlist: %s\n", otherUser.Name, err) - http.Error(w, "An error occurred while fetching this user's wishlist :(", http.StatusInternalServerError) + error.Page(w, "An error occurred while fetching this user's wishlist :(", http.StatusInternalServerError, err) return } - p := ForeignWishlistProps{CurrentUserId: user.Id, CurrentUserName: user.Name, Username: otherUser.Name, UserReference: userReference, Gifts: gifts} + p := foreignWishlistProps{CurrentUserId: user.Id, CurrentUserName: user.Name, Username: otherUser.Name, Gifts: gifts} templates.Execute(w, "foreign_wishlist.gotmpl", p) } + +type publicForeignWishlistProps struct { + Username string + GiftCount int +} + +func (ctx *Context) PublicForeignWishlist(w http.ResponseWriter, r *http.Request) { + userReference := r.PathValue("userReference") + otherUser, err := db.GetUserByReference(userReference) + if err != nil { + error.Page(w, "An error occurred while fetching this user :(", http.StatusInternalServerError, err) + return + } + if otherUser == nil { + error.Page(w, "User not found", http.StatusNotFound, err) + return + } + giftCount, err := otherUser.CountGifts() + if err != nil { + error.Page(w, "An error occurred while fetching data about this user :(", http.StatusInternalServerError, err) + return + } + p := publicForeignWishlistProps{Username: otherUser.Name, GiftCount: giftCount} + templates.Execute(w, "public_foreign_wishlist.gotmpl", p) +} diff --git a/context/home.go b/context/home.go index 8478f5a..1f76836 100644 --- a/context/home.go +++ b/context/home.go @@ -5,6 +5,7 @@ import ( "lishwist/db" "lishwist/env" + "lishwist/error" "lishwist/templates" ) @@ -20,12 +21,12 @@ func (ctx *Context) Home(w http.ResponseWriter, r *http.Request) { user := ctx.Auth.ExpectUser(r) gifts, err := user.GetGifts() if err != nil { - http.Error(w, "An error occurred while fetching your wishlist :(", http.StatusInternalServerError) + error.Page(w, "An error occurred while fetching your wishlist :(", http.StatusInternalServerError, err) return } todo, err := user.GetTodo() if err != nil { - http.Error(w, "An error occurred while fetching your wishlist :(", http.StatusInternalServerError) + error.Page(w, "An error occurred while fetching your wishlist :(", http.StatusInternalServerError, err) return } p := HomeProps{Username: user.Name, Gifts: gifts, Todo: todo, Reference: user.Reference, HostUrl: env.HostUrl.String()} diff --git a/db/user.go b/db/user.go index 26f9883..f7538b2 100644 --- a/db/user.go +++ b/db/user.go @@ -85,6 +85,16 @@ func (u *User) GetPassHash() ([]byte, error) { return []byte(passHash), nil } +func (u *User) CountGifts() (int, error) { + stmt := "SELECT COUNT(gift.id) AS gift_count FROM gift JOIN user ON gift.recipient_id = user.id LEFT JOIN user AS claimant ON gift.claimant_id = claimant.id WHERE gift.creator_id = user.id AND user.id = ?" + var giftCount int + err := database.QueryRow(stmt, u.Id).Scan(&giftCount) + if err != nil { + return 0, err + } + return giftCount, nil +} + func (u *User) GetGifts() ([]Gift, error) { stmt := "SELECT gift.id, gift.name, claimant.id, claimant.name, gift.sent FROM gift JOIN user ON gift.recipient_id = user.id LEFT JOIN user AS claimant ON gift.claimant_id = claimant.id WHERE gift.creator_id = user.id AND user.id = ?" rows, err := database.Query(stmt, u.Id) diff --git a/error/page.go b/error/page.go new file mode 100644 index 0000000..8fab823 --- /dev/null +++ b/error/page.go @@ -0,0 +1,17 @@ +package error + +import ( + "lishwist/templates" + "log" + "net/http" +) + +type pageProps struct { + Message string +} + +func Page(w http.ResponseWriter, publicMessage string, status int, err error) { + log.Printf("%s --- %s\n", publicMessage, err) + templates.Execute(w, "error_page.gotmpl", pageProps{publicMessage}) + http.Error(w, "", http.StatusInternalServerError) +} diff --git a/hashpword/main.go b/hashpword/main.go new file mode 100644 index 0000000..14d68f8 --- /dev/null +++ b/hashpword/main.go @@ -0,0 +1,23 @@ +package main + +import ( + "fmt" + "log" + "os" + "strconv" + + "golang.org/x/crypto/bcrypt" +) + +func main() { + password := []byte(os.Args[1]) + cost, err := strconv.ParseInt(os.Args[2], 10, 0) + if err != nil { + log.Fatalln("Failed to parse cost: ", err) + } + hash, err := bcrypt.GenerateFromPassword(password, int(cost)) + if err != nil { + log.Fatalln("Failed to hash: ", err) + } + fmt.Println(string(hash)) +} diff --git a/main.go b/main.go index 9ea69a8..d58fa5c 100644 --- a/main.go +++ b/main.go @@ -8,7 +8,6 @@ import ( "lishwist/context" "lishwist/db" "lishwist/env" - "lishwist/templates" ) func main() { @@ -30,10 +29,11 @@ func main() { Auth: authMiddleware, } - publicMux.HandleFunc("GET /register", templates.Register) + publicMux.HandleFunc("GET /register", authMiddleware.Register) publicMux.HandleFunc("POST /register", authMiddleware.RegisterPost) publicMux.HandleFunc("GET /", authMiddleware.Login) publicMux.HandleFunc("POST /", authMiddleware.LoginPost) + publicMux.HandleFunc("GET /list/{userReference}", ctx.PublicForeignWishlist) protectedMux.HandleFunc("GET /{$}", ctx.Home) protectedMux.HandleFunc("POST /{$}", ctx.HomePost) diff --git a/session/session.go b/session/session.go new file mode 100644 index 0000000..2d695f8 --- /dev/null +++ b/session/session.go @@ -0,0 +1,25 @@ +package sesh + +import ( + "log" + "net/http" + + "github.com/gorilla/sessions" +) + +func GetFirstFlash(w http.ResponseWriter, r *http.Request, session *sessions.Session, key ...string) (any, error) { + flashes := session.Flashes(key...) + + if len(flashes) < 1 { + return nil, nil + } + + flash := flashes[0] + + if err := session.Save(r, w); err != nil { + log.Println("Couldn't save session:", err) + return nil, err + } + + return flash, nil +} diff --git a/templates/base.gotmpl b/templates/base.gotmpl index c80727b..2ef3244 100644 --- a/templates/base.gotmpl +++ b/templates/base.gotmpl @@ -1,3 +1,17 @@ +{{define "input"}} + +{{with .Error}} +
+ {{.}} +
+{{else}} +
+​ +
+{{end}} +{{end}} + diff --git a/templates/error_page.gotmpl b/templates/error_page.gotmpl new file mode 100644 index 0000000..8903d5f --- /dev/null +++ b/templates/error_page.gotmpl @@ -0,0 +1,17 @@ +{{define "navbar"}} + +{{end}} + +{{define "body"}} +
+ +
+{{end}} diff --git a/templates/foreign_wishlist.gotmpl b/templates/foreign_wishlist.gotmpl index 3a3c397..743a771 100644 --- a/templates/foreign_wishlist.gotmpl +++ b/templates/foreign_wishlist.gotmpl @@ -84,7 +84,7 @@ {{end}}
- +
This will be invisible to {{.Username}}, but everyone else will be @@ -95,4 +95,4 @@
-{{end}} \ No newline at end of file +{{end}} diff --git a/templates/home.gotmpl b/templates/home.gotmpl index 2d9cec2..985fc67 100644 --- a/templates/home.gotmpl +++ b/templates/home.gotmpl @@ -47,7 +47,7 @@ {{end}}
- +
diff --git a/templates/login.gotmpl b/templates/login.gotmpl index f32ba41..158a608 100644 --- a/templates/login.gotmpl +++ b/templates/login.gotmpl @@ -8,17 +8,22 @@

Registration successful. Now you can login.

{{end}} + {{with .GeneralError}} + + {{end}}
-
+
-
+ diff --git a/templates/public_foreign_wishlist.gotmpl b/templates/public_foreign_wishlist.gotmpl new file mode 100644 index 0000000..5e85b6b --- /dev/null +++ b/templates/public_foreign_wishlist.gotmpl @@ -0,0 +1,37 @@ +{{define "navbar"}} + +{{end}} + +{{define "login_prompt"}} +Login or register +{{end}} + +{{define "body"}} +
+
+
+
+

{{.Username}}'s list

+ {{if eq .GiftCount 0}} +

{{.Username}} doesn't have any gift ideas!

+

{{template "login_prompt"}} to add some! :^)

+ {{else}} + {{if eq .GiftCount 1}} +

{{.Username}} only has one gift idea.

+

{{template "login_prompt"}} to claim it, or add more! :^)

+ {{else}} +

{{.Username}} has {{.GiftCount}} gift ideas.

+

{{template "login_prompt"}} to claim an idea, or add more! :^)

+ {{end}} + {{end}} +
+
+
+
+{{end}} \ No newline at end of file diff --git a/templates/register.go b/templates/register.go deleted file mode 100644 index cb9f387..0000000 --- a/templates/register.go +++ /dev/null @@ -1,9 +0,0 @@ -package templates - -import ( - "net/http" -) - -func Register(w http.ResponseWriter, r *http.Request) { - Execute(w, "register.gotmpl", nil) -} diff --git a/templates/register.gotmpl b/templates/register.gotmpl index 51de0a3..6a147f4 100644 --- a/templates/register.gotmpl +++ b/templates/register.gotmpl @@ -1,4 +1,11 @@ {{define "navbar"}} + {{end}} {{define "body"}} @@ -7,19 +14,24 @@

Your password will be stored in a safe, responsible manner; but don't trust my programming skills!

Maybe use a password here that you don't use for important things...

+ {{with .GeneralError}} + + {{end}} -
+
diff --git a/templates/templates.go b/templates/templates.go index 7c5cf62..570477f 100644 --- a/templates/templates.go +++ b/templates/templates.go @@ -6,6 +6,15 @@ import ( "text/template" ) +type InputProps struct { + Type string + Name string + Required bool + Value string + Error string + MinLength uint +} + var tmpls map[string]*template.Template = loadTemplates() func Execute(w http.ResponseWriter, name string, data any) { @@ -21,10 +30,14 @@ func loadTemplates() map[string]*template.Template { loginTmpl := template.Must(template.ParseFiles("templates/base.gotmpl", "templates/login.gotmpl")) registerTmpl := template.Must(template.ParseFiles("templates/base.gotmpl", "templates/register.gotmpl")) foreignTmpl := template.Must(template.ParseFiles("templates/base.gotmpl", "templates/foreign_wishlist.gotmpl")) + publicForeignTmpl := template.Must(template.ParseFiles("templates/base.gotmpl", "templates/public_foreign_wishlist.gotmpl")) + errorTmpl := template.Must(template.ParseFiles("templates/base.gotmpl", "templates/error_page.gotmpl")) return map[string]*template.Template{ - "home.gotmpl": homeTmpl, - "login.gotmpl": loginTmpl, - "register.gotmpl": registerTmpl, - "foreign_wishlist.gotmpl": foreignTmpl, + "home.gotmpl": homeTmpl, + "login.gotmpl": loginTmpl, + "register.gotmpl": registerTmpl, + "foreign_wishlist.gotmpl": foreignTmpl, + "public_foreign_wishlist.gotmpl": publicForeignTmpl, + "error_page.gotmpl": errorTmpl, } }