Fixed login redirecting issues
This commit is contained in:
@@ -506,6 +506,172 @@ current_customer: Customer = Depends(get_current_customer_api)
|
||||
current_user: User = Depends(get_current_user)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Optional Authentication Dependencies
|
||||
|
||||
These dependencies return `None` instead of raising exceptions when authentication fails. Used for login pages and public routes that need to conditionally check if a user is authenticated.
|
||||
|
||||
#### `get_current_admin_optional()`
|
||||
|
||||
**Purpose:** Check if admin user is authenticated (without enforcing)
|
||||
**Accepts:** Cookie (`admin_token`) OR Authorization header
|
||||
**Returns:**
|
||||
- `User` object with `role="admin"` if authenticated
|
||||
- `None` if no token, invalid token, or user is not admin
|
||||
**Raises:** Never raises exceptions
|
||||
|
||||
**Usage:**
|
||||
```python
|
||||
# Login page redirect
|
||||
@router.get("/admin/login")
|
||||
async def admin_login_page(
|
||||
request: Request,
|
||||
current_user: Optional[User] = Depends(get_current_admin_optional)
|
||||
):
|
||||
if current_user:
|
||||
# User already logged in, redirect to dashboard
|
||||
return RedirectResponse(url="/admin/dashboard", status_code=302)
|
||||
|
||||
# Not logged in, show login form
|
||||
return templates.TemplateResponse("admin/login.html", {"request": request})
|
||||
```
|
||||
|
||||
**Use Cases:**
|
||||
- Login pages (redirect if already authenticated)
|
||||
- Public pages with conditional admin content
|
||||
- Root redirects based on authentication status
|
||||
|
||||
#### `get_current_vendor_optional()`
|
||||
|
||||
**Purpose:** Check if vendor user is authenticated (without enforcing)
|
||||
**Accepts:** Cookie (`vendor_token`) OR Authorization header
|
||||
**Returns:**
|
||||
- `User` object with `role="vendor"` if authenticated
|
||||
- `None` if no token, invalid token, or user is not vendor
|
||||
**Raises:** Never raises exceptions
|
||||
|
||||
**Usage:**
|
||||
```python
|
||||
# Login page redirect
|
||||
@router.get("/vendor/{vendor_code}/login")
|
||||
async def vendor_login_page(
|
||||
request: Request,
|
||||
vendor_code: str = Path(...),
|
||||
current_user: Optional[User] = Depends(get_current_vendor_optional)
|
||||
):
|
||||
if current_user:
|
||||
# User already logged in, redirect to dashboard
|
||||
return RedirectResponse(url=f"/vendor/{vendor_code}/dashboard", status_code=302)
|
||||
|
||||
# Not logged in, show login form
|
||||
return templates.TemplateResponse("vendor/login.html", {
|
||||
"request": request,
|
||||
"vendor_code": vendor_code
|
||||
})
|
||||
```
|
||||
|
||||
**Use Cases:**
|
||||
- Login pages (redirect if already authenticated)
|
||||
- Public vendor pages with conditional content
|
||||
- Root redirects based on authentication status
|
||||
|
||||
#### `get_current_customer_optional()`
|
||||
|
||||
**Purpose:** Check if customer user is authenticated (without enforcing)
|
||||
**Accepts:** Cookie (`customer_token`) OR Authorization header
|
||||
**Returns:**
|
||||
- `User` object with `role="customer"` if authenticated
|
||||
- `None` if no token, invalid token, or user is not customer
|
||||
**Raises:** Never raises exceptions
|
||||
|
||||
**Usage:**
|
||||
```python
|
||||
# Shop login page redirect
|
||||
@router.get("/shop/account/login")
|
||||
async def customer_login_page(
|
||||
request: Request,
|
||||
current_user: Optional[User] = Depends(get_current_customer_optional)
|
||||
):
|
||||
if current_user:
|
||||
# User already logged in, redirect to account page
|
||||
return RedirectResponse(url="/shop/account", status_code=302)
|
||||
|
||||
# Not logged in, show login form
|
||||
return templates.TemplateResponse("shop/login.html", {"request": request})
|
||||
```
|
||||
|
||||
**Use Cases:**
|
||||
- Login pages (redirect if already authenticated)
|
||||
- Public shop pages with conditional customer content (e.g., "My Orders" link)
|
||||
- Root redirects based on authentication status
|
||||
|
||||
---
|
||||
|
||||
### Required vs Optional Dependencies
|
||||
|
||||
Understanding when to use each type:
|
||||
|
||||
#### Admin Context
|
||||
|
||||
| Scenario | Use | Returns | On Auth Failure |
|
||||
|----------|-----|---------|-----------------|
|
||||
| **Protected page (dashboard, settings)** | `get_current_admin_from_cookie_or_header` | `User` | Raises 401 exception |
|
||||
| **Login page** | `get_current_admin_optional` | `Optional[User]` | Returns `None` |
|
||||
| **API endpoint** | `get_current_admin_api` | `User` | Raises 401 exception |
|
||||
| **Public page with conditional content** | `get_current_admin_optional` | `Optional[User]` | Returns `None` |
|
||||
|
||||
#### Vendor Context
|
||||
|
||||
| Scenario | Use | Returns | On Auth Failure |
|
||||
|----------|-----|---------|-----------------|
|
||||
| **Protected page (dashboard, products)** | `get_current_vendor_from_cookie_or_header` | `User` | Raises 401 exception |
|
||||
| **Login page** | `get_current_vendor_optional` | `Optional[User]` | Returns `None` |
|
||||
| **API endpoint** | `get_current_vendor_api` | `User` | Raises 401 exception |
|
||||
| **Public page with conditional content** | `get_current_vendor_optional` | `Optional[User]` | Returns `None` |
|
||||
|
||||
#### Customer Context
|
||||
|
||||
| Scenario | Use | Returns | On Auth Failure |
|
||||
|----------|-----|---------|-----------------|
|
||||
| **Protected page (account, orders)** | `get_current_customer_from_cookie_or_header` | `User` | Raises 401 exception |
|
||||
| **Login page** | `get_current_customer_optional` | `Optional[User]` | Returns `None` |
|
||||
| **API endpoint** | `get_current_customer_api` | `User` | Raises 401 exception |
|
||||
| **Public page with conditional content** | `get_current_customer_optional` | `Optional[User]` | Returns `None` |
|
||||
|
||||
**Example Flow:**
|
||||
|
||||
```python
|
||||
# ❌ WRONG: Using required auth on login page
|
||||
@router.get("/admin/login")
|
||||
async def admin_login_page(
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header)
|
||||
):
|
||||
# This will return 401 error if not logged in!
|
||||
# Login page will never render for unauthenticated users
|
||||
...
|
||||
|
||||
# ✅ CORRECT: Using optional auth on login page
|
||||
@router.get("/admin/login")
|
||||
async def admin_login_page(
|
||||
current_user: Optional[User] = Depends(get_current_admin_optional)
|
||||
):
|
||||
# Returns None if not logged in, page renders normally
|
||||
if current_user:
|
||||
return RedirectResponse(url="/admin/dashboard")
|
||||
return templates.TemplateResponse("login.html", ...)
|
||||
|
||||
|
||||
# ✅ CORRECT: Using required auth on protected page
|
||||
@router.get("/admin/dashboard")
|
||||
async def admin_dashboard(
|
||||
current_user: User = Depends(get_current_admin_from_cookie_or_header)
|
||||
):
|
||||
# Automatically returns 401 if not authenticated
|
||||
# Only runs if user is authenticated admin
|
||||
...
|
||||
```
|
||||
|
||||
### Login Response Format
|
||||
|
||||
All login endpoints return:
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
There are three ways depending on the deployment mode:
|
||||
|
||||
**⚠️ Important:** This guide describes **customer-facing shop routes**. For vendor dashboard/management routes, see [Vendor Dashboard Documentation](../../vendor/). The shop uses `/vendors/{code}/shop/*` (plural) in path-based mode, while the vendor dashboard uses `/vendor/{code}/*` (singular).
|
||||
**⚠️ Important:** This guide describes **customer-facing shop routes**. For vendor dashboard/management routes, see [Vendor Frontend Architecture](../../frontend/vendor/architecture.md). The shop uses `/vendors/{code}/shop/*` (plural) in path-based mode, while the vendor dashboard uses `/vendor/{code}/*` (singular).
|
||||
|
||||
### 1. **SUBDOMAIN MODE** (Production - Recommended)
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user