File: /home/xedaptot/ai.naniguide.com/resources/views/recaptcha/script.blade.php
@if (isset($errors) && $errors->has('recaptcha_invalid'))
<span class="help-block text-danger">
<strong>{{ $errors->first('recaptcha_invalid') }}</strong>
</span>
@endif
{{--
Standard reCAPTCHA v3 (NOT Enterprise).
Behaviour: always submit the form, even when the captcha lib fails to load
or `execute()` rejects. The server-side fail-open path
(`App\Library\Tool::verifyCaptchaOrAlert`) treats Google rejections as a
config alert (admins get a bell-dropdown notification) and lets the request
through. This avoids locking everyone out of login when Google revokes the
site_key, the user has JS off, an ad blocker eats `api.js`, etc.
Past failure modes guarded against (each one previously broke prod login):
• jQuery missing in refactor auth layout → reference error → no submit
binding → empty token submit. Fixed by going vanilla JS here.
• Enterprise `enterprise.js` loaded for v3 keys → undefined namespace →
throw before preventDefault → empty submit. Fixed by using `api.js`.
• `api.js?render=KEY` returns 4xx (key revoked / invalid) → grecaptcha
never defined → submit handler crashed. Fixed by `<script onerror>` +
always-submit fallback below.
--}}
<input type="hidden" name="g-recaptcha-response" value="" />
<script>
window.__captchaUnreachable = false;
</script>
<script
src="https://www.google.com/recaptcha/api.js?render={{ App\Model\Setting::get('recaptcha_site_key') }}"
onerror="window.__captchaUnreachable = true;"
></script>
<script>
(function() {
var siteKey = @json(App\Model\Setting::get('recaptcha_site_key'));
var tokenInput = document.querySelector('input[name="g-recaptcha-response"]');
if (!tokenInput) return;
var form = tokenInput.closest('form');
if (!form) return;
function submitNatively() {
// Use form.submit() (NOT requestSubmit). requestSubmit dispatches a
// new submit event; when called from inside our own submit handler
// some browsers swallow the recursive dispatch and the form never
// actually POSTs. form.submit() bypasses event listeners entirely
// and does an immediate native submission, which is what we want
// here — we already passed the captcha gate, no other handler
// should re-prevent the navigation.
form.removeEventListener('submit', onSubmit);
form.submit();
}
function onSubmit(e) {
// Token already populated (re-entry after async fetch) — let it through.
if (tokenInput.value !== '') return;
// Always intercept first so any later failure can't accidentally
// trigger a native submit before we've had a chance to react.
e.preventDefault();
// api.js failed to load (network blocked, key revoked → 4xx, etc.)
// → submit anyway with empty token; server fail-open will alert admins.
if (window.__captchaUnreachable || typeof grecaptcha === 'undefined' || !grecaptcha.ready) {
submitNatively();
return;
}
grecaptcha.ready(function() {
grecaptcha.execute(siteKey, { action: 'LOGIN' }).then(function(token) {
tokenInput.value = token;
submitNatively();
}).catch(function() {
// execute() rejected (domain not allowed, key revoked,
// quota exceeded, …) — submit with empty token; server
// fail-open path takes over.
submitNatively();
});
});
}
form.addEventListener('submit', onSubmit);
})();
</script>