From 1f7fe5203c9d7531ba5ff007e2f2d9eaea0b9477 Mon Sep 17 00:00:00 2001 From: sm4640 Date: Mon, 12 May 2025 12:01:42 +0900 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Feat:=20[#50]=20=EC=86=8C=EC=85=9C?= =?UTF-8?q?=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- users/views.py | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/users/views.py b/users/views.py index d51fbe5..f8e557e 100644 --- a/users/views.py +++ b/users/views.py @@ -24,6 +24,9 @@ from portfolios.serializers import * from django.db import transaction +from google.oauth2 import id_token +from google.auth.transport import requests + class RefreshAPIView(APIView): permission_classes = [AllowAny] @@ -44,6 +47,65 @@ class RefreshAPIView(APIView): except TokenError as e: return Response({"message": f"Invalid token: {e}"}, status=status.HTTP_401_UNAUTHORIZED) +class GoogleLoginAPIView(APIView): + permission_classes = [AllowAny] + + @transaction.atomic + def post(self, request): + token_str = request.data.get("id_token") + if not token_str: + return Response({"message": "no id_token"}, status=status.HTTP_400_BAD_REQUEST) + + try: + idinfo = id_token.verify_oauth2_token( + token_str, + requests.Request(), + settings.GOOGLE_CLIENT_ID + ) + except ValueError: + return Response({"message": "wrong id_token"}, status=status.HTTP_400_BAD_REQUEST) + + email = idinfo["email"] + # sub = idinfo["sub"] # Google 고유 ID + + # 이미 소셜 회원가입을 한 경우, 로그인 기능. + if user := User.objects.filter(email=email).first(): + # 로그인 전 쿠키에 있는 리프레시 토큰 무효화 + try: + refresh = request.COOKIES.get('refresh') + if refresh: + refresh_token = RefreshToken(refresh) + refresh_token.blacklist() + except TokenError as e: + pass # 어차피 만료된거면 그냥 넘어가기 + + refresh = RefreshToken.for_user(user) + access = str(refresh.access_token) + + res = Response( + { + "message": "login success", + "user_id": user.id, + "nickname": user.nickname, + "access": access, + "is_member": True, + "is_custom_url": user.is_custom_url + }, + status=status.HTTP_200_OK, + ) + res.set_cookie("refresh", str(refresh), httponly=True, samesite=None, secure=not settings.DEBUG) + return res + else: + return Response( + { + "message": "Not member", + "email": email, + "is_member": False + }, + status=status.HTTP_200_OK + ) + + class JoinAPIView(APIView):