django-pfx 1.4.dev40__tar.gz → 1.4.dev44__tar.gz

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.
Files changed (143) hide show
  1. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/PKG-INFO +1 -1
  2. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/django_pfx.egg-info/PKG-INFO +1 -1
  3. django_pfx-1.4.dev44/pfx/pfxcore/locale/fr/LC_MESSAGES/django.mo +0 -0
  4. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/locale/fr/LC_MESSAGES/django.po +20 -16
  5. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/middleware/authentication.py +6 -6
  6. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/models/login_ban.py +3 -1
  7. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/authentication_views.py +18 -9
  8. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/tests/test_auth_api.py +18 -2
  9. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/tests/test_settings.py +1 -3
  10. django_pfx-1.4.dev40/pfx/pfxcore/locale/fr/LC_MESSAGES/django.mo +0 -0
  11. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/.gitignore +0 -0
  12. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/.gitlab-ci.yml +0 -0
  13. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/.pre-commit-config.yaml +0 -0
  14. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/LICENSE +0 -0
  15. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/MANIFEST.in +0 -0
  16. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/README.md +0 -0
  17. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/django_pfx.egg-info/SOURCES.txt +0 -0
  18. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/django_pfx.egg-info/dependency_links.txt +0 -0
  19. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/django_pfx.egg-info/requires.txt +0 -0
  20. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/django_pfx.egg-info/top_level.txt +0 -0
  21. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/doc/Makefile +0 -0
  22. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/doc/conf.py +0 -0
  23. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/doc/index.rst +0 -0
  24. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/doc/source/api.views.rst +0 -0
  25. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/doc/source/authentication.md +0 -0
  26. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/doc/source/decorator.md +0 -0
  27. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/doc/source/generate_openapi.md +0 -0
  28. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/doc/source/getting_started.md +0 -0
  29. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/doc/source/internationalisation.md +0 -0
  30. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/doc/source/model.md +0 -0
  31. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/doc/source/pfx_views.md +0 -0
  32. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/doc/source/profiling.md +0 -0
  33. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/doc/source/settings.md +0 -0
  34. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/doc/source/testing.md +0 -0
  35. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/img/pfx.png +0 -0
  36. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/img/pfx.svg +0 -0
  37. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/make_messages +0 -0
  38. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/manage.py +0 -0
  39. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/__init__.py +0 -0
  40. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/__init__.py +0 -0
  41. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/apidoc/__init__.py +0 -0
  42. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/apidoc/parameters.py +0 -0
  43. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/apidoc/schema.py +0 -0
  44. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/apidoc/tags.py +0 -0
  45. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/apps.py +0 -0
  46. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/decorator/__init__.py +0 -0
  47. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/decorator/rest.py +0 -0
  48. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/default_settings.py +0 -0
  49. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/exceptions.py +0 -0
  50. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/fields.py +0 -0
  51. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/http/__init__.py +0 -0
  52. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/http/json_response.py +0 -0
  53. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/management/__init__.py +0 -0
  54. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/management/commands/__init__.py +0 -0
  55. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/management/commands/makeapidoc.py +0 -0
  56. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/management/commands/profile.py +0 -0
  57. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/middleware/__init__.py +0 -0
  58. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/middleware/locale.py +0 -0
  59. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/middleware/profiling.py +0 -0
  60. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/migrations/0001_initial.py +0 -0
  61. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/migrations/__init__.py +0 -0
  62. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/models/__init__.py +0 -0
  63. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/models/abstract_pfx_base_user.py +0 -0
  64. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/models/cache_mixins.py +0 -0
  65. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/models/not_null_fields.py +0 -0
  66. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/models/otp_user_mixin.py +0 -0
  67. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/models/pfx_models.py +0 -0
  68. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/models/pfx_user.py +0 -0
  69. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/models/user_filtered_queryset_mixin.py +0 -0
  70. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/serializers/__init__.py +0 -0
  71. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/serializers/json.py +0 -0
  72. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/settings.py +0 -0
  73. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/shortcuts.py +0 -0
  74. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/storage/__init__.py +0 -0
  75. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/storage/s3_storage.py +0 -0
  76. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/templates/registration/otp_code_email.txt +0 -0
  77. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/templates/registration/otp_code_subject.txt +0 -0
  78. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/templates/registration/password_reset_email.txt +0 -0
  79. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/templates/registration/password_reset_subject.txt +0 -0
  80. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/templates/registration/welcome_email.txt +0 -0
  81. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/templates/registration/welcome_subject.txt +0 -0
  82. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/test.py +0 -0
  83. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/urls.py +0 -0
  84. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/__init__.py +0 -0
  85. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/fields.py +0 -0
  86. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/filters_views.py +0 -0
  87. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/locale_views.py +0 -0
  88. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/parameters/__init__.py +0 -0
  89. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/parameters/date_format.py +0 -0
  90. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/parameters/groups.py +0 -0
  91. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/parameters/list_count.py +0 -0
  92. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/parameters/list_items.py +0 -0
  93. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/parameters/list_mode.py +0 -0
  94. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/parameters/list_order.py +0 -0
  95. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/parameters/list_search.py +0 -0
  96. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/parameters/media_redirect.py +0 -0
  97. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/parameters/meta_fields.py +0 -0
  98. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/parameters/meta_filters.py +0 -0
  99. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/parameters/meta_orders.py +0 -0
  100. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/parameters/subset.py +0 -0
  101. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/parameters/subset_limit.py +0 -0
  102. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/parameters/subset_offset.py +0 -0
  103. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/parameters/subset_page.py +0 -0
  104. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/parameters/subset_page_size.py +0 -0
  105. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/parameters/subset_page_subset.py +0 -0
  106. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/pfxcore/views/rest_views.py +0 -0
  107. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/settings/__init__.py +0 -0
  108. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pfx/settings/dev.py +0 -0
  109. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/pyproject.toml +0 -0
  110. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/requirements.txt +0 -0
  111. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/serve-doc +0 -0
  112. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/setup.cfg +0 -0
  113. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/setup.py +0 -0
  114. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/__init__.py +0 -0
  115. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/locale/fr/LC_MESSAGES/django.po +0 -0
  116. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/models.py +0 -0
  117. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/settings/__init__.py +0 -0
  118. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/settings/ci.py +0 -0
  119. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/settings/common.py +0 -0
  120. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/settings/dev.py +0 -0
  121. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/settings/dev_custom_example.py +0 -0
  122. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/settings/dev_default.py +0 -0
  123. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/tests/__init__.py +0 -0
  124. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/tests/basic_api_errors.py +0 -0
  125. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/tests/basic_api_test.py +0 -0
  126. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/tests/test_api_doc.py +0 -0
  127. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/tests/test_body_mixin.py +0 -0
  128. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/tests/test_cache.py +0 -0
  129. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/tests/test_client.py +0 -0
  130. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/tests/test_fields.py +0 -0
  131. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/tests/test_filters.py +0 -0
  132. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/tests/test_locale_api.py +0 -0
  133. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/tests/test_perm_tests.py +0 -0
  134. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/tests/test_perms_api.py +0 -0
  135. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/tests/test_profiling_middleware.py +0 -0
  136. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/tests/test_shortcuts.py +0 -0
  137. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/tests/test_timezone_middleware.py +0 -0
  138. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/tests/test_tools.py +0 -0
  139. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/tests/test_user_queryset.py +0 -0
  140. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/tests/test_view_decorators.py +0 -0
  141. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/tests/test_view_fields.py +0 -0
  142. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/urls.py +0 -0
  143. {django_pfx-1.4.dev40 → django_pfx-1.4.dev44}/tests/views.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-pfx
