django-session-security-continued 3.0.0a1__py3-none-any.whl → 3.0.0a2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {django_session_security_continued-3.0.0a1.dist-info → django_session_security_continued-3.0.0a2.dist-info}/METADATA +5 -3
- django_session_security_continued-3.0.0a2.dist-info/RECORD +40 -0
- session_security/locale/ca/LC_MESSAGES/django.po +30 -0
- session_security/locale/cs/LC_MESSAGES/django.po +30 -0
- session_security/locale/de/LC_MESSAGES/django.po +29 -0
- session_security/locale/es/LC_MESSAGES/django.po +31 -0
- session_security/locale/fr/LC_MESSAGES/django.po +29 -0
- session_security/locale/it/LC_MESSAGES/django.po +31 -0
- session_security/locale/nl/LC_MESSAGES/django.po +31 -0
- session_security/locale/pl/LC_MESSAGES/django.po +35 -0
- session_security/locale/pt_BR/LC_MESSAGES/django.po +28 -0
- session_security/locale/pt_PT/LC_MESSAGES/django.po +28 -0
- session_security/static/session_security/script.js +282 -0
- session_security/static/session_security/style.css +30 -0
- session_security/templates/session_security/all.html +42 -0
- session_security/templates/session_security/dialog.html +9 -0
- session_security/tests/conftest.py +12 -3
- session_security/tests/test_packaging.py +15 -0
- session_security/tests/test_script.py +10 -10
- django_session_security_continued-3.0.0a1.dist-info/RECORD +0 -25
- {django_session_security_continued-3.0.0a1.dist-info → django_session_security_continued-3.0.0a2.dist-info}/WHEEL +0 -0
- {django_session_security_continued-3.0.0a1.dist-info → django_session_security_continued-3.0.0a2.dist-info}/licenses/LICENSE +0 -0
- {django_session_security_continued-3.0.0a1.dist-info → django_session_security_continued-3.0.0a2.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: django-session-security-continued
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.0a2
|
|
4
4
|
Summary: Client and server-side session timeout enforcement with warnings for Django 4.2+.
|
|
5
5
|
Author: Matt Bosworth (https://github.com/mattbo), Fabio Caritas Barrionuevo da Luz (https://github.com/luzfcb), Pēteris Caune (https://github.com/cuu508), John David Giese (https://github.com/johndgiese), Jose Antonio Martin Prieto (https://github.com/jantoniomartin), Richard Moorhead (https://github.com/autodidacticon), Jean-Michel Nirgal Vourgère (https://github.com/nirgal), Michał Pasternak (https://github.com/mpasternak), James Pic (https://github.com/jpic), Matthew Schettler (https://github.com/mschettler), Scott Sexton (https://github.com/scottsexton), Jacek Ostański (https://github.com/jacoor), Aaron Krill (https://github.com/krillr), @yscumc (https://github.com/yscumc), Marco Fucci (https://github.com/marcofucci), Andrei Coman (https://github.com/comandrei), Ali Hasan Imam (https://github.com/alihasanimam), Joel Hillacre (https://github.com/jhillacre), Peter Mack (https://github.com/pmack)
|
|
6
6
|
Maintainer-email: Arrai Innovations <support@arrai.com>
|
|
@@ -36,7 +36,8 @@ Dynamic: license-file
|
|
|
36
36
|
![python 3.10 status][]
|
|
37
37
|
![python 3.11 status][]
|
|
38
38
|
![python 3.12 status][]
|
|
39
|
-
![coverage status][]
|
|
39
|
+
![python coverage status][]
|
|
40
|
+
![javascript coverage status][]
|
|
40
41
|
|
|
41
42
|
<!--prettier-ignore-start-->
|
|
42
43
|
<!--TOC-->
|
|
@@ -203,7 +204,8 @@ Contributions are welcome. Please fork the repository and create a pull request
|
|
|
203
204
|
[python 3.10 status]: https://docs.arrai.dev/dssc/artifacts/main/python_3.10.svg
|
|
204
205
|
[python 3.11 status]: https://docs.arrai.dev/dssc/artifacts/main/python_3.11.svg
|
|
205
206
|
[python 3.12 status]: https://docs.arrai.dev/dssc/artifacts/main/python_3.12.svg
|
|
206
|
-
[coverage status]: https://docs.arrai.dev/dssc/artifacts/main/python_3.9.coverage.svg
|
|
207
|
+
[python coverage status]: https://docs.arrai.dev/dssc/artifacts/main/python_3.9.coverage.svg
|
|
208
|
+
[javascript coverage status]: https://docs.arrai.dev/dssc/artifacts/main/js-coverage.svg
|
|
207
209
|
[ruff status]: https://docs.arrai.dev/dssc/artifacts/main/ruff.svg
|
|
208
210
|
[pipenv]: https://github.com/pypa/pipenv
|
|
209
211
|
[pip-audit status]: https://docs.arrai.dev/dssc/artifacts/main/pip-audit.svg
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
django_session_security_continued-3.0.0a2.dist-info/licenses/LICENSE,sha256=sTEwnChiEDBXv8ZDFVYDAhXfIA1wjpwuIhTVDhGLssw,1107
|
|
2
|
+
session_security/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
session_security/middleware.py,sha256=matyK1lCSv5ZeIRWoxj-yThKNDMHRUM1Xf929pWTVmE,4008
|
|
4
|
+
session_security/models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
+
session_security/settings.py,sha256=pIxklXg3F1uyvsb0dl7ArQ0vquWLCie0CC5vy_fICas,2242
|
|
6
|
+
session_security/urls.py,sha256=QK_diUsqjyQkU6UQpUW9SV_3kpf0223glrtnM7jft7M,510
|
|
7
|
+
session_security/utils.py,sha256=d19NpP7f5kEdrVdZIae95c-Oeuw9gk0m4pATzuzlw3w,466
|
|
8
|
+
session_security/views.py,sha256=ktla3T5Pk8qajdVTIhatWKprm10iIjM-Ek495APDBLs,879
|
|
9
|
+
session_security/locale/ca/LC_MESSAGES/django.po,sha256=8YFDOajFwTFzf9CCl72LgWNs_qCaE6qEk6o1kgGG-7A,1131
|
|
10
|
+
session_security/locale/cs/LC_MESSAGES/django.po,sha256=9Pm6VHWXAqJiKKiblsIkm90WmnWmH2nolLjRRpKZsUU,1087
|
|
11
|
+
session_security/locale/de/LC_MESSAGES/django.po,sha256=apFmNzpW05ifHi1b_gDjKgxqbtrwz0TvtmvbTJrRPxw,1041
|
|
12
|
+
session_security/locale/es/LC_MESSAGES/django.po,sha256=c4cjeFUCCdQ5tJ9h44MrHAJnorsCGy6-ccjscrIteIA,1113
|
|
13
|
+
session_security/locale/fr/LC_MESSAGES/django.po,sha256=hdSp5VQdYX59z397bIQwSHymlCzgi61VRZYxPWeTz9U,1054
|
|
14
|
+
session_security/locale/it/LC_MESSAGES/django.po,sha256=8R2M_4MJreW1-_EDI_h_eNMzFnYrLfOmnOUqLTD3hDc,1130
|
|
15
|
+
session_security/locale/nl/LC_MESSAGES/django.po,sha256=UqCiUJDB5rnZNmS4mzo6ko3lG-Q2mDiSki3_fBlzxRY,1071
|
|
16
|
+
session_security/locale/pl/LC_MESSAGES/django.po,sha256=Wl4dQj--cRmPUQ_ysa07fy1G4GFkMBOvu_laDutX3nY,1285
|
|
17
|
+
session_security/locale/pt_BR/LC_MESSAGES/django.po,sha256=BU2U8nH1g6p65KSpzedLqymnHfhMwPwBDkquVPo7nKo,1021
|
|
18
|
+
session_security/locale/pt_PT/LC_MESSAGES/django.po,sha256=K3ss4zjKO90ALOzEY0Q3Ffe_GaSPXAOj5doSxR_ZL00,989
|
|
19
|
+
session_security/static/session_security/script.js,sha256=XePGKd6wEZQMnwUaSFX-3tW3MCNOb_BvM_ByOTe9siI,8614
|
|
20
|
+
session_security/static/session_security/style.css,sha256=11eLkqYNauOZBdXQAyLlSq0vC1dVdJNRHZBcUui54YY,558
|
|
21
|
+
session_security/templates/session_security/all.html,sha256=m1W6pX-4eTwIvjWU8fL40Ft1Gn_Q0uGJbG2gl6EVpuI,1777
|
|
22
|
+
session_security/templates/session_security/dialog.html,sha256=63GLn2f0H9vfoy3FlKzI6S3WChRfVmpdF1qif6_9IgY,451
|
|
23
|
+
session_security/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
|
+
session_security/templatetags/session_security_tags.py,sha256=Vhrxe0ThWpEbQZUlqxKl9XXOx8HhF96EoBmVk5hxhrc,627
|
|
25
|
+
session_security/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
|
+
session_security/tests/conftest.py,sha256=uT2X0J7uzmQD6TEPN86RtgkigC298BNMEl3UPu97nUE,5067
|
|
27
|
+
session_security/tests/test_base.py,sha256=bvqz385wyyBQNhrpeTyUTY0fWosLB9wOhPOBrt0tOBM,1775
|
|
28
|
+
session_security/tests/test_middleware.py,sha256=iLFlXXfoBwUBNUJPhyRvPR657y-MORj1nyjh3GXFNPc,3612
|
|
29
|
+
session_security/tests/test_packaging.py,sha256=MBoXky_pAWo_PFnZE1m_0p2h_kAX6nrCVxIPKmBcKpY,399
|
|
30
|
+
session_security/tests/test_script.py,sha256=nyPNrWJJ5F8TIrVwA-k-j8km3wrN6znW8WngViA63dk,2703
|
|
31
|
+
session_security/tests/test_templates.py,sha256=qXukArdCZvvthGLyHZzise9xV6Q8kFx-eUy8TCxsYXU,471
|
|
32
|
+
session_security/tests/test_views.py,sha256=97Ssf4nXGj0OIGc-fFf3_LdjC3k9yFMr6QD9CRsTrLc,1183
|
|
33
|
+
session_security/tests/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
34
|
+
session_security/tests/project/settings.py,sha256=BAN820rroRvYMKQPtTYvqkdjmy9ce5fznFWelrBG58c,2999
|
|
35
|
+
session_security/tests/project/urls.py,sha256=wFMGt1wQLCdoaAsJRltFypR473RJnkxbqReWh0FMFWE,1136
|
|
36
|
+
session_security/tests/project/wsgi.py,sha256=VFz8yKLbSm4-C5ejuLJ_ZuPoKZ1WP17WJVMx2R17Z8M,426
|
|
37
|
+
django_session_security_continued-3.0.0a2.dist-info/METADATA,sha256=_5RWprGJtAWE1r0ro0PdNVIIss63a-9uKFyXWKJO_aE,9070
|
|
38
|
+
django_session_security_continued-3.0.0a2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
39
|
+
django_session_security_continued-3.0.0a2.dist-info/top_level.txt,sha256=sUgnA1DNG4V434n9luYoNsltkfMgkCnI6GBZV6oKWJI,17
|
|
40
|
+
django_session_security_continued-3.0.0a2.dist-info/RECORD,,
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# SOME DESCRIPTIVE TITLE.
|
|
2
|
+
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
3
|
+
# This file is distributed under the same license as the PACKAGE package.
|
|
4
|
+
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
5
|
+
#
|
|
6
|
+
# , fuzzy
|
|
7
|
+
msgid ""
|
|
8
|
+
msgstr ""
|
|
9
|
+
"Project-Id-Version: PACKAGE VERSION\n"
|
|
10
|
+
"Report-Msgid-Bugs-To: \n"
|
|
11
|
+
"POT-Creation-Date: 2020-01-23 08:23+0100\n"
|
|
12
|
+
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
|
13
|
+
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
14
|
+
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
15
|
+
"Language: \n"
|
|
16
|
+
"MIME-Version: 1.0\n"
|
|
17
|
+
"Content-Type: text/plain; charset=UTF-8\n"
|
|
18
|
+
"Content-Transfer-Encoding: 8bit\n"
|
|
19
|
+
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
20
|
+
#: session_security/templates/session_security/all.html:32
|
|
21
|
+
msgid "You have unsaved changes in a form of this page."
|
|
22
|
+
msgstr "Un formulari d'aquesta pàgina té canvis sense guardar"
|
|
23
|
+
|
|
24
|
+
#: session_security/templates/session_security/dialog.html:6
|
|
25
|
+
msgid "Your session is about to expire"
|
|
26
|
+
msgstr "La teva sessió està a punt de caducar"
|
|
27
|
+
|
|
28
|
+
#: session_security/templates/session_security/dialog.html:7
|
|
29
|
+
msgid "Click or type to extend your session."
|
|
30
|
+
msgstr "Fes clic o premi una tecla per a continuar la sessió"
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Czech translation for the django-session-security app.
|
|
2
|
+
# Copyright (C) 2016 IT Management
|
|
3
|
+
# This file is distributed under the same license as the django-session-security package.
|
|
4
|
+
#
|
|
5
|
+
#, fuzzy
|
|
6
|
+
msgid ""
|
|
7
|
+
msgstr ""
|
|
8
|
+
"Project-Id-Version: PACKAGE VERSION\n"
|
|
9
|
+
"Report-Msgid-Bugs-To: \n"
|
|
10
|
+
"POT-Creation-Date: 2016-05-18 15:58+0200\n"
|
|
11
|
+
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
|
12
|
+
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
13
|
+
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
14
|
+
"Language: \n"
|
|
15
|
+
"MIME-Version: 1.0\n"
|
|
16
|
+
"Content-Type: text/plain; charset=UTF-8\n"
|
|
17
|
+
"Content-Transfer-Encoding: 8bit\n"
|
|
18
|
+
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
|
19
|
+
|
|
20
|
+
#: templates/session_security/all.html:33
|
|
21
|
+
msgid "You have unsaved changes in a form of this page."
|
|
22
|
+
msgstr "Ve formuláři na této stránce máte neuložené změny."
|
|
23
|
+
|
|
24
|
+
#: templates/session_security/dialog.html:6
|
|
25
|
+
msgid "Your session is about to expire"
|
|
26
|
+
msgstr "Vaše přihlášení brzy vyprší"
|
|
27
|
+
|
|
28
|
+
#: templates/session_security/dialog.html:7
|
|
29
|
+
msgid "Click to extend your session."
|
|
30
|
+
msgstr "Klikněte pro prodloužení vašeho přihlášení."
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Copyright (C) 2013 James Pic
|
|
2
|
+
# This file is distributed under the same license as the
|
|
3
|
+
# django-session-security package.
|
|
4
|
+
# James Pic <jamespic@gmail.com> 2013
|
|
5
|
+
msgid ""
|
|
6
|
+
msgstr ""
|
|
7
|
+
"Project-Id-Version: 2.0.3\n"
|
|
8
|
+
"Report-Msgid-Bugs-To: \n"
|
|
9
|
+
"POT-Creation-Date: 2024-03-18 11:41-0400\n"
|
|
10
|
+
"PO-Revision-Date: 2024-03-18 16:26+0100\n"
|
|
11
|
+
"Last-Translator: Daniel Zielinski <daniel@loctimize.com>\n"
|
|
12
|
+
"Language: German\n"
|
|
13
|
+
"MIME-Version: 1.0\n"
|
|
14
|
+
"Content-Type: text/plain; charset=UTF-8\n"
|
|
15
|
+
"Content-Transfer-Encoding: 8bit\n"
|
|
16
|
+
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
|
17
|
+
|
|
18
|
+
#: templates/session_security/all.html:32
|
|
19
|
+
msgid "You have unsaved changes in a form of this page."
|
|
20
|
+
msgstr ""
|
|
21
|
+
"Sie haben nicht gespeicherte Änderungen in einem Formular auf dieser Seite."
|
|
22
|
+
|
|
23
|
+
#: templates/session_security/dialog.html:6
|
|
24
|
+
msgid "Your session is about to expire"
|
|
25
|
+
msgstr "Ihre Sitzung läuft in Kürze ab."
|
|
26
|
+
|
|
27
|
+
#: templates/session_security/dialog.html:7
|
|
28
|
+
msgid "Click or type to extend your session."
|
|
29
|
+
msgstr "Klicken oder tippen Sie, um nicht automatisch ausgeloggt zu werden."
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Spanish translation for the django-session-security app.
|
|
2
|
+
# Copyright (C) 2014
|
|
3
|
+
# This file is distributed under the same license as the django-session-security package.
|
|
4
|
+
# Jose Antonio Martin <jantonio.martin@gmail.com>, 2014.
|
|
5
|
+
#
|
|
6
|
+
#, fuzzy
|
|
7
|
+
msgid ""
|
|
8
|
+
msgstr ""
|
|
9
|
+
"Project-Id-Version: PACKAGE VERSION\n"
|
|
10
|
+
"Report-Msgid-Bugs-To: \n"
|
|
11
|
+
"POT-Creation-Date: 2014-03-13 12:36+0100\n"
|
|
12
|
+
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
|
13
|
+
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
14
|
+
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
15
|
+
"Language: \n"
|
|
16
|
+
"MIME-Version: 1.0\n"
|
|
17
|
+
"Content-Type: text/plain; charset=UTF-8\n"
|
|
18
|
+
"Content-Transfer-Encoding: 8bit\n"
|
|
19
|
+
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
20
|
+
|
|
21
|
+
#: templates/session_security/all.html:33
|
|
22
|
+
msgid "You have unsaved changes in a form of this page."
|
|
23
|
+
msgstr "Un formulario de esta página tiene cambios sin guardar"
|
|
24
|
+
|
|
25
|
+
#: templates/session_security/dialog.html:6
|
|
26
|
+
msgid "Your session is about to expire"
|
|
27
|
+
msgstr "Tu sesión está a punto de caducar"
|
|
28
|
+
|
|
29
|
+
#: templates/session_security/dialog.html:7
|
|
30
|
+
msgid "Click or type to extend your session."
|
|
31
|
+
msgstr "Haz click o pulse una tecla para continuar la sesión"
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Copyright (C) 2013 James Pic
|
|
2
|
+
# This file is distributed under the same license as the
|
|
3
|
+
# django-session-security package.
|
|
4
|
+
# James Pic <jamespic@gmail.com> 2013
|
|
5
|
+
msgid ""
|
|
6
|
+
msgstr ""
|
|
7
|
+
"Project-Id-Version: 2.0.3\n"
|
|
8
|
+
"Report-Msgid-Bugs-To: \n"
|
|
9
|
+
"POT-Creation-Date: 2018-10-23 11:41-0400\n"
|
|
10
|
+
"PO-Revision-Date: 2013-02-19 16:26+0100\n"
|
|
11
|
+
"Last-Translator: James Pic <jamespic@gmail.com>\n"
|
|
12
|
+
"Language: French\n"
|
|
13
|
+
"MIME-Version: 1.0\n"
|
|
14
|
+
"Content-Type: text/plain; charset=UTF-8\n"
|
|
15
|
+
"Content-Transfer-Encoding: 8bit\n"
|
|
16
|
+
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
|
17
|
+
|
|
18
|
+
#: templates/session_security/all.html:32
|
|
19
|
+
msgid "You have unsaved changes in a form of this page."
|
|
20
|
+
msgstr ""
|
|
21
|
+
"Vous avez des changements non sauvegardés dans un formulaire de cette page."
|
|
22
|
+
|
|
23
|
+
#: templates/session_security/dialog.html:6
|
|
24
|
+
msgid "Your session is about to expire"
|
|
25
|
+
msgstr "Votre session est sur le point d'expirer"
|
|
26
|
+
|
|
27
|
+
#: templates/session_security/dialog.html:7
|
|
28
|
+
msgid "Click or type to extend your session."
|
|
29
|
+
msgstr "Touchez la souris ou tapez votre clavier pour étendre la durée de votre session."
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Italian translation for the django-session-security app.
|
|
2
|
+
# Copyright (C) 2019
|
|
3
|
+
# This file is distributed under the same license as the django-session-security package.
|
|
4
|
+
# Ali Hasan Imam <imam.aiub@gmail.com>, 2019.
|
|
5
|
+
#
|
|
6
|
+
#, fuzzy
|
|
7
|
+
msgid ""
|
|
8
|
+
msgstr ""
|
|
9
|
+
"Project-Id-Version: PACKAGE VERSION\n"
|
|
10
|
+
"Report-Msgid-Bugs-To: \n"
|
|
11
|
+
"POT-Creation-Date: 2019-05-14 14:35+0200\n"
|
|
12
|
+
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
|
13
|
+
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
14
|
+
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
15
|
+
"Language: \n"
|
|
16
|
+
"MIME-Version: 1.0\n"
|
|
17
|
+
"Content-Type: text/plain; charset=UTF-8\n"
|
|
18
|
+
"Content-Transfer-Encoding: 8bit\n"
|
|
19
|
+
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
20
|
+
|
|
21
|
+
#: session_security/templates/session_security/all.html:32
|
|
22
|
+
msgid "You have unsaved changes in a form of this page."
|
|
23
|
+
msgstr "Hai modifiche non salvate nella form di questa pagina."
|
|
24
|
+
|
|
25
|
+
#: session_security/templates/session_security/dialog.html:6
|
|
26
|
+
msgid "Your session is about to expire"
|
|
27
|
+
msgstr "La tua sessione sta per scadere"
|
|
28
|
+
|
|
29
|
+
#: session_security/templates/session_security/dialog.html:7
|
|
30
|
+
msgid "Click or type to extend your session."
|
|
31
|
+
msgstr "Fai clic per estendere la sessione."
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Dutch translation for the django-session-security app.
|
|
2
|
+
# Copyright (C) 2014
|
|
3
|
+
# This file is distributed under the same license as the django-session-security package.
|
|
4
|
+
# Rik Dekker <rdekker@jouwomgeving.nl>, 2016.
|
|
5
|
+
#
|
|
6
|
+
msgid ""
|
|
7
|
+
msgstr ""
|
|
8
|
+
"Project-Id-Version: \n"
|
|
9
|
+
"Report-Msgid-Bugs-To: \n"
|
|
10
|
+
"POT-Creation-Date: 2014-03-13 12:36+0100\n"
|
|
11
|
+
"PO-Revision-Date: 2018-05-14 08:56+0200\n"
|
|
12
|
+
"Language: nl\n"
|
|
13
|
+
"MIME-Version: 1.0\n"
|
|
14
|
+
"Content-Type: text/plain; charset=UTF-8\n"
|
|
15
|
+
"Content-Transfer-Encoding: 8bit\n"
|
|
16
|
+
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
17
|
+
"Last-Translator: Rik Dekker <rdekker@jouwomgeving.nl>\n"
|
|
18
|
+
"Language-Team: \n"
|
|
19
|
+
"X-Generator: Poedit 2.0.6\n"
|
|
20
|
+
|
|
21
|
+
#: templates/session_security/all.html:33
|
|
22
|
+
msgid "You have unsaved changes in a form of this page."
|
|
23
|
+
msgstr "Je hebt niet-opgeslagen wijzigingen op deze pagina."
|
|
24
|
+
|
|
25
|
+
#: templates/session_security/dialog.html:6
|
|
26
|
+
msgid "Your session is about to expire"
|
|
27
|
+
msgstr "Jouw sessie verloopt bijna"
|
|
28
|
+
|
|
29
|
+
#: templates/session_security/dialog.html:7
|
|
30
|
+
msgid "Click or type to extend your session."
|
|
31
|
+
msgstr "Klik of typ om je sessie te verlengen."
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# SOME DESCRIPTIVE TITLE.
|
|
2
|
+
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
|
3
|
+
# This file is distributed under the same license as the PACKAGE package.
|
|
4
|
+
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
5
|
+
#
|
|
6
|
+
msgid ""
|
|
7
|
+
msgstr ""
|
|
8
|
+
"Project-Id-Version: django-session-security\n"
|
|
9
|
+
"Report-Msgid-Bugs-To: \n"
|
|
10
|
+
"POT-Creation-Date: 2017-06-26 12:42+0200\n"
|
|
11
|
+
"PO-Revision-Date: 2017-06-26 12:44+0200\n"
|
|
12
|
+
"Last-Translator: Michał Pasternak <michal.dtz@gmail.com>\n"
|
|
13
|
+
"Language: pl\n"
|
|
14
|
+
"MIME-Version: 1.0\n"
|
|
15
|
+
"Content-Type: text/plain; charset=UTF-8\n"
|
|
16
|
+
"Content-Transfer-Encoding: 8bit\n"
|
|
17
|
+
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
|
|
18
|
+
"|| n%100>=20) ? 1 : 2);\n"
|
|
19
|
+
"X-Generator: Poedit 2.0.2\n"
|
|
20
|
+
"Language-Team: \n"
|
|
21
|
+
|
|
22
|
+
#: session_security/templates/session_security/all.html:32
|
|
23
|
+
msgid "You have unsaved changes in a form of this page."
|
|
24
|
+
msgstr ""
|
|
25
|
+
"Na tej stronie znajduje się formularz, w którym zmiany mogły jeszcze nie "
|
|
26
|
+
"zostać zapisane."
|
|
27
|
+
|
|
28
|
+
#: session_security/templates/session_security/dialog.html:6
|
|
29
|
+
msgid "Your session is about to expire"
|
|
30
|
+
msgstr "Twoja sesja za chwilę wygaśnie"
|
|
31
|
+
|
|
32
|
+
#: session_security/templates/session_security/dialog.html:7
|
|
33
|
+
msgid "Click or type to extend your session."
|
|
34
|
+
msgstr ""
|
|
35
|
+
"Kliknij lub wciśnij dowolny klawisz, aby wydłużyć czas trwania Twojej sesji."
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Copyright (C) 2013 James Pic
|
|
2
|
+
# This file is distributed under the same license as the
|
|
3
|
+
# django-session-security package.
|
|
4
|
+
# James Pic <jamespic@gmail.com> 2013
|
|
5
|
+
msgid ""
|
|
6
|
+
msgstr ""
|
|
7
|
+
"Project-Id-Version: 2.0.3\n"
|
|
8
|
+
"Report-Msgid-Bugs-To: \n"
|
|
9
|
+
"POT-Creation-Date: 2013-12-06 18:00-0300\n"
|
|
10
|
+
"PO-Revision-Date: 2013-12-06 18:00-0300\n"
|
|
11
|
+
"Last-Translator: Fabio Caritas Barrionuevo da Luz <bnafta at gmail.com>\n"
|
|
12
|
+
"Language: Brazilian Portuguese\n"
|
|
13
|
+
"MIME-Version: 1.0\n"
|
|
14
|
+
"Content-Type: text/plain; charset=UTF-8\n"
|
|
15
|
+
"Content-Transfer-Encoding: 8bit\n"
|
|
16
|
+
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
|
17
|
+
|
|
18
|
+
#: templates/session_security/all.html:32
|
|
19
|
+
msgid "You have unsaved changes in a form of this page."
|
|
20
|
+
msgstr "Você tem alterações não salvas em um formulário desta página."
|
|
21
|
+
|
|
22
|
+
#: templates/session_security/dialog.html:6
|
|
23
|
+
msgid "Your session is about to expire"
|
|
24
|
+
msgstr "Sua sessão está prestes a expirar"
|
|
25
|
+
|
|
26
|
+
#: templates/session_security/dialog.html:7
|
|
27
|
+
msgid "Click to extend your session."
|
|
28
|
+
msgstr "Clique para prolongar a sua sessão."
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Copyright (C) 2015 Nuno Khan
|
|
2
|
+
# This file is distributed under the same license as the
|
|
3
|
+
# django-session-security package.
|
|
4
|
+
# Nuno Khan <nunok7@gmail.com> 2015
|
|
5
|
+
msgid ""
|
|
6
|
+
msgstr ""
|
|
7
|
+
"Project-Id-Version: 2.0.3\n"
|
|
8
|
+
"Report-Msgid-Bugs-To: \n"
|
|
9
|
+
"POT-Creation-Date: 2015-06-16 16:29+0100\n"
|
|
10
|
+
"PO-Revision-Date: 2015-09-18 18:00-0300\n"
|
|
11
|
+
"Last-Translator: Nuno Khan <nunok7 at gmail.com>\n"
|
|
12
|
+
"Language: Portuguese\n"
|
|
13
|
+
"MIME-Version: 1.0\n"
|
|
14
|
+
"Content-Type: text/plain; charset=UTF-8\n"
|
|
15
|
+
"Content-Transfer-Encoding: 8bit\n"
|
|
16
|
+
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
|
17
|
+
|
|
18
|
+
#: templates/session_security/all.html:33
|
|
19
|
+
msgid "You have unsaved changes in a form of this page."
|
|
20
|
+
msgstr "Você tem alterações não guardadas em um formulário desta página."
|
|
21
|
+
|
|
22
|
+
#: templates/session_security/dialog.html:6
|
|
23
|
+
msgid "Your session is about to expire"
|
|
24
|
+
msgstr "Sua sessão está prestes a expirar"
|
|
25
|
+
|
|
26
|
+
#: templates/session_security/dialog.html:7
|
|
27
|
+
msgid "Click to extend your session."
|
|
28
|
+
msgstr "Clique para prolongar a sua sessão."
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
(function (globalWindow, globalDocument) {
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
if (typeof globalWindow.yourlabs === "undefined") {
|
|
5
|
+
globalWindow.yourlabs = {};
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function assign(target, source) {
|
|
9
|
+
if (!source) {
|
|
10
|
+
return target;
|
|
11
|
+
}
|
|
12
|
+
Object.keys(source).forEach(function (key) {
|
|
13
|
+
target[key] = source[key];
|
|
14
|
+
});
|
|
15
|
+
return target;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function buildUrl(url, params) {
|
|
19
|
+
let hasQuery = url.indexOf("?") !== -1;
|
|
20
|
+
let query = [];
|
|
21
|
+
for (let key in params) {
|
|
22
|
+
if (Object.prototype.hasOwnProperty.call(params, key)) {
|
|
23
|
+
query.push(encodeURIComponent(key) + "=" + encodeURIComponent(params[key]));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return url + (hasQuery ? "&" : "?") + query.join("&");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function hasDirtyForms() {
|
|
30
|
+
return globalDocument.querySelector("form[data-dirty]") !== null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function SessionSecurity(options) {
|
|
34
|
+
this.warning = globalDocument.getElementById("session_security_warning");
|
|
35
|
+
this.warningVisible = false;
|
|
36
|
+
this.lastActivity = new Date();
|
|
37
|
+
this.events = [
|
|
38
|
+
"mousemove",
|
|
39
|
+
"scroll",
|
|
40
|
+
"keyup",
|
|
41
|
+
"click",
|
|
42
|
+
"touchstart",
|
|
43
|
+
"touchend",
|
|
44
|
+
"touchmove",
|
|
45
|
+
];
|
|
46
|
+
this.counterElementID = "session_security_counter";
|
|
47
|
+
this.expired = false;
|
|
48
|
+
this.counterStarted = false;
|
|
49
|
+
this.timeout = null;
|
|
50
|
+
this.counterTimeout = null;
|
|
51
|
+
|
|
52
|
+
assign(this, options || {});
|
|
53
|
+
|
|
54
|
+
let self = this;
|
|
55
|
+
this.activityHandler = this.activity.bind(this);
|
|
56
|
+
this.events.forEach(function (eventName) {
|
|
57
|
+
globalDocument.addEventListener(eventName, self.activityHandler, true);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
if (this.confirmFormDiscard) {
|
|
61
|
+
this.beforeUnloadHandler = this.onbeforeunload.bind(this);
|
|
62
|
+
globalWindow.addEventListener("beforeunload", this.beforeUnloadHandler);
|
|
63
|
+
globalDocument.addEventListener(
|
|
64
|
+
"change",
|
|
65
|
+
function (event) {
|
|
66
|
+
self.formChange(event);
|
|
67
|
+
},
|
|
68
|
+
true,
|
|
69
|
+
);
|
|
70
|
+
globalDocument.addEventListener(
|
|
71
|
+
"submit",
|
|
72
|
+
function (event) {
|
|
73
|
+
self.formClean(event);
|
|
74
|
+
},
|
|
75
|
+
true,
|
|
76
|
+
);
|
|
77
|
+
globalDocument.addEventListener(
|
|
78
|
+
"reset",
|
|
79
|
+
function (event) {
|
|
80
|
+
self.formClean(event);
|
|
81
|
+
},
|
|
82
|
+
true,
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
this.apply();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
SessionSecurity.prototype.expire = function () {
|
|
90
|
+
if (this.expired) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
this.expired = true;
|
|
94
|
+
if (typeof this.returnToUrl === "string" && this.returnToUrl.length > 0) {
|
|
95
|
+
globalWindow.location.href = this.returnToUrl;
|
|
96
|
+
} else {
|
|
97
|
+
globalWindow.location.reload();
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
SessionSecurity.prototype.showWarning = function () {
|
|
102
|
+
if (!this.warning) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
this.warning.style.display = "block";
|
|
106
|
+
this.warning.setAttribute("aria-hidden", "false");
|
|
107
|
+
this.warningVisible = true;
|
|
108
|
+
let modal = this.warning.querySelector(".session_security_modal");
|
|
109
|
+
if (modal && typeof modal.focus === "function") {
|
|
110
|
+
modal.focus();
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
SessionSecurity.prototype.hideWarning = function () {
|
|
115
|
+
if (!this.warning) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
this.warning.style.display = "none";
|
|
119
|
+
this.warning.setAttribute("aria-hidden", "true");
|
|
120
|
+
this.warningVisible = false;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
SessionSecurity.prototype.activity = function () {
|
|
124
|
+
let now = new Date();
|
|
125
|
+
if (now - this.lastActivity < 1000) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
let idleFor = Math.floor((now - this.lastActivity) / 1000);
|
|
130
|
+
this.lastActivity = now;
|
|
131
|
+
|
|
132
|
+
if (idleFor >= this.expireAfter) {
|
|
133
|
+
this.expire();
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (this.warningVisible) {
|
|
138
|
+
this.ping();
|
|
139
|
+
this.hideWarning();
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
SessionSecurity.prototype.ping = function () {
|
|
144
|
+
let idleFor = Math.floor((new Date() - this.lastActivity) / 1000);
|
|
145
|
+
let self = this;
|
|
146
|
+
|
|
147
|
+
fetch(buildUrl(this.pingUrl, { idleFor: idleFor }), {
|
|
148
|
+
method: "GET",
|
|
149
|
+
credentials: "same-origin",
|
|
150
|
+
cache: "no-store",
|
|
151
|
+
headers: {
|
|
152
|
+
"X-Requested-With": "XMLHttpRequest",
|
|
153
|
+
},
|
|
154
|
+
})
|
|
155
|
+
.then(function (response) {
|
|
156
|
+
return response.json();
|
|
157
|
+
})
|
|
158
|
+
.then(function (data) {
|
|
159
|
+
self.pong(data);
|
|
160
|
+
})
|
|
161
|
+
.catch(function () {
|
|
162
|
+
self.apply();
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
SessionSecurity.prototype.pong = function (data) {
|
|
167
|
+
if (data === "logout") {
|
|
168
|
+
this.expire();
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
this.lastActivity = new Date();
|
|
173
|
+
this.lastActivity.setSeconds(this.lastActivity.getSeconds() - data);
|
|
174
|
+
this.apply();
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
SessionSecurity.prototype.apply = function () {
|
|
178
|
+
clearTimeout(this.timeout);
|
|
179
|
+
let idleFor = Math.floor((new Date() - this.lastActivity) / 1000);
|
|
180
|
+
let nextPing;
|
|
181
|
+
|
|
182
|
+
if (idleFor >= this.expireAfter) {
|
|
183
|
+
this.expire();
|
|
184
|
+
return;
|
|
185
|
+
} else if (idleFor >= this.warnAfter) {
|
|
186
|
+
if (!this.counterStarted && this.counterElementID) {
|
|
187
|
+
this.startCounter();
|
|
188
|
+
}
|
|
189
|
+
this.showWarning();
|
|
190
|
+
nextPing = this.expireAfter - idleFor;
|
|
191
|
+
} else {
|
|
192
|
+
this.hideWarning();
|
|
193
|
+
if (this.counterStarted && this.counterElementID) {
|
|
194
|
+
this.stopCounter();
|
|
195
|
+
}
|
|
196
|
+
nextPing = this.warnAfter - idleFor;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
let milliseconds = Math.min(nextPing * 1000, 2147483647);
|
|
200
|
+
let self = this;
|
|
201
|
+
this.timeout = setTimeout(function () {
|
|
202
|
+
self.ping();
|
|
203
|
+
}, milliseconds);
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
SessionSecurity.prototype.startCounter = function () {
|
|
207
|
+
if (!this.counterElementID) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
let element = globalDocument.getElementById(this.counterElementID);
|
|
211
|
+
if (!element) {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
let expireAfter = this.expireAfter;
|
|
215
|
+
let warnAfter = this.warnAfter;
|
|
216
|
+
let defaultTimeLeft = expireAfter - warnAfter;
|
|
217
|
+
|
|
218
|
+
if (!this.counterStarted) {
|
|
219
|
+
element.textContent = defaultTimeLeft.toString();
|
|
220
|
+
this.counterStarted = true;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
let endTime = new Date();
|
|
224
|
+
endTime.setSeconds(endTime.getSeconds() + defaultTimeLeft);
|
|
225
|
+
this.counterTimeout = setInterval(function () {
|
|
226
|
+
let now = new Date().getTime();
|
|
227
|
+
let distance = endTime - now;
|
|
228
|
+
let seconds = Math.max(0, Math.floor((distance % (1000 * expireAfter)) / 1000));
|
|
229
|
+
if (distance > 0) {
|
|
230
|
+
element.textContent = seconds.toString();
|
|
231
|
+
}
|
|
232
|
+
}, 1000);
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
SessionSecurity.prototype.stopCounter = function () {
|
|
236
|
+
if (!this.counterElementID) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
let element = globalDocument.getElementById(this.counterElementID);
|
|
240
|
+
if (!element) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
clearInterval(this.counterTimeout);
|
|
244
|
+
this.counterStarted = false;
|
|
245
|
+
let defaultTimeLeft = this.expireAfter - this.warnAfter;
|
|
246
|
+
element.textContent = defaultTimeLeft.toString();
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
SessionSecurity.prototype.onbeforeunload = function (event) {
|
|
250
|
+
if (this.expired || !this.confirmFormDiscard) {
|
|
251
|
+
return undefined;
|
|
252
|
+
}
|
|
253
|
+
if (hasDirtyForms()) {
|
|
254
|
+
event.preventDefault();
|
|
255
|
+
event.returnValue = this.confirmFormDiscard;
|
|
256
|
+
return this.confirmFormDiscard;
|
|
257
|
+
}
|
|
258
|
+
return undefined;
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
SessionSecurity.prototype.formChange = function (event) {
|
|
262
|
+
if (!event.target || typeof event.target.closest !== "function") {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
let form = event.target.closest("form");
|
|
266
|
+
if (form) {
|
|
267
|
+
form.setAttribute("data-dirty", "true");
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
SessionSecurity.prototype.formClean = function (event) {
|
|
272
|
+
if (!event.target || typeof event.target.closest !== "function") {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
let form = event.target.closest("form");
|
|
276
|
+
if (form) {
|
|
277
|
+
form.removeAttribute("data-dirty");
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
globalWindow.yourlabs.SessionSecurity = SessionSecurity;
|
|
282
|
+
})(window, document);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/* credit: http://www.csslab.cl/2008/01/30/ventana-modal-solo-con-css/ */
|
|
2
|
+
.session_security_overlay {
|
|
3
|
+
position: fixed;
|
|
4
|
+
top: 0;
|
|
5
|
+
left: 0;
|
|
6
|
+
width: 100%;
|
|
7
|
+
height: 100%;
|
|
8
|
+
background: #000;
|
|
9
|
+
z-index: 1001;
|
|
10
|
+
opacity: 0.75;
|
|
11
|
+
-moz-opacity: 0.75;
|
|
12
|
+
filter: alpha(opacity=75);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.session_security_modal {
|
|
16
|
+
position: fixed;
|
|
17
|
+
top: 25%;
|
|
18
|
+
left: 25%;
|
|
19
|
+
width: 50%;
|
|
20
|
+
padding: 16px;
|
|
21
|
+
background: #fff;
|
|
22
|
+
color: #333;
|
|
23
|
+
z-index: 1002;
|
|
24
|
+
overflow: auto;
|
|
25
|
+
text-align: center;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.session_security {
|
|
29
|
+
display: none;
|
|
30
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
This demonstrates how to setup session security client side stuff on your own.
|
|
3
|
+
It provides sensible defaults so you could start with just::
|
|
4
|
+
|
|
5
|
+
{% include 'session_security/all.html' %}
|
|
6
|
+
|
|
7
|
+
{% endcomment %}
|
|
8
|
+
|
|
9
|
+
{% load session_security_tags %}
|
|
10
|
+
{% load i18n l10n %}
|
|
11
|
+
{% load static %}
|
|
12
|
+
|
|
13
|
+
{# If the user is not authenticated then there is no session to secure ! #}
|
|
14
|
+
{% if request.user.is_authenticated %}
|
|
15
|
+
|
|
16
|
+
{# The modal dialog stylesheet, it's pretty light so it should be easy to hack #}
|
|
17
|
+
<link rel="stylesheet" type="text/css" href="{% static 'session_security/style.css' %}">
|
|
18
|
+
|
|
19
|
+
{# Include the template that actually contains the modal dialog #}
|
|
20
|
+
{% include 'session_security/dialog.html' %}
|
|
21
|
+
|
|
22
|
+
{% session_security_script_path as session_security_js %}
|
|
23
|
+
{# Load SessionSecurity javascript 'class' #}
|
|
24
|
+
<script type="text/javascript" src="{% static session_security_js %}"></script>
|
|
25
|
+
|
|
26
|
+
{# Bootstrap a SessionSecurity instance as the sessionSecurity global variable #}
|
|
27
|
+
{% localize off %}
|
|
28
|
+
<script type="text/javascript"{% if request.csp_nonce %} nonce="{{ request.csp_nonce }}"{% endif %}>
|
|
29
|
+
var sessionSecurity = new yourlabs.SessionSecurity({
|
|
30
|
+
pingUrl: '{% url 'session_security_ping' %}',
|
|
31
|
+
warnAfter: {{ request|warn_after|unlocalize }},
|
|
32
|
+
expireAfter: {{ request|expire_after|unlocalize }},
|
|
33
|
+
{% with redirect_to_logout=request|redirect_to_logout %}
|
|
34
|
+
{% if redirect_to_logout %}
|
|
35
|
+
returnToUrl: {% url 'logout' %},
|
|
36
|
+
{% endif %}
|
|
37
|
+
{% endwith %}
|
|
38
|
+
confirmFormDiscard: "{% trans 'You have unsaved changes in a form of this page.' %}"
|
|
39
|
+
});
|
|
40
|
+
</script>
|
|
41
|
+
{% endlocalize %}
|
|
42
|
+
{% endif %}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{% load i18n %}
|
|
2
|
+
|
|
3
|
+
<div id="session_security_warning" class="session_security" aria-hidden="true" role="dialog">
|
|
4
|
+
<div class="session_security_overlay"></div>
|
|
5
|
+
<div class="session_security_modal" role="document" tabindex="-1">
|
|
6
|
+
<h3>{% trans 'Your session is about to expire' %}: <span id="session_security_counter"></span> {% trans 'seconds' %}</h3></h3>
|
|
7
|
+
<p>{% trans 'Click or type to extend your session.' %}</p>
|
|
8
|
+
</div>
|
|
9
|
+
</div>
|
|
@@ -16,8 +16,10 @@ from selenium.webdriver.common.by import By
|
|
|
16
16
|
class ActivityWindow:
|
|
17
17
|
min_warn_after: float
|
|
18
18
|
max_warn_after: float
|
|
19
|
+
warn_timeout: float
|
|
19
20
|
min_expire_after: float
|
|
20
21
|
max_expire_after: float
|
|
22
|
+
expire_timeout: float
|
|
21
23
|
|
|
22
24
|
|
|
23
25
|
@pytest.fixture
|
|
@@ -45,11 +47,14 @@ def authenticated_client(client, admin_user):
|
|
|
45
47
|
|
|
46
48
|
|
|
47
49
|
TIMEOUT_PADDING_ENV = "SESSION_SECURITY_TIMEOUT_PADDING"
|
|
50
|
+
CI_TIMEOUT_PADDING_DEFAULT = 2.0
|
|
48
51
|
|
|
49
52
|
|
|
50
53
|
def _timeout_padding_seconds() -> float:
|
|
51
54
|
raw_value = os.environ.get(TIMEOUT_PADDING_ENV)
|
|
52
|
-
if
|
|
55
|
+
if raw_value is None:
|
|
56
|
+
return CI_TIMEOUT_PADDING_DEFAULT if os.environ.get("CI") else 0.0
|
|
57
|
+
if raw_value == "":
|
|
53
58
|
return 0.0
|
|
54
59
|
try:
|
|
55
60
|
padding = float(raw_value)
|
|
@@ -67,12 +72,16 @@ def activity_window(settings):
|
|
|
67
72
|
padding = _timeout_padding_seconds()
|
|
68
73
|
warn_margin = 0.5 # always keep at least this much headroom before expiry
|
|
69
74
|
max_warn_cap = max(warn_after, expire_after - warn_margin)
|
|
70
|
-
max_warn_after =
|
|
75
|
+
max_warn_after = max_warn_cap
|
|
76
|
+
warn_timeout = max_warn_after + padding
|
|
77
|
+
max_expire_after = expire_after * 1.5
|
|
71
78
|
return ActivityWindow(
|
|
72
79
|
min_warn_after=warn_after,
|
|
73
80
|
max_warn_after=max_warn_after,
|
|
81
|
+
warn_timeout=warn_timeout,
|
|
74
82
|
min_expire_after=expire_after,
|
|
75
|
-
max_expire_after=
|
|
83
|
+
max_expire_after=max_expire_after,
|
|
84
|
+
expire_timeout=max_expire_after + padding,
|
|
76
85
|
)
|
|
77
86
|
|
|
78
87
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from django.template.loader import get_template
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@pytest.mark.parametrize(
|
|
6
|
+
"template_name",
|
|
7
|
+
[
|
|
8
|
+
"session_security/all.html",
|
|
9
|
+
"session_security/dialog.html",
|
|
10
|
+
],
|
|
11
|
+
)
|
|
12
|
+
def test_templates_are_discoverable(template_name):
|
|
13
|
+
"""Ensure Django can load templates shipped with the package."""
|
|
14
|
+
template = get_template(template_name)
|
|
15
|
+
assert template is not None
|
|
@@ -25,28 +25,28 @@ def test_warning_shows_and_session_expires(selenium_browser, activity_window):
|
|
|
25
25
|
start = datetime.datetime.now()
|
|
26
26
|
|
|
27
27
|
for _ in _iterate_windows(selenium_browser):
|
|
28
|
-
warning = WebDriverWait(selenium_browser, activity_window.
|
|
28
|
+
warning = WebDriverWait(selenium_browser, activity_window.warn_timeout).until(
|
|
29
29
|
expected_conditions.visibility_of_element_located((By.ID, "session_security_warning"))
|
|
30
30
|
)
|
|
31
31
|
assert warning.is_displayed()
|
|
32
32
|
|
|
33
|
-
delta = datetime.datetime.now() - start
|
|
34
|
-
assert delta
|
|
35
|
-
assert delta
|
|
33
|
+
delta = (datetime.datetime.now() - start).total_seconds()
|
|
34
|
+
assert delta >= activity_window.min_warn_after
|
|
35
|
+
assert delta <= activity_window.max_warn_after
|
|
36
36
|
|
|
37
37
|
for _ in _iterate_windows(selenium_browser):
|
|
38
|
-
password_field = WebDriverWait(selenium_browser, activity_window.
|
|
38
|
+
password_field = WebDriverWait(selenium_browser, activity_window.expire_timeout).until(
|
|
39
39
|
expected_conditions.visibility_of_element_located((By.ID, "id_password"))
|
|
40
40
|
)
|
|
41
41
|
assert password_field.is_displayed()
|
|
42
|
-
delta = datetime.datetime.now() - start
|
|
43
|
-
assert delta
|
|
44
|
-
assert delta
|
|
42
|
+
delta = (datetime.datetime.now() - start).total_seconds()
|
|
43
|
+
assert delta >= activity_window.min_expire_after
|
|
44
|
+
assert delta <= activity_window.max_expire_after
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
def test_activity_hides_warning(selenium_browser, activity_window):
|
|
48
48
|
time.sleep(activity_window.min_warn_after * 0.7)
|
|
49
|
-
WebDriverWait(selenium_browser, activity_window.
|
|
49
|
+
WebDriverWait(selenium_browser, activity_window.warn_timeout).until(
|
|
50
50
|
expected_conditions.visibility_of_element_located((By.ID, "session_security_warning"))
|
|
51
51
|
)
|
|
52
52
|
|
|
@@ -65,7 +65,7 @@ def test_activity_prevents_warning(selenium_browser, activity_window):
|
|
|
65
65
|
_press_space(selenium_browser)
|
|
66
66
|
start = datetime.datetime.now()
|
|
67
67
|
|
|
68
|
-
warning = WebDriverWait(selenium_browser, activity_window.
|
|
68
|
+
warning = WebDriverWait(selenium_browser, activity_window.warn_timeout).until(
|
|
69
69
|
expected_conditions.visibility_of_element_located((By.ID, "session_security_warning"))
|
|
70
70
|
)
|
|
71
71
|
assert warning.is_displayed()
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
django_session_security_continued-3.0.0a1.dist-info/licenses/LICENSE,sha256=sTEwnChiEDBXv8ZDFVYDAhXfIA1wjpwuIhTVDhGLssw,1107
|
|
2
|
-
session_security/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
session_security/middleware.py,sha256=matyK1lCSv5ZeIRWoxj-yThKNDMHRUM1Xf929pWTVmE,4008
|
|
4
|
-
session_security/models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
-
session_security/settings.py,sha256=pIxklXg3F1uyvsb0dl7ArQ0vquWLCie0CC5vy_fICas,2242
|
|
6
|
-
session_security/urls.py,sha256=QK_diUsqjyQkU6UQpUW9SV_3kpf0223glrtnM7jft7M,510
|
|
7
|
-
session_security/utils.py,sha256=d19NpP7f5kEdrVdZIae95c-Oeuw9gk0m4pATzuzlw3w,466
|
|
8
|
-
session_security/views.py,sha256=ktla3T5Pk8qajdVTIhatWKprm10iIjM-Ek495APDBLs,879
|
|
9
|
-
session_security/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
-
session_security/templatetags/session_security_tags.py,sha256=Vhrxe0ThWpEbQZUlqxKl9XXOx8HhF96EoBmVk5hxhrc,627
|
|
11
|
-
session_security/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
-
session_security/tests/conftest.py,sha256=MFGSYiQ_9ViCKgr0BL0x9cB4eJR29m1XjMkoY1J6SeE,4756
|
|
13
|
-
session_security/tests/test_base.py,sha256=bvqz385wyyBQNhrpeTyUTY0fWosLB9wOhPOBrt0tOBM,1775
|
|
14
|
-
session_security/tests/test_middleware.py,sha256=iLFlXXfoBwUBNUJPhyRvPR657y-MORj1nyjh3GXFNPc,3612
|
|
15
|
-
session_security/tests/test_script.py,sha256=y-gNGt6vLgsjfvqIk7GsuS5RijoSVo50kzKpKkUXcJs,2707
|
|
16
|
-
session_security/tests/test_templates.py,sha256=qXukArdCZvvthGLyHZzise9xV6Q8kFx-eUy8TCxsYXU,471
|
|
17
|
-
session_security/tests/test_views.py,sha256=97Ssf4nXGj0OIGc-fFf3_LdjC3k9yFMr6QD9CRsTrLc,1183
|
|
18
|
-
session_security/tests/project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
|
-
session_security/tests/project/settings.py,sha256=BAN820rroRvYMKQPtTYvqkdjmy9ce5fznFWelrBG58c,2999
|
|
20
|
-
session_security/tests/project/urls.py,sha256=wFMGt1wQLCdoaAsJRltFypR473RJnkxbqReWh0FMFWE,1136
|
|
21
|
-
session_security/tests/project/wsgi.py,sha256=VFz8yKLbSm4-C5ejuLJ_ZuPoKZ1WP17WJVMx2R17Z8M,426
|
|
22
|
-
django_session_security_continued-3.0.0a1.dist-info/METADATA,sha256=jSCRkYxzDg-MpeqLKPxe23zGuccNJg4oBE1LUZsr5Kg,8935
|
|
23
|
-
django_session_security_continued-3.0.0a1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
24
|
-
django_session_security_continued-3.0.0a1.dist-info/top_level.txt,sha256=sUgnA1DNG4V434n9luYoNsltkfMgkCnI6GBZV6oKWJI,17
|
|
25
|
-
django_session_security_continued-3.0.0a1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|