django-pfx 1.7.2.dev12__tar.gz → 1.7.2.dev14__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 (206) hide show
  1. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/PKG-INFO +1 -1
  2. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/django_pfx.egg-info/PKG-INFO +1 -1
  3. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/django_pfx.egg-info/SOURCES.txt +1 -0
  4. django_pfx-1.7.2.dev14/pfx/pfxcore/locale/fr/LC_MESSAGES/django.mo +0 -0
  5. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/locale/fr/LC_MESSAGES/django.po +19 -17
  6. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/models/mfa_user_mixin.py +8 -3
  7. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/authentication_views.py +9 -3
  8. django_pfx-1.7.2.dev14/tests/migrations/0005_mfausermixin_fields_fix.py +17 -0
  9. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_auth_api.py +1 -0
  10. django_pfx-1.7.2.dev12/pfx/pfxcore/locale/fr/LC_MESSAGES/django.mo +0 -0
  11. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/.gitignore +0 -0
  12. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/.gitlab-ci.yml +0 -0
  13. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/.pre-commit-config.yaml +0 -0
  14. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/LICENSE +0 -0
  15. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/MANIFEST.in +0 -0
  16. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/README.md +0 -0
  17. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/django_pfx.egg-info/dependency_links.txt +0 -0
  18. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/django_pfx.egg-info/requires.txt +0 -0
  19. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/django_pfx.egg-info/top_level.txt +0 -0
  20. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/doc/Makefile +0 -0
  21. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/doc/conf.py +0 -0
  22. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/doc/index.rst +0 -0
  23. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/doc/source/api.views.rst +0 -0
  24. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/doc/source/authentication.md +0 -0
  25. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/doc/source/decorator.md +0 -0
  26. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/doc/source/generate_openapi.md +0 -0
  27. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/doc/source/getting_started.md +0 -0
  28. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/doc/source/internationalisation.md +0 -0
  29. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/doc/source/model.md +0 -0
  30. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/doc/source/pfx_views.md +0 -0
  31. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/doc/source/profiling.md +0 -0
  32. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/doc/source/settings.md +0 -0
  33. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/doc/source/testing.md +0 -0
  34. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/img/pfx.png +0 -0
  35. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/img/pfx.svg +0 -0
  36. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/make_messages +0 -0
  37. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/manage.py +0 -0
  38. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/__init__.py +0 -0
  39. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/__init__.py +0 -0
  40. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/apidoc/__init__.py +0 -0
  41. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/apidoc/parameters.py +0 -0
  42. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/apidoc/schema.py +0 -0
  43. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/apidoc/tags.py +0 -0
  44. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/apps.py +0 -0
  45. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/decorator/__init__.py +0 -0
  46. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/decorator/rest.py +0 -0
  47. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/default_settings.py +0 -0
  48. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/exceptions.py +0 -0
  49. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/fields/__init__.py +0 -0
  50. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/fields/decimal_field.py +0 -0
  51. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/fields/media_field.py +0 -0
  52. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/fields/minutes_duration_field.py +0 -0
  53. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/fields/rich_text_field.py +0 -0
  54. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/http/__init__.py +0 -0
  55. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/http/json_response.py +0 -0
  56. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/management/__init__.py +0 -0
  57. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/management/commands/__init__.py +0 -0
  58. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/management/commands/makeapidoc.py +0 -0
  59. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/management/commands/profile.py +0 -0
  60. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/middleware/__init__.py +0 -0
  61. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/middleware/authentication.py +0 -0
  62. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/middleware/locale.py +0 -0
  63. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/middleware/profiling.py +0 -0
  64. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/migrations/0001_initial.py +0 -0
  65. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/migrations/0002_pfxpermissionsuser.py +0 -0
  66. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/migrations/0003_delete_pfxpermissionsuser.py +0 -0
  67. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/migrations/0004_alter_loginban_failed_counter_and_more.py +0 -0
  68. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/migrations/__init__.py +0 -0
  69. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/migrations/operations/__init__.py +0 -0
  70. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/migrations/operations/permissions.py +0 -0
  71. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/models/__init__.py +0 -0
  72. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/models/abstract_pfx_base_user.py +0 -0
  73. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/models/cache_mixins.py +0 -0
  74. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/models/login_ban.py +0 -0
  75. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/models/not_null_fields.py +0 -0
  76. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/models/ordered_model_mixin.py +0 -0
  77. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/models/pfx_models.py +0 -0
  78. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/models/pfx_user.py +0 -0
  79. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/models/user_filtered_queryset_mixin.py +0 -0
  80. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/serializers/__init__.py +0 -0
  81. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/serializers/json.py +0 -0
  82. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/settings.py +0 -0
  83. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/shortcuts.py +0 -0
  84. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/sms/__init__.py +0 -0
  85. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/sms/backends/__init__.py +0 -0
  86. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/sms/backends/base.py +0 -0
  87. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/sms/backends/console.py +0 -0
  88. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/storage/__init__.py +0 -0
  89. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/storage/exceptions.py +0 -0
  90. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/storage/local_storage.py +0 -0
  91. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/storage/s3_storage.py +0 -0
  92. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/templates/registration/otp_code_email.txt +0 -0
  93. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/templates/registration/otp_code_subject.txt +0 -0
  94. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/templates/registration/password_reset_email.txt +0 -0
  95. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/templates/registration/password_reset_subject.txt +0 -0
  96. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/templates/registration/welcome_email.txt +0 -0
  97. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/templates/registration/welcome_subject.txt +0 -0
  98. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/test.py +0 -0
  99. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/urls.py +0 -0
  100. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/__init__.py +0 -0
  101. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/fields.py +0 -0
  102. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/filters_views.py +0 -0
  103. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/locale_views.py +0 -0
  104. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/media_rest_view_mixin.py +0 -0
  105. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/ordered_rest_view_mixin.py +0 -0
  106. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/parameters/__init__.py +0 -0
  107. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/parameters/date_format.py +0 -0
  108. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/parameters/groups.py +0 -0
  109. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/parameters/list_count.py +0 -0
  110. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/parameters/list_items.py +0 -0
  111. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/parameters/list_mode.py +0 -0
  112. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/parameters/list_order.py +0 -0
  113. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/parameters/list_search.py +0 -0
  114. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/parameters/media_redirect.py +0 -0
  115. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/parameters/meta_fields.py +0 -0
  116. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/parameters/meta_filters.py +0 -0
  117. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/parameters/meta_orders.py +0 -0
  118. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/parameters/subset.py +0 -0
  119. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/parameters/subset_limit.py +0 -0
  120. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/parameters/subset_offset.py +0 -0
  121. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/parameters/subset_page.py +0 -0
  122. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/parameters/subset_page_size.py +0 -0
  123. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/parameters/subset_page_subset.py +0 -0
  124. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/pfxcore/views/rest_views.py +0 -0
  125. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/settings/__init__.py +0 -0
  126. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pfx/settings/dev.py +0 -0
  127. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/pyproject.toml +0 -0
  128. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/requirements.txt +0 -0
  129. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/serve-doc +0 -0
  130. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/setup.cfg +0 -0
  131. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/setup.py +0 -0
  132. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/__init__.py +0 -0
  133. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/apps.py +0 -0
  134. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/locale/fr/LC_MESSAGES/django.po +0 -0
  135. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/migrations/0001_initial.py +0 -0
  136. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/migrations/0002_alter_book_cover.py +0 -0
  137. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/migrations/0003_book_local_file.py +0 -0
  138. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/migrations/0004_mfausermixin_fields.py +0 -0
  139. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/migrations/__init__.py +0 -0
  140. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/models.py +0 -0
  141. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/settings/__init__.py +0 -0
  142. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/settings/ci.py +0 -0
  143. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/settings/common.py +0 -0
  144. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/settings/dev.py +0 -0
  145. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/settings/dev_custom_example.py +0 -0
  146. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/settings/dev_default.py +0 -0
  147. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/__init__.py +0 -0
  148. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/basic_api_errors.py +0 -0
  149. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/basic_api_test.py +0 -0
  150. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_api_doc.py +0 -0
  151. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_api_doc_search.py +0 -0
  152. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_body_mixin.py +0 -0
  153. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_cache.py +0 -0
  154. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_client.py +0 -0
  155. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_fields_choices.py +0 -0
  156. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_fields_date.py +0 -0
  157. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_fields_decimal.py +0 -0
  158. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_fields_minutes_duration.py +0 -0
  159. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_fields_one2many.py +0 -0
  160. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_fields_rich_text.py +0 -0
  161. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_filters.py +0 -0
  162. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_locale_api.py +0 -0
  163. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_ordered_rest_view_mixin.py +0 -0
  164. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_perm_tests.py +0 -0
  165. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_permissions.py +0 -0
  166. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_perms_api.py +0 -0
  167. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_post_migrate_groups_update.py +0 -0
  168. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_profiling_middleware.py +0 -0
  169. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_settings.py +0 -0
  170. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_shortcuts.py +0 -0
  171. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_timezone_middleware.py +0 -0
  172. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_tools.py +0 -0
  173. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_user_queryset.py +0 -0
  174. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_view_decorators.py +0 -0
  175. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/tests/test_view_fields.py +0 -0
  176. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/urls.py +0 -0
  177. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests/views.py +0 -0
  178. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_base_user/__init__.py +0 -0
  179. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_base_user/migrations/0001_initial.py +0 -0
  180. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_base_user/migrations/__init__.py +0 -0
  181. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_base_user/settings/__init__.py +0 -0
  182. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_base_user/settings/ci.py +0 -0
  183. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_base_user/settings/common.py +0 -0
  184. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_base_user/settings/dev.py +0 -0
  185. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_base_user/settings/dev_custom_example.py +0 -0
  186. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_base_user/settings/dev_default.py +0 -0
  187. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_base_user/tests/__init__.py +0 -0
  188. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_base_user/tests/test_api.py +0 -0
  189. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_base_user/tests/test_auth_api.py +0 -0
  190. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_base_user/urls.py +0 -0
  191. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_base_user/views.py +0 -0
  192. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_custom_user/__init__.py +0 -0
  193. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_custom_user/migrations/0001_initial.py +0 -0
  194. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_custom_user/migrations/__init__.py +0 -0
  195. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_custom_user/models.py +0 -0
  196. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_custom_user/settings/__init__.py +0 -0
  197. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_custom_user/settings/ci.py +0 -0
  198. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_custom_user/settings/common.py +0 -0
  199. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_custom_user/settings/dev.py +0 -0
  200. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_custom_user/settings/dev_custom_example.py +0 -0
  201. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_custom_user/settings/dev_default.py +0 -0
  202. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_custom_user/tests/__init__.py +0 -0
  203. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_custom_user/tests/test_api.py +0 -0
  204. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_custom_user/tests/test_auth_api.py +0 -0
  205. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_custom_user/urls.py +0 -0
  206. {django_pfx-1.7.2.dev12 → django_pfx-1.7.2.dev14}/tests_custom_user/views.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-pfx