3
- Version: 1.4.dev40
3
+ Version: 1.4.dev44
4
4
  Summary: Django PFX is a toolkit designed to streamline the development of RESTful APIs using the Django framework.
5
5
  Author: Hervé Martinet
6
6
  Author-email: herve.martinet@gmail.com
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-pfx
3
- Version: 1.4.dev40
3
+ Version: 1.4.dev44
4
4
  Summary: Django PFX is a toolkit designed to streamline the development of RESTful APIs using the Django framework.
5
5
  Author: Hervé Martinet
6
6
  Author-email: herve.martinet@gmail.com
@@ -7,7 +7,7 @@ msgid ""
7
7
  msgstr ""
8
8
  "Project-Id-Version: \n"
9
9
  "Report-Msgid-Bugs-To: \n"
10
- "POT-Creation-Date: 2024-04-18 14:37+0200\n"
10
+ "POT-Creation-Date: 2024-04-23 14:41+0200\n"
11
11
  "PO-Revision-Date: 2021-06-22 23:31+0200\n"
12
12
  "Last-Translator: \n"
13
13
  "Language-Team: \n"
@@ -59,23 +59,23 @@ msgstr ""
59
59
  "Format non valide, il peut s’agir d’un nombre en heures, « 1:05 », « :05 », "
