django-pfx 1.4.dev24__tar.gz → 1.4.dev26__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 (136) hide show
  1. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/PKG-INFO +1 -1
  2. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/django_pfx.egg-info/PKG-INFO +1 -1
  3. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/middleware/authentication.py +27 -10
  4. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/authentication_views.py +12 -11
  5. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/tests/test_auth_api.py +6 -6
  6. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/.gitignore +0 -0
  7. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/.gitlab-ci.yml +0 -0
  8. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/.pre-commit-config.yaml +0 -0
  9. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/LICENSE +0 -0
  10. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/MANIFEST.in +0 -0
  11. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/README.md +0 -0
  12. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/django-admin-test +0 -0
  13. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/django_pfx.egg-info/SOURCES.txt +0 -0
  14. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/django_pfx.egg-info/dependency_links.txt +0 -0
  15. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/django_pfx.egg-info/requires.txt +0 -0
  16. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/django_pfx.egg-info/top_level.txt +0 -0
  17. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/doc/Makefile +0 -0
  18. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/doc/conf.py +0 -0
  19. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/doc/index.rst +0 -0
  20. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/doc/source/api.views.rst +0 -0
  21. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/doc/source/authentication.md +0 -0
  22. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/doc/source/decorator.md +0 -0
  23. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/doc/source/generate_openapi.md +0 -0
  24. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/doc/source/getting_started.md +0 -0
  25. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/doc/source/internationalisation.md +0 -0
  26. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/doc/source/model.md +0 -0
  27. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/doc/source/pfx_views.md +0 -0
  28. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/doc/source/profiling.md +0 -0
  29. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/doc/source/settings.md +0 -0
  30. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/doc/source/testing.md +0 -0
  31. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/img/pfx.png +0 -0
  32. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/img/pfx.svg +0 -0
  33. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/__init__.py +0 -0
  34. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/__init__.py +0 -0
  35. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/apidoc/__init__.py +0 -0
  36. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/apidoc/parameters.py +0 -0
  37. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/apidoc/schema.py +0 -0
  38. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/apidoc/tags.py +0 -0
  39. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/apps.py +0 -0
  40. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/decorator/__init__.py +0 -0
  41. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/decorator/rest.py +0 -0
  42. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/default_settings.py +0 -0
  43. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/exceptions.py +0 -0
  44. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/fields.py +0 -0
  45. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/http/__init__.py +0 -0
  46. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/http/json_response.py +0 -0
  47. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/locale/fr/LC_MESSAGES/django.mo +0 -0
  48. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/locale/fr/LC_MESSAGES/django.po +0 -0
  49. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/management/__init__.py +0 -0
  50. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/management/commands/__init__.py +0 -0
  51. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/management/commands/makeapidoc.py +0 -0
  52. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/management/commands/profile.py +0 -0
  53. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/middleware/__init__.py +0 -0
  54. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/middleware/locale.py +0 -0
  55. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/middleware/profiling.py +0 -0
  56. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/models/__init__.py +0 -0
  57. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/models/abstract_pfx_base_user.py +0 -0
  58. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/models/cache_mixins.py +0 -0
  59. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/models/login_ban.py +0 -0
  60. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/models/not_null_fields.py +0 -0
  61. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/models/otp_user_mixin.py +0 -0
  62. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/models/pfx_models.py +0 -0
  63. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/models/user_filtered_queryset_mixin.py +0 -0
  64. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/serializers/__init__.py +0 -0
  65. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/serializers/json.py +0 -0
  66. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/settings.py +0 -0
  67. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/shortcuts.py +0 -0
  68. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/storage/__init__.py +0 -0
  69. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/storage/s3_storage.py +0 -0
  70. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/templates/registration/otp_code_email.txt +0 -0
  71. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/templates/registration/otp_code_subject.txt +0 -0
  72. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/templates/registration/password_reset_email.txt +0 -0
  73. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/templates/registration/password_reset_subject.txt +0 -0
  74. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/templates/registration/welcome_email.txt +0 -0
  75. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/templates/registration/welcome_subject.txt +0 -0
  76. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/test.py +0 -0
  77. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/urls.py +0 -0
  78. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/__init__.py +0 -0
  79. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/fields.py +0 -0
  80. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/filters_views.py +0 -0
  81. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/locale_views.py +0 -0
  82. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/parameters/__init__.py +0 -0
  83. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/parameters/date_format.py +0 -0
  84. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/parameters/groups.py +0 -0
  85. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/parameters/list_count.py +0 -0
  86. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/parameters/list_items.py +0 -0
  87. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/parameters/list_mode.py +0 -0
  88. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/parameters/list_order.py +0 -0
  89. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/parameters/list_search.py +0 -0
  90. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/parameters/media_redirect.py +0 -0
  91. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/parameters/meta_fields.py +0 -0
  92. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/parameters/meta_filters.py +0 -0
  93. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/parameters/meta_orders.py +0 -0
  94. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/parameters/subset.py +0 -0
  95. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/parameters/subset_limit.py +0 -0
  96. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/parameters/subset_offset.py +0 -0
  97. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/parameters/subset_page.py +0 -0
  98. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/parameters/subset_page_size.py +0 -0
  99. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/parameters/subset_page_subset.py +0 -0
  100. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pfx/pfxcore/views/rest_views.py +0 -0
  101. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/pyproject.toml +0 -0
  102. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/requirements.txt +0 -0
  103. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/runtest.py +0 -0
  104. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/serve-doc +0 -0
  105. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/setup.cfg +0 -0
  106. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/setup.py +0 -0
  107. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/__init__.py +0 -0
  108. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/locale/fr/LC_MESSAGES/django.po +0 -0
  109. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/models.py +0 -0
  110. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/settings/__init__.py +0 -0
  111. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/settings/ci.py +0 -0
  112. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/settings/common.py +0 -0
  113. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/settings/dev.py +0 -0
  114. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/settings/dev_custom_example.py +0 -0
  115. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/settings/dev_default.py +0 -0
  116. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/tests/__init__.py +0 -0
  117. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/tests/basic_api_errors.py +0 -0
  118. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/tests/basic_api_test.py +0 -0
  119. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/tests/test_api_doc.py +0 -0
  120. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/tests/test_body_mixin.py +0 -0
  121. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/tests/test_cache.py +0 -0
  122. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/tests/test_client.py +0 -0
  123. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/tests/test_fields.py +0 -0
  124. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/tests/test_filters.py +0 -0
  125. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/tests/test_locale_api.py +0 -0
  126. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/tests/test_perm_tests.py +0 -0
  127. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/tests/test_perms_api.py +0 -0
  128. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/tests/test_profiling_middleware.py +0 -0
  129. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/tests/test_shortcuts.py +0 -0
  130. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/tests/test_timezone_middleware.py +0 -0
  131. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/tests/test_tools.py +0 -0
  132. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/tests/test_user_queryset.py +0 -0
  133. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/tests/test_view_decorators.py +0 -0
  134. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/tests/test_view_fields.py +0 -0
  135. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/urls.py +0 -0
  136. {django-pfx-1.4.dev24 → django-pfx-1.4.dev26}/tests/views.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-pfx
