From cabe5fd1a70cb32850189907e47f190f3e3008a8 Mon Sep 17 00:00:00 2001 From: yjoonjang Date: Sun, 31 Mar 2024 20:50:33 +0900 Subject: [PATCH 1/3] =?UTF-8?q?fix:=20api=20schema=20view=20=EB=94=94?= =?UTF-8?q?=ED=85=8C=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- accounts/serializers.py | 7 ++-- accounts/views.py | 89 +++++++++++++++++++---------------------- 2 files changed, 45 insertions(+), 51 deletions(-) diff --git a/accounts/serializers.py b/accounts/serializers.py index 228b7ec..f2aac45 100644 --- a/accounts/serializers.py +++ b/accounts/serializers.py @@ -19,10 +19,9 @@ def custom_signup(self, request, user): user.save() -class UserLoginSerializer(serializers.ModelSerializer): - class Meta: - model = User - fields = ("username", "email") +class KakaoTokenSerializer(serializers.Serializer): + access_token = serializers.CharField() + code = serializers.CharField() class UserInfoUpdateSerializer(serializers.ModelSerializer): diff --git a/accounts/views.py b/accounts/views.py index 26c8df0..c319ec8 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -3,7 +3,7 @@ import environ from pathlib import Path from django.db import transaction -from drf_spectacular.utils import extend_schema, OpenApiResponse, OpenApiExample +from drf_spectacular.utils import extend_schema, OpenApiResponse, OpenApiExample, OpenApiParameter from django.http import JsonResponse import requests @@ -19,7 +19,7 @@ from dj_rest_auth.registration.views import SocialLoginView from allauth.socialaccount.providers.kakao import views as kakao_view from .models import CustomUser -from .serializers import UserInfoUpdateSerializer, GetUserInfoSerializer +from .serializers import UserInfoUpdateSerializer, GetUserInfoSerializer, KakaoTokenSerializer import logging logger = logging.getLogger(__name__) @@ -41,59 +41,41 @@ @extend_schema( summary="카카오 로그인", - description="카카오 로그인 페이지로 리다이렉트합니다.", + description="카카오 로그인 페이지로 리다이렉트하여, 정보를 입력하면 카카오 **access_token, code**를 반환합니다.", responses={ - 302: OpenApiResponse( - description="Redirects to the Kakao login page.", response=None - ) - }, + 200: KakaoTokenSerializer + } ) @api_view(["GET"]) @permission_classes([AllowAny]) -def kakao_login(request): - print("hi") +def kakao_login(): return redirect( f"https://kauth.kakao.com/oauth/authorize?client_id={REST_API_KEY}&redirect_uri={KAKAO_CALLBACK_URI}&response_type=code" ) - -# @extend_schema(exclude=True) -# @permission_classes([AllowAny]) -# def finish_login(data): -# accept = requests.post(f"{BASE_URL}accounts/kakao/login/finish/", data=data) -# return accept - -# @extend_schema(exclude=True) @permission_classes([AllowAny]) def kakao_callback(request): - logger.warning("kakao callback") code = request.GET.get("code") - logger.warning(f"code: {code}") # Access Token Request token_req = requests.get( f"https://kauth.kakao.com/oauth/token?grant_type=authorization_code&client_id={REST_API_KEY}&client_secret={CLIENT_SECRET}&redirect_uri={KAKAO_CALLBACK_URI}&code={code}" ) - logger.warning(f"token_req: {token_req}") token_req_json = token_req.json() - logger.warning(f"token_req_json: {token_req_json}") error = token_req_json.get("error") if error is not None: raise JSONDecodeError(error) access_token = token_req_json.get("access_token") - logger.warning(f"access_token: {access_token}") # Email Request - profile_request = requests.get( "https://kapi.kakao.com/v2/user/me", headers={"Authorization": f"Bearer {access_token}"}, ) profile_data = profile_request.json() - logger.warning(f"profile_data: {profile_data}") kakao_oid = profile_data.get("id") kakao_account = profile_data.get("kakao_account") @@ -101,10 +83,7 @@ def kakao_callback(request): profile_image_url = kakao_account["profile"]["profile_image_url"] email = kakao_account.get("email") - # 회원가입, 로그인 로직 - data = {"access_token": access_token, "code": code} - logger.warning(f"data: {data}") # TODO 유저 프로필 이미지 저장하도록 return JsonResponse(data) @@ -159,27 +138,43 @@ def kakao_callback(request): # @extend_schema(exclude=True) @extend_schema( summary="카카오 로그인 마무리", - description="access token, code를 post 요청으로 보내면 access token, 유저 정보를 반환합니다.", - # responses={ - # 200: OpenApiResponse( - # description="Redirects to the Kakao login page.", response=None - # ) - # }, + description="access token, code를 post 요청으로 보내면 access token, 유저 정보를 반환합니다. **(id_token은 불필요합니다.)**", + parameters=[ + OpenApiParameter( + name="access_token", + type=str, + description="발급받은 카카오의 access_token 입니다." + ), + OpenApiParameter( + name="code", + type=str, + description="발급받은 카카오의 code 입니다." + ) + ], + request={ + "application/json": { + "type": "object", + "properties": { + "access_token": {"type": "string"}, + "code": {"type": "string"} + }, + }, + }, examples=[ - OpenApiExample( - response_only=True, - summary="Response Body Example입니다.", - name="success_example", - value={ - "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlI", - "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBl", - "user": { - "pk": 6, - "email": "yjoonjang@naver.com" - } - }, - ), - ], + OpenApiExample( + response_only=True, + summary="Response Body Example입니다.", + name="success_example", + value={ + "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlI", + "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBl", + "user": { + "pk": 6, + "email": "yjoonjang@naver.com" + } + }, + ), + ] ) class KakaoLoginView(SocialLoginView): adapter_class = kakao_view.KakaoOAuth2Adapter From 2f272616493c2cba6cff11eece835e2d1f7f93a9 Mon Sep 17 00:00:00 2001 From: yjoonjang Date: Sun, 31 Mar 2024 20:50:53 +0900 Subject: [PATCH 2/3] =?UTF-8?q?reformat:=20black=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EB=A6=AC=ED=8F=AC=EB=A7=A4=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- accounts/views.py | 38 ++++++++++++++++++++------------------ resumai/middleware.py | 7 ++++--- resumai/settings/base.py | 3 --- resumai/settings/prod.py | 6 +++--- resumai/urls.py | 4 +++- 5 files changed, 30 insertions(+), 28 deletions(-) diff --git a/accounts/views.py b/accounts/views.py index c319ec8..9050e93 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -3,7 +3,12 @@ import environ from pathlib import Path from django.db import transaction -from drf_spectacular.utils import extend_schema, OpenApiResponse, OpenApiExample, OpenApiParameter +from drf_spectacular.utils import ( + extend_schema, + OpenApiResponse, + OpenApiExample, + OpenApiParameter, +) from django.http import JsonResponse import requests @@ -19,7 +24,11 @@ from dj_rest_auth.registration.views import SocialLoginView from allauth.socialaccount.providers.kakao import views as kakao_view from .models import CustomUser -from .serializers import UserInfoUpdateSerializer, GetUserInfoSerializer, KakaoTokenSerializer +from .serializers import ( + UserInfoUpdateSerializer, + GetUserInfoSerializer, + KakaoTokenSerializer, +) import logging logger = logging.getLogger(__name__) @@ -42,9 +51,7 @@ @extend_schema( summary="카카오 로그인", description="카카오 로그인 페이지로 리다이렉트하여, 정보를 입력하면 카카오 **access_token, code**를 반환합니다.", - responses={ - 200: KakaoTokenSerializer - } + responses={200: KakaoTokenSerializer}, ) @api_view(["GET"]) @permission_classes([AllowAny]) @@ -53,6 +60,7 @@ def kakao_login(): f"https://kauth.kakao.com/oauth/authorize?client_id={REST_API_KEY}&redirect_uri={KAKAO_CALLBACK_URI}&response_type=code" ) + @permission_classes([AllowAny]) def kakao_callback(request): code = request.GET.get("code") @@ -135,6 +143,7 @@ def kakao_callback(request): # accept_json["userProfile"]["id"] = accept_json["userProfile"].pop("pk") # return JsonResponse(accept_json) + # @extend_schema(exclude=True) @extend_schema( summary="카카오 로그인 마무리", @@ -143,20 +152,18 @@ def kakao_callback(request): OpenApiParameter( name="access_token", type=str, - description="발급받은 카카오의 access_token 입니다." + description="발급받은 카카오의 access_token 입니다.", ), OpenApiParameter( - name="code", - type=str, - description="발급받은 카카오의 code 입니다." - ) + name="code", type=str, description="발급받은 카카오의 code 입니다." + ), ], request={ "application/json": { "type": "object", "properties": { "access_token": {"type": "string"}, - "code": {"type": "string"} + "code": {"type": "string"}, }, }, }, @@ -168,13 +175,10 @@ def kakao_callback(request): value={ "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlI", "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBl", - "user": { - "pk": 6, - "email": "yjoonjang@naver.com" - } + "user": {"pk": 6, "email": "yjoonjang@naver.com"}, }, ), - ] + ], ) class KakaoLoginView(SocialLoginView): adapter_class = kakao_view.KakaoOAuth2Adapter @@ -182,7 +186,6 @@ class KakaoLoginView(SocialLoginView): callback_url = KAKAO_CALLBACK_URI - class UpdateUserInfoView(APIView): permission_classes = [IsAuthenticated] # 인증된 사용자만 접근 가능하도록 설정 @@ -214,4 +217,3 @@ def get(self, request): user = request.user serializer = GetUserInfoSerializer(user) return Response(serializer.data) - diff --git a/resumai/middleware.py b/resumai/middleware.py index df7354d..001a021 100644 --- a/resumai/middleware.py +++ b/resumai/middleware.py @@ -1,10 +1,11 @@ from django.http import HttpResponse + class HealthCheckMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): - if request.path == '/health': - return HttpResponse('ok') - return self.get_response(request) \ No newline at end of file + if request.path == "/health": + return HttpResponse("ok") + return self.get_response(request) diff --git a/resumai/settings/base.py b/resumai/settings/base.py index 7c025ed..2f8859d 100644 --- a/resumai/settings/base.py +++ b/resumai/settings/base.py @@ -201,6 +201,3 @@ "version": 1, # the dictConfig format version "disable_existing_loggers": False, # retain the default loggers } - - - diff --git a/resumai/settings/prod.py b/resumai/settings/prod.py index 0cea8df..ba14073 100644 --- a/resumai/settings/prod.py +++ b/resumai/settings/prod.py @@ -22,9 +22,9 @@ SECURE_HSTS_SECONDS = 31536000 # SECURE_SSL_REDIRECT = True -CSRF_TRUSTED_ORIGINS=['https://*.resumai.kr'] +CSRF_TRUSTED_ORIGINS = ["https://*.resumai.kr"] CSRF_COOKIE_SECURE = True SESSION_COOKIE_SECURE = True -SECURE_HSTS_PRELOAD=True +SECURE_HSTS_PRELOAD = True # SECURE_HSTS_INCLUDE_SUBDOMAINS=True -SESSION_COOKIE_SECURE=True +SESSION_COOKIE_SECURE = True diff --git a/resumai/urls.py b/resumai/urls.py index e55954f..c9ae0f3 100644 --- a/resumai/urls.py +++ b/resumai/urls.py @@ -23,14 +23,16 @@ permission_classes=[permissions.AllowAny], ) + def preprocessing_filter_spec(endpoints): filtered = [] for path, path_regex, method, callback in endpoints: # Remove all but DRF API endpoints - if (not path.startswith("/registration/")): + if not path.startswith("/registration/"): filtered.append((path, path_regex, method, callback)) return filtered + urlpatterns = [ path("", kakao_login_page, name="home"), path("admin/", admin.site.urls), From 0c015e6ea1e95a3dc94d62367687b3c304847fe1 Mon Sep 17 00:00:00 2001 From: yjoonjang Date: Sun, 31 Mar 2024 20:51:42 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20allowed=5Fhosts=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resumai/settings/base.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/resumai/settings/base.py b/resumai/settings/base.py index 2f8859d..83974ee 100644 --- a/resumai/settings/base.py +++ b/resumai/settings/base.py @@ -21,8 +21,7 @@ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = f"{os.environ.get('DJANGO_SECURE_KEY')}" -# ALLOWED_HOSTS = ["127.0.0.1", "api.resumai.kr", "resumai.kr"] -ALLOWED_HOSTS = ["*"] +ALLOWED_HOSTS = ["127.0.0.1", "*.resumai.kr", "resumai.kr", "localhost:3000"] # Application definition