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..9e70c58 100644 --- a/ecommerce/baskets/views.py +++ b/ecommerce/baskets/views.py @@ -1,4 +1,6 @@ -from rest_framework import viewsets +from rest_framework import viewsets, status +from rest_framework.response import Response +from rest_framework.decorators import action from baskets.filters import BasketItemFilter, BasketFilter from baskets.models import BasketItem, Basket @@ -6,7 +8,8 @@ from core.mixins import DetailedViewSetMixin -class BasketItemViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): +class BasketItemViewSet(DetailedViewSetMixin,viewsets.ModelViewSet): + http_method_names = ["get"] queryset = BasketItem.objects.all() serializer_class = BasketItemSerializer filterset_class = BasketItemFilter @@ -15,12 +18,34 @@ class BasketItemViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): "detailed": BasketItemDetailedSerializer, } + def get_queryset(self): + queryset = super().get_queryset() + user = self.request.user.id + return queryset.filter(basket__customer__id=user) + class BasketViewSet(DetailedViewSetMixin, viewsets.ModelViewSet): + permission_classes = () + http_method_names = ["get", "delete", "post"] queryset = Basket.objects.all() serializer_class = BasketSerializer filterset_class = BasketFilter serializer_action_classes = { "detailed_list": BasketDetailedSerializer, "detailed": BasketDetailedSerializer, + "create_product": BasketItemSerializer } + + def get_queryset(self): + # customer can only see own basket + queryset = super().get_queryset() + user = self.request.user + return queryset.filter(customer=user) + + @action(detail=True, methods=['post']) + def add_product(self, request, pk=None): + 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) diff --git a/ecommerce/core/utils.py b/ecommerce/core/utils.py index 39bd401..4ab051d 100644 --- a/ecommerce/core/utils.py +++ b/ecommerce/core/utils.py @@ -32,3 +32,16 @@ class IsStaffUserAuthenticated(BasePermission): def has_permission(self, request, view): return bool(request.user and request.user.is_authenticated and request.user.is_staff) + + +class IsAuthenticated(BasePermission): + # checks whether the user auth or not + def has_permission(self, request, view): + return bool(request.user and request.user.is_authenticated) + + +class CanCreateUser(BasePermission): + # users who create account are either new user or staff user + def has_permission(self, request, view): + return IsStaffUserAuthenticated.has_permission(self, request, view) \ + or not (IsAuthenticated.has_permission(self, request, view)) \ No newline at end of file diff --git a/ecommerce/customers/serializers.py b/ecommerce/customers/serializers.py index ffad735..2d71953 100644 --- a/ecommerce/customers/serializers.py +++ b/ecommerce/customers/serializers.py @@ -1,20 +1,22 @@ +import django.core.validators as EmailValidator +from django.contrib.auth.password_validation import validate_password + 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 customers.models import Customer, Address, City, Country +from rest_framework.validators import UniqueValidator class CustomerSerializer(serializers.ModelSerializer): - class Meta: model = Customer fields = ("id", "first_name", "last_name", "email", "is_staff", "is_active", "date_joined") class ProfileSerializer(serializers.ModelSerializer): - class Meta: model = Customer fields = ("first_name", "last_name", "email") @@ -27,7 +29,6 @@ class Meta: class CitySerializer(serializers.ModelSerializer): - class Meta: model = City fields = ("id", "name", "country") @@ -55,7 +56,8 @@ def validate(self, attrs): return validated_data - def validate_full_name(self, value): + @staticmethod + def validate_full_name(value): if len(value) < 10: raise ValidationError(detail=_("Full name length must be bigger than 10")) return value @@ -68,3 +70,31 @@ class AddressDetailedSerializer(AddressSerializer): class CityDetailedSerializer(CitySerializer): country = CountrySerializer() + + +class CustomerRegisterSerializer(serializers.ModelSerializer): + email = serializers.EmailField(label=_("email"), + write_only=True, + required=True, + validators=[EmailValidator, UniqueValidator(queryset=Customer.objects.all())]) + password = serializers.CharField(label=_("Password"), + write_only=True, + required=True, + validators=[validate_password]) + password_confirm = serializers.CharField(label=_("Confirm Password"), + write_only=True, + required=True) + + class Meta: + model = Customer + fields = ("id", "email", "password", "password_confirm", "first_name", "last_name") + + def validate(self, attrs): + if attrs["password"] != attrs["password_confirm"]: + raise ValidationError(_("Passwords don't match.")) + return attrs + + def create(self, validated_data): + validated_data.pop("password_confirm") + new_customer = Customer.objects.create_user(**validated_data) + return new_customer diff --git a/ecommerce/customers/views.py b/ecommerce/customers/views.py index e2d05b6..fc7246d 100644 --- a/ecommerce/customers/views.py +++ b/ecommerce/customers/views.py @@ -3,11 +3,11 @@ from rest_framework.viewsets import GenericViewSet from core.mixins import DetailedViewSetMixin -from core.utils import IsStaffUserAuthenticated +from core.utils import IsStaffUserAuthenticated, CanCreateUser from customers.filters import CustomerFilter, AddressFilter, CountryFilter, CityFilter from customers.models import Customer, Address, City, Country from customers.serializers import CustomerSerializer, AddressSerializer, CitySerializer, \ - CountrySerializer, \ + CountrySerializer, CustomerRegisterSerializer, \ AddressDetailedSerializer, CityDetailedSerializer, ProfileSerializer @@ -65,4 +65,7 @@ def get_queryset(self): return queryset.filter(customer=user) - +class CustomerRegisterViewSet(mixins.CreateModelMixin, GenericViewSet): + permission_classes = (CanCreateUser,) + queryset = Customer.objects.all() + serializer_class = CustomerRegisterSerializer diff --git a/ecommerce/ecommerce/urls.py b/ecommerce/ecommerce/urls.py index 28278ef..05a8d9b 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, CustomerRegisterViewSet from ecommerce.router import router from orders.views import OrderItemViewSet, OrderViewSet, BillingAddressViewSet, ShippingAddressViewSet, \ OrderBankAccountViewSet @@ -46,6 +46,7 @@ router.register("banks", BankViewSet) router.register("admin-products", AdminProductViewSet, basename="admin-product") router.register("admin-customers", AdminCustomerViewSet, basename="admin-customer") +router.register("register", CustomerRegisterViewSet, basename="register") urlpatterns = [