@@ -211,6 +211,13 @@ class CustomUserModel(AbstractBaseUser, PermissionsMixin, BaseModel): if self.invite: return self.invite.referer_account + @property + def host(self): + try: + return self.host_account + except ObjectDoesNotExist: + return None + def is_corporate(self): return self.account_type == 'business_host' @@ -1,9 +1,8 @@ +from django.core.exceptions import ObjectDoesNotExist + from authentication.models import ( - BusinessAccount, - BusinessUserHost, CustomUserModel, ) -from authentication.models.choices import AccountPrivileges class AccountStatusSelector: @@ -11,11 +10,13 @@ class AccountStatusSelector: self.user = user def is_business_host(self) -> bool: - return BusinessUserHost.objects.filter(user=self.user).exists() + return bool(self.user.host) def is_business_account(self) -> bool: - return BusinessAccount.objects.filter(user=self.user).exists() + try: + return bool(self.user.business_account) + except ObjectDoesNotExist: + return False def is_admin(self) -> bool: - accounts = BusinessAccount.objects.filter(user=self.user) - return not accounts.exists() or (accounts.first().account_privileges == AccountPrivileges.ADMIN) + return self.user.business_account.account_privileges == 'admin' if self.is_business_account() else False \ No newline at end of file @@ -11,13 +11,10 @@ class BusinessAccountSelector: @classmethod def from_user(cls, user: CustomUserModel, company: BusinessUserHost | None = None): - account = BusinessAccount.objects.filter(user=user) - if company is not None: - account.filter(parent_company=company) - if not account.exists(): + account = getattr(user, 'business_account', None) + if not account or (company is not None and account.parent_company != company): return None - - return cls(account.first()) + return cls(account) @classmethod def filter_by_email(cls, email: str, company: BusinessUserHost | None = None): @@ -99,11 +99,12 @@ class UserSelector: return 'regular' account = BusinessAccountSelector.from_user(self.user) - if account.account_type() == 'admin': + account_type = account.account_type() + if account_type == 'admin': return 'business_admin' - elif account.account_type() == 'regular': + elif account_type == 'regular': return 'business_account' - elif account.account_type() == 'sec': + elif account_type == 'sec': return 'business_security' def check_model_availability(self, model_title: str) -> bool: @@ -0,0 +1,33 @@ +import jwt + +from authentication.models import CustomUserModel + +from django.conf import settings +from django.utils.translation import gettext_lazy as _ + +from rest_framework import exceptions +from rest_framework.authentication import BaseAuthentication + +from uuid import UUID + + +class CustomJWTAuthentication(BaseAuthentication): + def authenticate(self, request): + authorization_header = request.headers.get('Authorization') + if not authorization_header: + return None + try: + access_token = authorization_header.split(' ')[1] + payload = jwt.decode(access_token, settings.SECRET_KEY, algorithms=['HS256']) + except jwt.ExpiredSignatureError: + raise exceptions.AuthenticationFailed(_('Access token is expired')) + except IndexError: + raise exceptions.AuthenticationFailed(_('Token prefix is missing')) + user = CustomUserModel.objects.select_related( + 'payment_plan', + 'business_account', + 'business_account__group', + 'business_account__parent_company__user__payment_plan', + 'host_account' + ).get(uid=UUID(payload['uid'])) + return (user, None) \ No newline at end of file @@ -105,6 +105,7 @@ AUTHENTICATION_BACKENDS = [ REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( + 'authentication.authentication.CustomJWTAuthentication', 'oauth2_provider.contrib.rest_framework.OAuth2Authentication', 'rest_framework_simplejwt.authentication.JWTAuthentication', 'drf_social_oauth2.authentication.SocialAuthentication', @@ -1206,3 +1206,9 @@ msgstr "" #~ msgid "Points" #~ msgstr "Поинты" + +msgid "Access token is expired" +msgstr "Срок действия токена доступа истек" + +msgid "Token prefix is missing" +msgstr "Отсутствует префикс токена"