Update: 2026-05-03 21:58:11

This commit is contained in:
Hamza-Ayed
2026-05-03 21:58:11 +03:00
parent e1d4917369
commit 089a2b76c0
10 changed files with 668 additions and 9 deletions

105
scripts/migrate.php Normal file
View File

@@ -0,0 +1,105 @@
<?php
/**
* Advanced Migration Script: Schema Update + Data Encryption
*/
require_once __DIR__ . '/../app/bootstrap/init.php';
use App\Core\Database;
use App\Core\Encryption;
$db = Database::getInstance();
echo "--- Starting Security Migration ---\n";
// 1. Add email_hash column if it doesn't exist
try {
$db->exec("ALTER TABLE users ADD COLUMN email_hash VARCHAR(64) AFTER email, ADD INDEX (email_hash)");
echo "[OK] Added email_hash column and index.\n";
} catch (\Exception $e) {
echo "[SKIP] email_hash column might already exist.\n";
}
// 2. Fetch all users to encrypt their data
$stmt = $db->query("SELECT id, name, email FROM users");
$users = $stmt->fetchAll();
echo "Found " . count($users) . " users. Starting encryption...\n";
$updateStmt = $db->prepare("UPDATE users SET name = ?, email = ?, email_hash = ? WHERE id = ?");
foreach ($users as $user) {
// Check if data is already encrypted (to avoid double encryption)
$isAlreadyEncrypted = Encryption::decrypt($user['email']) !== false;
if ($isAlreadyEncrypted) {
echo "User ID {$user['id']} is already encrypted. Skipping.\n";
continue;
}
// Encrypt Name
$encryptedName = Encryption::encrypt($user['name']);
// Encrypt Email
$encryptedEmail = Encryption::encrypt($user['email']);
// Generate Hash for lookup
$emailHash = hash('sha256', strtolower($user['email']));
$updateStmt->execute([
$encryptedName,
$encryptedEmail,
$emailHash,
$user['id']
]);
echo "User ID {$user['id']} migrated successfully.\n";
}
// 3. Create companies table (Updated to match production schema)
try {
$db->exec("CREATE TABLE IF NOT EXISTS companies (
id INT AUTO_INCREMENT PRIMARY KEY,
tenant_id INT,
name VARCHAR(255) NOT NULL,
name_en VARCHAR(255),
tax_identification_number VARCHAR(50),
commercial_registration_number VARCHAR(50),
address TEXT,
city VARCHAR(100),
contact_email VARCHAR(255),
contact_phone VARCHAR(50),
jofotara_client_id_encrypted TEXT,
jofotara_secret_key_encrypted TEXT,
jofotara_income_source_sequence VARCHAR(50),
certificate_path VARCHAR(255),
certificate_password_encrypted TEXT,
is_jofotara_linked TINYINT(1) DEFAULT 0,
is_active TINYINT(1) DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
deleted_at DATETIME DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
echo "[OK] Companies table synchronized with production schema.\n";
} catch (\Exception $e) {
echo "[ERROR] Synchronizing companies table: " . $e->getMessage() . "\n";
}
// 4. Create user_companies pivot table
try {
$db->exec("CREATE TABLE IF NOT EXISTS user_companies (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
company_id INT NOT NULL,
role VARCHAR(50) DEFAULT 'employee',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY user_company (user_id, company_id),
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
echo "[OK] User_companies table created or exists.\n";
} catch (\Exception $e) {
echo "[ERROR] Creating user_companies table: " . $e->getMessage() . "\n";
}
echo "--- Migration Complete ---\n";