881 lines
34 KiB
Markdown
Executable file
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 مناسب دارد
|
|
✅ قابلیت توسعه دارد
|
|
✅ قابل تست است
|
|
|
|
**نکات مهم:**
|
|
- ✅ کپچا برای تمام عملیات تغییر شماره/ایمیل الزامی است
|
|
- ✅ بررسی دقیق وضعیت تایید شده/نشده توسط کاربر دیگر
|
|
- ✅ جلوگیری از استفاده موارد تایید شده توسط کاربر دیگر
|
|
- ✅ هشدار برای موارد ثبت شده اما تایید نشده
|
|
|