Files
intaleq/backend/migrations/2026_07_29_v2_migration_schema_fixes.sql
T

117 lines
8.6 KiB
SQL

-- ============================================================
-- 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;