3
- Version: 1.7.2.dev12
3
+ Version: 1.7.2.dev14
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.4
2
2
  Name: django-pfx
3
- Version: 1.7.2.dev12
3
+ Version: 1.7.2.dev14
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
@@ -135,6 +135,7 @@ tests/migrations/0001_initial.py
135
135
  tests/migrations/0002_alter_book_cover.py
136
136
  tests/migrations/0003_book_local_file.py
137
137
  tests/migrations/0004_mfausermixin_fields.py
138
+ tests/migrations/0005_mfausermixin_fields_fix.py
138
139
  tests/migrations/__init__.py
139
140
  tests/settings/__init__.py
140
141
  tests/settings/ci.py
@@ -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: 2026-04-20 16:17+0200\n"
10
+ "POT-Creation-Date: 2026-04-22 09:37+0200\n"
11
11
  "PO-Revision-Date: 2021-06-22 23:31+0200\n"
12
12
  "Last-Translator: \n"
13
13
  "Language-Team: \n"
@@ -112,10 +112,8 @@ msgid "Temporary SMS phone number"
112
112
  msgstr "Numéro de téléphone temporaire (SMS)"
113
113
 
114
114
  #: models/mfa_user_mixin.py:35
115
- #, fuzzy
116
- #| msgid "OTP enabled"
117
115
  msgid "SMS MFA enabled"
