Files
Bruno Macabeus 135f4b6036 Replace classnames with clsx (#1479)
* Replace `classnames` with `clsx`

* fix python code formatting
2025-03-04 11:54:52 -06:00

116 lines
3.4 KiB
Python

import logging
from typing import Callable, Optional, TYPE_CHECKING, Union
from django.contrib import auth
from django.contrib.auth.models import User
from django.http.request import HttpRequest
from django.utils.timezone import now
from rest_framework.request import Request as DRFRequest
from rest_framework.response import Response
from .models.profile import Profile
logger = logging.getLogger(__name__)
if TYPE_CHECKING:
from .models.github import GitHubUser
class AnonymousUser(auth.models.AnonymousUser):
profile: Profile
if TYPE_CHECKING:
class Request(DRFRequest):
user: Union[User, AnonymousUser]
profile: Profile
else:
Request = DRFRequest
def disable_csrf(
get_response: Callable[[HttpRequest], Response],
) -> Callable[[HttpRequest], Response]:
def middleware(request: HttpRequest) -> Response:
setattr(request, "_dont_enforce_csrf_checks", True)
return get_response(request)
return middleware
def set_user_profile(
get_response: Callable[[HttpRequest], Response],
) -> Callable[[Request], Response]:
"""
Makes sure that `request.profile` is always available, even for anonymous users.
"""
def middleware(request: Request) -> Response:
user_agent = request.headers.get("User-Agent")
# Avoid creating profiles for SSR or bots
if user_agent is None or (
"node" in user_agent
or "undici" in user_agent
or "Next.js Middleware" in user_agent
or "python-requests" in user_agent
or "curl" in user_agent
or "YandexRenderResourcesBot" in user_agent
):
request.profile = Profile()
return get_response(request)
profile: Optional[Profile] = None
# Use the user's profile if they're logged in
if not request.user.is_anonymous:
profile = Profile.objects.filter(user=request.user).first()
# Otherwise, use their session profile
if not profile:
id = request.session.get("profile_id")
if isinstance(id, int):
profile = Profile.objects.filter(id=id).first()
if profile is not None:
profile_user = User.objects.filter(profile=profile).first()
if profile_user and request.user.is_anonymous:
request.user = profile_user
# If we still don't have a profile, create a new one
if not profile:
profile = Profile()
# And attach it to the logged-in user, if there is one
if not request.user.is_anonymous:
assert Profile.objects.filter(user=request.user).first() is None
profile.user = request.user
profile.save()
request.session["profile_id"] = profile.id
# More info to help identify why we are creating so many profiles...
x_forwarded_for = request.headers.get("X-Forwarded-For", "n/a")
logger.debug(
"Made new profile: User-Agent: %s, IP: %s, name: %s, request path: %s",
user_agent,
x_forwarded_for,
profile,
request.path,
)
if profile.user is None and not request.user.is_anonymous:
profile.user = request.user
profile.last_request_date = now()
profile.save()
request.profile = profile
return get_response(request)
return middleware