#36015: Separate the validation process of password validators.
-------------------------------------+-------------------------------------
     Reporter:  Antoliny             |                     Type:  New
                                     |  feature
       Status:  new                  |                Component:
                                     |  contrib.auth
      Version:  5.1                  |                 Severity:  Normal
     Keywords:  password validators  |             Triage Stage:
                                     |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
 Currently, password validators serve the same role as Django's standard
 validators but are categorized separately.
 The reason for this, in my opinion, is that password validators receive
 the user instance when performing validation.
 Therefore, the validation process of password validators is actually
 called during the Form's `_post_clean` stage when it is invoked.
 {{{
 class SetPasswordMixin:
     ...
     def validate_password_for_user(self, user,
 password_field_name="password2"):
         password = self.cleaned_data.get(password_field_name)
         if password:
             try:
                 password_validation.validate_password(password, user) #
 run password validation
             except ValidationError as error:
                 self.add_error(password_field_name, error)
 }}}
 I think that among the password validators provided by Django, the only
 validator that requires an instance during the validation process is
 `UserAttributeSimilarityValidator`. The other validators can be fully
 integrated into standard validators and should be provided as customized
 versions of standard validators.
 Integrating the password validator into the standard validator will
 improve consistency([https://code.djangoproject.com/ticket/35693 #35693])
 and enhance reusability.

 e.g.)
 `CharField(..., validators=[MinimumLengthValidator()])`
 Although it can be used as shown below, it would be better for consistency
 if it could be called through `__call__`, making it more user friendly.
 `CharField(..., validators=[MinimumLengthValidator().validate])`

 **pre validation(Validated through `is_valid()`.)**
 * MinimumLengthValidator
 * CommonPasswordValidator
 * NumericPasswordValidator

 **post validation(Validated through
 `password_validation.validate_password()`.)**
 * UserAttributeSimilarityValidator

 If integrated into the standard validator, the integrated validator will
 perform validation through is_valid, while validators that require an
 instance and cannot be integrated will be handled in the existing
 validation step, the `_post_clean` method.
 Therefore, it is necessary to distinguish the validators that will perform
 the validation in the validate_password function where the password
 validators are executed.
 {{{
 def validate_password(password, user=None, password_validators=None):
     """
     Validate that the password meets all validator requirements.

     If the password is valid, return ``None``.
     If the password is invalid, raise ValidationError with all error
 messages.
     """
     errors = []
     if password_validators is None:
         password_validators = get_default_password_validators()
     for validator in password_validators:
         try:
             validator.validate(password, user) #  -> Perform validation
 only for post password validators.
         except ValidationError as error:
             errors.append(error)
     if errors:
         raise ValidationError(errors)
 }}}
 -----------------
 **Conclusion**

 It would be beneficial to integrate password validators that do not
 require an instance into a customized form of the standard validator,
 allowing validation to be performed through the `is_valid` call, while
 validators that require an instance continue to be called in the existing
 way.
-- 
Ticket URL: <https://code.djangoproject.com/ticket/36015>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/django-updates/01070193ceb4dc4f-9b34c164-c6ef-46be-8e06-5839f7473ad6-000000%40eu-central-1.amazonses.com.

Reply via email to