433 lines
11 KiB
Markdown
433 lines
11 KiB
Markdown
|
|
# Authentication & Account API Documentation
|
||
|
|
|
||
|
|
## فهرست مطالب
|
||
|
|
|
||
|
|
- [مکانیزم احراز هویت](#مکانیزم-احراز-هویت)
|
||
|
|
- [فرمت کلی پاسخها](#فرمت-کلی-پاسخها)
|
||
|
|
- [مدل کاربر](#مدل-کاربر)
|
||
|
|
- [Auth Endpoints](#auth-endpoints)
|
||
|
|
- [ثبتنام](#1-ثبتنام)
|
||
|
|
- [ورود با رمز عبور](#2-ورود-با-رمز-عبور)
|
||
|
|
- [درخواست OTP](#3-درخواست-otp)
|
||
|
|
- [تأیید OTP](#4-تأیید-otp)
|
||
|
|
- [رفرش توکن](#5-رفرش-توکن)
|
||
|
|
- [Account Endpoints](#account-endpoints)
|
||
|
|
- [آپدیت پروفایل](#1-آپدیت-پروفایل)
|
||
|
|
- [احراز هویت در درخواستها](#احراز-هویت-در-درخواستها)
|
||
|
|
- [کدهای خطا](#کدهای-خطا)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## مکانیزم احراز هویت
|
||
|
|
|
||
|
|
پروژه از **JWT (JSON Web Token)** با کتابخانه `djangorestframework-simplejwt` استفاده میکند.
|
||
|
|
|
||
|
|
- هر بار که کاربر ثبتنام یا لاگین موفق انجام میدهد، دو توکن دریافت میکند:
|
||
|
|
- **`access`** — توکن کوتاهمدت برای احراز هویت درخواستها
|
||
|
|
- **`refresh`** — توکن بلندمدت برای گرفتن `access` جدید
|
||
|
|
- برای اندپوینتهایی که نیاز به احراز هویت دارند، باید توکن `access` را در هدر `Authorization` ارسال کنید:
|
||
|
|
|
||
|
|
```
|
||
|
|
Authorization: Bearer <access_token>
|
||
|
|
```
|
||
|
|
|
||
|
|
- Backend احراز هویت: `MultiFieldBackend` — کاربر میتواند با `username`، `email` یا `phone_number` لاگین کند.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## فرمت کلی پاسخها
|
||
|
|
|
||
|
|
همه پاسخها از یک ساختار یکسان پیروی میکنند:
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"code": 200,
|
||
|
|
"msg": "success",
|
||
|
|
"data": { ... }
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
| فیلد | نوع | توضیح |
|
||
|
|
|---------|---------|---------------------------------------------|
|
||
|
|
| `code` | integer | کد وضعیت (مشابه HTTP status) |
|
||
|
|
| `msg` | string | پیام وضعیت (`"success"` یا متن خطا) |
|
||
|
|
| `data` | object | دادههای برگشتی (در صورت وجود) |
|
||
|
|
| `token` | object | توکنهای JWT (فقط در پاسخهای auth) |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## مدل کاربر
|
||
|
|
|
||
|
|
شیء `AuthUser` که در پاسخهای احراز هویت و پروفایل برگردانده میشود:
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"id": 1,
|
||
|
|
"username": "john_doe",
|
||
|
|
"email": "john@example.com",
|
||
|
|
"first_name": "John",
|
||
|
|
"last_name": "Doe",
|
||
|
|
"phone_number": "09121234567"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Auth Endpoints
|
||
|
|
|
||
|
|
Base URL: `/api/auth/`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 1. ثبتنام
|
||
|
|
|
||
|
|
**`POST /api/auth/register/`**
|
||
|
|
|
||
|
|
ساخت حساب کاربری جدید با نام کاربری، ایمیل، شماره موبایل و رمز عبور.
|
||
|
|
|
||
|
|
#### Request Body
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"username": "john_doe",
|
||
|
|
"email": "john@example.com",
|
||
|
|
"phone_number": "09121234567",
|
||
|
|
"password": "securepass123",
|
||
|
|
"first_name": "John",
|
||
|
|
"last_name": "Doe"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
| فیلد | نوع | الزامی | توضیح |
|
||
|
|
|----------------|--------|--------|-------------------------------|
|
||
|
|
| `username` | string | ✅ | حداکثر ۱۵۰ کاراکتر، یکتا |
|
||
|
|
| `email` | string | ✅ | فرمت ایمیل، یکتا |
|
||
|
|
| `phone_number` | string | ✅ | حداکثر ۳۲ کاراکتر، یکتا |
|
||
|
|
| `password` | string | ✅ | حداقل ۸ کاراکتر |
|
||
|
|
| `first_name` | string | ❌ | حداکثر ۱۵۰ کاراکتر |
|
||
|
|
| `last_name` | string | ❌ | حداکثر ۱۵۰ کاراکتر |
|
||
|
|
|
||
|
|
#### Response موفق — `201 Created`
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"code": 201,
|
||
|
|
"msg": "success",
|
||
|
|
"data": {
|
||
|
|
"id": 1,
|
||
|
|
"username": "john_doe",
|
||
|
|
"email": "john@example.com",
|
||
|
|
"first_name": "John",
|
||
|
|
"last_name": "Doe",
|
||
|
|
"phone_number": "09121234567"
|
||
|
|
},
|
||
|
|
"token": {
|
||
|
|
"access": "<access_token>",
|
||
|
|
"refresh": "<refresh_token>"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Response خطا — `400 Bad Request`
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"code": 400,
|
||
|
|
"msg": "A user with this username already exists."
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
پیامهای خطای احتمالی:
|
||
|
|
- `"A user with this username already exists."`
|
||
|
|
- `"A user with this email already exists."`
|
||
|
|
- `"A user with this phone number already exists."`
|
||
|
|
- `"A user with these credentials already exists."`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 2. ورود با رمز عبور
|
||
|
|
|
||
|
|
**`POST /api/auth/login/`**
|
||
|
|
|
||
|
|
ورود با استفاده از `username`، `email` یا `phone_number` به همراه رمز عبور.
|
||
|
|
|
||
|
|
#### Request Body
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"identifier": "john_doe",
|
||
|
|
"password": "securepass123"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
| فیلد | نوع | الزامی | توضیح |
|
||
|
|
|--------------|--------|--------|-----------------------------------------------------|
|
||
|
|
| `identifier` | string | ✅ | میتواند `username`، `email` یا `phone_number` باشد |
|
||
|
|
| `password` | string | ✅ | رمز عبور کاربر |
|
||
|
|
|
||
|
|
#### Response موفق — `200 OK`
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"code": 200,
|
||
|
|
"msg": "success",
|
||
|
|
"data": {
|
||
|
|
"id": 1,
|
||
|
|
"username": "john_doe",
|
||
|
|
"email": "john@example.com",
|
||
|
|
"first_name": "John",
|
||
|
|
"last_name": "Doe",
|
||
|
|
"phone_number": "09121234567"
|
||
|
|
},
|
||
|
|
"token": {
|
||
|
|
"access": "<access_token>",
|
||
|
|
"refresh": "<refresh_token>"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Response خطا — `401 Unauthorized`
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"code": 401,
|
||
|
|
"msg": "Invalid credentials."
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 3. درخواست OTP
|
||
|
|
|
||
|
|
**`POST /api/auth/request-otp/`**
|
||
|
|
|
||
|
|
> ⚠️ این endpoint در حال حاضر در `urls.py` کامنت شده است (غیرفعال).
|
||
|
|
|
||
|
|
ارسال کد یکبار مصرف (OTP) به شماره موبایل از طریق SMS.ir.
|
||
|
|
|
||
|
|
#### Request Body
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"phone_number": "09121234567"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
| فیلد | نوع | الزامی | توضیح |
|
||
|
|
|----------------|--------|--------|---------------------|
|
||
|
|
| `phone_number` | string | ✅ | حداکثر ۳۲ کاراکتر |
|
||
|
|
|
||
|
|
#### Response موفق — `200 OK`
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"code": 200,
|
||
|
|
"msg": "success",
|
||
|
|
"token": "<otp_token>"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
| فیلد | توضیح |
|
||
|
|
|---------------|--------------------------------------------------------------|
|
||
|
|
| `token` | توکن امضاشده که باید در مرحله verify-otp ارسال شود |
|
||
|
|
| `sms_warning` | (اختیاری) در صورت شکست ارسال پیامک ظاهر میشود |
|
||
|
|
| `debug_otp` | (اختیاری) فقط در حالت `DEBUG=True` — کد OTP در پاسخ میآید |
|
||
|
|
|
||
|
|
> کد OTP مدت اعتبار **۳۰۰ ثانیه (۵ دقیقه)** دارد.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 4. تأیید OTP
|
||
|
|
|
||
|
|
**`POST /api/auth/verify-otp/`**
|
||
|
|
|
||
|
|
> ⚠️ این endpoint در حال حاضر در `urls.py` کامنت شده است (غیرفعال).
|
||
|
|
|
||
|
|
تأیید کد OTP دریافتشده و ورود/ثبتنام خودکار کاربر.
|
||
|
|
|
||
|
|
#### Request Body
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"token": "<otp_token>",
|
||
|
|
"otp_code": "123456"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
| فیلد | نوع | الزامی | توضیح |
|
||
|
|
|------------|--------|--------|-------------------------------------------|
|
||
|
|
| `token` | string | ✅ | توکن دریافتشده از مرحله request-otp |
|
||
|
|
| `otp_code` | string | ✅ | کد ۶ رقمی ارسالشده به موبایل |
|
||
|
|
|
||
|
|
#### Response موفق — `200 OK`
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"code": 200,
|
||
|
|
"msg": "success",
|
||
|
|
"data": {
|
||
|
|
"id": 1,
|
||
|
|
"username": "09121234567",
|
||
|
|
"email": "09121234567@otp.local",
|
||
|
|
"first_name": "",
|
||
|
|
"last_name": "",
|
||
|
|
"phone_number": "09121234567"
|
||
|
|
},
|
||
|
|
"token": {
|
||
|
|
"access": "<access_token>",
|
||
|
|
"refresh": "<refresh_token>"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
> اگر کاربر با این شماره موبایل قبلاً ثبتنام نکرده باشد، حساب جدید بهصورت خودکار ساخته میشود.
|
||
|
|
|
||
|
|
#### Response خطا — `400 Bad Request`
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"code": 400,
|
||
|
|
"msg": "Token is invalid or expired."
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
یا:
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"code": 400,
|
||
|
|
"msg": "OTP code is invalid or expired."
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 5. رفرش توکن
|
||
|
|
|
||
|
|
**`POST /api/auth/token/refresh/`**
|
||
|
|
|
||
|
|
دریافت `access` token جدید با استفاده از `refresh` token.
|
||
|
|
|
||
|
|
> این endpoint توسط `djangorestframework-simplejwt` بهصورت پیشفرض فراهم میشود.
|
||
|
|
|
||
|
|
#### Request Body
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"refresh": "<refresh_token>"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Response موفق — `200 OK`
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"access": "<new_access_token>"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Account Endpoints
|
||
|
|
|
||
|
|
Base URL: `/api/account/`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 1. آپدیت پروفایل
|
||
|
|
|
||
|
|
**`PATCH /api/account/profile/`**
|
||
|
|
|
||
|
|
> 🔒 نیاز به احراز هویت دارد — هدر `Authorization: Bearer <access_token>` الزامی است.
|
||
|
|
|
||
|
|
ویرایش اطلاعات پروفایل کاربر لاگینشده.
|
||
|
|
|
||
|
|
#### Request Body
|
||
|
|
|
||
|
|
همه فیلدها اختیاری هستند (partial update):
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"first_name": "علی",
|
||
|
|
"last_name": "احمدی",
|
||
|
|
"email": "new_email@example.com"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
| فیلد | نوع | الزامی | توضیح |
|
||
|
|
|--------------|--------|--------|---------------------|
|
||
|
|
| `first_name` | string | ❌ | حداکثر ۱۵۰ کاراکتر |
|
||
|
|
| `last_name` | string | ❌ | حداکثر ۱۵۰ کاراکتر |
|
||
|
|
| `email` | string | ❌ | فرمت ایمیل معتبر |
|
||
|
|
|
||
|
|
#### Response موفق — `200 OK`
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"code": 200,
|
||
|
|
"msg": "success",
|
||
|
|
"data": {
|
||
|
|
"id": 1,
|
||
|
|
"username": "john_doe",
|
||
|
|
"email": "new_email@example.com",
|
||
|
|
"first_name": "علی",
|
||
|
|
"last_name": "احمدی",
|
||
|
|
"phone_number": "09121234567"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Response خطا — `401 Unauthorized`
|
||
|
|
|
||
|
|
در صورت نبود یا منقضی بودن توکن:
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"detail": "Authentication credentials were not provided."
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## احراز هویت در درخواستها
|
||
|
|
|
||
|
|
برای اندپوینتهایی که نیاز به احراز هویت دارند (مانند `PATCH /api/account/profile/`)، توکن `access` را در هدر HTTP ارسال کنید:
|
||
|
|
|
||
|
|
```
|
||
|
|
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||
|
|
```
|
||
|
|
|
||
|
|
### چرخه عمر توکن
|
||
|
|
|
||
|
|
```
|
||
|
|
[ثبتنام / لاگین]
|
||
|
|
↓
|
||
|
|
دریافت access + refresh
|
||
|
|
↓
|
||
|
|
ارسال درخواستها با access
|
||
|
|
↓
|
||
|
|
منقضی شدن access (401)
|
||
|
|
↓
|
||
|
|
ارسال refresh به POST /api/auth/token/refresh/
|
||
|
|
↓
|
||
|
|
دریافت access جدید
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## کدهای خطا
|
||
|
|
|
||
|
|
| HTTP Status | code | معنا |
|
||
|
|
|-------------|------|-----------------------------------------------|
|
||
|
|
| 201 | 201 | ثبتنام موفق |
|
||
|
|
| 200 | 200 | عملیات موفق |
|
||
|
|
| 400 | 400 | دادههای نامعتبر یا OTP/توکن اشتباه |
|
||
|
|
| 401 | 401 | احراز هویت ناموفق (رمز اشتباه یا بدون توکن) |
|
||
|
|
|
||
|
|
> پاسخهای خطای اعتبارسنجی serializer (مانند فیلد اجباری) با فرمت استاندارد DRF برگردانده میشوند:
|
||
|
|
> ```json
|
||
|
|
> {
|
||
|
|
> "field_name": ["This field is required."]
|
||
|
|
> }
|
||
|
|
> ```
|