Ticket #16845: mask-password-field.diff

File mask-password-field.diff, 2.7 KB (added by dstufft, 3 years ago)

Masks the Password Field in Admin to only show first N (6 by default) Digits and the hash type. Also makes the field read only.

  • django/contrib/auth/forms.py

    diff --git a/django/contrib/auth/forms.py b/django/contrib/auth/forms.py
    index b97c5d7..47e984b 100644
    a b  
    11from django import forms
     2from django.forms.util import flatatt
    23from django.template import loader
    34from django.utils.http import int_to_base36
     5from django.utils.safestring import mark_safe
    46from django.utils.translation import ugettext_lazy as _
    57
    68from django.contrib.auth.models import User
    from django.contrib.auth import authenticate 
    911from django.contrib.auth.tokens import default_token_generator
    1012from django.contrib.sites.models import get_current_site
    1113
     14UNMASKED_DIGITS_TO_SHOW = 6
     15
     16
     17class ReadOnlyHashedPasswordWidget(forms.Widget):
     18    def render(self, name, value, attrs):
     19        final_attrs = self.build_attrs(attrs)
     20
     21        if not value:
     22            return "None"
     23
     24        parts = value.split("$")
     25        if len(parts) != 3:
     26            # Legacy Passwords did not have a hash and were md5
     27            hash_type = "md5"
     28            masked = "%s%s" % (value[:UNMASKED_DIGITS_TO_SHOW], "*" * max(len(value) - UNMASKED_DIGITS_TO_SHOW, 0))
     29        else:
     30            hash_type = parts[0]
     31            masked = "%s%s" % (parts[2][:UNMASKED_DIGITS_TO_SHOW], "*" * max(len(parts[2]) - UNMASKED_DIGITS_TO_SHOW, 0))
     32
     33        return mark_safe("""<div%(attrs)s>
     34                    <strong>%(hash_type_label)s</strong>: %(hash_type)s
     35                    <strong>%(masked_label)s</strong>: %(masked)s
     36                </div>""" % {
     37                    "attrs": flatatt(final_attrs),
     38                    "hash_type_label": _("Hash Type"),
     39                    "hash_type": hash_type,
     40                    "masked_label": _("Masked Hash"),
     41                    "masked": masked,
     42                })
     43
     44
     45class ReadOnlyHashedPasswordField(forms.Field):
     46    widget = ReadOnlyHashedPasswordWidget
     47
     48    def __init__(self, *args, **kwargs):
     49        kwargs.setdefault("required", False)
     50        super(ReadOnlyHashedPasswordField, self).__init__(*args, **kwargs)
     51
    1252
    1353class UserCreationForm(forms.ModelForm):
    1454    """
    class UserChangeForm(forms.ModelForm): 
    5191    username = forms.RegexField(label=_("Username"), max_length=30, regex=r'^[\w.@+-]+$',
    5292        help_text = _("Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only."),
    5393        error_messages = {'invalid': _("This value may contain only letters, numbers and @/./+/-/_ characters.")})
     94    password = ReadOnlyHashedPasswordField(label=_("Password"), help_text=_("Use the <a href=\"password/\">change password form</a>."))
     95
     96    def clean_password(self):
     97        return self.initial["password"]
    5498
    5599    class Meta:
    56100        model = User
Back to Top