This commit is contained in:
2025-10-23 18:10:34 +02:00
parent 5c2691b070
commit 9a64ca5b01
14 changed files with 598 additions and 149 deletions

View File

@@ -1,7 +1,7 @@
from typing import Any, List, Optional
from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel
from pydantic import BaseModel, field_validator
from src.server.utils.dependencies import get_series_app, require_auth
@@ -97,7 +97,44 @@ async def trigger_rescan(series_app: Any = Depends(get_series_app)) -> dict:
class SearchRequest(BaseModel):
"""Request model for anime search with validation."""
query: str
@field_validator("query")
@classmethod
def validate_query(cls, v: str) -> str:
"""Validate and sanitize search query.
Args:
v: The search query string
Returns:
str: The validated query
Raises:
ValueError: If query is invalid
"""
if not v or not v.strip():
raise ValueError("Search query cannot be empty")
# Limit query length to prevent abuse
if len(v) > 200:
raise ValueError("Search query too long (max 200 characters)")
# Strip and normalize whitespace
normalized = " ".join(v.strip().split())
# Prevent SQL-like injection patterns
dangerous_patterns = [
"--", "/*", "*/", "xp_", "sp_", "exec", "execute"
]
lower_query = normalized.lower()
for pattern in dangerous_patterns:
if pattern in lower_query:
raise ValueError(f"Invalid character sequence: {pattern}")
return normalized
@router.post("/search", response_model=List[AnimeSummary])