package auth import ( "dk/internal/cookies" "dk/internal/helpers" "dk/internal/models/users" "dk/internal/router" "dk/internal/session" "fmt" "time" "github.com/valyala/fasthttp" ) const SessionCookieName = "dk_session" func Middleware() router.Middleware { return func(next router.Handler) router.Handler { return func(ctx router.Ctx, params []string) { sessionID := cookies.GetCookie(ctx, SessionCookieName) var sess *session.Session if sessionID != "" { if existingSess, exists := session.Get(sessionID); exists { sess = existingSess sess.Touch() if sess.UserID > 0 { // User session user, err := users.Find(sess.UserID) if err == nil && user != nil { ctx.SetUserValue("user", user) } else { // User not found, reset to guest session sess.SetUserID(0) } } session.Store(sess) setSessionCookie(ctx, sessionID) } } // Create guest session if none exists if sess == nil { sess = session.Create(0) // Guest session setSessionCookie(ctx, sess.ID) } ctx.SetUserValue("session", sess) next(ctx, params) } } } func RequireAuth(paths ...string) router.Middleware { redirect := "/login" if len(paths) > 0 && paths[0] != "" { redirect = paths[0] } return func(next router.Handler) router.Handler { return func(ctx router.Ctx, params []string) { if !IsAuthenticated(ctx) { ctx.Redirect(redirect, fasthttp.StatusFound) return } user := ctx.UserValue("user").(*users.User) user.UpdateLastOnline() user.Save() next(ctx, params) } } } func RequireGuest(paths ...string) router.Middleware { redirect := "/" if len(paths) > 0 && paths[0] != "" { redirect = paths[0] } return func(next router.Handler) router.Handler { return func(ctx router.Ctx, params []string) { if IsAuthenticated(ctx) { fmt.Println("RequireGuest: user is authenticated") ctx.Redirect(redirect, fasthttp.StatusFound) return } next(ctx, params) } } } func IsAuthenticated(ctx router.Ctx) bool { if user, ok := ctx.UserValue("user").(*users.User); ok && user != nil { return true } return false } func GetCurrentUser(ctx router.Ctx) *users.User { if user, ok := ctx.UserValue("user").(*users.User); ok { return user } return nil } func GetCurrentSession(ctx router.Ctx) *session.Session { if sess, ok := ctx.UserValue("session").(*session.Session); ok { return sess } return nil } func Login(ctx router.Ctx, user *users.User) { sess := ctx.UserValue("session").(*session.Session) // Update the session to be authenticated sess.SetUserID(user.ID) // This updates the struct field sess.RegenerateID() // Generate new ID for security sess.SetFlash("success", fmt.Sprintf("Welcome back, %s!", user.Username)) // Remove any old user_id from session data if it exists sess.Delete("user_id") session.Store(sess) // Update context values ctx.SetUserValue("session", sess) ctx.SetUserValue("user", user) // Update cookie with new session ID setSessionCookie(ctx, sess.ID) } func Logout(ctx router.Ctx) { sess := ctx.UserValue("session").(*session.Session) if sess != nil { // Convert back to guest session sess.SetUserID(0) // Reset to guest sess.RegenerateID() // Generate new ID for security // Clean up any user-related session data sess.Delete("user_id") session.Store(sess) ctx.SetUserValue("session", sess) // Update cookie with new session ID setSessionCookie(ctx, sess.ID) } ctx.SetUserValue("user", nil) } // Helper functions for session cookies func setSessionCookie(ctx router.Ctx, sessionID string) { cookies.SetSecureCookie(ctx, cookies.CookieOptions{ Name: SessionCookieName, Value: sessionID, Path: "/", Expires: time.Now().Add(24 * time.Hour), HTTPOnly: true, Secure: helpers.IsHTTPS(ctx), SameSite: "lax", }) } func deleteSessionCookie(ctx router.Ctx) { cookies.DeleteCookie(ctx, SessionCookieName) }