Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
207 changes: 114 additions & 93 deletions assets/js/checkout.js
Original file line number Diff line number Diff line change
Expand Up @@ -1209,61 +1209,68 @@
? this.email_address || ''
: this.username || '';

// Include captcha tokens if present on the page.
const login_data = {
username_or_email,
password: this.inline_login_password,
_wpnonce: jQuery('[name="_wpnonce"]').val()
};

const recaptcha_token = jQuery('input[name="g-recaptcha-response"]').filter(function() {
return this.value;
}).first().val();
const hcaptcha_token = jQuery('input[name="h-captcha-response"]').filter(function() {
return this.value;
}).first().val();
const cap_token = jQuery('input[name="cap-token"]').filter(function() {
return this.value;
}).first().val();

if (recaptcha_token) {
login_data[ 'g-recaptcha-response' ] = recaptcha_token;
}
// Include captcha tokens scoped to the inline login prompt container.
// Using scoped selectors avoids picking up the checkout form's captcha token.
const promptContainer = jQuery('#wu-inline-login-prompt-' + this.login_prompt_field);
const login_data = {
username_or_email,
password: this.inline_login_password,
_wpnonce: jQuery('[name="_wpnonce"]').val()
};

if (hcaptcha_token) {
login_data[ 'h-captcha-response' ] = hcaptcha_token;
}
const recaptcha_token = promptContainer.find('input[name="g-recaptcha-response"]').filter(function() {
return this.value;
}).first().val();
const hcaptcha_token = promptContainer.find('input[name="h-captcha-response"]').filter(function() {
return this.value;
}).first().val();
const cap_token = promptContainer.find('input[name="cap-token"]').filter(function() {
return this.value;
}).first().val();

if (cap_token) {
login_data[ 'cap-token' ] = cap_token;
}
if (recaptcha_token) {
login_data[ 'g-recaptcha-response' ] = recaptcha_token;
}

this.request('wu_inline_login', login_data, function(results) {
if (hcaptcha_token) {
login_data[ 'h-captcha-response' ] = hcaptcha_token;
}

that.logging_in = false;
if (cap_token) {
login_data[ 'cap-token' ] = cap_token;
}

if (results.success) {
this.request('wu_inline_login', login_data, function(results) {

// Login successful - reload page to show logged-in state
window.location.reload();
that.logging_in = false;

}
if (results.success) {

}, function(error) {
// Login successful - reload page to show logged-in state
window.location.reload();

that.logging_in = false;
}

if (error.responseJSON && error.responseJSON.data && error.responseJSON.data.message) {
}, function(error) {

that.login_error = error.responseJSON.data.message;
that.logging_in = false;

} else {
if (error.responseJSON && error.responseJSON.data && error.responseJSON.data.message) {

that.login_error = wu_checkout.i18n.login_failed || 'Login failed. Please try again.';
that.login_error = error.responseJSON.data.message;

}
} else {

});
that.login_error = wu_checkout.i18n.login_failed || 'Login failed. Please try again.';

}

// Reset inline login captcha widgets so the user can re-verify.
if (typeof window.wuCaptchaResetInlineLogin === 'function') {
window.wuCaptchaResetInlineLogin();
}

});
Comment on lines +1212 to +1273
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm the added lines are at single-tab indentation while neighbors are deeper,
# and check whether the repo's ESLint config enforces a specific indent depth.
fd -t f eslint -x echo "--- {} ---" \; -x cat {} \;
echo
echo "--- handle_inline_login indentation sample ---"
awk 'NR>=1205 && NR<=1275 { printf "%4d|", NR; for (i=1; i<=length($0); i++) { c=substr($0,i,1); if (c=="\t") printf "."; else { printf "%s", substr($0,i); break } } print "" }' assets/js/checkout.js
echo
echo "--- handleError / handleLogin sample ---"
awk 'NR>=1340 && NR<=1450 { printf "%4d|", NR; for (i=1; i<=length($0); i++) { c=substr($0,i,1); if (c=="\t") printf "."; else { printf "%s", substr($0,i); break } } print "" }' assets/js/checkout.js

Repository: Ultimate-Multisite/ultimate-multisite

Length of output: 5824


Fix indentation: all newly added code blocks are under-indented by 4–6 tabs.

