From 21418f632f12825001b4c865547c63412e71ad9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Thu, 13 Apr 2017 16:19:20 +0200 Subject: [PATCH] Added support for password validation using Django or custom validators e. g. for minimum password length. --- CHANGELOG | 2 ++ openslides/users/views.py | 10 ++++++++++ openslides/utils/settings.py.tpl | 8 +++++--- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 4fb48f183..3e023d9fe 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -29,6 +29,8 @@ Users: motion submitters and supporters, assignment candidates, mediafile uploader and chat message users if they have the respective 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) diff --git a/openslides/users/views.py b/openslides/users/views.py index 191d4e413..5d88f7270 100644 --- a/openslides/users/views.py +++ b/openslides/users/views.py @@ -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 update_session_auth_hash 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.translation import ugettext as _ @@ -102,6 +104,10 @@ class UserViewSet(ModelViewSet): """ user = self.get_object() 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.save() return Response({'detail': _('Password successfully reset.')}) @@ -319,6 +325,10 @@ class SetPasswordView(APIView): def post(self, request, *args, **kwargs): user = request.user 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.save() update_session_auth_hash(request, user) diff --git a/openslides/utils/settings.py.tpl b/openslides/utils/settings.py.tpl index b6bf1726b..7101c44b9 100644 --- a/openslides/utils/settings.py.tpl +++ b/openslides/utils/settings.py.tpl @@ -68,9 +68,7 @@ DATABASES = { # Set use_redis to True to activate redis as cache-, asgi- and session backend. use_redis = False - if use_redis: - # Django Channels # Unless you have only a small assembly uncomment the following lines to @@ -111,7 +109,6 @@ if use_redis: SESSION_ENGINE = 'redis_sessions.session' - # Internationalization # 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', '') +# 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 MOTION_IDENTIFIER_MIN_DIGITS = 1