-
Notifications
You must be signed in to change notification settings - Fork 701
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
Solution #667
base: master
Are you sure you want to change the base?
Solution #667
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
from rest_framework.permissions import BasePermission, SAFE_METHODS | ||
|
||
|
||
class IsAdminOrIfAuthenticatedReadOnly(BasePermission): | ||
def has_permission(self, request, view): | ||
if request.user and request.user.is_staff: | ||
return True | ||
|
||
# Разрешить аутентифицированным пользователям доступ к безопасным методам (чтение) | ||
if request.method in SAFE_METHODS: | ||
return request.user and request.user.is_authenticated | ||
|
||
# Разрешить аутентифицированным пользователям создание заказов (POST) только в OrderViewSet | ||
if (view.__class__.__name__ == "OrderViewSet" | ||
and request.method == "POST"): | ||
return request.user and request.user.is_authenticated | ||
Comment on lines
+12
to
+14
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The logic here correctly checks if the view is |
||
|
||
# Запретить все остальные действия для неадминистраторов | ||
return False |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,9 +2,18 @@ | |
|
||
from django.db.models import F, Count | ||
from rest_framework import viewsets | ||
from rest_framework.authentication import TokenAuthentication | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The use of |
||
from rest_framework.pagination import PageNumberPagination | ||
|
||
from cinema.models import Genre, Actor, CinemaHall, Movie, MovieSession, Order | ||
from cinema.models import ( | ||
Genre, | ||
Actor, | ||
CinemaHall, | ||
Movie, | ||
MovieSession, | ||
Order | ||
) | ||
from cinema.permissions import IsAdminOrIfAuthenticatedReadOnly | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The import of |
||
|
||
from cinema.serializers import ( | ||
GenreSerializer, | ||
|
@@ -24,21 +33,29 @@ | |
class GenreViewSet(viewsets.ModelViewSet): | ||
queryset = Genre.objects.all() | ||
serializer_class = GenreSerializer | ||
authentication_classes = (TokenAuthentication,) | ||
permission_classes = (IsAdminOrIfAuthenticatedReadOnly,) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
|
||
|
||
class ActorViewSet(viewsets.ModelViewSet): | ||
queryset = Actor.objects.all() | ||
serializer_class = ActorSerializer | ||
authentication_classes = (TokenAuthentication,) | ||
permission_classes = (IsAdminOrIfAuthenticatedReadOnly,) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
|
||
|
||
class CinemaHallViewSet(viewsets.ModelViewSet): | ||
queryset = CinemaHall.objects.all() | ||
serializer_class = CinemaHallSerializer | ||
authentication_classes = (TokenAuthentication,) | ||
permission_classes = (IsAdminOrIfAuthenticatedReadOnly,) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
|
||
|
||
class MovieViewSet(viewsets.ModelViewSet): | ||
queryset = Movie.objects.prefetch_related("genres", "actors") | ||
serializer_class = MovieSerializer | ||
authentication_classes = (TokenAuthentication,) | ||
permission_classes = (IsAdminOrIfAuthenticatedReadOnly,) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
|
||
@staticmethod | ||
def _params_to_ints(qs): | ||
|
@@ -87,6 +104,8 @@ class MovieSessionViewSet(viewsets.ModelViewSet): | |
) | ||
) | ||
serializer_class = MovieSessionSerializer | ||
authentication_classes = (TokenAuthentication,) | ||
permission_classes = (IsAdminOrIfAuthenticatedReadOnly,) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
|
||
def get_queryset(self): | ||
date = self.request.query_params.get("date") | ||
|
@@ -124,6 +143,8 @@ class OrderViewSet(viewsets.ModelViewSet): | |
) | ||
serializer_class = OrderSerializer | ||
pagination_class = OrderPagination | ||
authentication_classes = (TokenAuthentication,) | ||
permission_classes = (IsAdminOrIfAuthenticatedReadOnly,) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
|
||
def get_queryset(self): | ||
return Order.objects.filter(user=self.request.user) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,7 +15,6 @@ | |
# Build paths inside the project like this: BASE_DIR / 'subdir'. | ||
BASE_DIR = Path(__file__).resolve().parent.parent | ||
|
||
|
||
# Quick-start development settings - unsuitable for production | ||
# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/ | ||
|
||
|
@@ -80,7 +79,6 @@ | |
|
||
WSGI_APPLICATION = "cinema_service.wsgi.application" | ||
|
||
|
||
# Database | ||
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases | ||
|
||
|
@@ -91,26 +89,25 @@ | |
} | ||
} | ||
|
||
|
||
# Password validation | ||
# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators | ||
|
||
AUTH_PASSWORD_VALIDATORS = [ | ||
{ | ||
"NAME": "django.contrib.auth.password_validation." | ||
"UserAttributeSimilarityValidator", | ||
"UserAttributeSimilarityValidator", | ||
}, | ||
{ | ||
"NAME": "django.contrib.auth.password_validation." | ||
"MinimumLengthValidator", | ||
"MinimumLengthValidator", | ||
}, | ||
{ | ||
"NAME": "django.contrib.auth.password_validation." | ||
"CommonPasswordValidator", | ||
"CommonPasswordValidator", | ||
}, | ||
{ | ||
"NAME": "django.contrib.auth.password_validation." | ||
"NumericPasswordValidator", | ||
"NumericPasswordValidator", | ||
}, | ||
] | ||
|
||
|
@@ -121,12 +118,11 @@ | |
|
||
LANGUAGE_CODE = "en-us" | ||
|
||
TIME_ZONE = "UTC" | ||
TIME_ZONE = "Europe/Kiev" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
|
||
USE_I18N = True | ||
|
||
USE_TZ = False | ||
|
||
USE_TZ = True | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
|
||
# Static files (CSS, JavaScript, Images) | ||
# https://docs.djangoproject.com/en/4.0/howto/static-files/ | ||
|
@@ -137,3 +133,9 @@ | |
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field | ||
|
||
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" | ||
|
||
REST_FRAMEWORK = { | ||
"DEFAULT_PERMISSION_CLASSES": [ | ||
"rest_framework.permissions.IsAuthenticated", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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")), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The inclusion of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure that the |
||
path("__debug__/", include("debug_toolbar.urls")), | ||
] |
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") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
extra_kwargs = { | ||
"password": {"write_only": True, | ||
"min_length": 5} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
|
||
def create(self, validated_data): | ||
return get_user_model().objects.create_user(**validated_data) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
def update(self, instance, validated_data): | ||
password = validated_data.pop("password", None) | ||
user = super().update(instance, validated_data) | ||
|
||
if password: | ||
user.set_password(password) | ||
user.save() | ||
|
||
return user |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,12 @@ | ||
# write your code here | ||
from django.urls import path | ||
|
||
|
||
from user.views import CreateUserView, CreateTokenView, ManageUserView | ||
|
||
app_name = "user" | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
urlpatterns = [ | ||
path("register/", CreateUserView.as_view(), name="create"), | ||
path("login/", CreateTokenView.as_view(), name="login"), | ||
path("me/", ManageUserView.as_view(), name="manage"), | ||
] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The URL patterns are correctly defined for user registration, login, and management, linking to the appropriate views. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,25 @@ | ||
# write your code here | ||
from rest_framework import generics | ||
from rest_framework.authtoken.views import ObtainAuthToken | ||
from rest_framework.settings import api_settings | ||
from rest_framework.authentication import TokenAuthentication | ||
from rest_framework.permissions import IsAuthenticated | ||
|
||
|
||
from user.serializers import UserSerializer | ||
|
||
|
||
class CreateUserView(generics.CreateAPIView): | ||
serializer_class = UserSerializer | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
|
||
class CreateTokenView(ObtainAuthToken): | ||
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
|
||
class ManageUserView(generics.RetrieveUpdateAPIView): | ||
serializer_class = UserSerializer | ||
authentication_classes = (TokenAuthentication,) | ||
permission_classes = (IsAuthenticated,) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
def get_object(self): | ||
return self.request.user |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The import statement is correct.
SAFE_METHODS
is used to check if the request method is read-only, which is appropriate for this permission class.