Lines 1212–1273, 1346–1366, and 1390–1444 are indented with a single leading tab, while surrounding unchanged code at the same scope sits at 5–6 tabs (and 6–7 tabs inside the handleLogin function). For example:

  • Line 1210 (......: this.username || '';) sits at 6 tabs, yet the very next added line 1212 (./​/ Include captcha tokens...) drops to 1 tab.
  • Line 1340 (......function hideError() {) is at 6 tabs, but the added handleError function at line 1346 is at 1 tab.
  • Inside handleLogin (starting line 1368 at 7 tabs), the new captcha collection code at line 1390 starts at 1 tab.

This breaks nesting consistency and violates the project's WordPress ESLint tab-based indentation rule. Re-indent all three blocks to match their enclosing scope depth.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@assets/js/checkout.js` around lines 1212 - 1273, The added captcha-collection
block (creating promptContainer, login_data,
recaptcha_token/hcaptcha_token/cap_token and attaching them to login_data) and
the two other newly added helper functions (handleError and the captcha portion
inside handleLogin) are incorrectly under-indented; re-indent those entire
blocks to match their surrounding scope (use the same number of leading tabs as
the enclosing methods/blocks where promptContainer is used and where
handleError/handleLogin live), so the declarations for promptContainer,
login_data, recaptcha_token, hcaptcha_token, cap_token and the wu_inline_login
request callback align with the existing 5–7 tab indentation in that file and
satisfy the project's tab-based ESLint rules.

Comment on lines +1243 to +1273
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

handle_inline_login silently swallows {success:false} responses and skips the captcha reset.

The success callback only handles results.success === true (reload). When the server responds 200 with { success:false, data:{ message } } — e.g., wrong password, captcha rejected — none of the following happens:

  • this.login_error is not set, so the user sees no feedback.
  • window.wuCaptchaResetInlineLogin() is not called, so a one-time captcha token stays consumed and any retry will fail validation server-side.

Only network/HTTP errors hit the error callback where the reset now lives. The sibling setup_inline_login_handlers flow does route success:false through handleError(results) — these two paths should behave the same.

🐛 Proposed fix
 	this.request('wu_inline_login', login_data, function(results) {

 		that.logging_in = false;

 		if (results.success) {

 			// Login successful - reload page to show logged-in state
 			window.location.reload();
+			return;
+
+		}
+
+		if (results.data && results.data.message) {
+
+			that.login_error = results.data.message;
+
+		} else {
+
+			that.login_error = wu_checkout.i18n.login_failed || 'Login failed. Please try again.';

 		}

+		// Reset inline login captcha widgets so the user can re-verify.
+		if (typeof window.wuCaptchaResetInlineLogin === 'function') {
+			window.wuCaptchaResetInlineLogin();
+		}
+
 	}, function(error) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
this.request('wu_inline_login', login_data, function(results) {
// Login successful - reload page to show logged-in state
window.location.reload();
that.logging_in = false;
}
if (results.success) {
}, function(error) {
// Login successful - reload page to show logged-in state
window.location.reload();
that.logging_in = false;
}
if (error.responseJSON && error.responseJSON.data && error.responseJSON.data.message) {
}, function(error) {
that.login_error = error.responseJSON.data.message;
that.logging_in = false;
} else {
if (error.responseJSON && error.responseJSON.data && error.responseJSON.data.message) {
that.login_error = wu_checkout.i18n.login_failed || 'Login failed. Please try again.';
that.login_error = error.responseJSON.data.message;
}
} else {
});
that.login_error = wu_checkout.i18n.login_failed || 'Login failed. Please try again.';
}
// Reset inline login captcha widgets so the user can re-verify.
if (typeof window.wuCaptchaResetInlineLogin === 'function') {
window.wuCaptchaResetInlineLogin();
}
});
this.request('wu_inline_login', login_data, function(results) {
that.logging_in = false;
if (results.success) {
// Login successful - reload page to show logged-in state
window.location.reload();
return;
}
if (results.data && results.data.message) {
that.login_error = results.data.message;
} else {
that.login_error = wu_checkout.i18n.login_failed || 'Login failed. Please try again.';
}
// Reset inline login captcha widgets so the user can re-verify.
if (typeof window.wuCaptchaResetInlineLogin === 'function') {
window.wuCaptchaResetInlineLogin();
}
}, function(error) {
that.logging_in = false;
if (error.responseJSON && error.responseJSON.data && error.responseJSON.data.message) {
that.login_error = error.responseJSON.data.message;
} else {
that.login_error = wu_checkout.i18n.login_failed || 'Login failed. Please try again.';
}
// Reset inline login captcha widgets so the user can re-verify.
if (typeof window.wuCaptchaResetInlineLogin === 'function') {
window.wuCaptchaResetInlineLogin();
}
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@assets/js/checkout.js` around lines 1243 - 1273, The inline login success
handler in handle_inline_login currently only handles results.success === true
and ignores server 200 responses with success:false; update the success callback
inside the this.request('wu_inline_login', ...) call to treat a non-true
results.success the same as the error path: set that.login_error from
results.data.message (falling back to wu_checkout.i18n.login_failed), call
window.wuCaptchaResetInlineLogin() if available, and invoke the existing
handleError/results error-handling flow used by setup_inline_login_handlers (or
reuse its logic) so captcha tokens are reset and the user sees the error message
when the server returns {success:false}.


return false;

Expand Down Expand Up @@ -1336,22 +1343,27 @@

}

function handleError(error) {
function handleError(error) {

submitButton.disabled = false;
submitButton.textContent = wu_checkout.i18n.sign_in || 'Sign in';
submitButton.disabled = false;
submitButton.textContent = wu_checkout.i18n.sign_in || 'Sign in';

if (error.data && error.data.message) {
if (error.data && error.data.message) {

showError(error.data.message);
showError(error.data.message);

} else {
} else {

showError(wu_checkout.i18n.login_failed || 'Login failed. Please try again.');
showError(wu_checkout.i18n.login_failed || 'Login failed. Please try again.');

}
}

}
// Reset inline login captcha widgets so the user can re-verify.
if (typeof window.wuCaptchaResetInlineLogin === 'function') {
window.wuCaptchaResetInlineLogin();
}

}

function handleLogin(e) {

Expand All @@ -1375,52 +1387,61 @@

const username_or_email = fieldType === 'email' ? that.email_address : that.username;

// Include captcha tokens if present on the page.
const inline_login_data = {
username_or_email,
password,
_wpnonce: jQuery('[name="_wpnonce"]').val()
};

const recaptcha_val = jQuery('input[name="g-recaptcha-response"]').filter(function() {
return this.value;
}).first().val();
const hcaptcha_val = jQuery('input[name="h-captcha-response"]').filter(function() {
return this.value;
}).first().val();
const cap_val = jQuery('input[name="cap-token"]').filter(function() {
return this.value;
}).first().val();

if (recaptcha_val) {
inline_login_data[ 'g-recaptcha-response' ] = recaptcha_val;
}

if (hcaptcha_val) {
inline_login_data[ 'h-captcha-response' ] = hcaptcha_val;
}

if (cap_val) {
inline_login_data[ 'cap-token' ] = cap_val;
}

jQuery.ajax({
method: 'POST',
url: wu_checkout.late_ajaxurl + '&action=wu_inline_login',
data: inline_login_data,
success(results) {

if (results.success) {

window.location.reload();
// Include captcha tokens scoped to the inline login prompt container.
// Using scoped selectors avoids picking up the checkout form's captcha token.
const promptContainer = jQuery('#wu-inline-login-prompt-' + fieldType);
const inline_login_data = {
username_or_email,
password,
_wpnonce: jQuery('[name="_wpnonce"]').val()
};

const recaptcha_val = promptContainer.find('input[name="g-recaptcha-response"]').filter(function() {
return this.value;
}).first().val();
const hcaptcha_val = promptContainer.find('input[name="h-captcha-response"]').filter(function() {
return this.value;
}).first().val();
const cap_val = promptContainer.find('input[name="cap-token"]').filter(function() {
return this.value;
}).first().val();

if (recaptcha_val) {
inline_login_data[ 'g-recaptcha-response' ] = recaptcha_val;
}

if (hcaptcha_val) {
inline_login_data[ 'h-captcha-response' ] = hcaptcha_val;
}

if (cap_val) {
inline_login_data[ 'cap-token' ] = cap_val;
}

jQuery.ajax({
method: 'POST',
url: wu_checkout.late_ajaxurl + '&action=wu_inline_login',
data: inline_login_data,
success(results) {

if (results.success) {

window.location.reload();

} else {
handleError(results);
}

} else {
handleError(results);
}
},
error(xhr) {
handleError(xhr.responseJSON || {});

},
error: handleError
});
// Reset inline login captcha widgets so the user can re-verify.
if (typeof window.wuCaptchaResetInlineLogin === 'function') {
window.wuCaptchaResetInlineLogin();
}
}
});

return false;

Expand Down
Loading