diff --git a/alaltalk/asgi.py b/alaltalk/asgi.py index e37bf36..e05f8c0 100644 --- a/alaltalk/asgi.py +++ b/alaltalk/asgi.py @@ -14,16 +14,18 @@ from channels.sessions import SessionMiddlewareStack from django.core.asgi import get_asgi_application -import apps.chat.routing +# import apps.chat.routing os.environ.setdefault("DJANGO_SETTINGS_MODULE", "alaltalk.settings.dev") # chat.router를 root router로 설정 -application = ProtocolTypeRouter( - { - "http": get_asgi_application(), - "websocket": SessionMiddlewareStack( - URLRouter(apps.chat.routing.websocket_urlpatterns) - ), - } -) +# application = ProtocolTypeRouter( +# { +# "http": get_asgi_application(), +# "websocket": SessionMiddlewareStack( +# URLRouter(apps.chat.routing.websocket_urlpatterns) +# ), +# } +# ) + +application = get_asgi_application() diff --git a/alaltalk/settings/base.py b/alaltalk/settings/base.py index 345463c..ddc346b 100644 --- a/alaltalk/settings/base.py +++ b/alaltalk/settings/base.py @@ -31,7 +31,7 @@ INSTALLED_APPS = [ # "apps.chat", - "channels", + # "channels", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", diff --git a/alaltalk/urls.py b/alaltalk/urls.py index d6bcae6..6487514 100644 --- a/alaltalk/urls.py +++ b/alaltalk/urls.py @@ -38,7 +38,8 @@ urlpatterns = [ path("admin/", admin.site.urls), path("", landing_home, name="landing_page"), - path("account/", include("apps.account.urls")) + path("account/", include("apps.account.urls")), + path("friend/", include("apps.friend.urls")) # path("accounts/", include("accounts.urls")), # path("chat/", include("chat.urls")), # path("api/", api.urls), diff --git a/apps/friend/urls.py b/apps/friend/urls.py new file mode 100644 index 0000000..9fbebff --- /dev/null +++ b/apps/friend/urls.py @@ -0,0 +1,7 @@ +from django.urls import include, path + +app_name = "friend" + +urlpatterns = [ + path("v1/", include("apps.friend.v1.urls", namespace="v1")), +] diff --git a/apps/friend/v1/apis/friend_request_api.py b/apps/friend/v1/apis/friend_request_api.py index 2ef50cb..7cd9cbf 100644 --- a/apps/friend/v1/apis/friend_request_api.py +++ b/apps/friend/v1/apis/friend_request_api.py @@ -17,8 +17,8 @@ class FriendRequestViewSet(viewsets.ModelViewSet): def create(self, request, *args, **kwargs): """친구 요청을 전송합니다.""" - user_id = request.data.get("user_id") - target_user_id = request.data.get("target_user_id") + user_id = request.data.get("user") + target_user_id = request.data.get("target_user") try: friend_request = FriendService.send_friend_request( @@ -31,26 +31,26 @@ def create(self, request, *args, **kwargs): data = {"msg": "already"} return Response(data=data, status=status.HTTP_400_BAD_REQUEST) - def retrieve(self, request, pk: int): + def retrieve(self, request, *args, **kwargs): """친구 요청을 승낙합니다.""" - + request_id = self.get_object().id try: friend_request = FriendService.accept_friend_request( - target_user_id=request.user.id, request_id=pk + target_user_id=request.user.id, request_id=request_id ) serializer = self.get_serializer(friend_request) return Response(data=serializer.data, status=status.HTTP_200_OK) - except Exception as exception: + except IntegrityError as exception: raise exception - def destroy(self, request, pk: int): + def destroy(self, request, *args, **kwargs): """친구 요청을 거절합니다.""" - + request_id = self.get_object().id try: FriendService.decline_friend_request( - target_user_id=request.user.id, request_id=pk + target_user_id=request.user.id, request_id=request_id ) - friend_request = FriendRequest.objects.filter(id=pk).get() + friend_request = FriendRequest.objects.filter(id=request_id).get() serializer = self.get_serializer(friend_request) data = {"msg": "declined", "data": serializer.data} except Exception as exception: diff --git a/apps/friend/v1/urls.py b/apps/friend/v1/urls.py index e69de29..0ca7fba 100644 --- a/apps/friend/v1/urls.py +++ b/apps/friend/v1/urls.py @@ -0,0 +1,13 @@ +from django.urls import include, path +from rest_framework.routers import DefaultRouter + +from apps.friend.v1.apis.friend_request_api import FriendRequestViewSet + +app_name = "friend" + +router = DefaultRouter() +router.register("friend_request", FriendRequestViewSet, "friend_request") + +urlpatterns = [ + path("", include(router.urls)), +] diff --git a/tests/conftest.py b/tests/conftest.py index 4b9375b..0d1d0b0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,12 @@ import pytest +from django.urls import reverse +from rest_framework.test import APIClient +from rest_framework_simplejwt.tokens import RefreshToken from alaltalk.settings.base import CELERY_BROKER_URL, CELERY_RESULT_BACKEND +from apps.account.models import CustomUser +from apps.account.utils import random_string_generator +from tests.account.factories import UserFactory @pytest.fixture(scope="session") diff --git a/tests/friend/v1/apis/test_friend_request_api.py b/tests/friend/v1/apis/test_friend_request_api.py new file mode 100644 index 0000000..b282181 --- /dev/null +++ b/tests/friend/v1/apis/test_friend_request_api.py @@ -0,0 +1,128 @@ +from typing import Callable + +import pytest +from django.db import IntegrityError +from django.test import Client +from django.urls import reverse +from django.utils import timezone +from rest_framework import status + +from apps.friend import constants +from apps.friend.models import Friend, FriendRequest +from tests.account.factories import UserFactory +from tests.friend.factories import FriendFactory, FriendRequestFactory +from tests.helpers import authorization_header + +pytestmark = pytest.mark.django_db + + +def test_친구_요청시_유효하지않은_토큰_인증_오류_반환(client: Client): + + token = "invalid_token" + + user, target_user = UserFactory.create_batch(size=2) + + data = {"user": user.id, "target_user": target_user.id} + res = client.post( + reverse("friend:v1:friend_request-list"), + data=data, + content_type="application/json", + **{"HTTP_AUTHORIZATION": f"Bearer {token}"}, + ) + + assert res.status_code == status.HTTP_401_UNAUTHORIZED + + +def test_친구_요청시_sent_메시지_및_데이터_반환(client: Client, mocker: Callable): + + now = timezone.now() + mocker.patch("django.utils.timezone.now", return_value=now) + + user = UserFactory.create(is_active=True) + target_user = UserFactory.create(is_active=True) + + data = {"user": user.id, "target_user": target_user.id} + + res = client.post( + reverse("friend:v1:friend_request-list"), + data=data, + content_type="application/json", + **authorization_header(user), + ) + + assert res.status_code == status.HTTP_201_CREATED + assert res.data["msg"] == "sent" + assert res.data["data"]["user"]["email"] == user.email + assert res.data["data"]["target_user"]["email"] == target_user.email + assert res.data["data"]["status"] == constants.FriendRequestStatus.SENT + assert ( + FriendRequest.objects.filter(user=user, target_user=target_user).exists() + is True + ) + + +def test_친구_요청_중복시_already_메시지_반환(client: Client): + user = UserFactory.create(is_active=True) + target_user = UserFactory.create(is_active=True) + FriendRequestFactory.create(user=user, target_user=target_user) + + data = {"user": user.id, "target_user": target_user.id} + + res = client.post( + reverse("friend:v1:friend_request-list"), + data=data, + content_type="application/json", + **authorization_header(user), + ) + + assert res.status_code == status.HTTP_400_BAD_REQUEST + assert res.data["msg"] == "already" + + +def test_친구_요청_승낙시_status_변경_및_Friend_레코드_생성_확인(client: Client): + user = UserFactory.create(is_active=True) + target_user = UserFactory.create(is_active=True) + friend_request = FriendRequestFactory.create(user=user, target_user=target_user) + + res = client.get( + f"/friend/v1/friend_request/{friend_request.id}/", + **authorization_header(target_user), + ) + + friend = Friend.objects.filter(user=user, target_user=target_user).get() + + assert res.status_code == status.HTTP_200_OK + assert ( + FriendRequest.objects.get(user=user, target_user=target_user).status + == constants.FriendRequestStatus.ACCEPT + ) + assert friend.status == constants.FriendStatus.CONNECTED + + +def test_친구_요청_승낙시_user_및_targetUser_친구_확인(client: Client): + user = UserFactory.create(is_active=True) + target_user = UserFactory.create(is_active=True) + friend_request = FriendRequestFactory.create(user=user, target_user=target_user) + + res = client.get( + f"/friend/v1/friend_request/{friend_request.id}/", + **authorization_header(target_user), + ) + friend = Friend.objects.filter(user=user, target_user=target_user).get() + + assert res.status_code == status.HTTP_200_OK + assert target_user in friend.user.friends.all() + assert user in friend.target_user.friends.all() + + +def test_친구_상태에서_다시_친구_요청_승낙시_IntegrityError_발생(client: Client): + user = UserFactory.create(is_active=True) + target_user = UserFactory.create(is_active=True) + friend_request = FriendRequestFactory.create(user=user, target_user=target_user) + FriendFactory.create(user=user, target_user=target_user) + + with pytest.raises(IntegrityError): + client.get( + f"/friend/v1/friend_request/{friend_request.id}/", + **authorization_header(target_user), + ) diff --git a/tests/helpers.py b/tests/helpers.py new file mode 100644 index 0000000..6db0007 --- /dev/null +++ b/tests/helpers.py @@ -0,0 +1,11 @@ +from rest_framework_simplejwt.tokens import RefreshToken + +from apps.account.models import CustomUser + + +def authorization_header(user: CustomUser): + """ + header 인증 + """ + refresh = RefreshToken.for_user(user=user) + return {"HTTP_AUTHORIZATION": f"Bearer {refresh.access_token}"}