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.
- {oxutils-0.6.0 → oxutils-0.6.2}/PKG-INFO +1 -1
- {oxutils-0.6.0 → oxutils-0.6.2}/pyproject.toml +1 -1
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/__init__.py +1 -1
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mixins.py +3 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/sessions/controllers.py +7 -2
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/tokens/tokens.py +23 -0
- oxutils-0.6.2/src/oxutils/auth/tokens/utils.py +56 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/utils.py +8 -3
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/jwt/models.py +4 -0
- oxutils-0.6.0/src/oxutils/auth/tokens/utils.py +0 -53
- {oxutils-0.6.0 → oxutils-0.6.2}/README.md +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/apps.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/audit/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/audit/apps.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/audit/export.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/audit/locale/fr/LC_MESSAGES/django.po +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/audit/masks.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/audit/migrations/0001_initial.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/audit/migrations/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/audit/models.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/audit/settings.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/audit/utils.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/adapter.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/admin.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/app_settings.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/apps.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/constants.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/controllers.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/emails/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/emails/controllers.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/emails/schemas.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/emails/services.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/exceptions.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/invitations/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/invitations/backend.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/invitations/controllers.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/invitations/models.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/invitations/schemas.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/invitations/tokens.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/adapter.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/base/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/base/controllers.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/base/schemas.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/recovery_codes/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/recovery_codes/controllers.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/recovery_codes/flows.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/recovery_codes/schemas.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/recovery_codes/services.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/totp/__ini__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/totp/controllers.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/totp/flows.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/totp/permissions.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/totp/schemas.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/totp/services.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/mfa/utils.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/migrations/0001_initial.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/migrations/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/models.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/password_reset/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/password_reset/controllers.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/password_reset/models.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/password_reset/permissions.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/password_reset/schemas.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/registration/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/registration/controllers.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/registration/schemas.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/schemas.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/sessions/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/sessions/schemas.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/signals.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/templatetags/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/templatetags/spa_urls.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/tokens/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/tokens/app_settings.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/tokens/models.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/auth/tokens/schemas.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/celery/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/celery/base.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/celery/settings.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/conf.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/constants.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/context/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/context/site_name_processor.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/admin.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/apps.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/caches.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/controllers.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/enums.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/management/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/management/commands/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/management/commands/sync_currency.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/migrations/0001_initial.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/migrations/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/models.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/schemas.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/signals.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/tests.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/currency/utils.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/enums/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/enums/audit.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/enums/invoices.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/exceptions.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/functions.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/jwt/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/jwt/auth.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/jwt/middleware.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/jwt/tokens.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/jwt/utils.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/logger/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/logger/receivers.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/logger/settings.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/mixins/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/mixins/base.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/mixins/schemas.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/mixins/services.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/models/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/models/base.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/models/billing.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/models/change_tracker.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/models/fields.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/models/invoice.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/admin.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/apps.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/authorization.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/cacheops.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/caches.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/checks.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/constants.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/context.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/controllers.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/enums.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/exceptions.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/locale/fr/LC_MESSAGES/django.po +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/management/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/management/commands/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/management/commands/grant_tenant_owners.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/management/commands/init_oxiliere_system.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/middleware.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/migrations/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/models.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/permissions.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/schemas.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/services.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/settings.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/signals.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/tests.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/utils.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/pdf/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/pdf/printer.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/pdf/utils.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/pdf/views.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/actions.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/admin.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/apps.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/caches.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/checks.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/constants.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/controllers.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/exceptions.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/locale/fr/LC_MESSAGES/django.po +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/management/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/management/commands/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/management/commands/load_permission_preset.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/migrations/0001_initial.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/migrations/0002_alter_grant_role.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/migrations/0003_alter_grant_options_alter_group_options_and_more.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/migrations/0004_group_app_group_permissions_app_9a9924_idx.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/migrations/0005_role_app.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/migrations/0006_alter_rolegrant_options_and_more.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/migrations/0007_grant_locked_alter_grant_role_and_more.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/migrations/0008_remove_grant_unique_user_scope_role_and_more.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/migrations/0009_grant_is_active.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/migrations/0010_increase_action_max_length.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/migrations/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/models.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/permissions.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/perms.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/presets.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/queryset.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/schemas.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/services.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/tests.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/permissions/utils.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/py.typed +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/s3.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/settings.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/templates/account/email/base_message.txt +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/templates/email/password/reset_email_message.html +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/templates/email/password/reset_email_message.txt +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/templates/email/password/reset_email_subject.txt +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/templates/email/signup/email_message.html +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/templates/email/signup/email_subject.txt +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/templates/verified.html +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/types.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/admin.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/apps.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/locale/fr/LC_MESSAGES/django.po +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/migrations/0001_initial.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/migrations/0002_alter_user_first_name_alter_user_last_name.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/migrations/0003_user_photo.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/migrations/0004_alter_user_options.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/migrations/__init__.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/models.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/tests.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/users/utils.py +0 -0
- {oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/utils.py +0 -0
|
@@ -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
|
|
37
|
-
|
|
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
|
-
|
|
277
|
-
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/management/commands/grant_tenant_owners.py
RENAMED
|
File without changes
|
{oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/oxiliere/management/commands/init_oxiliere_system.py
RENAMED
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/templates/email/password/reset_email_message.html
RENAMED
|
File without changes
|
{oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/templates/email/password/reset_email_message.txt
RENAMED
|
File without changes
|
{oxutils-0.6.0 → oxutils-0.6.2}/src/oxutils/templates/email/password/reset_email_subject.txt
RENAMED
|
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
|
|
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
|