60
60
  "« 1h 5m », « 1.5h » ou « 30m »."
61
61
 
62
- #: models/login_ban.py:43
62
+ #: models/login_ban.py:45
63
63
  msgid "Username"
64
64
  msgstr "Nom d’utilisateur"
65
65
 
66
- #: models/login_ban.py:44
66
+ #: models/login_ban.py:46
67
67
  msgid "Failed counter"
68
68
  msgstr "Compteur d’échec"
69
69
 
70
- #: models/login_ban.py:45
70
+ #: models/login_ban.py:47
71
71
  msgid "Last failed"
72
72
  msgstr "Dernier échec"
73
73
 
74
- #: models/login_ban.py:50
74
+ #: models/login_ban.py:52
75
75
  msgid "Login ban"
76
76
  msgstr "Login banni"
77
77
 
78
- #: models/login_ban.py:51
78
+ #: models/login_ban.py:53
79
79
  msgid "Login bans"
80
80
  msgstr "Login bannis"
81
81
 
@@ -95,7 +95,7 @@ msgstr "Compte HOTP"
95
95
  msgid "HOTP expiry"
96
96
  msgstr "Expiration HOTP"
97
97
 
98
- #: models/otp_user_mixin.py:29 views/authentication_views.py:489
98
+ #: models/otp_user_mixin.py:29 views/authentication_views.py:496
99
99
  msgid "OTP enabled"
100
100
  msgstr "OTP activé"
101
101
 
@@ -205,7 +205,11 @@ msgstr ""
205
205
  "Votre connexion est temporairement désactivée après plusieurs tentatives "
206
206
  "infructueuses, veuillez réessayer dans {seconds} secondes."
207
207
 
208
- #: views/authentication_views.py:243 views/authentication_views.py:408
208
+ #: views/authentication_views.py:173
209
+ msgid "Successful login"
210
+ msgstr "Connexion réussie"
211
+
212
+ #: views/authentication_views.py:243 views/authentication_views.py:413
209
213
  msgid "password updated successfully"
210
214
  msgstr "le mot de passe a été mis à jour avec succès"
211
215
 
@@ -213,31 +217,31 @@ msgstr "le mot de passe a été mis à jour avec succès"
213
217
  msgid "Incorrect password"
214
218
  msgstr "Mot de passe incorrect"
215
219
 
216
- #: views/authentication_views.py:251 views/authentication_views.py:417
220
+ #: views/authentication_views.py:251 views/authentication_views.py:422
217
221
  msgid "Empty password is not allowed"
218
222
  msgstr "Un mot de passe vide n’est pas autorisé"
219
223
 
220
- #: views/authentication_views.py:342
224
+ #: views/authentication_views.py:347
221
225
  msgid "User and token are valid"
222
226
  msgstr "L'utilisateur et le token sont valides"
223
227
 
