turnstile is working - keep SSL turned of on dev

This commit is contained in:
David Bruno Vontor
2026-06-11 11:35:36 +02:00
parent 192143bfb6
commit 5ca62497b1
12 changed files with 245 additions and 79 deletions

View File

@@ -54,14 +54,11 @@ DEFAULT_FROM_EMAIL=
USE_S3=False
# RustFS (docker-compose default — S3-compatible MinIO successor)
AWS_S3_ENDPOINT_URL=http://rustfs:9000
AWS_S3_CUSTOM_DOMAIN=localhost:9000/vontor
AWS_STORAGE_BUCKET_NAME=vontor
AWS_ACCESS_KEY_ID=rustfsadmin
AWS_SECRET_ACCESS_KEY=rustfsadmin
RUSTFS_ACCESS_KEY=rustfsadmin
RUSTFS_SECRET_KEY=rustfsadmin
RUSTFS_BUCKET_NAME=vontor
AWS_S3_ENDPOINT_URL=https://s3.vontor.cz
AWS_S3_CUSTOM_DOMAIN=s3.vontor.cz
AWS_STORAGE_BUCKET_NAME=vontor-cz
AWS_ACCESS_KEY_ID=pO70oxXGV4R6OSHxNmzv
AWS_SECRET_ACCESS_KEY=1gY19XzWBOWiIkDKvCQF8Xkc72mFX4iILkBBV0ML
# AWS S3 (swap in for production — clear AWS_S3_ENDPOINT_URL)
# AWS_STORAGE_BUCKET_NAME=my-bucket
@@ -80,4 +77,7 @@ RUSTFS_BUCKET_NAME=vontor
# -- ČSOB API --
CSOB_MERCHANT_ID=A6680stogb
CSOB_API_URL=https://iapi.iplatebnibrana.csob.cz/ # PŘI PRODUKCI VYMĚNIT ZA REALNE API!!!!
CSOB_API_URL=https://iapi.iplatebnibrana.csob.cz/ # PŘI PRODUKCI VYMĚNIT ZA REALNE API!!!!
# -- TURNSTILE CAPTCHA --
SECRET_KEY_TURNSTILE=xxx

View File

@@ -25,6 +25,7 @@ from rest_framework_simplejwt.exceptions import TokenError, AuthenticationFailed
from django_filters.rest_framework import DjangoFilterBackend
from drf_spectacular.utils import extend_schema, OpenApiResponse, OpenApiExample, OpenApiParameter
from vontor_cz.turnstile import verify_turnstile
User = get_user_model()
@@ -52,6 +53,11 @@ class CookieTokenObtainPairView(TokenObtainPairView):
def post(self, request, *args, **kwargs):
turnstile_token = request.data.get("turnstile_token", "")
remote_ip = request.META.get("HTTP_X_FORWARDED_FOR", request.META.get("REMOTE_ADDR", ""))
if not verify_turnstile(turnstile_token, remote_ip):
return Response({"detail": "Ověření CAPTCHA selhalo."}, status=status.HTTP_400_BAD_REQUEST)
serializer = self.get_serializer(data=request.data)
try:
serializer.is_valid(raise_exception=True)
@@ -310,6 +316,11 @@ class UserRegistrationViewSet(ModelViewSet):
http_method_names = ['post']
def create(self, request, *args, **kwargs):
turnstile_token = request.data.get("turnstile_token", "")
remote_ip = request.META.get("HTTP_X_FORWARDED_FOR", request.META.get("REMOTE_ADDR", ""))
if not verify_turnstile(turnstile_token, remote_ip):
return Response({"detail": "Ověření CAPTCHA selhalo."}, status=status.HTTP_400_BAD_REQUEST)
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.save()

View File

@@ -9,6 +9,7 @@ from drf_spectacular.utils import extend_schema, extend_schema_view
from .models import ContactMe
from .serializer import ContactMeSerializer
from .tasks import send_contact_me_email_task, send_newly_added_items_to_store_email_task_last_week
from vontor_cz.turnstile import verify_turnstile
@extend_schema(tags=["advertisement", "public"])
@@ -26,6 +27,11 @@ class ContactMePublicView(APIView):
if honeypot:
return Response({"status": "ok"}, status=status.HTTP_200_OK)
turnstile_token = request.data.get("turnstile_token", "")
remote_ip = request.META.get("HTTP_X_FORWARDED_FOR", request.META.get("REMOTE_ADDR", ""))
if not verify_turnstile(turnstile_token, remote_ip):
return Response({"detail": "Ověření CAPTCHA selhalo."}, status=status.HTTP_400_BAD_REQUEST)
if not email or not message:
return Response({"detail": "Missing email or message."}, status=status.HTTP_400_BAD_REQUEST)

View File

@@ -958,6 +958,9 @@ GOPAY_GATEWAY_URL = os.getenv("GOPAY_GATEWAY_URL", "https://gw.sandbox.gopay.com
# New: absolute URL that GoPay calls (publicly reachable)
GOPAY_NOTIFICATION_URL = os.getenv("GOPAY_NOTIFICATION_URL", "http://localhost:8000/api/payments/gopay/webhook")
# --- Cloudflare Turnstile ---
CLOUDFLARE_TURNSTILE_SECRET_KEY = os.getenv("SECRET_KEY_TURNSTILE", "")
# -------------------------------------DOWNLOADER LIMITS------------------------------------
DOWNLOADER_MAX_SIZE_MB = int(os.getenv("DOWNLOADER_MAX_SIZE_MB", "200")) # Raspberry Pi safe cap
DOWNLOADER_MAX_SIZE_BYTES = DOWNLOADER_MAX_SIZE_MB * 1024 * 1024

View File

@@ -0,0 +1,33 @@
import logging
import requests
from django.conf import settings
logger = logging.getLogger(__name__)
SITEVERIFY_URL = "https://challenges.cloudflare.com/turnstile/v0/siteverify"
def verify_turnstile(token: str, remote_ip: str | None = None) -> bool:
"""
Verify a Cloudflare Turnstile token against the siteverify API.
Returns True if valid, False otherwise.
If CLOUDFLARE_TURNSTILE_SECRET_KEY is not configured, skips verification (dev bypass).
"""
secret = getattr(settings, "CLOUDFLARE_TURNSTILE_SECRET_KEY", "")
if not secret:
logger.debug("Turnstile: no secret key configured, skipping verification.")
return True
payload = {"secret": secret, "response": token}
if remote_ip:
payload["remoteip"] = remote_ip
try:
resp = requests.post(SITEVERIFY_URL, data=payload, timeout=5)
result = resp.json()
if not result.get("success"):
logger.warning("Turnstile verification failed: %s", result.get("error-codes"))
return bool(result.get("success"))
except Exception as e:
logger.error("Turnstile: siteverify request failed: %s", e)
return False