@@ -16,9 +16,29 @@ class UnconfirmedUserChangePass(Exception): return _('You cannot change the password of an unconfirmed e-mail user.') -class SecurityPasswordChangeForbidden(Exception): +class AdminPasswordChangeForbidden(Exception): def __str__(self): - return _('Security staff cannot change the password of another security staff member') + return _('Admin staff cannot change the password of another admin staff member') + + +class AdminUpdateForbidden(Exception): + def __str__(self): + return _('Admin staff cannot update other admin staff members') + + +class AdminCreateForbidden(Exception): + def __str__(self): + return _('Admin staff cannot create other admin staff members') + + +class AdminDeleteForbidden(Exception): + def __str__(self): + return _('Admin staff cannot delete other admin staff members') + + +class AdminPromoteForbidden(Exception): + def __str__(self): + return _('Admin staff cannot promote other staff members to admin') class PasswordChangeRestricted(Exception): @@ -3,8 +3,8 @@ from typing import Any, OrderedDict, Tuple from django.utils.translation import gettext_lazy as _ from authentication.exceptions.business_account import ( + AdminPasswordChangeForbidden, PasswordChangeRestricted, - SecurityPasswordChangeForbidden, UnconfirmedUserChangePass, ) from authentication.exceptions.user import PasswordsDoNotMatch @@ -85,11 +85,8 @@ class BusinessAccountService: if password_1 != password_2: raise PasswordsDoNotMatch - 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 PasswordChangeRestricted + if self.account.user.account_type == 'business_admin' == user.account_type: + raise AdminPasswordChangeForbidden self.account.user.set_password(password_1) self.account.user.save() @@ -6,7 +6,11 @@ from rest_framework.request import Request from authentication.exceptions import business_host_exceptions from authentication.exceptions.business_account import ( + AdminCreateForbidden, + AdminDeleteForbidden, + AdminPromoteForbidden, AdminReinviteForbidden, + AdminUpdateForbidden, BusinessAccountNotFound, ) from authentication.exceptions.business_host_exceptions import AlreadyAccount, InviteeHasPlan @@ -69,6 +73,8 @@ class BusinessHostService: def create_existing(self, email: str, account_privileges: str, group: UUID | None = None) -> BusinessAccountService: company = self.user.host or self.user.employee.parent_company + if self.user.account_type == 'business_admin' and account_privileges == 'admin': + raise AdminCreateForbidden try: user = UserSelector.get_by_email(email.lower()) if user.host: @@ -112,6 +118,13 @@ class BusinessHostService: business_account = UserSelector.get_by_email(email).employee if not business_account: raise BusinessAccountNotFound + + if business_account.user.account_type == 'business_admin' == self.user.account_type: + raise AdminUpdateForbidden + + if self.user.account_type == 'business_admin' and privileges == 'admin': + raise AdminPromoteForbidden + company = self.user.host or self.user.employee.parent_company if business_account.parent_company != company: raise AlreadyAccount @@ -150,6 +163,9 @@ class BusinessHostService: if not account: raise BusinessAccountNotFound + if self.user.account_type == 'business_admin' == account.user.account_type: + raise AdminDeleteForbidden + account.delete() def create_host(self, request: Request) -> UserDataSerializer: @@ -61,10 +61,3 @@ class HasBusinessAdminPermissions(BasePermission): elif b_acc := user.employee: return b_acc.account_privileges == AccountPrivileges.ADMIN return False - - -class ChangeEmployeePassPermission(BasePermission): - def has_permission(self, request, view): - if request.user.is_anonymous: - return False - return request.user.account_type in ('business_host', 'business_admin', 'business_security') @@ -28,7 +28,15 @@ from authentication.exceptions.business_host_exceptions import ( AlreadyHost, InviteeHasPlan, ) -from authentication.exceptions.business_account import AdminReinviteForbidden, BusinessAccountNotFound +from authentication.exceptions.business_account import ( + AdminCreateForbidden, + AdminDeleteForbidden, + AdminPasswordChangeForbidden, + AdminReinviteForbidden, + AdminUpdateForbidden, + BusinessAccountNotFound, + UnconfirmedUserChangePass, +) from authentication.exceptions.business_host_exceptions.not_allowed_ip import ( NotAllowedIP, ) @@ -38,6 +46,7 @@ from authentication.exceptions.email_token import EmailTokenNotFound from authentication.exceptions.user import ( DomainNotFound, EmailNotConfirmed, + PasswordsDoNotMatch, UserAlreadyExists, WrongEmail, WrongPassword, @@ -52,7 +61,6 @@ from authentication.permissions import ( IsBusinessSecurity, IsTelegramAirBot, IsVKMiniApp, - ChangeEmployeePassPermission, ) from authentication.selectors.business_account_selector import BusinessAccountSelector from authentication.selectors.business_host_selector import ( @@ -304,6 +312,8 @@ class BusinessHostAPIView(APIView): return Response(result.data, status=status.HTTP_201_CREATED) except (AlreadyAccount, AlreadyHost, AlreadyHasPlan, InviteeHasPlan) as err: return Response({'detail': str(err)}, status=status.HTTP_400_BAD_REQUEST) + except AdminCreateForbidden as err: + return Response({'detail': str(err)}, status=status.HTTP_403_FORBIDDEN) except Exception as err: return Response({'detail': f'{err}'}, status=status.HTTP_400_BAD_REQUEST) @@ -328,6 +338,8 @@ class BusinessHostAPIView(APIView): return Response({'detail': _('Business account has been deleted')}, status=status.HTTP_200_OK) except BusinessAccountNotFound as exc: return Response({'detail': str(exc)}, status=status.HTTP_400_BAD_REQUEST) + except AdminDeleteForbidden as exc: + return Response({'detail': str(exc)}, status=status.HTTP_403_FORBIDDEN) except Exception as exc: logger.exception(exc) return Response( @@ -398,7 +410,7 @@ class HostWorkersAPIView(APIView): class ChangeBusinessAccountPassAPIView(APIView): - permission_classes = (ChangeEmployeePassPermission,) + permission_classes = (HasBusinessAdminPermissions,) @extend_schema( parameters=[ @@ -417,11 +429,13 @@ class ChangeBusinessAccountPassAPIView(APIView): BusinessAccountService.get_company_name(self.request.user), ) if not business_account: - return Response({'detail': _('Business account not found')}, status=status.HTTP_404_NOT_FOUND) + return Response({'detail': _('Business account not found')}, status=status.HTTP_400_BAD_REQUEST) 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 (UnconfirmedUserChangePass, PasswordsDoNotMatch, AdminPasswordChangeForbidden) as exc: + return Response({'detail': str(exc)}, status=status.HTTP_403_FORBIDDEN) except Exception as exc: return Response({'detail': f'{exc}'}, status=status.HTTP_400_BAD_REQUEST) @@ -642,6 +656,10 @@ class HostInvitationAPIView(APIView): employee, context={'account_type': employee.user.account_type} ) return Response(result.data, status=status.HTTP_200_OK) + except (AlreadyAccount, BusinessAccountNotFound) as exc: + return Response({'detail': str(exc)}, status=status.HTTP_400_BAD_REQUEST) + except AdminUpdateForbidden as exc: + return Response({'detail': str(exc)}, status=status.HTTP_403_FORBIDDEN) except Exception as exc: return Response({'detail': f'{exc}'}, status=status.HTTP_400_BAD_REQUEST) @@ -34,13 +34,36 @@ msgstr "Вы не можете изменить пароль неподтвер #: authentication/exceptions/business_account.py:21 msgid "" -"Security staff cannot change the password of another security staff member" +"Admin staff cannot change the password of another admin staff member" msgstr "" -"Сотрудники безопасности не могут изменять пароль другого сотрудника " -"безопасности" +"Администраторы не могут изменять пароль другого администратора" #: authentication/exceptions/business_account.py:26 msgid "" +"Admin staff cannot update other admin staff members" +msgstr "" +"Администраторы не могут обновлять других администраторов" + +#: authentication/exceptions/business_account.py:31 +msgid "" +"Admin staff cannot create other admin staff members" +msgstr "" +"Администраторы не могут создавать других администраторов" + +#: authentication/exceptions/business_account.py:36 +msgid "" +"Admin staff cannot delete other admin staff members" +msgstr "" +"Администраторы не могут удалять других администраторов" + +#: authentication/exceptions/business_account.py:41 +msgid "" +"Admin staff cannot promote other staff members to admin" +msgstr "" +"Администраторы не могут повышать других сотрудников до администраторов" + +#: authentication/exceptions/business_account.py:46 +msgid "" "You can only change the password for regular employees or security staff " "members" msgstr ""