Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
177 changes: 124 additions & 53 deletions assets/js/checkout.js
Original file line number Diff line number Diff line change
Expand Up @@ -1182,7 +1182,7 @@
});

},
handle_inline_login(event) {
async handle_inline_login(event) {

// Prevent any default behavior or form submission
if (event) {
Expand All @@ -1205,45 +1205,63 @@
this.login_error = '';

const that = this;
const username_or_email = this.login_prompt_field === 'email'
const field_type = this.login_prompt_field;
const username_or_email = field_type === 'email'
? 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;
}
/**
* Filter collecting async pre-submission work for the inline login.
*
* Addons can push promises into the array; the login request waits
* for all of them to resolve before being sent. Useful when an
* addon needs to perform asynchronous work (e.g. solving an
* invisible captcha) before the payload is built.
*
* @param {Promise[]} promises The array of pending promises.
* @param {string} field_type The field type ('email' or 'username').
*/
try {

if (hcaptcha_token) {
login_data[ 'h-captcha-response' ] = hcaptcha_token;
}
await Promise.all(hooks.applyFilters('wu_before_inline_login_submitted', [], field_type));

} catch (err) {

this.logging_in = false;
this.login_error = (err && err.message) ? err.message : (wu_checkout.i18n.login_failed || 'Login failed. Please try again.');
return false;

Comment on lines +1224 to 1233
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

Emit the failure hook when pre-submit work rejects.

This failure path sets login_error but skips wu_inline_login_error, so addons that reset captcha/widgets on login failure will not run for rejected wu_before_inline_login_submitted promises. The nested prompt path already routes this through handleError.

Proposed fix
 	} catch (err) {
 
 		this.logging_in = false;
-		this.login_error = (err && err.message) ? err.message : (wu_checkout.i18n.login_failed || 'Login failed. Please try again.');
+		this.login_error = (err && err.message) ? err.message : (wu_checkout.i18n.login_failed || 'Login failed. Please try again.');
+		hooks.doAction('wu_inline_login_error', {
+			data: {
+				message: this.login_error,
+			},
+			originalError: err,
+		}, field_type);
 		return false;
 
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@assets/js/checkout.js` around lines 1224 - 1233, When the Promise.all of
hooks.applyFilters('wu_before_inline_login_submitted', [], field_type) rejects
the catch block currently sets this.logging_in and this.login_error but does not
emit the failure hook; call the same failure handler used by the nested prompt
path (emit the 'wu_inline_login_error' hook or invoke the existing handleError
path) with the error and field_type so addons can reset captcha/widgets, then
preserve the existing this.logging_in=false and return false behavior. Ensure
you reference the rejection from
hooks.applyFilters('wu_before_inline_login_submitted', [], field_type) and emit
'wu_inline_login_error' (or call handleError) with err and field_type before
returning.

if (cap_token) {
login_data[ 'cap-token' ] = cap_token;
}

/**
* Filter the inline login request data.
*
* Addons can hook into this filter to append extra fields to the
* inline login request (for example, captcha tokens).
*
* @param {Object} data The data object to be sent.
* @param {string} field_type The field type ('email' or 'username').
*/
const login_data = hooks.applyFilters('wu_inline_login_data', {
username_or_email,
password: this.inline_login_password,
_wpnonce: jQuery('[name="_wpnonce"]').val()
}, field_type);

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

that.logging_in = false;

if (results.success) {

/**
* Fires when an inline login attempt succeeds.
*
* @param {Object} results The AJAX success response.
* @param {string} field_type The field type ('email' or 'username').
*/
hooks.doAction('wu_inline_login_success', results, field_type);

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

Expand All @@ -1263,6 +1281,17 @@

}

/**
* Fires when an inline login attempt fails.
*
* Addons can hook into this action to react to failed logins
* (for example, resetting a captcha widget).
*
* @param {Object} error The AJAX error response.
* @param {string} field_type The field type ('email' or 'username').
*/
hooks.doAction('wu_inline_login_error', error, field_type);

});

return false;
Expand Down Expand Up @@ -1351,9 +1380,20 @@

}

/**
* Fires when an inline login attempt fails.
*
* Addons can hook into this action to react to failed logins
* (for example, resetting a captcha widget).
*
* @param {Object} error The AJAX error response or jqXHR.
* @param {string} fieldType The field type ('email' or 'username').
*/
hooks.doAction('wu_inline_login_error', error, fieldType);

}

function handleLogin(e) {
async function handleLogin(e) {

e.preventDefault();
e.stopPropagation();
Expand All @@ -1373,36 +1413,46 @@
submitButton.innerHTML = '<span class="spinner is-active wu-inline-block" style="float: none; width: 16px; height: 16px; margin: 0 4px 0 0;"></span>' + (wu_checkout.i18n.logging_in || 'Logging in...');
hideError();

/**
* Filter collecting async pre-submission work for the
* inline login.
*
* Addons can push promises into the array; the login
* request waits for all of them to resolve before being
* sent. Useful when an addon needs to perform async work
* (e.g. solving an invisible captcha) before the payload
* is built.
*
* @param {Promise[]} promises The array of pending promises.
* @param {string} fieldType The field type ('email' or 'username').
*/
try {

await Promise.all(hooks.applyFilters('wu_before_inline_login_submitted', [], fieldType));

} catch (err) {

handleError({ data: { message: (err && err.message) ? err.message : (wu_checkout.i18n.login_failed || 'Login failed. Please try again.') } });
return false;

}

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

// Include captcha tokens if present on the page.
const inline_login_data = {
/**
* Filter the inline login request data.
*
* Addons can hook into this filter to append extra fields
* to the inline login request (for example, captcha tokens).
*
* @param {Object} data The data object to be sent.
* @param {string} fieldType The field type ('email' or 'username').
*/
const inline_login_data = hooks.applyFilters('wu_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;
}
}, fieldType);

jQuery.ajax({
method: 'POST',
Expand All @@ -1412,6 +1462,14 @@

if (results.success) {

/**
* Fires when an inline login attempt succeeds.
*
* @param {Object} results The AJAX success response.
* @param {string} fieldType The field type.
*/
hooks.doAction('wu_inline_login_success', results, fieldType);

window.location.reload();

} else {
Expand Down Expand Up @@ -1457,6 +1515,19 @@

});

/**
* Fires once the inline login prompt is attached and ready.
*
* Addons can hook into this action to initialize their own
* widgets inside the prompt (for example, rendering a captcha
* widget whose markup was injected via the
* `wu_inline_login_prompt_before_submit` server-side action).
*
* @param {string} fieldType The field type ('email' or 'username').
* @param {HTMLElement} loginPromptContainer The prompt container element.
*/
hooks.doAction('wu_inline_login_prompt_ready', fieldType, loginPromptContainer);

});

},
Expand Down
Loading