Added profiles page and friends system

This commit is contained in:
ITQ
2024-03-03 09:20:17 +03:00
parent 13b4e8bafb
commit c81cd3560f
7 changed files with 132 additions and 3 deletions
@@ -1,3 +1,4 @@
import bcrypt
import jwt
from django.conf import settings
from rest_framework.authentication import (
@@ -30,6 +31,13 @@ class JWTAuthentication(BaseAuthentication):
)
user = Profile.objects.get(id=payload["id"])
if not bcrypt.checkpw(
payload["password"].encode("utf-8"),
user.password.encode("utf-8"),
):
error = "Token has expired"
raise AuthenticationFailed(error)
except Profile.DoesNotExist:
error = "Invalid token"
raise AuthenticationFailed(error) from None
@@ -1,4 +1,4 @@
# Generated by Django 4.2.10 on 2024-03-02 10:14
# Generated by Django 4.2.10 on 2024-03-03 06:12
import api.users.validators
import django.core.validators
@@ -24,6 +24,7 @@ class Migration(migrations.Migration):
('isPublic', models.BooleanField()),
('phone', models.CharField(blank=True, max_length=20, null=True, validators=[django.core.validators.MaxLengthValidator(20), django.core.validators.RegexValidator('\\+[\\d]+')])),
('image', models.URLField(blank=True, null=True)),
('friends', models.ManyToManyField(blank=True, to='users.profile')),
],
),
]
+11
View File
@@ -32,6 +32,7 @@ class Profile(models.Model):
null=True,
)
image = models.URLField(max_length=200, blank=True, null=True)
friends = models.ManyToManyField("self", blank=True, symmetrical=False)
def __str__(self):
return self.login
@@ -39,6 +40,16 @@ class Profile(models.Model):
def is_authenticated(self):
return True
def add_friend(self, user):
if self != user:
self.friends.add(user)
def remove_friend(self, user):
self.friends.remove(user)
def check_for_friendship(self, user):
return self.friends.filter(pk=user.pk).exists()
@classmethod
def check_unique(cls, user_id, validated_data):
errors = {}
+13
View File
@@ -0,0 +1,13 @@
from rest_framework.permissions import BasePermission
class CanAccessProfile(BasePermission):
def has_object_permission(self, request, view, obj):
if (
obj.isPublic
or obj.check_for_friendship(request.user)
or obj == request.user
):
return True
return False
+21
View File
@@ -28,3 +28,24 @@ class UpdateProfileSerializer(serializers.ModelSerializer):
"phone",
"image",
]
class PublicProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = [
"login",
"email",
"countryCode",
"isPublic",
"phone",
"image",
]
def to_representation(self, instance):
data = super().to_representation(instance)
if data["image"] is None:
del data["image"]
if data["phone"] is None:
del data["phone"]
return data
+17 -1
View File
@@ -16,5 +16,21 @@ urlpatterns = [
path(
"me/profile",
api.users.views.ProfileMeApiView.as_view(),
)
name="profile-me",
),
path(
"profiles/<str:login>",
api.users.views.ProfileAPIView.as_view(),
name="profiles",
),
path(
"friends/add",
api.users.views.AddFriendAPIView.as_view(),
name="add-friend",
),
path(
"friends/remove",
api.users.views.RemoveFriendAPIView.as_view(),
name="remove-friend",
),
]
+60 -1
View File
@@ -10,7 +10,12 @@ from rest_framework.response import Response
from rest_framework.views import APIView
from api.users.models import Profile
from api.users.serializers import ProfileSerializer, UpdateProfileSerializer
from api.users.permissions import CanAccessProfile
from api.users.serializers import (
ProfileSerializer,
PublicProfileSerializer,
UpdateProfileSerializer,
)
class RegisterUserApiView(APIView):
@@ -116,3 +121,57 @@ class ProfileMeApiView(APIView):
profile["image"] = user.image
return profile
class ProfileAPIView(APIView):
permission_classes = [IsAuthenticated, CanAccessProfile]
def get(self, request, login):
try:
profile = Profile.objects.get(login=login)
self.check_object_permissions(request, profile)
serializer = PublicProfileSerializer(profile)
return Response(serializer.data)
except Profile.DoesNotExist:
return Response(
{"detail": "Profile not found."},
status=status.HTTP_403_FORBIDDEN,
)
class AddFriendAPIView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request):
try:
login = request.data.get("login")
profile = Profile.objects.get(login=login)
request.user.add_friend(profile)
return Response(
{"status": "ok"},
status=status.HTTP_200_OK,
)
except Profile.DoesNotExist:
return Response(
{"detail": "Profile not found."},
status=status.HTTP_404_NOT_FOUND,
)
class RemoveFriendAPIView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request):
try:
login = request.data.get("login")
profile = Profile.objects.get(login=login)
request.user.remove_friend(profile)
return Response(
{"status": "ok"},
status=status.HTTP_200_OK,
)
except Profile.DoesNotExist:
return Response(
{"detail": "Profile not found."},
status=status.HTTP_404_NOT_FOUND,
)