89 lines
3.4 KiB
Python
89 lines
3.4 KiB
Python
from fastapi import APIRouter, HTTPException, Request, status
|
|
|
|
from app.config import settings
|
|
from app.schemas.booking import BookingCaptchaChallenge, BookingRequestCreate, BookingRequestResponse
|
|
from app.services.booking_security import (
|
|
create_captcha_challenge,
|
|
get_client_ip,
|
|
is_rate_limited,
|
|
new_request_id,
|
|
verify_captcha,
|
|
write_booking_audit_event,
|
|
)
|
|
from app.services.mailer import MailConfigurationError, send_booking_request_email
|
|
|
|
|
|
router = APIRouter(prefix="/api", tags=["booking"])
|
|
|
|
|
|
@router.get("/booking-captcha", response_model=BookingCaptchaChallenge)
|
|
def get_booking_captcha() -> BookingCaptchaChallenge:
|
|
return create_captcha_challenge()
|
|
|
|
|
|
@router.post("/booking-request", response_model=BookingRequestResponse)
|
|
def create_booking_request(request: Request, payload: BookingRequestCreate) -> BookingRequestResponse:
|
|
request_id = new_request_id()
|
|
write_booking_audit_event("received", request_id=request_id, request=request, payload=payload)
|
|
|
|
if not settings.booking_form_enabled:
|
|
write_booking_audit_event("blocked_form_disabled", request_id=request_id, request=request, payload=payload)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
detail="Form in aggiornamento.",
|
|
)
|
|
|
|
if payload.website:
|
|
write_booking_audit_event("blocked_honeypot", request_id=request_id, request=request, payload=payload)
|
|
return BookingRequestResponse(
|
|
message="La richiesta è stata inviata correttamente e sarà presa in carico al più presto dal team.",
|
|
)
|
|
|
|
client_ip = get_client_ip(request)
|
|
if is_rate_limited(client_ip):
|
|
write_booking_audit_event("blocked_rate_limit", request_id=request_id, request=request, payload=payload)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
|
|
detail="Sono state inviate troppe richieste. Riprova più tardi.",
|
|
)
|
|
|
|
if not verify_captcha(payload.captcha_id, payload.captcha_answer):
|
|
write_booking_audit_event("blocked_captcha", request_id=request_id, request=request, payload=payload)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="Verifica anti-spam non valida. Ricarica il codice e riprova.",
|
|
)
|
|
|
|
try:
|
|
send_booking_request_email(payload)
|
|
except MailConfigurationError as exc:
|
|
write_booking_audit_event(
|
|
"failed_configuration",
|
|
request_id=request_id,
|
|
request=request,
|
|
payload=payload,
|
|
error=exc,
|
|
)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
detail="Il servizio email non è ancora configurato.",
|
|
) from exc
|
|
except Exception as exc: # pragma: no cover - mail delivery path
|
|
write_booking_audit_event(
|
|
"failed_delivery",
|
|
request_id=request_id,
|
|
request=request,
|
|
payload=payload,
|
|
error=exc,
|
|
)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail="Si è verificato un problema durante l'invio della richiesta.",
|
|
) from exc
|
|
|
|
write_booking_audit_event("sent", request_id=request_id, request=request, payload=payload)
|
|
|
|
return BookingRequestResponse(
|
|
message="La richiesta è stata inviata correttamente e sarà presa in carico al più presto dal team.",
|
|
)
|