161 lines
4.5 KiB
Go
161 lines
4.5 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"errors"
|
|
"html/template"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/gofiber/fiber/v3"
|
|
"gorm.io/gorm"
|
|
"prada.ch/controllers"
|
|
)
|
|
|
|
type controller struct {
|
|
db *gorm.DB
|
|
mailConfig smtpConfig
|
|
authController *controllers.AuthController
|
|
subscribeController *controllers.SubscribeController
|
|
assetVersion string
|
|
landingTemplate *template.Template
|
|
howToWorkTemplate *template.Template
|
|
loginTemplate *template.Template
|
|
signupTemplate *template.Template
|
|
forgotPasswordTemplate *template.Template
|
|
resetPasswordTemplate *template.Template
|
|
welcomeTemplate *template.Template
|
|
}
|
|
|
|
const sessionCookieName = "bag_exchange_session"
|
|
|
|
func (h *controller) staticFile(c fiber.Ctx) error {
|
|
relativePath := filepath.Clean(c.Params("*"))
|
|
if relativePath == "." || strings.HasPrefix(relativePath, "..") {
|
|
return c.SendStatus(fiber.StatusNotFound)
|
|
}
|
|
return c.SendFile(filepath.Join("static", relativePath))
|
|
}
|
|
|
|
func (h *controller) home(c fiber.Ctx) error {
|
|
data := landingData{
|
|
Brand: "Bag Exchange",
|
|
InitialTitle: "Bag Exchange | Swap bags and handbags",
|
|
FooterText: "© 2026 Bag Exchange · Bag and handbag exchange between individuals",
|
|
AssetVersion: h.assetVersion,
|
|
}
|
|
|
|
var out bytes.Buffer
|
|
if err := h.landingTemplate.Execute(&out, data); err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).SendString("unable to render page")
|
|
}
|
|
|
|
c.Type("html", "utf-8")
|
|
return c.SendString(out.String())
|
|
}
|
|
|
|
func (h *controller) resetPasswordPage(c fiber.Ctx) error {
|
|
token := strings.TrimSpace(c.Query("token"))
|
|
var out bytes.Buffer
|
|
if err := h.resetPasswordTemplate.Execute(&out, resetPasswordPageData{Token: token}); err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).SendString("unable to render reset password page")
|
|
}
|
|
c.Type("html", "utf-8")
|
|
return c.SendString(out.String())
|
|
}
|
|
|
|
func (h *controller) howToWorkPage(c fiber.Ctx) error {
|
|
var out bytes.Buffer
|
|
if err := h.howToWorkTemplate.Execute(&out, nil); err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).SendString("unable to render howtowork page")
|
|
}
|
|
c.Type("html", "utf-8")
|
|
return c.SendString(out.String())
|
|
}
|
|
|
|
func (h *controller) loginPage(c fiber.Ctx) error {
|
|
var out bytes.Buffer
|
|
if err := h.loginTemplate.Execute(&out, nil); err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).SendString("unable to render login page")
|
|
}
|
|
c.Type("html", "utf-8")
|
|
return c.SendString(out.String())
|
|
}
|
|
|
|
func (h *controller) signupPage(c fiber.Ctx) error {
|
|
var out bytes.Buffer
|
|
if err := h.signupTemplate.Execute(&out, nil); err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).SendString("unable to render signup page")
|
|
}
|
|
c.Type("html", "utf-8")
|
|
return c.SendString(out.String())
|
|
}
|
|
|
|
func (h *controller) forgotPasswordPage(c fiber.Ctx) error {
|
|
var out bytes.Buffer
|
|
if err := h.forgotPasswordTemplate.Execute(&out, nil); err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).SendString("unable to render forgot password page")
|
|
}
|
|
c.Type("html", "utf-8")
|
|
return c.SendString(out.String())
|
|
}
|
|
|
|
func (h *controller) welcomePage(c fiber.Ctx) error {
|
|
email, ok := h.currentUserEmail(c)
|
|
if !ok {
|
|
return c.Redirect().To("/login")
|
|
}
|
|
|
|
var out bytes.Buffer
|
|
if err := h.welcomeTemplate.Execute(&out, map[string]string{"Email": email}); err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).SendString("unable to render welcome page")
|
|
}
|
|
c.Type("html", "utf-8")
|
|
return c.SendString(out.String())
|
|
}
|
|
|
|
func (h *controller) currentUserEmail(c fiber.Ctx) (string, bool) {
|
|
sessionToken := c.Cookies(sessionCookieName)
|
|
if sessionToken == "" {
|
|
return "", false
|
|
}
|
|
|
|
var sessionUser struct {
|
|
Email string `gorm:"column:email"`
|
|
}
|
|
err := h.db.Table("sessions").
|
|
Select("users.email").
|
|
Joins("JOIN users ON users.id = sessions.user_id").
|
|
Where("sessions.token_hash = ? AND sessions.expires_at > ?", hashSessionToken(sessionToken), time.Now().Unix()).
|
|
Take(&sessionUser).Error
|
|
if err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
clearAuthSessionCookie(c)
|
|
return "", false
|
|
}
|
|
return "", false
|
|
}
|
|
return sessionUser.Email, true
|
|
}
|
|
|
|
func hashSessionToken(value string) string {
|
|
sum := sha256.Sum256([]byte(value))
|
|
return hex.EncodeToString(sum[:])
|
|
}
|
|
|
|
func clearAuthSessionCookie(c fiber.Ctx) {
|
|
c.Cookie(&fiber.Cookie{
|
|
Name: sessionCookieName,
|
|
Value: "",
|
|
Path: "/",
|
|
HTTPOnly: true,
|
|
Secure: false,
|
|
SameSite: "Lax",
|
|
Expires: time.Unix(0, 0),
|
|
MaxAge: -1,
|
|
})
|
|
}
|