oxutils 0.5.0__tar.gz → 0.5.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.5.0 → oxutils-0.5.2}/PKG-INFO +1 -1
- {oxutils-0.5.0 → oxutils-0.5.2}/pyproject.toml +2 -1
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/__init__.py +2 -2
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/currency/models.py +2 -1
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/jwt/utils.py +5 -5
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/authorization.py +13 -7
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/controllers.py +18 -18
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/management/commands/init_oxiliere_system.py +6 -1
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/services.py +7 -3
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/actions.py +3 -8
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/caches.py +15 -16
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/checks.py +16 -24
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/exceptions.py +24 -14
- oxutils-0.5.2/src/oxutils/permissions/locale/fr/LC_MESSAGES/django.po +130 -0
- oxutils-0.5.2/src/oxutils/permissions/management/commands/load_permission_preset.py +91 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/models.py +1 -1
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/queryset.py +2 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/services.py +298 -268
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/utils.py +127 -110
- oxutils-0.5.0/src/oxutils/pagination/cursor.py +0 -367
- oxutils-0.5.0/src/oxutils/permissions/locale/fr/LC_MESSAGES/django.po +0 -78
- oxutils-0.5.0/src/oxutils/permissions/management/commands/load_permission_preset.py +0 -112
- oxutils-0.5.0/src/oxutils/users/migrations/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/README.md +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/apps.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/audit/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/audit/apps.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/audit/export.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/audit/locale/fr/LC_MESSAGES/django.po +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/audit/masks.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/audit/migrations/0001_initial.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/audit/migrations/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/audit/models.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/audit/settings.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/audit/utils.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/adapter.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/admin.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/app_settings.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/apps.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/constants.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/controllers.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/emails/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/emails/controllers.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/emails/schemas.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/emails/services.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/exceptions.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/invitations/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/invitations/backend.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/invitations/controllers.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/invitations/models.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/invitations/schemas.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/invitations/tokens.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/mfa/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/mfa/adapter.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/mfa/base/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/mfa/base/controllers.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/mfa/base/schemas.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/mfa/recovery_codes/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/mfa/recovery_codes/controllers.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/mfa/recovery_codes/flows.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/mfa/recovery_codes/schemas.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/mfa/recovery_codes/services.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/mfa/totp/__ini__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/mfa/totp/controllers.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/mfa/totp/flows.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/mfa/totp/permissions.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/mfa/totp/schemas.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/mfa/totp/services.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/mfa/utils.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/migrations/0001_initial.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/migrations/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/mixins.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/models.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/password_reset/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/password_reset/controllers.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/password_reset/models.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/password_reset/permissions.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/password_reset/schemas.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/registration/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/registration/controllers.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/registration/schemas.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/schemas.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/sessions/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/sessions/controllers.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/sessions/schemas.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/signals.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/templatetags/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/templatetags/spa_urls.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/tokens/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/tokens/app_settings.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/tokens/models.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/tokens/schemas.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/tokens/tokens.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/tokens/utils.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/auth/utils.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/celery/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/celery/base.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/celery/settings.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/conf.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/constants.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/context/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/context/site_name_processor.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/currency/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/currency/admin.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/currency/apps.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/currency/caches.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/currency/controllers.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/currency/enums.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/currency/management/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/currency/management/commands/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/currency/management/commands/sync_currency.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/currency/migrations/0001_initial.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/currency/migrations/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/currency/schemas.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/currency/signals.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/currency/tests.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/currency/utils.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/enums/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/enums/audit.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/enums/invoices.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/exceptions.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/functions.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/jwt/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/jwt/auth.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/jwt/middleware.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/jwt/models.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/jwt/tokens.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/logger/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/logger/receivers.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/logger/settings.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/mixins/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/mixins/base.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/mixins/schemas.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/mixins/services.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/models/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/models/base.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/models/billing.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/models/change_tracker.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/models/fields.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/models/invoice.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/admin.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/apps.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/cacheops.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/caches.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/checks.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/constants.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/context.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/enums.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/exceptions.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/locale/fr/LC_MESSAGES/django.po +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/management/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/management/commands/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/management/commands/grant_tenant_owners.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/middleware.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/migrations/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/models.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/permissions.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/schemas.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/settings.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/signals.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/tests.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/utils.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/pdf/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/pdf/printer.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/pdf/utils.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/pdf/views.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/admin.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/apps.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/constants.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/controllers.py +0 -0
- {oxutils-0.5.0/src/oxutils/pagination → oxutils-0.5.2/src/oxutils/permissions/management}/__init__.py +0 -0
- {oxutils-0.5.0/src/oxutils/permissions/management → oxutils-0.5.2/src/oxutils/permissions/management/commands}/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/migrations/0001_initial.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/migrations/0002_alter_grant_role.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/migrations/0003_alter_grant_options_alter_group_options_and_more.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/migrations/0004_group_app_group_permissions_app_9a9924_idx.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/migrations/0005_role_app.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/migrations/0006_alter_rolegrant_options_and_more.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/migrations/0007_grant_locked_alter_grant_role_and_more.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/migrations/0008_remove_grant_unique_user_scope_role_and_more.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/migrations/0009_grant_is_active.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/migrations/0010_increase_action_max_length.py +0 -0
- {oxutils-0.5.0/src/oxutils/permissions/management/commands → oxutils-0.5.2/src/oxutils/permissions/migrations}/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/permissions.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/perms.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/presets.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/schemas.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/permissions/tests.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/py.typed +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/s3.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/settings.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/templates/account/email/base_message.txt +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/templates/email/password/reset_email_message.html +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/templates/email/password/reset_email_message.txt +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/templates/email/password/reset_email_subject.txt +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/templates/email/signup/email_message.html +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/templates/email/signup/email_subject.txt +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/templates/verified.html +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/types.py +0 -0
- {oxutils-0.5.0/src/oxutils/permissions/migrations → oxutils-0.5.2/src/oxutils/users}/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/users/admin.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/users/apps.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/users/locale/fr/LC_MESSAGES/django.po +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/users/migrations/0001_initial.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/users/migrations/0002_alter_user_first_name_alter_user_last_name.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/users/migrations/0003_user_photo.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/users/migrations/0004_alter_user_options.py +0 -0
- {oxutils-0.5.0/src/oxutils/users → oxutils-0.5.2/src/oxutils/users/migrations}/__init__.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/users/models.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/users/tests.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/users/utils.py +0 -0
- {oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "oxutils"
|
|
3
|
-
version = "0.5.
|
|
3
|
+
version = "0.5.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"
|
|
@@ -100,6 +100,7 @@ dev = [
|
|
|
100
100
|
"ruff>=0.8.0",
|
|
101
101
|
"twine>=6.0.0",
|
|
102
102
|
"psycopg[binary]>=3.3.2",
|
|
103
|
+
"django-stubs>=6.0.7",
|
|
103
104
|
]
|
|
104
105
|
|
|
105
106
|
|
|
@@ -18,7 +18,7 @@ Infrastructure & tooling:
|
|
|
18
18
|
- Structured logging with correlation IDs, request metadata binding,
|
|
19
19
|
and pre-built ``LOGGING`` configuration (structlog)
|
|
20
20
|
- Audit log export to S3 with export-state tracking and status history
|
|
21
|
-
-
|
|
21
|
+
- Paginated APIs via Django Ninja Extra (``PageNumberPaginationExtra``)
|
|
22
22
|
- PDF generation via WeasyPrint (``Printer`` class and ``WeasyTemplateView``)
|
|
23
23
|
- Multi-currency support with rate syncing (BCC, Open Exchange Rates)
|
|
24
24
|
- Celery app with task auto-discovery and structlog integration
|
|
@@ -40,7 +40,7 @@ Other:
|
|
|
40
40
|
image validation, bound-request detection
|
|
41
41
|
"""
|
|
42
42
|
|
|
43
|
-
__version__ = "0.5.
|
|
43
|
+
__version__ = "0.5.2"
|
|
44
44
|
|
|
45
45
|
from oxutils.conf import AUDIT_MIDDLEWARE, UTILS_APPS
|
|
46
46
|
from oxutils.settings import oxi_settings
|
|
@@ -9,8 +9,8 @@ from oxutils.models import (
|
|
|
9
9
|
)
|
|
10
10
|
|
|
11
11
|
from .enums import CurrencySource
|
|
12
|
+
from .signals import currency_sync_failed, currency_sync_succeeded
|
|
12
13
|
from .utils import load_rates
|
|
13
|
-
from .signals import currency_sync_succeeded, currency_sync_failed
|
|
14
14
|
|
|
15
15
|
logger = structlog.get_logger(__name__)
|
|
16
16
|
|
|
@@ -20,6 +20,7 @@ AVAILABLES_CURRENCIES = [
|
|
|
20
20
|
"AUD",
|
|
21
21
|
"BIF",
|
|
22
22
|
"CAD",
|
|
23
|
+
"CDF",
|
|
23
24
|
"CHF",
|
|
24
25
|
"CNY",
|
|
25
26
|
"EUR",
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
from functools import wraps
|
|
2
|
+
|
|
2
3
|
import structlog
|
|
3
4
|
from django.contrib.auth import get_user_model
|
|
4
5
|
from django.http import HttpRequest
|
|
5
|
-
|
|
6
6
|
from ninja_jwt.exceptions import InvalidToken
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
8
|
logger = structlog.getLogger("django")
|
|
11
9
|
User = get_user_model()
|
|
12
10
|
|
|
@@ -26,11 +24,13 @@ def load_user(f):
|
|
|
26
24
|
# self.request.user will be the complete user object
|
|
27
25
|
pass
|
|
28
26
|
"""
|
|
27
|
+
|
|
29
28
|
@wraps(f)
|
|
30
29
|
def wrapper(self, *args, **kwargs):
|
|
31
30
|
populate_user(self.context.request)
|
|
32
31
|
res = f(self, *args, **kwargs)
|
|
33
32
|
return res
|
|
33
|
+
|
|
34
34
|
return wrapper
|
|
35
35
|
|
|
36
36
|
|
|
@@ -41,5 +41,5 @@ def populate_user(request: HttpRequest):
|
|
|
41
41
|
try:
|
|
42
42
|
request.user = User.objects.get(oxi_id=request.user.id)
|
|
43
43
|
except User.DoesNotExist as exc:
|
|
44
|
-
logger.exception(
|
|
45
|
-
raise InvalidToken()
|
|
44
|
+
logger.exception("user_not_found", oxi_id=request.user.id, message=str(exc))
|
|
45
|
+
raise InvalidToken() from exc
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from django.conf import settings
|
|
2
1
|
from django.db import transaction
|
|
3
2
|
|
|
4
3
|
from oxutils.oxiliere.models import BaseTenant
|
|
@@ -9,21 +8,28 @@ from oxutils.permissions.utils import assign_role
|
|
|
9
8
|
|
|
10
9
|
@transaction.atomic
|
|
11
10
|
def grant_manager_access_to_owners(tenant: BaseTenant):
|
|
11
|
+
"""
|
|
12
|
+
Grant **all** configured permissions to every tenant owner.
|
|
13
|
+
|
|
14
|
+
Idempotent — can be called multiple times without creating duplicates.
|
|
15
|
+
Uses :func:`assign_role` which performs an upsert per (user, scope, role).
|
|
16
|
+
"""
|
|
12
17
|
tenant_user_model = get_tenant_user_model()
|
|
13
18
|
tenant_users = tenant_user_model.objects.select_related("user").filter(
|
|
14
19
|
tenant=tenant, is_owner=True
|
|
15
20
|
)
|
|
16
21
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
# Vérifier qu'il y a des RoleGrants pour ce scope
|
|
20
|
-
role_grants = list(RoleGrant.objects.filter(scope=access_scope))
|
|
22
|
+
role_grants = list(RoleGrant.objects.select_related("role").all())
|
|
21
23
|
|
|
22
24
|
if not role_grants:
|
|
23
25
|
return
|
|
24
26
|
|
|
25
27
|
for tenant_user in tenant_users:
|
|
26
|
-
for
|
|
28
|
+
for rg in role_grants:
|
|
27
29
|
assign_role(
|
|
28
|
-
user=tenant_user.user,
|
|
30
|
+
user=tenant_user.user,
|
|
31
|
+
role=rg.role.slug,
|
|
32
|
+
scope=rg.scope,
|
|
33
|
+
by=None,
|
|
34
|
+
user_group=None,
|
|
29
35
|
)
|
|
@@ -2,43 +2,43 @@ from uuid import UUID
|
|
|
2
2
|
|
|
3
3
|
from ninja_extra import (
|
|
4
4
|
api_controller,
|
|
5
|
+
http_delete,
|
|
5
6
|
http_get,
|
|
6
7
|
http_put,
|
|
7
|
-
http_delete,
|
|
8
|
-
)
|
|
9
|
-
from ninja_extra.permissions import (
|
|
10
|
-
IsAuthenticated,
|
|
11
8
|
)
|
|
12
9
|
from ninja_extra.pagination import (
|
|
13
|
-
paginate,
|
|
14
|
-
PaginatedResponseSchema,
|
|
15
10
|
PageNumberPaginationExtra,
|
|
11
|
+
PaginatedResponseSchema,
|
|
12
|
+
paginate,
|
|
13
|
+
)
|
|
14
|
+
from ninja_extra.permissions import (
|
|
15
|
+
IsAuthenticated,
|
|
16
16
|
)
|
|
17
|
+
|
|
17
18
|
from oxutils.oxiliere.permissions import (
|
|
18
19
|
IsTenantAdmin,
|
|
19
20
|
IsTenantOwner,
|
|
20
21
|
)
|
|
22
|
+
|
|
21
23
|
from .schemas import (
|
|
22
|
-
get_tenant_user_list_schema,
|
|
23
|
-
get_tenant_user_detail_schema,
|
|
24
|
-
UpdateTenantUserSchema,
|
|
25
24
|
SetAdminSchema,
|
|
26
25
|
SetOwnerSchema,
|
|
26
|
+
UpdateTenantUserSchema,
|
|
27
|
+
get_tenant_user_detail_schema,
|
|
28
|
+
get_tenant_user_list_schema,
|
|
27
29
|
)
|
|
28
30
|
from .services import TenantUserService
|
|
29
31
|
|
|
30
|
-
|
|
31
32
|
TenantUserListSchema = get_tenant_user_list_schema()
|
|
32
33
|
TenantUserDetailSchema = get_tenant_user_detail_schema()
|
|
33
34
|
|
|
34
35
|
service = TenantUserService()
|
|
35
36
|
|
|
36
37
|
|
|
37
|
-
@api_controller(
|
|
38
|
+
@api_controller("/users")
|
|
38
39
|
class UserController:
|
|
39
|
-
|
|
40
40
|
@http_get(
|
|
41
|
-
|
|
41
|
+
"",
|
|
42
42
|
response=PaginatedResponseSchema[TenantUserListSchema],
|
|
43
43
|
permissions=[IsAuthenticated, IsTenantAdmin],
|
|
44
44
|
)
|
|
@@ -47,7 +47,7 @@ class UserController:
|
|
|
47
47
|
return service.list()
|
|
48
48
|
|
|
49
49
|
@http_get(
|
|
50
|
-
|
|
50
|
+
"/{user_id}",
|
|
51
51
|
response=TenantUserDetailSchema,
|
|
52
52
|
permissions=[IsAuthenticated, IsTenantAdmin],
|
|
53
53
|
)
|
|
@@ -55,7 +55,7 @@ class UserController:
|
|
|
55
55
|
return service.get(user_id)
|
|
56
56
|
|
|
57
57
|
@http_put(
|
|
58
|
-
|
|
58
|
+
"/{user_id}",
|
|
59
59
|
response=TenantUserDetailSchema,
|
|
60
60
|
permissions=[IsAuthenticated, IsTenantOwner],
|
|
61
61
|
)
|
|
@@ -63,7 +63,7 @@ class UserController:
|
|
|
63
63
|
return service.update(user_id, payload.dict(exclude_unset=True))
|
|
64
64
|
|
|
65
65
|
@http_put(
|
|
66
|
-
|
|
66
|
+
"/{user_id}/set-admin",
|
|
67
67
|
response=TenantUserDetailSchema,
|
|
68
68
|
permissions=[IsAuthenticated, IsTenantOwner],
|
|
69
69
|
)
|
|
@@ -71,7 +71,7 @@ class UserController:
|
|
|
71
71
|
return service.set_admin(user_id, payload.is_admin)
|
|
72
72
|
|
|
73
73
|
@http_put(
|
|
74
|
-
|
|
74
|
+
"/{user_id}/set-owner",
|
|
75
75
|
response=TenantUserDetailSchema,
|
|
76
76
|
permissions=[IsAuthenticated, IsTenantOwner],
|
|
77
77
|
)
|
|
@@ -79,7 +79,7 @@ class UserController:
|
|
|
79
79
|
return service.set_owner(user_id, payload.is_owner)
|
|
80
80
|
|
|
81
81
|
@http_delete(
|
|
82
|
-
|
|
82
|
+
"/{user_id}",
|
|
83
83
|
response={204: None},
|
|
84
84
|
permissions=[IsAuthenticated, IsTenantOwner],
|
|
85
85
|
)
|
{oxutils-0.5.0 → oxutils-0.5.2}/src/oxutils/oxiliere/management/commands/init_oxiliere_system.py
RENAMED
|
@@ -95,7 +95,12 @@ class Command(BaseCommand):
|
|
|
95
95
|
|
|
96
96
|
with tenant_context(tenant):
|
|
97
97
|
stats = load_preset()
|
|
98
|
-
|
|
98
|
+
self.stdout.write(
|
|
99
|
+
f" Permissions loaded: "
|
|
100
|
+
f"roles +{stats['roles']['created']}/~{stats['roles']['updated']}, "
|
|
101
|
+
f"groups +{stats['groups']['created']}/~{stats['groups']['updated']}, "
|
|
102
|
+
f"role_grants +{stats['role_grants']['created']}/~{stats['role_grants']['updated']}"
|
|
103
|
+
)
|
|
99
104
|
|
|
100
105
|
if created:
|
|
101
106
|
self.stdout.write(self.style.SUCCESS(f'✓ Superuser lié au tenant système'))
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Oxiliere services — TenantUser management + Tenant lifecycle.
|
|
3
3
|
"""
|
|
4
|
-
|
|
5
|
-
from typing import Optional
|
|
4
|
+
|
|
6
5
|
from uuid import UUID
|
|
7
6
|
|
|
7
|
+
import structlog
|
|
8
8
|
from django.contrib.auth.models import AbstractBaseUser
|
|
9
9
|
from django.db import transaction
|
|
10
10
|
from django.db.models import QuerySet
|
|
@@ -19,6 +19,7 @@ logger = structlog.get_logger(__name__)
|
|
|
19
19
|
|
|
20
20
|
# ── TenantUserService (existing) ────────────────────────────────────
|
|
21
21
|
|
|
22
|
+
|
|
22
23
|
class TenantUserService(BaseService):
|
|
23
24
|
logger = logger
|
|
24
25
|
|
|
@@ -98,6 +99,7 @@ class TenantUserService(BaseService):
|
|
|
98
99
|
|
|
99
100
|
# ── TenantService (new) ─────────────────────────────────────────────
|
|
100
101
|
|
|
102
|
+
|
|
101
103
|
class TenantService:
|
|
102
104
|
"""Thin service layer for tenant lifecycle operations."""
|
|
103
105
|
|
|
@@ -127,7 +129,9 @@ class TenantService:
|
|
|
127
129
|
tenant.save(update_fields=["status", "is_active"])
|
|
128
130
|
|
|
129
131
|
@staticmethod
|
|
130
|
-
def add_user(
|
|
132
|
+
def add_user(
|
|
133
|
+
tenant, user: AbstractBaseUser, is_owner: bool = False, is_admin: bool = False
|
|
134
|
+
) -> None:
|
|
131
135
|
tenant.add_user(user, is_owner=is_owner, is_admin=is_admin)
|
|
132
136
|
|
|
133
137
|
@staticmethod
|
|
@@ -33,6 +33,7 @@ no hierarchy expansion occurs (actions are treated as independent).
|
|
|
33
33
|
|
|
34
34
|
from __future__ import annotations
|
|
35
35
|
|
|
36
|
+
|
|
36
37
|
def _get_all_actions() -> dict[str, dict[str, dict]]:
|
|
37
38
|
"""Return all action definitions from ``PERMISSION_PRESET["actions"]``."""
|
|
38
39
|
from django.conf import settings
|
|
@@ -129,10 +130,7 @@ def validate_actions_for_scope(scope: str, actions: list[str]) -> list[str]:
|
|
|
129
130
|
|
|
130
131
|
invalid = [a for a in actions if a not in valid]
|
|
131
132
|
if invalid:
|
|
132
|
-
raise ValueError(
|
|
133
|
-
f"Invalid actions for scope '{scope}': {invalid}. "
|
|
134
|
-
f"Valid actions: {valid}"
|
|
135
|
-
)
|
|
133
|
+
raise ValueError(f"Invalid actions for scope '{scope}': {invalid}. Valid actions: {valid}")
|
|
136
134
|
return actions
|
|
137
135
|
|
|
138
136
|
|
|
@@ -172,7 +170,4 @@ def get_scope_actions_labels(scope: str) -> dict[str, str]:
|
|
|
172
170
|
Returns:
|
|
173
171
|
Dict mapping action key → translated label.
|
|
174
172
|
"""
|
|
175
|
-
return {
|
|
176
|
-
action: get_action_label(scope, action)
|
|
177
|
-
for action in get_valid_actions(scope)
|
|
178
|
-
}
|
|
173
|
+
return {action: get_action_label(scope, action) for action in get_valid_actions(scope)}
|
|
@@ -1,33 +1,32 @@
|
|
|
1
1
|
from django.conf import settings
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
CACHE_CHECK_PERMISSION = getattr(settings, 'CACHE_CHECK_PERMISSION', False)
|
|
3
|
+
CACHE_CHECK_PERMISSION = getattr(settings, "CACHE_CHECK_PERMISSION", False)
|
|
6
4
|
|
|
7
5
|
if CACHE_CHECK_PERMISSION:
|
|
8
6
|
from cacheops import cached_as
|
|
7
|
+
|
|
9
8
|
from .models import Grant
|
|
10
|
-
from .utils import
|
|
9
|
+
from .utils import any_action_check, any_permission_check, check
|
|
11
10
|
|
|
12
|
-
@cached_as(Grant, timeout=60*15)
|
|
13
|
-
def cache_check(user, scope, actions, role
|
|
11
|
+
@cached_as(Grant, timeout=60 * 15)
|
|
12
|
+
def cache_check(user, scope, actions, role=None, **context):
|
|
14
13
|
return check(user, scope, actions, role=role, **context)
|
|
15
|
-
|
|
16
|
-
@cached_as(Grant, timeout=60*15)
|
|
17
|
-
def cache_any_action_check(user, scope, required, role
|
|
14
|
+
|
|
15
|
+
@cached_as(Grant, timeout=60 * 15)
|
|
16
|
+
def cache_any_action_check(user, scope, required, role=None, **context):
|
|
18
17
|
return any_action_check(user, scope, required, role=role, **context)
|
|
19
|
-
|
|
20
|
-
@cached_as(Grant, timeout=60*15)
|
|
18
|
+
|
|
19
|
+
@cached_as(Grant, timeout=60 * 15)
|
|
21
20
|
def cache_any_permission_check(user, *str_perms):
|
|
22
21
|
return any_permission_check(user, *str_perms)
|
|
23
22
|
else:
|
|
24
|
-
from .utils import
|
|
23
|
+
from .utils import any_action_check, any_permission_check, check
|
|
25
24
|
|
|
26
|
-
def cache_check(user, scope, actions, role
|
|
25
|
+
def cache_check(user, scope, actions, role=None, **context):
|
|
27
26
|
return check(user, scope, actions, role=role, **context)
|
|
28
|
-
|
|
29
|
-
def cache_any_action_check(user, scope, required, role
|
|
27
|
+
|
|
28
|
+
def cache_any_action_check(user, scope, required, role=None, **context):
|
|
30
29
|
return any_action_check(user, scope, required, role=role, **context)
|
|
31
|
-
|
|
30
|
+
|
|
32
31
|
def cache_any_permission_check(user, *str_perms):
|
|
33
32
|
return any_permission_check(user, *str_perms)
|
|
@@ -23,7 +23,7 @@ Example configuration in settings.py:
|
|
|
23
23
|
|
|
24
24
|
PERMISSION_PRESET = {
|
|
25
25
|
"roles": [...],
|
|
26
|
-
"
|
|
26
|
+
"groups": [...],
|
|
27
27
|
"role_grants": [...]
|
|
28
28
|
}
|
|
29
29
|
"""
|
|
@@ -134,14 +134,14 @@ def check_permission_settings(app_configs, **kwargs):
|
|
|
134
134
|
)
|
|
135
135
|
else:
|
|
136
136
|
# Check required keys
|
|
137
|
-
required_keys = ["roles", "
|
|
137
|
+
required_keys = ["roles", "groups", "role_grants"]
|
|
138
138
|
for key in required_keys:
|
|
139
139
|
if key not in preset:
|
|
140
140
|
errors.append(
|
|
141
141
|
Error(
|
|
142
142
|
f"PERMISSION_PRESET is missing required key: {key}",
|
|
143
143
|
hint=f'Add "{key}" key to PERMISSION_PRESET',
|
|
144
|
-
id=
|
|
144
|
+
id="permissions.E007",
|
|
145
145
|
)
|
|
146
146
|
)
|
|
147
147
|
|
|
@@ -206,15 +206,15 @@ def check_permission_settings(app_configs, **kwargs):
|
|
|
206
206
|
and settings.ACCESS_MANAGER_GROUP is not None
|
|
207
207
|
and hasattr(settings, "PERMISSION_PRESET")
|
|
208
208
|
and isinstance(settings.PERMISSION_PRESET, dict)
|
|
209
|
-
and "
|
|
209
|
+
and "groups" in settings.PERMISSION_PRESET
|
|
210
210
|
):
|
|
211
|
-
group_slugs = [g.get("slug") for g in settings.PERMISSION_PRESET.get("
|
|
211
|
+
group_slugs = [g.get("slug") for g in settings.PERMISSION_PRESET.get("groups", [])]
|
|
212
212
|
|
|
213
213
|
if settings.ACCESS_MANAGER_GROUP not in group_slugs:
|
|
214
214
|
errors.append(
|
|
215
215
|
Error(
|
|
216
216
|
f'ACCESS_MANAGER_GROUP "{settings.ACCESS_MANAGER_GROUP}" is not in PERMISSION_PRESET groups',
|
|
217
|
-
hint=f'Add a group with slug "{settings.ACCESS_MANAGER_GROUP}" to PERMISSION_PRESET["
|
|
217
|
+
hint=f'Add a group with slug "{settings.ACCESS_MANAGER_GROUP}" to PERMISSION_PRESET["groups"]',
|
|
218
218
|
id="permissions.E009",
|
|
219
219
|
)
|
|
220
220
|
)
|
|
@@ -257,7 +257,7 @@ def check_permission_settings(app_configs, **kwargs):
|
|
|
257
257
|
)
|
|
258
258
|
)
|
|
259
259
|
|
|
260
|
-
for group_data in settings.PERMISSION_PRESET.get("
|
|
260
|
+
for group_data in settings.PERMISSION_PRESET.get("groups", []):
|
|
261
261
|
app = group_data.get("app")
|
|
262
262
|
if app and app not in apps_list:
|
|
263
263
|
errors.append(
|
|
@@ -268,17 +268,12 @@ def check_permission_settings(app_configs, **kwargs):
|
|
|
268
268
|
)
|
|
269
269
|
)
|
|
270
270
|
|
|
271
|
-
# Cross-validation: scope ownership — each scope in actions must be unique across apps
|
|
271
|
+
# Cross-validation: scope ownership — each scope in actions must be unique across apps.
|
|
272
|
+
# (Conflicts between settings.PERMISSION_PRESET and app presets are already caught
|
|
273
|
+
# by register_preset() which raises ImproperlyConfigured at startup.)
|
|
272
274
|
if hasattr(settings, "PERMISSION_PRESET") and isinstance(settings.PERMISSION_PRESET, dict):
|
|
273
275
|
scope_owners: dict[str, str] = {}
|
|
274
276
|
|
|
275
|
-
# Collect scopes from the base preset (settings.py)
|
|
276
|
-
base_actions = settings.PERMISSION_PRESET.get("actions", {})
|
|
277
|
-
if isinstance(base_actions, dict):
|
|
278
|
-
for scope in base_actions:
|
|
279
|
-
scope_owners[scope] = "settings.PERMISSION_PRESET"
|
|
280
|
-
|
|
281
|
-
# Collect scopes from discovered app presets
|
|
282
277
|
from oxutils.permissions.presets import discover_app_presets
|
|
283
278
|
|
|
284
279
|
for preset in discover_app_presets():
|
|
@@ -290,13 +285,10 @@ def check_permission_settings(app_configs, **kwargs):
|
|
|
290
285
|
if scope in scope_owners:
|
|
291
286
|
errors.append(
|
|
292
287
|
Error(
|
|
293
|
-
f'Scope "{scope}" is
|
|
294
|
-
f'
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
f'Remove the scope "{scope}" from app "{app_label}" '
|
|
298
|
-
f"or use a different scope name."
|
|
299
|
-
),
|
|
288
|
+
f'Scope "{scope}" is defined in both '
|
|
289
|
+
f'"{scope_owners[scope]}" and "{app_label}". '
|
|
290
|
+
f'Each scope must be owned by exactly one app.',
|
|
291
|
+
hint=f'Remove the scope "{scope}" from one of the apps.',
|
|
300
292
|
id="permissions.E022",
|
|
301
293
|
)
|
|
302
294
|
)
|
|
@@ -316,7 +308,7 @@ def check_permission_settings(app_configs, **kwargs):
|
|
|
316
308
|
break
|
|
317
309
|
|
|
318
310
|
if not has_app_attr:
|
|
319
|
-
for group_data in settings.PERMISSION_PRESET.get("
|
|
311
|
+
for group_data in settings.PERMISSION_PRESET.get("groups", []):
|
|
320
312
|
if group_data.get("app"):
|
|
321
313
|
has_app_attr = True
|
|
322
314
|
break
|
|
@@ -384,7 +376,7 @@ def check_permission_settings(app_configs, **kwargs):
|
|
|
384
376
|
)
|
|
385
377
|
continue
|
|
386
378
|
try:
|
|
387
|
-
|
|
379
|
+
import_string(path)
|
|
388
380
|
except ImportError:
|
|
389
381
|
errors.append(
|
|
390
382
|
Error(
|
|
@@ -1,60 +1,70 @@
|
|
|
1
1
|
from django.utils.translation import gettext_lazy as _
|
|
2
|
+
|
|
2
3
|
from oxutils.exceptions import (
|
|
3
|
-
APIException,
|
|
4
|
-
NotFoundException,
|
|
5
|
-
ValidationException,
|
|
6
4
|
DuplicateEntryException,
|
|
5
|
+
ExceptionCode,
|
|
6
|
+
NotFoundException,
|
|
7
7
|
PermissionDeniedException,
|
|
8
|
-
|
|
8
|
+
ValidationException,
|
|
9
9
|
)
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class RoleNotFoundException(NotFoundException):
|
|
13
13
|
"""Exception levée quand un rôle n'est pas trouvé."""
|
|
14
|
-
|
|
14
|
+
|
|
15
|
+
default_detail = _("The requested role does not exist")
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
class GroupNotFoundException(NotFoundException):
|
|
18
19
|
"""Exception levée quand un groupe n'est pas trouvé."""
|
|
19
|
-
|
|
20
|
+
|
|
21
|
+
default_detail = _("The requested group does not exist")
|
|
20
22
|
|
|
21
23
|
|
|
22
24
|
class GrantNotFoundException(NotFoundException):
|
|
23
25
|
"""Exception levée quand un grant n'est pas trouvé."""
|
|
24
|
-
|
|
26
|
+
|
|
27
|
+
default_detail = _("The requested grant does not exist")
|
|
25
28
|
|
|
26
29
|
|
|
27
30
|
class RoleGrantNotFoundException(NotFoundException):
|
|
28
31
|
"""Exception levée quand un role grant n'est pas trouvé."""
|
|
29
|
-
|
|
32
|
+
|
|
33
|
+
default_detail = _("The requested role grant does not exist")
|
|
30
34
|
|
|
31
35
|
|
|
32
36
|
class RoleAlreadyAssignedException(DuplicateEntryException):
|
|
33
37
|
"""Exception levée quand un rôle est déjà assigné à un utilisateur."""
|
|
34
|
-
|
|
38
|
+
|
|
39
|
+
default_detail = _("This role is already assigned to the user")
|
|
35
40
|
|
|
36
41
|
|
|
37
42
|
class GroupAlreadyAssignedException(DuplicateEntryException):
|
|
38
43
|
"""Exception levée quand un groupe est déjà assigné à un utilisateur."""
|
|
39
|
-
|
|
44
|
+
|
|
45
|
+
default_detail = _("This group is already assigned to the user")
|
|
40
46
|
|
|
41
47
|
|
|
42
48
|
class InvalidActionsException(ValidationException):
|
|
43
49
|
"""Exception levée quand des actions invalides sont fournies."""
|
|
44
|
-
|
|
50
|
+
|
|
51
|
+
default_detail = _("The provided actions are invalid")
|
|
45
52
|
|
|
46
53
|
|
|
47
54
|
class InsufficientPermissionsException(PermissionDeniedException):
|
|
48
55
|
"""Exception levée quand l'utilisateur n'a pas les permissions suffisantes."""
|
|
56
|
+
|
|
49
57
|
default_code = ExceptionCode.INSUFFICIENT_PERMISSIONS
|
|
50
|
-
default_detail = _(
|
|
58
|
+
default_detail = _("Insufficient permissions to perform this action")
|
|
51
59
|
|
|
52
60
|
|
|
53
61
|
class RoleGrantConflictException(DuplicateEntryException):
|
|
54
62
|
"""Exception levée quand un role grant existe déjà pour ce rôle et scope."""
|
|
55
|
-
|
|
63
|
+
|
|
64
|
+
default_detail = _("A role grant already exists for this role and scope")
|
|
56
65
|
|
|
57
66
|
|
|
58
67
|
class GrantConflictException(DuplicateEntryException):
|
|
59
68
|
"""Exception levée quand un grant existe déjà pour cet utilisateur et scope."""
|
|
60
|
-
|
|
69
|
+
|
|
70
|
+
default_detail = _("A grant already exists for this user and scope")
|