224
- #: views/authentication_views.py:344
228
+ #: views/authentication_views.py:349
225
229
  msgid "User or token is invalid"
226
230
  msgstr "L'utilisateur ou le token est invalide"
227
231
 
228
- #: views/authentication_views.py:451
232
+ #: views/authentication_views.py:456
229
233
  msgid "OTP is already enabled"
230
234
  msgstr "OTP est déjà activé"
231
235
 
232
- #: views/authentication_views.py:490 views/authentication_views.py:524
236
+ #: views/authentication_views.py:497 views/authentication_views.py:533
233
237
  msgid "Invalid code"
234
238
  msgstr "Code invalide"
235
239
 
236
- #: views/authentication_views.py:523
240
+ #: views/authentication_views.py:532
237
241
  msgid "OTP disabled"
238
242
  msgstr "OTP désactivé"
239
243
 
240
- #: views/authentication_views.py:783
244
+ #: views/authentication_views.py:792
241
245
  msgid ""
242
246
  "If the email address you entered is correct, you will receive an email from "
243
247
  "us with instructions to reset your password."
@@ -246,7 +250,7 @@ msgstr ""
246
250
  "un courrier électronique de notre part contenant des instructions pour "
247
251
  "réinitialiser votre mot de passe."
248
252
 
249
- #: views/authentication_views.py:857
253
+ #: views/authentication_views.py:866
250
254
  msgid "A new authentication code has been sent by email."
251
255
  msgstr "Un nouveau code d'authentification a été envoyé par e-mail."
252
256
 
@@ -58,12 +58,10 @@ class JWTTokenDecodeMixin:
58
58
  user.get_user_jwt_signature_key() + settings.PFX_SECRET_KEY,
59
59
  options=dict(require=["exp"]),
60
60
  algorithms="HS256")
61
- if 'otp_login' in decoded:
62
- if otp_login:
63
- return user, *decoded['otp_login']
61
+ if decoded.get('pfx_otp_login') and not otp_login:
64
62
  raise jwt.InvalidTokenError(
65
63
  "This token is reserved for OTP login")
66
- return user
64
+ return user, *decoded.get('pfx_login_options', ['jwt', False])
67
65
  except (get_user_model().DoesNotExist, jwt.ExpiredSignatureError,
68
66
  jwt.InvalidTokenError, jwt.InvalidSignatureError,
69
67
  DecodeError) as e:
@@ -93,7 +91,8 @@ class AuthenticationMiddleware(JWTTokenDecodeMixin, MiddlewareMixin):
93
91
  except ValueError:
94
92
  token = ""
95
93
  try:
96
- request.user = self.decode_jwt(token)
94
+ request.user, request.login_mode, request.login_remember_me = (
95
+ self.decode_jwt(token))
97
96
  except Exception:
98
97
  request.user = AnonymousUser()
99
98
  else:
@@ -122,7 +121,8 @@ class CookieAuthenticationMiddleware(JWTTokenDecodeMixin, MiddlewareMixin):
122
121
  token = request.COOKIES.get('token', "")
123
122
  if token:
124
123
  try:
125
- request.user = self.decode_jwt(token)
124
+ request.user, request.login_mode, request.login_remember_me = (
125
+ self.decode_jwt(token))
126
126
  except Exception:
127
127
  request.user = AnonymousUser()
128
128
  request.delete_cookie = True
@@ -17,7 +17,9 @@ class LoginBanQuerySet(models.QuerySet):
17
17
  return False
18
18
  if ban.failed_counter % settings.PFX_LOGIN_BAN_FAILED_NUMBER == 0:
19
19
  seconds = settings.PFX_LOGIN_BAN_SECONDS_START + (
20
- settings.PFX_LOGIN_BAN_SECONDS_STEP * (ban.failed_counter - 1))
20
+ settings.PFX_LOGIN_BAN_SECONDS_STEP * (
21
+ ban.failed_counter //
22
+ settings.PFX_LOGIN_BAN_FAILED_NUMBER - 1))
21
23
  ban_time = ban.last_failed + timedelta(seconds=seconds)
