Skip to content

Add change password UI and AJAX handler#1853

Open
arifulhoque7 wants to merge 1 commit into
weDevsOfficial:developfrom
arifulhoque7:feature/account-change-password-tab
Open

Add change password UI and AJAX handler#1853
arifulhoque7 wants to merge 1 commit into
weDevsOfficial:developfrom
arifulhoque7:feature/account-change-password-tab

Conversation

@arifulhoque7
Copy link
Copy Markdown
Contributor

@arifulhoque7 arifulhoque7 commented Apr 30, 2026

WPUF Account Page — Change Password Tab

Overview

Add a dedicated Change Password tab to the WPUF account page sidebar, positioned immediately after "Edit Profile". The tab is separate from Edit Profile so users have a single-purpose, focused flow for updating credentials.


Design Goals

  • Match existing account page sidebar design (icon + label, active state, same CSS classes)
  • Use the provided shield-check SVG as the tab icon
  • Three password fields with eye-toggle and infotip (tooltip) on each
  • Password strength indicator on the new password field
  • Dedicated AJAX handler — no coupling to the profile update flow
  • Full WPUF coding standards compliance (strict types, wp_unslash, nonces, snake_case)

Tab Position

Sidebar order (after the revamp):
1. Dashboard
2. Posts (CPT)
3. Edit Profile      ← existing
4. Change Password   ← NEW (inserted right after edit-profile)
5. Subscription
6. Billing Address
7. Submit Post

Insertion is done inside wpuf_get_account_sections() via array_merge so the key change-password lands after edit-profile.


Icon

Shield-check SVG from /WPUF icons-outline 3/Vector.svg:

<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg">
  <path d="M6.75 10.7857L9 13.0357L12.75 7.78574M9.75 0.75C7.5995 2.78662 4.69563 4.03575 1.5 4.03575C1.44922 4.03575 1.39852 4.03543 1.34789 4.03481C0.959898 5.21491 0.75 6.47584 0.75 7.7858C0.75 13.3773 4.57432 18.0756 9.75 19.4077C14.9257 18.0756 18.75 13.3773 18.75 7.7858C18.75 6.47584 18.5401 5.21491 18.1521 4.03481C18.1015 4.03543 18.0508 4.03575 18 4.03575C14.8044 4.03575 11.9005 2.78662 9.75 0.75Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Template: templates/dashboard/change-password.php

Fields

# Field ID Label Placeholder Infotip
1 current_password Current Password Enter current password Required to verify identity before changing password
2 pass1 New Password Enter new password Must be at least 8 characters. Use a mix of letters, numbers, and symbols for a stronger password
3 pass2 Confirm New Password Re-enter new password Must match the new password entered above

Infotip Implementation

Pure HTML/CSS tooltip using a ? icon button with title attribute and a sibling <span class="wpuf-field-hint"> element. No extra JS library needed — uses the same wpuf-field-hint class pattern already present in WPUF forms.

<label for="current_password" class="wpuf-form-label">
    <?php esc_html_e( 'Current Password', 'wp-user-frontend' ); ?>
    <span class="wpuf-help-tip" title="<?php esc_attr_e( 'Required to verify your identity before changing the password.', 'wp-user-frontend' ); ?>">
        <svg width="16" height="16" ...><!-- info circle icon --></svg>
    </span>
</label>

Password Strength

Show #pass-strength-result bar beneath the "New Password" field — same JS wp.passwordStrength.meter() call as in edit-profile.php.

NONCE & AJAX

  • Nonce action: wpuf-account-change-password
  • AJAX action: wpuf_account_change_password
  • Success: show .wpuf-success message, clear all three fields
  • Error: show .wpuf-error with the returned message

Button

<button type="submit" class="wpuf-btn wpuf-btn-primary">
    <?php esc_html_e( 'Update Password', 'wp-user-frontend' ); ?>
</button>
<button type="button" class="wpuf-btn wpuf-btn-secondary" onclick="window.location.reload();">
    <?php esc_html_e( 'Cancel', 'wp-user-frontend' ); ?>
</button>

Backend Changes

1. wpuf-functions.phpwpuf_get_account_sections()

Insert change-password key immediately after edit-profile in the base $sections array:

$sections = [
    'edit-profile'    => __( 'Edit Profile', 'wp-user-frontend' ),
    'change-password' => __( 'Change Password', 'wp-user-frontend' ),
    'subscription'    => __( 'Subscription', 'wp-user-frontend' ),
    'billing-address' => __( 'Billing Address', 'wp-user-frontend' ),
];

2. includes/Frontend/Frontend_Account.php

Constructor — register action hook:

add_action( 'wpuf_account_content_change-password', [ $this, 'change_password_section' ], 10, 2 );

New method change_password_section():

/**
 * Display the change password section.
 *
 * @since WPUF_SINCE
 *
 * @param array  $sections        Account sections.
 * @param string $current_section Active section slug.
 *
 * @return void
 */
public function change_password_section( $sections, $current_section ) {
    wpuf_load_template( 'dashboard/change-password.php', [
        'sections'        => $sections,
        'current_section' => $current_section,
    ] );
}

New method change_password() (AJAX handler):

/**
 * Handle change password AJAX request.
 *
 * @since WPUF_SINCE
 *
 * @return void Sends JSON response.
 */
