Files
domnitor/app/Views/auth/_captcha-widget.twig
Hosteroid 4818172bc6 Switch PHP views to Twig and add 2FA/UI enhancements
Migrate many view templates from raw PHP to Twig and modernize UI/UX for 2FA and settings. Controllers updated to provide avatar data and two-factor info (ProfileController, UserController) and SettingsController now includes timezone lists, notification preset selection, cron path, cached update state and rollback availability. ErrorHandler now attempts to render error pages via a new Core\TwigService with a safe fallback to raw PHP views. TwoFactorService generation silences deprecated warnings during QR code creation. Numerous .php view files were removed and replaced with .twig equivalents (2fa setup/verify/backup-codes and many auth, dashboard, domains, errors, layout, users, tags, tld-registry, etc.), and core/TwigService was added. These changes move the app toward a Twig-based templating system, improve 2FA flows, surface avatar images in lists/profiles, and make error rendering more robust.
2026-03-03 18:21:32 +02:00

81 lines
2.8 KiB
Twig

{#
# CAPTCHA Widget Component
# Renders the appropriate CAPTCHA widget based on settings
#
# Required variables:
# - captchaSettings: Array with 'provider' and 'site_key'
#}
{% set provider = captchaSettings.provider|default('disabled') %}
{% set siteKey = captchaSettings.site_key|default('') %}
{% if provider != 'disabled' and siteKey is not empty %}
{# CAPTCHA Widget #}
<div class="captcha-container mb-4">
{% if provider == 'recaptcha_v2' %}
{# reCAPTCHA v2 #}
<div class="g-recaptcha" data-sitekey="{{ siteKey }}"></div>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
{% elseif provider == 'recaptcha_v3' %}
{# reCAPTCHA v3 (Invisible) #}
<input type="hidden" id="captcha_response" name="captcha_response">
<script src="https://www.google.com/recaptcha/api.js?render={{ siteKey }}"></script>
{% elseif provider == 'turnstile' %}
{# Cloudflare Turnstile #}
<div class="cf-turnstile" data-sitekey="{{ siteKey }}"></div>
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
{% endif %}
</div>
{% if provider == 'recaptcha_v3' %}
{# reCAPTCHA v3 Form Submission Handler #}
<script>
// Store the original form submission handler
const form = document.querySelector('form');
const originalSubmit = form.onsubmit;
form.addEventListener('submit', function(e) {
e.preventDefault();
grecaptcha.ready(function() {
grecaptcha.execute('{{ siteKey }}', {action: 'submit'}).then(function(token) {
document.getElementById('captcha_response').value = token;
// Call original submit handler if it exists
if (originalSubmit && originalSubmit.call(form, e) === false) {
return;
}
// Submit the form
form.submit();
});
});
});
</script>
{% elseif provider == 'recaptcha_v2' or provider == 'turnstile' %}
{# reCAPTCHA v2 / Turnstile Response Handler #}
<script>
// Add hidden input to capture response
const form = document.querySelector('form');
const captchaInput = document.createElement('input');
captchaInput.type = 'hidden';
captchaInput.name = 'captcha_response';
captchaInput.id = 'captcha_response';
form.appendChild(captchaInput);
// Capture response on form submit
form.addEventListener('submit', function(e) {
{% if provider == 'recaptcha_v2' %}
const response = grecaptcha.getResponse();
{% else %}{# turnstile #}
const response = turnstile.getResponse();
{% endif %}
captchaInput.value = response;
});
</script>
{% endif %}
{% endif %}