Store current request rather than user/session/ip

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
This commit is contained in:
Yohann D'ANELLO 2021-06-15 12:17:42 +02:00
parent b4d87bc6b5
commit 5e9f36ef1a
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
2 changed files with 39 additions and 30 deletions

View File

@ -21,7 +21,7 @@ from rest_framework.authtoken.models import Token
from note.models import Alias, NoteUser from note.models import Alias, NoteUser
from note.models.transactions import Transaction, SpecialTransaction from note.models.transactions import Transaction, SpecialTransaction
from note.tables import HistoryTable, AliasTable from note.tables import HistoryTable, AliasTable
from note_kfet.middlewares import _set_current_user_and_ip from note_kfet.middlewares import _set_current_request
from permission.backends import PermissionBackend from permission.backends import PermissionBackend
from permission.models import Role from permission.models import Role
from permission.views import ProtectQuerysetMixin, ProtectedCreateView from permission.views import ProtectQuerysetMixin, ProtectedCreateView
@ -41,7 +41,8 @@ class CustomLoginView(LoginView):
@transaction.atomic @transaction.atomic
def form_valid(self, form): def form_valid(self, form):
logout(self.request) logout(self.request)
_set_current_user_and_ip(form.get_user(), self.request.session, None) self.request.user = form.get_user()
_set_current_request(self.request)
self.request.session['permission_mask'] = form.cleaned_data['permission_mask'].rank self.request.session['permission_mask'] = form.cleaned_data['permission_mask'].rank
return super().form_valid(form) return super().form_valid(form)

View File

@ -1,41 +1,57 @@
# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay # Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from threading import local
from typing import Optional
from django.conf import settings from django.conf import settings
from django.contrib.auth import login from django.contrib.auth import login
from django.contrib.auth.models import AnonymousUser, User from django.contrib.auth.models import User
from django.contrib.sessions.backends.db import SessionStore from django.contrib.sessions.backends.db import SessionStore
from django.http import HttpRequest
from threading import local REQUEST_ATTR_NAME = getattr(settings, 'LOCAL_REQUEST_ATTR_NAME', '_current_request')
USER_ATTR_NAME = getattr(settings, 'LOCAL_USER_ATTR_NAME', '_current_user')
SESSION_ATTR_NAME = getattr(settings, 'LOCAL_SESSION_ATTR_NAME', '_current_session')
IP_ATTR_NAME = getattr(settings, 'LOCAL_IP_ATTR_NAME', '_current_ip')
_thread_locals = local() _thread_locals = local()
def _set_current_user_and_ip(user=None, session=None, ip=None): def _set_current_request(request=None):
setattr(_thread_locals, USER_ATTR_NAME, user) setattr(_thread_locals, REQUEST_ATTR_NAME, request)
setattr(_thread_locals, SESSION_ATTR_NAME, session)
setattr(_thread_locals, IP_ATTR_NAME, ip)
def get_current_user() -> User: def get_current_request() -> Optional[HttpRequest]:
return getattr(_thread_locals, USER_ATTR_NAME, None) return getattr(_thread_locals, REQUEST_ATTR_NAME, None)
def get_current_session() -> SessionStore: def get_current_user() -> Optional[User]:
return getattr(_thread_locals, SESSION_ATTR_NAME, None) request = get_current_request()
if request is None:
return None
return request.user
def get_current_ip() -> str: def get_current_session() -> Optional[SessionStore]:
return getattr(_thread_locals, IP_ATTR_NAME, None) request = get_current_request()
if request is None:
return None
return request.session
def get_current_ip() -> Optional[str]:
request = get_current_request()
if request is None:
return None
elif 'HTTP_X_REAL_IP' in request.META:
return request.META.get('HTTP_X_REAL_IP')
elif 'HTTP_X_FORWARDED_FOR' in request.META:
return request.META.get('HTTP_X_FORWARDED_FOR').split(', ')[0]
return request.META.get('REMOTE_ADDR')
def get_current_authenticated_user(): def get_current_authenticated_user():
current_user = get_current_user() current_user = get_current_user()
if isinstance(current_user, AnonymousUser): if not current_user or not current_user.is_authenticated:
return None return None
return current_user return current_user
@ -49,8 +65,6 @@ class SessionMiddleware(object):
self.get_response = get_response self.get_response = get_response
def __call__(self, request): def __call__(self, request):
user = request.user
# If we authenticate through a token to connect to the API, then we query the good user # If we authenticate through a token to connect to the API, then we query the good user
if 'HTTP_AUTHORIZATION' in request.META and request.path.startswith("/api"): if 'HTTP_AUTHORIZATION' in request.META and request.path.startswith("/api"):
token = request.META.get('HTTP_AUTHORIZATION') token = request.META.get('HTTP_AUTHORIZATION')
@ -60,20 +74,14 @@ class SessionMiddleware(object):
if Token.objects.filter(key=token).exists(): if Token.objects.filter(key=token).exists():
token_obj = Token.objects.get(key=token) token_obj = Token.objects.get(key=token)
user = token_obj.user user = token_obj.user
request.user = user
session = request.session session = request.session
session["permission_mask"] = 42 session["permission_mask"] = 42
session.save() session.save()
if 'HTTP_X_REAL_IP' in request.META: _set_current_request(request)
ip = request.META.get('HTTP_X_REAL_IP')
elif 'HTTP_X_FORWARDED_FOR' in request.META:
ip = request.META.get('HTTP_X_FORWARDED_FOR').split(', ')[0]
else:
ip = request.META.get('REMOTE_ADDR')
_set_current_user_and_ip(user, request.session, ip)
response = self.get_response(request) response = self.get_response(request)
_set_current_user_and_ip(None, None, None) _set_current_request(None)
return response return response