422 lines
18 KiB
PHP
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>
|