-- ============================================================ -- 2026_07_29_v2_migration_schema_fixes.sql -- -- فجوات بين schema_primary.sql والكود الحيّ، يجب سدّها *قبل* تشغيل -- scripts/migrate_v2_reencrypt.php وإلا فشل الإدخال أو فشل تسجيل الدخول. -- -- كل تعليمة هنا نتيجة مقارنة فعلية بين: -- - CREATE TABLE في backend/schema_primary.sql -- - أعمدة INSERT/SELECT في auth/driver/register.php, auth/passenger/register.php, -- serviceapp/register.php, serviceapp/login.php, Admin/auth/*, auth/otp/* -- - scripts/backfill_blind_index.php (خريطة الفهارس المعتمدة) -- -- التنفيذ على قاعدة v3 الجديدة (الفارغة) قبل الترحيل. -- ============================================================ -- ───────────────────────────────────────────────────────────── -- 1) driver — الكود يُدخل name_bidx و phone_key وهما غير موجودين -- (auth/driver/register.php:444) → INSERT يفشل اليوم. -- national_bidx مطلوب من backfill_blind_index.php. -- ───────────────────────────────────────────────────────────── ALTER TABLE `driver` ADD COLUMN `name_bidx` VARCHAR(64) NULL DEFAULT NULL COMMENT 'HMAC للاسم الكامل بعد التطبيع', ADD COLUMN `national_bidx` VARCHAR(64) NULL DEFAULT NULL COMMENT 'HMAC للرقم الوطني', ADD COLUMN `phone_key` VARCHAR(80) NULL DEFAULT NULL COMMENT 'مفتاح ربط جداول التحقق — نفس صيغة otpPhoneKey()', ADD KEY `idx_driver_name_bidx` (`name_bidx`), ADD KEY `idx_driver_national_bidx` (`national_bidx`), ADD KEY `idx_driver_phone_key` (`phone_key`); -- UNIQUE على national_number يصبح بلا معنى تحت GCM (نفس الرقم يُنتج نصاً -- مختلفاً كل مرة) — بل يمنع فقط تكرار *النص المشفّر* لا تكرار الرقم. -- البديل الصحيح: UNIQUE على الفهرس الأعمى. ALTER TABLE `driver` DROP INDEX `national_number`; ALTER TABLE `driver` ADD UNIQUE KEY `uniq_driver_national_bidx` (`national_bidx`); ALTER TABLE `driver` ADD UNIQUE KEY `uniq_driver_phone_bidx` (`phone_bidx`); -- ───────────────────────────────────────────────────────────── -- 2) passengers — نفس المشكلة (auth/passenger/register.php:133) -- ───────────────────────────────────────────────────────────── ALTER TABLE `passengers` ADD COLUMN `name_bidx` VARCHAR(64) NULL DEFAULT NULL COMMENT 'HMAC للاسم الكامل بعد التطبيع', ADD COLUMN `phone_key` VARCHAR(80) NULL DEFAULT NULL COMMENT 'مفتاح ربط جداول التحقق — نفس صيغة otpPhoneKey()', ADD KEY `idx_passengers_name_bidx` (`name_bidx`), ADD KEY `idx_passengers_phone_key` (`phone_key`); -- UNIQUE (phone, email) على نصّين مشفّرين عشوائياً لا يمنع تكرار الحساب. ALTER TABLE `passengers` DROP INDEX `phone`; ALTER TABLE `passengers` ADD UNIQUE KEY `uniq_passengers_phone_bidx` (`phone_bidx`); -- ───────────────────────────────────────────────────────────── -- 3) users — نسخة schema_primary قديمة جداً مقارنة بالكود: -- ينقصها fingerprint / fingerprint_hash / status / country / -- email_bidx / phone_bidx (serviceapp/register.php:76, -- serviceapp/login.php:24, Admin/Staff/add.php:71). -- كما أن phone VARCHAR(15) لا يتّسع لنص مشفّر (≈44 حرفاً بـ CBC، -- ≈90 بـ GCM) — الإدخال سيُقطع أو يفشل. -- ───────────────────────────────────────────────────────────── ALTER TABLE `users` MODIFY COLUMN `phone` VARCHAR(255) NULL DEFAULT NULL, MODIFY COLUMN `email` VARCHAR(255) NULL DEFAULT NULL, MODIFY COLUMN `password` VARCHAR(255) NULL DEFAULT NULL, MODIFY COLUMN `first_name` VARCHAR(255) NULL DEFAULT NULL, MODIFY COLUMN `last_name` VARCHAR(255) NULL DEFAULT NULL, MODIFY COLUMN `birthdate` DATE NOT NULL DEFAULT '2002-01-01', MODIFY COLUMN `site` VARCHAR(255) NOT NULL DEFAULT 'Syria', MODIFY COLUMN `gender` VARCHAR(10) NOT NULL DEFAULT 'Female', ADD COLUMN `fingerprint` TEXT NULL DEFAULT NULL COMMENT 'بصمة الجهاز مشفرة', ADD COLUMN `fingerprint_hash` VARCHAR(64) NULL DEFAULT NULL COMMENT 'sha256(fingerprint) للبحث', ADD COLUMN `status` VARCHAR(20) NULL DEFAULT 'pending', ADD COLUMN `country` VARCHAR(100) NULL DEFAULT 'Jordan', ADD COLUMN `phone_bidx` VARCHAR(64) NULL DEFAULT NULL, ADD COLUMN `email_bidx` VARCHAR(64) NULL DEFAULT NULL, ADD KEY `idx_users_fp_hash` (`fingerprint_hash`), ADD KEY `idx_users_phone_bidx` (`phone_bidx`), ADD KEY `idx_users_email_bidx` (`email_bidx`); -- UNIQUE على نصّ مشفّر عشوائي بلا فائدة (وسيرفض NULL المتكرر فقط). ALTER TABLE `users` DROP INDEX `email`; ALTER TABLE `users` DROP INDEX `phone`; ALTER TABLE `users` ADD UNIQUE KEY `uniq_users_phone_bidx` (`phone_bidx`); -- ───────────────────────────────────────────────────────────── -- 4) token_verification_admin — أخطر فجوة: الكود يكتب اليوم -- phone_number = otpPhoneKey() ≈ 66 حرفاً، و token = GCM ≈ 90 حرفاً -- (auth/otp/request.php:131) بينما العمودان VARCHAR(20)/VARCHAR(10). -- النتيجة: قطع صامت للقيمة ⇒ لا يمكن التحقق من أي OTP للأدمن. -- ───────────────────────────────────────────────────────────── ALTER TABLE `token_verification_admin` MODIFY COLUMN `phone_number` VARCHAR(120) NOT NULL, MODIFY COLUMN `token` VARCHAR(255) NOT NULL, ADD COLUMN `verified` TINYINT(1) NOT NULL DEFAULT 0, ADD COLUMN `created_at` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP; -- auth/otp/verify.php:88 يحدّث verified، وrequest.php يعتمد ON DUPLICATE KEY -- على phone_number، فالـ UNIQUE يبقى لازماً بعد توسيع العمود. -- ───────────────────────────────────────────────────────────── -- 5) جداول التحقق الأخرى — أعمدة المفتاح تتّسع للـ K:hmac (66 حرفاً) -- ───────────────────────────────────────────────────────────── ALTER TABLE `phone_verification` MODIFY COLUMN `phone_number` VARCHAR(120) NOT NULL, MODIFY COLUMN `token_code` VARCHAR(255) NULL DEFAULT NULL, MODIFY COLUMN `email` VARCHAR(255) NOT NULL DEFAULT 'yet', ADD KEY `idx_pv_phone_number` (`phone_number`); ALTER TABLE `phone_verification_passenger` MODIFY COLUMN `phone_number` VARCHAR(120) NULL DEFAULT NULL, ADD KEY `idx_pvp_phone_number` (`phone_number`); -- ───────────────────────────────────────────────────────────── -- 6) adminUser — العمودان status/approved_* موجودان في -- 2026_07_25_blind_index.sql لكن schema_primary لا يحويهما. -- نفّذ هذا فقط إن لم تكن المايغريشن السابقة قد طُبّقت. -- ───────────────────────────────────────────────────────────── -- ALTER TABLE `adminUser` -- ADD COLUMN `status` VARCHAR(20) NOT NULL DEFAULT 'active', -- ADD COLUMN `approved_by` VARCHAR(32) NULL DEFAULT NULL, -- ADD COLUMN `approved_at` TIMESTAMP NULL DEFAULT NULL;