You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
jumpserver/apps/authentication/api/session.py

69 lines
2.1 KiB

import time
from threading import Thread
from django.conf import settings
from django.contrib.auth import logout
from django.contrib.auth.models import AnonymousUser
from rest_framework import generics
from rest_framework import status
from rest_framework.response import Response
from common.sessions.cache import user_session_manager
from common.utils import get_logger
__all__ = ['UserSessionApi']
logger = get_logger(__name__)
class UserSessionManager:
def __init__(self, request):
self.request = request
self.session = request.session
def connect(self):
user_session_manager.add_or_increment(self.session.session_key)
def disconnect(self):
user_session_manager.decrement(self.session.session_key)
if self.should_delete_session():
thread = Thread(target=self.delay_delete_session)
thread.start()
def should_delete_session(self):
return (self.session.modified or settings.SESSION_SAVE_EVERY_REQUEST) and \
not self.session.is_empty() and \
self.session.get_expire_at_browser_close() and \
not user_session_manager.check_active(self.session.session_key)
def delay_delete_session(self):
timeout = 6
check_interval = 0.5
start_time = time.time()
while time.time() - start_time < timeout:
time.sleep(check_interval)
if user_session_manager.check_active(self.session.session_key):
return
logout(self.request)
class UserSessionApi(generics.RetrieveDestroyAPIView):
permission_classes = ()
def retrieve(self, request, *args, **kwargs):
if isinstance(request.user, AnonymousUser):
return Response(status=status.HTTP_403_FORBIDDEN)
UserSessionManager(request).connect()
return Response(status=status.HTTP_200_OK, data={'ok': True})
def destroy(self, request, *args, **kwargs):
if isinstance(request.user, AnonymousUser):
return Response(status=status.HTTP_403_FORBIDDEN)
UserSessionManager(request).disconnect()
return Response(status=status.HTTP_200_OK, data={'ok': True})