From a461807eddd1de93a2ee0da1588013712567d926 Mon Sep 17 00:00:00 2001 From: jedi Date: Wed, 25 Oct 2023 23:50:19 +0200 Subject: [PATCH] add DELETE endpoints for /friends and /friendrequests --- backend/toolshed/api/friend.py | 27 +++++++++++++++++++++++++-- backend/toolshed/api/inventory.py | 6 ++++-- backend/toolshed/tests/test_friend.py | 22 ++++++++++++++++++++-- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/backend/toolshed/api/friend.py b/backend/toolshed/api/friend.py index 66f8342..efedd80 100644 --- a/backend/toolshed/api/friend.py +++ b/backend/toolshed/api/friend.py @@ -2,7 +2,7 @@ import secrets from django.urls import path from rest_framework import status -from rest_framework.decorators import api_view +from rest_framework.decorators import api_view, authentication_classes, permission_classes from rest_framework.generics import get_object_or_404 from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response @@ -11,7 +11,7 @@ from rest_framework.viewsets import ViewSetMixin from authentication.models import KnownIdentity, FriendRequestIncoming, FriendRequestOutgoing, ToolshedUser from authentication.signature_auth import verify_incoming_friend_request, split_userhandle_or_throw, \ - authenticate_request_against_local_users, SignatureAuthentication + authenticate_request_against_local_users, SignatureAuthenticationLocal, SignatureAuthentication from toolshed.serializers import FriendSerializer, FriendRequestSerializer @@ -120,7 +120,30 @@ class FriendsRequests(APIView, ViewSetMixin): return Response(status=status.HTTP_400_BAD_REQUEST) +@api_view(['DELETE']) +@authentication_classes([SignatureAuthenticationLocal]) +@permission_classes([IsAuthenticated]) +def dropFriend(request, pk, format=None): # /api/friends// + user = request.user + friend = get_object_or_404(user.friends, pk=pk) + user.friends.remove(friend) + user.save() + return Response(status=status.HTTP_204_NO_CONTENT) + + +@api_view(['DELETE']) +@authentication_classes([SignatureAuthenticationLocal]) +@permission_classes([IsAuthenticated]) +def deleteFriendRequest(request, pk, format=None): # /api/friendrequests// + user = request.user + get_object_or_404(user.friend_requests_incoming, pk=pk).delete() + user.save() + return Response(status=status.HTTP_204_NO_CONTENT) + + urlpatterns = [ path('friends/', Friends.as_view(), name='friends'), + path('friends//', dropFriend), path('friendrequests/', FriendsRequests.as_view(), name='friendrequests'), + path('friendrequests//', deleteFriendRequest), ] diff --git a/backend/toolshed/api/inventory.py b/backend/toolshed/api/inventory.py index eb472e9..b60ebee 100644 --- a/backend/toolshed/api/inventory.py +++ b/backend/toolshed/api/inventory.py @@ -5,7 +5,7 @@ from rest_framework.decorators import authentication_classes, api_view, permissi from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response -from authentication.models import ToolshedUser +from authentication.models import ToolshedUser, KnownIdentity from authentication.signature_auth import SignatureAuthentication from toolshed.models import InventoryItem from toolshed.serializers import InventoryItemSerializer @@ -33,7 +33,9 @@ class InventoryItemViewSet(viewsets.ModelViewSet): permission_classes = [IsAuthenticated] def get_queryset(self): - return InventoryItem.objects.filter(owner=self.request.user.user.get()) + if type(self.request.user) == KnownIdentity and self.request.user.user.exists(): + return InventoryItem.objects.filter(owner=self.request.user.user.get()) + return InventoryItem.objects.none() def perform_create(self, serializer): with transaction.atomic(): diff --git a/backend/toolshed/tests/test_friend.py b/backend/toolshed/tests/test_friend.py index f96b2a1..a6da890 100644 --- a/backend/toolshed/tests/test_friend.py +++ b/backend/toolshed/tests/test_friend.py @@ -78,6 +78,12 @@ class FriendApiTestCase(UserTestMixin, ToolshedTestCase): self.assertEqual(len(reply.json()), 1) self.assertEqual(reply.json()[0]['username'], str(self.f['local_user1'])) + def test_friend_delete(self): + reply = client.delete('/api/friends/{}/'.format(self.f['local_user2'].public_identity.id), + self.f['local_user1']) + self.assertEqual(reply.status_code, 204) + self.assertEqual(self.f['local_user1'].friends.count(), 1) + # what ~should~ happen: # 1. user x@A sends a friend request to user y@B @@ -100,10 +106,11 @@ class FriendRequestListTestCase(UserTestMixin, ToolshedTestCase): def setUp(self): super().setUp() self.prepare_users() - FriendRequestIncoming.objects.create( + self.friendrequest1 = FriendRequestIncoming.objects.create( befriender_username=self.f['ext_user2'].username, befriender_domain=self.f['ext_user2'].domain, befriender_public_key=self.f['ext_user2'].public_key(), befriendee_user=self.f['local_user1'], - secret='secret1').save() + secret='secret1') + self.friendrequest1.save() def test_friend_request_withouth_auth(self): reply = Client().get('/api/friendrequests/') @@ -121,6 +128,17 @@ class FriendRequestListTestCase(UserTestMixin, ToolshedTestCase): self.assertEqual(reply.json()[0]['befriender'], str(self.f['ext_user2'])) self.assertEqual(reply.json()[0]['befriender_public_key'], self.f['ext_user2'].public_key()) + def test_delete_friend_request(self): + reply = client.delete('/api/friendrequests/{}/'.format(self.friendrequest1.id), + self.f['local_user1']) + self.assertEqual(reply.status_code, 204) + self.assertEqual(FriendRequestIncoming.objects.count(), 0) + + def test_delete_friend_request_not_found(self): + reply = client.delete('/api/friendrequests/999/', self.f['local_user1']) + self.assertEqual(reply.status_code, 404) + self.assertEqual(FriendRequestIncoming.objects.count(), 1) + class FriendRequestIncomingTestCase(UserTestMixin, ToolshedTestCase): def setUp(self):