Skip to content

Commit a202d86

Browse files
committed
now you can set SESSION_TIME and IDLE_TIME with timedelta
1 parent ac82832 commit a202d86

File tree

2 files changed

+84
-14
lines changed

2 files changed

+84
-14
lines changed

django_auto_logout/middleware.py

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,28 +21,41 @@ def _auto_logout(request: HttpRequest, options):
2121
now = datetime.now()
2222

2323
if options.get('SESSION_TIME') is not None:
24-
ttl = timedelta(seconds=options['SESSION_TIME'])
24+
if isinstance(options['SESSION_TIME'], timedelta):
25+
ttl = options['SESSION_TIME']
26+
elif isinstance(options['SESSION_TIME'], int):
27+
ttl = timedelta(seconds=options['SESSION_TIME'])
28+
else:
29+
raise TypeError(f"AUTO_LOGOUT['SESSION_TIME'] should be `int` or `timedelta`, "
30+
f"not `{type(options['SESSION_TIME']).__name__}`.")
31+
2532
time_expired = user.last_login < now - ttl
2633
should_logout |= time_expired
2734
logger.debug('Check SESSION_TIME: %s < %s (%s)', user.last_login, now, time_expired)
2835

2936
if options.get('IDLE_TIME') is not None:
30-
ttl = timedelta(seconds=options['IDLE_TIME'])
37+
if isinstance(options['IDLE_TIME'], timedelta):
38+
ttl = options['IDLE_TIME']
39+
elif isinstance(options['IDLE_TIME'], int):
40+
ttl = timedelta(seconds=options['IDLE_TIME'])
41+
else:
42+
raise TypeError(f"AUTO_LOGOUT['IDLE_TIME'] should be `int` or `timedelta`, "
43+
f"not `{type(options['IDLE_TIME']).__name__}`.")
3144

32-
if 'django_auto_logout_last_touch' in request.session:
33-
last_touch = datetime.fromisoformat(request.session['django_auto_logout_last_touch'])
45+
if 'django_auto_logout_last_request' in request.session:
46+
last_req = datetime.fromisoformat(request.session['django_auto_logout_last_request'])
3447
else:
35-
last_touch = now
36-
request.session['django_auto_logout_last_touch'] = last_touch.isoformat()
48+
last_req = now
49+
request.session['django_auto_logout_last_request'] = last_req.isoformat()
3750

38-
time_expired = last_touch < now - ttl
51+
time_expired = last_req < now - ttl
3952
should_logout |= time_expired
40-
logger.debug('Check IDLE_TIME: %s < %s (%s)', last_touch, now, time_expired)
53+
logger.debug('Check IDLE_TIME: %s < %s (%s)', last_req, now, time_expired)
4154

4255
if should_logout:
43-
del request.session['django_auto_logout_last_touch']
56+
del request.session['django_auto_logout_last_request']
4457
else:
45-
request.session['django_auto_logout_last_touch'] = now.isoformat()
58+
request.session['django_auto_logout_last_request'] = now.isoformat()
4659

4760
if should_logout:
4861
logger.debug('Logout user %s', user)

example/some_app_login_required/tests.py

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from time import sleep
2+
from datetime import timedelta
23
from django.test import TestCase
34
from django.conf import settings
45
from django.contrib.auth import get_user_model
@@ -24,7 +25,6 @@ def assertLoginRequiredRedirect(self):
2425
return resp
2526

2627
def _logout_session_time(self):
27-
settings.AUTO_LOGOUT = {'SESSION_TIME': 1}
2828
self.assertLoginRequiredRedirect()
2929

3030
self.client.force_login(self.user)
@@ -34,35 +34,68 @@ def _logout_session_time(self):
3434
self.assertLoginRequiredRedirect()
3535

3636
def test_logout_session_time(self):
37+
settings.AUTO_LOGOUT = {'SESSION_TIME': 1}
3738
settings.USE_TZ = False
3839
self._logout_session_time()
3940

4041
def test_logout_session_time_using_tz_utc(self):
42+
settings.AUTO_LOGOUT = {'SESSION_TIME': 1}
4143
settings.USE_TZ = True
4244
self._logout_session_time()
4345

