Merge branch 'main' of codeberg.org:adrien-lsh/ft_transcendence

This commit is contained in:
2024-04-18 20:08:33 +02:00
9 changed files with 109 additions and 58 deletions

View File

@ -83,4 +83,5 @@ python manage.py runserver 0.0.0.0:8000
coc nvim
```
pip install django-stubs
pip install django-type
```

View File

@ -19,12 +19,22 @@ class MyProfile extends Profile
* @type {[Profile]}
*/
this.friends = [];
/**
* @type {[Profile]}
*/
this.incomingFriendRequests = [];
/**
* @type {[Profile]}
*/
this.outgoingFriendRequests = [];
}
async init() {
await super.init();
await this.getBlockedUsers();
await this.getFriends();
await this.getIncomingFriendRequests()
await this.getOutgoingFriendRequests()
}
async getBlockedUsers() {
@ -38,6 +48,20 @@ class MyProfile extends Profile
const data = await response.json();
data.forEach(profileData => this.friends.push(new Profile(this.client, profileData.username, profileData.user_id, profileData.avatar)));
}
async getIncomingFriendRequests() {
const response = await this.client._get('/api/profiles/incoming_friend_requests');
const data = await response.json();
data.forEach(profileData => this.incomingFriendRequests.push(
new Profile(this.client, profileData.username, profileData.user_id, profileData.avatar)
));
}
async getOutgoingFriendRequests() {
const response = await this.client._get('/api/profiles/outgoing_friend_requests');
const data = await response.json();
data.forEach(profileData => this.outgoingFriendRequests.push(
new Profile(this.client, profileData.username, profileData.user_id, profileData.avatar)
));
}
/**
*
* @param {File} selectedFile

View File

@ -2,7 +2,7 @@ from __future__ import annotations
from os.path import splitext
from django.contrib.auth.models import User
from django.db.models import Q, Model, CASCADE, ForeignKey, ImageField
from django.db.models import Q, Model, CASCADE, ForeignKey, ImageField, OneToOneField
from django.db.models.signals import post_save, pre_delete
from django.dispatch import receiver
@ -10,8 +10,9 @@ from django.dispatch import receiver
def upload_to(instance, filename: str):
return f"./profiles/static/avatars/{instance.pk}{splitext(filename)[1]}"
class ProfileModel(Model):
user = ForeignKey(User, on_delete=CASCADE)
user = OneToOneField(User, on_delete=CASCADE)
avatar = ImageField(upload_to=upload_to, default="./profiles/static/avatars/default.avif")
def get_game(self) -> int:
@ -43,7 +44,7 @@ class ProfileModel(Model):
).delete()
def is_friend_requested_by(self, profile):
return self.get_received_friend_request_from(profile) is None
return FriendRequestModel.objects.filter(author=profile, target=self).exists()
def get_received_friend_request_from(self, profile):
return FriendRequestModel.objects.filter(author=profile, target=self).first()
@ -51,10 +52,13 @@ class ProfileModel(Model):
def is_friend_requesting(self, profile):
return FriendRequestModel.objects.filter(author=self, target=profile).exists()
def get_sent_friend_requests(self) -> list[ProfileModel]:
def get_outgoing_friend_request_to(self, profile):
return FriendRequestModel.objects.filter(author=self, target=profile).first()
def get_outgoing_friend_requests(self) -> list[ProfileModel]:
return FriendRequestModel.objects.filter(author=self)
def get_received_friend_requests(self) -> list[ProfileModel]:
def get_incoming_friend_requests(self) -> list[ProfileModel]:
return FriendRequestModel.objects.filter(target=self)

View File

@ -3,7 +3,10 @@ from django.urls import path
from .viewsets.ProfileViewSet import ProfileViewSet
from .viewsets.MyProfileViewSet import MyProfileViewSet
from .views.blocks import GetBlocksView, EditBlocksView
from .views.friends import GetFriendsView, EditFriendView
from .views.friends import (GetFriendsView,
EditFriendView,
GetIncomingFriendRequestView,
GetOutgoingFriendRequestView)
urlpatterns = [
path("settings", MyProfileViewSet.as_view({'patch': 'partial_update', 'delete': 'delete_avatar'}), name="my_profile_page"),
@ -13,6 +16,8 @@ urlpatterns = [
path("block/<int:pk>", EditBlocksView.as_view(), name="block_page"),
path("friends", GetFriendsView.as_view(), name="friends_list_page"),
path("friends/<int:pk>", EditFriendView.as_view(), name="friends_edit_page"),
path("incoming_friend_requests", GetIncomingFriendRequestView.as_view(), name="incoming_friend_requests"),
path("outgoing_friend_requests", GetOutgoingFriendRequestView.as_view(), name="outgoing_friend_requests"),
path("user/<str:username>", ProfileViewSet.as_view({'get': 'retrieve'}), name="profile_page"),
path("id/<int:pk>", ProfileViewSet.as_view({'get': 'retrieve_id'}), name="profile_page"),
]

View File

@ -4,8 +4,8 @@ from rest_framework import permissions, status
from rest_framework.authentication import SessionAuthentication
from rest_framework.request import Request
from django.contrib.auth.models import User
from django.utils.translation import gettext as _
from django.shortcuts import get_object_or_404
from ..models import BlockModel, ProfileModel
from ..serializers.ProfileSerializer import ProfileSerializer
@ -16,7 +16,7 @@ class GetBlocksView(APIView):
authentication_classes = (SessionAuthentication,)
def get(self, request: Request):
blocks = BlockModel.objects.filter(blocker=ProfileModel.objects.filter(user=request.user).first())
blocks = BlockModel.objects.filter(blocker=request.user.profilemodel)
bloked_profiles = [block.blocked for block in blocks]
return Response(ProfileSerializer(bloked_profiles, many=True).data)
@ -26,32 +26,32 @@ class EditBlocksView(APIView):
permission_classes = (permissions.IsAuthenticated,)
authentication_classes = (SessionAuthentication,)
def get_object(self):
return self.request.user.profilemodel
def post(self, request, pk=None):
if (pk == request.user.pk):
user_profile = self.get_object()
blocked_profile = get_object_or_404(ProfileModel, pk=pk)
if user_profile.pk == pk:
return Response(_('You can\'t block yourself.'), status.HTTP_400_BAD_REQUEST)
blocked = User.objects.filter(pk=pk)
if (not blocked.exists()):
return Response(_('This user doesn\'t exist.'), status.HTTP_404_NOT_FOUND)
if BlockModel.objects.filter(blocker=user_profile, blocked=blocked_profile):
return Response(_('You already blocked this user.'), status.HTTP_409_CONFLICT)
if (BlockModel.objects.filter(blocker=request.user, blocked=pk)):
return Response(_('You already blocked this user.'), status=status.HTTP_409_CONFLICT)
BlockModel(blocker=request.user, blocked=blocked[0]).save()
return Response(status=status.HTTP_201_CREATED)
BlockModel(blocker=user_profile, blocked=blocked_profile).save()
return Response(_('User successfully blocked.'), status.HTTP_201_CREATED)
def delete(self, request, pk=None):
if (pk == request.user.pk):
user_profile = self.get_object()
blocked_profile = get_object_or_404(ProfileModel, pk=pk)
if user_profile.pk == pk:
return Response(_('You can\'t unblock yourself.'), status.HTTP_400_BAD_REQUEST)
blocked = User.objects.filter(pk=pk)
if (not blocked.exists()):
return Response(_('This user doesn\'t exist.'), status.HTTP_404_NOT_FOUND)
block_record = BlockModel.objects.filter(blocker=user_profile, blocked=blocked_profile).first()
if not block_record:
return Response(_('This user is not blocked.'), status.HTTP_400_BAD_REQUEST)
block = BlockModel.objects.filter(blocker=request.user, blocked=blocked[0])
if (not block):
return Response(_('This user isn\'t blocked.'), status.HTTP_400_NOT_FOUND)
block.delete()
return Response(status=status.HTTP_200_OK)
block_record.delete()
return Response(_('User successfully unblocked.'), status.HTTP_200_OK)

View File

@ -4,10 +4,9 @@ from rest_framework import permissions, status
from rest_framework.authentication import SessionAuthentication
from django.utils.translation import gettext as _
from django.db.models import Q
from django.shortcuts import get_object_or_404
from ..models import ProfileModel, FriendModel
from ..models import ProfileModel, FriendRequestModel
from ..serializers.ProfileSerializer import ProfileSerializer
@ -16,11 +15,7 @@ class GetFriendsView(APIView):
authentication_classes = (SessionAuthentication,)
def get(self, request):
query = ProfileModel.objects.filter(user=request.user)
if not query.exists():
return Response(status=status.HTTP_400_BAD_REQUEST)
friends = query[0].get_friends()
return Response(ProfileSerializer(friends, many=True).data)
return Response(ProfileSerializer(request.user.profilemodel.get_friends(), many=True).data)
class EditFriendView(APIView):
@ -28,10 +23,10 @@ class EditFriendView(APIView):
authentication_classes = (SessionAuthentication,)
def get_object(self):
return ProfileModel.objects.get(pk=self.request.user.pk)
return self.request.user.profilemodel
def post(self, request, pk=None):
user_profile = self.get_object()
user_profile: ProfileModel = self.get_object()
friend_profile = get_object_or_404(ProfileModel, pk=pk)
if user_profile.pk == pk:
@ -40,9 +35,17 @@ class EditFriendView(APIView):
if user_profile.is_friend(friend_profile):
return Response(_('You are already friend with this user.'), status.HTTP_400_BAD_REQUEST)
FriendModel(friend1=user_profile, friend2=friend_profile).save()
if user_profile.is_friend_requesting(friend_profile):
return Response(_('You already sent a request to this user.'), status.HTTP_400_BAD_REQUEST)
incoming_request = user_profile.get_received_friend_request_from(friend_profile)
if incoming_request:
incoming_request.accept()
return Response(_('Friendship succssfully created.'), status.HTTP_201_CREATED)
FriendRequestModel(author=user_profile, target=friend_profile).save()
return Response(_('Friend request sent.'), status.HTTP_200_OK)
def delete(self, request, pk=None):
user_profile = self.get_object()
friend_profile = get_object_or_404(ProfileModel, pk=pk)
@ -50,5 +53,30 @@ class EditFriendView(APIView):
if not user_profile.is_friend(friend_profile):
return Response(_('You are not friend with this user.'), status.HTTP_400_BAD_REQUEST)
outgoing_request = user_profile.get_outgoing_friend_request_to(friend_profile)
if outgoing_request:
outgoing_request.delete()
return Response(_('Friend request cancelled.'))
user_profile.delete_friend(friend_profile)
return Response(_('Friendship succssfully deleted.'))
class GetIncomingFriendRequestView(APIView):
permission_classes = (permissions.IsAuthenticated,)
authentication_classes = (SessionAuthentication,)
def get(self, request):
requests = request.user.profilemodel.get_incoming_friend_requests()
profiles = [request.author for request in requests]
return Response(ProfileSerializer(profiles, many=True).data)
class GetOutgoingFriendRequestView(APIView):
permission_classes = (permissions.IsAuthenticated,)
authentication_classes = (SessionAuthentication,)
def get(self, request):
requests = request.user.profilemodel.get_outgoing_friend_requests()
profiles = [request.target for request in requests]
return Response(ProfileSerializer(profiles, many=True).data)

View File

@ -14,8 +14,7 @@ class MyProfileViewSet(viewsets.ModelViewSet):
queryset = ProfileModel.objects.all()
def get_object(self):
obj = self.get_queryset().get(pk=self.request.user.pk)
return obj
return self.request.user.profilemodel
def perform_update(self, serializer: ProfileSerializer, pk=None):
serializer.is_valid(raise_exception=True)

View File

@ -1,7 +1,7 @@
from django.utils.translation import gettext as _
from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
from rest_framework import permissions, status
from rest_framework import permissions
from rest_framework import viewsets
from rest_framework.response import Response
@ -15,21 +15,12 @@ class ProfileViewSet(viewsets.ModelViewSet):
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
def retrieve(self, request, username=None):
query = User.objects.filter(username=username)
if (not query):
return Response({"detail": _("Profile not found.")}, status.HTTP_404_NOT_FOUND)
query = self.get_queryset().filter(pk=query[0].pk)
if (not query):
return Response({"detail": _("Profile not found.")}, status.HTTP_404_NOT_FOUND)
instance = query[0]
return Response(self.serializer_class(instance).data)
user = get_object_or_404(User, username=username)
return Response(self.serializer_class(user.profilemodel).data)
def retrieve_id(self, request, pk=None):
query = self.get_queryset().filter(pk=pk)
if (not query):
return Response({"detail": _("Profile not found.")}, status.HTTP_404_NOT_FOUND)
instance = query[0]
return Response(self.serializer_class(instance).data)
user = get_object_or_404(User, pk=pk)
return Response(self.serializer_class(user.profilemodel).data)
def list(self, request):
serializer = ProfileSerializer(self.get_queryset(), many=True)

View File

@ -72,15 +72,14 @@ CHANNEL_LAYERS = {
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.locale.LocaleMiddleware',
]
ROOT_URLCONF = 'transcendence.urls'