feat: implement security, error resilience, and query optimization proposals

Security Validation (enhance-security-validation):
- JWT secret validation with entropy checking and pattern detection
- CSRF protection middleware with token generation/validation
- Frontend CSRF token auto-injection for DELETE/PUT/PATCH requests
- MIME type validation with magic bytes detection for file uploads

Error Resilience (add-error-resilience):
- React ErrorBoundary component with fallback UI and retry functionality
- ErrorBoundaryWithI18n wrapper for internationalization support
- Page-level and section-level error boundaries in App.tsx

Query Performance (optimize-query-performance):
- Query monitoring utility with threshold warnings
- N+1 query fixes using joinedload/selectinload
- Optimized project members, tasks, and subtasks endpoints

Bug Fixes:
- WebSocket session management (P0): Return primitives instead of ORM objects
- LIKE query injection (P1): Escape special characters in search queries

Tests: 543 backend tests, 56 frontend tests passing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
beabigegg
2026-01-11 18:41:19 +08:00
parent 2cb591ef23
commit 679b89ae4c
41 changed files with 3673 additions and 153 deletions

View File

@@ -286,11 +286,15 @@ class FileStorageService:
return filename.rsplit(".", 1)[-1].lower() if "." in filename else ""
@staticmethod
def validate_file(file: UploadFile) -> Tuple[str, str]:
def validate_file(file: UploadFile, validate_mime: bool = True) -> Tuple[str, str]:
"""
Validate file size and type.
Validate file size, type, and optionally MIME content.
Returns (extension, mime_type) if valid.
Raises HTTPException if invalid.
Args:
file: The uploaded file
validate_mime: If True, validate MIME type using magic bytes detection
"""
# Check file size
file.file.seek(0, 2) # Seek to end
@@ -323,7 +327,35 @@ class FileStorageService:
detail=f"File type '.{extension}' is not supported"
)
mime_type = file.content_type or "application/octet-stream"
# Validate MIME type using magic bytes detection
if validate_mime:
from app.services.mime_validation_service import mime_validation_service
# Read first 16 bytes for magic detection (enough for most signatures)
file_header = file.file.read(16)
file.file.seek(0) # Reset
is_valid, detected_mime, error_message = mime_validation_service.validate_file_content(
file_content=file_header,
declared_extension=extension,
declared_mime_type=file.content_type
)
if not is_valid:
logger.warning(
"MIME validation failed for file '%s': %s (detected: %s)",
file.filename, error_message, detected_mime
)
raise HTTPException(
status_code=400,
detail=error_message or "File type validation failed"
)
# Use detected MIME type if available, otherwise fall back to declared
mime_type = detected_mime if detected_mime else (file.content_type or "application/octet-stream")
else:
mime_type = file.content_type or "application/octet-stream"
return extension, mime_type
async def save_file(