149 lines
3.3 KiB
Go

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()
session.Store(sess)
if sess.UserID > 0 { // User session
user, err := users.Find(sess.UserID)
if err == nil && user != nil {
ctx.SetUserValue("user", user)
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 {
_, exists := ctx.UserValue("user").(*users.User)
return exists
}
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)
sess.RegenerateID()
sess.Set("user_id", user.ID)
sess.SetFlash("success", fmt.Sprintf("Welcome back, %s!", user.Username))
session.Store(sess)
ctx.SetUserValue("session", sess)
ctx.SetUserValue("user", user)
}
func Logout(ctx router.Ctx) {
sessionID := cookies.GetCookie(ctx, SessionCookieName)
if sessionID != "" {
session.Delete(sessionID)
}
deleteSessionCookie(ctx)
ctx.SetUserValue("session", nil)
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)
}