Enhancing documentation
This commit is contained in:
377
docs/guides/user-management.md
Normal file
377
docs/guides/user-management.md
Normal file
@@ -0,0 +1,377 @@
|
||||
# Authentication Usage Examples
|
||||
|
||||
This document provides practical examples of how to use the authentication system in the Ecommerce Backend API.
|
||||
|
||||
## Overview
|
||||
|
||||
The API uses JWT (JSON Web Token) authentication with the following workflow:
|
||||
1. Register a new user account
|
||||
2. Login to receive a JWT token
|
||||
3. Include the token in the `Authorization` header for protected endpoints
|
||||
4. Token expires after 30 minutes (configurable)
|
||||
|
||||
## Python Examples
|
||||
|
||||
### Basic Authentication Functions
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
# API Base URL
|
||||
BASE_URL = "http://localhost:8000"
|
||||
|
||||
def register_user(email, username, password):
|
||||
"""Register a new user"""
|
||||
response = requests.post(
|
||||
f"{BASE_URL}/register",
|
||||
json={"email": email, "username": username, "password": password},
|
||||
)
|
||||
return response.json()
|
||||
|
||||
def login_user(username, password):
|
||||
"""Login and get JWT token"""
|
||||
response = requests.post(
|
||||
f"{BASE_URL}/login", json={"username": username, "password": password}
|
||||
)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
return data["access_token"]
|
||||
else:
|
||||
print(f"Login failed: {response.json()}")
|
||||
return None
|
||||
|
||||
def get_user_info(token):
|
||||
"""Get current user info"""
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
response = requests.get(f"{BASE_URL}/me", headers=headers)
|
||||
return response.json()
|
||||
```
|
||||
|
||||
### Using Protected Endpoints
|
||||
|
||||
```python
|
||||
def get_products(token, skip=0, limit=10):
|
||||
"""Get products (requires authentication)"""
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
response = requests.get(
|
||||
f"{BASE_URL}/products?skip={skip}&limit={limit}", headers=headers
|
||||
)
|
||||
return response.json()
|
||||
|
||||
def create_product(token, product_data):
|
||||
"""Create a new product (requires authentication)"""
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
response = requests.post(f"{BASE_URL}/products", json=product_data, headers=headers)
|
||||
return response.json()
|
||||
```
|
||||
|
||||
### Complete Workflow Example
|
||||
|
||||
```python
|
||||
# Example usage workflow
|
||||
if __name__ == "__main__":
|
||||
# 1. Register a new user
|
||||
print("1. Registering new user...")
|
||||
try:
|
||||
user_result = register_user("test@example.com", "testuser", "password123")
|
||||
print(f"User registered: {user_result}")
|
||||
except Exception as e:
|
||||
print(f"Registration failed: {e}")
|
||||
|
||||
# 2. Login with default admin user
|
||||
print("\n2. Logging in as admin...")
|
||||
admin_token = login_user("admin", "admin123")
|
||||
if admin_token:
|
||||
print(f"Admin login successful! Token: {admin_token[:50]}...")
|
||||
|
||||
# 3. Get user info
|
||||
print("\n3. Getting admin user info...")
|
||||
user_info = get_user_info(admin_token)
|
||||
print(f"User info: {user_info}")
|
||||
|
||||
# 4. Create a sample product
|
||||
print("\n4. Creating a sample product...")
|
||||
sample_product = {
|
||||
"product_id": "TEST001",
|
||||
"title": "Test Product",
|
||||
"description": "A test product for demonstration",
|
||||
"price": "19.99",
|
||||
"brand": "Test Brand",
|
||||
"availability": "in stock",
|
||||
}
|
||||
|
||||
product_result = create_product(admin_token, sample_product)
|
||||
print(f"Product created: {product_result}")
|
||||
|
||||
# 5. Get products list
|
||||
print("\n5. Getting products list...")
|
||||
products = get_products(admin_token)
|
||||
print(f"Products: {products}")
|
||||
|
||||
# 6. Login with regular user
|
||||
print("\n6. Logging in as regular user...")
|
||||
user_token = login_user("testuser", "password123")
|
||||
if user_token:
|
||||
print(f"User login successful! Token: {user_token[:50]}...")
|
||||
|
||||
# Regular users can also access protected endpoints
|
||||
user_info = get_user_info(user_token)
|
||||
print(f"Regular user info: {user_info}")
|
||||
|
||||
products = get_products(user_token, limit=5)
|
||||
print(
|
||||
f"Products accessible to regular user: {len(products.get('products', []))} products"
|
||||
)
|
||||
|
||||
print("\nAuthentication example completed!")
|
||||
```
|
||||
|
||||
## cURL Examples
|
||||
|
||||
### Register a New User
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:8000/register" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"email": "user@example.com",
|
||||
"username": "newuser",
|
||||
"password": "password123"
|
||||
}'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"id": 2,
|
||||
"email": "user@example.com",
|
||||
"username": "newuser",
|
||||
"role": "user",
|
||||
"is_active": true,
|
||||
"created_at": "2024-01-15T10:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### Login (Get JWT Token)
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:8000/login" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"username": "admin",
|
||||
"password": "admin123"
|
||||
}'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
"token_type": "bearer",
|
||||
"expires_in": 1800,
|
||||
"user": {
|
||||
"id": 1,
|
||||
"username": "admin",
|
||||
"email": "admin@example.com",
|
||||
"role": "admin",
|
||||
"is_active": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Use Token for Protected Endpoints
|
||||
|
||||
#### Get Current User Info
|
||||
|
||||
```bash
|
||||
curl -X GET "http://localhost:8000/me" \
|
||||
-H "Authorization: Bearer YOUR_JWT_TOKEN_HERE"
|
||||
```
|
||||
|
||||
#### Get Products List
|
||||
|
||||
```bash
|
||||
curl -X GET "http://localhost:8000/products" \
|
||||
-H "Authorization: Bearer YOUR_JWT_TOKEN_HERE"
|
||||
```
|
||||
|
||||
#### Create a Product
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:8000/products" \
|
||||
-H "Authorization: Bearer YOUR_JWT_TOKEN_HERE" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"product_id": "TEST001",
|
||||
"title": "Test Product",
|
||||
"description": "A test product for demonstration",
|
||||
"price": "19.99",
|
||||
"brand": "Test Brand",
|
||||
"availability": "in stock"
|
||||
}'
|
||||
```
|
||||
|
||||
## Default Accounts
|
||||
|
||||
### Admin Account
|
||||
- **Username**: `admin`
|
||||
- **Password**: `admin123`
|
||||
- **Email**: `admin@example.com`
|
||||
- **Role**: `admin`
|
||||
|
||||
**Security Note**: Change the admin password immediately in production environments!
|
||||
|
||||
## Authentication Headers
|
||||
|
||||
All protected endpoints require the JWT token in the Authorization header:
|
||||
|
||||
```
|
||||
Authorization: Bearer <your_jwt_token>
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Common Authentication Errors
|
||||
|
||||
#### Invalid Credentials (Login)
|
||||
```json
|
||||
{
|
||||
"detail": "Invalid credentials"
|
||||
}
|
||||
```
|
||||
|
||||
#### Missing or Invalid Token
|
||||
```json
|
||||
{
|
||||
"detail": "Not authenticated"
|
||||
}
|
||||
```
|
||||
|
||||
#### Expired Token
|
||||
```json
|
||||
{
|
||||
"detail": "Token has expired"
|
||||
}
|
||||
```
|
||||
|
||||
#### Insufficient Permissions
|
||||
```json
|
||||
{
|
||||
"detail": "Not enough permissions"
|
||||
}
|
||||
```
|
||||
|
||||
### Error Handling in Python
|
||||
|
||||
```python
|
||||
def safe_api_call(token, endpoint, method="GET", data=None):
|
||||
"""Make API call with proper error handling"""
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
|
||||
try:
|
||||
if method == "GET":
|
||||
response = requests.get(f"{BASE_URL}{endpoint}", headers=headers)
|
||||
elif method == "POST":
|
||||
response = requests.post(f"{BASE_URL}{endpoint}", json=data, headers=headers)
|
||||
|
||||
if response.status_code == 401:
|
||||
print("Authentication failed - token may be expired")
|
||||
return None
|
||||
elif response.status_code == 403:
|
||||
print("Access denied - insufficient permissions")
|
||||
return None
|
||||
elif response.status_code == 200:
|
||||
return response.json()
|
||||
else:
|
||||
print(f"API call failed: {response.status_code} - {response.text}")
|
||||
return None
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"Request failed: {e}")
|
||||
return None
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Token Management
|
||||
|
||||
1. **Store tokens securely** - Don't expose tokens in logs or client-side code
|
||||
2. **Handle token expiration** - Implement automatic token refresh or re-login
|
||||
3. **Use HTTPS in production** - Never send tokens over unencrypted connections
|
||||
|
||||
### Password Security
|
||||
|
||||
1. **Use strong passwords** - Minimum 6 characters (configurable)
|
||||
2. **Don't hardcode passwords** - Use environment variables or secure configuration
|
||||
3. **Regular password updates** - Especially for admin accounts
|
||||
|
||||
### API Integration
|
||||
|
||||
1. **Include error handling** - Always check response status codes
|
||||
2. **Implement retry logic** - Handle temporary network issues
|
||||
3. **Rate limiting awareness** - Respect API rate limits
|
||||
|
||||
## Testing Authentication
|
||||
|
||||
You can test the authentication system using the provided Python script or with make commands:
|
||||
|
||||
```bash
|
||||
# Run authentication tests
|
||||
make test-auth
|
||||
|
||||
# Run all tests including authentication
|
||||
make test
|
||||
```
|
||||
|
||||
## Integration with Frontend
|
||||
|
||||
### JavaScript/TypeScript Example
|
||||
|
||||
```javascript
|
||||
class APIClient {
|
||||
constructor(baseURL = 'http://localhost:8000') {
|
||||
this.baseURL = baseURL;
|
||||
this.token = localStorage.getItem('jwt_token');
|
||||
}
|
||||
|
||||
async login(username, password) {
|
||||
const response = await fetch(`${this.baseURL}/login`, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({username, password})
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
this.token = data.access_token;
|
||||
localStorage.setItem('jwt_token', this.token);
|
||||
return data;
|
||||
} else {
|
||||
throw new Error('Login failed');
|
||||
}
|
||||
}
|
||||
|
||||
async apiCall(endpoint, method = 'GET', data = null) {
|
||||
const headers = {
|
||||
'Authorization': `Bearer ${this.token}`,
|
||||
'Content-Type': 'application/json'
|
||||
};
|
||||
|
||||
const config = {method, headers};
|
||||
if (data) config.body = JSON.stringify(data);
|
||||
|
||||
const response = await fetch(`${this.baseURL}${endpoint}`, config);
|
||||
|
||||
if (response.status === 401) {
|
||||
// Token expired, redirect to login
|
||||
localStorage.removeItem('jwt_token');
|
||||
window.location.href = '/login';
|
||||
return;
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This authentication system provides secure access control for all API endpoints while maintaining ease of use for developers integrating with the system.
|
||||
Reference in New Issue
Block a user