How to find user_id in Django endpoint
I have this Django endpoint:
def get(http_request: HttpRequest, id: str):
book_account_id = UUID(id)
user_id: UUID = http_request.user.id
affiliated_price_subscriptions = None
response = BookAccountService.filter(
id=book_account_id
).prefetch_related(
Prefetch(
'subscription_set',
queryset=SubscriptionRepository.filter(
active=True
).prefetch_related(
Prefetch(
'pricesubscription_set',
queryset=PriceSubscriptionRepository.filter(
Q(status=PriceSubscription.PriceSubscriptionStatus.PENDING) |
Q(status=PriceSubscription.PriceSubscriptionStatus.REQUIRES_PAYMENT)
),
to_attr='price_subscriptions'
)
),
to_attr='subscriptions'
)
).first()
affiliated_price_subscriptions = list(chain.from_iterable(
subscription.price_subscriptions for subscription in response.subscriptions
))
# The user must be part of the group that owns the book account
# or the book acc must have at least one pending subscription
if not PersonGroupService.exists(
person__user_id=user_id,
group__bookaccount__id=book_account_id
) and affiliated_price_subscriptions is None:
return RestResponse(
status=status.HTTP_200_OK,
data=Response(
code=24,
error=True,
messages=[
f"User with ID {user_id} does not have access to book account with ID {book_account_id}."
],
data=None,
).to_dict(),
)
return (...)
Basically what it does is to get the book_account
either if:
- the user.id belongs to a person that belongs to the group of that book_account.
- The book account has a related a related price-subscription with a
PENDING
orPENDING_PAYMENT
status.
I erased the is_authenticated=True
since for 2) you do not need to be logged in to obtain the book_account data. However, when I call the endpoint while authenticated I get an error since user_id is null. I realized the only way to not have it be null is to have is_authenticated=True, but if I do so then I can´t do 2). Is there a way I can do both? Or should I create a different endpoint for both cases?
Use http_request.user.is_authenticated
to check if the user is logged in. If they are, you can now then access the http_request.user.id. If not, just skip the checks that needs user authentication.
i added two things in your code that should help
1. try-except for UUID Validation 2. Checked http_request.user.is_authenticated 3. Fallback alternative for Unauthenticated Users 4. Access denied response if authenticated group access or valid price subscriptions is not met
from django.http import JsonResponse
from django.db.models import Q, Prefetch
from itertools import chain
from uuid import UUID
def get(http_request: HttpRequest, id: str):
try:
book_account_id = UUID(id)
except ValueError:
return JsonResponse({
"code": 400,
"error": True,
"messages": ["Invalid book account ID."],
"data": None,
}, status=400)
affiliated_price_subscriptions = None
response = BookAccountService.filter(
id=book_account_id
).prefetch_related(
Prefetch(
'subscription_set',
queryset=SubscriptionRepository.filter(
active=True
).prefetch_related(
Prefetch(
'pricesubscription_set',
queryset=PriceSubscriptionRepository.filter(
Q(status=PriceSubscription.PriceSubscriptionStatus.PENDING) |
Q(status=PriceSubscription.PriceSubscriptionStatus.REQUIRES_PAYMENT)
),
to_attr='price_subscriptions'
)
),
to_attr='subscriptions'
)
).first()
if response:
affiliated_price_subscriptions = list(chain.from_iterable(
subscription.price_subscriptions for subscription in response.subscriptions
))
if http_request.user.is_authenticated:
user_id = http_request.user.id
# Check if the user is part of the group that owns the book account
if PersonGroupService.exists(
person__user_id=user_id,
group__bookaccount__id=book_account_id
):
return JsonResponse({
"code": 200,
"error": False,
"messages": ["Access granted."],
"data": response,
}, status=200)
# If not authenticated, or if the user isn't part of the group,
# check if there are affiliated price subscriptions
if affiliated_price_subscriptions:
return JsonResponse({
"code": 200,
"error": False,
"messages": ["Access granted based on price subscriptions."],
"data": response,
}, status=200)
return JsonResponse({
"code": 403,
"error": True,
"messages": ["Access denied."],
"data": None,
}, status=403)