Fix architecture issues from todolist

- Add documentation warnings for in-memory rate limiting and failed login attempts
- Consolidate duplicate health endpoints into api/health.py
- Fix CLI to use correct async rescan method names
- Update download.py and anime.py to use custom exception classes
- Add WebSocket room validation and rate limiting
This commit is contained in:
2025-12-15 14:23:41 +01:00
parent 54790a7ebb
commit 27108aacda
13 changed files with 303 additions and 255 deletions

View File

@@ -2,12 +2,18 @@ import logging
import warnings
from typing import Any, List, Optional
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi import APIRouter, Depends, status
from pydantic import BaseModel, Field
from sqlalchemy.ext.asyncio import AsyncSession
from src.core.entities.series import Serie
from src.server.database.service import AnimeSeriesService
from src.server.exceptions import (
BadRequestError,
NotFoundError,
ServerError,
ValidationError,
)
from src.server.services.anime_service import AnimeService, AnimeServiceError
from src.server.utils.dependencies import (
get_anime_service,
@@ -55,9 +61,8 @@ async def get_anime_status(
"series_count": series_count
}
except Exception as exc:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to get status: {str(exc)}",
raise ServerError(
message=f"Failed to get status: {str(exc)}"
) from exc
@@ -208,35 +213,30 @@ async def list_anime(
try:
page_num = int(page)
if page_num < 1:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail="Page number must be positive"
raise ValidationError(
message="Page number must be positive"
)
page = page_num
except (ValueError, TypeError):
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail="Page must be a valid number"
raise ValidationError(
message="Page must be a valid number"
)
if per_page is not None:
try:
per_page_num = int(per_page)
if per_page_num < 1:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail="Per page must be positive"
raise ValidationError(
message="Per page must be positive"
)
if per_page_num > 1000:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail="Per page cannot exceed 1000"
raise ValidationError(
message="Per page cannot exceed 1000"
)
per_page = per_page_num
except (ValueError, TypeError):
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail="Per page must be a valid number"
raise ValidationError(
message="Per page must be a valid number"
)
# Validate sort_by parameter to prevent ORM injection
@@ -245,9 +245,8 @@ async def list_anime(
allowed_sort_fields = ["title", "id", "missing_episodes", "name"]
if sort_by not in allowed_sort_fields:
allowed = ", ".join(allowed_sort_fields)
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail=f"Invalid sort_by parameter. Allowed: {allowed}"
raise ValidationError(
message=f"Invalid sort_by parameter. Allowed: {allowed}"
)
# Validate filter parameter
@@ -260,9 +259,8 @@ async def list_anime(
lower_filter = filter.lower()
for pattern in dangerous_patterns:
if pattern in lower_filter:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail="Invalid filter parameter"
raise ValidationError(
message="Invalid filter parameter"
)
try:
@@ -310,12 +308,11 @@ async def list_anime(
)
return summaries
except HTTPException:
except (ValidationError, BadRequestError, NotFoundError, ServerError):
raise
except Exception as exc:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to retrieve anime list",
raise ServerError(
message="Failed to retrieve anime list"
) from exc
@@ -346,14 +343,12 @@ async def trigger_rescan(
"message": "Rescan started successfully",
}
except AnimeServiceError as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Rescan failed: {str(e)}",
raise ServerError(
message=f"Rescan failed: {str(e)}"
) from e
except Exception as exc:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to start rescan",
raise ServerError(
message="Failed to start rescan"
) from exc