from django.conf import settings from django.shortcuts import get_object_or_404 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=not settings.DEBUG) 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=not settings.DEBUG) 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) class SetPortofolioRequiredInfoAPIView(APIView): def get(self, request): custom_url = request.GET.get('custom_url', None) if not custom_url: return Response({"message": "no url"}, status=status.HTTP_400_BAD_REQUEST) if User.objects.filter(custom_url=custom_url).exists(): return Response({"message": "already used url"}, status=status.HTTP_400_BAD_REQUEST) else: return Response({"message": "can use this url"}, status=status.HTTP_200_OK) def patch(self, request): user = request.user serializer = SetPortofolioRequiredInfoSerializer(user, data=request.data) if serializer.is_valid(): serializer.save() user.is_custom_url = True user.save() return Response({"message": "updated successfully"}, status=status.HTTP_202_ACCEPTED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)