Documentación Técnica — Sistema de Gestión de Usuarios
1. Descripción General
Aplicación web desarrollada en PHP 8.4 bajo el paradigma de Programación Orientada a Objetos (POO) con arquitectura MVC simplificada (sin capa de controladores formal, delegando la lógica a clases de servicio y archivos de vista). Utiliza MySQL como motor de persistencia, PDO para el acceso a datos con consultas preparadas, y Bootstrap 5 para la capa de presentación.
El sistema implementa autenticación basada en sesiones, control de acceso por roles (RBAC) y un dashboard administrativo.
2. Stack Tecnológico
| Componente | Versión / Tecnología |
|---|---|
| Lenguaje Backend | PHP 8.4 |
| Base de Datos | MySQL (InnoDB, utf8_general_ci) |
| Acceso a Datos | PDO con ATTR_EMULATE_PREPARES = false |
| Frontend | Bootstrap 5.3, Bootstrap Icons 1.10 |
| Efectos UI | TypewriterJS |
| Hash de Contraseñas | password_hash() con PASSWORD_DEFAULT (bcrypt) |
| Gestión de Sesión | $_SESSION nativo con wrapper estático |
3. Estructura del Proyecto
ds-php8-poo-login/
├── config/
│ ├── constants.php
│ └── database.php
├── classes/
│ ├── Auth.php
│ ├── Database.php
│ ├── Session.php
│ └── User.php
├── includes/
│ ├── header.php
│ └── footer.php
├── dashboard/
│ ├── index.php
│ └── users.php
├── index.php
├── login.php
├── logout.php
├── register.php
├── profile.php
├── style.css
├── database.sql
└── insert_data.sql
4. Patrones de Diseño y Arquitectura Aplicados
4.1 Patrón Singleton (implícito en sesión estática)
La clase Session expone métodos estáticos (set, get, delete, destroy, setFlash, getFlash) que actúan como fachada única sobre $_SESSION. Esto centraliza el acceso al estado de sesión y evita manipulación directa del array superglobal.
4.2 Patrón Data Mapper / Active Record parcial
La clase User encapsula todas las operaciones sobre la tabla usuarios, incluyendo su mapeo al modelo de dominio (rol_nombre, password, activo). Cada instancia abre su propia conexión PDO mediante (new Database())->connect() en el constructor.
4.3 Patrón Front Controller (implícito)
Cada archivo de la raíz (index.php, login.php, register.php, profile.php) actúa como punto de entrada que:
- Carga dependencias (
require_once). - Ejecuta guardias de autenticación (
Auth::requireLogin(),Auth::requireAdmin(),Auth::redirectIfLoggedIn()). - Procesa la lógica del formulario si
$_SERVER['REQUEST_METHOD'] === 'POST'. - Renderiza la vista mediante
includes/header.phpyincludes/footer.php.
4.4 Patrón Flash Message
Session::setFlash($type, $message) almacena un mensaje de un solo uso en $_SESSION['flash']. Session::getFlash() lo consume y elimina, garantizando la visualización única en la siguiente petición (patrón Post/Redirect/Get).
4.5 Patrón Helper estático (Auth)
La clase Auth implementa predicados de autorización (isLoggedIn, isAdmin, isUser) y guardias de acceso (requireLogin, requireAdmin, redirectIfLoggedIn).
4.6 Filtrado de salida y sanitización
Uso consistente de htmlspecialchars() en todas las vistas para prevenir XSS. Las consultas SQL utilizan PDO con parámetros vinculados para prevenir SQL Injection.
5. Modelo de Base de Datos
5.1 Diagrama relacional
roles (1) ────< (N) usuarios
roles.id→ PKusuarios.rol_id→ FK haciaroles.idconON DELETE RESTRICT
5.2 Tabla roles
| Columna | Tipo | Restricciones |
|---|---|---|
| id | INT | PK, AUTO_INCREMENT |
| nombre | VARCHAR(50) | NOT NULL, UNIQUE |
| descripcion | TEXT | — |
| creado_en | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP |
5.3 Tabla usuarios
| Columna | Tipo | Restricciones |
|---|---|---|
| id | INT | PK, AUTO_INCREMENT |
| nombre | VARCHAR(100) | NOT NULL |
| VARCHAR(100) | NOT NULL, UNIQUE | |
| password | VARCHAR(255) | NOT NULL (hash bcrypt) |
| rol_id | INT | NOT NULL, FK → roles(id) |
| activo | BOOLEAN | DEFAULT TRUE |
| creado_en | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP |
| actualizado_en | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE |
5.4 Índices
idx_usuarios_emailsobreusuarios(email)— optimizalogin()yemailExists().idx_usuarios_rol_idsobreusuarios(rol_id)— optimiza conteos por rol.
5.5 Datos Semilla
Roles:
| id | nombre | descripción |
|---|---|---|
| 1 | administrador | Privilegios totales |
| 2 | usuario | Permisos limitados |
| 3 | invitado | Permisos mínimos |
Usuarios demo (contraseña: admin123, hash bcrypt $2y$12$...):
admin@demo.com→ rol 1juan@demo.com,maria@demo.com,ana@demo.com→ rol 2carlos@demo.com→ rol 3
Observación técnica: El
insert_data.sqlinyecta IDs explícitos enroles, por lo que un reinicio del AUTO_INCREMENT no reasignará IDs distintos. Sin embargo, no se reiniciaAUTO_INCREMENTdeusuarios, lo cual es correcto para el flujo.

0 Comentarios