Carpeta controllers

This commit is contained in:
Axel Axt
2026-08-04 19:20:18 -03:00
parent f13321f90c
commit 24ae0e327f
14 changed files with 6971 additions and 0 deletions
+646
View File
@@ -0,0 +1,646 @@
<?php
// Requiere el modelo de logIn
require_once __DIR__ . '/../models/logInModel.php';
$loginmodel = new logInModel();
$opt = $_GET['opt'] ?? 'login_operador';
// Manejo de opt enviado por URL
switch ($opt) {
// LOGIN
case 'login':
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
if (isset($_SESSION['reset_autorizado'])) {
unset($_SESSION['reset_autorizado']);
}
ob_start();
require __DIR__ . '/../views/login/logInView.php';
return ob_get_clean();
}
$usuario = trim($_POST['usuario'] ?? ''); // Se almacenan los datos enviados por $_POST desde el form en las variables
$password = trim($_POST['password'] ?? '');
$errores = [];
// Validaciones para iniciar sesión
if ($usuario === '') {
$errores[] = "El usuario no puede estar vacío.";
} elseif (!preg_match('/^(?=.*[a-zA-Z])(?!.*[._]{2})[a-zA-Z0-9._]{5,30}$/', $usuario)) {
$errores[] = "El usuario debe tener 530 caracteres, incluir al menos una letra y solo usar letras, números, puntos o guiónes bajos no consecutivos.";
}
if ($password === '') {
$errores[] = "La contraseña no puede estar vacía.";
} elseif (strpos($password, ' ') !== false) {
$errores[] = "La contraseña no puede contener espacios.";
} elseif (!preg_match('/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{6,}$/', $password)) {
$errores[] = "La contraseña debe tener al menos una mayúscula, una minúscula y un número, y mínimo 6 caracteres.";
}
// Control de intentos de inicio de sesión
$maxIntentos = 3;
$tiempoBloqueo = 60; // segundos
if (!isset($_SESSION['login_intentos'])) {
$_SESSION['login_intentos'] = 0;
$_SESSION['login_ultimo_intento'] = time();
}
// Si pasó el tiempo, resetear
if (time() - $_SESSION['login_ultimo_intento'] > $tiempoBloqueo) {
$_SESSION['login_intentos'] = 0;
}
// Verificar bloqueo
if ($_SESSION['login_intentos'] >= $maxIntentos) {
$_SESSION['flash_error'] = "Demasiados intentos. Espere 1 minuto antes de volver a intentar.";
header("Location: index.php?opt=login_operador");
exit;
}
// Si existen errores de validación, se informan definiendo flash_error en el array asociativo $_SESSION
if (!empty($errores)) {
// Se suma el intento erroneo de inicio de sesión y se guarda el tiempo
$_SESSION['login_intentos']++;
$_SESSION['login_ultimo_intento'] = time();
$_SESSION['flash_error'] = implode('<br>', $errores); // Agrega un salto de linea entre cada error encontrado y los guarda en $_SESSION
header("Location: index.php?opt=login_operador");
exit;
}
// Si no existen errores, buscamos el usuario mediante logInModel
$user = $loginmodel->buscarPorUsuario($usuario);
if (!$user || !password_verify($password, $user['password'])) {
$_SESSION['login_intentos']++;
$_SESSION['login_ultimo_intento'] = time();
$_SESSION['flash_error'] = 'Usuario o contraseña incorrectos';
header("Location: index.php?opt=login_operador");
exit;
}
// Verificamos el rol del usuario para cargar la vista correspondiente
if ($user['rol'] === 'operador') {
// Se resetean los intentos
$_SESSION['login_intentos'] = 0;
$_SESSION['login_ultimo_intento'] = time();
$_SESSION['user'] = $user; // Se define $user dentro del array asociativo $_SESSION para tenerlo disponible en todo el sistema
header("Location: index.php?opt=inicio_operador");
exit;
} else if ($user['rol'] === 'admin') {
// Se resetean los intentos
$_SESSION['login_intentos'] = 0;
$_SESSION['login_ultimo_intento'] = time();
$_SESSION['user'] = $user; // Se define $user dentro del array asociativo $_SESSION para tenerlo disponible en todo el sistema
header("Location: index.php?opt=inicio_admin");
exit;
}
// HOME OPERADOR
case 'home_operador':
// Validar sesión
if (!isset($_SESSION['user'])) {
header("Location: index.php?opt=login_operador");
exit;
}
// Si el rol es admin, se redirigue al home_admin (en caso de ingresar por URL)
if ($_SESSION['user']['rol'] !== 'operador') {
header("Location: index.php?opt=home_admin");
exit;
}
// Se carga en caché el home operador y se envía el HTML
ob_start();
require __DIR__ . '/../views/login/homeOperadorView.php';
return ob_get_clean();
// HOME ADMIN
case 'home_admin':
// Validar sesión
if (!isset($_SESSION['user'])) {
header("Location: index.php?opt=login_admin");
exit;
}
// Si el rol es operador, se redirigue al home_operador (en caso de ingresar por URL)
if ($_SESSION['user']['rol'] !== 'admin') {
header("Location: index.php?opt=home_operador");
exit;
}
// Se carga en caché el home admin y se envía el HTML
ob_start();
require __DIR__ . '/../views/login/homeAdminView.php';
return ob_get_clean();
// INICIO OPERADOR
case 'inicio_operador':
// Validar sesión
if (!isset($_SESSION['user'])) {
header("Location: index.php?opt=login_operador");
exit;
}
// Si el rol es admin, se redirigue al inicio_admin (en caso de ingresar por URL)
if ($_SESSION['user']['rol'] !== 'operador') {
header("Location: index.php?opt=inicio_admin");
exit;
}
// Se carga en caché el inicio operador y se envía el HTML
ob_start();
require __DIR__ . '/../views/login/inicioOperadorView.php';
return ob_get_clean();
// INICIO ADMIN
case 'inicio_admin':
// Validar sesión
if (!isset($_SESSION['user'])) {
header("Location: index.php?opt=login_admin");
exit;
}
// Si el rol es operador, se redirigue al inicio_operador (en caso de ingresar por URL)
if ($_SESSION['user']['rol'] !== 'admin') {
header("Location: index.php?opt=inicio_operador");
exit;
}
// Calcular si mostrar alerta de backup (solo a admin)
if ($_SESSION['user']['rol'] === 'admin') {
require __DIR__ . '/../models/configuracionModel.php';
$configuracionmodel = new configuracionModel();
$fechaUltimoBackup = $configuracionmodel->obtenerFechaUltimoBackup();
if ($fechaUltimoBackup) {
$dias = (new DateTime($fechaUltimoBackup))->diff(new DateTime())->days;
if ($dias >= 7) {
header("Location: index.php?opt=generar_backup&from=inicio_admin&auto=1");
exit;
}
} else {
$ahora = time();
// Si nunca se mostró o ya pasó 1 hora
if (!isset($_SESSION['ultimo_aviso_backup']) || ($ahora - $_SESSION['ultimo_aviso_backup']) >= 3600) {
$_SESSION['flash_error'] = "No se encontraron copias de seguridad. Por favor, verifique.";
// Guardamos cuándo mostramos el mensaje
$_SESSION['ultimo_aviso_backup'] = $ahora;
}
}
}
// Se carga en caché el inicio admin y se envía el HTML
ob_start();
require __DIR__ . '/../views/login/inicioAdminView.php';
return ob_get_clean();
// LOGOUT
case 'logout':
session_unset(); // Libera las variables almacenadas en $_SESSION
session_destroy(); // Destruye la sesión del servidor
setcookie(session_name(), '', time() - 3600, '/'); // Borra la cookie en el navegaodor
header("Location: index.php?opt=login");
exit;
// CARGAR VISTA README (AYUDA)
case 'readme':
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
ob_start();
require __DIR__ . '/../views/ayudas/readMe.php';
return ob_get_clean();
}
// RECUPERACIÓN DE CUENTA
case 'recuperar_cuenta':
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
ob_start();
require __DIR__ . '/../views/login/recuperarCuentaView.php';
return ob_get_clean();
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!isset($_POST['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) { // Recorre todos los caracteres (siempre) y retorna true or false
$_SESSION['flash_error'] = 'Acción inválida.';
header('Location: index.php?opt=login');
exit;
}
// Requiero modelos necesarios
require_once __DIR__ . '/../models/usuarioModel.php';
$usuariomodel = new usuarioModel();
require_once __DIR__ . '/../models/logInModel.php';
$loginmodel = new logInModel();
require_once __DIR__ . '/../helpers/email_recuperar_cuenta.php';
$email = trim($_POST['email'] ?? $_SESSION['reset_email'] ?? '');
// Cooltime de envío de mails
if (isset($_SESSION['ultimo_envio_codigo'])) {
$segundosRestantes = 60 - (time() - $_SESSION['ultimo_envio_codigo']);
if ($segundosRestantes > 0) {
$_SESSION['flash_success'] = "Ya se envió un código recientemente. Espere {$segundosRestantes} segundos.";
header('Location: index.php?opt=verificar_codigo');
exit;
}
}
// Validación
if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
$_SESSION['flash_error'] = 'Email inválido';
header('Location: index.php?opt=recuperar_cuenta');
exit;
}
// Buscar usuario
$usuario = $usuariomodel->obtenerPorEmail($email);
// Siempre respuesta genérica (seguridad)
if (!$usuario || $usuario['rol'] !== 'admin') {
$_SESSION['flash_error'] = 'Si el correo ingresado es válido, recibirás un código de verificación.';
header('Location: index.php?opt=recuperar_cuenta');
exit;
}
// Generar código
$codigo = random_int(100000, 999999);
$codigoHash = password_hash($codigo, PASSWORD_DEFAULT);
$expira = date('Y-m-d H:i:s', strtotime('+10 minutes'));
// Invalidar códigos anteriores
if (!$loginmodel->invalidarPorUsuario($usuario['id'])) {
$_SESSION['flash_error'] = 'Ocurrió un error inesperado.';
header('Location: index.php?opt=recuperar_cuenta');
exit;
}
// Guardar nuevo código
if (!$loginmodel->crear([
'id_usuario' => $usuario['id'],
'codigo' => $codigoHash,
'expira_a' => $expira
])) {
$_SESSION['flash_error'] = 'Ocurrió un error inesperado.';
header('Location: index.php?opt=recuperar_cuenta');
exit;
}
// Guardar email en sesión (UX)
$_SESSION['reset_email'] = $email;
// Enviar mail
if (!enviarCodigoRecuperacion($email, $codigo)) {
$_SESSION['flash_error'] = 'Ocurrió un error inesperado al enviar el email.';
header('Location: index.php?opt=recuperar_cuenta');
exit;
}
$_SESSION['ultimo_envio_codigo'] = time();
// Redirigir a verificación
$_SESSION['flash_success'] = 'Si el correo ingresado es válido, recibirás un código de verificación.';
header('Location: index.php?opt=verificar_codigo');
exit;
}
case 'verificar_codigo':
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
if (empty($_SESSION['reset_email'])) {
header('Location: index.php?opt=recuperar_cuenta');
exit;
}
ob_start();
require __DIR__ . '/../views/login/verificarCodigoView.php';
return ob_get_clean();
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!isset($_POST['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
$_SESSION['flash_error'] = 'Acción inválida.';
header('Location: index.php?opt=login');
exit;
}
// Inicializamos contador
if (!isset($_SESSION['codigo_intentos'])) {
$_SESSION['codigo_intentos'] = 0;
}
// VALIDAMOS BLOQUEO ACTIVO
// SI EL BLOQUEO YA EXPIRÓ, RESETEAMOS
if (isset($_SESSION['codigo_bloqueado_hasta']) && time() >= $_SESSION['codigo_bloqueado_hasta']) {
unset($_SESSION['codigo_bloqueado_hasta']);
$_SESSION['codigo_intentos'] = 0;
}
// SI SIGUE BLOQUEADO
if (isset($_SESSION['codigo_bloqueado_hasta']) && time() < $_SESSION['codigo_bloqueado_hasta']) {
$segundos = $_SESSION['codigo_bloqueado_hasta'] - time();
$minutos = ceil($segundos / 60);
$_SESSION['flash_error'] = "Demasiados intentos fallidos. Espere {$minutos} minuto(s).";
header('Location: index.php?opt=verificar_codigo');
exit;
}
require_once __DIR__ . '/../models/usuarioModel.php';
$usuariomodel = new usuarioModel();
require_once __DIR__ . '/../models/logInModel.php';
$loginmodel = new logInModel();
$codigo = trim($_POST['codigo'] ?? '');
$email = $_SESSION['reset_email'] ?? null;
if (empty($codigo) || empty($email)) {
$_SESSION['flash_error'] = 'Debe ingresar el código.';
header('Location: index.php?opt=verificar_codigo');
exit;
}
$usuario = $usuariomodel->obtenerPorEmail($email);
if (!$usuario) {
$_SESSION['flash_error'] = 'Ocurrió un error.';
header('Location: index.php?opt=login');
exit;
}
$registro = $loginmodel->obtenerCodigoValido($usuario['id']);
if (!$registro) {
$_SESSION['codigo_intentos']++;
// BLOQUEO AUTOMÁTICO
if ($_SESSION['codigo_intentos'] >= 5) {
$_SESSION['codigo_bloqueado_hasta'] = time() + (15 * 60);
$_SESSION['flash_error'] = 'Demasiados intentos fallidos. Intente nuevamente en 15 minutos.';
} else {
$_SESSION['flash_error'] = 'El código no es válido.';
}
header('Location: index.php?opt=verificar_codigo');
exit;
}
// EXPIRACIÓN
if (strtotime($registro['expira_a']) < time()) {
$loginmodel->marcarComoUsado($registro['id']);
$_SESSION['flash_error'] = 'El código ha expirado.';
header('Location: index.php?opt=verificar_codigo');
exit;
}
// VALIDACIÓN HASH
if (!password_verify($codigo, $registro['codigo'])) {
$_SESSION['codigo_intentos']++;
// BLOQUEAR SI LLEGA AL LÍMITE
if ($_SESSION['codigo_intentos'] >= 5) {
$_SESSION['codigo_bloqueado_hasta'] = time() + (15 * 60);
$_SESSION['flash_error'] = 'Demasiados intentos fallidos. Intente nuevamente en 15 minutos.';
} else {
$_SESSION['flash_error'] = 'Código incorrecto.';
}
header('Location: index.php?opt=verificar_codigo');
exit;
}
// ÉXITO
$loginmodel->marcarComoUsado($registro['id']);
$_SESSION['reset_autorizado'] = $usuario['id'];
// Limpiar protección
unset($_SESSION['codigo_intentos']);
unset($_SESSION['codigo_bloqueado_hasta']);
header('Location: index.php?opt=restablecer_contrasenia');
exit;
}
// RESTABLECER CONTRASENIA
case 'restablecer_contrasenia':
if (!isset($_SESSION['reset_autorizado'])) {
header('Location: index.php?opt=login');
exit;
}
// MOSTRAR VISTA
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
ob_start();
require __DIR__ . '/../views/login/restablecerContraseniaView.php';
return ob_get_clean();
}
// GUARDAR NUEVA CONTRASENIA
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!isset($_POST['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
$_SESSION['flash_error'] = 'Acción inválida.';
header('Location: index.php?opt=login');
exit;
}
require_once __DIR__ . '/../models/usuarioModel.php';
$usuariomodel = new usuarioModel();
$password = trim($_POST['password'] ?? '');
$confirmar = trim($_POST['confirmar_password'] ?? '');
$errores = [];
// VALIDACIONES
if (empty($password) || empty($confirmar)) {
$_SESSION['flash_error'] = 'Complete todos los campos.';
header('Location: index.php?opt=restablecer_contrasenia');
exit;
}
// VALIDACIONES DE CONTRASENIA
if ($password === '') {
$errores[] = "La contraseña no puede estar vacía.";
} elseif (strpos($password, ' ') !== false) {
$errores[] = "La contraseña no puede contener espacios.";
} elseif (!preg_match('/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{6,}$/', $password)) {
$errores[] = "La contraseña debe tener al menos una mayúscula, una minúscula y un número, y mínimo 6 caracteres.";
}
if ($password !== $confirmar) {
$_SESSION['flash_error'] = 'Las contraseñas no coinciden.';
header('Location: index.php?opt=restablecer_contrasenia');
exit;
}
if (!empty($errores)) {
$_SESSION['flash_error'] = implode('<br>', $errores);
header("Location: index.php?opt=restablecer_contrasenia");
exit;
}
// HASH
$passwordHash = password_hash($password, PASSWORD_DEFAULT);
// ACTUALIZAR
if (!$usuariomodel->actualizarContrasenia (
$_SESSION['reset_autorizado'], $passwordHash
)) {
$_SESSION['flash_error'] = 'Ocurrió un error inesperado.';
header('Location: index.php?opt=restablecer_contrasenia');
exit;
}
// INVALIDAMOS TODOS LOS CODIGOS (PARA PREVENIR)
$loginmodel->invalidarPorUsuario($_SESSION['reset_autorizado']);
// Limpiar sesión temporal
unset($_SESSION['reset_autorizado']);
unset($_SESSION['reset_email']);
// REGENERACION DE SESSION ID
session_regenerate_id(true);
$_SESSION['flash_success'] = 'Contraseña actualizada correctamente.';
header('Location: index.php?opt=login');
exit;
}
// DEFAULT (404)
default:
ob_start();
require __DIR__ . '/../views/404View.php';
return ob_get_clean();
}