Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

212 password change #254

Merged
merged 11 commits into from
Oct 16, 2017
50 changes: 48 additions & 2 deletions humans/forms.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
from django.forms import ModelForm
from django import forms
from django.contrib.auth.password_validation import validate_password
from django.utils.translation import ugettext_lazy as _
from allauth.account.forms import LoginForm as BaseLoginForm
from allauth.account.forms import SignupForm as BaseSignupForm
from .models import User
from .utils import key_state

import requests


class UpdateUserInfoForm(ModelForm):

class Meta:
model = User
fields = [
Expand All @@ -21,17 +22,62 @@ class Meta:
"fingerprint",
"server_signed",
"timezone",
"language",
"language"
]

widgets = {
'keyserver_url': forms.TextInput(attrs={'placeholder': _("https://example.com/key.asc")}),
'public_key': forms.Textarea(attrs={'placeholder': _("-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: SKS 1.1.1\n<PGP KEY>\n-----END PGP PUBLIC KEY BLOCK-----")})
}

current_password = forms.CharField(label=_('Current password'),
required=False,
widget=forms.PasswordInput)
new_password1 = forms.CharField(label=_('New password'),
required=False,
widget=forms.PasswordInput)
new_password2 = forms.CharField(label=_('New password confirmation'),
required=False,
widget=forms.PasswordInput)

def __init__(self, *args, **kwargs):
# Flag to let the save method know when to call set_password
self.change_password = False
self.pub_key = None
return super().__init__(*args, **kwargs)

def save(self, commit=True):
new_password = self.cleaned_data.get('new_password2')
if self.change_password:
self.instance.set_password(new_password)
return super().save(commit=commit)

def clean_current_password(self):
"""
Validates that the current_password field is correct.
"""
current_password = self.cleaned_data.get('current_password')
if len(current_password) > 0:
if not self.instance.check_password(current_password):
self.add_error('current_password',
_('Your current password was entered incorrectly.'))
return current_password

def clean_new_password2(self):
"""
Validates that both new password entries are equal.
"""
password1 = self.cleaned_data.get('new_password1')
password2 = self.cleaned_data.get('new_password2')
if password1 and password2:
validate_password(password1, self.instance)
if password1 != password2:
self.add_error('new_password2',
_("The two password fields didn't match."))
else:
self.change_password = True
return password2

def clean_public_key(self):
# Validate the public key
if self.pub_key:
Expand Down
6 changes: 4 additions & 2 deletions humans/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ class User(AbstractUser):
timezone = TimeZoneField(default='UTC', verbose_name=_('Timezone'))
language = models.CharField(default="en-us", max_length=16, choices=LANGUAGE_CHOICES , verbose_name=_('Language'))



def has_setup_complete(self):
if self.public_key and self.fingerprint:
return True
return False

@property
def has_github_login(self):
return self.socialaccount_set.filter(provider='github').count() >= 1

@property
def has_public_key(self):
return True if self.public_key else False
Expand Down
35 changes: 9 additions & 26 deletions humans/static/javascripts/update_user_form.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,16 @@ $(document).ready(function(){
$(".label-form-b label").addClass("smallmedium text-darkest");
$(".checkbox- label").addClass("smallmedium text-darkest");

$("#tab1").click(function(){
//slide up all the link lists
$("#section1").show();
$("#section2").hide();
$("#section3").hide();
$("#tab1").addClass("active");
$("#tab2").removeClass("active");
$("#tab3").removeClass("active");
});
$("#tab2").click(function(){
//slide up all the link lists
$("#section2").show();
$("#section1").hide();
$("#section3").hide();
$("#tab2").addClass("active");
$("#tab1").removeClass("active");
$("#tab3").removeClass("active");
});
$("#tab3").click(function(){
//slide up all the link lists
$("#section3").show();
$("#section1").hide();
$("#section2").hide();
$("#tab3").addClass("active");
$("#tab1").removeClass("active");
$("#tab2").removeClass("active");
$(".sett__nav__item").click(function(evt) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason this event is not being added to #tab4 (at least on Firefox)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested here on Firefox and it triggers the event just fine.
Maybe a version issue? Can you try again?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just tested again, with different browsers and it is working fine. Not sure what was the problem the other time.

var tabId = evt.target.id;
var index = $(evt.target).index() + 1;

$(".sett__nav__item").removeClass("active");
$(tabId).addClass("active");
$(".section").hide();
$("#section" + index).show();
});

$('.radio_button').on('change', function() {
if ($('.radio_button:checked').val() == "keyserver") {
$("#keyserver_url").show();
Expand Down
18 changes: 17 additions & 1 deletion humans/templates/humans/update_user_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
<div class="col-xs-12 nav-st no-padding text-left">
<li id="tab1" class="sett__nav__item text-darkest active">{% trans "Profile" %}</li>
<li id="tab2" class="sett__nav__item text-darkest">{% trans "Keys" %}</li>
<li id="tab3" class="sett__nav__item text-darkest">{% trans "Experimental Features" %}</li>
{% if not form.instance.has_github_login %}
<li id="tab3" class="sett__nav__item text-darkest">{% trans "Password" %}</li>
{%endif %}
<li id="tab4" class="sett__nav__item text-darkest">{% trans "Experimental Features" %}</li>
</div>
</ul>

Expand Down Expand Up @@ -65,6 +68,19 @@
</div>
</li>
<li class="section" id="section3">
<div class="col-xxs-12 col-xs-12 col-md-12 start-xs">
<div class="form__block">
{{ form.current_password.errors }} {{ form.current_password.label_tag }} {{ form.current_password }}
</div>
<div class="form__block">
{{ form.new_password2.errors }} {{ form.new_password1.label_tag }} {{ form.new_password1 }}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a typo, should be {{ form.new_password1.errors }}

</div>
<div class="form__block">
{{ form.new_password2.errors }} {{ form.new_password2.label_tag }} {{ form.new_password2 }}
</div>
</div>
</li>
<li class="section" id="section4">
<div class="col-xs-12 start-xs">
<span class="text-blue smalltext">
<p>
Expand Down
73 changes: 73 additions & 0 deletions humans/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,79 @@ def test_non_valid_language(self):
form = UpdateUserInfoForm(data)
self.assertEqual(form.is_valid(), False)

def test_wrong_current_password(self):
"""
Tests if the form is invalidated because the wrong password was sent
"""
data = {
'current_password': 'wrongpassword',
'timezone': 'UTC',
'language': 'en-us'
}
user = create_and_login_user(self.client)
form = UpdateUserInfoForm(data, instance=user)
self.assertEqual(form.is_valid(), False)
self.assertTrue('current_password' in form.errors)

def test_invalid_password(self):
"""
Tests that Django password constraints are being tested
"""
data = {
'current_password': '123123',
'new_password1': 'a',
'new_password2': 'a',
'timezone': 'UTC',
'language': 'en-us'
}
user = create_and_login_user(self.client)
user.set_password('123123')
user.save()

form = UpdateUserInfoForm(data, instance=user)
self.assertEqual(form.is_valid(), False)
self.assertTrue('new_password2' in form.errors)

def test_non_matching_passwords(self):
"""
Tests if the form invalidates when password are valid but different
"""
data = {
'current_password': '123123',
'new_password1': 'abcABCD123',
'new_password2': 'abcABCD1234',
'timezone': 'UTC',
'language': 'en-us'
}
user = create_and_login_user(self.client)
user.set_password('123123')
user.save()

form = UpdateUserInfoForm(data, instance=user)
self.assertEqual(form.is_valid(), False)
self.assertTrue('new_password2' in form.errors)

def test_change_password(self):
"""
Tests if the password is actually changed
"""
data = {
'current_password':'123123',
'new_password1': 'abcABCD123',
'new_password2': 'abcABCD123',
'timezone': 'UTC',
'language': 'en-us'
}
user = create_and_login_user(self.client)
user.set_password('123123')
user.save()

form = UpdateUserInfoForm(data, instance=user)
self.assertEqual(form.is_valid(), True)
form.save()
user.refresh_from_db()
self.assertTrue(user.check_password(data["new_password1"]))


class UtilsTests(TestCase):

Expand Down
3 changes: 3 additions & 0 deletions humans/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.contrib.auth.mixins import LoginRequiredMixin as LoginRequired
from django.contrib.auth import logout, authenticate
from django.contrib.auth import update_session_auth_hash
from django.views.generic import FormView, DeleteView
from django.core.urlresolvers import reverse_lazy
from django.utils.translation import ugettext_lazy as _
Expand Down Expand Up @@ -48,6 +49,8 @@ def get_form_kwargs(self):

def form_valid(self, form):
form.save()
if form.change_password:
update_session_auth_hash(self.request, form.instance)
messages.success(self.request, _('Settings successfully updated'))
return super().form_valid(form)

Expand Down
Binary file modified locale/pt_PT/LC_MESSAGES/django.mo
Binary file not shown.