refactor-upto-phase 6

This commit is contained in:
alorig
2025-11-20 21:29:14 +05:00
parent 8b798ed191
commit b0409d965b
14 changed files with 478 additions and 314 deletions

View File

@@ -4,6 +4,7 @@ Extracts account from JWT token and injects into request context
"""
from django.utils.deprecation import MiddlewareMixin
from django.http import JsonResponse
from django.contrib.auth import logout
from rest_framework import status
try:
@@ -41,14 +42,19 @@ class AccountContextMiddleware(MiddlewareMixin):
request.user = user
# Get account from refreshed user
user_account = getattr(user, 'account', None)
if user_account:
request.account = user_account
return None
validation_error = self._validate_account_and_plan(request, user)
if validation_error:
return validation_error
request.account = getattr(user, 'account', None)
return None
except (AttributeError, UserModel.DoesNotExist, Exception):
# If refresh fails, fallback to cached account
try:
user_account = getattr(request.user, 'account', None)
if user_account:
validation_error = self._validate_account_and_plan(request, request.user)
if validation_error:
return validation_error
request.account = user_account
return None
except (AttributeError, Exception):
@@ -96,6 +102,9 @@ class AccountContextMiddleware(MiddlewareMixin):
# Get user from DB (but don't set request.user - let DRF authentication handle that)
# Only set request.account for account context
user = User.objects.select_related('account', 'account__plan').get(id=user_id)
validation_error = self._validate_account_and_plan(request, user)
if validation_error:
return validation_error
if account_id:
# Verify account still exists
try:
@@ -119,4 +128,47 @@ class AccountContextMiddleware(MiddlewareMixin):
request.account = None
return None
def _validate_account_and_plan(self, request, user):
"""
Ensure the authenticated user has an account and an active plan.
If not, logout the user (for session auth) and block the request.
"""
try:
account = getattr(user, 'account', None)
except Exception:
account = None
if not account:
return self._deny_request(
request,
error='Account not configured for this user. Please contact support.',
status_code=status.HTTP_403_FORBIDDEN,
)
plan = getattr(account, 'plan', None)
if plan is None or getattr(plan, 'is_active', False) is False:
return self._deny_request(
request,
error='Active subscription required. Visit igny8.com/pricing to subscribe.',
status_code=status.HTTP_402_PAYMENT_REQUIRED,
)
return None
def _deny_request(self, request, error, status_code):
"""Logout session users (if any) and return a consistent JSON error."""
try:
if hasattr(request, 'user') and request.user and request.user.is_authenticated:
logout(request)
except Exception:
pass
return JsonResponse(
{
'success': False,
'error': error,
},
status=status_code,
)