118
- msgstr "OTP activé"
116
+ msgstr "MFA SMS activé"
119
117
 
120
118
  #: models/mfa_user_mixin.py:37
121
119
  msgid "Email MFA enabled"
@@ -125,7 +123,11 @@ msgstr "MFA par email activé"
125
123
  msgid "MFA setup dismissed"
126
124
  msgstr "Configuration MFA annulée"
127
125
 
128
- #: models/mfa_user_mixin.py:47 views/authentication_views.py:712
126
+ #: models/mfa_user_mixin.py:43
127
+ msgid "Authenticator MFA enabled"
128
+ msgstr "Application MFA activée"
129
+
130
+ #: models/mfa_user_mixin.py:50 views/authentication_views.py:718
129
131
  msgid "OTP enabled"
130
132
  msgstr "OTP activé"
131
133
 
@@ -249,47 +251,47 @@ msgstr ""
249
251
  msgid "Successful login"
250
252
  msgstr "Connexion réussie"
251
253
 
252
- #: views/authentication_views.py:385
254
+ #: views/authentication_views.py:391
253
255
  msgid "This field is required."
254
256
  msgstr "Ce champ est requis."
255
257
 
256
- #: views/authentication_views.py:396
258
+ #: views/authentication_views.py:402
257
259
  msgid "Code sent."