3
- Version: 1.4.dev24
3
+ Version: 1.4.dev26
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.dev24
3
+ Version: 1.4.dev26
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
@@ -30,13 +30,29 @@ class JWTTokenDecodeMixin:
30
30
  return user
31
31
 
32
32
  @classmethod
33
- def decode_jwt(cls, token, otp_login=False):
33
+ def decode_jwt_header(cls, token):
34
34
  try:
35
35
  headers = jwt.get_unverified_header(token)
36
36
  if 'pfx_user_pk' not in headers:
37
37
  raise jwt.InvalidTokenError(
38
38
  "Missing pfx_user_pk in token headers")
39
- user = cls.get_cached_user(headers['pfx_user_pk'])
39
+ return headers['pfx_user_pk']
40
+ except (jwt.ExpiredSignatureError,
41
+ jwt.InvalidTokenError, jwt.InvalidSignatureError,
42
+ DecodeError) as e:
43
+ # Log these exceptions only in debug mode
44
+ logger.debug(e, exc_info=True)
45
+ raise
46
+ except Exception as e:
47
+ # Always logs unexpected exceptions
48
+ logger.exception(e)
49
+ raise
50
+
51
+ @classmethod
52
+ def decode_jwt(cls, token, otp_login=False):
53
+ user_pk = cls.decode_jwt_header(token)
54
+ try:
55
+ user = cls.get_cached_user(user_pk)
40
56
  decoded = jwt.decode(
41
57
  token,
42
58
  user.get_user_jwt_signature_key() + settings.PFX_SECRET_KEY,
@@ -49,11 +65,12 @@ class JWTTokenDecodeMixin:
49
65
  "This token is reserved for OTP login")
50
66
  return user
51
67
  except (get_user_model().DoesNotExist, jwt.ExpiredSignatureError,
52
- jwt.InvalidTokenError, jwt.InvalidSignatureError) as e:
68
+ jwt.InvalidTokenError, jwt.InvalidSignatureError,
69
+ DecodeError) as e:
53
70
  # Log these exceptions only in debug mode
54
71
  logger.debug(e, exc_info=True)
55
72
  raise
56
- except (DecodeError, Exception) as e:
73
+ except Exception as e:
57
74
  # Always logs unexpected exceptions
58
75
  logger.exception(e)
59
76
  raise
@@ -72,11 +89,11 @@ class AuthenticationMiddleware(JWTTokenDecodeMixin, MiddlewareMixin):
72
89
  authorization = request.headers.get('Authorization')
