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
)
41 changes: 35 additions & 6 deletions cinema/views.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
from datetime import datetime

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

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

from cinema.serializers import (
GenreSerializer,
Expand All @@ -21,22 +26,39 @@
)


class GenreViewSet(viewsets.ModelViewSet):
class GenreViewSet(
mixins.ListModelMixin,
mixins.CreateModelMixin,
viewsets.GenericViewSet
):
queryset = Genre.objects.all()
serializer_class = GenreSerializer


class ActorViewSet(viewsets.ModelViewSet):
class ActorViewSet(
mixins.ListModelMixin,
mixins.CreateModelMixin,
viewsets.GenericViewSet
):
queryset = Actor.objects.all()
serializer_class = ActorSerializer


class CinemaHallViewSet(viewsets.ModelViewSet):
class CinemaHallViewSet(
mixins.ListModelMixin,
mixins.CreateModelMixin,
viewsets.GenericViewSet
):
queryset = CinemaHall.objects.all()
serializer_class = CinemaHallSerializer


class MovieViewSet(viewsets.ModelViewSet):
class MovieViewSet(
mixins.ListModelMixin,
mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
viewsets.GenericViewSet
):
queryset = Movie.objects.prefetch_related("genres", "actors")
serializer_class = MovieSerializer

Expand Down Expand Up @@ -87,6 +109,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 @@ -118,12 +142,17 @@ class OrderPagination(PageNumberPagination):
max_page_size = 100


class OrderViewSet(viewsets.ModelViewSet):
class OrderViewSet(
mixins.ListModelMixin,
mixins.CreateModelMixin,
viewsets.GenericViewSet
):
queryset = Order.objects.prefetch_related(
"tickets__movie_session__movie", "tickets__movie_session__cinema_hall"
)
serializer_class = OrderSerializer
pagination_class = OrderPagination
permission_classes = (IsAuthenticated,)

Choose a reason for hiding this comment

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

The OrderViewSet is missing the custom permission class IsAdminOrIfAuthenticatedReadOnly. This is crucial for ensuring the correct access control as per the task requirements. Please add it to the permission_classes.


def get_queryset(self):
return Order.objects.filter(user=self.request.user)
Expand Down
15 changes: 12 additions & 3 deletions cinema_service/settings.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
Django settings for cinema_service project.

Generated by 'django-admin startproject' using Django 4.0.4.
Generated by "django-admin startproject" using Django 4.0.4.

For more information on this file, see
https://docs.djangoproject.com/en/4.0/topics/settings/
Expand All @@ -12,7 +12,7 @@

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
# Build paths inside the project like this: BASE_DIR / "subdir".
BASE_DIR = Path(__file__).resolve().parent.parent


Expand All @@ -24,7 +24,7 @@
"django-insecure-6vubhk2$++agnctay_4pxy_8cq)mosmn(*-#2b^v4cgsh-^!i3"
)

# SECURITY WARNING: don't run with debug turned on in production!
# SECURITY WARNING: don"t run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []
Expand Down Expand Up @@ -137,3 +137,12 @@
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"

REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": [
"rest_framework.authentication.TokenAuthentication",
],
"DEFAULT_PERMISSION_CLASSES": [
"cinema.permissions.IsAdminOrIfAuthenticatedReadOnly",
],
}
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"),
]
27 changes: 26 additions & 1 deletion user/views.py
Original file line number Diff line number Diff line change
@@ -1 +1,26 @@
# 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, AllowAny
from rest_framework.settings import api_settings

from user.serializers import UserSerializer


class CreateUserView(generics.CreateAPIView):
serializer_class = UserSerializer
permission_classes = (AllowAny, )


class LoginUserView(ObtainAuthToken):
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
permission_classes = (AllowAny, )


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

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