This commit is contained in:
Ján Pták 2026-08-14 23:45:48 +02:00
parent 62dd1819cb
commit ba0bb1c8b9

View File

@ -54,11 +54,20 @@ logger = logging.getLogger(__name__)
router = APIRouter() router = APIRouter()
MAX_WEBHOOK_BODY_BYTES = (
2 * 1024 * 1024
)
RETRIEVAL_UNAVAILABLE_DETAIL = ( RETRIEVAL_UNAVAILABLE_DETAIL = (
"Vyhľadávací index alebo embeddingový " "Vyhľadávací index alebo embeddingový "
"model momentálne nie je dostupný." "model momentálne nie je dostupný."
) )
INVALID_QUERY_DETAIL = (
"Neplatný vyhľadávací dotaz."
)
INTERNAL_ERROR_DETAIL = ( INTERNAL_ERROR_DETAIL = (
"Nastala interná chyba servera." "Nastala interná chyba servera."
) )
@ -166,21 +175,16 @@ class HealthResponse(BaseModel):
ready: bool ready: bool
database_exists: bool database_exists: bool
database_path: str
search_engine: str search_engine: str
rag_enabled: bool rag_enabled: bool
zpwiki_root: str
zpwiki_exists: bool zpwiki_exists: bool
security_configured: bool security_configured: bool
class RagSource(BaseModel): class RagSource(BaseModel):
# RAG source sa môže v budúcnosti
# rozšíriť o ďalšie retrieval metadata
# bez rozbitia response modelu.
model_config = ConfigDict( model_config = ConfigDict(
extra="allow", extra="allow",
) )
@ -302,12 +306,17 @@ def raise_retrieval_error(
error, error,
ValueError, ValueError,
): ):
logger.warning(
"Neplatný retrieval dotaz: %s",
error,
)
raise HTTPException( raise HTTPException(
status_code=( status_code=(
status.HTTP_400_BAD_REQUEST status.HTTP_400_BAD_REQUEST
), ),
detail=str( detail=(
error INVALID_QUERY_DETAIL
), ),
) from error ) from error
@ -420,6 +429,79 @@ def configured_repository() -> str:
) from error ) from error
async def read_webhook_body(
request: Request,
) -> bytes:
content_length = request.headers.get(
"content-length"
)
if content_length:
try:
declared_length = int(
content_length
)
except ValueError as error:
raise HTTPException(
status_code=400,
detail=(
"Neplatná Content-Length "
"hlavička"
),
) from error
if declared_length < 0:
raise HTTPException(
status_code=400,
detail=(
"Neplatná Content-Length "
"hlavička"
),
)
if (
declared_length
> MAX_WEBHOOK_BODY_BYTES
):
raise HTTPException(
status_code=413,
detail=(
"Webhook payload je "
"príliš veľký"
),
)
chunks: list[bytes] = []
total_size = 0
async for chunk in request.stream():
total_size += len(
chunk
)
if (
total_size
> MAX_WEBHOOK_BODY_BYTES
):
raise HTTPException(
status_code=413,
detail=(
"Webhook payload je "
"príliš veľký"
),
)
chunks.append(
chunk
)
return b"".join(
chunks
)
@router.get( @router.get(
"/health", "/health",
include_in_schema=False, include_in_schema=False,
@ -436,6 +518,7 @@ def health() -> dict[str, Any]:
try: try:
validate_security_configuration() validate_security_configuration()
security_configured = True security_configured = True
except RuntimeError: except RuntimeError:
@ -453,16 +536,10 @@ def health() -> dict[str, Any]:
"database_exists": ( "database_exists": (
database_exists database_exists
), ),
"database_path": str(
DB_FILE
),
"search_engine": ( "search_engine": (
"hybrid_fts5_embeddings" "hybrid_fts5_embeddings"
), ),
"rag_enabled": True, "rag_enabled": True,
"zpwiki_root": str(
ZPWIKI_ROOT
),
"zpwiki_exists": ( "zpwiki_exists": (
zpwiki_exists zpwiki_exists
), ),
@ -665,10 +742,14 @@ async def gitea_webhook(
dict[str, Any] dict[str, Any]
| JSONResponse | JSONResponse
): ):
raw_body = await request.body()
secret = webhook_secret() secret = webhook_secret()
raw_body = await read_webhook_body(
request
)
# Gitea podpis overujeme nad presným raw
# request body ešte pred JSON parsingom.
if not verify_gitea_signature( if not verify_gitea_signature(
raw_body, raw_body,
x_gitea_signature, x_gitea_signature,