You are here

function password_policy_cron in Password Policy 8.3

Same name and namespace in other branches
  1. 5 password_policy.module \password_policy_cron()
  2. 6 password_policy.module \password_policy_cron()
  3. 7.2 password_policy.module \password_policy_cron()
  4. 7 password_policy.module \password_policy_cron()

Implements hook_cron().

Looks for expired passwords and updates the expiration based on the policy assigned.

File

./password_policy.module, line 268
Module file for the Password Policy module.

Code

function password_policy_cron() {

  // Load each policy.
  $policies = \Drupal::entityTypeManager()
    ->getStorage('password_policy')
    ->loadMultiple();
  $current_time = \Drupal::time()
    ->getRequestTime();

  /** @var \Drupal\password_policy\Entity\PasswordPolicy $policy */
  foreach ($policies as $policy) {

    // Check each policy configured w/ a password expiration > than 0 days.
    if ($policy
      ->getPasswordReset() > 0) {

      // Load user roles for policy.
      $policy_roles = $policy
        ->getRoles();
      if (empty($policy_roles)) {
        continue;
      }

      // Determine date user accounts expired.
      $expire_timestamp = strtotime('-' . $policy
        ->getPasswordReset() . ' days', $current_time);
      $expire_date = \Drupal::service('date.formatter')
        ->format($expire_timestamp, 'custom', DateTimeItemInterface::DATETIME_STORAGE_FORMAT, DateTimeItemInterface::STORAGE_TIMEZONE);

      // Configurable limit to users per policy per run, to prevent OOM errors.
      $threshold = \Drupal::config('password_policy.settings')
        ->get('cron_threshold');

      // Do not continue with User query if the policy's expire date is less
      // than the install time of the module itself. This prevents the policy
      // from immediately applying to all users after initial module install.
      $install_time = \Drupal::state()
        ->get('password_policy.install_time');
      if ($install_time && $install_time >= $expire_date) {
        $users = [];
      }
      else {

        // Limit to active users.
        $query = \Drupal::entityQuery('user')
          ->condition('status', 1);

        // Limit to roles set by policy configuration.
        if (!in_array(AccountInterface::AUTHENTICATED_ROLE, $policy_roles)) {
          $query
            ->condition('roles', $policy_roles, 'IN');
        }

        // Create condition groups for users with no value for the
        // `field_password_expiration` and `field_last_password_reset` fields.
        // This will be _all users_ after initial module installation.
        $notset_group = $query
          ->andConditionGroup()
          ->condition('field_password_expiration', NULL, 'IS NULL')
          ->condition('field_last_password_reset', NULL, 'IS NULL');

        // Add condition group for users with a `field_password_expiration`
        // value and `field_last_password_reset` value less than or equal the
        // current expire date for the policy.
        $isset_group = $query
          ->andConditionGroup()
          ->condition('field_password_expiration', 0)
          ->condition('field_last_password_reset', $expire_date, '<=');

        // Combine and add groups to query.
        $combined_group = $query
          ->orConditionGroup()
          ->condition($notset_group)
          ->condition($isset_group);
        $query
          ->condition($combined_group);

        // Limit the number of results to the cron threshold setting.
        $query
          ->condition('uid', 0, '>')
          ->range(0, $threshold);
        $valid_list = $query
          ->execute();

        // Load User Objects.
        $users = \Drupal::entityTypeManager()
          ->getStorage('user')
          ->loadMultiple($valid_list);
      }

      // Expire passwords.

      /** @var \Drupal\user\UserInterface $user */
      foreach ($users as $user) {
        $user
          ->set('field_password_expiration', '1');
        $user
          ->save();
      }
    }
  }
}