@@ -9,3 +9,18 @@ class BusinessAccountNotFound(Exception): class AdminReinviteForbidden(Exception): def __str__(self): return _('You cannot reinvite other administrators') + + +class UnconfirmedUserChangePass(Exception): + def __str__(self): + return _('You cannot change the password of an unconfirmed e-mail user.') + + +class SecurityPasswordChangeForbidden(Exception): + def __str__(self): + return _('Security staff cannot change the password of another security staff member') + + +class PasswordChangeRestricted(Exception): + def __str__(self): + return _('You can only change the password for regular employees or security staff members') @@ -11,6 +11,11 @@ class WrongPassword(Exception): return _('Wrong password') +class PasswordsDoNotMatch(Exception): + def __str__(self): + return _("Passwords don't match") + + class EmailNotConfirmed(Exception): def __str__(self): return _('User has not confirmed his email yet') @@ -2,15 +2,19 @@ from decimal import Decimal from typing import Any, OrderedDict, Tuple from django.utils.translation import gettext_lazy as _ -from rest_framework.request import Request +from authentication.exceptions.business_account import ( + PasswordChangeRestricted, + SecurityPasswordChangeForbidden, + UnconfirmedUserChangePass, +) +from authentication.exceptions.user import PasswordsDoNotMatch from authentication.models import ( BusinessAccount, BusinessUserHost, CustomUserModel, ) from authentication.models.choices import InvitationStatus -from authentication.serializers import ChangePasswordSerializer class BusinessAccountService: @@ -92,23 +96,20 @@ class BusinessAccountService: self.account.account_privileges = new_privileges self.account.save() - def update_user_password(self, request: Request): - serializer = ChangePasswordSerializer(data=request.data) - serializer.is_valid(raise_exception=True) + def update_user_password(self, user: CustomUserModel, password_1: str, password_2: str): + if self.account.acceptance_status != InvitationStatus.ACCEPTED: + raise UnconfirmedUserChangePass - if serializer.validated_data['password_1'] != serializer.validated_data['password_2']: - raise Exception(_("Passwords don't match")) + if password_1 != password_2: + raise PasswordsDoNotMatch - if self.account.user.account_type == 'business_security' and request.user.account_type == 'business_security': - raise Exception(_("You do not have sufficient rights to perform this action")) + if self.account.user.account_type == 'business_security' == user.account_type: + raise SecurityPasswordChangeForbidden if self.account.user.account_type not in ('business_account', 'business_security'): - raise Exception(_("You do not have sufficient rights to perform this action")) - - if self.account.acceptance_status != InvitationStatus.ACCEPTED: - raise Exception(_('You cannot change the password of an unconfirmed e-mail user.')) + raise PasswordChangeRestricted - self.account.user.set_password(serializer.validated_data['password_1']) + self.account.user.set_password(password_1) self.account.user.save() def update_status(self, status: Tuple[str, Any]): @@ -91,7 +91,7 @@ urlpatterns = [ path('business-host/logs/', views.LogsAPIView.as_view()), path( 'business-host/account/change-pass/', - views.ChangeHostPassAPIView.as_view(), + views.ChangeBusinessAccountPassAPIView.as_view(), name='change_host_pass', ), path( @@ -393,7 +393,7 @@ class HostWorkersAPIView(APIView): return Response({'detail': f'{err}'}, status=status.HTTP_400_BAD_REQUEST) -class ChangeHostPassAPIView(APIView): +class ChangeBusinessAccountPassAPIView(APIView): permission_classes = (ChangeEmployeePassPermission,) @extend_schema( @@ -402,15 +402,22 @@ class ChangeHostPassAPIView(APIView): ], request=ChangePasswordSerializer, ) - def patch(self, request, *args, **kwargs): + def patch(self, request, email: str, *args, **kwargs): """Change business account password""" try: + serializer = ChangePasswordSerializer(data=request.data) + serializer.is_valid(raise_exception=True) + data = serializer.validated_data business_account = BusinessAccountSelector.filter_by_email( - request.parser_context['kwargs'].get('email'), + email, BusinessAccountService.get_company_name(self.request.user), ) - BusinessAccountService(business_account).update_user_password(request) - return Response({'detail': 'Host password has been updated'}, status=status.HTTP_200_OK) + if not business_account: + return Response({'detail': _('Business account not found')}, status=status.HTTP_404_NOT_FOUND) + BusinessAccountService(business_account).update_user_password( + request.user, data['password_1'], data['password_2'] + ) + return Response({'detail': _('Business account password has been updated')}, status=status.HTTP_200_OK) except Exception as exc: return Response({'detail': f'{exc}'}, status=status.HTTP_400_BAD_REQUEST) @@ -28,6 +28,14 @@ msgstr "Сотрудник не найден" msgid "You cannot reinvite other administrators" msgstr "Вы не можете повторно приглашать администраторов" +#: authentication/exceptions/business_account.py:20 +msgid "Security staff cannot change the password of another security staff member" +msgstr "Сотрудники безопасности не могут изменять пароль другого сотрудника безопасности" + +#: authentication/exceptions/business_account.py:25 +msgid "You can only change the password for regular employees or security staff members" +msgstr "Вы можете изменять пароль только обычным сотрудникам или сотрудникам безопасности" + #: authentication/exceptions/business_host_exceptions/access_denied.py:6 #: authentication/services/business_account_service.py:103 #: authentication/services/business_account_service.py:106 @@ -506,9 +514,7 @@ msgstr "Бизнес-аккаунт для данного юзера не най msgid "Invited account can either accept or reject an invitation" msgstr "Приглашенный аккаунт может принять или отклонить приглашение" -#: authentication/services/business_account_service.py:100 -#, fuzzy -#| msgid "Passwords do not match" +#: authentication/exceptions/user.py:16 msgid "Passwords don't match" msgstr "Пароли не совпадают" @@ -561,6 +567,10 @@ msgstr "Сотрудник успешно удален" msgid "Business account has been reinvited" msgstr "Повторное приглашение сотруднику успешно отправлено" +#: authentication/views.py:420 +msgid "Business account password has been updated" +msgstr "Пароль сотрудника успешно обновлен" + #: authentication/views.py:460 msgid "Could not confirm email, please try again." msgstr "Невозможно подтвердить email, попробуйте позже"