oxutils 0.5.2__tar.gz → 0.6.0__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.5.2 → oxutils-0.6.0}/PKG-INFO +5 -1
- {oxutils-0.5.2 → oxutils-0.6.0}/README.md +4 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/pyproject.toml +1 -1
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/__init__.py +1 -1
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/jwt/auth.py +7 -13
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/jwt/utils.py +1 -1
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/middleware.py +1 -1
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/permissions.py +2 -0
- oxutils-0.6.0/src/oxutils/settings.py +79 -0
- oxutils-0.5.2/src/oxutils/settings.py +0 -72
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/apps.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/audit/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/audit/apps.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/audit/export.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/audit/locale/fr/LC_MESSAGES/django.po +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/audit/masks.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/audit/migrations/0001_initial.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/audit/migrations/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/audit/models.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/audit/settings.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/audit/utils.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/adapter.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/admin.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/app_settings.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/apps.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/constants.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/controllers.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/emails/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/emails/controllers.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/emails/schemas.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/emails/services.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/exceptions.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/invitations/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/invitations/backend.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/invitations/controllers.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/invitations/models.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/invitations/schemas.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/invitations/tokens.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/mfa/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/mfa/adapter.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/mfa/base/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/mfa/base/controllers.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/mfa/base/schemas.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/mfa/recovery_codes/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/mfa/recovery_codes/controllers.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/mfa/recovery_codes/flows.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/mfa/recovery_codes/schemas.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/mfa/recovery_codes/services.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/mfa/totp/__ini__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/mfa/totp/controllers.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/mfa/totp/flows.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/mfa/totp/permissions.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/mfa/totp/schemas.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/mfa/totp/services.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/mfa/utils.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/migrations/0001_initial.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/migrations/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/mixins.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/models.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/password_reset/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/password_reset/controllers.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/password_reset/models.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/password_reset/permissions.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/password_reset/schemas.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/registration/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/registration/controllers.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/registration/schemas.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/schemas.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/sessions/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/sessions/controllers.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/sessions/schemas.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/signals.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/templatetags/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/templatetags/spa_urls.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/tokens/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/tokens/app_settings.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/tokens/models.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/tokens/schemas.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/tokens/tokens.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/tokens/utils.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/auth/utils.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/celery/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/celery/base.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/celery/settings.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/conf.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/constants.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/context/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/context/site_name_processor.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/currency/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/currency/admin.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/currency/apps.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/currency/caches.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/currency/controllers.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/currency/enums.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/currency/management/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/currency/management/commands/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/currency/management/commands/sync_currency.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/currency/migrations/0001_initial.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/currency/migrations/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/currency/models.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/currency/schemas.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/currency/signals.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/currency/tests.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/currency/utils.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/enums/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/enums/audit.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/enums/invoices.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/exceptions.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/functions.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/jwt/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/jwt/middleware.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/jwt/models.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/jwt/tokens.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/logger/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/logger/receivers.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/logger/settings.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/mixins/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/mixins/base.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/mixins/schemas.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/mixins/services.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/models/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/models/base.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/models/billing.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/models/change_tracker.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/models/fields.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/models/invoice.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/admin.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/apps.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/authorization.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/cacheops.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/caches.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/checks.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/constants.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/context.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/controllers.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/enums.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/exceptions.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/locale/fr/LC_MESSAGES/django.po +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/management/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/management/commands/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/management/commands/grant_tenant_owners.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/management/commands/init_oxiliere_system.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/migrations/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/models.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/permissions.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/schemas.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/services.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/settings.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/signals.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/tests.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/utils.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/pdf/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/pdf/printer.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/pdf/utils.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/pdf/views.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/actions.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/admin.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/apps.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/caches.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/checks.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/constants.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/controllers.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/exceptions.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/locale/fr/LC_MESSAGES/django.po +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/management/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/management/commands/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/management/commands/load_permission_preset.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/migrations/0001_initial.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/migrations/0002_alter_grant_role.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/migrations/0003_alter_grant_options_alter_group_options_and_more.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/migrations/0004_group_app_group_permissions_app_9a9924_idx.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/migrations/0005_role_app.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/migrations/0006_alter_rolegrant_options_and_more.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/migrations/0007_grant_locked_alter_grant_role_and_more.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/migrations/0008_remove_grant_unique_user_scope_role_and_more.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/migrations/0009_grant_is_active.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/migrations/0010_increase_action_max_length.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/migrations/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/models.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/perms.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/presets.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/queryset.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/schemas.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/services.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/tests.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/permissions/utils.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/py.typed +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/s3.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/templates/account/email/base_message.txt +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/templates/email/password/reset_email_message.html +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/templates/email/password/reset_email_message.txt +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/templates/email/password/reset_email_subject.txt +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/templates/email/signup/email_message.html +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/templates/email/signup/email_subject.txt +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/templates/verified.html +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/types.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/users/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/users/admin.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/users/apps.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/users/locale/fr/LC_MESSAGES/django.po +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/users/migrations/0001_initial.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/users/migrations/0002_alter_user_first_name_alter_user_last_name.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/users/migrations/0003_user_photo.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/users/migrations/0004_alter_user_options.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/users/migrations/__init__.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/users/models.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/users/tests.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/users/utils.py +0 -0
- {oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: oxutils
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
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
|
|
@@ -121,6 +121,10 @@ MIDDLEWARE = [
|
|
|
121
121
|
```bash
|
|
122
122
|
OXI_SERVICE_NAME=my-service
|
|
123
123
|
OXI_JWT_JWKS_URL=https://auth.example.com/.well-known/jwks.json
|
|
124
|
+
|
|
125
|
+
# JWT keys are base64-encoded PEM contents (not file paths)
|
|
126
|
+
OXI_JWT_SIGNING_KEY=$(base64 -w0 private_key.pem)
|
|
127
|
+
OXI_JWT_VERIFYING_KEY=$(base64 -w0 public_key.pem)
|
|
124
128
|
```
|
|
125
129
|
|
|
126
130
|
### 3. Usage Examples
|
|
@@ -59,6 +59,10 @@ MIDDLEWARE = [
|
|
|
59
59
|
```bash
|
|
60
60
|
OXI_SERVICE_NAME=my-service
|
|
61
61
|
OXI_JWT_JWKS_URL=https://auth.example.com/.well-known/jwks.json
|
|
62
|
+
|
|
63
|
+
# JWT keys are base64-encoded PEM contents (not file paths)
|
|
64
|
+
OXI_JWT_SIGNING_KEY=$(base64 -w0 private_key.pem)
|
|
65
|
+
OXI_JWT_VERIFYING_KEY=$(base64 -w0 public_key.pem)
|
|
62
66
|
```
|
|
63
67
|
|
|
64
68
|
### 3. Usage Examples
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import os
|
|
2
1
|
from typing import Any, Dict, List, Optional, Tuple, Type
|
|
3
2
|
|
|
4
3
|
from django.contrib.auth import SESSION_KEY, get_user_model
|
|
@@ -33,31 +32,26 @@ def get_jwks() -> Dict[str, Any]:
|
|
|
33
32
|
Dict containing the public JWK in JWKS format.
|
|
34
33
|
|
|
35
34
|
Raises:
|
|
36
|
-
ImproperlyConfigured: If jwt_verifying_key is not configured or
|
|
35
|
+
ImproperlyConfigured: If jwt_verifying_key is not configured or is not a
|
|
36
|
+
valid base64-encoded PEM string.
|
|
37
37
|
"""
|
|
38
38
|
global _public_jwk_cache
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
key_data = oxi_settings.jwt_verifying_key_pem
|
|
41
|
+
|
|
42
|
+
if key_data is None:
|
|
41
43
|
raise ImproperlyConfigured(
|
|
42
44
|
"JWT verifying key is not configured. Set OXI_JWT_VERIFYING_KEY environment variable."
|
|
43
45
|
)
|
|
44
46
|
|
|
45
|
-
key_path = oxi_settings.jwt_verifying_key
|
|
46
|
-
|
|
47
|
-
if not os.path.exists(key_path):
|
|
48
|
-
raise ImproperlyConfigured(f"JWT verifying key file not found at: {key_path}")
|
|
49
|
-
|
|
50
47
|
if _public_jwk_cache is None:
|
|
51
48
|
try:
|
|
52
|
-
with open(key_path, "r") as f:
|
|
53
|
-
key_data = f.read()
|
|
54
|
-
|
|
55
49
|
_public_jwk_cache = jwk.JWK.from_pem(key_data.encode("utf-8"))
|
|
56
50
|
_public_jwk_cache.update(kid="main")
|
|
57
51
|
except Exception as e:
|
|
58
52
|
raise ImproperlyConfigured(
|
|
59
|
-
f"Failed to load JWT verifying key
|
|
60
|
-
)
|
|
53
|
+
f"Failed to load JWT verifying key: {str(e)}"
|
|
54
|
+
) from e
|
|
61
55
|
|
|
62
56
|
return {"keys": [_public_jwk_cache.export(as_dict=True)]}
|
|
63
57
|
|
|
@@ -39,7 +39,7 @@ def populate_user(request: HttpRequest):
|
|
|
39
39
|
return
|
|
40
40
|
|
|
41
41
|
try:
|
|
42
|
-
request.user = User.objects.get(
|
|
42
|
+
request.user = User.objects.get(pk=request.user.id)
|
|
43
43
|
except User.DoesNotExist as exc:
|
|
44
44
|
logger.exception("user_not_found", oxi_id=request.user.id, message=str(exc))
|
|
45
45
|
raise InvalidToken() from exc
|
|
@@ -57,7 +57,7 @@ class TenantMainMiddleware(MiddlewareMixin):
|
|
|
57
57
|
try:
|
|
58
58
|
return tenant.users.select_related("user").get(user__pk=user.id, status="active")
|
|
59
59
|
except ObjectDoesNotExist as exc:
|
|
60
|
-
logger.error("tenant_user_not_found", tenant_id=tenant.id, user_id=user.id,
|
|
60
|
+
logger.error("tenant_user_not_found", tenant_id=tenant.id, user_id=user.id, error=str(exc))
|
|
61
61
|
if raise_exception:
|
|
62
62
|
raise ObjectDoesNotExist("tenant_user_not_found") from exc
|
|
63
63
|
return None
|
|
@@ -11,6 +11,8 @@ in the active language.
|
|
|
11
11
|
|
|
12
12
|
from django.utils.translation import gettext_lazy as _
|
|
13
13
|
|
|
14
|
+
ACCESS_APPLICATION_NAME = "access"
|
|
15
|
+
|
|
14
16
|
# ── Actions used internally by the permissions module ────────────────
|
|
15
17
|
# The ``access`` scope is strictly owned by ``oxutils.permissions``.
|
|
16
18
|
PERMISSION_PRESET = {
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import binascii
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import Field
|
|
6
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
'oxi_settings',
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class OxUtilsSettings(BaseSettings):
|
|
14
|
+
model_config = SettingsConfigDict(
|
|
15
|
+
validate_assignment=True,
|
|
16
|
+
extra="ignore",
|
|
17
|
+
env_prefix='OXI_'
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
# Service
|
|
21
|
+
service_name: Optional[str] = 'Oxutils'
|
|
22
|
+
site_name: Optional[str] = 'Oxiliere'
|
|
23
|
+
site_domain: Optional[str] = 'oxiliere.com'
|
|
24
|
+
multitenancy: bool = Field(False)
|
|
25
|
+
|
|
26
|
+
# Auth JWT Settings — base64-encoded PEM strings
|
|
27
|
+
jwt_signing_key: Optional[str] = None
|
|
28
|
+
jwt_verifying_key: Optional[str] = None
|
|
29
|
+
jwt_jwks_url: Optional[str] = None
|
|
30
|
+
jwt_access_token_key: str = Field('access')
|
|
31
|
+
jwt_algorithm: Optional[str] = Field('RS256')
|
|
32
|
+
jwt_access_token_lifetime: int = Field(15) # minutes
|
|
33
|
+
|
|
34
|
+
# AuditLog
|
|
35
|
+
log_access: bool = Field(False)
|
|
36
|
+
retention_delay: int = Field(7) # one week
|
|
37
|
+
|
|
38
|
+
# logger
|
|
39
|
+
log_file_path: Optional[str] = Field('logs/oxiliere.log')
|
|
40
|
+
|
|
41
|
+
def model_post_init(self, __context):
|
|
42
|
+
"""Called after model initialization to perform validation."""
|
|
43
|
+
self._validate_jwt_keys()
|
|
44
|
+
|
|
45
|
+
@staticmethod
|
|
46
|
+
def _decode_jwt_key(value: str, name: str) -> str:
|
|
47
|
+
"""Decode a base64-encoded PEM key, raising ValueError if invalid."""
|
|
48
|
+
try:
|
|
49
|
+
decoded = base64.b64decode("".join(value.split()), validate=True)
|
|
50
|
+
return decoded.decode("utf-8")
|
|
51
|
+
except (binascii.Error, UnicodeDecodeError) as exc:
|
|
52
|
+
raise ValueError(
|
|
53
|
+
f"{name} is not a valid base64-encoded PEM string: {exc}"
|
|
54
|
+
) from exc
|
|
55
|
+
|
|
56
|
+
def _validate_jwt_keys(self):
|
|
57
|
+
"""Validate that configured JWT keys are valid base64-encoded PEM strings."""
|
|
58
|
+
if self.jwt_signing_key:
|
|
59
|
+
self._decode_jwt_key(self.jwt_signing_key, "JWT signing key")
|
|
60
|
+
|
|
61
|
+
if self.jwt_verifying_key:
|
|
62
|
+
self._decode_jwt_key(self.jwt_verifying_key, "JWT verifying key")
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def jwt_signing_key_pem(self) -> Optional[str]:
|
|
66
|
+
"""The decoded PEM signing key, or None if not configured."""
|
|
67
|
+
if not self.jwt_signing_key:
|
|
68
|
+
return None
|
|
69
|
+
return self._decode_jwt_key(self.jwt_signing_key, "JWT signing key")
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def jwt_verifying_key_pem(self) -> Optional[str]:
|
|
73
|
+
"""The decoded PEM verifying key, or None if not configured."""
|
|
74
|
+
if not self.jwt_verifying_key:
|
|
75
|
+
return None
|
|
76
|
+
return self._decode_jwt_key(self.jwt_verifying_key, "JWT verifying key")
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
oxi_settings = OxUtilsSettings()
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
from typing import Optional
|
|
2
|
-
from pydantic import Field
|
|
3
|
-
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
__all__ = [
|
|
9
|
-
'oxi_settings',
|
|
10
|
-
]
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class OxUtilsSettings(BaseSettings):
|
|
15
|
-
model_config = SettingsConfigDict(
|
|
16
|
-
validate_assignment=True,
|
|
17
|
-
extra="ignore",
|
|
18
|
-
env_prefix='OXI_'
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
# Service
|
|
22
|
-
service_name: Optional[str] = 'Oxutils'
|
|
23
|
-
site_name: Optional[str] = 'Oxiliere'
|
|
24
|
-
site_domain: Optional[str] = 'oxiliere.com'
|
|
25
|
-
multitenancy: bool = Field(False)
|
|
26
|
-
|
|
27
|
-
# Auth JWT Settings (JWT_SIGNING_KEY)
|
|
28
|
-
jwt_signing_key: Optional[str] = None
|
|
29
|
-
jwt_verifying_key: Optional[str] = None
|
|
30
|
-
jwt_jwks_url: Optional[str] = None
|
|
31
|
-
jwt_access_token_key: str = Field('access')
|
|
32
|
-
jwt_algorithm: Optional[str] = Field('RS256')
|
|
33
|
-
jwt_access_token_lifetime: int = Field(15) # minutes
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
# AuditLog
|
|
37
|
-
log_access: bool = Field(False)
|
|
38
|
-
retention_delay: int = Field(7) # one week
|
|
39
|
-
|
|
40
|
-
# logger
|
|
41
|
-
log_file_path: Optional[str] = Field('logs/oxiliere.log')
|
|
42
|
-
|
|
43
|
-
def model_post_init(self, __context):
|
|
44
|
-
"""Called after model initialization to perform validation."""
|
|
45
|
-
self._validate_jwt_keys()
|
|
46
|
-
|
|
47
|
-
def _validate_jwt_keys(self):
|
|
48
|
-
"""Validate JWT key files if configured."""
|
|
49
|
-
import os
|
|
50
|
-
|
|
51
|
-
if self.jwt_signing_key:
|
|
52
|
-
if not os.path.exists(self.jwt_signing_key):
|
|
53
|
-
raise ValueError(
|
|
54
|
-
f"JWT signing key file not found at: {self.jwt_signing_key}"
|
|
55
|
-
)
|
|
56
|
-
if not os.path.isfile(self.jwt_signing_key):
|
|
57
|
-
raise ValueError(
|
|
58
|
-
f"JWT signing key path is not a file: {self.jwt_signing_key}"
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
if self.jwt_verifying_key:
|
|
62
|
-
if not os.path.exists(self.jwt_verifying_key):
|
|
63
|
-
raise ValueError(
|
|
64
|
-
f"JWT verifying key file not found at: {self.jwt_verifying_key}"
|
|
65
|
-
)
|
|
66
|
-
if not os.path.isfile(self.jwt_verifying_key):
|
|
67
|
-
raise ValueError(
|
|
68
|
-
f"JWT verifying key path is not a file: {self.jwt_verifying_key}"
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
oxi_settings = OxUtilsSettings()
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/oxiliere/management/commands/grant_tenant_owners.py
RENAMED
|
File without changes
|
{oxutils-0.5.2 → oxutils-0.6.0}/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
|
{oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/templates/email/password/reset_email_message.html
RENAMED
|
File without changes
|
{oxutils-0.5.2 → oxutils-0.6.0}/src/oxutils/templates/email/password/reset_email_message.txt
RENAMED
|
File without changes
|
{oxutils-0.5.2 → oxutils-0.6.0}/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
|