From fe4acbbb9b32b76333fa8361ecceea1a555ae565 Mon Sep 17 00:00:00 2001 From: Paul Eggleton Date: Wed, 17 Jul 2019 15:15:07 +1200 Subject: [PATCH] Optionally allow accounts without security questions to reset password Add a SECURITY_QUESTIONS_REQUIRED setting that defaults to True, but if set to False then a user who has not set security questions will still be allowed to reset their password. This is convenient for the OE Layer index because there are a number of existing accounts, none of which will have security questions set. Signed-off-by: Paul Eggleton --- docker/settings.py | 3 +++ layerindex/auth_forms.py | 30 +++++++++++++++++++++++++----- layerindex/auth_views.py | 3 ++- settings.py | 3 +++ 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/docker/settings.py b/docker/settings.py index c11c700..616b67b 100644 --- a/docker/settings.py +++ b/docker/settings.py @@ -257,6 +257,9 @@ REMOVE_LAYER_DEPENDENCIES = False # the login page) FORCE_REVIEW_HTTPS = True +# False to allow accounts without security questions to reset their password +SECURITY_QUESTIONS_REQUIRED = True + # Settings for layer submission feature SUBMIT_EMAIL_FROM = 'noreply@' + os.getenv('HOSTNAME', 'layers.test') SUBMIT_EMAIL_SUBJECT = 'OE Layerindex layer submission' diff --git a/layerindex/auth_forms.py b/layerindex/auth_forms.py index 1f6091d..fc3d2d1 100644 --- a/layerindex/auth_forms.py +++ b/layerindex/auth_forms.py @@ -11,7 +11,8 @@ from django.contrib.auth.hashers import check_password from django.contrib.auth.models import User from django_registration.forms import RegistrationForm -from layerindex.models import SecurityQuestion +from layerindex.models import SecurityQuestion, UserProfile +import settings class CaptchaRegistrationForm(RegistrationForm): @@ -84,9 +85,24 @@ class SecurityQuestionPasswordResetForm(SetPasswordForm): def __init__(self, *args, **kwargs): super(SecurityQuestionPasswordResetForm, self ).__init__(*args, **kwargs) - self.fields['security_question_1'].initial=SecurityQuestion.objects.all()[0] - self.fields['security_question_2'].initial=SecurityQuestion.objects.all()[1] - self.fields['security_question_3'].initial=SecurityQuestion.objects.all()[2] + security_questions = True + try: + self.user.userprofile + except UserProfile.DoesNotExist: + if not getattr(settings, 'SECURITY_QUESTIONS_REQUIRED', True): + security_questions = False + + if security_questions: + self.fields['security_question_1'].initial = SecurityQuestion.objects.all()[0] + self.fields['security_question_2'].initial = SecurityQuestion.objects.all()[1] + self.fields['security_question_3'].initial = SecurityQuestion.objects.all()[2] + else: + del self.fields['security_question_1'] + del self.fields['answer_1'] + del self.fields['security_question_2'] + del self.fields['answer_2'] + del self.fields['security_question_3'] + del self.fields['answer_3'] def clean_answer_util(self, question, answer): form_security_question = self.cleaned_data[question] @@ -117,7 +133,11 @@ class SecurityQuestionPasswordResetForm(SetPasswordForm): def clean(self): # We require three correct security question answers. The user gets # three attempts before their account is locked out. - answer_attempts = self.user.userprofile.answer_attempts + try: + answer_attempts = self.user.userprofile.answer_attempts + except UserProfile.DoesNotExist: + if not getattr(settings, 'SECURITY_QUESTIONS_REQUIRED', True): + return if self.correct_answers < 3: if answer_attempts < 2: self.user.userprofile.answer_attempts = self.user.userprofile.answer_attempts + 1 diff --git a/layerindex/auth_views.py b/layerindex/auth_views.py index 5fc0400..d10c750 100644 --- a/layerindex/auth_views.py +++ b/layerindex/auth_views.py @@ -109,7 +109,8 @@ class PasswordResetSecurityQuestions(PasswordResetConfirmView): try: self.user.userprofile except UserProfile.DoesNotExist: - return HttpResponseRedirect(reverse('password_reset_fail')) + if getattr(settings, 'SECURITY_QUESTIONS_REQUIRED', True): + return HttpResponseRedirect(reverse('password_reset_fail')) if not self.user.is_active: return HttpResponseRedirect(reverse('account_lockout')) diff --git a/settings.py b/settings.py index 3dc4b99..e0f5984 100644 --- a/settings.py +++ b/settings.py @@ -252,6 +252,9 @@ REMOVE_LAYER_DEPENDENCIES = False # the login page) FORCE_REVIEW_HTTPS = False +# False to allow accounts without security questions to reset their password +SECURITY_QUESTIONS_REQUIRED = True + # Settings for layer submission feature SUBMIT_EMAIL_FROM = 'noreply@example.com' SUBMIT_EMAIL_SUBJECT = 'OE Layerindex layer submission'