mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-28 20:47:03 -05:00
feat: Add user leaderboard API, Cloudflare Turnstile integration, and support ticket categorization.
This commit is contained in:
64
backend/apps/core/utils/turnstile.py
Normal file
64
backend/apps/core/utils/turnstile.py
Normal file
@@ -0,0 +1,64 @@
|
||||
"""
|
||||
Cloudflare Turnstile validation utilities.
|
||||
|
||||
This module provides a function to validate Turnstile tokens
|
||||
on the server side before processing form submissions.
|
||||
"""
|
||||
import requests
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
def validate_turnstile_token(token: str, ip: str = None) -> dict:
|
||||
"""
|
||||
Validate a Cloudflare Turnstile token.
|
||||
|
||||
Args:
|
||||
token: The Turnstile response token from the client
|
||||
ip: Optional client IP address for additional verification
|
||||
|
||||
Returns:
|
||||
dict with 'success' boolean and optional 'error' message
|
||||
"""
|
||||
# Skip validation if configured (dev mode)
|
||||
if getattr(settings, 'TURNSTILE_SKIP_VALIDATION', False):
|
||||
return {'success': True}
|
||||
|
||||
secret = getattr(settings, 'TURNSTILE_SECRET', '')
|
||||
if not secret:
|
||||
return {'success': True} # Skip if no secret configured
|
||||
|
||||
if not token:
|
||||
return {'success': False, 'error': 'Captcha verification required'}
|
||||
|
||||
try:
|
||||
response = requests.post(
|
||||
'https://challenges.cloudflare.com/turnstile/v0/siteverify',
|
||||
data={
|
||||
'secret': secret,
|
||||
'response': token,
|
||||
'remoteip': ip,
|
||||
},
|
||||
timeout=10
|
||||
)
|
||||
result = response.json()
|
||||
|
||||
if result.get('success'):
|
||||
return {'success': True}
|
||||
else:
|
||||
error_codes = result.get('error-codes', [])
|
||||
return {
|
||||
'success': False,
|
||||
'error': 'Captcha verification failed',
|
||||
'error_codes': error_codes
|
||||
}
|
||||
except requests.RequestException as e:
|
||||
# Log error but don't block user on network issues
|
||||
return {'success': True} # Fail open to avoid blocking legitimate users
|
||||
|
||||
|
||||
def get_client_ip(request):
|
||||
"""Extract client IP from request, handling proxies."""
|
||||
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
|
||||
if x_forwarded_for:
|
||||
return x_forwarded_for.split(',')[0].strip()
|
||||
return request.META.get('REMOTE_ADDR')
|
||||
Reference in New Issue
Block a user