mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-18 05:51:26 +02:00
New endpoint to update self account password
This commit is contained in:
@@ -292,39 +292,6 @@ class AccountExistsSerializer(serializers.Serializer):
|
||||
exists = serializers.BooleanField()
|
||||
|
||||
|
||||
class AccountPasswordSerializer(serializers.ModelSerializer):
|
||||
"""A serializer used to change a user password."""
|
||||
|
||||
new_password = serializers.CharField()
|
||||
|
||||
class Meta:
|
||||
model = core_models.User
|
||||
fields = (
|
||||
"password",
|
||||
"new_password",
|
||||
)
|
||||
|
||||
def validate_password(self, value):
|
||||
"""Check password."""
|
||||
if not self.instance.check_password(value):
|
||||
raise serializers.ValidationError("Password not correct")
|
||||
return value
|
||||
|
||||
def validate_new_password(self, value):
|
||||
"""Check new password."""
|
||||
try:
|
||||
password_validation.validate_password(value, self.instance)
|
||||
except ValidationError as exc:
|
||||
raise serializers.ValidationError(exc.messages[0]) from None
|
||||
return value
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
"""Set new password."""
|
||||
instance.set_password(validated_data["new_password"])
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
|
||||
class WritableAccountSerializer(AccountSerializer):
|
||||
"""Serializer to create account."""
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ from rest_framework.response import Response
|
||||
|
||||
from modoboa.core import models as core_models
|
||||
from modoboa.core import sms_backends
|
||||
from modoboa.core.api.v1 import serializers as core_serializers
|
||||
from modoboa.lib import renderers as lib_renderers
|
||||
from modoboa.lib import viewsets as lib_viewsets
|
||||
from modoboa.lib.throttle import GetThrottleViewsetMixin, PasswordResetRequestThrottle
|
||||
@@ -112,7 +113,7 @@ class AccountViewSet(
|
||||
action_dict = {
|
||||
"list": serializers.AccountSerializer,
|
||||
"retrieve": serializers.AccountSerializer,
|
||||
"password": serializers.AccountPasswordSerializer,
|
||||
"password": core_serializers.AccountPasswordSerializer,
|
||||
"reset_password": serializers.ResetPasswordSerializer,
|
||||
}
|
||||
return action_dict.get(self.action, serializers.WritableAccountSerializer)
|
||||
|
||||
@@ -331,6 +331,16 @@ class AccountViewSetTestCase(ModoAPITestCase):
|
||||
resp = self.client.patch(url, data, format="json")
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
|
||||
def test_user_updates_password(self):
|
||||
account = core_models.User.objects.get(username="user@test.com")
|
||||
self.authenticate_user(account)
|
||||
response = self.client.post(
|
||||
reverse("v2:account-set-me-password"),
|
||||
{"password": "toto", "new_password": "Toto1234"},
|
||||
format="json",
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_rename(self):
|
||||
account = core_models.User.objects.get(username="user@test.com")
|
||||
url = reverse("v2:account-detail", args=[account.pk])
|
||||
|
||||
@@ -2,14 +2,51 @@
|
||||
|
||||
import logging
|
||||
|
||||
from django.contrib.auth import password_validation
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.html import escape
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from modoboa.core import models
|
||||
|
||||
logger = logging.getLogger("modoboa.auth")
|
||||
|
||||
|
||||
class AccountPasswordSerializer(serializers.ModelSerializer):
|
||||
"""A serializer used to change a user password."""
|
||||
|
||||
new_password = serializers.CharField()
|
||||
|
||||
class Meta:
|
||||
model = models.User
|
||||
fields = (
|
||||
"password",
|
||||
"new_password",
|
||||
)
|
||||
|
||||
def validate_password(self, value):
|
||||
"""Check password."""
|
||||
if not self.instance.check_password(value):
|
||||
raise serializers.ValidationError("Password not correct")
|
||||
return value
|
||||
|
||||
def validate_new_password(self, value):
|
||||
"""Check new password."""
|
||||
try:
|
||||
password_validation.validate_password(value, self.instance)
|
||||
except ValidationError as exc:
|
||||
raise serializers.ValidationError(exc.messages[0]) from None
|
||||
return value
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
"""Set new password."""
|
||||
instance.set_password(validated_data["new_password"])
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
|
||||
class CheckTFASetupSerializer(serializers.Serializer):
|
||||
"""Serializer used to finalize 2FA setup."""
|
||||
|
||||
|
||||
@@ -68,6 +68,20 @@ class AccountViewSet(core_v1_viewsets.AccountViewSet):
|
||||
serializer.is_valid(raise_exception=True)
|
||||
return response.Response()
|
||||
|
||||
@action(
|
||||
methods=["post"],
|
||||
detail=False,
|
||||
url_path="me/password/change",
|
||||
serializer_class=core_v1_serializers.AccountPasswordSerializer,
|
||||
)
|
||||
def set_me_password(self, request):
|
||||
serializer = core_v1_serializers.AccountPasswordSerializer(
|
||||
instance=request.user, data=request.data
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
serializer.save()
|
||||
return response.Response()
|
||||
|
||||
@extend_schema(
|
||||
description="Get current API token",
|
||||
responses={200: serializers.UserAPITokenSerializer},
|
||||
|
||||
@@ -160,10 +160,9 @@ class ProfileTestCase(LDAPTestCaseMixin, ModoAPITestCase):
|
||||
|
||||
username = "testuser@example.com"
|
||||
self.authenticate(username, "test")
|
||||
account = models.User.objects.get(username=username)
|
||||
response = self.client.put(
|
||||
reverse("v2:account-password", args=[account.id]),
|
||||
{"password": "test", "newpassword": "Toto1234"},
|
||||
response = self.client.post(
|
||||
reverse("v2:account-set-me-password"),
|
||||
{"password": "test", "new_password": "Toto1234"},
|
||||
format="json",
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
Reference in New Issue
Block a user