diff --git a/users/views.py b/users/views.py index 91ea44a..68efe8a 100644 --- a/users/views.py +++ b/users/views.py @@ -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) + \ No newline at end of file