From e0762573ae40309e1ec3d8d94062ef58376adc86 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 18 Oct 2023 15:50:38 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E5=9C=A8=E7=BA=BF=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E8=BF=87=E6=9C=9F=E6=97=B6=E9=97=B4=20(#1188?= =?UTF-8?q?9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng <1304903146@qq.com> --- apps/audits/api.py | 9 ++++----- apps/audits/models.py | 14 +++++++++++--- apps/audits/serializers.py | 1 + apps/audits/signal_handlers/login_log.py | 6 ------ 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/apps/audits/api.py b/apps/audits/api.py index f332c5718..35315aa65 100644 --- a/apps/audits/api.py +++ b/apps/audits/api.py @@ -6,7 +6,6 @@ from importlib import import_module from django.conf import settings from django.db.models import F, Value, CharField, Q from django.http import HttpResponse, FileResponse -from django.utils import timezone from django.utils.encoding import escape_uri_path from rest_framework import generics from rest_framework import status @@ -269,9 +268,7 @@ class UserSessionViewSet(CommonApiMixin, viewsets.ModelViewSet): def get_queryset(self): keys = UserSession.get_keys() - queryset = UserSession.objects.filter( - date_expired__gt=timezone.now(), key__in=keys - ) + queryset = UserSession.objects.filter(key__in=keys) if current_org.is_root(): return queryset user_ids = self.org_user_ids @@ -281,7 +278,9 @@ class UserSessionViewSet(CommonApiMixin, viewsets.ModelViewSet): @action(['POST'], detail=False, url_path='offline') def offline(self, request, *args, **kwargs): ids = request.data.get('ids', []) - queryset = self.get_queryset().exclude(key=request.session.session_key).filter(id__in=ids) + queryset = self.get_queryset() + session_key = request.session.session_key + queryset = queryset.exclude(key=session_key).filter(id__in=ids) if not queryset.exists(): return Response(status=status.HTTP_200_OK) diff --git a/apps/audits/models.py b/apps/audits/models.py index ff58f962a..f7a669114 100644 --- a/apps/audits/models.py +++ b/apps/audits/models.py @@ -1,5 +1,6 @@ import os import uuid +from datetime import timedelta from importlib import import_module from django.conf import settings @@ -263,7 +264,6 @@ class UserSession(models.Model): type = models.CharField(choices=LoginTypeChoices.choices, max_length=2, verbose_name=_("Login type")) backend = models.CharField(max_length=32, default="", verbose_name=_("Authentication backend")) date_created = models.DateTimeField(null=True, blank=True, verbose_name=_('Date created')) - date_expired = models.DateTimeField(null=True, blank=True, verbose_name=_("Date expired"), db_index=True) user = models.ForeignKey( 'users.User', verbose_name=_('User'), related_name='sessions', on_delete=models.CASCADE ) @@ -275,6 +275,14 @@ class UserSession(models.Model): def backend_display(self): return gettext(self.backend) + @property + def date_expired(self): + session_store_cls = import_module(settings.SESSION_ENGINE).SessionStore + session_store = session_store_cls(session_key=self.key) + cache_key = session_store.cache_key + ttl = caches[settings.SESSION_CACHE_ALIAS].ttl(cache_key) + return timezone.now() + timedelta(seconds=ttl) + @staticmethod def get_keys(): session_store_cls = import_module(settings.SESSION_ENGINE).SessionStore @@ -284,8 +292,8 @@ class UserSession(models.Model): @classmethod def clear_expired_sessions(cls): - cls.objects.filter(date_expired__lt=timezone.now()).delete() - cls.objects.exclude(key__in=cls.get_keys()).delete() + keys = cls.get_keys() + cls.objects.exclude(key__in=keys).delete() class Meta: ordering = ['-date_created'] diff --git a/apps/audits/serializers.py b/apps/audits/serializers.py index 829986297..472f6ae28 100644 --- a/apps/audits/serializers.py +++ b/apps/audits/serializers.py @@ -169,6 +169,7 @@ class FileSerializer(serializers.Serializer): class UserSessionSerializer(serializers.ModelSerializer): type = LabeledChoiceField(choices=LoginTypeChoices.choices, label=_("Type")) user = ObjectRelatedField(required=False, queryset=User.objects, label=_('User')) + date_expired = serializers.DateTimeField(format="%Y/%m/%d %H:%M:%S", label=_('Date expired')) is_current_user_session = serializers.SerializerMethodField() class Meta: diff --git a/apps/audits/signal_handlers/login_log.py b/apps/audits/signal_handlers/login_log.py index 2ad9c0a7a..2d8560412 100644 --- a/apps/audits/signal_handlers/login_log.py +++ b/apps/audits/signal_handlers/login_log.py @@ -1,7 +1,5 @@ # -*- coding: utf-8 -*- # -from datetime import timedelta -from importlib import import_module from django.conf import settings from django.contrib.auth import BACKEND_SESSION_KEY @@ -88,9 +86,6 @@ def create_user_session(request, user_id, instance: UserLoginLog): if instance.type != LoginTypeChoices.web: return session_key = request.session.session_key or '-' - session_store_cls = import_module(settings.SESSION_ENGINE).SessionStore - session_store = session_store_cls(session_key=session_key) - ttl = session_store.get_expiry_age() online_session_data = { 'user_id': user_id, @@ -101,7 +96,6 @@ def create_user_session(request, user_id, instance: UserLoginLog): 'backend': instance.backend, 'user_agent': instance.user_agent, 'date_created': instance.datetime, - 'date_expired': instance.datetime + timedelta(seconds=ttl), } user_session = UserSession.objects.create(**online_session_data) request.session['user_session_id'] = str(user_session.id)