Skip to content

Commit

Permalink
Merge pull request #22 from Django-Wanted-Internship-3-Team/feature/i…
Browse files Browse the repository at this point in the history
…ssue-007

유저 가입 승인 api 작성
  • Loading branch information
lfoyh6591 authored Oct 30, 2023
2 parents d4ad866 + b83ca0b commit bd16fba
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 12 deletions.
39 changes: 39 additions & 0 deletions users/serializers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import random
import string

from django.contrib.auth import get_user_model, password_validation
from rest_framework import serializers

from users.models import UserConfirmCode


class UserSerializer(serializers.ModelSerializer):
class Meta:
Expand All @@ -15,3 +20,37 @@ def validate_password(self, data):
def create(self, validated_data):
user = get_user_model().objects.create_user(validated_data["email"], validated_data["username"], validated_data["password"])
return user


class UserConfirmCodeSerializer(UserSerializer):
def create(self, validated_data):
user = super().create(validated_data)

confirm_code = "".join(random.choice(string.ascii_letters + string.digits) for i in range(6))
user_confirm_code = UserConfirmCode.objects.create(code=confirm_code, user=user)
return user_confirm_code


class UserConfirmSerializer(serializers.Serializer):
username = serializers.CharField(max_length=128)
password = serializers.CharField(max_length=128, write_only=True)
code = serializers.CharField(max_length=32)

def validate(self, data):
user = self.instance
if not user.check_password(data["password"]):
raise serializers.ValidationError("Password is incorrect")

if user.is_confirmed:
raise serializers.ValidationError("User is already confirmed")

confirm_code = UserConfirmCode.objects.get(user=user).code
if confirm_code != data["code"]:
raise serializers.ValidationError("Confirmation code is incorrect")

return data

def update(self, user, validated_data):
user.is_confirmed = True
user.save()
return user
93 changes: 93 additions & 0 deletions users/tests/views/test_confirm_user_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import json

from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase

from users.models import User, UserConfirmCode


class SignupViewTest(APITestCase):
@classmethod
def setUpTestData(cls):
cls.user = User.objects.create_user(
email="testuser1@example.com",
username="testusername1",
password="testpassword",
)

cls.userconfirmcode = UserConfirmCode.objects.create(
code="abcdef",
user=cls.user,
)

def test_post_signup_success(self):
response = self.client.post(
path=reverse("confirm"),
data=json.dumps(
{
"username": "testusername1",
"password": "testpassword",
"code": "abcdef",
}
),
content_type="application/json",
)
self.assertEqual(response.status_code, status.HTTP_200_OK)

def test_post_signup_fail_user_not_found(self):
response = self.client.post(
path=reverse("confirm"),
data=json.dumps(
{
"username": "testusername2",
"password": "testpassword",
"code": "abcdef",
}
),
content_type="application/json",
)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

def test_post_signup_fail_invalid_password(self):
response = self.client.post(
path=reverse("signup"),
data=json.dumps(
{
"username": "testusername1",
"password": "testpassword2",
"code": "abcdef",
}
),
content_type="application/json",
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

def test_post_signup_fail_invalid_code(self):
response = self.client.post(
path=reverse("signup"),
data=json.dumps(
{
"username": "testusername1",
"password": "testpassword",
"code": "aaaaaa",
}
),
content_type="application/json",
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

def test_post_signup_fail_already_confirmed(self):
self.user.is_confirmed = True
response = self.client.post(
path=reverse("signup"),
data=json.dumps(
{
"username": "testusername1",
"password": "testpassword",
"code": "abcdef",
}
),
content_type="application/json",
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
6 changes: 2 additions & 4 deletions users/urls.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from django.urls import path

from users.views import SignupView
from users.views import ConfirmUserView, SignupView

urlpatterns = [
path("signup/", SignupView.as_view(), name="signup"),
]
urlpatterns = [path("signup/", SignupView.as_view(), name="signup"), path("confirm/", ConfirmUserView.as_view(), name="confirm")]
57 changes: 49 additions & 8 deletions users/views.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,73 @@
from django.contrib.auth import get_user_model
from django.shortcuts import get_object_or_404
from drf_yasg.utils import swagger_auto_schema
from rest_framework import status
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.views import APIView

from users.serializers import UserSerializer
from users.serializers import (
UserConfirmCodeSerializer,
UserConfirmSerializer,
UserSerializer,
)


class SignupView(APIView):
@swagger_auto_schema(
operation_summary="유저 회원가입",
request_body=UserSerializer,
request_body=UserConfirmCodeSerializer,
responses={
status.HTTP_201_CREATED: UserSerializer,
status.HTTP_201_CREATED: UserConfirmCodeSerializer,
},
)
def post(self, request: Request) -> Response:
"""
username, email, paswword를 받아 유저 계정을 생성합니다.
username, email, paswword를 받아 유저 계정과 인증 코드를 생성합니다.
Args:
email: 이메일
username: 이름
password: 비밀번호
Returns:
email: 생성된 계정 이메일
username: 생성된 계정 이름
code: 생성된 인증 코드
"""
serializer = UserSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
user_confirm_code_serializer = UserConfirmCodeSerializer(data=request.data)
user_confirm_code_serializer.is_valid(raise_exception=True)
user_confirm_code = user_confirm_code_serializer.save()

response_data = UserSerializer(user_confirm_code.user).data
response_data["confirm_code"] = user_confirm_code.code
return Response(response_data, status=status.HTTP_201_CREATED)


class ConfirmUserView(APIView):
@swagger_auto_schema(
operation_summary="유저 가입 승인",
request_body=UserConfirmSerializer,
responses={
status.HTTP_200_OK: UserConfirmSerializer,
},
)
def post(self, request: Request) -> Response:
"""
username, paswword, code를 받아 code가 user의 인증코드와 같을 경우 회원가입을 승인합니다.
Args:
username: 이름
password: 비밀번호
code: 인증 코드
Returns:
username: 이름
is_confirmed: 인증 여부
"""
user = get_object_or_404(get_user_model(), username=request.data["username"])
user_confirm_serializer = UserConfirmSerializer(user, data=request.data)
user_confirm_serializer.is_valid(raise_exception=True)
user_confirm_serializer.save()

response_data = {}
response_data["username"] = user.username
response_data["is_confirmed"] = user.is_confirmed

return Response(response_data, status=status.HTTP_200_OK)

0 comments on commit bd16fba

Please sign in to comment.