#!/usr/bin/env bash # ============================================================ # run_v2_migration.sh — تشغيل ترحيل intaleqDBV2 → intaleqDB1 على السيرفر # # يُشغَّل على السيرفر فقط. كل خطوة خطرة مسبوقة بفحص وقائي. # # bash backend/scripts/run_v2_migration.sh # # يتوقّع في البيئة (أو في ~/.env): # SRC_DB_HOST SRC_DB_NAME SRC_DB_USER SRC_DB_PASS ← القديمة (intaleqDBV2) # DB_PRIMARY_*_V2 ← الجديدة (intaleqDB1) # ENCRYPTION_KEY_PATH أو ENC_KEY, initializationVector, BLIND_INDEX_PEPPER # ============================================================ set -euo pipefail HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" BACKEND="$(dirname "$HERE")" STAMP="$(date +%Y%m%d-%H%M%S)" BACKUP="$HOME/backup_intaleqDB1_before_migration_$STAMP.sql" # ── تحميل .env إن وُجد ─────────────────────────────────────── for f in "$HOME/.env" "$BACKEND/.env"; do if [[ -f "$f" ]]; then set -a; . "$f"; set +a; echo "loaded env: $f"; break; fi done SRC_DB_HOST="${SRC_DB_HOST:-localhost}" : "${SRC_DB_NAME:?SRC_DB_NAME is not set — it must be the OLD database (intaleqDBV2)}" : "${SRC_DB_USER:?SRC_DB_USER is not set}" : "${DB_PRIMARY_NAME_V2:?DB_PRIMARY_NAME_V2 is not set — it must be the NEW database (intaleqDB1)}" : "${BLIND_INDEX_PEPPER:?BLIND_INDEX_PEPPER is not set}" DST="$DB_PRIMARY_NAME_V2" DST_HOST="${DB_PRIMARY_HOST_V2:-localhost}" DST_USER="${DB_PRIMARY_USER_V2:?DB_PRIMARY_USER_V2 is not set}" DST_PASS="${DB_PRIMARY_PASS_V2:-}" echo echo "══════════════════════════════════════════" echo " SOURCE (read-only) : $SRC_DB_NAME @ $SRC_DB_HOST" echo " TARGET (written) : $DST @ $DST_HOST" echo "══════════════════════════════════════════" # ── حارس الانعكاس: لا يجوز أن يكون الاثنان نفس القاعدة ────── if [[ "$SRC_DB_NAME" == "$DST" ]]; then echo "✘ ABORT: source and target are the same database ($DST)." echo " SRC_DB_NAME must be the OLD db; DB_PRIMARY_NAME_V2 the NEW one." exit 1 fi # ── حارس إضافي: الهدف يجب أن يكون شبه فارغ ────────────────── mysql_dst() { mysql -h "$DST_HOST" -u "$DST_USER" ${DST_PASS:+-p"$DST_PASS"} "$DST" "$@"; } DRIVERS_IN_TARGET=$(mysql_dst -N -B -e "SELECT COUNT(*) FROM driver" 2>/dev/null || echo "?") echo " target currently holds $DRIVERS_IN_TARGET driver row(s)" if [[ "$DRIVERS_IN_TARGET" != "0" && "$DRIVERS_IN_TARGET" != "?" ]]; then echo " ⚠️ target is NOT empty — --truncate would delete those rows." fi read -r -p $'\nType the TARGET database name to confirm: ' CONFIRM [[ "$CONFIRM" == "$DST" ]] || { echo "✘ mismatch — aborted."; exit 1; } # ── 1) نسخة احتياطية ──────────────────────────────────────── echo echo "── [1/6] backing up target → $BACKUP" mysqldump -h "$DST_HOST" -u "$DST_USER" ${DST_PASS:+-p"$DST_PASS"} \ --single-transaction --routines --triggers "$DST" > "$BACKUP" [[ -s "$BACKUP" ]] || { echo "✘ backup is empty — aborted."; exit 1; } echo " ✔ $(du -h "$BACKUP" | cut -f1)" # ── 2) إصلاحات المخطط ─────────────────────────────────────── echo echo "── [2/6] applying schema fixes" mysql_dst < "$BACKEND/migrations/2026_07_29_v2_migration_schema_fixes.sql" echo " ✔ applied" # ── 3) فحص المفتاح ────────────────────────────────────────── echo echo "── [3/6] probing legacy key/IV (must report FAILED=0)" php "$HERE/migrate_v2_reencrypt.php" --probe # ── 4) تشغيل جاف ──────────────────────────────────────────── echo echo "── [4/6] dry run" php "$HERE/migrate_v2_reencrypt.php" --dry-run read -r -p $'\nDry run looks correct? proceed with the real migration [yes/N]: ' GO [[ "$GO" == "yes" ]] || { echo "stopped before writing. Backup kept at $BACKUP"; exit 0; } # ── 5) التنفيذ ────────────────────────────────────────────── echo echo "── [5/6] migrating" php "$HERE/migrate_v2_reencrypt.php" --truncate # ── 6) التدقيق ────────────────────────────────────────────── echo echo "── [6/6] verifying" php "$HERE/migrate_v2_reencrypt.php" --verify cat <> ~/.env sudo systemctl reload php8.3-fpm للتراجع: mysql -u $DST_USER -p $DST < $BACKUP ══════════════════════════════════════════ EOF