Files
whatsapp/migrar_passwords_bd.php
2026-01-12 11:06:43 -05:00

422 lines
18 KiB
PHP

<?php
/**
* Migración del Sistema de Contraseñas a Base de Datos
* Fecha: 4 de enero de 2026
*/
require_once 'config/config.php';
// Solo permitir acceso desde localhost por seguridad
$allowedIPs = ['127.0.0.1', '::1', 'localhost'];
$clientIP = $_SERVER['REMOTE_ADDR'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? 'unknown';
if (!in_array($clientIP, $allowedIPs) && $clientIP !== 'unknown') {
die("❌ Acceso denegado. Esta utilidad solo puede ejecutarse desde localhost por seguridad.");
}
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🔄 Migrar Contraseñas a Base de Datos</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #25D366 0%, #128C7E 100%);
color: #333;
margin: 0;
padding: 20px;
min-height: 100vh;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 40px;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
}
h1 {
color: #25D366;
text-align: center;
margin-bottom: 30px;
}
.info-box {
background: #e8f5e8;
padding: 20px;
border-left: 5px solid #25D366;
margin: 20px 0;
border-radius: 5px;
}
.warning-box {
background: #fff3cd;
padding: 20px;
border-left: 5px solid #ffc107;
margin: 20px 0;
border-radius: 5px;
}
.error-box {
background: #f8d7da;
padding: 20px;
border-left: 5px solid #dc3545;
margin: 20px 0;
border-radius: 5px;
}
.btn {
background: #25D366;
color: white;
padding: 12px 30px;
border: none;
border-radius: 8px;
font-size: 16px;
cursor: pointer;
width: 100%;
margin: 10px 0;
}
.btn:hover {
background: #1aa347;
}
.btn-danger {
background: #dc3545;
}
.btn-danger:hover {
background: #c82333;
}
.progress-box {
background: #f8f9fa;
padding: 15px;
border-radius: 8px;
margin: 20px 0;
border: 1px solid #dee2e6;
}
code {
background: #f8f9fa;
padding: 2px 6px;
border-radius: 3px;
font-family: monospace;
}
</style>
</head>
<body>
<div class="container">
<h1>🔄 Migración: Contraseñas a Base de Datos</h1>
<div class="warning-box">
<strong>⚡ Sistema de Migración:</strong>
<p>Esta herramienta migrará el sistema de contraseñas desde archivos de configuración a la base de datos, creando un sistema unificado y más seguro.</p>
</div>
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
if ($_POST['action'] === 'migrate_system') {
echo '<div class="progress-box"><h4>🚀 Iniciando Migración...</h4>';
try {
// 1. Conectar a la base de datos
echo '<p>✅ 1. Conectando a la base de datos...</p>';
$pdo = new PDO(
"mysql:host=" . DB_HOST . ";port=" . DB_PORT . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET,
DB_USER,
DB_PASS,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]
);
// 2. Crear tabla de administradores
echo '<p>✅ 2. Creando tabla de administradores...</p>';
$createAdminTable = "
CREATE TABLE IF NOT EXISTS admin_users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
email VARCHAR(100),
full_name VARCHAR(100),
is_active TINYINT(1) DEFAULT 1,
last_login DATETIME NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_username (username),
INDEX idx_active (is_active)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
";
$pdo->exec($createAdminTable);
// 3. Migrar contraseña actual del config
echo '<p>✅ 3. Migrando contraseña actual...</p>';
$currentUsername = ADMIN_USERNAME;
$currentPasswordHash = ADMIN_PASSWORD;
// Verificar si ya existe el admin
$checkAdmin = $pdo->prepare("SELECT id FROM admin_users WHERE username = ?");
$checkAdmin->execute([$currentUsername]);
if (!$checkAdmin->fetch()) {
$insertAdmin = $pdo->prepare("
INSERT INTO admin_users (username, password_hash, full_name, email)
VALUES (?, ?, ?, ?)
");
$insertAdmin->execute([
$currentUsername,
$currentPasswordHash,
'Administrador Principal',
'admin@u-site.app'
]);
echo '<p>✅ Usuario administrador migrado exitosamente</p>';
} else {
echo '<p>⚠️ Usuario administrador ya existe en BD</p>';
}
// 4. Crear tabla de configuración si no existe
echo '<p>✅ 4. Verificando tabla de configuración...</p>';
$createConfigTable = "
CREATE TABLE IF NOT EXISTS system_config (
id INT PRIMARY KEY AUTO_INCREMENT,
config_key VARCHAR(100) UNIQUE NOT NULL,
config_value TEXT,
config_type VARCHAR(50) DEFAULT 'string',
description TEXT,
is_encrypted TINYINT(1) DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_config_key (config_key)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
";
$pdo->exec($createConfigTable);
// 5. Actualizar configuraciones existentes
echo '<p>✅ 5. Configurando sistema...</p>';
$systemConfigs = [
['password_system_migrated', '1', 'boolean', 'Indica si el sistema de contraseñas fue migrado a BD'],
['login_attempts_max', MAX_LOGIN_ATTEMPTS, 'integer', 'Número máximo de intentos de login'],
['login_lockout_time', LOGIN_LOCKOUT_TIME, 'integer', 'Tiempo de bloqueo en segundos'],
['session_timeout', SESSION_TIMEOUT, 'integer', 'Timeout de sesión en segundos'],
['system_version', '2.0.0', 'string', 'Versión del sistema con BD']
];
foreach ($systemConfigs as $config) {
$stmt = $pdo->prepare("
INSERT INTO system_config (config_key, config_value, config_type, description)
VALUES (?, ?, ?, ?)
ON DUPLICATE KEY UPDATE config_value = VALUES(config_value)
");
$stmt->execute($config);
}
echo '<p>✅ 6. Creando funciones de autenticación...</p>';
echo '</div>';
echo '<div class="info-box">';
echo '<h4>🎉 ¡Migración Completada Exitosamente!</h4>';
echo '<p><strong>Cambios realizados:</strong></p>';
echo '<ul>';
echo '<li>✅ Tabla <code>admin_users</code> creada</li>';
echo '<li>✅ Contraseña actual migrada a BD</li>';
echo '<li>✅ Configuración del sistema actualizada</li>';
echo '<li>✅ Sistema preparado para funcionar con BD</li>';
echo '</ul>';
echo '<p><strong>Próximo paso:</strong> Actualizar el código para usar la nueva estructura</p>';
echo '</div>';
} catch (Exception $e) {
echo '</div>';
echo '<div class="error-box">❌ <strong>Error en la migración:</strong> ' . $e->getMessage() . '</div>';
}
}
if ($_POST['action'] === 'update_system_files') {
echo '<div class="progress-box"><h4>🔧 Actualizando archivos del sistema...</h4>';
try {
// Actualizar config.php para incluir funciones de BD
echo '<p>✅ 1. Actualizando config.php...</p>';
$newConfigFunctions = '
// Funciones de autenticación con base de datos
function getAdminByUsername($username) {
try {
$pdo = new PDO(
"mysql:host=" . DB_HOST . ";port=" . DB_PORT . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET,
DB_USER,
DB_PASS,
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]
);
$stmt = $pdo->prepare("SELECT * FROM admin_users WHERE username = ? AND is_active = 1");
$stmt->execute([$username]);
return $stmt->fetch();
} catch (Exception $e) {
error_log("Error getting admin user: " . $e->getMessage());
return false;
}
}
function verifyAdminPassword($username, $password) {
$admin = getAdminByUsername($username);
if ($admin && password_verify($password, $admin["password_hash"])) {
// Actualizar último login
updateAdminLastLogin($admin["id"]);
return $admin;
}
return false;
}
function updateAdminLastLogin($adminId) {
try {
$pdo = new PDO(
"mysql:host=" . DB_HOST . ";port=" . DB_PORT . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET,
DB_USER,
DB_PASS,
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
$stmt = $pdo->prepare("UPDATE admin_users SET last_login = NOW() WHERE id = ?");
$stmt->execute([$adminId]);
} catch (Exception $e) {
error_log("Error updating last login: " . $e->getMessage());
}
}
function updateAdminPassword($username, $newPassword) {
try {
$pdo = new PDO(
"mysql:host=" . DB_HOST . ";port=" . DB_PORT . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET,
DB_USER,
DB_PASS,
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
$newHash = password_hash($newPassword, PASSWORD_DEFAULT);
$stmt = $pdo->prepare("UPDATE admin_users SET password_hash = ?, updated_at = NOW() WHERE username = ?");
return $stmt->execute([$newHash, $username]);
} catch (Exception $e) {
error_log("Error updating password: " . $e->getMessage());
return false;
}
}
function isPasswordSystemMigrated() {
$config = getConfigFromDB("password_system_migrated");
return $config === "1";
}
// Función de autenticación unificada (retrocompatible)
function authenticateAdmin($username, $password) {
if (isPasswordSystemMigrated()) {
return verifyAdminPassword($username, $password);
} else {
// Fallback al sistema anterior
if ($username === ADMIN_USERNAME && password_verify($password, ADMIN_PASSWORD)) {
return ["id" => 1, "username" => $username, "full_name" => "Admin"];
}
}
return false;
}
';
// Leer config actual y agregar las nuevas funciones
$configFile = 'config/config.php';
$configContent = file_get_contents($configFile);
// Agregar las nuevas funciones antes del cierre de PHP
$configContent = str_replace('?>', $newConfigFunctions . '?>', $configContent);
file_put_contents($configFile, $configContent);
echo '<p>✅ 2. config.php actualizado con funciones de BD</p>';
echo '</div>';
echo '<div class="info-box">';
echo '<h4>🔧 Archivos actualizados exitosamente!</h4>';
echo '<p>El sistema ahora soporta contraseñas en base de datos.</p>';
echo '<p><strong>Recarga esta página</strong> para usar las nuevas funciones.</p>';
echo '</div>';
} catch (Exception $e) {
echo '</div>';
echo '<div class="error-box">❌ <strong>Error actualizando archivos:</strong> ' . $e->getMessage() . '</div>';
}
}
}
// Verificar estado actual
try {
$pdo = new PDO(
"mysql:host=" . DB_HOST . ";port=" . DB_PORT . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET,
DB_USER,
DB_PASS,
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
// Verificar si existe la tabla admin_users
$checkTable = $pdo->query("SHOW TABLES LIKE 'admin_users'");
$tableExists = $checkTable->rowCount() > 0;
$isMigrated = false;
if ($tableExists) {
$configCheck = getConfigFromDB('password_system_migrated');
$isMigrated = ($configCheck === '1');
}
echo '<div class="progress-box">';
echo '<h3>📊 Estado Actual del Sistema</h3>';
echo '<p><strong>Base de datos:</strong> ✅ Conectada (' . DB_NAME . ')</p>';
echo '<p><strong>Tabla admin_users:</strong> ' . ($tableExists ? '✅ Existe' : '❌ No existe') . '</p>';
echo '<p><strong>Sistema migrado:</strong> ' . ($isMigrated ? '✅ Sí' : '❌ No') . '</p>';
echo '<p><strong>Usuario actual:</strong> ' . ADMIN_USERNAME . '</p>';
echo '</div>';
if (!$tableExists || !$isMigrated) {
echo '<form method="post">';
echo '<input type="hidden" name="action" value="migrate_system">';
echo '<button type="submit" class="btn" onclick="return confirm(\'¿Estás seguro de migrar el sistema a base de datos?\')">';
echo '🔄 Migrar Sistema a Base de Datos';
echo '</button>';
echo '</form>';
if ($tableExists && !$isMigrated) {
echo '<form method="post" style="margin-top: 10px;">';
echo '<input type="hidden" name="action" value="update_system_files">';
echo '<button type="submit" class="btn">';
echo '🔧 Actualizar Archivos del Sistema';
echo '</button>';
echo '</form>';
}
} else {
echo '<div class="info-box">';
echo '<h4>✅ Sistema Ya Migrado</h4>';
echo '<p>El sistema de contraseñas ya está funcionando con base de datos.</p>';
echo '<p><a href="gestion_admin_unificada.php" class="btn" style="text-decoration: none; display: inline-block; text-align: center;">🛠️ Ir a Gestión de Administradores</a></p>';
echo '</div>';
}
} catch (Exception $e) {
echo '<div class="error-box">❌ <strong>Error conectando a BD:</strong> ' . $e->getMessage() . '</div>';
}
?>
<div class="warning-box" style="margin-top: 30px;">
<h4>📋 Lo que hace esta migración:</h4>
<ul>
<li>Crea tabla <code>admin_users</code> para gestionar administradores</li>
<li>Migra la contraseña actual del config.php a la BD</li>
<li>Actualiza funciones de autenticación</li>
<li>Mantiene retrocompatibilidad durante la transición</li>
<li>Permite múltiples administradores en el futuro</li>
</ul>
<h4>🔒 Beneficios del nuevo sistema:</h4>
<ul>
<li>Contraseñas seguras en base de datos</li>
<li>Múltiples usuarios administradores</li>
<li>Seguimiento de últimos accesos</li>
<li>Gestión unificada de credenciales</li>
<li>Mayor seguridad y escalabilidad</li>
</ul>
</div>
</div>
</body>
</html>