package handlers import ( "database/sql" "html/template" "mealprep/auth" "mealprep/database" "net/http" "strings" "time" ) // LoginPageHandler shows the login page func LoginPageHandler(w http.ResponseWriter, r *http.Request) { tmpl := ` Login - Meal Prep Planner

🍽️ Meal Prep Planner

Login

{{if .Error}}
{{.Error}}
{{end}}
` data := struct { Error string }{ Error: r.URL.Query().Get("error"), } t := template.Must(template.New("login").Parse(tmpl)) t.Execute(w, data) } // RegisterPageHandler shows the registration page func RegisterPageHandler(w http.ResponseWriter, r *http.Request) { tmpl := ` Register - Meal Prep Planner

🍽️ Meal Prep Planner

Create Account

{{if .Error}}
{{.Error}}
{{end}}
` data := struct { Error string }{ Error: r.URL.Query().Get("error"), } t := template.Must(template.New("register").Parse(tmpl)) t.Execute(w, data) } // LoginHandler processes login requests func LoginHandler(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { http.Redirect(w, r, "/login", http.StatusSeeOther) return } if err := r.ParseForm(); err != nil { http.Redirect(w, r, "/login?error=Invalid+request", http.StatusSeeOther) return } email := strings.TrimSpace(strings.ToLower(r.FormValue("email"))) password := r.FormValue("password") // Validate input if email == "" || password == "" { http.Redirect(w, r, "/login?error=Email+and+password+required", http.StatusSeeOther) return } if !auth.ValidateEmail(email) { http.Redirect(w, r, "/login?error=Invalid+email+format", http.StatusSeeOther) return } // Get user from database user, err := database.GetUserByEmail(email) if err != nil { if err == sql.ErrNoRows { http.Redirect(w, r, "/login?error=Invalid+credentials", http.StatusSeeOther) return } http.Redirect(w, r, "/login?error=Server+error", http.StatusSeeOther) return } // Check password if !auth.CheckPassword(password, user.PasswordHash) { http.Redirect(w, r, "/login?error=Invalid+credentials", http.StatusSeeOther) return } // Create session token, err := auth.GenerateSessionToken() if err != nil { http.Redirect(w, r, "/login?error=Failed+to+create+session", http.StatusSeeOther) return } expiresAt := auth.GetSessionExpiry() if err := database.CreateSession(token, user.ID, expiresAt); err != nil { http.Redirect(w, r, "/login?error=Failed+to+create+session", http.StatusSeeOther) return } // Set secure cookie http.SetCookie(w, &http.Cookie{ Name: "session_token", Value: token, Expires: expiresAt, HttpOnly: true, Secure: false, // Set to true in production with HTTPS SameSite: http.SameSiteStrictMode, Path: "/", }) // Redirect to home http.Redirect(w, r, "/", http.StatusSeeOther) } // RegisterHandler processes registration requests func RegisterHandler(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { http.Redirect(w, r, "/register", http.StatusSeeOther) return } if err := r.ParseForm(); err != nil { http.Redirect(w, r, "/register?error=Invalid+request", http.StatusSeeOther) return } email := strings.TrimSpace(strings.ToLower(r.FormValue("email"))) password := r.FormValue("password") passwordConfirm := r.FormValue("password_confirm") // Validate input if email == "" || password == "" || passwordConfirm == "" { http.Redirect(w, r, "/register?error=All+fields+required", http.StatusSeeOther) return } if !auth.ValidateEmail(email) { http.Redirect(w, r, "/register?error=Invalid+email+format", http.StatusSeeOther) return } if password != passwordConfirm { http.Redirect(w, r, "/register?error=Passwords+do+not+match", http.StatusSeeOther) return } if len(password) < 8 { http.Redirect(w, r, "/register?error=Password+must+be+at+least+8+characters", http.StatusSeeOther) return } // Check if user exists existingUser, _ := database.GetUserByEmail(email) if existingUser != nil { http.Redirect(w, r, "/register?error=Email+already+registered", http.StatusSeeOther) return } // Hash password passwordHash, err := auth.HashPassword(password) if err != nil { http.Redirect(w, r, "/register?error=Failed+to+create+account", http.StatusSeeOther) return } // Create user userID, err := database.CreateUser(email, passwordHash) if err != nil { http.Redirect(w, r, "/register?error=Failed+to+create+account", http.StatusSeeOther) return } // Create session token, err := auth.GenerateSessionToken() if err != nil { http.Redirect(w, r, "/login", http.StatusSeeOther) return } expiresAt := auth.GetSessionExpiry() if err := database.CreateSession(token, int(userID), expiresAt); err != nil { http.Redirect(w, r, "/login", http.StatusSeeOther) return } // Set secure cookie http.SetCookie(w, &http.Cookie{ Name: "session_token", Value: token, Expires: expiresAt, HttpOnly: true, Secure: false, // Set to true in production with HTTPS SameSite: http.SameSiteStrictMode, Path: "/", }) // Redirect to home http.Redirect(w, r, "/", http.StatusSeeOther) } // LogoutHandler processes logout requests func LogoutHandler(w http.ResponseWriter, r *http.Request) { // Get session cookie cookie, err := r.Cookie("session_token") if err == nil { // Delete session from database database.DeleteSession(cookie.Value) } // Clear cookie http.SetCookie(w, &http.Cookie{ Name: "session_token", Value: "", Expires: time.Unix(0, 0), HttpOnly: true, Secure: false, SameSite: http.SameSiteStrictMode, Path: "/", MaxAge: -1, }) http.Redirect(w, r, "/login", http.StatusSeeOther) }