Repository: modoboa/modoboa (language: python)

Issue:
A user can change its password without specifying the current one
It should not be allowed.

# Impacted versions

* Modoboa: 2.0.4



Discussion / hints:

Fix patch:
diff --git a/modoboa/core/forms.py b/modoboa/core/forms.py
index b5d107658..b98e53175 100644
--- a/modoboa/core/forms.py
+++ b/modoboa/core/forms.py
@@ -59,7 +59,7 @@ class Meta(object):
         }
 
     def __init__(self, update_password, *args, **kwargs):
-        super(ProfileForm, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
         if not update_password:
             del self.fields["oldpassword"]
             del self.fields["newpassword"]
@@ -76,18 +76,26 @@ def clean_oldpassword(self):
             raise forms.ValidationError(_("Old password mismatchs"))
         return self.cleaned_data["oldpassword"]
 
-    def clean_confirmation(self):
-        newpassword = self.cleaned_data["newpassword"]
-        confirmation = self.cleaned_data["confirmation"]
-        if not newpassword and not confirmation:
-            return confirmation
-        if newpassword != confirmation:
-            raise forms.ValidationError(_("Passwords mismatch"))
-        password_validation.validate_password(confirmation, self.instance)
-        return confirmation
+    def clean(self):
+        super().clean()
+        if self.errors:
+            return self.cleaned_data
+        oldpassword = self.cleaned_data.get("oldpassword")
+        newpassword = self.cleaned_data.get("newpassword")
+        confirmation = self.cleaned_data.get("confirmation")
+        if newpassword and confirmation:
+            if oldpassword:
+                if newpassword != confirmation:
+                    self.add_error("confirmation", _("Passwords mismatch"))
+                else:
+                    password_validation.validate_password(
+                        confirmation, self.instance)
+            else:
+                self.add_error("oldpassword", _("This field is required."))
+        return self.cleaned_data
 
     def save(self, commit=True):
-        user = super(ProfileForm, self).save(commit=False)
+        user = super().save(commit=False)
         if commit:
             if self.cleaned_data.get("confirmation", "") != "":
                 user.set_password(


Test patch:
diff --git a/modoboa/core/tests/test_core.py b/modoboa/core/tests/test_core.py
index 5585d2644..b0b476bc2 100644
--- a/modoboa/core/tests/test_core.py
+++ b/modoboa/core/tests/test_core.py
@@ -154,6 +154,19 @@ def test_update_password(self):
             self.client.login(username="user@test.com", password="Toto1234")
         )
 
+    def test_update_password_restrictions(self):
+        self.ajax_post(
+            reverse("core:user_profile"),
+            {"language": "en", "oldpassword": "",
+             "newpassword": "12345Toi", "confirmation": "12345Toi"},
+            status=400
+        )
+        self.client.logout()
+
+        self.assertEqual(
+            self.client.login(username="admin", password="12345Toi"), False
+        )
+
     def test_update_password_url(self):
         """Check if external is used when defined."""
         self.set_global_parameter(