> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# ترحيل المستخدمين: استيراد كلمات المرور وMFA

> استورد المستخدمين إلى Didit مع كلمات المرور والبريد المُتحقَّق منه وحسابات التواصل وتطبيقات المصادقة والأدوار، من ملف CSV أو JSON أو دفعات.

> [!WARNING]
>
> المصادقة ميزة جديدة. شغّل كل عملية استيراد في تطبيق ضمن البيئة التجريبية أولاً، ثم استورد إلى تطبيقك في بيئة الإنتاج.

ينقل الاستيراد الأشخاص من منصة هوية أخرى إلى Didit Authentication. تنتقل معهم كلمة المرور، والبريد الإلكتروني المُتحقَّق منه، وروابط تسجيل الدخول الاجتماعي، وتطبيق المصادقة، وأدوار المؤسسة. لا يتغير شيء بالنسبة لهم حتى يسجّل تطبيقك دخولهم عبر Didit.

تستخدم عمليات الاستيراد واجهة برمجة تطبيقات إدارة المصادقة الخاصة بتطبيقك، مع جلسة في وحدة التحكم تتضمن `write:authentication` (أو `read:authentication` لعرض القوائم). لا تستخدم هذه العمليات token المستخدم النهائي ولا مفتاح API للتحقق. في الأمثلة، يكون `MANAGEMENT_BASE` كما يلي:

```text theme={null}
https://apx.didit.me/auth/v2/organizations/{org_id}/applications/{application_id}/authentication/
```

## طريقتان للاستيراد

| | مهمة ملف | طلب دفعات |
| - | - | - |
| نقطة النهاية | `POST import-jobs/` (multipart) | `POST imports/` (JSON) |
| الحجم | ملف CSV أو JSON واحد، بحد أقصى 25 ميغابايت و100,000 شخص | من 1 إلى 1,000 سطر `rows` لكل طلب |
| التشغيل التجريبي | يُنفَّذ دائماً أولاً في الخلفية | `dry_run: true` افتراضياً |
| الاعتماد | `POST import-jobs/{id}/start/` | الطلب نفسه مع `dry_run: false` |
| الفشل الجزئي | تُعتمد كل دفعة من 1,000 بشكل مستقل، ويُستأنف الاستيراد الذي انقطع | الكل أو لا شيء |

## استيراد ملف

### 1. الرفع

```bash theme={null}
curl --fail-with-body "${MANAGEMENT_BASE}import-jobs/" \
  -H "Authorization: Bearer $CONSOLE_ACCESS_TOKEN" \
  -F file=@users.csv \
  -F passwords=import \
  -F keep_social=true \
  -F keep_verified=true \
  -F keep_mfa=true \
  -F keep_ids=true
```

| الحقل | المعنى |
| - | - |
| `file` | ملف CSV أو JSON بترميز UTF-8 (يُسمح بعلامة ترتيب البايتات)، بحد أقصى 25 ميغابايت. |
| `passwords` | القيمة `import` (الافتراضية) تحتفظ بتجزئات كلمات المرور. القيمة `reset` تتجاهلها، فيُعيّن الجميع كلمة مرور جديدة. |
| `keep_social` | الاحتفاظ بروابط تسجيل الدخول الاجتماعي. |
| `keep_verified` | الاحتفاظ بالحقل `email_verified`. مع `false`، يصبح كل بريد إلكتروني غير مُتحقَّق منه. |
| `keep_mfa` | الاحتفاظ بأسرار تطبيق المصادقة. |
| `keep_ids` | الاحتفاظ بالحقل `external_id`. مع `false`، تصبح قيمة `vendor_data` هي معرّف الهوية في Didit. |
| `firebase_signer_key`, `firebase_salt_separator`, `firebase_rounds`, `firebase_mem_cost` | معاملات التجزئة في مشروع Firebase الخاص بك. أرسل الأربعة جميعاً أو لا ترسل أياً منها. |

يكون كل مفتاح `keep_*` بالقيمة `true` ما لم ترسل `false`. تعيد الواجهة الاستجابة `202` مع مهمة. يحتفظ التطبيق بـ5 ملفات مرفوعة كحد أقصى في آنٍ واحد.

### 2. مراجعة التشغيل التجريبي

يبدأ كل رفع بتشغيل تجريبي. يتحقق هذا التشغيل من كل شخص ولا يكتب أي شيء. استعلم عن `GET import-jobs/{id}/` بشكل دوري:

