From 73f5b5dcd72602020585b67f3d34db6a3a84a97c Mon Sep 17 00:00:00 2001 From: Beyza Koroglu Date: Sat, 18 Dec 2021 02:07:40 +0300 Subject: [PATCH 1/4] added register endpoint --- ecommerce/core/utils.py | 7 +++++++ ecommerce/customers/serializers.py | 28 ++++++++++++++++++++++++++++ ecommerce/customers/views.py | 10 ++++++++-- ecommerce/ecommerce/urls.py | 3 ++- 4 files changed, 45 insertions(+), 3 deletions(-) diff --git a/ecommerce/core/utils.py b/ecommerce/core/utils.py index 39bd401..ad17f5d 100644 --- a/ecommerce/core/utils.py +++ b/ecommerce/core/utils.py @@ -1,5 +1,6 @@ from django.core.validators import RegexValidator from django.utils.translation import gettext_lazy as _ +from rest_framework import permissions from rest_framework.permissions import BasePermission @@ -32,3 +33,9 @@ class IsStaffUserAuthenticated(BasePermission): def has_permission(self, request, view): return bool(request.user and request.user.is_authenticated and request.user.is_staff) + + +class IsNotAuthenticated(BasePermission): + + def has_permission(self, request, view): + return not bool(request.user and request.user.is_authenticated) diff --git a/ecommerce/customers/serializers.py b/ecommerce/customers/serializers.py index ffad735..72450aa 100644 --- a/ecommerce/customers/serializers.py +++ b/ecommerce/customers/serializers.py @@ -1,7 +1,10 @@ +from django.contrib.auth.password_validation import validate_password +from django.core.validators import EmailValidator from django.utils.translation import gettext_lazy as _ from django.db.transaction import atomic from rest_framework import serializers from rest_framework.exceptions import ValidationError +from rest_framework.validators import UniqueValidator from customers.models import Customer, Address, City, Country @@ -20,6 +23,31 @@ class Meta: fields = ("first_name", "last_name", "email") +class RegisterSerializer(serializers.ModelSerializer): + email = serializers.EmailField(write_only=True, required=True, validators=[EmailValidator(), + UniqueValidator(queryset=Customer.objects.all())]) + password = serializers.CharField(write_only=True, required=True, validators=[validate_password]) + password_repeat = serializers.CharField(write_only=True, required=True) + + class Meta: + model = Customer + fields = fields = ("id", "email", "password", "password_repeat", "first_name", "last_name") + + def validate(self, attrs): + if attrs["password"] != attrs["password_repeat"]: + raise ValidationError(_("Passwords are not same")) + return attrs + + def create(self, validated_data): + customer = Customer.objects.create_user( + first_name=validated_data["first_name"], + last_name=validated_data["last_name"], + email=validated_data["email"], + password=validated_data["password"] + ) + return customer + + class CountrySerializer(serializers.ModelSerializer): class Meta: model = Country diff --git a/ecommerce/customers/views.py b/ecommerce/customers/views.py index e2d05b6..53fd23f 100644 --- a/ecommerce/customers/views.py +++ b/ecommerce/customers/views.py @@ -3,12 +3,12 @@ from rest_framework.viewsets import GenericViewSet from core.mixins import DetailedViewSetMixin -from core.utils import IsStaffUserAuthenticated +from core.utils import IsStaffUserAuthenticated, IsNotAuthenticated from customers.filters import CustomerFilter, AddressFilter, CountryFilter, CityFilter from customers.models import Customer, Address, City, Country from customers.serializers import CustomerSerializer, AddressSerializer, CitySerializer, \ CountrySerializer, \ - AddressDetailedSerializer, CityDetailedSerializer, ProfileSerializer + AddressDetailedSerializer, CityDetailedSerializer, ProfileSerializer, RegisterSerializer class AdminCustomerViewSet(viewsets.ModelViewSet): @@ -32,6 +32,12 @@ def get_object(self): return obj +class RegisterViewSet(mixins.CreateModelMixin, GenericViewSet): + permission_classes = (IsNotAuthenticated,) + queryset = Customer.objects.all() + serializer_class = RegisterSerializer + + class CountryViewSet(viewsets.ModelViewSet): permission_classes = () queryset = Country.objects.all() diff --git a/ecommerce/ecommerce/urls.py b/ecommerce/ecommerce/urls.py index 28278ef..2da8774 100644 --- a/ecommerce/ecommerce/urls.py +++ b/ecommerce/ecommerce/urls.py @@ -21,7 +21,7 @@ from baskets.views import BasketItemViewSet, BasketViewSet from core.views import APITokenObtainPairView from customers.views import AddressViewSet, CityViewSet, \ - CountryViewSet, AdminCustomerViewSet, MyProfileViewSet + CountryViewSet, AdminCustomerViewSet, MyProfileViewSet, RegisterViewSet from ecommerce.router import router from orders.views import OrderItemViewSet, OrderViewSet, BillingAddressViewSet, ShippingAddressViewSet, \ OrderBankAccountViewSet @@ -55,6 +55,7 @@ path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'), path('api/profile/', MyProfileViewSet.as_view( {"get": "retrieve", "put": "update", "patch": "partial_update"}), name='profile'), + path('api/register/', RegisterViewSet.as_view({"post": "create"}), name='register'), ] if settings.DEBUG: From e677a752a62fde94ff3907ea45a0743cb604e54e Mon Sep 17 00:00:00 2001 From: Beyza Koroglu Date: Sat, 18 Dec 2021 19:04:57 +0300 Subject: [PATCH 2/4] added add_product action --- ecommerce/baskets/serializers.py | 1 + ecommerce/baskets/views.py | 27 +++++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/ecommerce/baskets/serializers.py b/ecommerce/baskets/serializers.py index 9dc4c30..4ccb05b 100644 --- a/ecommerce/baskets/serializers.py +++ b/ecommerce/baskets/serializers.py @@ -13,6 +13,7 @@ class Meta: class BasketSerializer(serializers.ModelSerializer): + customer = serializers.HiddenField(default=serializers.CurrentUserDefault()) class Meta: model = Basket diff --git a/ecommerce/baskets/views.py b/ecommerce/baskets/views.py index ee32571..9d75933 100644 --- a/ecommerce/baskets/views.py +++ b/ecommerce/baskets/views.py @@ -1,8 +1,11 @@ -from rest_framework import viewsets +from rest_framework import viewsets, status +from rest_framework.decorators import action +from rest_framework.response import Response from baskets.filters import BasketItemFilter, BasketFilter from baskets.models import BasketItem, Basket -from baskets.serializers import BasketItemSerializer, BasketSerializer, BasketItemDetailedSerializer, BasketDetailedSerializer +from baskets.serializers import BasketItemSerializer, BasketSerializer, BasketItemDetailedSerializer, \ + BasketDetailedSerializer from core.mixins import DetailedViewSetMixin @@ -13,8 +16,23 @@ class BasketItemViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): serializer_action_classes = { "detailed_list": BasketItemDetailedSerializer, "detailed": BasketItemDetailedSerializer, + "add_product": BasketItemDetailedSerializer, } + def get_queryset(self): + queryset = super().get_queryset() + user = self.request.user + return queryset.filter(basket__customer=user) + + @action(detail=True, methods=['post'], http_method_names=['post']) + def add_product(self, request): + serializer = BasketItemSerializer(data=request.data) + + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + class BasketViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): queryset = Basket.objects.all() @@ -24,3 +42,8 @@ class BasketViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): "detailed_list": BasketDetailedSerializer, "detailed": BasketDetailedSerializer, } + + def get_queryset(self): + queryset = super().get_queryset() + user = self.request.user + return queryset.filter(customer=user) \ No newline at end of file From fcd88b98103982c92e2a7c303d8868e950cc259f Mon Sep 17 00:00:00 2001 From: Beyza Koroglu Date: Sat, 18 Dec 2021 19:18:37 +0300 Subject: [PATCH 3/4] added permissions --- ecommerce/customers/views.py | 1 + ecommerce/orders/views.py | 7 ++++++- ecommerce/payments/views.py | 2 ++ ecommerce/products/views.py | 2 ++ 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/ecommerce/customers/views.py b/ecommerce/customers/views.py index 53fd23f..dc4d1bc 100644 --- a/ecommerce/customers/views.py +++ b/ecommerce/customers/views.py @@ -57,6 +57,7 @@ class CityViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): class AddressViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + permission_classes = (permissions.IsAuthenticated,) queryset = Address.objects.all() serializer_class = AddressSerializer filterset_class = AddressFilter diff --git a/ecommerce/orders/views.py b/ecommerce/orders/views.py index dde7137..f6faa3e 100644 --- a/ecommerce/orders/views.py +++ b/ecommerce/orders/views.py @@ -1,4 +1,4 @@ -from rest_framework import viewsets +from rest_framework import viewsets, permissions from core.mixins import DetailedViewSetMixin from orders.filters import OrderItemFilter, OrderFilter, BillingAddressFilter, ShippingAddressFilter, \ @@ -10,6 +10,7 @@ class OrderItemViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + permission_classes = (permissions.IsAuthenticated,) queryset = OrderItem.objects.all() serializer_class = OrderItemSerializer filterset_class = OrderItemFilter @@ -20,6 +21,7 @@ class OrderItemViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): class OrderViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + permission_classes = (permissions.IsAuthenticated,) queryset = Order.objects.all() serializer_class = OrderSerializer filterset_class = OrderFilter @@ -30,6 +32,7 @@ class OrderViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): class BillingAddressViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + permission_classes = (permissions.IsAuthenticated,) queryset = BillingAddress.objects.all() serializer_class = BillingAddressSerializer filterset_class = BillingAddressFilter @@ -40,6 +43,7 @@ class BillingAddressViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): class ShippingAddressViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + permission_classes = (permissions.IsAuthenticated,) queryset = ShippingAddress.objects.all() serializer_class = ShippingAddressSerializer filterset_class = ShippingAddressFilter @@ -50,6 +54,7 @@ class ShippingAddressViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): class OrderBankAccountViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + permission_classes = (permissions.IsAuthenticated,) queryset = OrderBankAccount.objects.all() serializer_class = OrderBankAccountSerializer filterset_class = OrderBankAccountFilter diff --git a/ecommerce/payments/views.py b/ecommerce/payments/views.py index 09b28a7..38eb264 100644 --- a/ecommerce/payments/views.py +++ b/ecommerce/payments/views.py @@ -7,6 +7,7 @@ class BankAccountViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + permission_classes = (permissions.IsAuthenticated,) queryset = BankAccount.objects.all() serializer_class = BankAccountSerializer filterset_class = BankAccountFilter @@ -17,6 +18,7 @@ class BankAccountViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): class BankViewSet(viewsets.ModelViewSet): + permission_classes = () queryset = Bank.objects.all() serializer_class = BankSerializer filterset_class = BankFilter diff --git a/ecommerce/products/views.py b/ecommerce/products/views.py index 4f75c73..f31e1ca 100644 --- a/ecommerce/products/views.py +++ b/ecommerce/products/views.py @@ -37,12 +37,14 @@ class AdminProductViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): class CategoryViewSet(viewsets.ModelViewSet): + permission_classes = () http_method_names = ["get"] queryset = Category.objects.all() serializer_class = CategorySerializer class PriceViewSet(viewsets.ModelViewSet): + permission_classes = () http_method_names = ["get"] queryset = Price.objects.all() filterset_class = PriceFilter From 8bf001d7f336727adda59847212ecca43313ed42 Mon Sep 17 00:00:00 2001 From: Beyza Koroglu Date: Sat, 18 Dec 2021 19:18:37 +0300 Subject: [PATCH 4/4] added permissions --- ecommerce/customers/views.py | 1 + ecommerce/orders/views.py | 7 ++++++- ecommerce/payments/views.py | 4 +++- ecommerce/products/views.py | 2 ++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ecommerce/customers/views.py b/ecommerce/customers/views.py index 53fd23f..dc4d1bc 100644 --- a/ecommerce/customers/views.py +++ b/ecommerce/customers/views.py @@ -57,6 +57,7 @@ class CityViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): class AddressViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + permission_classes = (permissions.IsAuthenticated,) queryset = Address.objects.all() serializer_class = AddressSerializer filterset_class = AddressFilter diff --git a/ecommerce/orders/views.py b/ecommerce/orders/views.py index dde7137..f6faa3e 100644 --- a/ecommerce/orders/views.py +++ b/ecommerce/orders/views.py @@ -1,4 +1,4 @@ -from rest_framework import viewsets +from rest_framework import viewsets, permissions from core.mixins import DetailedViewSetMixin from orders.filters import OrderItemFilter, OrderFilter, BillingAddressFilter, ShippingAddressFilter, \ @@ -10,6 +10,7 @@ class OrderItemViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + permission_classes = (permissions.IsAuthenticated,) queryset = OrderItem.objects.all() serializer_class = OrderItemSerializer filterset_class = OrderItemFilter @@ -20,6 +21,7 @@ class OrderItemViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): class OrderViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + permission_classes = (permissions.IsAuthenticated,) queryset = Order.objects.all() serializer_class = OrderSerializer filterset_class = OrderFilter @@ -30,6 +32,7 @@ class OrderViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): class BillingAddressViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + permission_classes = (permissions.IsAuthenticated,) queryset = BillingAddress.objects.all() serializer_class = BillingAddressSerializer filterset_class = BillingAddressFilter @@ -40,6 +43,7 @@ class BillingAddressViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): class ShippingAddressViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + permission_classes = (permissions.IsAuthenticated,) queryset = ShippingAddress.objects.all() serializer_class = ShippingAddressSerializer filterset_class = ShippingAddressFilter @@ -50,6 +54,7 @@ class ShippingAddressViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): class OrderBankAccountViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + permission_classes = (permissions.IsAuthenticated,) queryset = OrderBankAccount.objects.all() serializer_class = OrderBankAccountSerializer filterset_class = OrderBankAccountFilter diff --git a/ecommerce/payments/views.py b/ecommerce/payments/views.py index 09b28a7..c961d30 100644 --- a/ecommerce/payments/views.py +++ b/ecommerce/payments/views.py @@ -1,4 +1,4 @@ -from rest_framework import viewsets +from rest_framework import viewsets, permissions from core.mixins import DetailedViewSetMixin from payments.filters import BankAccountFilter, BankFilter @@ -7,6 +7,7 @@ class BankAccountViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + permission_classes = (permissions.IsAuthenticated,) queryset = BankAccount.objects.all() serializer_class = BankAccountSerializer filterset_class = BankAccountFilter @@ -17,6 +18,7 @@ class BankAccountViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): class BankViewSet(viewsets.ModelViewSet): + permission_classes = () queryset = Bank.objects.all() serializer_class = BankSerializer filterset_class = BankFilter diff --git a/ecommerce/products/views.py b/ecommerce/products/views.py index 4f75c73..f31e1ca 100644 --- a/ecommerce/products/views.py +++ b/ecommerce/products/views.py @@ -37,12 +37,14 @@ class AdminProductViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): class CategoryViewSet(viewsets.ModelViewSet): + permission_classes = () http_method_names = ["get"] queryset = Category.objects.all() serializer_class = CategorySerializer class PriceViewSet(viewsets.ModelViewSet): + permission_classes = () http_method_names = ["get"] queryset = Price.objects.all() filterset_class = PriceFilter