feat: implement 8 OpenSpec proposals for security, reliability, and UX improvements
## Security Enhancements (P0) - Add input validation with max_length and numeric range constraints - Implement WebSocket token authentication via first message - Add path traversal prevention in file storage service ## Permission Enhancements (P0) - Add project member management for cross-department access - Implement is_department_manager flag for workload visibility ## Cycle Detection (P0) - Add DFS-based cycle detection for task dependencies - Add formula field circular reference detection - Display user-friendly cycle path visualization ## Concurrency & Reliability (P1) - Implement optimistic locking with version field (409 Conflict on mismatch) - Add trigger retry mechanism with exponential backoff (1s, 2s, 4s) - Implement cascade restore for soft-deleted tasks ## Rate Limiting (P1) - Add tiered rate limits: standard (60/min), sensitive (20/min), heavy (5/min) - Apply rate limits to tasks, reports, attachments, and comments ## Frontend Improvements (P1) - Add responsive sidebar with hamburger menu for mobile - Improve touch-friendly UI with proper tap target sizes - Complete i18n translations for all components ## Backend Reliability (P2) - Configure database connection pool (size=10, overflow=20) - Add Redis fallback mechanism with message queue - Add blocker check before task deletion ## API Enhancements (P3) - Add standardized response wrapper utility - Add /health/ready and /health/live endpoints - Implement project templates with status/field copying ## Tests Added - test_input_validation.py - Schema and path traversal tests - test_concurrency_reliability.py - Optimistic locking and retry tests - test_backend_reliability.py - Connection pool and Redis tests - test_api_enhancements.py - Health check and template tests Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,11 +3,19 @@ Rate limiting configuration using slowapi with Redis backend.
|
||||
|
||||
This module provides rate limiting functionality to protect against
|
||||
brute force attacks and DoS attempts on sensitive endpoints.
|
||||
|
||||
Rate Limit Tiers:
|
||||
- standard: 60/minute - For normal CRUD operations (tasks, comments)
|
||||
- sensitive: 20/minute - For sensitive operations (attachments, password change)
|
||||
- heavy: 5/minute - For resource-intensive operations (reports, bulk operations)
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
from functools import wraps
|
||||
from typing import Callable, Optional
|
||||
|
||||
from fastapi import Request, Response
|
||||
from slowapi import Limiter
|
||||
from slowapi.util import get_remote_address
|
||||
|
||||
@@ -60,8 +68,56 @@ _storage_uri = _get_storage_uri()
|
||||
|
||||
# Create limiter instance with appropriate storage
|
||||
# Uses the client's remote address (IP) as the key for rate limiting
|
||||
# Note: headers_enabled=False because slowapi's header injection requires Response objects,
|
||||
# which conflicts with endpoints that return Pydantic models directly.
|
||||
# Rate limit status can be checked via the 429 Too Many Requests response.
|
||||
limiter = Limiter(
|
||||
key_func=get_remote_address,
|
||||
storage_uri=_storage_uri,
|
||||
strategy="fixed-window", # Fixed window strategy for predictable rate limiting
|
||||
headers_enabled=False, # Disabled due to compatibility issues with Pydantic model responses
|
||||
)
|
||||
|
||||
|
||||
# Convenience functions for rate limit tiers
|
||||
def get_rate_limit_standard() -> str:
|
||||
"""Get the standard rate limit tier (60/minute by default)."""
|
||||
return settings.RATE_LIMIT_STANDARD
|
||||
|
||||
|
||||
def get_rate_limit_sensitive() -> str:
|
||||
"""Get the sensitive rate limit tier (20/minute by default)."""
|
||||
return settings.RATE_LIMIT_SENSITIVE
|
||||
|
||||
|
||||
def get_rate_limit_heavy() -> str:
|
||||
"""Get the heavy rate limit tier (5/minute by default)."""
|
||||
return settings.RATE_LIMIT_HEAVY
|
||||
|
||||
|
||||
# Pre-configured rate limit decorators for common use cases
|
||||
def rate_limit_standard(func: Optional[Callable] = None):
|
||||
"""
|
||||
Apply standard rate limit (60/minute) for normal CRUD operations.
|
||||
|
||||
Use for: Task creation/update, comment creation, etc.
|
||||
"""
|
||||
return limiter.limit(get_rate_limit_standard())(func) if func else limiter.limit(get_rate_limit_standard())
|
||||
|
||||
|
||||
def rate_limit_sensitive(func: Optional[Callable] = None):
|
||||
"""
|
||||
Apply sensitive rate limit (20/minute) for sensitive operations.
|
||||
|
||||
Use for: File uploads, password changes, report exports, etc.
|
||||
"""
|
||||
return limiter.limit(get_rate_limit_sensitive())(func) if func else limiter.limit(get_rate_limit_sensitive())
|
||||
|
||||
|
||||
def rate_limit_heavy(func: Optional[Callable] = None):
|
||||
"""
|
||||
Apply heavy rate limit (5/minute) for resource-intensive operations.
|
||||
|
||||
Use for: Report generation, bulk operations, data exports, etc.
|
||||
"""
|
||||
return limiter.limit(get_rate_limit_heavy())(func) if func else limiter.limit(get_rate_limit_heavy())
|
||||
|
||||
Reference in New Issue
Block a user