Watch
1
0
Fork
You've already forked Seyyed_arc
0
forked from hesabix/arc
Seyyed_arc/docs/VERIFICATION_PAGE_SCENARIO.md
2026-04-14 19:34:55 +03:30

881 lines
34 KiB
Markdown
Executable file

# سناریو صفحه تایید شماره موبایل و ایمیل
## مقدمه
این سند سناریوی کامل پیاده‌سازی صفحه تایید شماره موبایل و ایمیل را شرح می‌دهد که به صورت یکپارچه و تجمیع‌شده در یک صفحه نمایش داده می‌شود.
## اهداف کلی
1. نمایش وضعیت تایید شماره موبایل و ایمیل کاربر
2. امکان تغییر شماره موبایل و ایمیل با رعایت مسائل امنیتی
3. جلوگیری از تایید مجدد مواردی که قبلاً تایید شده‌اند
4. اعتبارسنجی مناسب ورودی‌ها
5. تجمیع تمام فرآیندهای تایید در یک صفحه
---
## 1. ساختار صفحه
### 1.1. بخش تایید شماره موبایل
**وضعیت‌های ممکن:**
- ✅ **تایید شده**: نمایش شماره موبایل (مخفی شده) و آیکون تیک سبز
- ⏳ **تایید نشده**: نمایش فرم تایید
- 📝 **در حال ویرایش**: نمایش فرم ویرایش با Switch
**عناصر UI:**
- نمایش شماره موبایل فعلی (مثلاً: `091*****789`)
- آیکون وضعیت (✓ برای تایید شده، ⚠️ برای تایید نشده)
- Switch برای فعال‌سازی حالت ویرایش
- فیلد ورودی شماره موبایل (غیرفعال به‌صورت پیش‌فرض)
- **کپچا**: تصویر کپچا و فیلد ورود کد کپچا (قبل از ارسال)
- دکمه "ارسال کد تایید"
- Dialog برای وارد کردن OTP (در صورت ارسال کد)
- Dialog هشدار برای شماره ثبت‌شده اما تایید نشده
### 1.2. بخش تایید ایمیل
**وضعیت‌های ممکن:**
- ✅ **تایید شده**: نمایش ایمیل و آیکون تیک سبز
- ⏳ **تایید نشده**: نمایش فرم تایید
- 📝 **در حال ویرایش**: نمایش فرم ویرایش با Switch
**عناصر UI:**
- نمایش ایمیل فعلی (با مخفی‌سازی جزئی)
- آیکون وضعیت
- Switch برای فعال‌سازی حالت ویرایش
- فیلد ورودی ایمیل (غیرفعال به‌صورت پیش‌فرض)
- **کپچا**: تصویر کپچا و فیلد ورود کد کپچا (قبل از ارسال)
- دکمه "ارسال ایمیل تایید"
- نمایش پیام "ایمیل تایید ارسال شد"
- Dialog هشدار برای ایمیل ثبت‌شده اما تایید نشده
---
## 2. جریان‌های کاربری
### 2.1. بارگذاری صفحه (Initial Load)
**Frontend:**
1. فراخوانی `GET /api/v1/auth/me` برای دریافت اطلاعات کاربر
2. بررسی فیلدهای:
- `mobile`: شماره موبایل فعلی
- `mobile_verified`: وضعیت تایید شماره موبایل
- `email`: ایمیل فعلی
- `email_verified`: وضعیت تایید ایمیل
**Backend (نیاز به تغییر):**
- باید `mobile_verified` به response اضافه شود (در حال حاضر در `to_dict()` نیست)
**State اولیه:**
```dart
{
mobile: "09123456789",
mobileVerified: false,
email: "user@example.com",
emailVerified: false,
editMobileEnabled: false,
editEmailEnabled: false
}
```
### 2.2. نمایش حالت تایید شده شماره موبایل
**شرایط:**
- `mobile_verified == true`
- `mobile` وجود دارد و خالی نیست
**نمایش:**
```
┌─────────────────────────────────────┐
│ 📱 شماره موبایل │
│ ✅ تایید شده │
│ 091*****789 │
│ [Switch: فعال‌سازی ویرایش] │
└─────────────────────────────────────┘
```
**رفتار:**
- بخش تایید (ارسال کد) مخفی می‌شود
- فقط نمایش وضعیت و Switch برای ویرایش
- اگر کاربر Switch را فعال کند → حالت ویرایش فعال می‌شود
### 2.3. نمایش حالت تایید نشده شماره موبایل
**شرایط:**
- `mobile_verified == false` یا `mobile` خالی است
**نمایش:**
```
┌─────────────────────────────────────┐
│ 📱 شماره موبایل │
│ ⚠️ تایید نشده │
│ [شماره موبایل: 09123456789] (غیرفعال) │
│ [Switch: فعال‌سازی ویرایش] │
│ [ارسال کد تایید] (غیرفعال) │
└─────────────────────────────────────┘
```
**رفتار:**
- فیلد شماره موبایل با شماره فعلی پر می‌شود (پیش‌فرض)
- فیلد و دکمه غیرفعال هستند تا Switch فعال شود
- بعد از فعال شدن Switch:
- فیلد قابل ویرایش می‌شود
- دکمه "ارسال کد تایید" فعال می‌شود
### 2.4. تغییر شماره موبایل
**جریان:**
1. کاربر Switch را فعال می‌کند
2. فیلد شماره موبایل قابل ویرایش می‌شود
3. کاربر شماره جدید وارد می‌کند
4. اعتبارسنجی بلافاصله انجام می‌شود:
- فرمت شماره موبایل ایرانی: `^09\d{9}$`
- نرمال‌سازی شماره موبایل (تبدیل به فرمت استاندارد)
5. کاربر روی "ارسال کد تایید" کلیک می‌کند
6. ✅ **کپچا نمایش داده می‌شود**:
- فراخوانی `GET /api/v1/auth/captcha` برای دریافت کپچا (در صورت نیاز)
- نمایش کپچا به کاربر
- کاربر باید کد کپچا را وارد کند
7. پس از تایید کپچا، درخواست تغییر شماره موبایل ارسال می‌شود:
```
POST /api/v1/auth/update-mobile
Body: {
"mobile": "09123456789",
"captcha_id": "cpt_xxx",
"captcha_code": "123456"
}
```
8. Backend بررسی می‌کند:
- ✅ کپچا معتبر است؟
- ✅ شماره توسط کاربر دیگری تایید شده است؟ → خطا
- ✅ شماره ثبت شده اما تایید نشده است؟ → هشدار و درخواست تایید
- ✅ شماره قبلی کاربر تایید شده است؟ → خطا
9. در صورت موفقیت:
- شماره به‌روزرسانی می‌شود
- `mobile_verified = false` می‌شود
- سپس OTP ارسال می‌شود
10. Dialog OTP نمایش داده می‌شود
**قوانین امنیتی:**
- ✅ **کپچا الزامی است**: قبل از هر تغییری باید کپچا تایید شود
- بررسی Rate Limiting (حداکثر 3 درخواست در 24 ساعت)
- بررسی شماره موبایل تکراری در سیستم:
- بررسی اینکه شماره توسط کاربر دیگری ثبت نشده باشد
- ⚠️ **مهم**: اگر شماره توسط کاربر دیگری **ثبت و تایید شده** باشد:
- ❌ خطا: "این شماره موبایل قبلاً توسط کاربر دیگری ثبت و تایید شده است. لطفاً شماره دیگری وارد کنید."
- از ادامه عملیات جلوگیری می‌شود
- اگر شماره توسط کاربر دیگری ثبت شده اما تایید نشده باشد:
- ⚠️ هشدار: "این شماره موبایل قبلاً ثبت شده است اما تایید نشده. آیا می‌خواهید ادامه دهید؟"
- اگر شماره جدید با شماره قبلی کاربر متفاوت است:
- بررسی: آیا شماره قبلی تایید شده بود؟
- اگر بله: ❌ خطا: "شما نمی‌توانید شماره موبایل تایید شده را تغییر دهید. لطفاً ابتدا شماره فعلی را حذف کنید."
- اگر خیر: ✅ اجازه تغییر
- ذخیره شماره جدید در `user.mobile`
- Reset کردن `mobile_verified = false` (چون شماره جدید است)
**نیاز به Endpoint جدید:**
```
POST /api/v1/auth/update-mobile
Body: {
"mobile": "09123456789",
"captcha_id": "cpt_xxx",
"captcha_code": "123456"
}
```
### 2.5. تایید شماره موبایل با OTP
**جریان:**
1. کاربر روی "ارسال کد تایید" کلیک می‌کند
2. کد OTP به شماره موبایل ارسال می‌شود
3. Dialog برای وارد کردن OTP نمایش داده می‌شود
4. کاربر کد را وارد می‌کند
5. بررسی کد:
- فراخوانی: `POST /api/v1/auth/verify-mobile?otp_code=123456`
- بررسی اعتبار کد (6 رقم، معتبر، منقضی نشده)
- حداکثر 5 تلاش
6. در صورت موفقیت:
- `mobile_verified = true`
- نمایش پیام موفقیت
- بستن Dialog
- به‌روزرسانی UI
### 2.6. نمایش حالت تایید شده ایمیل
**شرایط:**
- `email_verified == true`
- `email` وجود دارد
**نمایش:**
```
┌─────────────────────────────────────┐
│ 📧 ایمیل │
│ ✅ تایید شده │
│ us**@example.com │
│ [Switch: فعال‌سازی ویرایش] │
└─────────────────────────────────────┘
```
### 2.7. نمایش حالت تایید نشده ایمیل
**نمایش:**
```
┌─────────────────────────────────────┐
│ 📧 ایمیل │
│ ⚠️ تایید نشده │
│ [ایمیل: user@example.com] (غیرفعال) │
│ [Switch: فعال‌سازی ویرایش] │
│ [ارسال ایمیل تایید] (غیرفعال) │
└─────────────────────────────────────┘
```
### 2.8. تغییر ایمیل
**جریان مشابه شماره موبایل با تفاوت‌های زیر:**
- اعتبارسنجی: فرمت ایمیل معتبر
- ارسال ایمیل به جای SMS
- تایید از طریق لینک در ایمیل (نه OTP)
- ✅ **کپچا الزامی است**: قبل از تغییر ایمیل، کاربر باید کپچا را تایید کند
**جریان:**
1. کاربر Switch را فعال می‌کند
2. فیلد ایمیل قابل ویرایش می‌شود
3. کاربر ایمیل جدید وارد می‌کند
4. اعتبارسنجی بلافاصله انجام می‌شود (فرمت ایمیل)
5. کاربر روی "ارسال ایمیل تایید" کلیک می‌کند
6. ✅ **کپچا نمایش داده می‌شود**
7. پس از تایید کپچا، درخواست تغییر ایمیل ارسال می‌شود:
```
POST /api/v1/auth/update-email
Body: {
"email": "newemail@example.com",
"captcha_id": "cpt_xxx",
"captcha_code": "123456"
}
```
8. Backend بررسی می‌کند (مشابه شماره موبایل)
9. در صورت موفقیت، ایمیل تایید ارسال می‌شود
**قوانین امنیتی:**
- ✅ **کپچا الزامی است**: قبل از هر تغییری باید کپچا تایید شود
- بررسی Rate Limiting (حداکثر 3 درخواست در 24 ساعت)
- بررسی ایمیل تکراری در سیستم:
- بررسی اینکه ایمیل توسط کاربر دیگری ثبت نشده باشد
- ⚠️ **مهم**: اگر ایمیل توسط کاربر دیگری **ثبت و تایید شده** باشد:
- ❌ خطا: "این ایمیل قبلاً توسط کاربر دیگری ثبت و تایید شده است. لطفاً ایمیل دیگری وارد کنید."
- از ادامه عملیات جلوگیری می‌شود
- اگر ایمیل توسط کاربر دیگری ثبت شده اما تایید نشده باشد:
- ⚠️ هشدار: "این ایمیل قبلاً ثبت شده است اما تایید نشده. آیا می‌خواهید ادامه دهید؟"
- اگر ایمیل جدید با قبلی متفاوت است:
- بررسی: آیا ایمیل قبلی تایید شده بود؟
- اگر بله: ❌ خطا: "شما نمی‌توانید ایمیل تایید شده را تغییر دهید. لطفاً ابتدا ایمیل فعلی را حذف کنید."
- اگر خیر: ✅ اجازه تغییر
- Reset کردن `email_verified = false`
- ایجاد verification token
- ارسال ایمیل با لینک تایید
### 2.9. تایید ایمیل
**جریان:**
1. کاربر روی "ارسال ایمیل تایید" کلیک می‌کند
2. فراخوانی: `POST /api/v1/auth/resend-verification`
3. ایمیل حاوی لینک تایید ارسال می‌شود
4. کاربر روی لینک کلیک می‌کند
5. تایید از طریق: `GET /api/v1/auth/verify-email?token=xxx`
6. در صورت موفقیت:
- `email_verified = true`
- نمایش پیام موفقیت در UI
---
## 3. تغییرات Backend
### 3.1. تغییر در `AuthContext.to_dict()`
افزودن `mobile_verified` به response:
```python
def to_dict(self) -> dict:
return {
"user": {
...
"mobile": self.user.mobile,
"mobile_verified": getattr(self.user, "mobile_verified", False),
"email": self.user.email,
"email_verified": getattr(self.user, "email_verified", False),
...
},
...
}
```
### 3.2. Endpoint جدید: تغییر شماره موبایل
```
POST /api/v1/auth/update-mobile
Summary: تغییر شماره موبایل کاربر
Authentication: Required
Body:
{
"mobile": "09123456789",
"captcha_id": "cpt_xxx",
"captcha_code": "123456"
}
Rules:
1. ✅ تایید کپچا (validate_captcha) - الزامی
2. بررسی Rate Limiting (حداکثر 3 بار در 24 ساعت)
3. اعتبارسنجی شماره موبایل (فرمت و نرمال‌سازی)
4. بررسی تکراری نبودن:
a. جستجوی کاربر با این شماره موبایل
b. اگر کاربری با این شماره وجود دارد:
- اگر user_id != current_user_id:
* اگر mobile_verified == True:
❌ خطا: "این شماره موبایل قبلاً توسط کاربر دیگری ثبت و تایید شده است"
* اگر mobile_verified == False:
⚠️ هشدار: "این شماره موبایل قبلاً ثبت شده اما تایید نشده است. آیا می‌خواهید ادامه دهید؟"
5. بررسی: اگر شماره قبلی کاربر تایید شده بود → خطا
6. به‌روزرسانی user.mobile
7. Reset کردن mobile_verified = false
8. باطل کردن تمام OTP های قبلی برای شماره قبلی
Response:
{
"success": true,
"message": "شماره موبایل با موفقیت به‌روزرسانی شد",
"data": {
"mobile": "09123456789",
"mobile_verified": false
}
}
Errors:
- 400: "INVALID_CAPTCHA" - کپچا نامعتبر
- 400: "MOBILE_IN_USE_VERIFIED" - شماره توسط کاربر دیگری تایید شده
- 400: "MOBILE_IN_USE_UNVERIFIED" - شماره ثبت شده اما تایید نشده (با confirm نیاز است)
- 400: "MOBILE_ALREADY_VERIFIED" - نمی‌توان شماره تایید شده را تغییر داد
- 429: "RATE_LIMIT_EXCEEDED" - تعداد درخواست‌ها بیش از حد
```
### 3.3. Endpoint جدید: تغییر ایمیل
```
POST /api/v1/auth/update-email
Summary: تغییر ایمیل کاربر
Authentication: Required
Body:
{
"email": "newemail@example.com",
"captcha_id": "cpt_xxx",
"captcha_code": "123456"
}
Rules:
1. ✅ تایید کپچا (validate_captcha) - الزامی
2. بررسی Rate Limiting (حداکثر 3 بار در 24 ساعت)
3. اعتبارسنجی فرمت ایمیل
4. بررسی تکراری نبودن:
a. جستجوی کاربر با این ایمیل
b. اگر کاربری با این ایمیل وجود دارد:
- اگر user_id != current_user_id:
* اگر email_verified == True:
❌ خطا: "این ایمیل قبلاً توسط کاربر دیگری ثبت و تایید شده است"
* اگر email_verified == False:
⚠️ هشدار: "این ایمیل قبلاً ثبت شده اما تایید نشده است. آیا می‌خواهید ادامه دهید؟"
5. بررسی: اگر ایمیل قبلی کاربر تایید شده بود → خطا
6. به‌روزرسانی user.email
7. Reset کردن email_verified = false
8. باطل کردن تمام verification tokens قبلی
9. ایجاد verification token جدید (اختیاری)
10. ارسال ایمیل تایید (اختیاری - می‌تواند در endpoint جداگانه باشد)
Response:
{
"success": true,
"message": "ایمیل با موفقیت به‌روزرسانی شد",
"data": {
"email": "newemail@example.com",
"email_verified": false
}
}
Errors:
- 400: "INVALID_CAPTCHA" - کپچا نامعتبر
- 400: "EMAIL_IN_USE_VERIFIED" - ایمیل توسط کاربر دیگری تایید شده
- 400: "EMAIL_IN_USE_UNVERIFIED" - ایمیل ثبت شده اما تایید نشده (با confirm نیاز است)
- 400: "EMAIL_ALREADY_VERIFIED" - نمی‌توان ایمیل تایید شده را تغییر داد
- 429: "RATE_LIMIT_EXCEEDED" - تعداد درخواست‌ها بیش از حد
```
### 3.4. تغییر در `send-mobile-verification`
**تغییرات:**
- اگر شماره ارسالی با شماره فعلی کاربر متفاوت است:
- بررسی: آیا شماره فعلی تایید شده بود؟
- اگر بله: خطا
- اگر خیر: به‌روزرسانی شماره قبل از ارسال OTP
### 3.5. اعتبارسنجی شماره موبایل
**قوانین:**
- فرمت: `^09\d{9}$`
- نرمال‌سازی:
- تبدیل `+989` به `09`
- تبدیل `00989` به `09`
- تبدیل `989` به `09`
- تبدیل `9` (10 رقم) به `09`
---
## 4. تغییرات Frontend
### 4.1. ایجاد صفحه جدید: `VerificationPage`
**مسیر:** `lib/pages/profile/verification_page.dart`
**ویژگی‌ها:**
- نمایش دو بخش: شماره موبایل و ایمیل
- مدیریت State برای هر بخش
- Switch برای فعال‌سازی ویرایش
- اعتبارسنجی real-time
- نمایش Dialog برای OTP
- نمایش پیام‌های موفقیت/خطا
### 4.2. Service جدید: `VerificationService`
**مسیر:** `lib/services/verification_service.dart`
**متدها:**
- `getUserInfo()`: دریافت اطلاعات کاربر از `/api/v1/auth/me`
- `getCaptcha()`: دریافت کپچا از `/api/v1/auth/captcha`
- `updateMobile(String mobile, String captchaId, String captchaCode)`: تغییر شماره موبایل (با کپچا)
- `updateEmail(String email, String captchaId, String captchaCode)`: تغییر ایمیل (با کپچا)
- `sendMobileVerification(String mobile)`: ارسال کد OTP
- `sendEmailVerification()`: ارسال ایمیل تایید
- `verifyMobile(String otp)`: تایید شماره موبایل
- `verifyEmail(String token)`: تایید ایمیل (از لینک)
### 4.3. Widget جدید: `VerificationSection`
**ویژگی‌ها:**
- نمایش وضعیت تایید
- Switch برای ویرایش
- فیلد ورودی (غیرفعال/فعال)
- نمایش کپچا قبل از تغییر
- فیلد ورود کد کپچا
- دکمه ارسال/تایید
- اعتبارسنجی
- نمایش Dialog تایید در صورت وجود شماره/ایمیل ثبت‌شده اما تایید نشده
---
## 5. قوانین امنیتی
### 5.1. Rate Limiting
- تغییر شماره موبایل: حداکثر 3 بار در 24 ساعت
- تغییر ایمیل: حداکثر 3 بار در 24 ساعت
- ارسال OTP: حداکثر 3 بار در ساعت (قبلاً وجود دارد)
- ارسال ایمیل تایید: حداکثر 3 بار در ساعت (قبلاً وجود دارد)
### 5.2. اعتبارسنجی
- شماره موبایل: فرمت ایرانی معتبر
- ایمیل: فرمت معتبر و بررسی Domain
- بررسی تکراری نبودن در سیستم:
- ✅ بررسی اینکه شماره/ایمیل توسط کاربر دیگری ثبت نشده باشد
- ✅ بررسی وضعیت تایید (verified/unverified)
- ✅ جلوگیری از استفاده شماره/ایمیل تایید شده توسط کاربر دیگر
### 5.5. کپچا (CAPTCHA)
- ✅ **کپچا الزامی برای تغییر شماره موبایل**: قبل از هر تغییری باید کپچا تایید شود
- ✅ **کپچا الزامی برای تغییر ایمیل**: قبل از هر تغییری باید کپچا تایید شود
- استفاده از سرویس کپچای موجود: `validate_captcha(db, captcha_id, captcha_code)`
- جلوگیری از brute force و spam
- کپچا باید از endpoint `/api/v1/auth/captcha` دریافت شود
### 5.3. محدودیت تغییر
- **شماره تایید شده قابل تغییر نیست**: اگر شماره قبلی تایید شده باشد، کاربر نمی‌تواند آن را تغییر دهد مگر با فرآیند خاص (مثلاً تماس با پشتیبانی)
- **ایمیل تایید شده قابل تغییر نیست**: مشابه شماره موبایل
### 5.4. لاگ و Audit
- ثبت تمام تغییرات شماره موبایل و ایمیل
- ثبت IP و User Agent
- ثبت زمان تغییر
---
## 6. سناریوهای Edge Cases
### 6.1. کاربر شماره موبایل ندارد
- نمایش پیام: "شماره موبایل ثبت نشده است"
- نمایش فیلد خالی
- Switch برای افزودن شماره موبایل
### 6.2. کاربر ایمیل ندارد
- نمایش پیام: "ایمیل ثبت نشده است"
- نمایش فیلد خالی
- Switch برای افزودن ایمیل
### 6.3. شماره موبایل تکراری
**سناریو 1: شماره توسط کاربر دیگری تایید شده**
- بررسی قبل از تغییر
- ❌ نمایش خطا: "این شماره موبایل قبلاً توسط کاربر دیگری ثبت و تایید شده است. لطفاً شماره دیگری وارد کنید."
- جلوگیری از ادامه عملیات
**سناریو 2: شماره ثبت شده اما تایید نشده**
- بررسی قبل از تغییر
- ⚠️ نمایش هشدار: "این شماره موبایل قبلاً ثبت شده است اما تایید نشده است. آیا می‌خواهید ادامه دهید؟"
- درخواست تایید از کاربر (Confirm Dialog)
- در صورت تایید، ادامه عملیات
### 6.4. ایمیل تکراری
**سناریو 1: ایمیل توسط کاربر دیگری تایید شده**
- بررسی قبل از تغییر
- ❌ نمایش خطا: "این ایمیل قبلاً توسط کاربر دیگری ثبت و تایید شده است. لطفاً ایمیل دیگری وارد کنید."
- جلوگیری از ادامه عملیات
**سناریو 2: ایمیل ثبت شده اما تایید نشده**
- بررسی قبل از تغییر
- ⚠️ نمایش هشدار: "این ایمیل قبلاً ثبت شده است اما تایید نشده است. آیا می‌خواهید ادامه دهید؟"
- درخواست تایید از کاربر (Confirm Dialog)
- در صورت تایید، ادامه عملیات
### 6.5. OTP منقضی شده
- نمایش خطا: "کد تایید منقضی شده است"
- دکمه "ارسال مجدد"
### 6.6. خطا در ارسال SMS/Email
- نمایش خطا به کاربر
- پیشنهاد تلاش مجدد بعداً
### 6.7. کپچای نامعتبر
- نمایش خطا: "کد کپچا نامعتبر است"
- امکان دریافت کپچای جدید
- نمایش مجدد فیلد کپچا
### 6.8. شماره/ایمیل ثبت شده اما تایید نشده (نیاز به تایید)
**جریان:**
1. کاربر شماره/ایمیل وارد می‌کند
2. Backend پاسخ می‌دهد: `requires_confirmation: true`
3. Dialog هشدار نمایش داده می‌شود:
```
⚠️ هشدار
این [شماره موبایل/ایمیل] قبلاً ثبت شده است
اما تایید نشده است.
آیا می‌خواهید ادامه دهید؟
[لغو] [ادامه]
```
4. در صورت انتخاب "ادامه"، عملیات ادامه می‌یابد
5. در صورت انتخاب "لغو"، عملیات متوقف می‌شود
### 6.9. شماره/ایمیل تایید شده توسط کاربر دیگر
**جریان:**
1. کاربر شماره/ایمیل وارد می‌کند
2. Backend خطا برمی‌گرداند: `MOBILE_IN_USE_VERIFIED` / `EMAIL_IN_USE_VERIFIED`
3. پیام خطا نمایش داده می‌شود:
```
❌ خطا
این [شماره موبایل/ایمیل] قبلاً توسط کاربر دیگری
ثبت و تایید شده است.
لطفاً [شماره موبایل/ایمیل] دیگری وارد کنید.
[متوجه شدم]
```
4. فیلد برای ورود مجدد باز می‌ماند
---
## 7. UI/UX Considerations
### 7.1. طراحی
- استفاده از Material Design 3
- آیکون‌های واضح برای وضعیت‌ها
- رنگ‌بندی مناسب (سبز برای تایید شده، زرد برای تایید نشده)
- Loading states برای عملیات async
### 7.2. پیام‌ها
- پیام‌های واضح و فارسی
- راهنمایی برای کاربر
- نمایش تعداد تلاش‌های باقی‌مانده برای OTP
### 7.3. دسترسی‌پذیری
- Label مناسب برای فیلدها
- توضیحات برای Screen Readers
- Keyboard Navigation
---
## 8. Testing Scenarios
### 8.1. Unit Tests
- اعتبارسنجی شماره موبایل
- اعتبارسنجی ایمیل
- نرمال‌سازی شماره موبایل
### 8.2. Integration Tests
- تغییر شماره موبایل
- تایید شماره موبایل
- تغییر ایمیل
- تایید ایمیل
### 8.3. Security Tests
- Rate Limiting
- بررسی تغییر شماره/ایمیل تایید شده
- بررسی تکراری نبودن
- تست کپچا:
- کپچای نامعتبر
- کپچای منقضی شده
- کپچای استفاده شده
- تست بررسی تایید شده بودن توسط کاربر دیگر:
- شماره/ایمیل تایید شده توسط کاربر دیگر → باید خطا بدهد
- شماره/ایمیل ثبت شده اما تایید نشده → باید هشدار بدهد
---
## 9. Migration Plan
### Phase 1: Backend Changes
1. افزودن `mobile_verified` به `to_dict()`
2. ایجاد endpoint `update-mobile` (با کپچا)
3. ایجاد endpoint `update-email` (با کپچا)
4. اضافه کردن بررسی تایید شده بودن توسط کاربر دیگر
5. اضافه کردن قوانین امنیتی و کپچا
6. پیاده‌سازی منطق بررسی وضعیت verified/unverified
### Phase 2: Frontend Changes
1. ایجاد `VerificationService`
2. ایجاد `VerificationPage`
3. ایجاد `VerificationSection` widget
4. اتصال به Backend
### Phase 3: Testing & Polish
1. تست تمام سناریوها
2. بررسی UI/UX
3. بررسی عملکرد
---
## 10. API Reference
### 10.1. دریافت اطلاعات کاربر
```
GET /api/v1/auth/me
Response:
{
"success": true,
"data": {
"user": {
"id": 1,
"mobile": "09123456789",
"mobile_verified": true,
"email": "user@example.com",
"email_verified": false,
...
}
}
}
```
### 10.2. دریافت کپچا
```
GET /api/v1/auth/captcha
Response:
{
"success": true,
"data": {
"captcha_id": "cpt_abc123def456",
"image_base64": "iVBORw0KGgoAAAANSUhEUgAA...",
"ttl_seconds": 180
}
}
```
### 10.3. تغییر شماره موبایل
```
POST /api/v1/auth/update-mobile
Body: {
"mobile": "09123456789",
"captcha_id": "cpt_abc123def456",
"captcha_code": "123456"
}
Response:
{
"success": true,
"message": "شماره موبایل با موفقیت به‌روزرسانی شد",
"data": {
"mobile": "09123456789",
"mobile_verified": false
}
}
Error Response (شماره تایید شده توسط کاربر دیگر):
{
"success": false,
"error_code": "MOBILE_IN_USE_VERIFIED",
"message": "این شماره موبایل قبلاً توسط کاربر دیگری ثبت و تایید شده است"
}
```
### 10.4. تغییر ایمیل
```
POST /api/v1/auth/update-email
Body: {
"email": "newemail@example.com",
"captcha_id": "cpt_abc123def456",
"captcha_code": "123456"
}
Response:
{
"success": true,
"message": "ایمیل با موفقیت به‌روزرسانی شد",
"data": {
"email": "newemail@example.com",
"email_verified": false
}
}
Error Response (ایمیل تایید شده توسط کاربر دیگر):
{
"success": false,
"error_code": "EMAIL_IN_USE_VERIFIED",
"message": "این ایمیل قبلاً توسط کاربر دیگری ثبت و تایید شده است"
}
```
---
---
## 11. منطق بررسی تایید شده بودن توسط کاربر دیگر
### 11.1. بررسی شماره موبایل
**Backend Logic (Python):**
```python
def check_mobile_availability(db: Session, mobile: str, current_user_id: int) -> dict:
"""
بررسی اینکه آیا شماره موبایل قابل استفاده است یا نه
Returns:
{
"available": bool,
"message": str,
"requires_confirmation": bool # برای شماره ثبت شده اما تایید نشده
}
"""
repo = UserRepository(db)
existing_user = repo.get_by_mobile(mobile)
if not existing_user:
return {"available": True, "message": "", "requires_confirmation": False}
if existing_user.id == current_user_id:
# همان کاربر است
return {"available": True, "message": "", "requires_confirmation": False}
# کاربر دیگری است
if existing_user.mobile_verified:
return {
"available": False,
"message": "این شماره موبایل قبلاً توسط کاربر دیگری ثبت و تایید شده است",
"requires_confirmation": False
}
else:
return {
"available": False,
"message": "این شماره موبایل قبلاً ثبت شده است اما تایید نشده",
"requires_confirmation": True
}
```
### 11.2. بررسی ایمیل
**Backend Logic (Python):**
```python
def check_email_availability(db: Session, email: str, current_user_id: int) -> dict:
"""
بررسی اینکه آیا ایمیل قابل استفاده است یا نه
Returns:
{
"available": bool,
"message": str,
"requires_confirmation": bool # برای ایمیل ثبت شده اما تایید نشده
}
"""
repo = UserRepository(db)
existing_user = repo.get_by_email(email)
if not existing_user:
return {"available": True, "message": "", "requires_confirmation": False}
if existing_user.id == current_user_id:
# همان کاربر است
return {"available": True, "message": "", "requires_confirmation": False}
# کاربر دیگری است
if existing_user.email_verified:
return {
"available": False,
"message": "این ایمیل قبلاً توسط کاربر دیگری ثبت و تایید شده است",
"requires_confirmation": False
}
else:
return {
"available": False,
"message": "این ایمیل قبلاً ثبت شده است اما تایید نشده",
"requires_confirmation": True
}
```
### 11.3. Endpoint برای بررسی (اختیاری)
می‌توان یک endpoint جداگانه برای بررسی قبل از ارسال درخواست ایجاد کرد:
```
GET /api/v1/auth/check-mobile-availability?mobile=09123456789
GET /api/v1/auth/check-email-availability?email=user@example.com
```
---
## خلاصه
این سناریو یک راه‌حل جامع برای مدیریت تایید شماره موبایل و ایمیل ارائه می‌دهد که:
✅ همه نیازمندی‌ها را پوشش می‌دهد
✅ امنیت را رعایت می‌کند (کپچا + بررسی تایید شده بودن)
✅ جلوگیری از استفاده شماره/ایمیل تایید شده توسط کاربر دیگر
✅ UX مناسب دارد
✅ قابلیت توسعه دارد
✅ قابل تست است
**نکات مهم:**
- ✅ کپچا برای تمام عملیات تغییر شماره/ایمیل الزامی است
- ✅ بررسی دقیق وضعیت تایید شده/نشده توسط کاربر دیگر
- ✅ جلوگیری از استفاده موارد تایید شده توسط کاربر دیگر
- ✅ هشدار برای موارد ثبت شده اما تایید نشده