oxutils 0.6.0__tar.gz → 0.6.2__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 (212) hide show
  1. {oxutils-0.6.0 → oxutils-0.6.2}/PKG-INFO +1 -1
  2. {oxutils-0.6.0 → oxutils-0.6.2}/pyproject.toml +1 -1
  3. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/__init__.py +1 -1
  4. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mixins.py +3 -0
  5. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/sessions/controllers.py +7 -2
  6. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/tokens/tokens.py +23 -0
  7. oxutils-0.6.2/src/oxutils/auth/tokens/utils.py +56 -0
  8. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/utils.py +8 -3
  9. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/jwt/models.py +4 -0
  10. oxutils-0.6.0/src/oxutils/auth/tokens/utils.py +0 -53
  11. {oxutils-0.6.0 → oxutils-0.6.2}/README.md +0 -0
  12. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/apps.py +0 -0
  13. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/audit/__init__.py +0 -0
  14. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/audit/apps.py +0 -0
  15. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/audit/export.py +0 -0
  16. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/audit/locale/fr/LC_MESSAGES/django.po +0 -0
  17. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/audit/masks.py +0 -0
  18. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/audit/migrations/0001_initial.py +0 -0
  19. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/audit/migrations/__init__.py +0 -0
  20. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/audit/models.py +0 -0
  21. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/audit/settings.py +0 -0
  22. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/audit/utils.py +0 -0
  23. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/__init__.py +0 -0
  24. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/adapter.py +0 -0
  25. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/admin.py +0 -0
  26. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/app_settings.py +0 -0
  27. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/apps.py +0 -0
  28. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/constants.py +0 -0
  29. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/controllers.py +0 -0
  30. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/emails/__init__.py +0 -0
  31. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/emails/controllers.py +0 -0
  32. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/emails/schemas.py +0 -0
  33. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/emails/services.py +0 -0
  34. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/exceptions.py +0 -0
  35. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/invitations/__init__.py +0 -0
  36. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/invitations/backend.py +0 -0
  37. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/invitations/controllers.py +0 -0
  38. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/invitations/models.py +0 -0
  39. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/invitations/schemas.py +0 -0
  40. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/invitations/tokens.py +0 -0
  41. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/__init__.py +0 -0
  42. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/adapter.py +0 -0
  43. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/base/__init__.py +0 -0
  44. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/base/controllers.py +0 -0
  45. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/base/schemas.py +0 -0
  46. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/recovery_codes/__init__.py +0 -0
  47. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/recovery_codes/controllers.py +0 -0
  48. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/recovery_codes/flows.py +0 -0
  49. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/recovery_codes/schemas.py +0 -0
  50. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/recovery_codes/services.py +0 -0
  51. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/totp/__ini__.py +0 -0
  52. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/totp/controllers.py +0 -0
  53. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/totp/flows.py +0 -0
  54. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/totp/permissions.py +0 -0
  55. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/totp/schemas.py +0 -0
  56. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/totp/services.py +0 -0
  57. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/utils.py +0 -0
  58. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/migrations/0001_initial.py +0 -0
  59. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/migrations/__init__.py +0 -0
  60. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/models.py +0 -0
  61. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/password_reset/__init__.py +0 -0
  62. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/password_reset/controllers.py +0 -0
  63. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/password_reset/models.py +0 -0
  64. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/password_reset/permissions.py +0 -0
  65. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/password_reset/schemas.py +0 -0
  66. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/registration/__init__.py +0 -0
  67. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/registration/controllers.py +0 -0
  68. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/registration/schemas.py +0 -0
  69. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/schemas.py +0 -0
  70. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/sessions/__init__.py +0 -0
  71. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/sessions/schemas.py +0 -0
  72. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/signals.py +0 -0
  73. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/templatetags/__init__.py +0 -0
  74. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/templatetags/spa_urls.py +0 -0
  75. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/tokens/__init__.py +0 -0
  76. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/tokens/app_settings.py +0 -0
  77. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/tokens/models.py +0 -0
  78. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/tokens/schemas.py +0 -0
  79. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/celery/__init__.py +0 -0
  80. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/celery/base.py +0 -0
  81. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/celery/settings.py +0 -0
  82. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/conf.py +0 -0
  83. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/constants.py +0 -0
  84. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/context/__init__.py +0 -0
  85. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/context/site_name_processor.py +0 -0
  86. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/__init__.py +0 -0
  87. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/admin.py +0 -0
  88. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/apps.py +0 -0
  89. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/caches.py +0 -0
  90. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/controllers.py +0 -0
  91. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/enums.py +0 -0
  92. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/management/__init__.py +0 -0
  93. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/management/commands/__init__.py +0 -0
  94. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/management/commands/sync_currency.py +0 -0
  95. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/migrations/0001_initial.py +0 -0
  96. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/migrations/__init__.py +0 -0
  97. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/models.py +0 -0
  98. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/schemas.py +0 -0
  99. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/signals.py +0 -0
  100. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/tests.py +0 -0
  101. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/utils.py +0 -0
  102. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/enums/__init__.py +0 -0
  103. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/enums/audit.py +0 -0
  104. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/enums/invoices.py +0 -0
  105. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/exceptions.py +0 -0
  106. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/functions.py +0 -0
  107. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/jwt/__init__.py +0 -0
  108. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/jwt/auth.py +0 -0
  109. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/jwt/middleware.py +0 -0
  110. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/jwt/tokens.py +0 -0
  111. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/jwt/utils.py +0 -0
  112. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/logger/__init__.py +0 -0
  113. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/logger/receivers.py +0 -0
  114. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/logger/settings.py +0 -0
  115. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/mixins/__init__.py +0 -0
  116. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/mixins/base.py +0 -0
  117. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/mixins/schemas.py +0 -0
  118. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/mixins/services.py +0 -0
  119. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/models/__init__.py +0 -0
  120. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/models/base.py +0 -0
  121. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/models/billing.py +0 -0
  122. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/models/change_tracker.py +0 -0
  123. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/models/fields.py +0 -0
  124. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/models/invoice.py +0 -0
  125. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/__init__.py +0 -0
  126. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/admin.py +0 -0
  127. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/apps.py +0 -0
  128. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/authorization.py +0 -0
  129. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/cacheops.py +0 -0
  130. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/caches.py +0 -0
  131. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/checks.py +0 -0
  132. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/constants.py +0 -0
  133. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/context.py +0 -0
  134. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/controllers.py +0 -0
  135. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/enums.py +0 -0
  136. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/exceptions.py +0 -0
  137. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/locale/fr/LC_MESSAGES/django.po +0 -0
  138. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/management/__init__.py +0 -0
  139. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/management/commands/__init__.py +0 -0
  140. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/management/commands/grant_tenant_owners.py +0 -0
  141. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/management/commands/init_oxiliere_system.py +0 -0
  142. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/middleware.py +0 -0
  143. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/migrations/__init__.py +0 -0
  144. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/models.py +0 -0
  145. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/permissions.py +0 -0
  146. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/schemas.py +0 -0
  147. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/services.py +0 -0
  148. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/settings.py +0 -0
  149. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/signals.py +0 -0
  150. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/tests.py +0 -0
  151. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/utils.py +0 -0
  152. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/pdf/__init__.py +0 -0
  153. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/pdf/printer.py +0 -0
  154. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/pdf/utils.py +0 -0
  155. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/pdf/views.py +0 -0
  156. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/__init__.py +0 -0
  157. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/actions.py +0 -0
  158. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/admin.py +0 -0
  159. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/apps.py +0 -0
  160. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/caches.py +0 -0
  161. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/checks.py +0 -0
  162. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/constants.py +0 -0
  163. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/controllers.py +0 -0
  164. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/exceptions.py +0 -0
  165. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/locale/fr/LC_MESSAGES/django.po +0 -0
  166. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/management/__init__.py +0 -0
  167. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/management/commands/__init__.py +0 -0
  168. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/management/commands/load_permission_preset.py +0 -0
  169. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/migrations/0001_initial.py +0 -0
  170. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/migrations/0002_alter_grant_role.py +0 -0
  171. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/migrations/0003_alter_grant_options_alter_group_options_and_more.py +0 -0
  172. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/migrations/0004_group_app_group_permissions_app_9a9924_idx.py +0 -0
  173. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/migrations/0005_role_app.py +0 -0
  174. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/migrations/0006_alter_rolegrant_options_and_more.py +0 -0
  175. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/migrations/0007_grant_locked_alter_grant_role_and_more.py +0 -0
  176. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/migrations/0008_remove_grant_unique_user_scope_role_and_more.py +0 -0
  177. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/migrations/0009_grant_is_active.py +0 -0
  178. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/migrations/0010_increase_action_max_length.py +0 -0
  179. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/migrations/__init__.py +0 -0
  180. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/models.py +0 -0
  181. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/permissions.py +0 -0
  182. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/perms.py +0 -0
  183. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/presets.py +0 -0
  184. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/queryset.py +0 -0
  185. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/schemas.py +0 -0
  186. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/services.py +0 -0
  187. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/tests.py +0 -0
  188. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/utils.py +0 -0
  189. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/py.typed +0 -0
  190. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/s3.py +0 -0
  191. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/settings.py +0 -0
  192. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/templates/account/email/base_message.txt +0 -0
  193. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/templates/email/password/reset_email_message.html +0 -0
  194. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/templates/email/password/reset_email_message.txt +0 -0
  195. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/templates/email/password/reset_email_subject.txt +0 -0
  196. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/templates/email/signup/email_message.html +0 -0
  197. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/templates/email/signup/email_subject.txt +0 -0
  198. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/templates/verified.html +0 -0
  199. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/types.py +0 -0
  200. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/__init__.py +0 -0
  201. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/admin.py +0 -0
  202. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/apps.py +0 -0
  203. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/locale/fr/LC_MESSAGES/django.po +0 -0
  204. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/migrations/0001_initial.py +0 -0
  205. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/migrations/0002_alter_user_first_name_alter_user_last_name.py +0 -0
  206. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/migrations/0003_user_photo.py +0 -0
  207. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/migrations/0004_alter_user_options.py +0 -0
  208. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/migrations/__init__.py +0 -0
  209. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/models.py +0 -0
  210. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/tests.py +0 -0
  211. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/utils.py +0 -0
  212. {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: oxutils
3
- Version: 0.6.0
3
+ Version: 0.6.2
4
4
  Summary: Production-ready utilities for Django applications in the Oxiliere ecosystem
5
5
  Keywords: django,utilities,jwt,audit,logging,celery,structlog
6
6
  Author: Edimedia Mutoke
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "oxutils"
3
- version = "0.6.0"
3
+ version = "0.6.2"
4
4
  description = "Production-ready utilities for Django applications in the Oxiliere ecosystem"
5
5
  readme = "README.md"
6
6
  license = "LGPL-3.0-only"
@@ -40,7 +40,7 @@ Other:
40
40
  image validation, bound-request detection
41
41
  """
42
42
 
43
- __version__ = "0.6.0"
43
+ __version__ = "0.6.2"
44
44
 
45
45
  from oxutils.conf import AUDIT_MIDDLEWARE, UTILS_APPS
46
46
  from oxutils.settings import oxi_settings
@@ -2,6 +2,7 @@
2
2
  Cookie token mixin with configurable security flags.
3
3
  """
4
4
  from django.conf import settings
5
+ from ninja_jwt.settings import api_settings
5
6
 
6
7
  from oxutils.auth.constants import ACCESS_TOKEN_COOKIE, REFRESH_TOKEN_COOKIE
7
8
 
@@ -39,6 +40,7 @@ class CookieTokenMixin:
39
40
  self.context.response.set_cookie(
40
41
  key=REFRESH_TOKEN_COOKIE,
41
42
  value=refresh_token,
43
+ max_age=int(api_settings.REFRESH_TOKEN_LIFETIME.total_seconds()),
42
44
  httponly=httponly,
43
45
  domain=domain,
44
46
  secure=secure,
@@ -48,6 +50,7 @@ class CookieTokenMixin:
48
50
  self.context.response.set_cookie(
49
51
  key=ACCESS_TOKEN_COOKIE,
50
52
  value=access_token,
53
+ max_age=int(api_settings.ACCESS_TOKEN_LIFETIME.total_seconds()),
51
54
  httponly=httponly,
52
55
  domain=domain,
53
56
  secure=secure,
@@ -33,8 +33,13 @@ class UserSessionController(ControllerBase):
33
33
 
34
34
  def _validate_current_session_age(self, request: HttpRequest) -> None:
35
35
  """
36
- Validate that the current session (the one making the request) is older than 3 days
37
- This ensures account security by preventing new sessions from deleting established sessions.
36
+ Validate that the current session (the one making the request) is older
37
+ than 3 days.
38
+
39
+ The age comes from the ``cat`` claim, stamped once when the session is
40
+ created. Rotating the refresh token preserves it, so a long-lived
41
+ session keeps the ability to revoke newer ones — even after a
42
+ reauthentication (which only moves ``rat``).
38
43
  """
39
44
  # Get the current session token from Authorization header
40
45
 
@@ -18,7 +18,15 @@ class RefreshToken(DefaultRefreshToken):
18
18
 
19
19
  def __init__(self, token: Optional[Any] = None, verify: bool = True) -> None:
20
20
  super().__init__(token, verify)
21
+ # ``cat`` is the session creation time. It is stamped once, when the
22
+ # session opens, and never moves afterwards: rotating a token must not
23
+ # make an old session look new (the 3-day revoke guard relies on it).
21
24
  self.set_cat() # type: ignore
25
+ # ``rat`` is the last time the user actually re-proved their identity.
26
+ # A brand-new token is "recently authenticated"; a rotated token
27
+ # inherits the claim from its predecessor.
28
+ if token is None:
29
+ self.set_rat() # type: ignore
22
30
 
23
31
  def set_session(self, id_=None):
24
32
  """
@@ -46,6 +54,21 @@ class RefreshToken(DefaultRefreshToken):
46
54
 
47
55
  self.payload[claim] = datetime_to_epoch(at_time)
48
56
 
57
+ def set_rat(
58
+ self,
59
+ claim: str = "rat",
60
+ at_time: Optional[datetime] = None,
61
+ force: bool = False,
62
+ ) -> None:
63
+ """Set the last reauthentication time if absent (or force it)."""
64
+ if self.payload.get(claim) and not force:
65
+ return
66
+
67
+ if at_time is None:
68
+ at_time = self.current_time
69
+
70
+ self.payload[claim] = datetime_to_epoch(at_time)
71
+
49
72
  @classmethod
50
73
  def for_user(cls, user, request=None, enabled=True):
51
74
  """
@@ -0,0 +1,56 @@
1
+ from typing import cast, Dict
2
+ from oxutils.auth.tokens.app_settings import RefreshToken
3
+ from oxutils.auth.tokens.models import (
4
+ RefreshTokenWhitelistModel,
5
+ )
6
+ from ninja_jwt.exceptions import InvalidToken
7
+ from oxutils.auth.utils import is_email_verified
8
+
9
+
10
+
11
+
12
+ def create_user_token(user, request):
13
+ refresh = RefreshToken.for_user(user, request=request)
14
+ return cast(RefreshToken, refresh)
15
+
16
+
17
+ def refresh_token(token: str, context: Dict):
18
+ refresh = RefreshToken(token)
19
+
20
+ current = RefreshTokenWhitelistModel.objects.filter(
21
+ jti=refresh.payload["jti"]
22
+ ).first()
23
+ if current is None:
24
+ # Already rotated or revoked. It cannot authenticate anything anymore;
25
+ # deleting the whole session here would turn a benign concurrent
26
+ # refresh (multiple tabs, retries) into a logout.
27
+ raise InvalidToken()
28
+
29
+ if not current.enabled:
30
+ is_email_verified(current.user, raise_exception=True)
31
+ raise InvalidToken()
32
+
33
+ context = dict(context or {})
34
+ force = bool(context.pop("force", False))
35
+
36
+ data = {"access": str(refresh.access_token)}
37
+
38
+ refresh.set_jti()
39
+ refresh.set_exp()
40
+ refresh.set_iat()
41
+ # A rotation is not a reauthentication: only ``rat`` may move, and only
42
+ # when the caller explicitly re-proved the identity.
43
+ if force:
44
+ refresh.set_rat(force=True)
45
+
46
+ data["refresh"] = str(refresh)
47
+
48
+ # Rotate in place: ``created`` (session start), ``session`` and ``enabled``
49
+ # stay untouched, and bypassing ``RefreshTokenManager.create()`` keeps the
50
+ # rotation from counting as a new session (no eviction at the limit).
51
+ for field, value in context.items():
52
+ setattr(current, field, value)
53
+ current.jti = refresh.payload["jti"]
54
+ current.save()
55
+
56
+ return data
@@ -273,12 +273,17 @@ def did_recently_authenticate(request: HttpRequest) -> bool:
273
273
  return True
274
274
 
275
275
  user = get_token_user(request)
276
- cat_claim = getattr(user, "token_created_at", None)
277
- if not cat_claim:
276
+ # ``rat`` is the explicit reauthentication timestamp. Tokens minted before
277
+ # 0.6.2 only carry ``cat`` (their login time): falling back to it is safe,
278
+ # since it can never make an old token look freshly reauthenticated.
279
+ reauth_claim = getattr(user, "token_reauthenticated_at", None) or getattr(
280
+ user, "token_created_at", None
281
+ )
282
+ if not reauth_claim:
278
283
  return False
279
284
 
280
285
  try:
281
- authenticated_at = datetime_from_epoch(cat_claim)
286
+ authenticated_at = datetime_from_epoch(reauth_claim)
282
287
  time_diff = time.time() - authenticated_at.timestamp()
283
288
  timeout = allauth_settings.REAUTHENTICATION_TIMEOUT
284
289
  return time_diff < timeout
@@ -19,6 +19,10 @@ class TokenUser(DefaultTonkenUser):
19
19
  def token_created_at(self):
20
20
  return self.token.get("cat", None)
21
21
 
22
+ @cached_property
23
+ def token_reauthenticated_at(self):
24
+ return self.token.get("rat", None)
25
+
22
26
  @cached_property
23
27
  def token_session(self):
24
28
  return self.token.get("session", None)
@@ -1,53 +0,0 @@
1
- from typing import cast, Dict
2
- from django.utils import timezone
3
- from oxutils.auth.tokens.app_settings import RefreshToken
4
- from oxutils.auth.tokens.models import (
5
- RefreshTokenWhitelistModel,
6
- )
7
- from ninja_jwt.exceptions import InvalidToken
8
- from oxutils.auth.utils import is_email_verified
9
-
10
-
11
-
12
-
13
- def create_user_token(user, request):
14
- refresh = RefreshToken.for_user(user, request=request)
15
- return cast(RefreshToken, refresh)
16
-
17
-
18
- def refresh_token(token: str, context: Dict):
19
- refresh = RefreshToken(token)
20
-
21
- query_set = list(RefreshTokenWhitelistModel.objects.filter(jti=refresh.payload["jti"]).all())
22
- if len(query_set) == 0:
23
- # Suspicious operation
24
- RefreshTokenWhitelistModel.objects.filter(session=refresh.payload["session"]).delete()
25
- raise InvalidToken()
26
- if not query_set[0].enabled:
27
- is_email_verified(query_set[0].user, raise_exception=True)
28
- raise InvalidToken()
29
-
30
- data = {"access": str(refresh.access_token)}
31
-
32
- RefreshTokenWhitelistModel.objects.filter(jti=refresh.payload["jti"]).delete()
33
-
34
- refresh.set_jti()
35
- refresh.set_exp()
36
- refresh.set_iat()
37
- refresh.set_cat(force=bool(context.pop('force', False)))
38
-
39
- data["refresh"] = str(refresh)
40
-
41
- serializer_data = {
42
- 'jti': refresh.payload['jti'],
43
- 'user_id': refresh.payload['user_id'],
44
- 'session': refresh.payload['session'],
45
- 'created': timezone.now(),
46
- **context
47
- }
48
-
49
- RefreshTokenWhitelistModel.objects.create(
50
- **serializer_data
51
- )
52
-
53
- return data
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes