Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #683

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
21 changes: 21 additions & 0 deletions cinema/permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from rest_framework.permissions import BasePermission, SAFE_METHODS

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a syntax error in the import statement. The correct syntax should be from rest_framework.permissions import BasePermission, SAFE_METHODS without the slash (/).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a syntax error in the import statement. The correct syntax should be: from rest_framework.permissions import BasePermission, SAFE_METHODS.



class IsAdminOrIfAuthenticatedReadOnly(BasePermission):
"""
Custom permission class that grants
different levels of access based on user role.

- Full access is granted if the user is an admin.
- Read-only access is granted if the
user is authenticated but not an admin.
"""

def has_permission(self, request, view):
return bool(
request.method in SAFE_METHODS
and request.user
and request.user.is_authenticated
) or (
request.user and request.user.is_staff
)
17 changes: 17 additions & 0 deletions cinema/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@

from django.db.models import F, Count
from rest_framework import viewsets
from rest_framework.authentication import TokenAuthentication
from rest_framework.pagination import PageNumberPagination
from rest_framework.permissions import IsAdminUser, IsAuthenticated

from cinema.models import Genre, Actor, CinemaHall, Movie, MovieSession, Order
from cinema.permissions import (
IsAdminOrIfAuthenticatedReadOnly
)

from cinema.serializers import (
GenreSerializer,
Expand All @@ -24,21 +29,29 @@
class GenreViewSet(viewsets.ModelViewSet):
queryset = Genre.objects.all()
serializer_class = GenreSerializer
authentication_classes = (TokenAuthentication,)
permission_classes = (IsAdminOrIfAuthenticatedReadOnly, IsAuthenticated)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The permission_classes for GenreViewSet includes both IsAdminOrIfAuthenticatedReadOnly and IsAuthenticated. This is redundant because IsAdminOrIfAuthenticatedReadOnly already handles both admin and authenticated user permissions. You can remove IsAuthenticated from this tuple.



class ActorViewSet(viewsets.ModelViewSet):
queryset = Actor.objects.all()
serializer_class = ActorSerializer
authentication_classes = (TokenAuthentication,)
permission_classes = (IsAdminOrIfAuthenticatedReadOnly,)


class CinemaHallViewSet(viewsets.ModelViewSet):
queryset = CinemaHall.objects.all()
serializer_class = CinemaHallSerializer
authentication_classes = (TokenAuthentication,)
permission_classes = (IsAdminOrIfAuthenticatedReadOnly,)


class MovieViewSet(viewsets.ModelViewSet):
queryset = Movie.objects.prefetch_related("genres", "actors")
serializer_class = MovieSerializer
authentication_classes = (TokenAuthentication,)
permission_classes = (IsAdminOrIfAuthenticatedReadOnly,)

@staticmethod
def _params_to_ints(qs):
Expand Down Expand Up @@ -87,6 +100,8 @@ class MovieSessionViewSet(viewsets.ModelViewSet):
)
)
serializer_class = MovieSessionSerializer
authentication_classes = (TokenAuthentication,)
permission_classes = (IsAdminOrIfAuthenticatedReadOnly,)

def get_queryset(self):
date = self.request.query_params.get("date")
Expand Down Expand Up @@ -124,6 +139,8 @@ class OrderViewSet(viewsets.ModelViewSet):
)
serializer_class = OrderSerializer
pagination_class = OrderPagination
authentication_classes = (TokenAuthentication,)
permission_classes = (IsAdminOrIfAuthenticatedReadOnly,)

def get_queryset(self):
return Order.objects.filter(user=self.request.user)
Expand Down
1 change: 1 addition & 0 deletions cinema_service/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
urlpatterns = [
path("admin/", admin.site.urls),
path("api/cinema/", include("cinema.urls", namespace="cinema")),
path("api/user/", include("user.urls", namespace="user")),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The include function is used with a namespace argument, but the namespace should be defined in the included urls.py files of the respective apps (cinema and user). Ensure that the urls.py files in these apps have a namespace defined in their app_name variable.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The namespace argument in the include function requires that the app_name variable is defined in the urls.py files of the respective apps (cinema and user). Please ensure that the app_name is correctly set in those files to avoid any namespace-related issues.

path("__debug__/", include("debug_toolbar.urls")),
]
28 changes: 27 additions & 1 deletion user/serializers.py
Original file line number Diff line number Diff line change
@@ -1 +1,27 @@
# write your code here
from django.contrib.auth import get_user_model
from rest_framework import serializers


class UserSerializer(serializers.ModelSerializer):
class Meta:
model = get_user_model()
fields = ("id", "username", "email", "password", "is_staff")
read_only_fields = ("id", "is_staff")
extra_kwargs = {
"password": {"write_only": True, "min_length": 5}
}

def create(self, validated_data):
"""create user with encrypted password"""
return get_user_model().objects.create_user(**validated_data)

def update(self, instance, validated_data):
"""Update User with encrypted password"""
password = validated_data.pop("password", None)
user = super().update(instance, validated_data)

if password:
user.set_password(password)
user.save()

return user
15 changes: 14 additions & 1 deletion user/urls.py
Original file line number Diff line number Diff line change
@@ -1 +1,14 @@
# write your code here
from django.urls import path


from user.views import CreateUserView, LoginUserView, ManagerUserView
from rest_framework.authtoken import views


app_name = "user"

urlpatterns = [
path("register/", CreateUserView.as_view(), name="create"),
path("login/", LoginUserView.as_view(), name="login"),
path("me/", ManagerUserView.as_view(), name="manage"),
]
25 changes: 24 additions & 1 deletion user/views.py
Original file line number Diff line number Diff line change
@@ -1 +1,24 @@
# write your code here
from rest_framework import generics
from rest_framework.authentication import TokenAuthentication
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.permissions import IsAuthenticated
from rest_framework.settings import api_settings

from user.serializers import UserSerializer


class CreateUserView(generics.CreateAPIView):
serializer_class = UserSerializer


class LoginUserView(ObtainAuthToken):
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES


class ManagerUserView(generics.RetrieveUpdateAPIView):
serializer_class = UserSerializer
authentication_classes = (TokenAuthentication,)
permission_classes = (IsAuthenticated,)

def get_object(self):
return self.request.user
Loading