Initial commit: breakpilot-core - Shared Infrastructure
Docker Compose with 24+ services: - PostgreSQL (PostGIS), Valkey, MinIO, Qdrant - Vault (PKI/TLS), Nginx (Reverse Proxy) - Backend Core API, Consent Service, Billing Service - RAG Service, Embedding Service - Gitea, Woodpecker CI/CD - Night Scheduler, Health Aggregator - Jitsi (Web/XMPP/JVB/Jicofo), Mailpit Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
196
consent-service/internal/session/session_middleware.go
Normal file
196
consent-service/internal/session/session_middleware.go
Normal file
@@ -0,0 +1,196 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
// SessionMiddleware extracts session from request and adds to context
|
||||
func SessionMiddleware(pgPool *pgxpool.Pool) gin.HandlerFunc {
|
||||
store := GetSessionStore(pgPool)
|
||||
|
||||
return func(c *gin.Context) {
|
||||
sessionID := extractSessionID(c)
|
||||
|
||||
if sessionID != "" {
|
||||
session, err := store.GetSession(c.Request.Context(), sessionID)
|
||||
if err == nil && session != nil {
|
||||
// Add session to context
|
||||
c.Set("session", session)
|
||||
c.Set("session_id", session.SessionID)
|
||||
c.Set("user_id", session.UserID)
|
||||
c.Set("email", session.Email)
|
||||
c.Set("user_type", string(session.UserType))
|
||||
c.Set("roles", session.Roles)
|
||||
c.Set("permissions", session.Permissions)
|
||||
if session.TenantID != nil {
|
||||
c.Set("tenant_id", *session.TenantID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// extractSessionID extracts session ID from request
|
||||
func extractSessionID(c *gin.Context) string {
|
||||
// Try Authorization header first
|
||||
authHeader := c.GetHeader("Authorization")
|
||||
if strings.HasPrefix(authHeader, "Bearer ") {
|
||||
return strings.TrimPrefix(authHeader, "Bearer ")
|
||||
}
|
||||
|
||||
// Try X-Session-ID header
|
||||
if sessionID := c.GetHeader("X-Session-ID"); sessionID != "" {
|
||||
return sessionID
|
||||
}
|
||||
|
||||
// Try cookie
|
||||
if cookie, err := c.Cookie("session_id"); err == nil {
|
||||
return cookie
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// RequireSession requires a valid session
|
||||
func RequireSession() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
session := GetSession(c)
|
||||
|
||||
if session == nil {
|
||||
// Check development bypass
|
||||
if os.Getenv("ENVIRONMENT") == "development" {
|
||||
// Set demo session
|
||||
demoSession := getDemoSession()
|
||||
c.Set("session", demoSession)
|
||||
c.Set("session_id", demoSession.SessionID)
|
||||
c.Set("user_id", demoSession.UserID)
|
||||
c.Set("email", demoSession.Email)
|
||||
c.Set("user_type", string(demoSession.UserType))
|
||||
c.Set("roles", demoSession.Roles)
|
||||
c.Set("permissions", demoSession.Permissions)
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
|
||||
"error": "unauthorized",
|
||||
"message": "Authentication required",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// GetSession retrieves session from context
|
||||
func GetSession(c *gin.Context) *Session {
|
||||
if session, exists := c.Get("session"); exists {
|
||||
if s, ok := session.(*Session); ok {
|
||||
return s
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSessionUserID retrieves user ID from session context
|
||||
func GetSessionUserID(c *gin.Context) (uuid.UUID, error) {
|
||||
userIDStr, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
return uuid.Nil, nil
|
||||
}
|
||||
|
||||
return uuid.Parse(userIDStr.(string))
|
||||
}
|
||||
|
||||
// GetSessionEmail retrieves email from session context
|
||||
func GetSessionEmail(c *gin.Context) string {
|
||||
email, exists := c.Get("email")
|
||||
if !exists {
|
||||
return ""
|
||||
}
|
||||
return email.(string)
|
||||
}
|
||||
|
||||
// GetSessionUserType retrieves user type from session context
|
||||
func GetSessionUserType(c *gin.Context) UserType {
|
||||
userType, exists := c.Get("user_type")
|
||||
if !exists {
|
||||
return UserTypeCustomer
|
||||
}
|
||||
return UserType(userType.(string))
|
||||
}
|
||||
|
||||
// GetSessionRoles retrieves roles from session context
|
||||
func GetSessionRoles(c *gin.Context) []string {
|
||||
roles, exists := c.Get("roles")
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
if r, ok := roles.([]string); ok {
|
||||
return r
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSessionPermissions retrieves permissions from session context
|
||||
func GetSessionPermissions(c *gin.Context) []string {
|
||||
perms, exists := c.Get("permissions")
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
if p, ok := perms.([]string); ok {
|
||||
return p
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSessionTenantID retrieves tenant ID from session context
|
||||
func GetSessionTenantID(c *gin.Context) *string {
|
||||
tenantID, exists := c.Get("tenant_id")
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
if t, ok := tenantID.(string); ok {
|
||||
return &t
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getDemoSession returns a demo session for development
|
||||
func getDemoSession() *Session {
|
||||
tenantID := "a0000000-0000-0000-0000-000000000001"
|
||||
ip := "127.0.0.1"
|
||||
ua := "Development"
|
||||
|
||||
return &Session{
|
||||
SessionID: "demo-session-id",
|
||||
UserID: "10000000-0000-0000-0000-000000000024",
|
||||
Email: "demo@breakpilot.app",
|
||||
UserType: UserTypeEmployee,
|
||||
Roles: []string{
|
||||
"admin", "schul_admin", "teacher",
|
||||
},
|
||||
Permissions: []string{
|
||||
"grades:read", "grades:write",
|
||||
"attendance:read", "attendance:write",
|
||||
"students:read", "students:write",
|
||||
"reports:generate", "consent:admin",
|
||||
"own_data:read", "users:manage",
|
||||
},
|
||||
TenantID: &tenantID,
|
||||
IPAddress: &ip,
|
||||
UserAgent: &ua,
|
||||
CreatedAt: time.Now().UTC(),
|
||||
LastActivityAt: time.Now().UTC(),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user