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
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user