Added support for password validation using Django or custom validators e. g. for minimum password length.

This commit is contained in:
Norman Jäckel 2017-04-13 16:19:20 +02:00
parent 7d2785b9ec
commit 21418f632f
3 changed files with 17 additions and 3 deletions

View File

@ -29,6 +29,8 @@ Users:
motion submitters and supporters, assignment candidates, mediafile motion submitters and supporters, assignment candidates, mediafile
uploader and chat message users if they have the respective uploader and chat message users if they have the respective
permissions [#3191]. permissions [#3191].
- Added support for password validation using Django or custom validators
e. g. for minimum password length [#3200].
Version 2.1.1 (2017-04-05) Version 2.1.1 (2017-04-05)

View File

@ -2,6 +2,8 @@ from django.contrib.auth import login as auth_login
from django.contrib.auth import logout as auth_logout from django.contrib.auth import logout as auth_logout
from django.contrib.auth import update_session_auth_hash from django.contrib.auth import update_session_auth_hash
from django.contrib.auth.forms import AuthenticationForm from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.password_validation import validate_password
from django.core.exceptions import ValidationError as DjangoValidationError
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
@ -102,6 +104,10 @@ class UserViewSet(ModelViewSet):
""" """
user = self.get_object() user = self.get_object()
if isinstance(request.data.get('password'), str): if isinstance(request.data.get('password'), str):
try:
validate_password(request.data.get('password'), user=request.user)
except DjangoValidationError as errors:
raise ValidationError({'detail': ' '.join(errors)})
user.set_password(request.data.get('password')) user.set_password(request.data.get('password'))
user.save() user.save()
return Response({'detail': _('Password successfully reset.')}) return Response({'detail': _('Password successfully reset.')})
@ -319,6 +325,10 @@ class SetPasswordView(APIView):
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
user = request.user user = request.user
if user.check_password(request.data['old_password']): if user.check_password(request.data['old_password']):
try:
validate_password(request.data.get('new_password'), user=user)
except DjangoValidationError as errors:
raise ValidationError({'detail': ' '.join(errors)})
user.set_password(request.data['new_password']) user.set_password(request.data['new_password'])
user.save() user.save()
update_session_auth_hash(request, user) update_session_auth_hash(request, user)

View File

@ -68,9 +68,7 @@ DATABASES = {
# Set use_redis to True to activate redis as cache-, asgi- and session backend. # Set use_redis to True to activate redis as cache-, asgi- and session backend.
use_redis = False use_redis = False
if use_redis: if use_redis:
# Django Channels # Django Channels
# Unless you have only a small assembly uncomment the following lines to # Unless you have only a small assembly uncomment the following lines to
@ -111,7 +109,6 @@ if use_redis:
SESSION_ENGINE = 'redis_sessions.session' SESSION_ENGINE = 'redis_sessions.session'
# Internationalization # Internationalization
# https://docs.djangoproject.com/en/1.10/topics/i18n/ # https://docs.djangoproject.com/en/1.10/topics/i18n/
@ -132,6 +129,11 @@ STATIC_ROOT = os.path.join(OPENSLIDES_USER_DATA_PATH, 'collected-static')
MEDIA_ROOT = os.path.join(OPENSLIDES_USER_DATA_PATH, 'media', '') MEDIA_ROOT = os.path.join(OPENSLIDES_USER_DATA_PATH, 'media', '')
# Password validation
# https://docs.djangoproject.com/en/1.10/topics/auth/passwords/#module-django.contrib.auth.password_validation
# AUTH_PASSWORD_VALIDATORS = []
# Customization of OpenSlides apps # Customization of OpenSlides apps
MOTION_IDENTIFIER_MIN_DIGITS = 1 MOTION_IDENTIFIER_MIN_DIGITS = 1