Files
BagExchange/controller.go
2026-02-19 20:08:06 +01:00

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,
})
}