4446
def test_logout_session_time_using_tz_non_utc(self):
47+
settings.AUTO_LOGOUT = {'SESSION_TIME': 1}
4548
settings.USE_TZ = True
4649
settings.TIME_ZONE = 'Asia/Yekaterinburg'
4750
self._logout_session_time()
4851

49-
def test_logout_idle_time_no_idle(self):
50-
settings.AUTO_LOGOUT = {'IDLE_TIME': 1}
52+
def test_logout_session_time_timedelta(self):
53+
settings.AUTO_LOGOUT = {'SESSION_TIME': timedelta(seconds=1)}
54+
settings.USE_TZ = False
55+
self._logout_session_time()
56+
57+
def test_logout_session_time_using_tz_utc_timedelta(self):
58+
settings.AUTO_LOGOUT = {'SESSION_TIME': timedelta(seconds=1)}
59+
settings.USE_TZ = True
60+
self._logout_session_time()
61+
62+
def test_logout_session_time_using_tz_non_utc_timedelta(self):
63+
settings.AUTO_LOGOUT = {'SESSION_TIME': timedelta(seconds=1)}
64+
settings.USE_TZ = True
65+
settings.TIME_ZONE = 'Asia/Yekaterinburg'
66+
self._logout_session_time()
67+
68+
def _test_logout_idle_time_no_idle(self):
5169
self.client.force_login(self.user)
5270
self.assertLoginRequiredIsOk()
5371

5472
for _ in range(10):
5573
sleep(0.5)
5674
self.assertLoginRequiredIsOk()
5775

58-
def test_logout_idle_time(self):
76+
def test_logout_idle_time_no_idle(self):
5977
settings.AUTO_LOGOUT = {'IDLE_TIME': 1}
78+
self._test_logout_idle_time_no_idle()
79+
80+
def test_logout_idle_time_no_idle_timedelta(self):
81+
settings.AUTO_LOGOUT = {'IDLE_TIME': timedelta(seconds=1)}
82+
self._test_logout_idle_time_no_idle()
83+
84+
def _test_logout_idle_time(self):
6085
self.client.force_login(self.user)
6186
self.assertLoginRequiredIsOk()
6287

6388
sleep(1.5)
6489
self.assertLoginRequiredRedirect()
6590

91+
def test_logout_idle_time(self):
92+
settings.AUTO_LOGOUT = {'IDLE_TIME': 1}
93+
self._test_logout_idle_time()
94+
95+
def test_logout_idle_time_timedelta(self):
96+
settings.AUTO_LOGOUT = {'IDLE_TIME': timedelta(seconds=1)}
97+
self._test_logout_idle_time()
98+
6699
def test_combine_idle_and_session_time(self):
67100
settings.AUTO_LOGOUT = {
68101
'IDLE_TIME': 1,
@@ -81,6 +114,30 @@ def test_combine_idle_and_session_time(self):
81114
sleep(0.5)
82115
self.assertLoginRequiredRedirect()
83116

117+
def test_session_time_config_time(self):
118+
settings.AUTO_LOGOUT = {
119+
'IDLE_TIME': 1,
120+
'SESSION_TIME': '2',
121+
}
122+
123+
self.client.force_login(self.user)
124+
125+
exc_message = "AUTO_LOGOUT['SESSION_TIME'] should be `int` or `timedelta`, not `str`."
126+
with self.assertRaisesMessage(TypeError, exc_message):
127+
self.client.get('/login-required/')
128+
129+
def test_idle_time_config_time(self):
130+
settings.AUTO_LOGOUT = {
131+
'IDLE_TIME': '1',
132+
'SESSION_TIME': 2,
133+
}
134+
135+
self.client.force_login(self.user)
136+
137+
exc_message = "AUTO_LOGOUT['IDLE_TIME'] should be `int` or `timedelta`, not `str`."
138+
with self.assertRaisesMessage(TypeError, exc_message):
139+
self.client.get('/login-required/')
140+
84141
def test_combine_idle_and_session_time_but_session_less_than_idle(self):
85142
settings.AUTO_LOGOUT = {
86143
'IDLE_TIME': 2,

0 commit comments

Comments
 (0)