SciPost Code Repository

Skip to content
Snippets Groups Projects
Commit 1c29aa27 authored by Jorran de Wit's avatar Jorran de Wit
Browse files

Merge branch 'password' into development

parents da68c036 9490ba5e
No related branches found
No related tags found
No related merge requests found
...@@ -246,3 +246,31 @@ CROSSREF_LOGIN_PASSWORD = '' ...@@ -246,3 +246,31 @@ CROSSREF_LOGIN_PASSWORD = ''
RECAPTCHA_PUBLIC_KEY = '6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI' RECAPTCHA_PUBLIC_KEY = '6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI'
RECAPTCHA_PRIVATE_KEY = '6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe' RECAPTCHA_PRIVATE_KEY = '6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe'
NOCAPTCHA = True NOCAPTCHA = True
# PASSWORDS
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.Argon2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
'django.contrib.auth.hashers.BCryptPasswordHasher',
]
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
'OPTIONS': {
'min_length': 8,
}
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
alabaster==0.7.9 alabaster==0.7.9
argon2-cffi==16.3.0
Babel==2.3.4 Babel==2.3.4
Django==1.10.3 Django==1.10.3
django_ajax_selects==1.5.2 django_ajax_selects==1.5.2
......
from django import forms from django import forms
from django.contrib.auth import authenticate from django.contrib.auth import authenticate
from django.contrib.auth.models import User, Group from django.contrib.auth.models import User, Group
from django.contrib.auth.password_validation import validate_password
from django.core.exceptions import ValidationError
from django.core.urlresolvers import reverse_lazy from django.core.urlresolvers import reverse_lazy
from django.utils.http import is_safe_url from django.utils.http import is_safe_url
...@@ -16,7 +18,7 @@ from .models import Contributor, DraftInvitation, RegistrationInvitation,\ ...@@ -16,7 +18,7 @@ from .models import Contributor, DraftInvitation, RegistrationInvitation,\
UnavailabilityPeriod, PrecookedEmail UnavailabilityPeriod, PrecookedEmail
from journals.models import Publication from journals.models import Publication
from mailing_lists.models import MailchimpList, MailchimpSubscription # from mailing_lists.models import MailchimpList, MailchimpSubscription
REGISTRATION_REFUSAL_CHOICES = ( REGISTRATION_REFUSAL_CHOICES = (
...@@ -60,13 +62,28 @@ class RegistrationForm(forms.Form): ...@@ -60,13 +62,28 @@ class RegistrationForm(forms.Form):
required=False) required=False)
username = forms.CharField(label='* Username', max_length=100) username = forms.CharField(label='* Username', max_length=100)
password = forms.CharField(label='* Password', widget=forms.PasswordInput()) password = forms.CharField(label='* Password', widget=forms.PasswordInput())
password_verif = forms.CharField(label='* Verify password', widget=forms.PasswordInput()) password_verif = forms.CharField(label='* Verify password', widget=forms.PasswordInput(),
help_text='Your password must contain at least 8 characters')
captcha = ReCaptchaField(attrs={'theme': 'clean'}, label='*Please verify to continue:') captcha = ReCaptchaField(attrs={'theme': 'clean'}, label='*Please verify to continue:')
def clean_password(self):
password = self.cleaned_data.get('password', '')
user = User(
username=self.cleaned_data.get('username', ''),
first_name=self.cleaned_data.get('first_name', ''),
last_name=self.cleaned_data.get('last_name', ''),
email=self.cleaned_data.get('email', '')
)
try:
validate_password(password, user)
except ValidationError as error_message:
self.add_error('password', error_message)
return password
def clean_password_verif(self): def clean_password_verif(self):
if self.cleaned_data['password'] != self.cleaned_data['password_verif']: if self.cleaned_data.get('password', '') != self.cleaned_data.get('password_verif', ''):
self.add_error('password', 'Your passwords must match') self.add_error('password_verif', 'Your password entries must match')
self.add_error('password_verif', 'Your passwords must match') return self.cleaned_data.get('password_verif', '')
def clean_username(self): def clean_username(self):
if User.objects.filter(username=self.cleaned_data['username']).exists(): if User.objects.filter(username=self.cleaned_data['username']).exists():
...@@ -245,6 +262,40 @@ class PasswordChangeForm(forms.Form): ...@@ -245,6 +262,40 @@ class PasswordChangeForm(forms.Form):
password_new = forms.CharField(label='New password', widget=forms.PasswordInput()) password_new = forms.CharField(label='New password', widget=forms.PasswordInput())
password_verif = forms.CharField(label='Reenter new password', widget=forms.PasswordInput()) password_verif = forms.CharField(label='Reenter new password', widget=forms.PasswordInput())
def __init__(self, *args, **kwargs):
self.current_user = kwargs.pop('current_user', None)
super().__init__(*args, **kwargs)
def clean_password_prev(self):
'''Check if old password is correct.'''
password_prev = self.cleaned_data['password_prev']
if not self.current_user.check_password(password_prev):
self.add_error('password_prev',
'The currently existing password you entered is incorrect')
return password_prev
def clean_password_new(self):
'''Validate the newly chosen password using the validators as per the settingsfile.'''
password = self.cleaned_data['password_new']
try:
validate_password(password, self.current_user)
except ValidationError as error_message:
self.add_error('password_new', error_message)
return password
def clean_password_verif(self):
'''Check if the new password's match to ensure the user entered new password correctly.'''
password_verif = self.cleaned_data.get('password_verif', '')
if self.cleaned_data['password_new'] != password_verif:
self.add_error('password_verif', 'Your new password entries must match')
return password_verif
def save_new_password(self):
'''Save new password is form is valid.'''
if not self.errors:
self.current_user.set_password(self.cleaned_data['password_new'])
self.current_user.save()
AUTHORSHIP_CLAIM_CHOICES = ( AUTHORSHIP_CLAIM_CHOICES = (
('-', '-'), ('-', '-'),
......
...@@ -6,26 +6,16 @@ ...@@ -6,26 +6,16 @@
{% block content %} {% block content %}
{% if ack %} <div class="row">
<div class="row"> <div class="col-lg-8 offset-lg-2">
<div class="col-12"> <h1 class="highlight">Change your SciPost password</h1>
<h1>Your SciPost password has been successfully changed</h1>
</div> <form action="{% url 'scipost:change_password' %}" method="post">
</div> {% csrf_token %}
{% else %} {{form|bootstrap}}
<div class="row"> <input type="submit" class="btn btn-secondary" value="Change" />
<div class="col-lg-8 offset-lg-2"> </form>
<h1 class="highlight">Change your SciPost password</h1>
{% if errormessage %}
<p class="text-danger">{{ errormessage }}</p>
{% endif %}
<form action="{% url 'scipost:change_password' %}" method="post">
{% csrf_token %}
{{form|bootstrap}}
<input type="submit" class="btn btn-secondary" value="Change" />
</form>
</div>
</div> </div>
{% endif %} </div>
{% endblock content %} {% endblock content %}
...@@ -2,20 +2,20 @@ ...@@ -2,20 +2,20 @@
{% block pagetitle %}: Reset Password{% endblock pagetitle %} {% block pagetitle %}: Reset Password{% endblock pagetitle %}
{% block bodysup %}
{% load bootstrap %} {% load bootstrap %}
<div class="container"> {% block content %}
<div class="row">
<div class="col-md-4">
<h3>Reset password request form</h3> <div class="row">
<form method="post"> <div class="col-md-4 offset-md-4">
{% csrf_token %} <h3>Reset password request form</h3>
{{ form|bootstrap }} <form method="post">
<input class="btn btn-primary" type="submit" value="Submit" /> {% csrf_token %}
</form> {{ form|bootstrap }}
<input class="btn btn-primary" type="submit" value="Submit" />
</form>
</div> </div>
</div>
</div> </div>
{% endblock bodysup %}
{% endblock %}
...@@ -3,5 +3,5 @@ ...@@ -3,5 +3,5 @@
{% block pagetitle %}: Reset password complete{% endblock pagetitle %} {% block pagetitle %}: Reset password complete{% endblock pagetitle %}
{% block bodysup %} {% block bodysup %}
<p>You have successfully reset your password.</p> <p>You have successfully reset your password.</p>
{% endblock bodysup %} {% endblock bodysup %}
...@@ -2,16 +2,22 @@ ...@@ -2,16 +2,22 @@
{% block pagetitle %}: Reset password confirm{% endblock pagetitle %} {% block pagetitle %}: Reset password confirm{% endblock pagetitle %}
{% block bodysup %} {% load bootstrap %}
<section>
{% block content %}
<div class="row">
<div class="col-md-6 offset-md-3">
{% if validlink %} {% if validlink %}
<form method="post"> <form method="post">
{% csrf_token %} {% csrf_token %}
{{ form.as_p }} {{ form|bootstrap }}
<button type="submit">Submit</button> <input class="btn btn-secondary" type="submit" value="Submit">
</form> </form>
{% else %} {% else %}
<p>This reset link is no longer valid!</p> <p>This reset link is no longer valid!</p>
{% endif %} {% endif %}
</section> </div>
{% endblock bodysup %} </div>
{% endblock content %}
...@@ -3,7 +3,7 @@ import re ...@@ -3,7 +3,7 @@ import re
from django.utils import timezone from django.utils import timezone
from django.shortcuts import get_object_or_404, render from django.shortcuts import get_object_or_404, render
from django.contrib import messages from django.contrib import messages
from django.contrib.auth import login, logout from django.contrib.auth import login, logout, update_session_auth_hash
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from django.contrib.auth.views import password_reset, password_reset_confirm from django.contrib.auth.views import password_reset, password_reset_confirm
...@@ -914,23 +914,14 @@ def personal_page(request): ...@@ -914,23 +914,14 @@ def personal_page(request):
@login_required @login_required
def change_password(request): def change_password(request):
form = PasswordChangeForm(request.POST or None) form = PasswordChangeForm(request.POST or None, current_user=request.user)
ack = False
if form.is_valid(): if form.is_valid():
if not request.user.check_password(form.cleaned_data['password_prev']): form.save_new_password()
return render( # Update user's session hash to stay logged in.
request, 'scipost/change_password.html', update_session_auth_hash(request, request.user)
{'form': form, messages.success(request, 'Your SciPost password has been successfully changed')
'errormessage': 'The currently existing password you entered is incorrect'}) return redirect(reverse('scipost:personal_page'))
if form.cleaned_data['password_new'] != form.cleaned_data['password_verif']: return render(request, 'scipost/change_password.html', {'form': form})
return render(request, 'scipost/change_password.html', {
'form': form,
'errormessage': 'Your new password entries must match'})
request.user.set_password(form.cleaned_data['password_new'])
request.user.save()
ack = True
return render(request, 'scipost/change_password.html', {'ack': ack, 'form': form})
def reset_password_confirm(request, uidb64=None, token=None): def reset_password_confirm(request, uidb64=None, token=None):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment