feat(router): improve error handling with dedicated error pages
- Add renderErrorPage helper for consistent error rendering - Add ensureUserExistsMiddleware to detect deleted users and redirect to login - Add catch-all 404 handler for unknown routes - Gracefully handle data loading failures with error messages instead of crashing - Log errors for debugging while still rendering pages
This commit is contained in:
@@ -8,6 +8,8 @@ import (
|
||||
ratelimit "bookhoard/internal/middleware"
|
||||
"bookhoard/internal/services"
|
||||
"bookhoard/internal/sync"
|
||||
"bookhoard/templates"
|
||||
"bytes"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
@@ -105,6 +107,45 @@ func createJWTMiddleware(cfg *Config) echo.MiddlewareFunc {
|
||||
})
|
||||
}
|
||||
|
||||
// ensureUserExistsMiddleware checks if the authenticated user still exists in the database
|
||||
func ensureUserExistsMiddleware(cfg *Config) echo.MiddlewareFunc {
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
userIDStr, ok := c.Get("user_id").(string)
|
||||
if !ok {
|
||||
return next(c)
|
||||
}
|
||||
|
||||
userUUID, err := uuid.Parse(userIDStr)
|
||||
if err != nil {
|
||||
log.Printf("Invalid UUID in user existence check: %v", err)
|
||||
return next(c)
|
||||
}
|
||||
|
||||
// Check if user exists in database
|
||||
_, err = cfg.Queries.GetUser(c.Request().Context(), uuidToPGType(userUUID))
|
||||
if err != nil {
|
||||
log.Printf("User not found in database: %s", userIDStr)
|
||||
|
||||
// Clear invalid cookie
|
||||
c.SetCookie(&http.Cookie{
|
||||
Name: "token",
|
||||
Value: "",
|
||||
Expires: time.Now().Add(-24 * time.Hour),
|
||||
Path: "/",
|
||||
HttpOnly: true,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
})
|
||||
|
||||
// Redirect to login with session=invalid
|
||||
return c.Redirect(http.StatusFound, "/login?session=invalid")
|
||||
}
|
||||
|
||||
return next(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// wantsHTML determines if the request expects HTML response
|
||||
func wantsHTML(header http.Header) bool {
|
||||
// Check Accept header
|
||||
@@ -180,6 +221,16 @@ func RegisterRoutes(cfg *Config) *handlers.Handler {
|
||||
registerDocumentationRoutes(cfg)
|
||||
e.Static("/static", "web/static")
|
||||
|
||||
// Catch-all 404 handler - must be last
|
||||
e.GET("/*", func(c echo.Context) error {
|
||||
var buf bytes.Buffer
|
||||
err := templates.ErrorPage("Page not found", "404").Render(c.Request().Context(), &buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.HTML(http.StatusNotFound, buf.String())
|
||||
})
|
||||
|
||||
// Start background tasks (queue processor and connection cleanup)
|
||||
scannerHandler.StartBackgroundTasks()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user