258
260
  msgstr "Code envoyé."
259
261
 
260
- #: views/authentication_views.py:459 views/authentication_views.py:629
262
+ #: views/authentication_views.py:465 views/authentication_views.py:635
261
263
  msgid "password updated successfully"
262
264
  msgstr "le mot de passe a été mis à jour avec succès"
263
265
 
264
- #: views/authentication_views.py:464
266
+ #: views/authentication_views.py:470
265
267
  msgid "Incorrect password"
266
268
  msgstr "Mot de passe incorrect"
267
269
 
268
- #: views/authentication_views.py:467 views/authentication_views.py:638
270
+ #: views/authentication_views.py:473 views/authentication_views.py:644
269
271
  msgid "Empty password is not allowed"
270
272
  msgstr "Un mot de passe vide n’est pas autorisé"
271
273
 
272
- #: views/authentication_views.py:558
274
+ #: views/authentication_views.py:564
273
275
  msgid "User and token are valid"
274
276
  msgstr "L'utilisateur et le token sont valides"
275
277
 
276
- #: views/authentication_views.py:560
278
+ #: views/authentication_views.py:566
277
279
  msgid "User or token is invalid"
278
280
  msgstr "L'utilisateur ou le token est invalide"
279
281
 
280
- #: views/authentication_views.py:672
282
+ #: views/authentication_views.py:678
281
283
  msgid "OTP is already enabled"
282
284
  msgstr "OTP est déjà activé"
283
285
 
284
- #: views/authentication_views.py:713 views/authentication_views.py:749
286
+ #: views/authentication_views.py:719 views/authentication_views.py:755
285
287
  msgid "Invalid code"
286
288
  msgstr "Code invalide"
287
289
 
288
- #: views/authentication_views.py:748
290
+ #: views/authentication_views.py:754
289
291
  msgid "OTP disabled"
290
292
  msgstr "OTP désactivé"
291
293
 
292
- #: views/authentication_views.py:1009
294
+ #: views/authentication_views.py:1015
293
295
  msgid ""
294
296
  "If the email address you entered is correct, you will receive an email from "
295
297
  "us with instructions to reset your password."
@@ -298,7 +300,7 @@ msgstr ""
298
300
  "un courrier électronique de notre part contenant des instructions pour "
299
301
  "réinitialiser votre mot de passe."
300
302
 
301
- #: views/authentication_views.py:1083
303
+ #: views/authentication_views.py:1089
302
304
  msgid "A new authentication code has been sent by email."
303
305
  msgstr "Un nouveau code d'authentification a été envoyé par e-mail."
304
306
 
@@ -38,6 +38,9 @@ class MFAUserMixin(models.Model):
38
38
  #: User has dismissed or completed the MFA setup screen.
39
39
  mfa_setup_dismissed = models.BooleanField(
40
40
  _("MFA setup dismissed"), default=False)
41
+ #: Authenticator app MFA explicitly enabled by the user.
42
+ otp_enabled = models.BooleanField(
43
+ _("Authenticator MFA enabled"), default=False)
41
44
 
42
45
  class Meta:
43
46
  abstract = True
@@ -46,7 +49,7 @@ class MFAUserMixin(models.Model):
46
49
 
47
50
  @rest_property(_("OTP enabled"), "BooleanField")
48
51
  def is_otp(self):
49
- return bool(self.otp_secret_token)
52
+ return self.otp_enabled
50
53
 
