495 lines
18 KiB
PHP
495 lines
18 KiB
PHP
<?php
|
|
|
|
// Validacion de token
|
|
|
|
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=inicio_operador');
|
|
exit;
|
|
}
|
|
}
|
|
|
|
// Requiero helper que contiene métodos para encriptar y desencriptar contraseñas
|
|
|
|
require_once __DIR__ . '/../helpers/crypto.php';
|
|
|
|
// Requiero modelo de configuración
|
|
|
|
require __DIR__ . '/../models/configuracionModel.php';
|
|
$configuracionmodel = new configuracionModel();
|
|
|
|
// Validar sesión
|
|
|
|
if (!isset($_SESSION['user'])) {
|
|
header("Location: index.php?opt=login_operador");
|
|
exit;
|
|
}
|
|
|
|
$user = $_SESSION['user']; // Defino el array del usuario dentro de una variable
|
|
$rol = $user['rol']; // Defino el rol dentro de la variable
|
|
$esAdmin = ($rol === 'admin'); // Variable booleana, true = admin
|
|
|
|
// Verifico rol del usuarios (solo se permite admin)
|
|
|
|
if (!$esAdmin) {
|
|
header("Location: index.php?opt=inicio_operador");
|
|
exit;
|
|
}
|
|
|
|
$opt = $_GET['opt'] ?? null;
|
|
|
|
// Manejo de opt
|
|
|
|
switch ($opt) {
|
|
|
|
// OBTENER CONFIGURACIÓN
|
|
|
|
case 'configuracion':
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
|
|
|
$configuracion = $configuracionmodel->obtenerConfiguracion();
|
|
|
|
// Desencriptación de contraseña emisor
|
|
|
|
if (isset($configuracion['contrasenia_emisor'])) {
|
|
$configuracion['contrasenia_emisor_formateada'] = decryptData($configuracion['contrasenia_emisor']);
|
|
} else {
|
|
$configuracion['contrasenia_emisor_formateada'] = 'Sin Setear';
|
|
}
|
|
|
|
// Saneamiento de email emisor
|
|
|
|
if (isset($configuracion['email_emisor'])) {
|
|
$configuracion['email_emisor'] = $configuracion['email_emisor'];
|
|
} else {
|
|
$configuracion['email_emisor'] = 'Sin Setear';
|
|
}
|
|
|
|
// Validaciones
|
|
|
|
if (empty($configuracion)) {
|
|
$_SESSION['flash_error'] = 'Ocurrió un error al cargar la configuración.';
|
|
header("Location: index.php?opt=configuracion");
|
|
exit;
|
|
}
|
|
|
|
// Saneamiento de fecha
|
|
|
|
if (!empty($configuracion['inicio_act'])) {
|
|
$dt = new DateTime($configuracion['inicio_act']);
|
|
$configuracion['inicio_act_formateada'] = $dt->format('d/m/Y');
|
|
} else {
|
|
$configuracion['inicio_act_formateada'] = '-';
|
|
}
|
|
|
|
ob_start();
|
|
require_once __DIR__ . '/../views/configuracion/configuracionView.php';
|
|
return ob_get_clean();
|
|
}
|
|
|
|
// ACTUALIZAR CONFIGURACIÓN
|
|
|
|
case 'actualizar_config':
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
|
|
$configuracion = [
|
|
|
|
'nombre' => trim($_POST['nombre'] ?? ''),
|
|
'direccion' => trim($_POST['direccion'] ?? ''),
|
|
'ciudad' => trim($_POST['ciudad'] ?? ''),
|
|
'codigo_postal' => trim($_POST['codigo_postal'] ?? ''),
|
|
'provincia' => trim($_POST['provincia'] ?? ''),
|
|
'telefono' => trim($_POST['telefono'] ?? ''),
|
|
'email' => trim($_POST['email'] ?? ''),
|
|
'cond_iva' => trim($_POST['cond_iva'] ?? 'responsable_inscripto'),
|
|
'cuit' => ($_POST['cuit_1'] ?? '') . ($_POST['cuit_2'] ?? '') . ($_POST['cuit_3'] ?? ''),
|
|
'iva' => $_POST['iva'] ?? 21,
|
|
'hora_apertura_maniana' => trim($_POST['hora_apertura_maniana'] ?? ''),
|
|
'hora_cierre_maniana' => trim($_POST['hora_cierre_maniana'] ?? ''),
|
|
'hora_apertura_tarde' => trim($_POST['hora_apertura_tarde'] ?? ''),
|
|
'hora_cierre_tarde' => trim($_POST['hora_cierre_tarde'] ?? ''),
|
|
'mail_automatico' => isset($_POST['mail_automatico']) ? 1 : 0,
|
|
'cargo_cancelacion_servicio' => $_POST['cargo_cancelacion_servicio'] ?? 0,
|
|
'email_emisor' => trim($_POST['email_emisor'] ?? ''),
|
|
'contrasenia_emisor' => trim($_POST['contrasenia_emisor'] ?? ''),
|
|
];
|
|
|
|
$errores = [];
|
|
|
|
// Validaciones
|
|
|
|
// NOMBRE
|
|
|
|
if ($configuracion['nombre'] === '') {
|
|
$errores[] = "El nombre no puede estar vacío.";
|
|
} else if (!preg_match('/^[A-Za-zÁÉÍÓÚáéíóú0-9\s\.\-]{2,100}$/', $configuracion['nombre'])) {
|
|
$errores[] = "El nombre contiene caracteres inválidos.";
|
|
} else if (strlen($configuracion['nombre']) < 2) {
|
|
$errores[] = "El nombre debe tener al menos 2 caracteres.";
|
|
} else if (strlen($configuracion['nombre']) > 50) {
|
|
$errores[] = "El nombre no puede superar los 50 caracteres.";
|
|
}
|
|
|
|
// DIRECCIÓN
|
|
|
|
if ($configuracion['direccion'] === '') {
|
|
$errores[] = "La dirección no puede estar vacía.";
|
|
} else if (strlen($configuracion['direccion']) < 3) {
|
|
$errores[] = "La dirección debe tener al menos 3 caracteres.";
|
|
} else if (strlen($configuracion['direccion']) > 100) {
|
|
$errores[] = "La dirección no puede superar los 100 caracteres.";
|
|
}
|
|
|
|
// CIUDAD
|
|
|
|
if ($configuracion['ciudad'] === '') {
|
|
$errores[] = "La ciudad no puede estar vacía.";
|
|
} else if (!preg_match('/^[A-Za-zÁÉÍÓÚáéíóúñÑ\s]{2,100}$/', $configuracion['ciudad'])) {
|
|
$errores[] = "La ciudad solo puede contener letras y espacios.";
|
|
}
|
|
|
|
// CODIGO POSTAL
|
|
|
|
if ($configuracion['codigo_postal'] === '') {
|
|
$errores[] = "El código postal no puede estar vacío.";
|
|
} else if (!preg_match('/^[0-9]{4}$/', $configuracion['codigo_postal'])) {
|
|
$errores[] = "El código postal debe tener 4 dígitos.";
|
|
}
|
|
|
|
// PROVINCIA
|
|
|
|
if ($configuracion['provincia'] === '') {
|
|
$errores[] = "La provincia no puede estar vacía.";
|
|
} else if (!preg_match('/^[A-Za-zÁÉÍÓÚáéíóúñÑ\s]{2,100}$/', $configuracion['provincia'])) {
|
|
$errores[] = "La provincia contiene caracteres inválidos.";
|
|
}
|
|
|
|
// TELÉFONO
|
|
|
|
if ($configuracion['telefono'] === '') {
|
|
$errores[] = "El teléfono no puede estar vacío.";
|
|
} else if (!preg_match('/^[0-9]{10}$/', $configuracion['telefono'])) {
|
|
$errores[] = "El teléfono debe tener 10 dígitos.";
|
|
}
|
|
|
|
// EMAIL
|
|
|
|
if ($configuracion['email'] === '') {
|
|
$errores[] = "El email no puede estar vacío.";
|
|
} else if (!filter_var($configuracion['email'], FILTER_VALIDATE_EMAIL)) {
|
|
$errores[] = "Formato de email inválido.";
|
|
} else if (strlen($configuracion['email']) > 100) {
|
|
$errores[] = "El email no puede superar los 100 caracteres.";
|
|
}
|
|
|
|
// CONDICIÓN_IVA
|
|
|
|
$condicionesValidas = [
|
|
'consumidor_final',
|
|
'responsable_inscripto',
|
|
'monotributo'
|
|
];
|
|
|
|
if (!in_array($configuracion['cond_iva'], $condicionesValidas)) {
|
|
$errores[] = "Condición de IVA inválida.";
|
|
}
|
|
|
|
// CUIT
|
|
|
|
if (!preg_match('/^\d{10,11}$/', $configuracion['cuit'])) {
|
|
$errores[] = 'CUIT inválido. Debe contener solo números.';
|
|
}
|
|
|
|
// IVA
|
|
|
|
if (!is_numeric($configuracion['iva'])) {
|
|
$errores[] = "El IVA debe ser numérico.";
|
|
}
|
|
|
|
// HORA DE APERTURA Y CIERRE
|
|
|
|
if ($configuracion['hora_apertura_maniana'] && $configuracion['hora_cierre_maniana']) {
|
|
|
|
if ($configuracion['hora_apertura_maniana'] >= $configuracion['hora_cierre_maniana']) {
|
|
$errores[] = "El horario de apertura debe ser menor al de cierre.";
|
|
}
|
|
|
|
}
|
|
|
|
if ($configuracion['hora_apertura_tarde'] && $configuracion['hora_cierre_tarde']) {
|
|
|
|
if ($configuracion['hora_apertura_tarde'] >= $configuracion['hora_cierre_tarde']) {
|
|
$errores[] = "El horario de apertura debe ser menor al de cierre.";
|
|
}
|
|
|
|
}
|
|
|
|
// CARGO POR CANCELACIÓN DE SERVICIO
|
|
|
|
if (!is_numeric($configuracion['cargo_cancelacion_servicio'])) {
|
|
$errores[] = "El cargo por cancelación debe ser numérico.";
|
|
}
|
|
|
|
// EMAIL EMISOR
|
|
|
|
if ($configuracion['email_emisor'] === '') {
|
|
$errores[] = "El email no puede estar vacío.";
|
|
} else if (!filter_var($configuracion['email_emisor'], FILTER_VALIDATE_EMAIL)) {
|
|
$errores[] = "Formato de email inválido.";
|
|
} else if (strlen($configuracion['email_emisor']) > 100) {
|
|
$errores[] = "El email no puede superar los 100 caracteres.";
|
|
}
|
|
|
|
// CONTRASEÑA EMISOR
|
|
|
|
if (strlen($configuracion['contrasenia_emisor']) > 100) {
|
|
$errores[] = "Contraseña demasiado larga.";
|
|
}
|
|
|
|
if (!empty($errores)) {
|
|
$_SESSION['flash_error'] = implode('<br>', $errores); // Se guarda en $_SESSION el error
|
|
header("Location: index.php?opt=configuracion");
|
|
exit;
|
|
}
|
|
|
|
// ENCRIPTACION DE CONTRASEÑA
|
|
|
|
if ($configuracion['contrasenia_emisor'] !== '') {
|
|
$passLimpia = str_replace(' ', '', $configuracion['contrasenia_emisor']);
|
|
$configuracion['contrasenia_emisor'] = encryptData($passLimpia);
|
|
}
|
|
|
|
// Actualizamos datos de configuración
|
|
|
|
if ($configuracionmodel->actualizarConfiguracion($configuracion)) {
|
|
$_SESSION['flash_success'] = 'Configuración actualizada correctamente.';
|
|
header("Location: index.php?opt=configuracion");
|
|
exit;
|
|
} else {
|
|
$_SESSION['flash_error'] = 'Error al actualizar la configuración.';
|
|
header("Location: index.php?opt=configuracion");
|
|
exit;
|
|
}
|
|
}
|
|
|
|
// GENERAR BACKUP
|
|
|
|
case 'generar_backup':
|
|
|
|
// Obtenemos desde donde viene la petición (puede ser backup automático)
|
|
|
|
$return = $_GET['from'] ?? 'backups';
|
|
|
|
$backupDir = $_ENV['BACKUP_PATH'] ?? (__DIR__ . '/../backups/');
|
|
|
|
$fecha = date('Y-m-d_H-i-s');
|
|
$archivo = "backup_$fecha.sql"; // Generación de nombre de archivo con extensión
|
|
$rutaBackup = $backupDir . $archivo; // Generación de ruta completa de archivo backup
|
|
|
|
// Datos de conexión
|
|
|
|
$rutaBackup = escapeshellarg($rutaBackup); // Permite omitir espacios o caracteres no deseados (puede romper ruta o comando)
|
|
$host = escapeshellarg($_ENV['DB_HOST']);
|
|
$usuario = escapeshellarg($_ENV['DB_USER']);
|
|
$database = escapeshellarg($_ENV['DB_NAME']);
|
|
$password = escapeshellarg($_ENV['DB_PASSWORD']);
|
|
|
|
// Comando pg_dump
|
|
|
|
$comando = "PGPASSWORD=$password pg_dump --clean --if-exists --no-owner -h $host -U $usuario -d $database > $rutaBackup"; // Guardamos el comando a ejecutar mediante pg_dump
|
|
|
|
exec($comando, $output, $resultado); // Lo ejecutamos
|
|
|
|
if ($resultado === 0) { // Entra al if solo si el (exec) dio como resultado 0 (éxito) en la variable $resultado
|
|
|
|
// Limitar cantidad de backups
|
|
|
|
$maxBackups = 4;
|
|
|
|
$archivos = glob($backupDir . '*.sql'); // Permite obtener todos los archivos ubicados en esa ruta
|
|
|
|
if (count($archivos) > $maxBackups) { // Contamos la cantidad de archivos (comparando con la cantidad máxima definida)
|
|
|
|
usort($archivos, function ($a, $b) {
|
|
return filemtime($a) - filemtime($b);
|
|
}); // Se ordenan en base a la fecha de modificación de mas antiguo a mas nuevo
|
|
|
|
while (count($archivos) > $maxBackups) {
|
|
$archivoEliminar = array_shift($archivos); // Se elimina el archivo del array
|
|
unlink($archivoEliminar); // Se elimina fisicamente el archivo
|
|
}
|
|
}
|
|
|
|
if (isset($_GET['auto'])) {
|
|
|
|
$_SESSION['flash_success'] = "Copia de seguridad automática generada con éxito.";
|
|
} else {
|
|
|
|
$_SESSION['flash_success'] = "Backup generado correctamente.";
|
|
}
|
|
|
|
} else {
|
|
|
|
$_SESSION['flash_error'] = "Error al generar el backup.";
|
|
}
|
|
|
|
header("Location: index.php?opt=$return");
|
|
exit;
|
|
|
|
// LISTAR BACKUPS
|
|
|
|
case 'backups':
|
|
|
|
$backupDir = $_ENV['BACKUP_PATH'] ?? (__DIR__ . '/../backups/');
|
|
|
|
$archivos = glob($backupDir . '*.sql');
|
|
|
|
$backups = [];
|
|
$totalSize = 0;
|
|
|
|
$ultimoBackup = null;
|
|
|
|
if ($archivos) {
|
|
|
|
usort($archivos, function ($a, $b) {
|
|
return filemtime($b) <=> filemtime($a);
|
|
});
|
|
|
|
$ultimoBackup = date('d/m/Y H:i', filemtime($archivos[0])); // Guardamos el archivo mas reciente para informar en la vista
|
|
|
|
foreach ($archivos as $archivo) {
|
|
|
|
$size = filesize($archivo); // Obtenemos el tamaño total del archivo
|
|
|
|
$backups[] = [
|
|
'nombre' => basename($archivo), // Obtenemos nombre de archivo
|
|
'fecha' => date('d/m/Y H:i', filemtime($archivo)), // Obtenemos la fecha del archivo
|
|
'size' => round($size / 1024, 2) . ' KB' // Obtenemos el tamaño del archivo en KB
|
|
];
|
|
|
|
$totalSize += $size; // Acumulamos el tamaño de los archivos para obtener el total
|
|
}
|
|
}
|
|
|
|
$totalSize = round($totalSize / 1024 / 1024, 2); // Total utilizado en MB
|
|
|
|
ob_start();
|
|
require __DIR__ . '/../views/configuracion/buckupsView.php';
|
|
return ob_get_clean();
|
|
|
|
// DESCARGAR BACKUP
|
|
|
|
case 'descargar_backup':
|
|
|
|
$file = basename($_GET['file']);
|
|
|
|
$backupDir = $_ENV['BACKUP_PATH'] ?? (__DIR__ . '/../backups/');
|
|
$ruta = $backupDir . $file;
|
|
|
|
if (!file_exists($ruta)) {
|
|
header("Location: index.php?opt=backups");
|
|
exit;
|
|
}
|
|
|
|
header('Content-Type: application/sql'); // Indica el tipo de contenido del archivo (SQL en este caso)
|
|
header('Content-Disposition: attachment; filename="' . $file . '"'); // Fuerza la descarga del archivo en lugar de mostrarlo en el navegador y define el nombre con el que se va a guardar
|
|
header('Content-Length: ' . filesize($ruta)); // Informa el tamaño del archivo (mejora la descarga/progreso)
|
|
|
|
readfile($ruta); // Envía el contenido del archivo al navegador
|
|
exit;
|
|
|
|
// ELIMINAR BACKUP
|
|
|
|
case 'eliminar_backup':
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
|
|
$backupDir = $_ENV['BACKUP_PATH'] ?? (__DIR__ . '/../backups/');
|
|
|
|
$archivo = basename($_POST['file']); // Evita rutas maliciosas
|
|
|
|
$rutaArchivo = $backupDir . $archivo;
|
|
|
|
if (file_exists($rutaArchivo)) {
|
|
|
|
unlink($rutaArchivo);
|
|
|
|
$_SESSION['flash_success'] = "Backup eliminado correctamente.";
|
|
|
|
} else {
|
|
|
|
$_SESSION['flash_error'] = "El archivo no existe.";
|
|
|
|
}
|
|
|
|
header("Location: index.php?opt=backups");
|
|
exit;
|
|
}
|
|
|
|
// RESTAURAR BACKUP
|
|
|
|
case 'restaurar_backup':
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
|
|
$backupDir = $_ENV['BACKUP_PATH'] ?? (__DIR__ . '/../backups/');
|
|
|
|
$archivo = basename($_POST['file']);
|
|
$rutaBackup = $backupDir . $archivo;
|
|
|
|
if (!file_exists($rutaBackup)) {
|
|
|
|
$_SESSION['flash_error'] = "El archivo de backup no existe.";
|
|
header("Location: index.php?opt=backups");
|
|
exit;
|
|
|
|
}
|
|
|
|
$host = escapeshellarg($_ENV['DB_HOST']);
|
|
$usuario = escapeshellarg($_ENV['DB_USER']);
|
|
$database = escapeshellarg($_ENV['DB_NAME']);
|
|
$password = escapeshellarg($_ENV['DB_PASSWORD']);
|
|
|
|
// 1. BACKUP AUTOMÁTICO PREVIO
|
|
|
|
$backupSeguridad = $backupDir . 'auto_pre_restore_' . date('Y-m-d_H-i-s') . '.sql';
|
|
$backupSeguridadEscaped = escapeshellarg($backupSeguridad);
|
|
|
|
$comandoBackup = "PGPASSWORD=$password pg_dump --clean --if-exists --no-owner -h $host -U $usuario -d $database > $backupSeguridadEscaped";
|
|
|
|
exec($comandoBackup, $outBackup, $resultadoBackup);
|
|
|
|
if ($resultadoBackup !== 0) {
|
|
|
|
$_SESSION['flash_error'] = "No se pudo crear el backup de seguridad antes de restaurar.";
|
|
header("Location: index.php?opt=backups");
|
|
exit;
|
|
|
|
}
|
|
|
|
// 2. RESTAURAR COPIA DE SEGURIDAD SELECCIONADA
|
|
|
|
$rutaBackupEscaped = escapeshellarg($rutaBackup);
|
|
|
|
$comandoRestore = "PGPASSWORD=$password psql -h $host -U $usuario -d $database < $rutaBackupEscaped";
|
|
|
|
exec($comandoRestore, $output, $resultadoRestore);
|
|
|
|
if ($resultadoRestore === 0) {
|
|
|
|
$_SESSION['flash_success'] = "Backup restaurado correctamente. Se creó una copia de seguridad previa.";
|
|
|
|
} else {
|
|
|
|
$_SESSION['flash_error'] = "Error al restaurar el backup.";
|
|
|
|
}
|
|
|
|
header("Location: index.php?opt=backups");
|
|
exit;
|
|
}
|
|
} |