forked from mysociety/local-intelligence-hub
-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: make middleware async-compatible to fix asgi
- Loading branch information
Showing
5 changed files
with
86 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
.venv | ||
__pycache__ | ||
.env | ||
.env.local | ||
.static/**/* | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,99 @@ | ||
import logging | ||
from datetime import timedelta | ||
from inspect import isawaitable | ||
|
||
from django.http import HttpRequest | ||
from django.utils.decorators import sync_and_async_middleware | ||
from django.utils.timezone import now | ||
|
||
from asgiref.sync import iscoroutinefunction, sync_to_async | ||
from gqlauth.core.middlewares import USER_OR_ERROR_KEY, UserOrError | ||
from gqlauth.core.middlewares import django_jwt_middleware as _django_jwt_middleware | ||
from gqlauth.core.types_ import GQLAuthError, GQLAuthErrors | ||
from whitenoise.middleware import WhiteNoiseMiddleware | ||
|
||
from hub.models import UserProperties | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
class RecordLastSeenMiddleware: | ||
one_day = timedelta(hours=24) | ||
|
||
def __init__(self, get_response): | ||
self.get_response = get_response | ||
@sync_and_async_middleware | ||
def record_last_seen_middleware(get_response): | ||
one_day = timedelta(hours=24) | ||
|
||
def __call__(self, request): | ||
def process_request(request): | ||
if request.user.is_authenticated: | ||
user = request.user | ||
if not hasattr(user, "userproperties"): | ||
UserProperties.objects.create(user=user) | ||
|
||
props = UserProperties.objects.get_or_create(user=user) | ||
last_seen = request.session.get("last_seen", None) | ||
|
||
yesterday = now().replace(hour=0, minute=0) - self.one_day | ||
|
||
yesterday = now().replace(hour=0, minute=0) - one_day | ||
if last_seen is None or last_seen < yesterday.timestamp(): | ||
props = user.userproperties | ||
props.last_seen = now() | ||
request.session["last_seen"] = props.last_seen.timestamp() | ||
props.save() | ||
|
||
response = self.get_response(request) | ||
if iscoroutinefunction(get_response): | ||
async def middleware(request: HttpRequest): | ||
await sync_to_async(process_request)(request) | ||
return await get_response(request) | ||
|
||
else: | ||
def middleware(request: HttpRequest): | ||
process_request(request) | ||
return get_response(request) | ||
|
||
return middleware | ||
|
||
|
||
@sync_and_async_middleware | ||
def async_whitenoise_middleware(get_response): | ||
def logic(request): | ||
return WhiteNoiseMiddleware(get_response)(request) | ||
|
||
if iscoroutinefunction(get_response): | ||
async def middleware(request: HttpRequest): | ||
response = await sync_to_async(logic)(request) | ||
if isawaitable(response): | ||
response = await response | ||
return response | ||
|
||
else: | ||
def middleware(request: HttpRequest): | ||
return logic(request) | ||
|
||
return middleware | ||
|
||
|
||
@sync_and_async_middleware | ||
def django_jwt_middleware(get_response): | ||
""" | ||
Wrap the gqlauth jwt middleware in an exception | ||
handler (initially added because if a user is | ||
deleted, the middleware throws an error, | ||
causing a 500 instead of a 403). | ||
""" | ||
gqlauth_middleware = _django_jwt_middleware(get_response) | ||
|
||
def exception_handler(error: Exception, request: HttpRequest): | ||
logger.warning(f"Gqlauth middleware error: {error}") | ||
user_or_error = UserOrError() | ||
user_or_error.error = GQLAuthError(code=GQLAuthErrors.UNAUTHENTICATED) | ||
setattr(request, USER_OR_ERROR_KEY, user_or_error) | ||
|
||
if iscoroutinefunction(get_response): | ||
async def middleware(request: HttpRequest): | ||
try: | ||
return await gqlauth_middleware(request) | ||
except Exception: | ||
exception_handler(request) | ||
return await get_response(request) | ||
|
||
else: | ||
def middleware(request: HttpRequest): | ||
try: | ||
return gqlauth_middleware(request) | ||
except Exception as e: | ||
exception_handler(request) | ||
return get_response(request) | ||
|
||
return response | ||
return middleware |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters