Skip to content

Commit 0cbd57e

Browse files
authored
Merge pull request #5 from bugov/add-idle-check
add info message after auto-logout && more readme
2 parents 008da2d + 81e6c9b commit 0cbd57e

File tree

10 files changed

+128
-18
lines changed

10 files changed

+128
-18
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
!.travis.yml
44
__pycache__
55
*.egg-info
6+
*.sqlite3
67
venv
78
htmlcov
89
build

README.rst

+47-11
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ django-auto-logout
66

77
Auto logout a user after specific time in Django.
88

9-
Works with Python ≥ 3.7, Django ≥ 3.0.
9+
Works with Python🐍 ≥ 3.7, Django🌐 ≥ 3.0.
1010

11-
Installation
12-
------------
11+
✔️ Installation
12+
----------------
1313

1414
.. code:: bash
1515
@@ -20,13 +20,20 @@ Append to `settings` middlewares:
2020

2121
.. code:: python
2222
23-
MIDDLEWARE = (
23+
MIDDLEWARE = [
2424
...
2525
'django_auto_logout.middleware.auto_logout',
26-
)
26+
]
2727
28-
Logout in case of idle
29-
----------------------
28+
.. note::
29+
Make sure that the following middlewares are used before doing this:
30+
31+
- `django.contrib.sessions.middleware.SessionMiddleware`
32+
- `django.contrib.auth.middleware.AuthenticationMiddleware`
33+
- `django.contrib.messages.middleware.MessageMiddleware`
34+
35+
💤 Logout in case of idle
36+
------------------------
3037

3138
Logout a user if there are no requests for a long time.
3239

@@ -37,8 +44,8 @@ Add to `settings`:
3744
AUTO_LOGOUT = {'IDLE_TIME': 600} # logout after 10 minutes of downtime
3845
3946
40-
Limit session time
41-
------------------
47+
Limit session time
48+
--------------------
4249

4350
Logout a user after 3600 seconds (hour) from the last login.
4451

@@ -48,8 +55,36 @@ Add to `settings`:
4855
4956
AUTO_LOGOUT = {'SESSION_TIME': 3600}
5057
51-
Combine configurations
52-
----------------------
58+
✉️ Show messages when logging out automatically
59+
------------------------------------------------
60+
61+
Set the message that will be displayed after the user automatically logs out of the system:
62+
63+
.. code:: python
64+
65+
AUTO_LOGOUT = {
66+
'SESSION_TIME': 3600,
67+
'MESSAGE': 'The session has expired. Please login again to continue.',
68+
}
69+
70+
It uses `django.contrib.messages`. Don't forget to display messages in templates:
71+
72+
.. code:: html
73+
74+
{% for message in messages %}
75+
<div class="message {{ message.tags }}">
76+
{{ message }}
77+
</div>
78+
{% endfor %}
79+
80+
.. note::
81+
`messages` template variable provides by `django.contrib.messages.context_processors.messages`
82+
context processor.
83+
84+
See `TEMPLATES` → `OPTIONS` → `context_processors` in your `settings.py` file.
85+
86+
🌈 Combine configurations
87+
------------------------
5388

5489
You can combine previous configurations. For example, you may want to logout a user
5590
in case of downtime (5 minutes or more) and not allow working within one session
@@ -61,4 +96,5 @@ for more than half an hour:
6196
AUTO_LOGOUT = {
6297
'IDLE_TIME': 300, # 5 minutes
6398
'SESSION_TIME': 1800, # 30 minutes
99+
'MESSAGE': 'The session has expired. Please login again to continue.',
64100
}

django_auto_logout/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '0.2.0'
1+
__version__ = '0.3.0'

django_auto_logout/middleware.py

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from django.conf import settings
55
from django.http import HttpRequest, HttpResponse
66
from django.contrib.auth import get_user_model, logout
7+
from django.contrib.messages import info
78
from pytz import timezone
89

910
UserModel = get_user_model()
@@ -47,6 +48,9 @@ def _auto_logout(request: HttpRequest, options):
4748
logger.debug('Logout user %s', user)
4849
logout(request)
4950

51+
if options.get('MESSAGE') is not None:
52+
info(request, options['MESSAGE'])
53+
5054

5155
def auto_logout(get_response: Callable[[HttpRequest], HttpResponse]) -> Callable:
5256
def middleware(request: HttpRequest) -> HttpResponse:

example/example/settings.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@
163163

164164
# DJANGO AUTO LOGIN
165165
AUTO_LOGOUT = {
166-
'IDLE_TIME': 300, # 5 minutes
167-
'SESSION_TIME': 1800, # 30 minutes
166+
'IDLE_TIME': 10, # 10 seconds
167+
'SESSION_TIME': 120, # 2 minutes
168+
'MESSAGE': 'The session has expired. Please login again to continue.',
168169
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>Title</title>
6+
</head>
7+
<body>
8+
{% for message in messages %}
9+
<div class="message {{ message.tags }}">
10+
{{ message }}
11+
</div>
12+
{% endfor %}
13+
14+
{% block content %}{% endblock %}
15+
</body>
16+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{% extends 'layout.html' %}
2+
3+
{% block content %}
4+
<p>
5+
login page
6+
</p>
7+
{% endblock %}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{% extends 'layout.html' %}
2+
3+
{% block content %}
4+
<p>
5+
login required view
6+
</p>
7+
{% endblock %}

example/some_app_login_required/tests.py

+39-1
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@ def setUp(self):
1515
def assertLoginRequiredIsOk(self):
1616
resp = self.client.get(self.url)
1717
self.assertContains(resp, 'login required view', msg_prefix='Fine with authorized')
18+
return resp
1819

1920
def assertLoginRequiredRedirect(self):
2021
resp = self.client.get(self.url)
21-
self.assertRedirects(resp, f'{settings.LOGIN_URL}?next={self.url}', msg_prefix='Redirect for anonymous')
22+
self.assertEqual(resp.status_code, 302, msg='Redirect for anonymous')
23+
self.assertEqual(resp['location'], f'{settings.LOGIN_URL}?next={self.url}')
24+
return resp
2225

2326
def _logout_session_time(self):
2427
settings.AUTO_LOGOUT = {'SESSION_TIME': 1}
@@ -102,3 +105,38 @@ def test_combine_idle_and_session_time_but_session_less_than_idle(self):
102105
self.assertLoginRequiredIsOk()
103106
sleep(1)
104107
self.assertLoginRequiredRedirect()
108+
109+
def test_message_on_auto_logout(self):
110+
settings.AUTO_LOGOUT = {
111+
'SESSION_TIME': 1,
112+
'MESSAGE': 'The session has expired. Please login again to continue.',
113+
}
114+
self.client.force_login(self.user)
115+
self.assertLoginRequiredIsOk()
116+
sleep(1)
117+
resp = self.assertLoginRequiredRedirect()
118+
119+
# display message after redirect
120+
resp = self.client.get(resp['location'])
121+
self.assertContains(resp, 'login page', msg_prefix=resp.content.decode())
122+
self.assertContains(resp, 'class="message info"', msg_prefix=resp.content.decode())
123+
self.assertContains(resp, settings.AUTO_LOGOUT['MESSAGE'])
124+
125+
# message displays only once
126+
resp = self.assertLoginRequiredRedirect()
127+
resp = self.client.get(resp['location'])
128+
self.assertContains(resp, 'login page', msg_prefix=resp.content.decode())
129+
self.assertNotContains(resp, 'class="message info"', msg_prefix=resp.content.decode())
130+
131+
def test_no_messages_if_no_messages(self):
132+
settings.AUTO_LOGOUT = {
133+
'SESSION_TIME': 1,
134+
'MESSAGE': None,
135+
}
136+
self.client.force_login(self.user)
137+
self.assertLoginRequiredIsOk()
138+
sleep(1)
139+
resp = self.assertLoginRequiredRedirect()
140+
resp = self.client.get(resp['location'])
141+
self.assertContains(resp, 'login page', msg_prefix=resp.content.decode())
142+
self.assertNotContains(resp, 'class="message info"', msg_prefix=resp.content.decode())
+3-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
from django.http import HttpResponse
21
from django.contrib.auth.decorators import login_required
2+
from django.shortcuts import render
33

44

55
def login_page(request):
6-
return HttpResponse(b'login page')
6+
return render(request, 'login_page.html', {})
77

88

99
@login_required
1010
def login_required_view(request):
11-
return HttpResponse(b'login required view')
11+
return render(request, 'login_required.html', {})

0 commit comments

Comments
 (0)