Files
fn_registry/functions/infra/session_validate.go
T
egutierrez 9153a20384 feat: session_create, session_validate, session_cleanup
Fase 3 del issue 0010 — sesiones SQLite como alternativa a JWT.
- Tabla sessions creada con CREATE TABLE IF NOT EXISTS (autosetup)
- Tokens de 32 bytes aleatorios (crypto/rand) codificados en hex (256 bits)
- Indices en user_id y expires_at
- Prepared statements para evitar SQL injection
- SessionCleanup para eliminar expiradas periodicamente
2026-04-18 17:40:13 +02:00

59 lines
1.4 KiB
Go

package infra
import (
"database/sql"
"encoding/json"
"errors"
"fmt"
"time"
)
// SessionValidate busca el token en la tabla sessions, verifica que no este
// expirado y retorna la Session con su metadata deserializada.
// Error si el token no existe, esta expirado o la BD falla.
func SessionValidate(db *sql.DB, token string) (Session, error) {
var zero Session
if db == nil {
return zero, fmt.Errorf("session_validate: db nil")
}
if token == "" {
return zero, fmt.Errorf("session_validate: token vacio")
}
var (
userID string
expiresAt int64
createdAt int64
metaStr string
)
row := db.QueryRow(
"SELECT user_id, expires_at, created_at, metadata FROM sessions WHERE token = ?",
token,
)
if err := row.Scan(&userID, &expiresAt, &createdAt, &metaStr); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return zero, fmt.Errorf("session_validate: token no encontrado")
}
return zero, fmt.Errorf("session_validate: scan: %w", err)
}
if time.Now().Unix() >= expiresAt {
return zero, fmt.Errorf("session_validate: sesion expirada")
}
var metadata map[string]any
if metaStr != "" {
if err := json.Unmarshal([]byte(metaStr), &metadata); err != nil {
return zero, fmt.Errorf("session_validate: metadata malformada: %w", err)
}
}
return Session{
Token: token,
UserID: userID,
ExpiresAt: expiresAt,
CreatedAt: createdAt,
Metadata: metadata,
}, nil
}