Issue #3207974: Clear password expiration for users whose policy role was removed

Problem

When a user has their password policy role removed while field_password_expiration is set to 1, they are permanently locked in the password reset redirect loop. Cron never clears the flag because it only queries users who currently have a policy role — users who lost the role are invisible to the expiration logic but still affected by the redirect.

Steps to reproduce:

  1. Create a password policy targeting a specific role (e.g. password_policy) with password_reset: 60
  2. Assign the role to a user and let cron expire their password (field_password_expiration = 1)
  3. Remove the password_policy role from the user
  4. The user is still redirected to the password change form on every page load, with no way out

Fix

Adds a cleanup pass at the end of password_policy_cron() that:

  • Collects all roles from active policies with password_reset > 0
  • Queries users who have field_password_expiration = 1
  • Clears field_password_expiration and field_pending_expire_sent for users who no longer have any role covered by an active policy
  • Skips cleanup entirely if any policy targets the authenticated role (all users would be covered)
  • Respects the existing cron_threshold setting to avoid memory issues

Testing

Tested on Drupal 11 / PHP 8.3 / password_policy 4.0.3. Verified that:

  • Users with the policy role are still expired normally by cron
  • Users whose policy role was removed have their expiration flag cleared
  • Externally authenticated (SSO) users are unaffected
  • The cleanup respects the cron threshold limit

Closes #3207974

Merge request reports

Loading