package errors import ( "fmt" "net/http" "os" templateHelpers "synlotto-website/internal/helpers/template" "synlotto-website/internal/models" "synlotto-website/internal/platform/sessionkeys" "github.com/alexedwards/scs/v2" "github.com/gin-gonic/gin" ) // RenderStatus renders web/templates/error/.html inside layout.html, // using ONLY session data (no DB) so 404/500 pages don't crash and still // look "logged in" when a session exists. func RenderStatus(c *gin.Context, sessions *scs.SessionManager, status int) { // Synthesize minimal TemplateData from session only var data models.TemplateData ctx := c.Request.Context() // Read minimal user snapshot from session var uid int64 if v := sessions.Get(ctx, sessionkeys.UserID); v != nil { switch t := v.(type) { case int64: uid = t case int: uid = int64(t) } } if uid > 0 { // username and is_admin are optional but make navbar correct var uname string if v := sessions.Get(ctx, sessionkeys.Username); v != nil { if s, ok := v.(string); ok { uname = s } } var isAdmin bool if v := sessions.Get(ctx, sessionkeys.IsAdmin); v != nil { if b, ok := v.(bool); ok { isAdmin = b } } // Build a lightweight user; avoids DB lookups in error paths data.User = &models.User{ Id: uid, Username: uname, IsAdmin: isAdmin, } data.IsAdmin = isAdmin } // Turn into the template context map (adds site meta, funcs, etc.) ctxMap := templateHelpers.TemplateContext(c.Writer, c.Request, data) // Flash (SCS) if f := sessions.PopString(ctx, sessionkeys.Flash); f != "" { ctxMap["Flash"] = f } // Template paths (layout-first) pagePath := fmt.Sprintf("web/templates/error/%d.html", status) if _, err := os.Stat(pagePath); err != nil { c.String(status, http.StatusText(status)) return } tmpl := templateHelpers.LoadTemplateFiles( "web/templates/layout.html", pagePath, ) c.Status(status) if err := tmpl.ExecuteTemplate(c.Writer, "layout", ctxMap); err != nil { c.String(status, http.StatusText(status)) } } // Adapters so bootstrap can wire these without lambdas everywhere. func NoRoute(sessions *scs.SessionManager) gin.HandlerFunc { return func(c *gin.Context) { RenderStatus(c, sessions, http.StatusNotFound) } } func NoMethod(sessions *scs.SessionManager) gin.HandlerFunc { return func(c *gin.Context) { RenderStatus(c, sessions, http.StatusMethodNotAllowed) } } func Recovery(sessions *scs.SessionManager) gin.RecoveryFunc { return func(c *gin.Context, _ interface{}) { RenderStatus(c, sessions, http.StatusInternalServerError) } }