oxutils 0.4.0__tar.gz → 0.4.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.4.0 → oxutils-0.4.2}/PKG-INFO +1 -1
- {oxutils-0.4.0 → oxutils-0.4.2}/pyproject.toml +2 -1
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/__init__.py +1 -1
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/cacheops.py +1 -1
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/middleware.py +20 -3
- oxutils-0.4.2/src/oxutils/permissions/migrations/0009_grant_is_active.py +18 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/models.py +1 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/perms.py +40 -45
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/schemas.py +50 -28
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/utils.py +46 -17
- oxutils-0.4.0/src/oxutils/audit/locale/fr/LC_MESSAGES/django.mo +0 -0
- oxutils-0.4.0/src/oxutils/oxiliere/locale/fr/LC_MESSAGES/django.mo +0 -0
- oxutils-0.4.0/src/oxutils/permissions/locale/fr/LC_MESSAGES/django.mo +0 -0
- oxutils-0.4.0/src/oxutils/users/locale/fr/LC_MESSAGES/django.mo +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/README.md +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/apps.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/audit/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/audit/apps.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/audit/export.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/audit/locale/fr/LC_MESSAGES/django.po +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/audit/masks.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/audit/migrations/0001_initial.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/audit/migrations/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/audit/models.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/audit/settings.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/audit/utils.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/adapter.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/admin.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/app_settings.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/apps.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/constants.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/controllers.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/emails/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/emails/controllers.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/emails/schemas.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/emails/services.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/exceptions.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/invitations/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/invitations/backend.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/invitations/controllers.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/invitations/models.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/invitations/schemas.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/invitations/tokens.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/mfa/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/mfa/adapter.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/mfa/base/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/mfa/base/controllers.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/mfa/base/schemas.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/mfa/recovery_codes/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/mfa/recovery_codes/controllers.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/mfa/recovery_codes/flows.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/mfa/recovery_codes/schemas.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/mfa/recovery_codes/services.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/mfa/totp/__ini__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/mfa/totp/controllers.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/mfa/totp/flows.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/mfa/totp/permissions.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/mfa/totp/schemas.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/mfa/totp/services.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/mfa/utils.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/migrations/0001_initial.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/migrations/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/mixins.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/models.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/password_reset/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/password_reset/controllers.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/password_reset/models.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/password_reset/permissions.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/password_reset/schemas.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/registration/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/registration/controllers.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/registration/schemas.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/schemas.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/sessions/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/sessions/controllers.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/sessions/schemas.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/signals.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/templatetags/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/templatetags/spa_urls.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/tokens/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/tokens/app_settings.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/tokens/models.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/tokens/schemas.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/tokens/tokens.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/tokens/utils.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/auth/utils.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/celery/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/celery/base.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/celery/settings.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/conf.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/constants.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/context/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/context/site_name_processor.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/currency/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/currency/admin.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/currency/apps.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/currency/caches.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/currency/controllers.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/currency/enums.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/currency/management/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/currency/management/commands/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/currency/management/commands/sync_currency.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/currency/migrations/0001_initial.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/currency/migrations/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/currency/models.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/currency/schemas.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/currency/signals.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/currency/tests.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/currency/utils.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/enums/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/enums/audit.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/enums/invoices.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/exceptions.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/functions.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/jwt/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/jwt/auth.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/jwt/middleware.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/jwt/models.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/jwt/tokens.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/jwt/utils.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/logger/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/logger/receivers.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/logger/settings.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/mixins/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/mixins/base.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/mixins/schemas.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/mixins/services.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/models/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/models/base.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/models/billing.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/models/change_tracker.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/models/fields.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/models/invoice.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/admin.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/apps.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/authorization.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/caches.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/checks.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/constants.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/context.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/controllers.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/enums.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/exceptions.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/locale/fr/LC_MESSAGES/django.po +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/management/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/management/commands/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/management/commands/grant_tenant_owners.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/management/commands/init_oxiliere_system.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/migrations/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/models.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/permissions.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/schemas.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/services.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/settings.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/signals.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/tests.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/oxiliere/utils.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/pagination/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/pagination/cursor.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/pdf/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/pdf/printer.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/pdf/utils.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/pdf/views.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/actions.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/admin.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/apps.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/caches.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/checks.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/constants.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/controllers.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/exceptions.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/locale/fr/LC_MESSAGES/django.po +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/management/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/management/commands/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/management/commands/load_permission_preset.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/migrations/0001_initial.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/migrations/0002_alter_grant_role.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/migrations/0003_alter_grant_options_alter_group_options_and_more.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/migrations/0004_group_app_group_permissions_app_9a9924_idx.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/migrations/0005_role_app.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/migrations/0006_alter_rolegrant_options_and_more.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/migrations/0007_grant_locked_alter_grant_role_and_more.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/migrations/0008_remove_grant_unique_user_scope_role_and_more.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/migrations/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/queryset.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/services.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/permissions/tests.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/py.typed +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/s3.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/settings.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/templates/account/email/base_message.txt +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/templates/email/password/reset_email_message.html +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/templates/email/password/reset_email_message.txt +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/templates/email/password/reset_email_subject.txt +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/templates/email/signup/email_message.html +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/templates/email/signup/email_subject.txt +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/templates/verified.html +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/types.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/users/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/users/admin.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/users/apps.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/users/locale/fr/LC_MESSAGES/django.po +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/users/migrations/0001_initial.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/users/migrations/0002_alter_user_first_name_alter_user_last_name.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/users/migrations/0003_user_photo.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/users/migrations/0004_alter_user_options.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/users/migrations/__init__.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/users/models.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/users/tests.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/users/utils.py +0 -0
- {oxutils-0.4.0 → oxutils-0.4.2}/src/oxutils/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "oxutils"
|
|
3
|
-
version = "0.4.
|
|
3
|
+
version = "0.4.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"
|
|
@@ -98,6 +98,7 @@ dev = [
|
|
|
98
98
|
"coverage>=7.4.0",
|
|
99
99
|
"pillow>=12.0.0",
|
|
100
100
|
"ruff>=0.8.0",
|
|
101
|
+
"twine>=6.0.0",
|
|
101
102
|
"psycopg[binary]>=3.3.2",
|
|
102
103
|
]
|
|
103
104
|
|
|
@@ -34,7 +34,7 @@ def get_cached_tenant_token(oxi_id: str, user_id: str):
|
|
|
34
34
|
raise ObjectDoesNotExist(f"tenant not found: {oxi_id}") from ex
|
|
35
35
|
|
|
36
36
|
try:
|
|
37
|
-
tenant_user = tenant.users.select_related("user").get(user__pk=user_id)
|
|
37
|
+
tenant_user = tenant.users.select_related("user").get(user__pk=user_id, status="active")
|
|
38
38
|
except (ObjectDoesNotExist, ValueError) as ex:
|
|
39
39
|
raise ObjectDoesNotExist(f"tenant_user not found: {oxi_id}/{user_id}") from ex
|
|
40
40
|
|
|
@@ -55,7 +55,7 @@ class TenantMainMiddleware(MiddlewareMixin):
|
|
|
55
55
|
return None
|
|
56
56
|
|
|
57
57
|
try:
|
|
58
|
-
return tenant.users.select_related("user").get(user__pk=user.id)
|
|
58
|
+
return tenant.users.select_related("user").get(user__pk=user.id, status="active")
|
|
59
59
|
except ObjectDoesNotExist as exc:
|
|
60
60
|
logger.error("tenant_user_not_found", tenant_id=tenant.id, user_id=user.id, exc_info=exc)
|
|
61
61
|
if raise_exception:
|
|
@@ -99,8 +99,25 @@ class TenantMainMiddleware(MiddlewareMixin):
|
|
|
99
99
|
|
|
100
100
|
return HttpResponseBadRequest("Missing X-Organization-ID header")
|
|
101
101
|
else:
|
|
102
|
-
# oxi_id present but no authenticated user
|
|
103
|
-
|
|
102
|
+
# oxi_id present but no authenticated user → fall back to system tenant
|
|
103
|
+
# (same behaviour as "no org header") — previously this raised Http404,
|
|
104
|
+
# which broke every route (including public ones) when the JWT token
|
|
105
|
+
# expired but the front-end still sent X-Organization-ID.
|
|
106
|
+
try:
|
|
107
|
+
from oxutils.oxiliere.caches import get_system_tenant
|
|
108
|
+
|
|
109
|
+
tenant = get_system_tenant()
|
|
110
|
+
# don't try to attach a tenant-user — the user is anonymous anyway
|
|
111
|
+
tenant.user = None
|
|
112
|
+
except Exception as e:
|
|
113
|
+
logger.error(
|
|
114
|
+
"system_tenant_not_found",
|
|
115
|
+
oxi_id=oxi_id,
|
|
116
|
+
error=str(e),
|
|
117
|
+
)
|
|
118
|
+
from django.http import HttpResponseBadRequest
|
|
119
|
+
|
|
120
|
+
return HttpResponseBadRequest("Missing X-Organization-ID header")
|
|
104
121
|
|
|
105
122
|
# ── Status guards ─────────────────────────────────────────────
|
|
106
123
|
if tenant.is_deleted or not tenant.is_active:
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Generated by Django 5.2.9 on 2026-06-29 14:25
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('permissions', '0008_remove_grant_unique_user_scope_role_and_more'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AddField(
|
|
14
|
+
model_name='grant',
|
|
15
|
+
name='is_active',
|
|
16
|
+
field=models.BooleanField(default=True),
|
|
17
|
+
),
|
|
18
|
+
]
|
|
@@ -148,6 +148,7 @@ class Grant(TimestampMixin):
|
|
|
148
148
|
scope = models.CharField(max_length=100)
|
|
149
149
|
actions = ArrayField(models.CharField(max_length=5))
|
|
150
150
|
context = models.JSONField(default=dict, blank=True)
|
|
151
|
+
is_active = models.BooleanField(default=True)
|
|
151
152
|
|
|
152
153
|
class Meta:
|
|
153
154
|
constraints = [
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
from typing import Optional
|
|
2
|
+
|
|
2
3
|
from django.conf import settings
|
|
3
4
|
from django.core.exceptions import ImproperlyConfigured
|
|
4
5
|
from django.http import HttpRequest
|
|
5
|
-
from ninja_extra.permissions import BasePermission
|
|
6
6
|
from ninja_extra.controllers import ControllerBase
|
|
7
|
+
from ninja_extra.permissions import BasePermission
|
|
7
8
|
|
|
8
9
|
from oxutils.permissions.utils import str_check
|
|
9
10
|
|
|
10
11
|
|
|
11
|
-
|
|
12
12
|
class ScopePermission(BasePermission):
|
|
13
13
|
"""
|
|
14
14
|
Permission class for checking user permissions using the string format.
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
Format: "<scope>:<actions>" or "<scope>:<actions>:<role>?key=value"
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
Example:
|
|
19
19
|
@api_controller('/articles', permissions=[ScopePermission('articles:w')])
|
|
20
20
|
class ArticleController:
|
|
21
21
|
pass
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
@api_controller('/articles', permissions=[ScopePermission('articles:w:editor')])
|
|
24
24
|
class EditorArticleController:
|
|
25
25
|
pass
|
|
@@ -28,7 +28,7 @@ class ScopePermission(BasePermission):
|
|
|
28
28
|
def __init__(self, perm: str, ctx: Optional[dict] = None):
|
|
29
29
|
"""
|
|
30
30
|
Initialize the permission checker.
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
Args:
|
|
33
33
|
perm: Permission string in format "<scope>:<actions>" or "<scope>:<actions>:<role>?context"
|
|
34
34
|
"""
|
|
@@ -38,11 +38,11 @@ class ScopePermission(BasePermission):
|
|
|
38
38
|
def has_permission(self, request: HttpRequest, controller: ControllerBase) -> bool:
|
|
39
39
|
"""
|
|
40
40
|
Check if the user has the required permission.
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
Args:
|
|
43
43
|
request: HTTP request object
|
|
44
44
|
controller: Controller instance
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
Returns:
|
|
47
47
|
True if user has permission, False otherwise
|
|
48
48
|
"""
|
|
@@ -52,10 +52,10 @@ class ScopePermission(BasePermission):
|
|
|
52
52
|
class ScopeAnyPermission(BasePermission):
|
|
53
53
|
"""
|
|
54
54
|
Permission class for checking if user has at least one of multiple permissions.
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
Vérifie si l'utilisateur possède au moins une des permissions fournies.
|
|
57
57
|
Utilise any_permission_check pour une vérification optimisée en une seule requête.
|
|
58
|
-
|
|
58
|
+
|
|
59
59
|
Example:
|
|
60
60
|
@api_controller('/articles', permissions=[
|
|
61
61
|
ScopeAnyPermission('articles:r', 'articles:w:editor', 'articles:d:admin')
|
|
@@ -68,7 +68,7 @@ class ScopeAnyPermission(BasePermission):
|
|
|
68
68
|
def __init__(self, *perms: str):
|
|
69
69
|
"""
|
|
70
70
|
Initialize the permission checker with multiple permission strings.
|
|
71
|
-
|
|
71
|
+
|
|
72
72
|
Args:
|
|
73
73
|
*perms: Variable number of permission strings in format "<scope>:<actions>" or "<scope>:<actions>:<role>?context"
|
|
74
74
|
"""
|
|
@@ -79,25 +79,26 @@ class ScopeAnyPermission(BasePermission):
|
|
|
79
79
|
def has_permission(self, request: HttpRequest, controller: ControllerBase) -> bool:
|
|
80
80
|
"""
|
|
81
81
|
Check if the user has at least one of the required permissions.
|
|
82
|
-
|
|
82
|
+
|
|
83
83
|
Args:
|
|
84
84
|
request: HTTP request object
|
|
85
85
|
controller: Controller instance
|
|
86
|
-
|
|
86
|
+
|
|
87
87
|
Returns:
|
|
88
88
|
True if user has at least one permission, False otherwise
|
|
89
89
|
"""
|
|
90
90
|
from oxutils.permissions.caches import cache_any_permission_check
|
|
91
|
+
|
|
91
92
|
return cache_any_permission_check(request.user, *self.perms)
|
|
92
93
|
|
|
93
94
|
|
|
94
95
|
class ScopeAnyActionPermission(BasePermission):
|
|
95
96
|
"""
|
|
96
97
|
Permission class for checking if user has at least one of multiple actions on a scope.
|
|
97
|
-
|
|
98
|
+
|
|
98
99
|
Vérifie si l'utilisateur possède au moins une des actions requises pour un scope donné.
|
|
99
100
|
La chaîne d'actions contient plusieurs actions dont au moins une est requise.
|
|
100
|
-
|
|
101
|
+
|
|
101
102
|
Example:
|
|
102
103
|
@api_controller('/articles', permissions=[
|
|
103
104
|
ScopeAnyActionPermission('articles:rwd')
|
|
@@ -105,7 +106,7 @@ class ScopeAnyActionPermission(BasePermission):
|
|
|
105
106
|
class ArticleController:
|
|
106
107
|
# User needs read OR write OR delete access on articles
|
|
107
108
|
pass
|
|
108
|
-
|
|
109
|
+
|
|
109
110
|
@api_controller('/invoices', permissions=[
|
|
110
111
|
ScopeAnyActionPermission('invoices:rw:accountant')
|
|
111
112
|
])
|
|
@@ -117,7 +118,7 @@ class ScopeAnyActionPermission(BasePermission):
|
|
|
117
118
|
def __init__(self, perm: str, ctx: Optional[dict] = None):
|
|
118
119
|
"""
|
|
119
120
|
Initialize the permission checker with a permission string.
|
|
120
|
-
|
|
121
|
+
|
|
121
122
|
Args:
|
|
122
123
|
perm: Permission string in format "<scope>:<actions>" or "<scope>:<actions>:<role>?context"
|
|
123
124
|
where actions contains multiple characters (e.g., 'rwd' for read OR write OR delete)
|
|
@@ -125,82 +126,76 @@ class ScopeAnyActionPermission(BasePermission):
|
|
|
125
126
|
"""
|
|
126
127
|
if not perm:
|
|
127
128
|
raise ValueError("Permission string must be provided")
|
|
128
|
-
|
|
129
|
+
|
|
129
130
|
self.perm = perm
|
|
130
|
-
self.ctx = ctx if ctx else
|
|
131
|
+
self.ctx = ctx if ctx else {}
|
|
131
132
|
|
|
132
133
|
def has_permission(self, request: HttpRequest, controller: ControllerBase) -> bool:
|
|
133
134
|
"""
|
|
134
135
|
Check if the user has at least one of the required actions.
|
|
135
|
-
|
|
136
|
+
|
|
136
137
|
Args:
|
|
137
138
|
request: HTTP request object
|
|
138
139
|
controller: Controller instance
|
|
139
|
-
|
|
140
|
+
|
|
140
141
|
Returns:
|
|
141
142
|
True if user has at least one action, False otherwise
|
|
142
143
|
"""
|
|
143
144
|
from oxutils.permissions.caches import cache_any_action_check
|
|
144
145
|
from oxutils.permissions.utils import parse_permission
|
|
145
|
-
|
|
146
|
+
|
|
146
147
|
scope, actions, role, query_context = parse_permission(self.perm)
|
|
147
148
|
final_context = {**query_context, **self.ctx}
|
|
148
|
-
|
|
149
|
-
return cache_any_action_check(
|
|
150
|
-
request.user,
|
|
151
|
-
scope,
|
|
152
|
-
actions,
|
|
153
|
-
role=role,
|
|
154
|
-
**final_context
|
|
155
|
-
)
|
|
149
|
+
|
|
150
|
+
return cache_any_action_check(request.user, scope, actions, role=role, **final_context)
|
|
156
151
|
|
|
157
152
|
|
|
158
153
|
def access_manager(actions: str):
|
|
159
154
|
"""
|
|
160
155
|
Factory function for creating ScopePermission instances for access manager.
|
|
161
|
-
|
|
156
|
+
|
|
162
157
|
Builds a permission string from settings:
|
|
163
158
|
- ACCESS_MANAGER_SCOPE: The scope to check
|
|
164
159
|
- ACCESS_MANAGER_GROUP: Optional group for UserGroup assignment (used in authorization)
|
|
165
160
|
- ACCESS_MANAGER_ROLE: Optional role filter for permission checks
|
|
166
161
|
- ACCESS_MANAGER_CONTEXT: Optional context dict converted to query params
|
|
167
|
-
|
|
162
|
+
|
|
168
163
|
Args:
|
|
169
164
|
actions: Actions required (e.g., 'r', 'rw', 'rwd')
|
|
170
|
-
|
|
165
|
+
|
|
171
166
|
Returns:
|
|
172
167
|
ScopePermission instance configured with access manager settings
|
|
173
|
-
|
|
168
|
+
|
|
174
169
|
Raises:
|
|
175
170
|
ImproperlyConfigured: If required settings are missing
|
|
176
|
-
|
|
171
|
+
|
|
177
172
|
Example:
|
|
178
173
|
@api_controller('/access', permissions=[access_manager('w')])
|
|
179
174
|
class AccessController:
|
|
180
175
|
pass
|
|
181
176
|
"""
|
|
182
177
|
# Validate required settings
|
|
183
|
-
if not hasattr(settings,
|
|
178
|
+
if not hasattr(settings, "ACCESS_MANAGER_SCOPE"):
|
|
184
179
|
raise ImproperlyConfigured(
|
|
185
|
-
|
|
180
|
+
"ACCESS_MANAGER_SCOPE is not defined. "
|
|
186
181
|
'Add ACCESS_MANAGER_SCOPE = "access" to your settings.'
|
|
187
182
|
)
|
|
188
|
-
|
|
183
|
+
|
|
189
184
|
# Build base permission string: scope:actions
|
|
190
185
|
perm = f"{settings.ACCESS_MANAGER_SCOPE}:{actions}"
|
|
191
|
-
|
|
186
|
+
|
|
192
187
|
# Add role if defined and not None
|
|
193
|
-
if hasattr(settings,
|
|
188
|
+
if hasattr(settings, "ACCESS_MANAGER_ROLE") and settings.ACCESS_MANAGER_ROLE is not None:
|
|
194
189
|
perm += f":{settings.ACCESS_MANAGER_ROLE}"
|
|
195
|
-
|
|
190
|
+
|
|
196
191
|
# Get context if defined and not empty
|
|
197
192
|
context = {}
|
|
198
|
-
if hasattr(settings,
|
|
193
|
+
if hasattr(settings, "ACCESS_MANAGER_CONTEXT") and settings.ACCESS_MANAGER_CONTEXT:
|
|
199
194
|
context = settings.ACCESS_MANAGER_CONTEXT
|
|
200
195
|
if not isinstance(context, dict):
|
|
201
196
|
raise ImproperlyConfigured(
|
|
202
|
-
|
|
203
|
-
f
|
|
197
|
+
"ACCESS_MANAGER_CONTEXT must be a dictionary. "
|
|
198
|
+
f"Got {type(context).__name__} instead."
|
|
204
199
|
)
|
|
205
|
-
|
|
200
|
+
|
|
206
201
|
return ScopePermission(perm, context)
|
|
@@ -1,36 +1,35 @@
|
|
|
1
|
-
from typing import Any, Optional
|
|
2
1
|
from datetime import datetime
|
|
2
|
+
from typing import Any, Optional
|
|
3
3
|
from uuid import UUID
|
|
4
|
+
|
|
4
5
|
from django.conf import settings
|
|
5
6
|
from ninja import Schema
|
|
6
|
-
from oxutils.oxiliere.schemas import UserSchema
|
|
7
7
|
from pydantic import field_validator
|
|
8
8
|
|
|
9
|
+
from oxutils.oxiliere.schemas import UserSchema
|
|
10
|
+
|
|
9
11
|
from .actions import ACTIONS
|
|
10
12
|
|
|
11
13
|
|
|
12
14
|
def validate_actions_list(actions: list[str]) -> list[str]:
|
|
13
15
|
"""
|
|
14
16
|
Valide qu'une liste d'actions contient uniquement des actions valides.
|
|
15
|
-
|
|
17
|
+
|
|
16
18
|
Args:
|
|
17
19
|
actions: Liste des actions à valider
|
|
18
|
-
|
|
20
|
+
|
|
19
21
|
Returns:
|
|
20
22
|
La liste d'actions si valide
|
|
21
|
-
|
|
23
|
+
|
|
22
24
|
Raises:
|
|
23
25
|
ValueError: Si des actions invalides sont présentes
|
|
24
26
|
"""
|
|
25
27
|
if not actions:
|
|
26
28
|
raise ValueError("Les actions ne peuvent pas être vides")
|
|
27
|
-
|
|
29
|
+
|
|
28
30
|
invalid_actions = [a for a in actions if a not in ACTIONS]
|
|
29
31
|
if invalid_actions:
|
|
30
|
-
raise ValueError(
|
|
31
|
-
f"Actions invalides: {invalid_actions}. "
|
|
32
|
-
f"Actions valides: {ACTIONS}"
|
|
33
|
-
)
|
|
32
|
+
raise ValueError(f"Actions invalides: {invalid_actions}. Actions valides: {ACTIONS}")
|
|
34
33
|
return actions
|
|
35
34
|
|
|
36
35
|
|
|
@@ -38,6 +37,7 @@ class RoleSchema(Schema):
|
|
|
38
37
|
"""
|
|
39
38
|
Schéma pour un rôle.
|
|
40
39
|
"""
|
|
40
|
+
|
|
41
41
|
slug: str
|
|
42
42
|
name: str
|
|
43
43
|
created_at: datetime
|
|
@@ -51,6 +51,7 @@ class RoleSimpleSchema(Schema):
|
|
|
51
51
|
"""
|
|
52
52
|
Schéma pour un rôle.
|
|
53
53
|
"""
|
|
54
|
+
|
|
54
55
|
slug: str
|
|
55
56
|
name: str
|
|
56
57
|
|
|
@@ -62,6 +63,7 @@ class RoleCreateSchema(Schema):
|
|
|
62
63
|
"""
|
|
63
64
|
Schéma pour la création d'un rôle.
|
|
64
65
|
"""
|
|
66
|
+
|
|
65
67
|
slug: str
|
|
66
68
|
name: str
|
|
67
69
|
|
|
@@ -70,6 +72,7 @@ class RoleUpdateSchema(Schema):
|
|
|
70
72
|
"""
|
|
71
73
|
Schéma pour la mise à jour d'un rôle.
|
|
72
74
|
"""
|
|
75
|
+
|
|
73
76
|
name: Optional[str] = None
|
|
74
77
|
|
|
75
78
|
|
|
@@ -77,6 +80,7 @@ class GroupSchema(Schema):
|
|
|
77
80
|
"""
|
|
78
81
|
Schéma pour un groupe.
|
|
79
82
|
"""
|
|
83
|
+
|
|
80
84
|
slug: str
|
|
81
85
|
name: str
|
|
82
86
|
app: Optional[str] = None
|
|
@@ -99,6 +103,7 @@ class GroupCreateSchema(Schema):
|
|
|
99
103
|
"""
|
|
100
104
|
Schéma pour la création d'un groupe.
|
|
101
105
|
"""
|
|
106
|
+
|
|
102
107
|
name: str
|
|
103
108
|
app: Optional[str] = None
|
|
104
109
|
roles: list[str] = []
|
|
@@ -108,6 +113,7 @@ class GroupUpdateSchema(Schema):
|
|
|
108
113
|
"""
|
|
109
114
|
Schéma pour la mise à jour d'un groupe.
|
|
110
115
|
"""
|
|
116
|
+
|
|
111
117
|
name: Optional[str] = None
|
|
112
118
|
roles: Optional[list[str]] = None
|
|
113
119
|
|
|
@@ -116,6 +122,7 @@ class GroupMemberSchema(Schema):
|
|
|
116
122
|
"""
|
|
117
123
|
Schéma pour un membre d'un groupe.
|
|
118
124
|
"""
|
|
125
|
+
|
|
119
126
|
user: UserSchema
|
|
120
127
|
group_id: str
|
|
121
128
|
created_at: Optional[datetime] = None
|
|
@@ -125,6 +132,7 @@ class RoleGrantSchema(Schema):
|
|
|
125
132
|
"""
|
|
126
133
|
Schéma pour un role grant.
|
|
127
134
|
"""
|
|
135
|
+
|
|
128
136
|
id: int
|
|
129
137
|
role: RoleSimpleSchema
|
|
130
138
|
scope: str
|
|
@@ -139,12 +147,13 @@ class RoleGrantCreateSchema(Schema):
|
|
|
139
147
|
"""
|
|
140
148
|
Schéma pour la création d'un role grant.
|
|
141
149
|
"""
|
|
150
|
+
|
|
142
151
|
role: str
|
|
143
152
|
scope: str
|
|
144
153
|
actions: list[str]
|
|
145
154
|
context: dict[str, Any] = {}
|
|
146
|
-
|
|
147
|
-
@field_validator(
|
|
155
|
+
|
|
156
|
+
@field_validator("actions")
|
|
148
157
|
@classmethod
|
|
149
158
|
def validate_actions(cls, v: list[str]) -> list[str]:
|
|
150
159
|
"""Valide que toutes les actions sont valides."""
|
|
@@ -155,10 +164,11 @@ class RoleGrantUpdateSchema(Schema):
|
|
|
155
164
|
"""
|
|
156
165
|
Schéma pour la mise à jour d'un role grant.
|
|
157
166
|
"""
|
|
167
|
+
|
|
158
168
|
actions: Optional[list[str]] = None
|
|
159
169
|
context: Optional[dict[str, Any]] = None
|
|
160
|
-
|
|
161
|
-
@field_validator(
|
|
170
|
+
|
|
171
|
+
@field_validator("actions")
|
|
162
172
|
@classmethod
|
|
163
173
|
def validate_actions(cls, v: Optional[list[str]]) -> Optional[list[str]]:
|
|
164
174
|
"""Valide que toutes les actions sont valides."""
|
|
@@ -171,6 +181,7 @@ class GrantSchema(Schema):
|
|
|
171
181
|
"""
|
|
172
182
|
Schéma pour un grant utilisateur.
|
|
173
183
|
"""
|
|
184
|
+
|
|
174
185
|
id: int
|
|
175
186
|
user_id: UUID
|
|
176
187
|
role: RoleSimpleSchema
|
|
@@ -194,13 +205,14 @@ class GrantCreateSchema(Schema):
|
|
|
194
205
|
"""
|
|
195
206
|
Schéma pour la création d'un grant utilisateur.
|
|
196
207
|
"""
|
|
208
|
+
|
|
197
209
|
user_id: UUID
|
|
198
210
|
scope: str
|
|
199
211
|
actions: list[str]
|
|
200
212
|
context: dict[str, Any] = {}
|
|
201
213
|
role: str
|
|
202
|
-
|
|
203
|
-
@field_validator(
|
|
214
|
+
|
|
215
|
+
@field_validator("actions")
|
|
204
216
|
@classmethod
|
|
205
217
|
def validate_actions(cls, v: list[str]) -> list[str]:
|
|
206
218
|
"""Valide que toutes les actions sont valides."""
|
|
@@ -211,11 +223,12 @@ class GrantUpdateSchema(Schema):
|
|
|
211
223
|
"""
|
|
212
224
|
Schéma pour la mise à jour d'un grant utilisateur.
|
|
213
225
|
"""
|
|
226
|
+
|
|
214
227
|
actions: Optional[list[str]] = None
|
|
215
228
|
context: Optional[dict[str, Any]] = None
|
|
216
229
|
role: Optional[str] = None
|
|
217
|
-
|
|
218
|
-
@field_validator(
|
|
230
|
+
|
|
231
|
+
@field_validator("actions")
|
|
219
232
|
@classmethod
|
|
220
233
|
def validate_actions(cls, v: Optional[list[str]]) -> Optional[list[str]]:
|
|
221
234
|
"""Valide que toutes les actions sont valides."""
|
|
@@ -228,12 +241,13 @@ class PermissionCheckSchema(Schema):
|
|
|
228
241
|
"""
|
|
229
242
|
Schéma pour une requête de vérification de permissions.
|
|
230
243
|
"""
|
|
244
|
+
|
|
231
245
|
user_id: UUID
|
|
232
246
|
scope: str
|
|
233
247
|
required_actions: list[str]
|
|
234
248
|
context: dict[str, Any] = {}
|
|
235
|
-
|
|
236
|
-
@field_validator(
|
|
249
|
+
|
|
250
|
+
@field_validator("required_actions")
|
|
237
251
|
@classmethod
|
|
238
252
|
def validate_actions(cls, v: list[str]) -> list[str]:
|
|
239
253
|
"""Valide que toutes les actions sont valides."""
|
|
@@ -244,6 +258,7 @@ class PermissionCheckResponseSchema(Schema):
|
|
|
244
258
|
"""
|
|
245
259
|
Schéma pour la réponse d'une vérification de permissions.
|
|
246
260
|
"""
|
|
261
|
+
|
|
247
262
|
allowed: bool
|
|
248
263
|
user_id: UUID
|
|
249
264
|
scope: str
|
|
@@ -254,16 +269,17 @@ class AssignRoleSchema(Schema):
|
|
|
254
269
|
"""
|
|
255
270
|
Schéma pour assigner un rôle à un utilisateur.
|
|
256
271
|
"""
|
|
272
|
+
|
|
257
273
|
user_id: UUID
|
|
258
274
|
role: str
|
|
259
275
|
scope: str
|
|
260
276
|
|
|
261
|
-
@field_validator(
|
|
277
|
+
@field_validator("scope")
|
|
262
278
|
@classmethod
|
|
263
279
|
def validate_scope(cls, v: str) -> str:
|
|
264
280
|
"""Valide que le scope est valide."""
|
|
265
|
-
scopes = getattr(settings,
|
|
266
|
-
|
|
281
|
+
scopes = getattr(settings, "ACCESS_SCOPES", [])
|
|
282
|
+
|
|
267
283
|
if v not in scopes:
|
|
268
284
|
raise ValueError(f"Invalid scope '{v}'")
|
|
269
285
|
return v
|
|
@@ -273,22 +289,23 @@ class OverrideGrantSchema(Schema):
|
|
|
273
289
|
"""
|
|
274
290
|
Schéma pour modifier un grant utilisateur.
|
|
275
291
|
"""
|
|
292
|
+
|
|
276
293
|
user_id: UUID
|
|
277
294
|
scope: str
|
|
278
295
|
role: str
|
|
279
296
|
actions: list[str]
|
|
280
297
|
|
|
281
|
-
@field_validator(
|
|
298
|
+
@field_validator("scope")
|
|
282
299
|
@classmethod
|
|
283
300
|
def validate_scope(cls, v: str) -> str:
|
|
284
301
|
"""Valide que le scope est valide."""
|
|
285
|
-
scopes = getattr(settings,
|
|
302
|
+
scopes = getattr(settings, "ACCESS_SCOPES", [])
|
|
286
303
|
|
|
287
304
|
if v not in scopes:
|
|
288
305
|
raise ValueError(f"Invalid scope '{v}'")
|
|
289
306
|
return v
|
|
290
307
|
|
|
291
|
-
@field_validator(
|
|
308
|
+
@field_validator("actions")
|
|
292
309
|
@classmethod
|
|
293
310
|
def validate_actions(cls, v: list[str]) -> list[str]:
|
|
294
311
|
"""Valide que toutes les actions sont valides."""
|
|
@@ -299,15 +316,16 @@ class RevokeRoleSchema(Schema):
|
|
|
299
316
|
"""
|
|
300
317
|
Schéma pour révoquer un rôle d'un utilisateur.
|
|
301
318
|
"""
|
|
319
|
+
|
|
302
320
|
user_id: UUID
|
|
303
321
|
scope: str
|
|
304
322
|
role: str
|
|
305
323
|
|
|
306
|
-
@field_validator(
|
|
324
|
+
@field_validator("scope")
|
|
307
325
|
@classmethod
|
|
308
326
|
def validate_scope(cls, v: str) -> str:
|
|
309
327
|
"""Valide que le scope est valide."""
|
|
310
|
-
scopes = getattr(settings,
|
|
328
|
+
scopes = getattr(settings, "ACCESS_SCOPES", [])
|
|
311
329
|
|
|
312
330
|
if v not in scopes:
|
|
313
331
|
raise ValueError(f"Invalid scope '{v}'")
|
|
@@ -318,6 +336,7 @@ class AssignGroupSchema(Schema):
|
|
|
318
336
|
"""
|
|
319
337
|
Schéma pour assigner un groupe à un utilisateur.
|
|
320
338
|
"""
|
|
339
|
+
|
|
321
340
|
user_id: UUID
|
|
322
341
|
group: str
|
|
323
342
|
|
|
@@ -326,6 +345,7 @@ class RevokeGroupSchema(Schema):
|
|
|
326
345
|
"""
|
|
327
346
|
Schéma pour révoquer un groupe d'un utilisateur.
|
|
328
347
|
"""
|
|
348
|
+
|
|
329
349
|
user_id: UUID
|
|
330
350
|
group: str
|
|
331
351
|
|
|
@@ -334,6 +354,7 @@ class GroupSyncResponseSchema(Schema):
|
|
|
334
354
|
"""
|
|
335
355
|
Schéma pour la réponse de la synchronisation d'un groupe.
|
|
336
356
|
"""
|
|
357
|
+
|
|
337
358
|
users_synced: int
|
|
338
359
|
grants_updated: int
|
|
339
360
|
|
|
@@ -342,6 +363,7 @@ class PresetLoadResponseSchema(Schema):
|
|
|
342
363
|
"""
|
|
343
364
|
Schéma pour la réponse du chargement d'un preset.
|
|
344
365
|
"""
|
|
366
|
+
|
|
345
367
|
roles_created: int
|
|
346
368
|
groups_created: int
|
|
347
369
|
role_grants_created: int
|