73
90
  if authorization:
74
91
  try:
75
- _, key = authorization.split("Bearer ")
92
+ _, token = authorization.split("Bearer ")
76
93
  except ValueError:
77
- key = None
94
+ token = ""
78
95
  try:
79
- request.user = self.decode_jwt(key)
96
+ request.user = self.decode_jwt(token)
80
97
  except Exception:
81
98
  request.user = AnonymousUser()
82
99
  else:
@@ -102,10 +119,10 @@ class CookieAuthenticationMiddleware(JWTTokenDecodeMixin, MiddlewareMixin):
102
119
  """
103
120
 
104
121
  def process_request(self, request):
105
- key = request.COOKIES.get('token')
106
- if key:
122
+ token = request.COOKIES.get('token', "")
123
+ if token:
107
124
  try:
108
- request.user = self.decode_jwt(key)
125
+ request.user = self.decode_jwt(token)
109
126
  except Exception:
110
127
  request.user = AnonymousUser()
111
128
  request.delete_cookie = True
@@ -261,9 +261,7 @@ class AuthenticationView(
261
261
  return jwt.encode(
262
262
  payload,
263
263
  user.get_user_jwt_signature_key() + settings.PFX_SECRET_KEY,
264
- headers=dict(
265
- pfx_user_pk=user.pk,
266
- username=user.get_username()),
264
+ headers=dict(pfx_user_pk=user.pk),
267
265
  algorithm="HS256")
268
266
 
269
267
  def get_extra_payload(self, user):
@@ -559,9 +557,13 @@ class AuthenticationView(
559
557
  description: If the OTP is disabled for this user.
560
558
  """
561
559
  data = self.deserialize_body()
562
- token = data.get('token')
563
- username = jwt.get_unverified_header(token).get('username')
564
- ban_dt = LoginBan.objects.is_ban(username)
560
+ token = data.get('token', "")
561
+ try:
562
+ user_pk = self.decode_jwt_header(token)
563
+ ban_key = f"otp_{user_pk}"
564
+ except Exception:
565
+ raise UnauthorizedError()
566
+ ban_dt = LoginBan.objects.is_ban(ban_key)
565
567
  if ban_dt:
566
568
  return self.login_ban_response(ban_dt)
567
569
  try:
@@ -574,9 +576,9 @@ class AuthenticationView(
574
576
  if not user.otp_secret_token:
575
577
  raise ForbiddenError()
576
578
  if user.is_otp_valid(data.get('otp_code')):
577
- LoginBan.objects.unban(username)
579
+ LoginBan.objects.unban(ban_key)
578
580
  return self._login_success(user, mode, remember_me)
579
- LoginBan.objects.ban(username)
581
+ LoginBan.objects.ban(ban_key)
580
582
  return self.login_failed_response()
581
583
 
582
584
  def get_user(self, uidb64):
@@ -836,9 +838,8 @@ class OtpEmailView(BodyMixin, JWTTokenDecodeMixin, BaseRestView):
836
838
  data = self.deserialize_body()
837
839
  try:
838
840
  user, __, __ = self.decode_jwt(
839
- data.get('token'), otp_login=True)
840
- except Exception as e:
841
- logger.exception(e)
841
+ data.get('token', ""), otp_login=True)
842
+ except Exception:
842
843
  raise UnauthorizedError()
843
844
  else:
844
845
  user = self.request.user
@@ -1287,20 +1287,20 @@ class AuthAPITest(TestAssertMixin, TransactionTestCase):
1287
1287
  code_match = re.search(
1288
1288
  r'Authentication code: (\d{6})', mail.outbox[0].body)
1289
1289
  self.assertIsNotNone(code_match)
1290
- otp_code = int(code_match.group(1))
1290
+ otp_code = code_match.group(1)
1291
1291
 
1292
- with freeze_time("2023-05-01 08:15:01"):
1292
+ with freeze_time("2023-05-01 08:15:00"):
1293
1293
  response = self.client.post('/api/auth/otp/login', dict(
1294
1294
  token=otp_token,
1295
1295
  otp_code=otp_code))
1296
- self.assertRC(response, 422)
1296
+ self.assertRC(response, 200)
1297
+ self.assertJEExists(response, 'token')
1297
1298
 
1298
- with freeze_time("2023-05-01 08:15:00"):
1299
+ with freeze_time("2023-05-01 08:15:01"):
1299
1300
  response = self.client.post('/api/auth/otp/login', dict(
1300
1301
  token=otp_token,
1301
1302
  otp_code=otp_code))
1302
- self.assertRC(response, 200)
1303
- self.assertJEExists(response, 'token')
1303
+ self.assertRC(response, 422)
1304
1304
 
1305
1305
  @override_settings(
1306
1306
  PFX_HOTP_CODE_VALIDITY=15,
File without changes
File without changes
File without changes
File without changes
File without changes