Coverage for /Users/davegaeddert/Developer/dropseed/plain/plain-sessions/plain/sessions/middleware.py: 81%

1 import time

2 from importlib import import_module

3

4 from plain.runtime import settings

5 from plain.sessions.backends.base import UpdateError

6 from plain.sessions.exceptions import SessionInterrupted

7 from plain.utils.cache import patch_vary_headers

8 from plain.utils.http import http_date

9

10

11 class SessionMiddleware:

12 def __init__(self, get_response):

13 self.get_response = get_response

14 engine = import_module(settings.SESSION_ENGINE)

15 self.SessionStore = engine.SessionStore

16

17 def __call__(self, request):

18 session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)

19 request.session = self.SessionStore(session_key)

20

21 response = self.get_response(request)

22

23 """

24 If request.session was modified, or if the configuration is to save the

25 session every time, save the changes and set a session cookie or delete

26 the session cookie if the session has been emptied.

27 """

28 try:

29 accessed = request.session.accessed

30 modified = request.session.modified

31 empty = request.session.is_empty()

32 except AttributeError:

33 return response

34 # First check if we need to delete this cookie.

35 # The session should be deleted only if the session is entirely empty.

36 if settings.SESSION_COOKIE_NAME in request.COOKIES and empty:

37 response.delete_cookie(

38 settings.SESSION_COOKIE_NAME,

39 path=settings.SESSION_COOKIE_PATH,

40 domain=settings.SESSION_COOKIE_DOMAIN,

41 samesite=settings.SESSION_COOKIE_SAMESITE,

42 )

43 patch_vary_headers(response, ("Cookie",))

44 else:

45 if accessed:

46 patch_vary_headers(response, ("Cookie",))

47 if (modified or settings.SESSION_SAVE_EVERY_REQUEST) and not empty:

48 if request.session.get_expire_at_browser_close():

49 max_age = None

50 expires = None

51 else:

52 max_age = request.session.get_expiry_age()

53 expires_time = time.time() + max_age

54 expires = http_date(expires_time)

55 # Save the session data and refresh the client cookie.

56 # Skip session save for 5xx responses.

57 if response.status_code < 500:

58 try:

59 request.session.save()

60 except UpdateError:

61 raise SessionInterrupted(

62 "The request's session was deleted before the "

63 "request completed. The user may have logged "

64 "out in a concurrent request, for example."

65 )

66 response.set_cookie(

67 settings.SESSION_COOKIE_NAME,

68 request.session.session_key,

69 max_age=max_age,

70 expires=expires,

71 domain=settings.SESSION_COOKIE_DOMAIN,

72 path=settings.SESSION_COOKIE_PATH,

73 secure=settings.SESSION_COOKIE_SECURE or None,

74 httponly=settings.SESSION_COOKIE_HTTPONLY or None,

75 samesite=settings.SESSION_COOKIE_SAMESITE,

76 )

77 return response