chore: Put widgets from django-password-strength into ietfauth

This commit is contained in:
Jennifer Richards 2023-05-15 17:55:11 -03:00
parent 329fa26ee0
commit b714bfb083
No known key found for this signature in database
GPG key ID: 9B2BF5C5ADDA6A6E
4 changed files with 118 additions and 6 deletions

View file

@ -11,14 +11,14 @@ from django.core.exceptions import ValidationError
from django.db import models from django.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django_password_strength.widgets import PasswordStrengthInput, PasswordConfirmationInput
import debug # pyflakes:ignore import debug # pyflakes:ignore
from ietf.person.models import Person, Email from ietf.person.models import Person, Email
from ietf.mailinglists.models import Allowlisted from ietf.mailinglists.models import Allowlisted
from ietf.utils.text import isascii from ietf.utils.text import isascii
from .widgets import PasswordStrengthInput, PasswordConfirmationInput
class RegistrationForm(forms.Form): class RegistrationForm(forms.Form):
email = forms.EmailField(label="Your email (lowercase)") email = forms.EmailField(label="Your email (lowercase)")

114
ietf/ietfauth/widgets.py Normal file
View file

@ -0,0 +1,114 @@
from django.forms import PasswordInput
from django.utils.safestring import mark_safe
from django.utils.translation import gettext as _
# The PasswordStrengthInput and PasswordConfirmationInput widgets come from the
# django-password-strength project, https://pypi.org/project/django-password-strength/
#
# Original license:
#
# Copyright © 2015 A.J. May and individual contributors. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
# following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
# disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
# following disclaimer in the documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
# products derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
class PasswordStrengthInput(PasswordInput):
"""
Form widget to show the user how strong his/her password is.
"""
def render(self, name, value, attrs=None, renderer=None):
strength_markup = """
<div style="margin-top: 10px;">
<div class="progress" style="margin-bottom: 10px;">
<div class="progress-bar progress-bar-warning password_strength_bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="5" style="width: 0%%"></div>
</div>
<p class="text-muted password_strength_info hidden">
<span class="label label-danger">
%s
</span>
<span style="margin-left:5px;">
%s
</span>
</p>
</div>
""" % (
_("Warning"),
_(
'This password would take <em class="password_strength_time"></em> to crack.'
),
)
try:
self.attrs["class"] = "%s password_strength".strip() % self.attrs["class"]
except KeyError:
self.attrs["class"] = "password_strength"
return mark_safe(
super(PasswordInput, self).render(name, value, attrs, renderer)
+ strength_markup
)
class Media:
js = (
"ietf/js/zxcvbn.js",
"ietf/js/password_strength.js",
)
class PasswordConfirmationInput(PasswordInput):
"""
Form widget to confirm the users password by letting him/her type it again.
"""
def __init__(self, confirm_with=None, attrs=None, render_value=False):
super(PasswordConfirmationInput, self).__init__(attrs, render_value)
self.confirm_with = confirm_with
def render(self, name, value, attrs=None, renderer=None):
if self.confirm_with:
self.attrs["data-confirm-with"] = "id_%s" % self.confirm_with
confirmation_markup = """
<div style="margin-top: 10px;" class="hidden password_strength_info">
<p class="text-muted">
<span class="label label-danger">
%s
</span>
<span style="margin-left:5px;">%s</span>
</p>
</div>
""" % (
_("Warning"),
_("Your passwords don't match."),
)
try:
self.attrs["class"] = (
"%s password_confirmation".strip() % self.attrs["class"]
)
except KeyError:
self.attrs["class"] = "password_confirmation"
return mark_safe(
super(PasswordInput, self).render(name, value, attrs, renderer)
+ confirmation_markup
)

View file

@ -6,8 +6,7 @@
{% block title %}Change password{% endblock %} {% block title %}Change password{% endblock %}
{% block js %} {% block js %}
{{ block.super }} {{ block.super }}
<script src="{% static 'ietf/js/zxcvbn.js' %}"></script> {{ form.media.js }}
<script src="{% static 'ietf/js/password_strength.js' %}"></script>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
{% origin %} {% origin %}

View file

@ -6,8 +6,7 @@
{% block title %}Complete account creation{% endblock %} {% block title %}Complete account creation{% endblock %}
{% block js %} {% block js %}
{{ block.super }} {{ block.super }}
<script src="{% static 'ietf/js/zxcvbn.js' %}"></script> {{ form.media.js }}
<script src="{% static 'ietf/js/password_strength.js' %}"></script>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
{% origin %} {% origin %}