dateme/DEVELOPMENT.md
2025-12-17 00:44:01 +02:00

540 lines
13 KiB
Markdown

# Development & Architecture Guide
## Project Structure Overview
```
aws-final-project/
├── backend/ # FastAPI Python application
├── frontend/ # React Vite SPA
├── helm/dating-app/ # Kubernetes Helm chart
├── docker-compose.yml # Local dev environment
├── README.md # Main documentation
├── DEPLOYMENT.md # Deployment instructions
└── DEVELOPMENT.md # This file
```
## Backend Architecture
### Core Components
**app/db.py** - Database Connection
- SimpleConnectionPool for connection management
- Auto-initialization of tables on startup
- Safe context manager for connections
**app/config.py** - Configuration Management
- Environment variable loading with defaults
- Settings validation
- Centralized config source
**app/auth/** - Authentication
- `utils.py`: Password hashing (bcrypt), JWT creation/validation
- `__init__.py`: Authorization dependency for FastAPI
**app/models/** - Database Models
- Pure Python classes representing database entities
- User, Profile, Photo, Like, Conversation, Message
- to_dict() methods for serialization
**app/schemas/** - Pydantic Schemas
- Request/response validation
- Type hints and documentation
- Automatic OpenAPI schema generation
**app/services/** - Business Logic
- `auth_service.py`: Registration, login
- `profile_service.py`: Profile CRUD, discovery
- `photo_service.py`: Upload, storage, deletion
- `like_service.py`: Like tracking, match detection
- `chat_service.py`: Message operations, conversations
**app/routers/** - API Endpoints
- Modular organization by feature
- Protected endpoints with `get_current_user` dependency
- Consistent error handling
### Database Design
#### users table
```sql
id (PK), email (UNIQUE), hashed_password, created_at, updated_at
```
#### profiles table
```sql
id (PK), user_id (FK UNIQUE), display_name, age, gender,
location, bio, interests (JSONB), created_at, updated_at
```
#### photos table
```sql
id (PK), profile_id (FK), file_path, display_order, created_at
```
#### likes table
```sql
id (PK), liker_id (FK), liked_id (FK), created_at
UNIQUE(liker_id, liked_id)
```
#### conversations table
```sql
id (PK), user_id_1 (FK), user_id_2 (FK), created_at, updated_at
UNIQUE(user_id_1, user_id_2)
```
#### messages table
```sql
id (PK), conversation_id (FK), sender_id (FK), content, created_at
```
### Key Design Decisions
1. **Synchronous psycopg2** - Per requirements, enables simpler debugging
2. **Connection Pooling** - SimpleConnectionPool provides basic pooling
3. **Auto-initialization** - Tables created on startup, no separate migration step
4. **JWT Tokens** - Stateless auth, no session storage needed
5. **Local File Storage** - Disk-based for lab, easily swappable to S3
6. **Match Logic** - Dual-directional like check in database
### Adding New Features
**Example: Add "message read receipts"**
1. Add schema to `app/schemas/message.py`:
```python
class MessageResponse(BaseModel):
# ... existing fields ...
read_at: Optional[str] = None
```
2. Update database in `app/db.py`:
```python
cur.execute("""
ALTER TABLE messages ADD COLUMN read_at TIMESTAMP
""")
```
3. Add method to `app/services/chat_service.py`:
```python
@staticmethod
def mark_message_read(message_id: int):
# Implementation
```
4. Add endpoint to `app/routers/chat.py`:
```python
@router.patch("/messages/{message_id}/read")
def mark_read(message_id: int, current_user: dict = Depends(get_current_user)):
# Implementation
```
## Frontend Architecture
### Project Structure
```
frontend/src/
├── pages/ # Full page components
│ ├── Login.jsx
│ ├── Register.jsx
│ ├── ProfileEditor.jsx
│ ├── Discover.jsx
│ ├── Matches.jsx
│ └── Chat.jsx
├── styles/ # CSS for each page
│ ├── auth.css
│ ├── profileEditor.css
│ ├── discover.css
│ ├── matches.css
│ └── chat.css
├── api.js # Centralized API client
├── App.jsx # Main app component
├── App.css # Global styles
├── main.jsx # React entry point
└── index.css # Global CSS
```
### API Client Pattern
**src/api.js** provides:
- Axios instance with base configuration
- Request interceptor for JWT token injection
- Response interceptor for 401 handling
- Organized API methods by feature:
- authAPI.register(), authAPI.login()
- profileAPI.getMyProfile(), profileAPI.discoverProfiles()
- etc.
**Usage in components:**
```javascript
import { profileAPI } from '../api'
const response = await profileAPI.getMyProfile()
const profiles = await profileAPI.discoverProfiles()
```
### State Management
**Simple localStorage approach:**
- JWT stored in localStorage, auto-attached to requests
- User ID stored for context
- Component-level state with useState for forms
- No Redux/MobX needed for MVP
**Example:**
```javascript
// After login
localStorage.setItem('token', response.data.access_token)
localStorage.setItem('user_id', response.data.user_id)
// On API calls
// Automatically added by axios interceptor
Authorization: `Bearer ${token}`
// On logout
localStorage.removeItem('token')
localStorage.removeItem('user_id')
```
### Component Patterns
**Page Component Template:**
```jsx
export default function FeaturePage() {
const [data, setData] = useState([])
const [isLoading, setIsLoading] = useState(false)
const [error, setError] = useState('')
useEffect(() => {
loadData()
}, [])
const loadData = async () => {
try {
setIsLoading(true)
const response = await featureAPI.getData()
setData(response.data)
} catch (err) {
setError(err.response?.data?.detail || 'Error')
} finally {
setIsLoading(false)
}
}
return (
<div className="feature-page">
{error && <div className="error-message">{error}</div>}
{/* JSX */}
</div>
)
}
```
### Styling Approach
- CSS modules for component isolation
- Global styles in index.css and App.css
- BEM naming convention for clarity
- Mobile-responsive with flexbox/grid
### Environment Configuration
Frontend uses Vite's import.meta.env:
```javascript
// In src/api.js
const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000'
```
In `frontend/.env`:
```
VITE_API_URL=http://localhost:8000
```
## Docker Build Process
### Backend Dockerfile
```dockerfile
# Multi-stage not needed
# Single stage with Python 3.11
# System dependencies: gcc, postgresql-client
# Python dependencies: fastapi, uvicorn, etc.
# Health check via /health endpoint
# CMD: uvicorn main:app
```
### Frontend Dockerfile
```dockerfile
# Multi-stage: builder + runtime
# Stage 1: Build with Node
# - npm install
# - npm run build -> dist/
# Stage 2: Runtime with nginx
# - nginx:alpine
# - Copy dist to /usr/share/nginx/html
# - Custom nginx.conf for SPA routing
# - Health check via /health endpoint
```
### Nginx Configuration
Handles:
- SPA routing: try_files fallback to index.html
- Static file caching: 1-year expiry for assets
- Deny access to hidden files
- Health check endpoint
## Kubernetes Deployment
### Helm Chart Structure
**Chart.yaml** - Chart metadata
**values.yaml** - Default configuration (override for different environments)
**values-lab.yaml** - Home-lab specific values
- Single replicas
- Local storage classes
- Default passwords (change in production)
**values-aws.yaml** - AWS specific values
- Multiple replicas
- EBS storage class
- ALB ingress class
- RDS database URL
**Templates:**
- `namespace.yaml` - Creates dedicated namespace
- `configmap.yaml` - Backend and frontend config
- `secret.yaml` - PostgreSQL credentials
- `postgres.yaml` - PostgreSQL deployment + PVC + service
- `backend.yaml` - Backend deployment + service
- `frontend.yaml` - Frontend deployment + service
- `ingress.yaml` - Ingress for both services
### Deployment Flow
1. Helm reads values file
2. Templates rendered with values
3. Kubernetes resources created in order:
- Namespace
- ConfigMap, Secret
- PVC
- Postgres deployment waits for PVC
- Backend deployment waits for postgres
- Frontend deployment (no deps)
- Services for each
- Ingress routes traffic
### Network Architecture
```
Internet
|
Ingress (nginx/traefik)
|
+-> Frontend Service (80) -> Frontend Pods
|
+-> Backend Service (8000) -> Backend Pods
|
Postgres Service (5432)
|
Postgres Pod
```
### Storage
**PVC for Postgres:**
- ReadWriteOnce access mode
- Survives pod restarts
- Data persists across deployments
**PVC for Backend Media:**
- ReadWriteMany access mode (for multiple replicas)
- Shared media storage across pods
- Migrates to S3 for cloud deployments
## Development Workflow
### Local Testing
```bash
# 1. Modify code
# 2. Test with compose
docker-compose up -d
curl http://localhost:8000/docs
# 3. Modify Helm values
# 4. Test with Helm (dry-run)
helm install dating-app ./helm/dating-app \
-n dating-app --dry-run --debug
# 5. Test with Helm (actual)
helm install dating-app ./helm/dating-app \
-n dating-app --create-namespace
# 6. Verify
kubectl get all -n dating-app
```
### Code Changes
**Backend changes:**
- Edit Python files in app/
- Changes automatically available in dev environment
- Production requires rebuilding Docker image
**Frontend changes:**
- Edit .jsx files
- Changes automatically available in dev environment
- Production requires rebuilding and redeploying
**Database schema changes:**
- Modify app/db.py init_db()
- For Alembic (future): `alembic revision --autogenerate`
- Existing migrations: Update manually or recreate database
## Performance Considerations
### Backend
- Connection pooling limits: Currently 1-20 connections
- Query optimization: Use indexes on foreign keys
- Response caching: Can add for discover endpoint
- Pagination: Not implemented yet, add for large datasets
### Frontend
- Image optimization: Profile pictures should be compressed
- Lazy loading: Add for discover card images
- Code splitting: Can split by route
- Caching: Service workers for offline support
### Database
- Indexes created on common query columns
- JSONB for interests enables efficient queries
- Unique constraints prevent duplicates
- Foreign keys maintain referential integrity
## Testing Strategy
### Unit Tests (Future)
```python
# backend/tests/
# test_auth.py - Auth functions
# test_services.py - Service logic
# test_routers.py - API endpoints
```
### Integration Tests (Future)
```python
# Full workflow testing
# Database interactions
# API contract validation
```
### E2E Tests (Future)
```javascript
# frontend/tests/
# User registration flow
# Profile creation
# Swiping and matching
# Chat functionality
```
### Manual Testing Checklist
- [ ] Registration with new email
- [ ] Login with correct password
- [ ] Create and update profile
- [ ] Upload multiple photos
- [ ] Delete photos
- [ ] View discover profiles
- [ ] Like a user
- [ ] Check matches
- [ ] Send message to match
- [ ] View conversation history
- [ ] Logout
## Security Considerations
### Current Implementation
- ✅ Password hashing with bcrypt
- ✅ JWT with expiration
- ✅ CORS configured
- ✅ Protected endpoints
- ✅ SQL injection prevention (parameterized queries)
### Recommended Additions
- [ ] Rate limiting on auth endpoints
- [ ] HTTPS/TLS enforcement
- [ ] CSRF token for state-changing operations
- [ ] Input validation and sanitization
- [ ] Audit logging
- [ ] API key authentication for service-to-service
- [ ] Secrets management (Vault)
- [ ] Regular security scanning
- [ ] Penetration testing
### Data Protection
- [ ] Encrypt sensitive data in transit (HTTPS)
- [ ] Encrypt sensitive data at rest
- [ ] Implement data retention policies
- [ ] GDPR compliance (right to delete, data export)
- [ ] Regular backups with encryption
- [ ] Secure backup storage
## Common Issues & Solutions
### Issue: Photo uploads fail
**Cause:** Media directory not writable
**Solution:** Check MEDIA_DIR permissions, ensure PVC mounted
### Issue: Matches not showing
**Cause:** Mutual like check query fails
**Solution:** Verify both users liked each other, check database
### Issue: Slow profile discovery
**Cause:** N+1 query problem
**Solution:** Add query optimization, batch load photos
### Issue: Connection pool exhausted
**Cause:** Too many concurrent requests
**Solution:** Increase pool size, add connection timeout
## Future Enhancements
1. **WebSocket Chat**
- Real-time messages without polling
- Typing indicators
- Read receipts
2. **Image Optimization**
- Automatic compression
- Multiple sizes for responsive design
- CDN distribution
3. **Recommendation Engine**
- Machine learning for match suggestions
- Interest-based filtering
- Location-based matching
4. **Advanced Features**
- Video calls
- Story features
- Search and filtering
- Blocking/reporting
- Verification badges
5. **Infrastructure**
- Load balancing improvements
- Caching layer (Redis)
- Message queue (RabbitMQ) for async tasks
- Monitoring and alerting
- CI/CD pipeline
- Database read replicas