Abstract Validation into Service for Web Service Context

Created on 2 February 2018, over 6 years ago
Updated 7 April 2024, 3 months ago

Problem/Motivation

The current strategy is tightly coupled into Form API validation callback. Client applications, using REST or JSONAPI, should be able to apply the validation logic inside HOOK_user_presave().

Expected Results:

When a client application creates a user that does not meet the password policy constraints, a descriptive exception is thrown, and processed by the client.

Actual Result:

When a client application creates a user that does not meet the password policy constraints, the user is saved.


In Progress Resolution

  public function presaveUserValidate(User $entity) {

    $request = \Drupal\Component\Serialization\Json::decode(\Drupal::request()->getContent());
    $pass = $request['data']['attributes']['pass'];

    //@todo get role
    $roles = $entity->getRoles();
    if (empty($roles)) {
      $roles = ['authenticated' => 'authenticated'];
    }

    // Run validation.
    $applicable_policies = [];
    $ids = [];
    foreach ($roles as $role_key => $role_enabled) {
      if ($role_enabled) {
        $role_map = ['roles.' . $role_enabled => $role_enabled];
        $role_policies = \Drupal::entityTypeManager()->getStorage('password_policy')->loadByProperties($role_map);
        /** @var \Drupal\password_policy\Entity\PasswordPolicy $policy */
        foreach ($role_policies as $policy) {
          if (!in_array($policy->id(), $ids)) {
            $applicable_policies[] = $policy;
            $ids[] = $policy->id();
          }
        }
      }
    }

    // Run validation.
    $failed = FALSE;
    $force_failure = FALSE;

    // Process user context
    // TODO - Turn this into configuration.
    $user_context_fields = ['mail', 'name', 'uid'];
    $user_context_values = [];
    foreach ($user_context_fields as $user_context_field) {
      if($entity->hasField($user_context_field)) {
        $user_context_values[$user_context_field] = $entity->get($user_context_field)->value;
      }
    }

    /** @var \Drupal\password_policy\Entity\PasswordPolicy $policy */
    foreach ($applicable_policies as $policy_id => $policy) {
      $policy_constraints = $policy->getConstraints();

      foreach ($policy_constraints as $constraint_id => $constraint) {

        $plugin_inst = \Drupal::service('plugin.manager.password_policy.password_constraint');
        $plugin_object = $plugin_inst->createInstance($constraint['id'], $constraint);

        // Execute validation.
        $validation = $plugin_object->validate($pass, $user_context_values);

        if ($validation->isValid() && !$force_failure) {
          $status = t('Pass');
        }
        else {
          $message = $validation->getErrorMessage();
          $failed = TRUE;
        }

      }
    }

    if($failed) {
      throw new AccessDeniedHttpException('There is an issue with the password');
    }
    return;
  }
✨ Feature request
Status

Postponed: needs info

Version

3.0

Component

Code

Created by

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡―πŸ‡΄Jordan Anas_maw

    I think this is duplicate of ✨ Apply policy globally through validation constraint on user entity Needs review

  • πŸ‡¦πŸ‡ΊAustralia Nadim Hossain

    Rerolled the patch to be compatible with php 8.1 upgrade.
    just one minor change. From if ($role_enabled['target_id']) to if (isset($role_enabled['target_id']))

    Thanks Anas for pointing out the similar patch and looks like the other patch has more possibility to get merged. I will apply the other patch you mentioned in our project and do some testing, after that will be closing this issue.

  • Status changed to Postponed: needs info 3 months ago
  • πŸ‡ΊπŸ‡ΈUnited States Kristen Pol Santa Cruz, CA, USA

    Thanks to everyone for the work on this issue.

    I'm going through all the 8.x issues.

    As the 8.x is no longer supported, I'm postponing this issue for now and need feedback as to whether or not this issue is relevant to 4.0.x.

    If it is, please reopen and change the version, make sure the issue summary is clear and complete, including steps to reproduce, and reroll the patch. If it's not, please close.

    If there is no response to this in a month addressing the above, it can be closed.

Production build 0.69.0 2024