22
24
  now = timezone.now()
23
25
  if now < ban_time:
@@ -151,9 +151,9 @@ class AuthenticationView(
151
151
  return self._login_need_otp_response(user, mode, remember_me)
152
152
  return self._login_success(user, mode, remember_me)
153
153
 
154
- def _login_success(self, user, mode, remember_me=False):
155
- token = self._prepare_token(
156
- user, token_validity('long' if remember_me else 'short'))
154
+ def _login_success(
155
+ self, user, mode, remember_me=False, message=None):
156
+ token = self._prepare_token(user, mode, remember_me)
157
157
  if mode == 'cookie':
158
158
  if remember_me:
159
159
  expires = datetime.now(
@@ -170,6 +170,7 @@ class AuthenticationView(
170
170
  httponly=True, samesite=settings.PFX_COOKIE_SAMESITE)
171
171
  return res
172
172
  return JsonResponse(dict(
173
+ message=message or _("Successful login"),
173
174
  need_otp=False,
174
175
  token=token,
175
176
  user=self.get_user_information(user)))
@@ -178,8 +179,7 @@ class AuthenticationView(
178
179
  """Return the response for login if OTP login is needed.
179
180
 
180
181
  Can be overridden to customize the response."""
181
- token = self._prepare_token(user, token_validity('otp'), otp_login=[
182
- mode, remember_me])
182
+ token = self._prepare_token(user, mode, remember_me, otp_login=True)
183
183
  return JsonResponse(dict(need_otp=True, token=token))
184
184
 
185
185
  @method_decorator(never_cache)
@@ -252,10 +252,15 @@ class AuthenticationView(
252
252
  return JsonResponse(
253
253
  ValidationError(errors), status=422)
254
254
 
255
- def _prepare_token(self, user, validity, **extra_payload):
256
- exp = datetime.now(tz=timezone.utc) + validity
255
+ def _prepare_token(
256
+ self, user, mode='jwt', remember_me=False, otp_login=False,
257
+ **extra_payload):
258
+ exp = datetime.now(tz=timezone.utc) + token_validity(
259
+ otp_login and 'otp' or (remember_me and 'long' or 'short'))
257
260
  payload = dict(
258
261
  exp=exp,
262
+ pfx_login_options=[mode, remember_me],
263
+ pfx_otp_login=otp_login,
259
264
  **self.get_extra_payload(user), **extra_payload)
260
265
  return jwt.encode(
261
266
  payload,
@@ -486,7 +491,9 @@ class AuthenticationView(
486
491
  raise NotFoundError()
487
492
  data = self.deserialize_body()
488
493
  if self.request.user.confirm_otp(data.get('otp_code')):
489
- return JsonResponse(dict(message=_("OTP enabled")))
494
+ return self._login_success(
495
+ self.request.user, self.request.login_mode,
496
+ self.request.login_remember_me, message=_("OTP enabled"))
490
497
  return JsonResponse(dict(otp_code=[_("Invalid code")]), status=422)
491
498
 
492
499
  @method_decorator(never_cache)
@@ -520,7 +527,9 @@ class AuthenticationView(
520
527
  data = self.deserialize_body()
521
528
  if self.request.user.is_otp_valid(data.get('otp_code')):
522
529
  self.request.user.disable_otp()
523
- return JsonResponse(dict(message=_("OTP disabled")))
530
+ return self._login_success(
531
+ self.request.user, self.request.login_mode,
532
+ self.request.login_remember_me, message=_("OTP disabled"))
524
533
  return JsonResponse(dict(otp_code=[_("Invalid code")]), status=422)
525
534
 
526
535
  @method_decorator(never_cache)
@@ -88,7 +88,7 @@ class AuthAPITest(TestAssertMixin, TransactionTestCase):
88
88
 
89
89
  @override_settings(
90
90
  PFX_TOKEN_SHORT_VALIDITY={'minutes': 30},
91
- PFX_LOGIN_BAN_FAILED_NUMBER=1,
91
+ PFX_LOGIN_BAN_FAILED_NUMBER=2,
92
92
  PFX_LOGIN_BAN_SECONDS_START=30,
93
93
  PFX_LOGIN_BAN_SECONDS_STEP=60)
94
94
  def test_login_ban(self):
@@ -98,6 +98,11 @@ class AuthAPITest(TestAssertMixin, TransactionTestCase):
98
98
  'username': 'jrr.tolkien',
99
99
  'password': 'BAD PASSWORD'})
100
100
  self.assertRC(response, 422)
101
+ response = self.client.post(
102
+ '/api/auth/login', {
103
+ 'username': 'jrr.tolkien',
104
+ 'password': 'BAD PASSWORD'})
105
+ self.assertRC(response, 422)
101
106
 
102
107
  response = self.client.post(
103
108
  '/api/auth/login', {
@@ -128,6 +133,11 @@ class AuthAPITest(TestAssertMixin, TransactionTestCase):
128
133
  'username': 'jrr.tolkien',
129
134
  'password': 'BAD PASSWORD'})
130
135
  self.assertRC(response, 422)
136
+ response = self.client.post(
137
+ '/api/auth/login', {
138
+ 'username': 'jrr.tolkien',
139
+ 'password': 'BAD PASSWORD'})
140
+ self.assertRC(response, 422)
131
141
 
132
142
  response = self.client.post(
133
143
  '/api/auth/login', {
@@ -1072,7 +1082,7 @@ class AuthAPITest(TestAssertMixin, TransactionTestCase):
1072
1082
 
1073
1083
  @override_settings(
1074
1084
  PFX_TOKEN_SHORT_VALIDITY={'minutes': 30},
1075
- PFX_LOGIN_BAN_FAILED_NUMBER=1,
1085
+ PFX_LOGIN_BAN_FAILED_NUMBER=2,
1076
1086
  PFX_LOGIN_BAN_SECONDS_START=30,
1077
1087
  PFX_LOGIN_BAN_SECONDS_STEP=60)
1078
1088
  def test_otp_login_ban(self):
@@ -1085,6 +1095,9 @@ class AuthAPITest(TestAssertMixin, TransactionTestCase):
1085
1095
  self.assertRC(response, 200)
1086
1096
  token = self.get_val(response, 'token')
1087
1097
 
1098
+ response = self.client.post('/api/auth/otp/login', dict(
1099
+ token=token, otp_code='-'))
1100
+ self.assertRC(response, 422)
1088
1101
  response = self.client.post('/api/auth/otp/login', dict(
1089
1102
  token=token, otp_code='-'))
1090
1103
  self.assertRC(response, 422)
@@ -1112,6 +1125,9 @@ class AuthAPITest(TestAssertMixin, TransactionTestCase):
1112
1125
  response = self.client.post('/api/auth/otp/login', dict(
1113
1126
  token=token, otp_code='-'))
1114
1127
  self.assertRC(response, 422)
1128
+ response = self.client.post('/api/auth/otp/login', dict(
1129
+ token=token, otp_code='-'))
1130
+ self.assertRC(response, 422)
1115
1131
 
1116
1132
  response = self.client.post('/api/auth/otp/login', dict(
1117
1133
  token=token, otp_code='-'))
@@ -1,5 +1,3 @@
1
- from datetime import timedelta
2
-
3
1
  from django.core.exceptions import ImproperlyConfigured
4
2
  from django.test import TestCase, override_settings
5
3
 
@@ -20,4 +18,4 @@ class TestSettings(TestAssertMixin, TestCase):
20
18
  last_name='Test')
21
19
 
22
20
  with self.assertRaises(ImproperlyConfigured):
23
- AuthenticationView()._prepare_token(user, timedelta())
21
+ AuthenticationView()._prepare_token(user)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes