diff --git a/solution/pulse/api/posts/permissions.py b/solution/pulse/api/posts/permissions.py index ee40832..e5cd177 100644 --- a/solution/pulse/api/posts/permissions.py +++ b/solution/pulse/api/posts/permissions.py @@ -15,3 +15,18 @@ class CanAccessPost(BasePermission): return True return False + + +class CanAccessFeed(BasePermission): + message = "You do not have permission to access this feed." + status_code = status.HTTP_404_NOT_FOUND + + 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 diff --git a/solution/pulse/api/posts/urls.py b/solution/pulse/api/posts/urls.py index 6e55be5..b4f9044 100644 --- a/solution/pulse/api/posts/urls.py +++ b/solution/pulse/api/posts/urls.py @@ -13,4 +13,14 @@ urlpatterns = [ api.posts.views.PostDetailApiView.as_view(), name="post-detail", ), + path( + "/feed/my", + api.posts.views.MyFeedListApiView.as_view(), + name="my-feed", + ), + path( + "/feed/", + api.posts.views.UserFeedListApiView.as_view(), + name="user-feed", + ), ] diff --git a/solution/pulse/api/posts/views.py b/solution/pulse/api/posts/views.py index b854efa..5c46f73 100644 --- a/solution/pulse/api/posts/views.py +++ b/solution/pulse/api/posts/views.py @@ -1,12 +1,14 @@ -from rest_framework import status +from rest_framework import serializers, status from rest_framework.exceptions import NotFound, ValidationError +from rest_framework.generics import ListAPIView from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView from api.posts.models import Post -from api.posts.permissions import CanAccessPost +from api.posts.permissions import CanAccessFeed, CanAccessPost from api.posts.serializers import PostSerializer +from api.users.models import Profile class CreatePostApiView(APIView): @@ -33,3 +35,50 @@ class PostDetailApiView(APIView): raise NotFound( {"detail": "Post not found."}, ) from None + + +class MyFeedListApiView(ListAPIView): + permission_classes = [IsAuthenticated] + serializer_class = PostSerializer + + def get_queryset(self): + class QueryParamsSerializer(serializers.Serializer): + limit = serializers.IntegerField(default=5) + offset = serializers.IntegerField(default=0) + + serializer = QueryParamsSerializer(data=self.request.query_params) + serializer.is_valid(raise_exception=True) + + limit = serializer.validated_data.get("limit") + offset = serializer.validated_data.get("offset") + + return self.request.user.posts.all()[offset: offset + limit] + + +class UserFeedListApiView(ListAPIView): + permission_classes = [IsAuthenticated, CanAccessFeed] + serializer_class = PostSerializer + + def get_queryset(self): + class QueryParamsSerializer(serializers.Serializer): + limit = serializers.IntegerField(default=5) + offset = serializers.IntegerField(default=0) + + login = self.kwargs.get("login") + + try: + user = Profile.objects.get(login=login) + except Profile.DoesNotExist: + raise NotFound( + {"detail": "Profile not found."}, + ) from None + + self.check_object_permissions(self.request, user) + + serializer = QueryParamsSerializer(data=self.request.query_params) + serializer.is_valid(raise_exception=True) + + limit = serializer.validated_data.get("limit") + offset = serializer.validated_data.get("offset") + + return user.posts.all()[offset: offset + limit] diff --git a/solution/pulse/api/users/views.py b/solution/pulse/api/users/views.py index daf532d..c3ddc51 100644 --- a/solution/pulse/api/users/views.py +++ b/solution/pulse/api/users/views.py @@ -4,7 +4,7 @@ import bcrypt import jwt from django.conf import settings from django.utils import timezone -from rest_framework import status +from rest_framework import serializers, status from rest_framework.exceptions import ( NotAuthenticated, NotFound, @@ -192,11 +192,18 @@ class FriendsListApiView(ListAPIView): serializer_class = FriendshipSerializer def get_queryset(self): - limit = int(self.request.query_params.get("limit", 5)) - offset = int(self.request.query_params.get("offset", 0)) + class QueryParamsSerializer(serializers.Serializer): + limit = serializers.IntegerField(default=5) + offset = serializers.IntegerField(default=0) + + serializer = QueryParamsSerializer(data=self.request.query_params) + serializer.is_valid(raise_exception=True) + + limit = serializer.validated_data.get("limit") + offset = serializer.validated_data.get("offset") return Friendship.objects.filter(from_profile=self.request.user)[ - offset : offset + limit + offset: offset + limit ]