From cddefe5de4237f25e4752e9e782253a54637edbb Mon Sep 17 00:00:00 2001 From: jhynsoo Date: Tue, 31 Oct 2023 14:25:16 +0900 Subject: [PATCH] feat: Add password change feature --- market/models.py | 4 +++- user/serializers.py | 13 ++++++++++++- user/viewsets.py | 31 +++++++++++++++++++++++++++---- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/market/models.py b/market/models.py index fad9066..c3e2ff6 100644 --- a/market/models.py +++ b/market/models.py @@ -35,7 +35,9 @@ class Post(models.Model): ) price = models.IntegerField() text = models.TextField() - author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True) + author = models.ForeignKey( + User, on_delete=models.SET_NULL, null=True, related_name="posts" + ) status = models.CharField( max_length=1, choices=STATUS_CHOICES, default="s" ) diff --git a/user/serializers.py b/user/serializers.py index 297d215..7825d58 100644 --- a/user/serializers.py +++ b/user/serializers.py @@ -1,4 +1,6 @@ -from rest_framework.serializers import ModelSerializer +from rest_framework.serializers import ModelSerializer, Serializer +from rest_framework import serializers +from django.contrib.auth import password_validation from .models import User @@ -32,3 +34,12 @@ class UserCreateSerializer(ModelSerializer): nickname=validated_data["nickname"], ) return user + + +class PasswordSerializer(Serializer): + oldPassword = serializers.CharField(required=True) + newPassword = serializers.CharField(required=True) + + def validate_newPassword(self, value): + password_validation.validate_password(value) + return value diff --git a/user/viewsets.py b/user/viewsets.py index 166cac6..2eef9ac 100644 --- a/user/viewsets.py +++ b/user/viewsets.py @@ -9,7 +9,11 @@ from core.mixins import ActionBasedMixin from market.serializers import PostSerializer from .models import User -from .serializers import UserSerializer, UserCreateSerializer +from .serializers import ( + UserSerializer, + UserCreateSerializer, + PasswordSerializer, +) class UserViewset(ActionBasedMixin, ModelViewSet): @@ -18,6 +22,7 @@ class UserViewset(ActionBasedMixin, ModelViewSet): serializer_class_map = { "create": UserCreateSerializer, "posts": PostSerializer, + "password": PasswordSerializer, } permission_classes = [IsAdminUser] permission_classes_map = { @@ -26,11 +31,12 @@ class UserViewset(ActionBasedMixin, ModelViewSet): "logout": [IsAuthenticated], "me": [IsAuthenticated], "posts": [IsAuthenticated], + "password": [IsAuthenticated], } - @action(detail=True, methods=["GET"]) - def posts(self, request, pk): - user = self.get_object() + @action(detail=False, methods=["GET"]) + def posts(self, request): + user = request.user queryset = user.posts.all() page = self.paginate_queryset(queryset) @@ -41,6 +47,23 @@ class UserViewset(ActionBasedMixin, ModelViewSet): serializer = self.get_serializer(queryset, many=True) return Response(serializer.data) + @action(detail=False, methods=["PATCH"]) + def password(self, request): + user = request.user + if user.is_anonymous: + return Response(status=401) + oldPassword = request.data["oldPassword"] + newPassword = request.data["newPassword"] + if not user.check_password(oldPassword): + return Response(status=400, data={"msg": "현재 비밀번호가 일치하지 않습니다"}) + serializer = self.get_serializer(data=request.data) + if not serializer.is_valid(): + msg = " ".join(serializer.errors["newPassword"]) + return Response(status=400, data={"msg": msg}) + user.set_password(newPassword) + user.save() + return Response(status=204) + def create(self, request, *args, **kwargs): serializer = UserCreateSerializer(data=request.data) serializer.is_valid(raise_exception=True)