From c17768c5c15ac015c64dbc603177a8e64ecbd676 Mon Sep 17 00:00:00 2001 From: Nemykin_Eu Date: Tue, 4 May 2021 08:48:03 +0300 Subject: [PATCH] First review: Fixed mistakes --- api/admin.py | 2 +- api/models.py | 2 +- api/permissions.py | 2 +- api/serializers.py | 2 +- api/urls.py | 2 +- api/validators.py | 2 +- api/views.py | 2 +- api_users_auth/backends.py | 2 +- api_users_auth/models.py | 10 +++---- api_users_auth/permissions.py | 41 +--------------------------- api_users_auth/serializers.py | 17 +++++++----- api_users_auth/urls.py | 29 ++++++++++++-------- api_users_auth/views.py | 50 ++++++++++++++++------------------- api_yamdb/settings.py | 12 +++------ api_yamdb/urls.py | 15 +++++++---- titles/filters.py | 2 +- titles/serializers.py | 2 +- titles/urls.py | 2 +- titles/views.py | 3 --- 19 files changed, 81 insertions(+), 118 deletions(-) diff --git a/api/admin.py b/api/admin.py index 34ef61e..8c38f3f 100644 --- a/api/admin.py +++ b/api/admin.py @@ -1,3 +1,3 @@ from django.contrib import admin -# Register your models here. \ No newline at end of file +# Register your models here. diff --git a/api/models.py b/api/models.py index e9cc8a0..5c23bd1 100644 --- a/api/models.py +++ b/api/models.py @@ -77,4 +77,4 @@ class Meta: ordering = ('-pub_date',) def __str__(self): - return self.text \ No newline at end of file + return self.text diff --git a/api/permissions.py b/api/permissions.py index 9e9d172..388b719 100644 --- a/api/permissions.py +++ b/api/permissions.py @@ -17,4 +17,4 @@ def has_object_permission(self, request, view, obj): or request.user.role == CustomUser.ROLE_MODERATOR ) - return request.method in permissions.SAFE_METHODS \ No newline at end of file + return request.method in permissions.SAFE_METHODS diff --git a/api/serializers.py b/api/serializers.py index 30d45bd..2b7bc34 100644 --- a/api/serializers.py +++ b/api/serializers.py @@ -28,4 +28,4 @@ class CommentSerializer(serializers.ModelSerializer): class Meta: fields = ('id', 'text', 'author', 'pub_date') - model = Comment \ No newline at end of file + model = Comment diff --git a/api/urls.py b/api/urls.py index eb64f34..d194192 100644 --- a/api/urls.py +++ b/api/urls.py @@ -18,4 +18,4 @@ urlpatterns = [ path('v1/', include(router.urls)), -] \ No newline at end of file +] diff --git a/api/validators.py b/api/validators.py index 424f2a7..7b9a597 100644 --- a/api/validators.py +++ b/api/validators.py @@ -4,4 +4,4 @@ def score_validator(value): if not 1 <= value <= 10: params = {'value': value, } - raise ValidationError('Оценка может быть от 1 до 10', params=params) \ No newline at end of file + raise ValidationError('Оценка может быть от 1 до 10', params=params) diff --git a/api/views.py b/api/views.py index b74e736..390e474 100644 --- a/api/views.py +++ b/api/views.py @@ -37,4 +37,4 @@ def perform_create(self, serializer): def get_queryset(self): review = get_object_or_404(Review, pk=self.kwargs.get('review_id')) - return review.comments.all() \ No newline at end of file + return review.comments.all() diff --git a/api_users_auth/backends.py b/api_users_auth/backends.py index 4d9c25f..78cc71a 100644 --- a/api_users_auth/backends.py +++ b/api_users_auth/backends.py @@ -12,7 +12,7 @@ def authenticate(self, request, username=None, password=None, **kwargs): if user.check_password(password): return user return None - + def get_user(self, user_id): try: return CustomUser.objects.get(pk=user_id) diff --git a/api_users_auth/models.py b/api_users_auth/models.py index f749d43..74993b2 100644 --- a/api_users_auth/models.py +++ b/api_users_auth/models.py @@ -1,10 +1,10 @@ from django.contrib.auth.models import AbstractUser from django.db import models -from rest_framework import permissions + class CustomUser(AbstractUser): USERNAME_FIELD = 'email' - REQUIRED_FIELDS = ['username',] + REQUIRED_FIELDS = ['username', ] ROLE_USER = 'user' ROLE_MODERATOR = 'moderator' ROLE_ADMIN = 'admin' @@ -17,7 +17,7 @@ class CustomUser(AbstractUser): choices=USERS_ROLE, max_length=10, verbose_name='Роль пользователя', - default='user' + default=ROLE_USER ) email = models.EmailField('e-mail', unique=True, blank=False) bio = models.TextField( @@ -25,7 +25,6 @@ class CustomUser(AbstractUser): blank=True, null=True, ) - confirmation_code = models.TextField(null=True, default='') @property def is_admin(self): @@ -42,9 +41,6 @@ class Meta: ordering = ['id'] - - - class ConfirmationCode(models.Model): confirmation_code = models.CharField(max_length=32) email = models.EmailField(max_length=254, unique=True) diff --git a/api_users_auth/permissions.py b/api_users_auth/permissions.py index f06c355..059f05c 100644 --- a/api_users_auth/permissions.py +++ b/api_users_auth/permissions.py @@ -1,24 +1,5 @@ from rest_framework import permissions -from .models import CustomUser - - -class IsAuthorOrStaffOrReadOnly(permissions.BasePermission): - def has_object_permission(self, request, view, obj): - return (request.method in permissions.SAFE_METHODS - or obj.author == request.user - or request.user.is_admin - or request.user.is_moderator) -""" - -class IsAdminOrReadOnly(permissions.BasePermission): - def has_permission(self, request, view): - return (request.method in permissions.SAFE_METHODS - or request.user.is_authenticated - and request.user.is_admin - or request.user.is_superuser - ) -""" class IsSuperuser(permissions.BasePermission): @@ -31,24 +12,4 @@ class IsAdminRole(permissions.BasePermission): def has_permission(self, request, view): if request.user.is_anonymous: return request.user.is_staff - return (request.user.is_superuser - or request.user.is_admin - ) - -""" - def has_object_permission(self, request, view, obj): - return request.user.is_authenticated and request.user.is_admin - - def has_permission(self, request, view): - return request.user.is_authenticated and request.user.is_admin - - def has_delete_permission(self, request): - if request.user.is_admin: - return False - - def has_object_permission(self, request, view, obj): - return ( - request.method in permissions.SAFE_METHODS - or obj.author == request.user - ) -""" \ No newline at end of file + return (request.user.is_superuser or request.user.is_admin) diff --git a/api_users_auth/serializers.py b/api_users_auth/serializers.py index cd15d38..98be7d8 100644 --- a/api_users_auth/serializers.py +++ b/api_users_auth/serializers.py @@ -8,23 +8,28 @@ class CustomUserSerializer(serializers.ModelSerializer): username = serializers.CharField( required=True, - validators=[validators.UniqueValidator(queryset=CustomUser.objects.all())] + validators=[validators.UniqueValidator( + queryset=CustomUser.objects.all() + )] ) class Meta: - fields = ['first_name', 'last_name', 'username', 'bio', 'email', 'role'] + fields = [ + 'first_name', 'last_name', 'username', 'bio', 'email', 'role' + ] model = CustomUser -class MyTokenObtainPairSerializer(TokenObtainPairSerializer): +class TokenObtainPairSerializer(TokenObtainPairSerializer): username_field = CustomUser.email def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.fields['password'].required = False + self.fields['password'].required = False def validate(self, attrs): - attrs['password'] = self.context['request'].data.get('confirmation_code') + password = self.context['request'].data.get('confirmation_code') + attrs['password'] = password return super().validate(attrs) @@ -39,7 +44,7 @@ class ConfirmationCodeSerializer(serializers.Serializer): many=False, read_only=True ) - code_date = serializers.DateTimeField() + code_date = serializers.DateTimeField() class Meta: fields = '__all__' diff --git a/api_users_auth/urls.py b/api_users_auth/urls.py index baf66a3..21562b0 100644 --- a/api_users_auth/urls.py +++ b/api_users_auth/urls.py @@ -4,18 +4,25 @@ from .views import UserViewSet, MyTokenObtainPairView, get_confirmation_code -API_VER = 'v1' - -router = DefaultRouter() -router.register(r'users', UserViewSet, basename='users') +router_v1 = DefaultRouter() +router_v1.register(r'users', UserViewSet, basename='users') urlpatterns = [ - path(f'{API_VER}/', include(router.urls)), - path(f'{API_VER}/auth/email/', get_confirmation_code, name='get_confirmation_code'), - path(f'{API_VER}/auth/token/', - MyTokenObtainPairView.as_view(), - name='token_obtain_pair' - ), - path('{API_VER}/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'), + path('v1/', include(router_v1.urls)), + path( + 'v1/auth/email/', + get_confirmation_code, + name='get_confirmation_code' + ), + path( + 'v1/auth/token/', + MyTokenObtainPairView.as_view(), + name='token_obtain_pair' + ), + path( + 'v1/token/refresh/', + TokenRefreshView.as_view(), + name='token_refresh' + ), ] diff --git a/api_users_auth/views.py b/api_users_auth/views.py index aeb843b..184f42e 100644 --- a/api_users_auth/views.py +++ b/api_users_auth/views.py @@ -2,18 +2,18 @@ from django.core.mail import send_mail from django.http import HttpResponse -from django.shortcuts import get_object_or_404 from django_filters.rest_framework import DjangoFilterBackend -from rest_framework import serializers, status, viewsets +from rest_framework import viewsets from rest_framework.decorators import api_view, action from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework_simplejwt.views import TokenObtainPairView +from api_yamdb.settings import ADMIN_EMAIL from .models import ConfirmationCode, CustomUser -from .permissions import IsAdminRole, IsAuthorOrStaffOrReadOnly, IsSuperuser +from .permissions import IsAdminRole, IsSuperuser from .serializers import (ConfirmationCodeSerializer, CustomUserSerializer, - MyTokenObtainPairSerializer) + TokenObtainPairSerializer) class HttpResponseUnauthorized(HttpResponse): @@ -30,9 +30,9 @@ class UserViewSet(viewsets.ModelViewSet): lookup_field = 'username' @action(detail=False, - methods=['GET', 'PATCH'], - permission_classes = (IsAuthenticated,) - ) + methods=['GET', 'PATCH'], + permission_classes=(IsAuthenticated,) + ) def me(self, request): user = self.request.user serializer = self.get_serializer( @@ -46,30 +46,26 @@ def me(self, request): class MyTokenObtainPairView(TokenObtainPairView): - serializer_class = MyTokenObtainPairSerializer + serializer_class = TokenObtainPairSerializer @api_view(['POST']) def get_confirmation_code(request): - print('request:', request) serializer = ConfirmationCodeSerializer(data=request.data) - print('serializer = ', serializer) - if not serializer.is_valid(): - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + serializer.is_valid(raise_exception=True) user_email = serializer.validated_data['email'] - #user = CustomUser.objects.get_or_create(username='username', user_email='email') confirmation_code = str(uuid.uuid4()) - if confirmation_code is not None: - send_mail( - 'Your confirmation code', - confirmation_code, - 'nemykin.eu@yandex.ru', - [user_email], - fail_silently=False, - ) - ConfirmationCode.objects.create( - email=user_email, - confirmation_code=confirmation_code - ) - return HttpResponse(f'Confirmation code was sent to your email') - return HttpResponseUnauthorized() + if confirmation_code is None: + return HttpResponseUnauthorized() + send_mail( + 'Your confirmation code', + confirmation_code, + ADMIN_EMAIL, + [user_email], + fail_silently=False, + ) + ConfirmationCode.objects.create( + email=user_email, + confirmation_code=confirmation_code + ) + return HttpResponse('Confirmation code was sent to your email') diff --git a/api_yamdb/settings.py b/api_yamdb/settings.py index 8cd54ac..2dd08cc 100644 --- a/api_yamdb/settings.py +++ b/api_yamdb/settings.py @@ -128,22 +128,18 @@ # Добавлено EugeneN AUTH_USER_MODEL = 'api_users_auth.CustomUser' -# Добавлено EugeneN -#AUTHENTICATION_BACKENDS = ['core.authentication.EmailBackend'] - AUTHENTICATION_BACKENDS = [ - #'core.authentication.Emailbackend', 'django.core.mail.backends.console.EmailBackend', - #'api_users_auth.backends.EmailBackend' - #'django.contrib.auth.backends.ModelBackend', ] # Добавлено EugeneN # подключаем движок filebased.EmailBackend -EMAIL_BACKEND = "django.core.mail.backends.filebased.EmailBackend" +EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend' + +ADMIN_EMAIL = 'nemykin.eu@yandex.ru' # указываем директорию, в которую будут складываться файлы писем -EMAIL_FILE_PATH = os.path.join(BASE_DIR, "sent_emails") +EMAIL_FILE_PATH = os.path.join(BASE_DIR, 'sent_emails') REST_AUTH_SERIALIZERS = { 'USER_DETAILS_SERIALIZER': 'api_users_auth.serializers.CustomUserSerializer', diff --git a/api_yamdb/urls.py b/api_yamdb/urls.py index b9d7255..5a712f5 100644 --- a/api_yamdb/urls.py +++ b/api_yamdb/urls.py @@ -4,9 +4,6 @@ from rest_framework_simplejwt.views import (TokenObtainPairView, TokenRefreshView) -#from allauth.account.views import confirm_email -#from django.conf.urls import url - urlpatterns = [ path('admin/', admin.site.urls), @@ -16,8 +13,16 @@ TemplateView.as_view(template_name='redoc.html'), name='redoc' ), - path('api/v1/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'), - path('api/v1/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'), + path( + 'api/v1/token/', + TokenObtainPairView.as_view(), + name='token_obtain_pair' + ), + path( + 'api/v1/token/refresh/', + TokenRefreshView.as_view(), + name='token_refresh' + ), path('api/', include('api.urls')), path('api/', include('titles.urls')), ] diff --git a/titles/filters.py b/titles/filters.py index f6061b6..2e51dde 100644 --- a/titles/filters.py +++ b/titles/filters.py @@ -16,4 +16,4 @@ class TitleFilter(filters.FilterSet): class Meta: model = Title - fields = ['name', 'category', 'genre', 'year'] \ No newline at end of file + fields = ['name', 'category', 'genre', 'year'] diff --git a/titles/serializers.py b/titles/serializers.py index 439ebb0..5b42f62 100644 --- a/titles/serializers.py +++ b/titles/serializers.py @@ -26,4 +26,4 @@ class TitleSerializer(serializers.ModelSerializer): class Meta: model = Title - fields = ('id', 'name', 'year', 'description', 'genre', 'category',) \ No newline at end of file + fields = ('id', 'name', 'year', 'description', 'genre', 'category',) diff --git a/titles/urls.py b/titles/urls.py index 88af8d1..cc834e4 100644 --- a/titles/urls.py +++ b/titles/urls.py @@ -10,4 +10,4 @@ urlpatterns = [ path('v1/', include(router_v1.urls)) -] \ No newline at end of file +] diff --git a/titles/views.py b/titles/views.py index 889f175..9e3ba8f 100644 --- a/titles/views.py +++ b/titles/views.py @@ -1,5 +1,3 @@ -from django.db.models import query -from django.shortcuts import get_object_or_404 from django_filters.rest_framework import DjangoFilterBackend from rest_framework import filters, viewsets from rest_framework.pagination import PageNumberPagination @@ -31,4 +29,3 @@ class TitleViewSet(viewsets.ModelViewSet): pagination_class = PageNumberPagination filter_backends = [DjangoFilterBackend] filterset_class = TitleFilter - \ No newline at end of file