| | |
| | | { |
| | | $this->siteFeatures = Features::forSite(); |
| | | $this->emailManager = new EmailManager(); |
| | | $this->rateLimiter = new AjaxRateLimiter(); |
| | | |
| | | |
| | | $this->cache = CacheManager::for('login'); |
| | | |
| | |
| | | /************************************************************************* |
| | | * SECURITY & VALIDATION |
| | | *************************************************************************/ |
| | | protected function checkAjaxRateLimit(string $action): bool |
| | | { |
| | | return $this->rateLimiter->checkLimit($action); |
| | | } |
| | | |
| | | protected function checkRequestId(): bool |
| | | { |
| | | $request_id = $_POST['request_id'] ?? ''; |
| | |
| | | $action = $this->getAction(); |
| | | ob_start(); |
| | | ?> |
| | | <script type="text/javascript"> |
| | | window.checkedEmails = new Set(); |
| | | |
| | | document.addEventListener('DOMContentLoaded', () => { |
| | | const form = document.querySelector('.login form'); |
| | | if (!form) return; |
| | |
| | | window.LoginController.subscribe((event, data) => { |
| | | if (event === 'form-submit') { |
| | | handleFormSubmission(data); |
| | | } else if (event === 'field-validated' && data.name === 'user_email') { |
| | | if (!window.checkedEmails.has(data.value)){ |
| | | checkEmail(data.value, data); |
| | | } |
| | | } |
| | | }); |
| | | |
| | | |
| | | async function handleFormSubmission(data) { |
| | | let realFormData = data.fullData; |
| | | const { formId, config, data: formData } = data; |
| | | |
| | | |
| | | const form = config.element; |
| | | |
| | | const submit = form.querySelector('[type=submit]'); |
| | | let oldText = submit.textContent; |
| | | // Show uploading status |
| | | |
| | | |
| | | window.LoginController.showFormStatus(formId, 'uploading'); |
| | | |
| | | try { |
| | |
| | | 'Content-Type': 'application/json', |
| | | 'X-WP-Nonce': jvbSettings.nonce |
| | | }, |
| | | body: JSON.stringify(formData) |
| | | body: JSON.stringify(realFormData) |
| | | }); |
| | | |
| | | const result = await response.json(); |
| | |
| | | submit.disabled = false; |
| | | } |
| | | } |
| | | async function checkEmail(email, input) { |
| | | window.checkedEmails.add(email); |
| | | let wrapper = input.closest('.field'); |
| | | let submit = input.closest('form').querySelector('[type=submit]'); |
| | | try { |
| | | submit.disabled = true; |
| | | window.LoginController.showSuccess(wrapper, 'Checking our records...'); |
| | | const response = await fetch(`${jvbSettings.api}auth/email`, { |
| | | method: 'POST', |
| | | headers: { |
| | | 'Content-Type': 'application/json', |
| | | 'X-WP-Nonce': jvbSettings.nonce |
| | | }, |
| | | body: JSON.stringify({ email: email }) |
| | | }); |
| | | |
| | | const result = await response.json(); |
| | | |
| | | if (!response.ok) { |
| | | return; // On error, allow to proceed (fail open) |
| | | } |
| | | |
| | | if (result.exists) { |
| | | <?php |
| | | switch ($action) { |
| | | case 'register': |
| | | echo 'window.LoginController.showError(wrapper,\'This email is already registered. Log in instead?\');'; |
| | | break; |
| | | case 'login': |
| | | case 'lostpassword': |
| | | case 'magic': |
| | | echo 'window.LoginController.showSuccess(wrapper,\'Email exists in our system.\');'; |
| | | break; |
| | | } |
| | | ?> |
| | | } else { |
| | | <?php |
| | | switch ($action) { |
| | | case 'register': |
| | | echo 'window.LoginController.showSuccess(wrapper,\'Email is available!\');'; |
| | | break; |
| | | case 'login': |
| | | case 'lostpassword': |
| | | case 'magic': |
| | | echo 'window.LoginController.showError(wrapper,\'This email doesn\\\'t seem to exist in our system. Create account instead?\');'; |
| | | break; |
| | | } |
| | | ?> |
| | | } |
| | | |
| | | return true; // Email is available |
| | | } catch (error) { |
| | | console.error('Email check failed:', error); |
| | | return true; // On network error, allow to proceed |
| | | }finally { |
| | | submit.disabled = false; |
| | | } |
| | | } |
| | | }); |
| | | |
| | | |
| | | </script> |
| | | |
| | | <?php |
| | | $script = ob_get_clean(); |
| | | |