51
54
  def need_otp_response_extra(self):
52
55
  """Add extra attribute to response when need_otp=True."""
@@ -74,8 +77,9 @@ class MFAUserMixin(models.Model):
74
77
  if self.is_otp_valid(otp_code, tmp=True):
75
78
  self.otp_secret_token = self.otp_secret_token_tmp
76
79
  self.otp_secret_token_tmp = None
80
+ self.otp_enabled = True
77
81
  self.save(update_fields=[
78
- 'otp_secret_token', 'otp_secret_token_tmp'])
82
+ 'otp_secret_token', 'otp_secret_token_tmp', 'otp_enabled'])
79
83
  return True
80
84
  return False
81
85
 
@@ -85,7 +89,8 @@ class MFAUserMixin(models.Model):
85
89
  Remove the OTP secret token.
86
90
  """
87
91
  self.otp_secret_token = None
88
- self.save(update_fields=['otp_secret_token'])
92
+ self.otp_enabled = False
93
+ self.save(update_fields=['otp_secret_token', 'otp_enabled'])
89
94
 
90
95
  def get_otp_setup_uri(self, tmp=False, with_color=True):
91
96
  """Return the setup URL for OTP activation.
@@ -230,6 +230,12 @@ class AuthenticationView(
230
230
  self.send_mfa_challenge(user, backend_id)
231
231
  token = self._prepare_token(user, mode, remember_me, otp_login=True)
232
232
  available = self.get_mfa_backends(user)
233
+ # Ensure the active OOB backend appears in available_backends so the
234
+ # frontend can offer a resend button (e.g. forced-email fallback where
235
+ # email_enabled is False but email is still the active channel).
236
+ available_for_response = list(available)
237
+ if is_oob and backend_id not in available_for_response:
238
+ available_for_response.append(backend_id)
233
239
  extra = user.need_otp_response_extra() if isinstance(
234
240
  user, MFAUserMixin) else {}
235
241
  return JsonResponse(dict(
@@ -239,7 +245,7 @@ class AuthenticationView(
239
245
  mfa_backend={'id': backend_id, 'is_oob': is_oob},
240
246
  available_backends=[
241
247
  {'id': b, 'is_oob': b in {'email', 'sms'}}
242
- for b in available
248
+ for b in available_for_response
243
249
  ]))
244
250
 
245
251
  # --- MFA helpers ---
@@ -253,7 +259,7 @@ class AuthenticationView(
253
259
  return []
254
260
  result = []
255
261
  for backend_id in settings.PFX_MFA_BACKENDS:
256
- if backend_id == 'authenticator' and user.otp_secret_token:
262
+ if backend_id == 'authenticator' and user.otp_enabled:
257
263
  result.append(backend_id)
258
264
  elif backend_id == 'sms' and user.sms_enabled:
259
265
  result.append(backend_id)
@@ -667,7 +673,7 @@ class AuthenticationView(
667
673
  if not isinstance(self.request.user, MFAUserMixin):
668
674
  logger.error("User must inherit MFAUserMixin to use MFA")
669
675
  raise NotFoundError()
670
- if self.request.user.otp_secret_token:
676
+ if self.request.user.otp_enabled:
671
677
  return JsonResponse(
672
678
  dict(message=_("OTP is already enabled")), status=400)
673
679
  self.request.user.enable_otp()
@@ -0,0 +1,17 @@
1
+ from django.db import migrations, models
2
+
3
+
4
+ class Migration(migrations.Migration):
5
+
6
+ dependencies = [
7
+ ('tests', '0004_mfausermixin_fields'),
8
+ ]
9
+
10
+ operations = [
11
+ migrations.AddField(
12
+ model_name='user',
13
+ name='otp_enabled',
14
+ field=models.BooleanField(
15
+ default=False, verbose_name='Authenticator MFA enabled'),
16
+ ),
17
+ ]
@@ -924,6 +924,7 @@ class MFALoginTest(TestAssertMixin, TransactionTestCase):
924
924
 
925
925
  def enable_otp(self, user):
926
926
  user.otp_secret_token = pyotp.random_base32()
927
+ user.otp_enabled = True
927
928
  user.save()
928
929
  user.refresh_from_db()
929
930
  return pyotp.totp.TOTP(user.otp_secret_token)