| الحقل | المعنى |
| - | - |
| `kind` | القيمة `dry_run`، ثم `import` بعد أن تبدأه. |
| `status` | القيم `queued` و`running`، ثم `passed` أو `failed` للتشغيل التجريبي، و`done` أو `error` للاستيراد. |
| `processed`, `total` | التقدم، بعدد الأشخاص. |
| `result` | محتويات الملف (انظر [النتائج](#النتائج)). |
| `startable` | القيمة `true` عندما يجتاز التشغيل التجريبي ولم تنتهِ صلاحية الملف. |
| `expires_at` | يُحذف الملف بعد 24 ساعة من تشغيل تجريبي لم يُستورد بعده. |

يعرض التشغيل التجريبي الفاشل أخطاءه. صحّح الملف وارفعه مجدداً.

### 3. بدء الاستيراد

يستورد `POST import-jobs/{id}/start/` ما تحقق منه التشغيل التجريبي، ويعيد `202`.

* يُستورد الأشخاص على دفعات من 1,000. تُعتمد كل دفعة بشكل مستقل.
* يعمل استيراد واحد فقط لكل تطبيق في المرة الواحدة (وإلا فستظهر رسالة `import_running`).
* يُستأنف الاستيراد الذي انقطع بعد آخر دفعة تم اعتمادها.
* يُتخطّى الأشخاص الذين استُوردوا سابقاً، لذا يمكنك تشغيل الملف نفسه مرة أخرى.
* يتلقى الشخص الذي بدأ الاستيراد بريداً إلكترونياً عند انتهائه أو توقفه.

يُخزَّن الملف المرفوع مشفّراً. يُحذف عند انتهاء الاستيراد، أو عند فشل تشغيله التجريبي، أو بعد 24 ساعة من تشغيل تجريبي لم يُستورد بعده.

## استيراد على دفعات

أرسل حتى 1,000 شخص في كل طلب، مع `idempotency_key` بطول 100 حرف كحد أقصى.

```json theme={null}
{
  "rows": [
    {
      "email": "user@example.com",
      "external_id": "user-1234",
      "email_verified": true,
      "display_name": "Example User",
      "password_hash": "$2b$12$...",
      "social": [{ "provider": "google", "subject": "1234567890" }],
      "organizations": [{ "slug": "acme", "name": "Acme", "role": "admin" }]
    }
  ],
  "dry_run": true,
  "idempotency_key": "migration-batch-0001"
}
```

* يعيد التشغيل التجريبي `200` مع النتيجة، ولا يكتب أي شيء.
* مع `dry_run: false`، يعيد الاستيراد الناجح `201`. تعيد الدفعة التي تحتوي على أي خطأ `400` ولا تستورد أحداً.
* إعادة إرسال طلب معتمد بالمفتاح نفسه تعيد نتيجته المسجلة. أما المفتاح نفسه مع محتوى مختلف فيعيد `400 {"idempotency_key": "different_payload"}`.
* تُرسل معاملات Firebase داخل كائن `firebase`: `{signer_key, salt_separator, rounds, mem_cost}`.
* يعرض `GET imports/` الدفعات المعتمدة.

## تنسيق الملف

### JSON

مصفوفة من الأشخاص، أو كائن يحتوي حقل `users` بهذه المصفوفة.

| الحقل | القاعدة |
| - | - |
| `email` | مطلوب. |
| `external_id` | حتى 255 حرفاً. تصبح قيمته [`vendor_data`](https://docs.didit.me/ar/entities/vendor-data-linking) الخاصة بالشخص. |
| `email_verified` | `true` أو `false` (أو `1`/`0`، و`yes`/`no`). |
| `display_name` | حتى 200 حرف. |
| `password_hash`, `password_salt`, `password_algorithm` | انظر [كلمات المرور](#كلمات-المرور). |
| `totp_secret` | سر تطبيق المصادقة بترميز Base32. |
| `created_at`, `last_signed_in_at` | بصيغة ISO 8601. يُعامل الوقت بدون منطقة زمنية على أنه UTC. |
| `social` | حتى 8 عناصر من الشكل `{provider, subject, tenant_id}`. القيمة `provider` هي `google` أو `apple` أو `github` أو `microsoft`. الحقل `tenant_id` مطلوب لـ Microsoft فقط. |
| `organizations` | حتى 20 عنصراً من الشكل `{slug, name, role}`. القيمة `role` هي `admin` أو `member` (الافتراضية) أو `billing`. |

### CSV

الأعمدة نفسها ذات القيمة المفردة، بالإضافة إلى `google_id` و`apple_id` و`github_id` و`microsoft_id` و`microsoft_tenant_id` و`organization_slug` و`organization_name` و`organization_role`. يأخذ الشخص الذي ينتمي إلى عدة مؤسسات سطراً واحداً لكل مؤسسة.

```csv theme={null}
email,external_id,email_verified,password_hash,google_id,organization_slug,organization_role
user@example.com,user-1234,true,$2b$12$...,1234567890,acme,admin
```

تُعد الحقول أو الأعمدة غير المعروفة أخطاءً، ولا تُتجاهل أبداً.

### التكرارات والحسابات الموجودة

* تُدمج الأسطر ذات البريد الإلكتروني نفسه في شخص واحد. يُحسب السطر المطابق تماماً مكرراً. يُدمج السطر الذي يحتوي روابط أو مؤسسات أو تطبيق مصادقة أكثر.
* يُعد وجود تجزئتين مختلفتين لكلمة المرور، أو سرين مختلفين لتطبيق المصادقة، أو دورين مختلفين في المؤسسة لشخص واحد، خطأً. وكذلك الأمر إذا ادّعى شخصان الحقل `external_id` نفسه، أو معرّف الحساب نفسه لدى المزوّد.
* إذا كان هناك حساب بالبريد الإلكتروني نفسه وأنشأه استيراد سابق، يُتخطّى الشخص (`already_imported`). وإذا سجّل الشخص بنفسه، يُعد ذلك خطأ `identity_conflict`. لا يُغيّر الاستيراد أبداً حساباً موجوداً.

## كلمات المرور

| الصيغة | المقبول |
| - | - |
| bcrypt | `$2a$` أو `$2b$` أو `$2y$`، بتكلفة من 4 إلى 13. |
| Argon2id | `$argon2id$v=19$...`. حتى 64 MiB من الذاكرة، والذاكرة مضروبة في عدد المرات حتى 256 MiB، وحتى 8 مسارات. |
| Django PBKDF2-SHA256 | `pbkdf2_sha256$...`، من 10,000 إلى 2,000,000 تكرار. |
| Django scrypt | `scrypt$...`، عامل العمل حتى 32,768، وحجم الكتلة من 1 إلى 8، والتوازي من 1 إلى 5. |
| Firebase scrypt | `password_algorithm: "firebase_scrypt"`، و`password_hash` و`password_salt` بترميز base64 لكل شخص، إضافةً إلى `signer_key` و`salt_separator` و`rounds` (من 1 إلى 8) و`mem_cost` (من 1 إلى 14) الخاصة بمشروعك، مرة واحدة لكل استيراد. |

تُخزَّن معاملات Firebase مشفّرةً ولهذا التطبيق وحده. أي صيغة أخرى، أو تكلفة تتجاوز هذه الحدود، تعني أن الشخص يحتاج إلى كلمة مرور جديدة. بعد أول تسجيل دخول ناجح للشخص، تعيد Didit تخزين كلمة مروره بصيغتها الخاصة.

### الأشخاص بدون كلمة مرور صالحة للاستخدام

عندما لا يكون لدى الشخص تجزئة، أو تكون التجزئة غير مدعومة، تتلقى محاولة تسجيل الدخول بكلمة المرور الرد المعتاد الخاص بكلمة المرور الخاطئة. ترسل Didit إليه أيضاً بريداً إلكترونياً يحتوي على رابط لتعيين كلمة مرور جديدة (صالح لمدة 30 دقيقة، ومرة واحدة في اليوم على الأكثر). يحدث هذا فقط عندما تم التحقق من بريده الإلكتروني، ولم يُحظر الحساب، وكان تسجيل الدخول بكلمة المرور مفعّلاً.

في النتيجة، يُحصي `reset_required` الأشخاص الذين لا يملكون كلمة مرور صالحة للاستخدام. ويُحصي `reset_emails` من بينهم أصحاب البريد الإلكتروني المتحقَّق منه فقط، فهم وحدهم من يمكن الوصول إليهم بهذه الطريقة. لا يستطيع الأشخاص الذين لم يتحقق من بريدهم الإلكتروني تسجيل الدخول بكلمة مرور. ومع ذلك يمكنهم تسجيل الدخول برمز يُرسل إلى بريدهم الإلكتروني إذا فعّلت هذه الطريقة.

## الروابط الاجتماعية وتطبيقات المصادقة والمؤسسات

* **الروابط الاجتماعية** تُحتفظ بها للمزوّدين الذين سبق أن هيّأهم تطبيقك، ضمن معرّف العميل الحالي. عندها لا يحتاج تسجيل الدخول العائد إلى إثبات بالبريد الإلكتروني. معرّفات Google وGitHub عامة على مستوى العالم. أما معرّفات Apple فهي خاصة بفريق المطوّر، ومعرّفات Microsoft خاصة بتسجيل التطبيق، لذلك لا تتطابق هذه الروابط إلا إذا كانت منصتك القديمة تستخدم الفريق أو التسجيل نفسه. الروابط المرتبطة بمزوّدين لم تُهيَّئ لديك تُحسب ضمن `social_unavailable` ولا تُستورد.
* **تطبيقات المصادقة** (أسرار TOTP: SHA-1، و6 أرقام، و30 ثانية) تُخزَّن مشفّرة. يجب على الأشخاص المستوردين استخدامها كعامل ثانٍ للتحقق. ولا يحصلون على رموز استرداد.
* **المؤسسات** التي لا وجود لها بعد تُنشأ من معرّفها المختصر.
* **مفاتيح المرور** لا يمكن استيرادها. فهي تنتمي إلى نطاق تسجيل الدخول القديم لديك، لذلك يضيف الأشخاص مفتاح مرور جديداً بعد أن يسجلوا الدخول عبر Didit.

## النتائج

تُعيد كل عملية تشغيل تجريبي ودفعة ومهمة النتيجة `result` نفسها:

| الحقل | المعنى |
| - | - |
| `rows`, `people_total` | الأسطر التي قُرئت والأشخاص غير المكررين. |
| `ready`, `already_imported`, `duplicates`, `merged`, `skipped` | ما يحدث لكل شخص. |
| `passwords` | العدد لكل صيغة: `bcrypt` و`argon2id` و`firebase_scrypt` و`pbkdf2_sha256` و`scrypt`. |
| `reset_required`, `reset_emails`, `unsupported_hashes` | الأشخاص الذين يحتاجون إلى كلمة مرور جديدة. |
| `verified_emails` | الأشخاص المستوردون ببريد إلكتروني متحقَّق منه. |
| `social_links`, `social_unavailable` | الروابط المحتفظ بها لكل مزوّد، والروابط المتخطاة. |
| `authenticator_apps` | الأشخاص الذين استُورد لهم تطبيق مصادقة. |
| `organizations` | `count` و`members` وما يصل إلى خمسة أسماء في `names`. |
| `error_count`, `errors` | حتى 100 خطأ، لكل منها `row` مُعرَّف من الصفر (سطر CSV هو `row + 2`)، و`field`، ورمز خطأ `error`. |

لا تتضمن الاستجابات أبداً تجزئات كلمات المرور ولا الأملاح ولا أسرار تطبيقات المصادقة ولا قيم الحقول.

| الخطأ | المعنى |
| - | - |
| `file_too_large`, `too_many_rows`, `empty_file` | أكبر من 25 MB، أو أكثر من 100,000 شخص، أو فارغ. |
| `invalid_encoding`, `invalid_json`, `invalid_csv` | تعذّرت قراءة الملف. |
| `unknown_column`, `missing_column`, `duplicate_column`, `unknown_field` | الملف لا يطابق الصيغة. |
| `required`, `invalid_field`, `invalid_row` | قيمة مفقودة أو غير صالحة. |
| `identity_conflict` | حساب بهذا البريد الإلكتروني سُجّل بشكل مستقل. |
| `social_link_conflict`, `password_conflict`, `authenticator_conflict`, `role_conflict` | سطران لشخص واحد يتعارضان. |
| `too_many_uploads`, `import_running`, `not_startable`, `file_expired` | لا يمكن بدء المهمة الآن. |

## قبل التبديل

اختبر في تطبيقك في البيئة التجريبية:

* تسجيل الدخول بكل صيغة كلمة مرور تستوردها،
* بريد تعيين كلمة مرور جديدة لشخص ليست لديه تجزئة صالحة للاستخدام،
* تسجيل الدخول الاجتماعي ورموز تطبيقات المصادقة للأشخاص المستوردين،
* تشغيل الملف نفسه مرتين.

ثم تحقّق من أن `vendor_data` لكل شخص يطابق القيمة التي تستخدمها لـ[عمليات التحقق والمعاملات](https://docs.didit.me/ar/authentication/overview.md#الحفاظ-على-هوية-المستخدم-نفسه-عبر-المنتجات).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.