package web import ( "context" "encoding/gob" "net/http" "omixlab.com/mosis-portal/internal/database" ) func init() { // Register types for gob encoding (used by cookie sessions) gob.Register(&database.Developer{}) } // SessionMiddleware handles session-based authentication for web pages type SessionMiddleware struct { db *database.DB cookieKey string } // NewSessionMiddleware creates a new session middleware func NewSessionMiddleware(db *database.DB, cookieKey string) *SessionMiddleware { return &SessionMiddleware{ db: db, cookieKey: cookieKey, } } // LoadSession loads the developer from session cookie func (m *SessionMiddleware) LoadSession(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Try to get developer ID from session cookie cookie, err := r.Cookie("session") if err != nil { next.ServeHTTP(w, r) return } // Lookup developer developer, err := m.db.GetDeveloper(r.Context(), cookie.Value) if err != nil { // Invalid session, clear cookie http.SetCookie(w, &http.Cookie{ Name: "session", Value: "", Path: "/", MaxAge: -1, HttpOnly: true, }) next.ServeHTTP(w, r) return } // Add developer to context ctx := context.WithValue(r.Context(), "developer", developer) next.ServeHTTP(w, r.WithContext(ctx)) }) } // RequireSession redirects to login if not authenticated func (m *SessionMiddleware) RequireSession(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { developer := getDeveloperFromContext(r) if developer == nil { http.Redirect(w, r, "/login", http.StatusSeeOther) return } next.ServeHTTP(w, r) }) } // SetSession creates a session for the developer func SetSession(w http.ResponseWriter, developerID string) { http.SetCookie(w, &http.Cookie{ Name: "session", Value: developerID, Path: "/", MaxAge: 60 * 60 * 24 * 30, // 30 days HttpOnly: true, SameSite: http.SameSiteLaxMode, }) } // ClearSession clears the session cookie func ClearSession(w http.ResponseWriter) { http.SetCookie(w, &http.Cookie{ Name: "session", Value: "", Path: "/", MaxAge: -1, HttpOnly: true, }) }