Replaced django-passwords by django's builtins.

see #1153
This commit is contained in:
Antoine Nguyen
2017-06-22 15:53:58 +02:00
parent 6b5c666731
commit c236d60bd9
8 changed files with 137 additions and 22 deletions
+4 -3
View File
@@ -10,7 +10,7 @@ from django.core.urlresolvers import reverse
from django.http import QueryDict
from django.utils.translation import ugettext as _, ugettext_lazy
from passwords.fields import PasswordField
from django.contrib.auth import password_validation
from modoboa.core import signals as core_signals
from modoboa.core.models import User
@@ -45,11 +45,11 @@ class AccountFormGeneral(forms.ModelForm):
choices=[("", ugettext_lazy("Choose"))],
help_text=ugettext_lazy("What level of permission this user will have")
)
password1 = PasswordField(
password1 = forms.CharField(
label=ugettext_lazy("Password"), widget=forms.widgets.PasswordInput
)
password2 = PasswordField(
password2 = forms.CharField(
label=ugettext_lazy("Confirmation"),
widget=forms.widgets.PasswordInput,
help_text=ugettext_lazy(
@@ -157,6 +157,7 @@ class AccountFormGeneral(forms.ModelForm):
if password1 != password2:
raise forms.ValidationError(
_("The two password fields didn't match."))
password_validation.validate_password(password2, self.instance)
return password2
def clean(self):
+3 -3
View File
@@ -7,8 +7,9 @@ from django.shortcuts import get_object_or_404
from django.utils.translation import ugettext as _, ugettext_lazy
from django.utils.encoding import force_text
from django.contrib.auth import password_validation
from rest_framework import serializers
from passwords import validators
from modoboa.admin import models as admin_models
from modoboa.core import constants as core_constants
@@ -159,8 +160,7 @@ class AccountPasswordSerializer(serializers.ModelSerializer):
def validate_new_password(self, value):
"""Check new password."""
try:
validators.validate_length(value)
validators.complexity(value)
password_validation.validate_password(value, self.instance)
except ValidationError as exc:
raise serializers.ValidationError(exc.messages[0])
return value
+8 -3
View File
@@ -6,7 +6,7 @@ from django import forms
from django.conf import settings
from django.utils.translation import ugettext as _, ugettext_lazy
from passwords import validators
from django.contrib.auth import password_validation
from modoboa.lib import fields as lib_fields
from modoboa.lib.cryptutils import random_key
@@ -83,8 +83,7 @@ class GeneralParametersForm(param_forms.AdminParametersForm):
label=ugettext_lazy("Default password"),
initial="password",
help_text=ugettext_lazy(
"Default password for automatically created accounts."),
validators=[validators.validate_length, validators.complexity]
"Default password for automatically created accounts.")
)
# LDAP specific settings
@@ -351,6 +350,12 @@ class GeneralParametersForm(param_forms.AdminParametersForm):
raise forms.ValidationError(_("Invalid rounds number"))
return value
def clean_default_password(self):
"""Check password complexity."""
value = self.cleaned_data["default_password"]
password_validation.validate_password(value)
return value
def clean(self):
"""Custom validation method
@@ -178,15 +178,31 @@ REST_FRAMEWORK = {
MODOBOA_API_URL = 'https://api.modoboa.org/1/'
# django-passwords
# Password validation rules
PASSWORD_MIN_LENGTH = 8
PASSWORD_COMPLEXITY = {
"UPPER": 1,
"LOWER": 1,
"DIGITS": 1
}
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
{
'NAME': 'modoboa.core.password_validation.ComplexityValidator',
'OPTIONS': {
'upper': 1,
'lower': 1,
'digits': 1,
'specials': 0
}
},
]
# CKeditor
+5 -4
View File
@@ -7,7 +7,7 @@ from __future__ import unicode_literals
from django import forms
from django.utils.translation import ugettext as _, ugettext_lazy
from passwords.fields import PasswordField
from django.contrib.auth import password_validation
from modoboa.core.models import User
from modoboa.parameters import tools as param_tools
@@ -37,11 +37,11 @@ class ProfileForm(forms.ModelForm):
label=ugettext_lazy("Old password"), required=False,
widget=forms.PasswordInput(attrs={"class": "form-control"})
)
newpassword = PasswordField(
newpassword = forms.CharField(
label=ugettext_lazy("New password"), required=False,
widget=forms.PasswordInput(attrs={"class": "form-control"})
)
confirmation = PasswordField(
confirmation = forms.CharField(
label=ugettext_lazy("Confirmation"), required=False,
widget=forms.PasswordInput(attrs={"class": "form-control"})
)
@@ -78,7 +78,8 @@ class ProfileForm(forms.ModelForm):
confirmation = self.cleaned_data["confirmation"]
if newpassword != confirmation:
raise forms.ValidationError(_("Passwords mismatch"))
return self.cleaned_data["confirmation"]
password_validation.validate_password(confirmation, self.instance)
return confirmation
def save(self, commit=True):
user = super(ProfileForm, self).save(commit=False)
+68
View File
@@ -0,0 +1,68 @@
"""Custom password validators."""
from __future__ import unicode_literals
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext as _, ungettext
class ComplexityValidator(object):
"""Check password contains at least a few things."""
def __init__(self, upper=1, lower=1, digits=1, specials=1):
self.upper = upper
self.lower = lower
self.digits = digits
self.specials = specials
def validate(self, password, user=None):
special_characters = "~!@#$%^&*()_+{}\":;,'[]"
condition = (
self.digits > 0 and
sum([1 for char in password if char.isdigit()]) < self.digits)
if condition:
raise ValidationError(
ungettext(
"Password must contain at least {} digit.",
"Password must contain at least {} digits.",
self.digits
).format(self.digits))
condition = (
self.lower > 0 and
sum([1 for char in password if char.islower()]) < self.lower)
if condition:
raise ValidationError(
ungettext(
"Password must contain at least {} lowercase letter.",
"Password must contain at least {} lowercase letters.",
self.lower
)
.format(self.lower))
condition = (
self.upper > 0 and
sum([1 for char in password if char.isupper()]) < self.upper)
if condition:
raise ValidationError(
ungettext(
"Password must contain at least {} uppercase letter.",
"Password must contain at least {} uppercase letters.",
self.upper
)
.format(self.upper))
condition = (
self.specials > 0 and
sum([1 for char in password if char in special_characters]) <
self.specials)
if condition:
raise ValidationError(
ungettext(
"Password must contain at least {} special character.",
"Password must contain at least {} special characters.",
self.specials
)
.format(self.specials))
def get_help_text(self):
return _(
"Your password must contain a combination of different "
"character types.")
-1
View File
@@ -1,6 +1,5 @@
django>=1.10,<=1.10.99
django-ckeditor==5.2.1
django-passwords==0.3.12
django-reversion==1.10.2
django-subcommand2==0.1.1
django-versionfield2>=0.5.0
+25
View File
@@ -87,6 +87,31 @@ AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
)
# Password validation rules
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
{
'NAME': 'modoboa.core.password_validation.ComplexityValidator',
'OPTIONS': {
'upper': 1,
'lower': 1,
'digits': 1,
'specials': 0
}
},
]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',