public function change_password() {
    $nonce = isset( $_REQUEST['_wpnonce'] ) ? sanitize_key( wp_unslash( $_REQUEST['_wpnonce'] ) ) : '';

    if ( ! wp_verify_nonce( $nonce, 'wpuf-account-change-password' ) ) {
        wp_send_json_error( __( 'Security check failed.', 'wp-user-frontend' ) );
    }

    if ( ! is_user_logged_in() ) {
        wp_send_json_error( __( 'You must be logged in.', 'wp-user-frontend' ) );
    }

    global $current_user;

    $current_password = ! empty( $_POST['current_password'] ) ? sanitize_text_field( wp_unslash( $_POST['current_password'] ) ) : '';
    $pass1            = ! empty( $_POST['pass1'] ) ? sanitize_text_field( wp_unslash( $_POST['pass1'] ) ) : '';
    $pass2            = ! empty( $_POST['pass2'] ) ? sanitize_text_field( wp_unslash( $_POST['pass2'] ) ) : '';

    // Validation
    if ( empty( $current_password ) ) {
        wp_send_json_error( __( 'Please enter your current password.', 'wp-user-frontend' ) );
    }
    if ( empty( $pass1 ) ) {
        wp_send_json_error( __( 'Please enter a new password.', 'wp-user-frontend' ) );
    }
    if ( empty( $pass2 ) ) {
        wp_send_json_error( __( 'Please confirm your new password.', 'wp-user-frontend' ) );
    }
    if ( $pass1 !== $pass2 ) {
        wp_send_json_error( __( 'New passwords do not match.', 'wp-user-frontend' ) );
    }
    if ( ! wp_check_password( $current_password, $current_user->user_pass, $current_user->ID ) ) {
        wp_send_json_error( __( 'Your current password is incorrect.', 'wp-user-frontend' ) );
    }

    $result = wp_update_user( [
        'ID'        => $current_user->ID,
        'user_pass' => $pass1,
    ] );

    if ( is_wp_error( $result ) ) {
        wp_send_json_error( __( 'Could not update password. Please try again.', 'wp-user-frontend' ) );
    }

    wp_send_json_success( __( 'Password updated successfully!', 'wp-user-frontend' ) );
}

3. includes/Ajax.php

Register the new AJAX action (logged-in only):

$this->register_ajax( 'wpuf_account_change_password', [ new Frontend\Frontend_Account(), 'change_password' ], $this->logged_in_only );

4. templates/account.php — nav icon switch-case

Add change-password case before the default:

case 'change-password':
    $icon = '<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg">
        <path d="M6.75 10.7857L9 13.0357L12.75 7.78574M9.75 0.75C7.5995 2.78662 4.69563 4.03575 1.5 4.03575C1.44922 4.03575 1.39852 4.03543 1.34789 4.03481C0.959898 5.21491 0.75 6.47584 0.75 7.7858C0.75 13.3773 4.57432 18.0756 9.75 19.4077C14.9257 18.0756 18.75 13.3773 18.75 7.7858C18.75 6.47584 18.5401 5.21491 18.1521 4.03481C18.1015 4.03543 18.0508 4.03575 18 4.03575C14.8044 4.03575 11.9005 2.78662 9.75 0.75Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
    </svg>';
    break;

File Checklist

File Change
wpuf-functions.php Add change-password to $sections array in wpuf_get_account_sections()
includes/Frontend/Frontend_Account.php Register action hook + add change_password_section() + add change_password() AJAX method
includes/Ajax.php Register wpuf_account_change_password AJAX action
templates/account.php Add change-password icon case in nav switch
templates/dashboard/change-password.php NEW — password form template

No Breaking Changes

  • wpuf_account_sections filter still fires — Pro / modules can remove this tab
  • Password logic in update_profile() is untouched — Edit Profile still works as before
  • No CSS files modified — template uses existing wpuf-form-group, wpuf-form-label, wpuf-form-input, wpuf-password-field, wpuf-btn-* classes

Close 1313

Introduce a new Change Password account section and full AJAX flow. Changes include:

- Register a new account section key ('change-password') in wpuf_get_account_sections().
- Add a change-password dashboard template (templates/dashboard/change-password.php) with password strength meter, eye toggle, nonce, and AJAX submission UI. Enqueues zxcvbn/password-strength-meter and uses an eye icon asset when available.
- Add Frontend_Account::change_password_section() to load the template and Frontend_Account::change_password() to handle the AJAX request: nonce and auth checks, input validation, current password verification, wp_update_user call, and JSON success/error responses.
- Update includes/Ajax.php to instantiate Frontend_Account once and register the new wpuf_account_change_password AJAX action (logged-in only).
- Add a menu icon for the change-password section in templates/account.php.

This implements a complete frontend flow for users to change their password securely.
@arifulhoque7 arifulhoque7 requested a review from sapayth April 30, 2026 05:16
@arifulhoque7 arifulhoque7 self-assigned this Apr 30, 2026
@arifulhoque7 arifulhoque7 added needs: testing needs: dev review This PR needs review by a developer labels Apr 30, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 30, 2026

Warning

Rate limit exceeded

@arifulhoque7 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 39 minutes and 14 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6570af98-0301-4d7c-b1e5-86a0a7b3188d

📥 Commits

Reviewing files that changed from the base of the PR and between 95079a6 and a6bcc5e.

📒 Files selected for processing (5)
  • includes/Ajax.php
  • includes/Frontend/Frontend_Account.php
  • templates/account.php
  • templates/dashboard/change-password.php
  • wpuf-functions.php
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 39 minutes and 14 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs: dev review This PR needs review by a developer needs: testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant