diff --git a/humans/forms.py b/humans/forms.py index bed71b72..73c457a9 100644 --- a/humans/forms.py +++ b/humans/forms.py @@ -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 = [ @@ -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\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: diff --git a/humans/models.py b/humans/models.py index a3edf2fb..afdca64e 100644 --- a/humans/models.py +++ b/humans/models.py @@ -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 diff --git a/humans/static/javascripts/update_user_form.js b/humans/static/javascripts/update_user_form.js index afe415af..9ecd4998 100644 --- a/humans/static/javascripts/update_user_form.js +++ b/humans/static/javascripts/update_user_form.js @@ -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) { + 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(); diff --git a/humans/templates/humans/update_user_form.html b/humans/templates/humans/update_user_form.html index 53d27dd1..1616917e 100644 --- a/humans/templates/humans/update_user_form.html +++ b/humans/templates/humans/update_user_form.html @@ -11,7 +11,10 @@ @@ -65,6 +68,19 @@
  • +
    +
    + {{ form.current_password.errors }} {{ form.current_password.label_tag }} {{ form.current_password }} +
    +
    + {{ form.new_password2.errors }} {{ form.new_password1.label_tag }} {{ form.new_password1 }} +
    +
    + {{ form.new_password2.errors }} {{ form.new_password2.label_tag }} {{ form.new_password2 }} +
    +
    +
  • +
  • diff --git a/humans/tests.py b/humans/tests.py index 61dc35c1..e562f287 100644 --- a/humans/tests.py +++ b/humans/tests.py @@ -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): diff --git a/humans/views.py b/humans/views.py index 465df4d1..a4d768aa 100644 --- a/humans/views.py +++ b/humans/views.py @@ -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 _ @@ -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) diff --git a/locale/pt_PT/LC_MESSAGES/django.mo b/locale/pt_PT/LC_MESSAGES/django.mo index 33c7907e..65f97d0f 100644 Binary files a/locale/pt_PT/LC_MESSAGES/django.mo and b/locale/pt_PT/LC_MESSAGES/django.mo differ diff --git a/locale/pt_PT/LC_MESSAGES/django.po b/locale/pt_PT/LC_MESSAGES/django.po index 9ddcd541..eea4be47 100644 --- a/locale/pt_PT/LC_MESSAGES/django.po +++ b/locale/pt_PT/LC_MESSAGES/django.po @@ -8,14 +8,15 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-08-25 12:38+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" +"POT-Creation-Date: 2017-10-03 15:31+0000\n" +"PO-Revision-Date: 2017-10-03 12:36-0300\n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Last-Translator: \n" +"Language-Team: \n" +"X-Generator: Poedit 2.0.1\n" #: boxes/forms.py:40 msgid "The date must be on the future." @@ -192,7 +193,7 @@ msgstr "Ainda não tem caixas criadas" #: boxes/templates/boxes/box_list.html:93 msgid "" -"A Box is a generated link where other people can submit information, that " +"A Box is a generated link where other people can submit information that " "will be encrypted and delivered to you. They can have several different " "settings." msgstr "" @@ -207,8 +208,8 @@ msgid "" "not please add your public key first." msgstr "" "Se já configurou a sua chave pública nas definições, para começar a usar o " -"Hawkpost precisa apenas de clicar no botão ''Nova caixa''. Se ainda não o fez " -"por favor adicione a sua chave pública primeiro." +"Hawkpost precisa apenas de clicar no botão ''Nova caixa''. Se ainda não o " +"fez por favor adicione a sua chave pública primeiro." #: boxes/templates/boxes/box_list.html:104 msgid "Previous" @@ -1028,11 +1029,11 @@ msgstr "Administrador Hawkpost" msgid "Project Models" msgstr "Modelos do projecto" -#: humans/forms.py:27 +#: humans/forms.py:29 msgid "https://example.com/key.asc" msgstr "" -#: humans/forms.py:28 +#: humans/forms.py:30 msgid "" "-----BEGIN PGP PUBLIC KEY BLOCK-----\n" "Version: SKS 1.1.1\n" @@ -1040,27 +1041,47 @@ msgid "" "-----END PGP PUBLIC KEY BLOCK-----" msgstr "" -#: humans/forms.py:46 +#: humans/forms.py:33 humans/templates/humans/user_confirm_delete.html:22 +msgid "Current password" +msgstr "Password actual" + +#: humans/forms.py:36 +msgid "New password" +msgstr "Nova password" + +#: humans/forms.py:39 +msgid "New password confirmation" +msgstr "Confirmação da nova password" + +#: humans/forms.py:63 +msgid "Your current password was entered incorrectly." +msgstr "Sua password actual está incorreta." + +#: humans/forms.py:76 +msgid "The two password fields didn't match." +msgstr "As passwords inseridas não são iguais" + +#: humans/forms.py:92 msgid "This key is not valid" msgstr "Esta chave não é válida" -#: humans/forms.py:49 +#: humans/forms.py:95 msgid "This key is revoked" msgstr "Esta chave foi revogada" -#: humans/forms.py:52 +#: humans/forms.py:98 msgid "This key is expired" msgstr "Esta chave expirou" -#: humans/forms.py:64 +#: humans/forms.py:110 msgid "Fingerprint does not match" msgstr "A impressão digital não corresponde" -#: humans/forms.py:74 +#: humans/forms.py:120 msgid "Could not access the specified url" msgstr "Não foi possível aceder ao url especificado" -#: humans/forms.py:82 +#: humans/forms.py:128 msgid "This url does not have a pgp key" msgstr "Este url não contém uma chave pgp" @@ -1161,10 +1182,14 @@ msgid "Keys" msgstr "Chaves" #: humans/templates/humans/update_user_form.html:14 +msgid "Password" +msgstr "Definir Password\n" + +#: humans/templates/humans/update_user_form.html:15 msgid "Experimental Features" msgstr "Funcionalidades Experimentais" -#: humans/templates/humans/update_user_form.html:48 +#: humans/templates/humans/update_user_form.html:49 msgid "" "You can provide the public key in a static away or " "provide a link to your key in a public key server so we can fetch it for you " @@ -1174,7 +1199,7 @@ msgstr "" "através de um endereço para a chave num servidor externo, de forma a " "podermos descarrega-la por si(recomendado)." -#: humans/templates/humans/update_user_form.html:71 +#: humans/templates/humans/update_user_form.html:85 msgid "" "The \"Server signed\" feature allows you to improve your security by " "allowing us to sign the (already encrypted) message with " @@ -1188,24 +1213,24 @@ msgstr "" "Por agora, os únicos clientes de e-mail que intrepretam correctamente esta " "funcionalidade são oEvolution e mutt" -#: humans/templates/humans/update_user_form.html:81 +#: humans/templates/humans/update_user_form.html:95 msgid "The key used to sign can be found" msgstr "A chave usada para assinar pode ser encontrada" -#: humans/templates/humans/update_user_form.html:81 -#: humans/templates/humans/update_user_form.html:96 +#: humans/templates/humans/update_user_form.html:95 +#: humans/templates/humans/update_user_form.html:110 msgid "here" msgstr "aqui" -#: humans/templates/humans/update_user_form.html:81 +#: humans/templates/humans/update_user_form.html:95 msgid "and the fingerprint, so you can verify it, is the following:" msgstr "e a impressão digital, de forma a poder verificar, é a seguinte:" -#: humans/templates/humans/update_user_form.html:89 +#: humans/templates/humans/update_user_form.html:103 msgid "Save" msgstr "Gravar" -#: humans/templates/humans/update_user_form.html:96 +#: humans/templates/humans/update_user_form.html:110 msgid "Do you wish to delete your account? if yes, just click" msgstr "Deseja apagar a sua conta? se sim, clique" @@ -1221,10 +1246,6 @@ msgstr "" "A sua conta no Hawkpost irá ser apagada juntamente com todas as informações " "relacionada com a mesma. Tem a certeza que deseja continuar?" -#: humans/templates/humans/user_confirm_delete.html:22 -msgid "Current password" -msgstr "Password actual" - #: humans/templates/humans/user_confirm_delete.html:26 msgid "Yes, I want to delete everything" msgstr "Sim, eu quero apagar tudo" @@ -1233,23 +1254,23 @@ msgstr "Sim, eu quero apagar tudo" msgid "No, take me back to the settings" msgstr "Não, voltar para a página das definições" -#: humans/views.py:34 +#: humans/views.py:35 msgid "To start using hawkpost, you must add a valid public key" msgstr "Para começar a usar o hawkpost deve adicionar uma chave pública válida" -#: humans/views.py:51 +#: humans/views.py:54 msgid "Settings successfully updated" msgstr "Definições actualizadas com sucesso" -#: humans/views.py:55 +#: humans/views.py:58 msgid "Please check the invalid fields" msgstr "Por favor, verifique os campos inválidos" -#: humans/views.py:72 +#: humans/views.py:75 msgid "Account deleted successfully. We hope you comeback soon." msgstr "Conta apagada com sucesso. Esperemos que regresse em breve." -#: humans/views.py:77 +#: humans/views.py:80 msgid "In order to delete the account you must provide the current password." msgstr "De modo a apagar a conta, deve inserir a password actual." @@ -1717,6 +1738,11 @@ msgstr "" msgid "Ready to start?" msgstr "Vamos começar?" +#, fuzzy +#~| msgid "change password" +#~ msgid "Old password" +#~ msgstr "mudar password" + #~ msgid "The message must be encrypted before the server forwards it" #~ msgstr "A mensagem deve ser encriptada antes do servidor a enviar"