diff --git a/config/settings.py b/config/settings.py index a664e98..a75c436 100644 --- a/config/settings.py +++ b/config/settings.py @@ -46,6 +46,7 @@ 'django_filters', 'custom_user.apps.CustomUserConfig', + 'products.apps.ProductsConfig', ] @@ -69,8 +70,8 @@ ), 'DEFAULT_PERMISSION_CLASSES': [ - # 'rest_framework.permissions.IsAuthenticated', - 'rest_framework.permissions.AllowAny', + 'rest_framework.permissions.IsAuthenticated', + # 'rest_framework.permissions.AllowAny', ], 'DEFAULT_FILTER_BACKENDS': ( diff --git a/config/urls.py b/config/urls.py index 2f94eca..90ad49e 100644 --- a/config/urls.py +++ b/config/urls.py @@ -22,6 +22,7 @@ urlpatterns = [ path('admin/', admin.site.urls), path('users/', include('custom_user.urls', namespace='custom_user')), + path('products/', include('products.urls', namespace='products')), # authorization urls path('token/', TokenObtainPairView.as_view(), name='token_obtain_pair'), diff --git a/products/permissions.py b/products/permissions.py new file mode 100644 index 0000000..b639ec3 --- /dev/null +++ b/products/permissions.py @@ -0,0 +1,34 @@ +from rest_framework.permissions import BasePermission + + +class IsSeller(BasePermission): + """ + Данный класс предоставляет право доступа к контроллеру в том случае, + если текущий пользователь имеет статус "Продавец". + """ + + def has_permission(self, request, view): + return bool(request.user.is_seller) + + +class IsSuperUser(BasePermission): + """ + Данный класс определяет права доступа для пользователей, у которых стоит флаг 'is_superuser'. + В отличие от IsAdminUser, 'IsSuperUser' предоставляет доступ только суперпользователям. + """ + + def has_permission(self, request, view): + return bool(request.user.is_superuser) + + +class IsShopOwner(BasePermission): + """ + Контроллер определяет доступ только к тем объектам, которые были созданы текущим авторизованным пользователем. + """ + + def has_object_permission(self, request, view, obj): + + if request.user == obj.seller: + return True + + return False diff --git a/products/serializers.py b/products/serializers.py new file mode 100644 index 0000000..d4464c8 --- /dev/null +++ b/products/serializers.py @@ -0,0 +1,17 @@ +from rest_framework import serializers +from products.models import Product + + +class ProductSerializer(serializers.ModelSerializer): + """ + Сериализатор модели Product. + :shop_title Название магазина, указанное продавцом при регистрации. Значение берется из модели CustomUser. + :seller Удобочитаемое отображение пользователя (email) вместо id пользователя. + """ + + shop_title = serializers.CharField(source='seller.shop_name', read_only=True) + seller = serializers.CharField(default=serializers.CurrentUserDefault(), read_only=True) + + class Meta: + model = Product + fields = '__all__' diff --git a/products/urls.py b/products/urls.py new file mode 100644 index 0000000..0a465f1 --- /dev/null +++ b/products/urls.py @@ -0,0 +1,13 @@ +from django.urls import path +from .apps import ProductsConfig +from .views import ProductCreateView, ProductDetailView, ProductListView, ProductDeleteView + +app_name = ProductsConfig.name + + +urlpatterns = [ + path('create/', ProductCreateView.as_view(), name='create-product'), + path('list/', ProductListView.as_view(), name='products-list'), + path('detail//', ProductDetailView.as_view(), name='product-detail'), + path('delete//', ProductDeleteView.as_view(), name='product-delete'), + ] diff --git a/products/views.py b/products/views.py new file mode 100644 index 0000000..dcf63c2 --- /dev/null +++ b/products/views.py @@ -0,0 +1,60 @@ +from rest_framework import generics +from products.models import Product +from products.permissions import IsSeller, IsSuperUser, IsShopOwner +from products.serializers import ProductSerializer + + +class ProductCreateView(generics.CreateAPIView): + """ + Контроллер для публикации продукта. + Доступ к контроллеру имеется только у суперпользователя и пользователей со статусом "Продавец". + """ + + serializer_class = ProductSerializer + permission_classes = [IsSeller | IsSuperUser] + + def perform_create(self, serializer): + + new_product = serializer.save(seller=self.request.user) + new_product.seller = self.request.user + new_product.save() + + +class ProductListView(generics.ListCreateAPIView): + """ + Контроллер для просмотра размещенных на площадке товарах. + Доступ к контроллеру имеется только у суперпользователя и пользователей со статусом "Продавец". + Каждый продавец видит список только своих товаров, суперпользователь видит все размещенные товары. + """ + + serializer_class = ProductSerializer + permission_classes = [IsSeller | IsSuperUser] + + def get_queryset(self): + if self.request.user.is_superuser: + return Product.objects.all() + + return Product.objects.filter(seller=self.request.user) + + +class ProductDetailView(generics.RetrieveAPIView): + """ + Контроллер для просмотра детальной информации о товаре. + Информацию о товаре может просмотреть только тот продавец, который разместил данный товар. + Суперпользователь может просматривать детальную информацию всех размещенных товаров. + """ + + queryset = Product.objects.all() + serializer_class = ProductSerializer + permission_classes = [IsShopOwner | IsSuperUser] + + +class ProductDeleteView(generics.DestroyAPIView): + """ + Контроллер для удаления размещенного на площадке товара. + Удалить товар может только тот продавец, который разместил данный товар. + Суперпользователь может удалить любой размещенный товар. + """ + + queryset = Product.objects.all() + permission_classes = [IsShopOwner | IsSuperUser]