diff --git a/backend/api/mixins.py b/backend/api/mixins.py index f141134..203fdb7 100644 --- a/backend/api/mixins.py +++ b/backend/api/mixins.py @@ -4,6 +4,8 @@ from projects.models import Organization, Volunteer +from .utils import modify_errors + class DestroyUserMixin: """ @@ -34,16 +36,14 @@ def is_valid(self, *, raise_exception=False): try: super().is_valid(raise_exception=True) except ValidationError as error: - keys = error.detail.keys() - modified_errors = {} - for key in keys: - if isinstance(error.detail.get(key), dict): - modified_errors.update(error.detail.get(key)) - else: - modified_errors[key] = error.detail.get(key) + errors_db, errors_valid = modify_errors( + error.get_full_details(), {} + ) + errors_db.update({'ValidationErrors': errors_valid}) raise ValidationError( { - self.__class__.__name__: modified_errors + self.__class__.__name__: + errors_db } ) return bool(self._errors) diff --git a/backend/api/utils.py b/backend/api/utils.py index 54f5108..bd243c9 100644 --- a/backend/api/utils.py +++ b/backend/api/utils.py @@ -49,3 +49,30 @@ def to_internal_value(self, data): if value in [None, ""]: raise ValidationError("Поле c изображением не может быть пустым.") return value + + +def modify_errors(details, errors_valid): + keys = details.keys() + errors_db = {} + for key in keys: + if isinstance(details.get(key), dict): + inner_details, inner_valid = modify_errors( + details.get(key), errors_valid) + for key_in in inner_details.keys(): + errors_db.setdefault( + key_in, + [] + ).append(inner_details.get(key_in)[0]) + else: + for i in range(len(details.get(key))): + if details.get(key)[i]['code'] in ['unique', 'not_exist']: + errors_db.setdefault( + key, + [] + ).append(str(details.get(key)[i].get('message'))) + else: + errors_valid.setdefault( + key, + [] + ).append(str(details.get(key)[i].get('message'))) + return errors_db, errors_valid diff --git a/backend/backend/settings.py b/backend/backend/settings.py index 20701f8..3ef2cc3 100644 --- a/backend/backend/settings.py +++ b/backend/backend/settings.py @@ -198,6 +198,7 @@ 'SERIALIZERS': { 'current_user': 'api.serializers.CurrentUserSerializer', 'token_create': 'users.auth.serializers.CustomTokenCreateSerializer', + 'password_reset': 'users.auth.serializers.CustomSendEmailResetSerializer', }, } @@ -232,8 +233,9 @@ 'JSON_EDITOR': True, 'SHOW_REQUEST_HEADERS': True, 'DEFAULT_MODEL_RENDERING': 'model', # Отображение моделей (model, example) - 'DEFAULT_MODEL_DEPTH': 2, # Глубина отображения моделей (-1 - без ограничений) - 'DOC_EXPANSION': 'list', # full, none + # Глубина отображения моделей (-1 - без ограничений) + 'DEFAULT_MODEL_DEPTH': 2, + 'DOC_EXPANSION': 'list', # full, none 'OPERATIONS_SORTER': 'alpha', # Сортировка операций (alpha, method) 'TAGS_SORTER': 'alpha', # Сортировка тегов (alpha, order) } diff --git a/backend/users/auth/serializers.py b/backend/users/auth/serializers.py index bafdff9..dd06d1e 100644 --- a/backend/users/auth/serializers.py +++ b/backend/users/auth/serializers.py @@ -1,6 +1,7 @@ + from django.contrib.auth import authenticate, get_user_model from djoser.conf import settings -from djoser.serializers import TokenCreateSerializer +from djoser.serializers import SendEmailResetSerializer, TokenCreateSerializer from rest_framework.validators import ValidationError from api.mixins import IsValidModifyErrorForFrontendMixin @@ -28,7 +29,7 @@ def validate(self, attrs): settings.LOGIN_FIELD: [self.default_error_messages.get('missing_account')] } - }, + }, code='not_exist' ) elif not self.user.check_password(password): raise ValidationError( @@ -37,7 +38,7 @@ def validate(self, attrs): 'password': [self.default_error_messages.get('wrong_password')] } - }, + }, code='invalid' ) self.user = authenticate( request=self.context.get('request'), **params, password=password @@ -50,5 +51,34 @@ def validate(self, attrs): 'not_active': [self.default_error_messages.get('inactive_account')] } - }, + }, code='invalid' ) + + +class CustomSendEmailResetSerializer(IsValidModifyErrorForFrontendMixin, + SendEmailResetSerializer): + + def get_user(self, is_active=True): + try: + user = User._default_manager.get( + is_active=is_active, + **{self.email_field: self.data.get(self.email_field, "")}, + ) + if user.has_usable_password(): + return user + except User.DoesNotExist: + pass + if ( + settings.PASSWORD_RESET_SHOW_EMAIL_NOT_FOUND + or settings.USERNAME_RESET_SHOW_EMAIL_NOT_FOUND + ): + class_name = self.__class__.__name__ + raise ValidationError( + { + class_name: { + settings.LOGIN_FIELD: + [self.default_error_messages.get('email_not_found')], + 'ValidationErrors': {} + }, + } + )