Feat: [#13] 회원가입, 로그인, 토큰 재발급, 닉네임 중복체크 로직 구현

This commit is contained in:
sm4640
2025-04-08 01:05:05 +09:00
parent 65d0c10889
commit a6225db2b2

View File

@@ -1,3 +1,97 @@
from django.shortcuts import render from django.shortcuts import get_object_or_404
# Create your views here. from rest_framework.views import APIView
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer, TokenRefreshSerializer
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework_simplejwt.exceptions import TokenError, InvalidToken
from rest_framework import status
from rest_framework.response import Response
from rest_framework.permissions import AllowAny, IsAuthenticated
from django.contrib.auth import authenticate
from .models import *
from .serializers import *
class RefreshAPIView(APIView):
permission_classes = [AllowAny]
# access token 재발급
def post(self, request):
refresh = request.COOKIES.get("refresh")
if not refresh:
return Response({"message": "No refresh token"}, status=status.HTTP_400_BAD_REQUEST)
if request.data.get("user_id", None) != RefreshToken(refresh).payload.get("user_id", None):
return Response({"message": "Wrong userid"}, status=status.HTTP_400_BAD_REQUEST)
try:
serializer = TokenRefreshSerializer(data={'refresh': refresh})
if serializer.is_valid():
res = Response({"access": serializer.validated_data['access']}, status=status.HTTP_200_OK)
res.set_cookie("refresh", serializer.validated_data['refresh'], httponly=True, samesite="Lax", secure=True)
return res
except TokenError as e:
return Response({"message": f"Invalid token: {e}"}, status=status.HTTP_401_UNAUTHORIZED)
class JoinAPIView(APIView):
permission_classes = [AllowAny]
# 회원가입
def post(self, request):
serializer = JoinSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
res = Response({"message": "회원가입이 완료되었습니다."}, status=status.HTTP_200_OK)
return res
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class LoginAPIView(APIView):
permission_classes = [AllowAny]
# 로그인
def post(self, request):
email=request.data.get("email", None)
password=request.data.get("password", None)
# 로그인 전 쿠키에 있는 리프레시 토큰 무효화
try:
refresh = request.COOKIES.get('refresh')
if refresh:
refresh_token = RefreshToken(refresh)
refresh_token.blacklist()
except TokenError as e:
pass
if user := authenticate(email=email, password=password):
serializer = TokenObtainPairSerializer(data={'email': email, 'password': password})
# id, 비번 맞나 틀리나 검사
if serializer.is_valid():
res = Response(
{
"message": "login success",
"user_id": user.id,
"nickname": user.nickname,
"access": serializer.validated_data['access'],
"is_custom_url": user.is_custom_url
},
status=status.HTTP_200_OK,
)
res.set_cookie("refresh", serializer.validated_data['refresh'], httponly=True, samesite="Lax", secure=True)
return res
else:
return Response(serializer.errors)
else: # id, 비번 둘 중 하나가 틀렸을 때
return Response({"message": "아이디 혹은 비밀번호가 맞지 않습니다."}, status=status.HTTP_400_BAD_REQUEST)
class NicknameAPIView(APIView):
permission_classes = [AllowAny]
# 닉네임 중복 체크
def get(self, request):
nickname = request.GET.get('nickname', None)
if not nickname:
return Response({"message": "닉네임을 입력하세요."}, status=status.HTTP_400_BAD_REQUEST)
try:
get_object_or_404(User, nickname=nickname)
return Response({"message": "해당 닉네임은 사용할 수 없습니다."}, status=status.HTTP_400_BAD_REQUEST)
except:
return Response({"message": "사용할 수 있는 닉네임입니다."}, status=status.HTTP_200_OK)