@@ -12,6 +12,6 @@ router = Router(auth=AsyncAuthBearer(), tags=['auth']) async def get_user_data(request): """Get user details.""" try: - return await UserSelector.detail(user=request.auth) + return await UserSelector.detail(user=request.auth, provider=request.provider) except Exception as exc: - raise HttpError(401, f'{exc}') + raise HttpError(400, f'{exc}') @@ -3,6 +3,7 @@ from uuid import UUID from asgiref.sync import sync_to_async from django.db.models import Prefetch +from django.utils import timezone from django.utils.translation import gettext_lazy as _ from rest_framework_simplejwt.token_blacklist.models import OutstandingToken from rest_framework_simplejwt.tokens import RefreshToken @@ -42,7 +43,7 @@ class UserSelector: return users @classmethod - async def detail(cls, user: CustomUserModel) -> UserDetailSerializer | CustomUserModel: + async def detail(cls, user: CustomUserModel, provider: str) -> UserDetailSerializer | CustomUserModel: # TODO: refactor this hook if user.account_type in ( 'business_account', @@ -54,8 +55,11 @@ class UserSelector: user.payment_plan.current_token_balance = 0 user.payment_plan.plan = user.business_account.parent_company.user.payment_plan.plan refresh_token = await OutstandingToken.objects.filter(user=user).order_by('-created_at').afirst() - access_token = await sync_to_async(lambda: RefreshToken(token=refresh_token.token).access_token)() - user.token = {'access': str(access_token), 'refresh': str(refresh_token.token)} + if not refresh_token or refresh_token.expires_at < timezone.now() and provider == 'yandex': + access_token = await sync_to_async(lambda: RefreshToken.for_user(user))() + else: + access_token = await sync_to_async(lambda: RefreshToken(token=refresh_token.token).access_token)() + user.token = {'access': str(access_token), 'refresh': str(access_token.token)} return user def list_social_accounts(self, serialize: bool = False): @@ -69,6 +69,7 @@ class AsyncAuthBearer(HttpBearer): async def authenticate(self, request: HttpRequest, token: str) -> Any | None: try: user_payload = await TokenService.decode(token=token) + request.provider = 'air' return await CustomUserModel.objects.select_related( 'payment_plan', 'payment_plan__plan', @@ -86,7 +87,21 @@ class AsyncAuthBearer(HttpBearer): ) except InvalidToken: try: - access = await AccessToken.objects.prefetch_related('user').aget(token=token) + access = await AccessToken.objects.prefetch_related( + 'user', + 'user__payment_plan', + 'user__payment_plan__plan', + 'user__business_account', + 'user__business_account__group', + 'user__business_account__parent_company__user__payment_plan', + 'user__business_account__parent_company__user__payment_plan__plan', + 'user__host_account' + ).prefetch_related( + 'user__payment_plan__plan__accessed_models', + 'user__business_account__parent_company__user__payment_plan__plan__accessed_models', + 'user__social_auth' + ).aget(token=token) + request.provider = 'yandex' return access.user except AccessToken.DoesNotExist: raise HttpError(401, _('Access token expired or does not exist'))