django-cfg 1.4.20__py3-none-any.whl → 1.4.23__py3-none-any.whl
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.
- django_cfg/__init__.py +4 -4
- django_cfg/apps/accounts/__init__.py +1 -1
- django_cfg/apps/accounts/__models.py +30 -29
- django_cfg/apps/accounts/admin/__init__.py +14 -3
- django_cfg/apps/accounts/admin/activity_admin.py +19 -19
- django_cfg/apps/accounts/admin/filters.py +7 -6
- django_cfg/apps/accounts/admin/group_admin.py +10 -16
- django_cfg/apps/accounts/admin/inlines.py +21 -19
- django_cfg/apps/accounts/admin/otp_admin.py +12 -12
- django_cfg/apps/accounts/admin/registration_admin.py +24 -24
- django_cfg/apps/accounts/admin/resources.py +49 -48
- django_cfg/apps/accounts/admin/twilio_admin.py +37 -37
- django_cfg/apps/accounts/admin/user_admin.py +45 -41
- django_cfg/apps/accounts/management/commands/otp_test.py +11 -11
- django_cfg/apps/accounts/managers/__init__.py +1 -1
- django_cfg/apps/accounts/managers/user_manager.py +6 -7
- django_cfg/apps/accounts/migrations/0001_initial.py +3 -2
- django_cfg/apps/accounts/models/__init__.py +15 -16
- django_cfg/apps/accounts/models/activity.py +5 -5
- django_cfg/apps/accounts/models/integrations.py +15 -15
- django_cfg/apps/accounts/models/registration.py +3 -2
- django_cfg/apps/accounts/models/user.py +3 -2
- django_cfg/apps/accounts/serializers/__init__.py +10 -3
- django_cfg/apps/accounts/serializers/otp.py +5 -4
- django_cfg/apps/accounts/serializers/profile.py +4 -5
- django_cfg/apps/accounts/serializers/webhook.py +13 -13
- django_cfg/apps/accounts/services/activity_service.py +13 -12
- django_cfg/apps/accounts/services/otp_service.py +16 -14
- django_cfg/apps/accounts/signals.py +18 -16
- django_cfg/apps/accounts/urls.py +10 -5
- django_cfg/apps/accounts/utils/notifications.py +22 -22
- django_cfg/apps/accounts/views/__init__.py +1 -1
- django_cfg/apps/accounts/views/otp.py +15 -14
- django_cfg/apps/accounts/views/profile.py +14 -10
- django_cfg/apps/accounts/views/webhook.py +46 -48
- django_cfg/apps/agents/__init__.py +3 -3
- django_cfg/apps/agents/admin/__init__.py +1 -1
- django_cfg/apps/agents/admin/execution_admin.py +68 -72
- django_cfg/apps/agents/admin/registry_admin.py +50 -54
- django_cfg/apps/agents/admin/toolsets_admin.py +63 -67
- django_cfg/apps/agents/apps.py +3 -3
- django_cfg/apps/agents/core/__init__.py +4 -4
- django_cfg/apps/agents/core/dependencies.py +24 -23
- django_cfg/apps/agents/core/django_agent.py +41 -39
- django_cfg/apps/agents/core/exceptions.py +12 -12
- django_cfg/apps/agents/core/models.py +16 -15
- django_cfg/apps/agents/core/orchestrator.py +58 -58
- django_cfg/apps/agents/examples/simple_example.py +24 -19
- django_cfg/apps/agents/integration/__init__.py +1 -1
- django_cfg/apps/agents/integration/middleware.py +12 -11
- django_cfg/apps/agents/integration/registry.py +52 -49
- django_cfg/apps/agents/integration/signals.py +5 -5
- django_cfg/apps/agents/management/commands/create_agent.py +39 -38
- django_cfg/apps/agents/management/commands/orchestrator_status.py +40 -39
- django_cfg/apps/agents/managers/__init__.py +8 -3
- django_cfg/apps/agents/managers/execution.py +42 -41
- django_cfg/apps/agents/managers/registry.py +40 -39
- django_cfg/apps/agents/managers/toolsets.py +87 -86
- django_cfg/apps/agents/migrations/0001_initial.py +2 -1
- django_cfg/apps/agents/models/__init__.py +2 -2
- django_cfg/apps/agents/models/execution.py +43 -42
- django_cfg/apps/agents/models/registry.py +46 -45
- django_cfg/apps/agents/models/toolsets.py +63 -62
- django_cfg/apps/agents/patterns/__init__.py +5 -5
- django_cfg/apps/agents/patterns/content_agents.py +17 -16
- django_cfg/apps/agents/toolsets/__init__.py +3 -3
- django_cfg/apps/agents/toolsets/cache_toolset.py +56 -55
- django_cfg/apps/agents/toolsets/django_toolset.py +43 -42
- django_cfg/apps/agents/toolsets/file_toolset.py +64 -63
- django_cfg/apps/agents/toolsets/orm_toolset.py +75 -74
- django_cfg/apps/agents/urls.py +3 -2
- django_cfg/apps/api/commands/urls.py +1 -0
- django_cfg/apps/api/commands/views.py +23 -26
- django_cfg/apps/api/endpoints/checker.py +5 -4
- django_cfg/apps/api/endpoints/drf_views.py +2 -2
- django_cfg/apps/api/endpoints/tests.py +6 -5
- django_cfg/apps/api/endpoints/urls.py +2 -1
- django_cfg/apps/api/endpoints/views.py +1 -0
- django_cfg/apps/api/health/drf_views.py +6 -6
- django_cfg/apps/api/health/urls.py +2 -1
- django_cfg/apps/api/health/views.py +41 -41
- django_cfg/{modules/django_ipc_client → apps/ipc}/__init__.py +6 -6
- django_cfg/apps/ipc/apps.py +28 -0
- django_cfg/apps/ipc/serializers/__init__.py +19 -0
- django_cfg/apps/ipc/serializers/serializers.py +229 -0
- django_cfg/apps/ipc/services/__init__.py +7 -0
- django_cfg/apps/ipc/services/client/__init__.py +23 -0
- django_cfg/{modules/django_ipc_client → apps/ipc/services/client}/client.py +7 -6
- django_cfg/{modules/django_ipc_client → apps/ipc/services/client}/exceptions.py +1 -1
- django_cfg/{modules/django_ipc_client/dashboard → apps/ipc/services}/monitor.py +23 -5
- django_cfg/{modules/django_ipc_client/dashboard/static/django_ipc_dashboard/js/dashboard.js → apps/ipc/static/django_cfg_ipc/js/dashboard.mjs} +131 -63
- django_cfg/{modules/django_ipc_client/dashboard/templates/django_ipc_dashboard → apps/ipc/templates/django_cfg_ipc}/base.html +5 -10
- django_cfg/apps/ipc/templates/django_cfg_ipc/dashboard.html +202 -0
- django_cfg/apps/ipc/urls.py +21 -0
- django_cfg/apps/ipc/urls_admin.py +20 -0
- django_cfg/apps/ipc/views/__init__.py +8 -0
- django_cfg/apps/ipc/views/dashboard.py +15 -0
- django_cfg/apps/ipc/views/viewsets.py +245 -0
- django_cfg/apps/knowbase/admin/__init__.py +2 -2
- django_cfg/apps/knowbase/admin/actions/__init__.py +1 -1
- django_cfg/apps/knowbase/admin/actions/visibility_actions.py +2 -1
- django_cfg/apps/knowbase/admin/archive_admin.py +81 -84
- django_cfg/apps/knowbase/admin/chat_admin.py +70 -72
- django_cfg/apps/knowbase/admin/document_admin.py +10 -11
- django_cfg/apps/knowbase/admin/external_data_admin.py +69 -71
- django_cfg/apps/knowbase/admin/helpers/__init__.py +1 -1
- django_cfg/apps/knowbase/admin/helpers/configs.py +2 -2
- django_cfg/apps/knowbase/admin/helpers/statistics.py +1 -1
- django_cfg/apps/knowbase/apps.py +13 -13
- django_cfg/apps/knowbase/config/__init__.py +7 -6
- django_cfg/apps/knowbase/config/constance_fields.py +14 -12
- django_cfg/apps/knowbase/config/constance_settings.py +32 -31
- django_cfg/apps/knowbase/config/settings.py +28 -28
- django_cfg/apps/knowbase/examples/external_data_usage.py +35 -32
- django_cfg/apps/knowbase/management/commands/knowbase_stats.py +33 -32
- django_cfg/apps/knowbase/management/commands/setup_knowbase.py +11 -13
- django_cfg/apps/knowbase/managers/__init__.py +2 -2
- django_cfg/apps/knowbase/managers/archive.py +86 -85
- django_cfg/apps/knowbase/managers/base.py +5 -5
- django_cfg/apps/knowbase/managers/chat.py +29 -28
- django_cfg/apps/knowbase/managers/document.py +39 -39
- django_cfg/apps/knowbase/managers/external_data.py +74 -73
- django_cfg/apps/knowbase/migrations/0001_initial.py +2 -1
- django_cfg/apps/knowbase/migrations/0002_archiveitem_archiveitemchunk_documentarchive_and_more.py +2 -1
- django_cfg/apps/knowbase/migrations/0003_alter_documentarchive_archive_type.py +29 -0
- django_cfg/apps/knowbase/mixins/__init__.py +4 -4
- django_cfg/apps/knowbase/mixins/config/__init__.py +1 -1
- django_cfg/apps/knowbase/mixins/config/meta_config.py +1 -1
- django_cfg/apps/knowbase/mixins/config.py +19 -18
- django_cfg/apps/knowbase/mixins/creator.py +7 -7
- django_cfg/apps/knowbase/mixins/examples/vehicle_model_example.py +29 -28
- django_cfg/apps/knowbase/mixins/external_data_mixin.py +6 -5
- django_cfg/apps/knowbase/mixins/generators/__init__.py +1 -1
- django_cfg/apps/knowbase/mixins/generators/content_generator.py +2 -2
- django_cfg/apps/knowbase/mixins/service.py +47 -45
- django_cfg/apps/knowbase/models/__init__.py +7 -7
- django_cfg/apps/knowbase/models/archive.py +72 -72
- django_cfg/apps/knowbase/models/base.py +12 -13
- django_cfg/apps/knowbase/models/chat.py +20 -19
- django_cfg/apps/knowbase/models/document.py +37 -35
- django_cfg/apps/knowbase/models/external_data.py +41 -42
- django_cfg/apps/knowbase/serializers/__init__.py +7 -7
- django_cfg/apps/knowbase/serializers/archive_serializers.py +50 -42
- django_cfg/apps/knowbase/serializers/chat_serializers.py +16 -15
- django_cfg/apps/knowbase/serializers/document_serializers.py +13 -12
- django_cfg/apps/knowbase/serializers/external_data_serializers.py +31 -31
- django_cfg/apps/knowbase/serializers/public_serializers.py +10 -9
- django_cfg/apps/knowbase/services/__init__.py +7 -7
- django_cfg/apps/knowbase/services/archive/__init__.py +7 -7
- django_cfg/apps/knowbase/services/archive/analyzers/__init__.py +1 -1
- django_cfg/apps/knowbase/services/archive/analyzers/tag_generator.py +1 -1
- django_cfg/apps/knowbase/services/archive/archive_service.py +109 -112
- django_cfg/apps/knowbase/services/archive/chunking/__init__.py +3 -3
- django_cfg/apps/knowbase/services/archive/chunking/base.py +1 -0
- django_cfg/apps/knowbase/services/archive/chunking/json_chunker.py +4 -3
- django_cfg/apps/knowbase/services/archive/chunking/markdown_chunker.py +5 -4
- django_cfg/apps/knowbase/services/archive/chunking/python_chunker.py +6 -5
- django_cfg/apps/knowbase/services/archive/chunking/text_chunker.py +4 -3
- django_cfg/apps/knowbase/services/archive/chunking_service.py +3 -7
- django_cfg/apps/knowbase/services/archive/context/__init__.py +1 -1
- django_cfg/apps/knowbase/services/archive/context/builders.py +2 -1
- django_cfg/apps/knowbase/services/archive/context/models.py +2 -1
- django_cfg/apps/knowbase/services/archive/exceptions.py +5 -5
- django_cfg/apps/knowbase/services/archive/extraction_service.py +111 -110
- django_cfg/apps/knowbase/services/archive/vectorization_service.py +80 -77
- django_cfg/apps/knowbase/services/base.py +11 -9
- django_cfg/apps/knowbase/services/chat_service.py +40 -39
- django_cfg/apps/knowbase/services/document_service.py +28 -27
- django_cfg/apps/knowbase/services/embedding/__init__.py +9 -9
- django_cfg/apps/knowbase/services/embedding/async_processor.py +38 -40
- django_cfg/apps/knowbase/services/embedding/batch_processor.py +45 -42
- django_cfg/apps/knowbase/services/embedding/batch_result.py +7 -6
- django_cfg/apps/knowbase/services/embedding/models.py +52 -51
- django_cfg/apps/knowbase/services/embedding/processors.py +24 -23
- django_cfg/apps/knowbase/services/embedding/utils.py +17 -17
- django_cfg/apps/knowbase/services/prompt_builder.py +24 -23
- django_cfg/apps/knowbase/services/search_service.py +52 -49
- django_cfg/apps/knowbase/signals/__init__.py +2 -5
- django_cfg/apps/knowbase/signals/archive_signals.py +35 -34
- django_cfg/apps/knowbase/signals/chat_signals.py +6 -5
- django_cfg/apps/knowbase/signals/document_signals.py +22 -22
- django_cfg/apps/knowbase/signals/external_data_signals.py +22 -22
- django_cfg/apps/knowbase/tasks/__init__.py +6 -7
- django_cfg/apps/knowbase/tasks/archive_tasks.py +41 -41
- django_cfg/apps/knowbase/tasks/document_processing.py +49 -44
- django_cfg/apps/knowbase/tasks/external_data_tasks.py +46 -44
- django_cfg/apps/knowbase/tasks/maintenance.py +26 -24
- django_cfg/apps/knowbase/urls.py +3 -2
- django_cfg/apps/knowbase/urls_admin.py +6 -3
- django_cfg/apps/knowbase/urls_system.py +4 -5
- django_cfg/apps/knowbase/utils/chunk_settings.py +22 -20
- django_cfg/apps/knowbase/utils/text_processing.py +76 -75
- django_cfg/apps/knowbase/utils/validation.py +9 -9
- django_cfg/apps/knowbase/views/__init__.py +5 -5
- django_cfg/apps/knowbase/views/archive_views.py +90 -87
- django_cfg/apps/knowbase/views/base.py +9 -12
- django_cfg/apps/knowbase/views/chat_views.py +35 -32
- django_cfg/apps/knowbase/views/document_views.py +27 -28
- django_cfg/apps/knowbase/views/public_views.py +19 -19
- django_cfg/apps/leads/admin/leads_admin.py +41 -45
- django_cfg/apps/leads/admin/resources.py +14 -14
- django_cfg/apps/leads/admin.py +7 -9
- django_cfg/apps/leads/apps.py +1 -1
- django_cfg/apps/leads/models.py +17 -17
- django_cfg/apps/leads/serializers.py +5 -4
- django_cfg/apps/leads/signals.py +7 -7
- django_cfg/apps/leads/tests.py +47 -47
- django_cfg/apps/leads/urls.py +2 -2
- django_cfg/apps/leads/views.py +11 -11
- django_cfg/apps/maintenance/__init__.py +3 -3
- django_cfg/apps/maintenance/admin/__init__.py +1 -1
- django_cfg/apps/maintenance/admin/api_key_admin.py +36 -36
- django_cfg/apps/maintenance/admin/log_admin.py +35 -37
- django_cfg/apps/maintenance/admin/scheduled_admin.py +47 -51
- django_cfg/apps/maintenance/admin/site_admin.py +49 -52
- django_cfg/apps/maintenance/apps.py +2 -2
- django_cfg/apps/maintenance/management/commands/maintenance.py +53 -52
- django_cfg/apps/maintenance/management/commands/process_scheduled_maintenance.py +44 -44
- django_cfg/apps/maintenance/management/commands/sync_cloudflare.py +32 -32
- django_cfg/apps/maintenance/managers/__init__.py +1 -1
- django_cfg/apps/maintenance/managers/cloudflare_site_manager.py +39 -38
- django_cfg/apps/maintenance/managers/maintenance_log_manager.py +32 -31
- django_cfg/apps/maintenance/migrations/0001_initial.py +1 -0
- django_cfg/apps/maintenance/models/__init__.py +2 -2
- django_cfg/apps/maintenance/models/cloudflare_api_key.py +15 -15
- django_cfg/apps/maintenance/models/cloudflare_site.py +24 -22
- django_cfg/apps/maintenance/models/maintenance_log.py +15 -14
- django_cfg/apps/maintenance/models/scheduled_maintenance.py +53 -52
- django_cfg/apps/maintenance/services/__init__.py +3 -3
- django_cfg/apps/maintenance/services/bulk_operations_service.py +68 -68
- django_cfg/apps/maintenance/services/maintenance_service.py +59 -58
- django_cfg/apps/maintenance/services/scheduled_maintenance_service.py +52 -52
- django_cfg/apps/maintenance/services/site_sync_service.py +64 -65
- django_cfg/apps/maintenance/utils/__init__.py +1 -1
- django_cfg/apps/maintenance/utils/retry_utils.py +17 -17
- django_cfg/apps/newsletter/admin/__init__.py +12 -16
- django_cfg/apps/newsletter/admin/newsletter_admin.py +90 -87
- django_cfg/apps/newsletter/admin/resources.py +29 -29
- django_cfg/apps/newsletter/admin.py +39 -32
- django_cfg/apps/newsletter/management/commands/test_newsletter.py +3 -3
- django_cfg/apps/newsletter/managers/__init__.py +1 -1
- django_cfg/apps/newsletter/migrations/0001_initial.py +2 -1
- django_cfg/apps/newsletter/models.py +34 -33
- django_cfg/apps/newsletter/serializers.py +13 -13
- django_cfg/apps/newsletter/services/email_service.py +42 -40
- django_cfg/apps/newsletter/signals.py +4 -3
- django_cfg/apps/newsletter/urls.py +7 -7
- django_cfg/apps/newsletter/views/__init__.py +14 -19
- django_cfg/apps/newsletter/views/campaigns.py +19 -19
- django_cfg/apps/newsletter/views/emails.py +20 -20
- django_cfg/apps/newsletter/views/newsletters.py +5 -5
- django_cfg/apps/newsletter/views/subscriptions.py +24 -24
- django_cfg/apps/newsletter/views/tracking.py +6 -5
- django_cfg/apps/payments/admin/__init__.py +6 -5
- django_cfg/apps/payments/admin/api_keys_admin.py +43 -45
- django_cfg/apps/payments/admin/balance_admin.py +41 -47
- django_cfg/apps/payments/admin/currencies_admin.py +60 -62
- django_cfg/apps/payments/admin/endpoint_groups_admin.py +14 -28
- django_cfg/apps/payments/admin/filters.py +59 -59
- django_cfg/apps/payments/admin/networks_admin.py +36 -50
- django_cfg/apps/payments/admin/payments_admin.py +47 -49
- django_cfg/apps/payments/admin/subscriptions_admin.py +30 -32
- django_cfg/apps/payments/admin/tariffs_admin.py +37 -42
- django_cfg/apps/payments/admin_interface/serializers/__init__.py +12 -13
- django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +28 -27
- django_cfg/apps/payments/admin_interface/serializers/webhook_serializers.py +4 -5
- django_cfg/apps/payments/admin_interface/templates/payments/base.html +407 -3
- django_cfg/apps/payments/admin_interface/templates/payments/components/ngrok_status.html +13 -13
- django_cfg/apps/payments/admin_interface/templates/payments/payment_dashboard.html +5 -1
- django_cfg/apps/payments/admin_interface/templates/payments/payment_detail.html +105 -49
- django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +4 -1
- django_cfg/apps/payments/admin_interface/templates/payments/payment_list.html +16 -8
- django_cfg/apps/payments/admin_interface/templates/payments/webhook_dashboard.html +16 -8
- django_cfg/apps/payments/admin_interface/views/__init__.py +8 -9
- django_cfg/apps/payments/admin_interface/views/api/__init__.py +3 -3
- django_cfg/apps/payments/admin_interface/views/api/payments.py +52 -54
- django_cfg/apps/payments/admin_interface/views/api/stats.py +33 -30
- django_cfg/apps/payments/admin_interface/views/api/users.py +10 -11
- django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +46 -51
- django_cfg/apps/payments/admin_interface/views/api/webhook_public.py +9 -9
- django_cfg/apps/payments/admin_interface/views/base.py +17 -19
- django_cfg/apps/payments/admin_interface/views/dashboard.py +10 -10
- django_cfg/apps/payments/admin_interface/views/forms.py +21 -20
- django_cfg/apps/payments/apps.py +7 -6
- django_cfg/apps/payments/config/__init__.py +4 -4
- django_cfg/apps/payments/config/django_cfg_integration.py +22 -21
- django_cfg/apps/payments/config/helpers.py +14 -12
- django_cfg/apps/payments/management/commands/cleanup_expired_data.py +85 -86
- django_cfg/apps/payments/management/commands/currency_stats.py +84 -87
- django_cfg/apps/payments/management/commands/manage_currencies.py +59 -58
- django_cfg/apps/payments/management/commands/manage_providers.py +103 -105
- django_cfg/apps/payments/management/commands/process_pending_payments.py +67 -70
- django_cfg/apps/payments/management/commands/test_providers.py +83 -84
- django_cfg/apps/payments/middleware/__init__.py +1 -1
- django_cfg/apps/payments/middleware/api_access.py +77 -78
- django_cfg/apps/payments/middleware/rate_limiting.py +72 -72
- django_cfg/apps/payments/middleware/usage_tracking.py +66 -64
- django_cfg/apps/payments/migrations/0001_initial.py +2 -1
- django_cfg/apps/payments/models/__init__.py +11 -12
- django_cfg/apps/payments/models/api_keys.py +29 -27
- django_cfg/apps/payments/models/balance.py +38 -38
- django_cfg/apps/payments/models/base.py +12 -11
- django_cfg/apps/payments/models/currencies.py +53 -52
- django_cfg/apps/payments/models/managers/__init__.py +13 -14
- django_cfg/apps/payments/models/managers/api_key_managers.py +55 -53
- django_cfg/apps/payments/models/managers/balance_managers.py +98 -97
- django_cfg/apps/payments/models/managers/currency_managers.py +70 -69
- django_cfg/apps/payments/models/managers/payment_managers.py +113 -111
- django_cfg/apps/payments/models/managers/subscription_managers.py +99 -97
- django_cfg/apps/payments/models/payments.py +167 -73
- django_cfg/apps/payments/models/subscriptions.py +56 -54
- django_cfg/apps/payments/models/tariffs.py +35 -34
- django_cfg/apps/payments/services/__init__.py +33 -36
- django_cfg/apps/payments/services/cache/__init__.py +7 -1
- django_cfg/apps/payments/services/cache_service/__init__.py +22 -20
- django_cfg/apps/payments/services/cache_service/api_key_cache.py +6 -5
- django_cfg/apps/payments/services/cache_service/interfaces.py +5 -5
- django_cfg/apps/payments/services/cache_service/keys.py +8 -8
- django_cfg/apps/payments/services/cache_service/rate_limit_cache.py +8 -7
- django_cfg/apps/payments/services/cache_service/simple_cache.py +17 -14
- django_cfg/apps/payments/services/core/__init__.py +3 -3
- django_cfg/apps/payments/services/core/balance_service.py +69 -65
- django_cfg/apps/payments/services/core/base.py +25 -22
- django_cfg/apps/payments/services/core/currency/__init__.py +1 -1
- django_cfg/apps/payments/services/core/currency/currency_converter.py +2 -0
- django_cfg/apps/payments/services/core/currency_service.py +68 -66
- django_cfg/apps/payments/services/core/operations/__init__.py +1 -1
- django_cfg/apps/payments/services/core/operations/payment_canceller.py +2 -1
- django_cfg/apps/payments/services/core/operations/payment_creator.py +2 -1
- django_cfg/apps/payments/services/core/operations/status_checker.py +2 -1
- django_cfg/apps/payments/services/core/payment_service.py +10 -7
- django_cfg/apps/payments/services/core/providers/provider_client.py +2 -2
- django_cfg/apps/payments/services/core/subscription_service.py +77 -74
- django_cfg/apps/payments/services/core/utils/data_converter.py +1 -0
- django_cfg/apps/payments/services/core/utils/statistics_calculator.py +1 -0
- django_cfg/apps/payments/services/core/webhook_service.py +67 -63
- django_cfg/apps/payments/services/integrations/__init__.py +3 -3
- django_cfg/apps/payments/services/integrations/ngrok_service.py +1 -0
- django_cfg/apps/payments/services/integrations/providers_config.py +3 -2
- django_cfg/apps/payments/services/providers/base.py +59 -57
- django_cfg/apps/payments/services/providers/models/__init__.py +7 -14
- django_cfg/apps/payments/services/providers/models/base.py +15 -15
- django_cfg/apps/payments/services/providers/models/providers.py +13 -12
- django_cfg/apps/payments/services/providers/models/universal.py +6 -5
- django_cfg/apps/payments/services/providers/nowpayments/__init__.py +4 -4
- django_cfg/apps/payments/services/providers/nowpayments/config.py +9 -8
- django_cfg/apps/payments/services/providers/nowpayments/models.py +15 -15
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/__init__.py +2 -2
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/patterns.py +26 -26
- django_cfg/apps/payments/services/providers/nowpayments/parsers/parser.py +3 -2
- django_cfg/apps/payments/services/providers/nowpayments/provider.py +95 -99
- django_cfg/apps/payments/services/providers/nowpayments/sync.py +41 -40
- django_cfg/apps/payments/services/providers/registry.py +65 -63
- django_cfg/apps/payments/services/providers/sync_service.py +50 -50
- django_cfg/apps/payments/services/types/__init__.py +21 -22
- django_cfg/apps/payments/services/types/data.py +14 -13
- django_cfg/apps/payments/services/types/requests.py +21 -22
- django_cfg/apps/payments/services/types/responses.py +16 -15
- django_cfg/apps/payments/services/types/webhooks.py +30 -30
- django_cfg/apps/payments/signals/__init__.py +4 -6
- django_cfg/apps/payments/signals/api_key_signals.py +36 -35
- django_cfg/apps/payments/signals/balance_signals.py +28 -26
- django_cfg/apps/payments/signals/payment_signals.py +29 -28
- django_cfg/apps/payments/signals/subscription_signals.py +39 -38
- django_cfg/apps/payments/static/payments/js/ngrok-status.js +12 -8
- django_cfg/apps/payments/static/payments/js/payment-detail.js +1 -1
- django_cfg/apps/payments/static/payments/js/payment-form.js +3 -3
- django_cfg/apps/payments/static/payments/js/payment-list.js +13 -6
- django_cfg/apps/payments/static/payments/js/webhook-dashboard-mjs.js +241 -0
- django_cfg/apps/payments/tasks/__init__.py +11 -12
- django_cfg/apps/payments/tasks/types.py +10 -9
- django_cfg/apps/payments/tasks/usage_tracking.py +44 -46
- django_cfg/apps/payments/templatetags/payment_tags.py +27 -27
- django_cfg/apps/payments/urls.py +31 -14
- django_cfg/apps/payments/urls_admin.py +10 -10
- django_cfg/apps/payments/views/api/__init__.py +32 -33
- django_cfg/apps/payments/views/api/api_keys.py +62 -62
- django_cfg/apps/payments/views/api/balances.py +63 -64
- django_cfg/apps/payments/views/api/base.py +52 -52
- django_cfg/apps/payments/views/api/currencies.py +75 -63
- django_cfg/apps/payments/views/api/payments.py +73 -74
- django_cfg/apps/payments/views/api/subscriptions.py +71 -72
- django_cfg/apps/payments/views/api/webhooks.py +85 -84
- django_cfg/apps/payments/views/overview/__init__.py +7 -7
- django_cfg/apps/payments/views/overview/serializers.py +13 -14
- django_cfg/apps/payments/views/overview/services.py +66 -67
- django_cfg/apps/payments/views/overview/urls.py +2 -1
- django_cfg/apps/payments/views/overview/views.py +31 -31
- django_cfg/apps/payments/views/serializers/__init__.py +35 -36
- django_cfg/apps/payments/views/serializers/api_keys.py +59 -57
- django_cfg/apps/payments/views/serializers/balances.py +34 -33
- django_cfg/apps/payments/views/serializers/currencies.py +36 -34
- django_cfg/apps/payments/views/serializers/payments.py +48 -47
- django_cfg/apps/payments/views/serializers/subscriptions.py +50 -45
- django_cfg/apps/payments/views/serializers/webhooks.py +17 -16
- django_cfg/apps/support/admin/__init__.py +3 -3
- django_cfg/apps/support/admin/resources.py +26 -26
- django_cfg/apps/support/admin/support_admin.py +44 -48
- django_cfg/apps/support/admin.py +16 -15
- django_cfg/apps/support/apps.py +1 -1
- django_cfg/apps/support/managers/message_manager.py +4 -4
- django_cfg/apps/support/managers/ticket_manager.py +13 -12
- django_cfg/apps/support/migrations/0001_initial.py +2 -1
- django_cfg/apps/support/models.py +3 -1
- django_cfg/apps/support/serializers.py +4 -2
- django_cfg/apps/support/signals.py +12 -10
- django_cfg/apps/support/urls.py +4 -3
- django_cfg/apps/support/utils/support_email_service.py +11 -9
- django_cfg/apps/support/views/__init__.py +3 -3
- django_cfg/apps/support/views/admin.py +9 -9
- django_cfg/apps/support/views/api.py +12 -13
- django_cfg/apps/support/views/chat.py +14 -14
- django_cfg/apps/tasks/admin/tasks_admin.py +65 -74
- django_cfg/apps/tasks/apps.py +2 -2
- django_cfg/apps/tasks/serializers.py +6 -6
- django_cfg/apps/tasks/static/tasks/js/dashboard/main.mjs +44 -20
- django_cfg/apps/tasks/static/tasks/js/dashboard/overview.mjs +7 -5
- django_cfg/apps/tasks/static/tasks/js/dashboard/queues.mjs +5 -3
- django_cfg/apps/tasks/static/tasks/js/dashboard/tasks.mjs +5 -3
- django_cfg/apps/tasks/static/tasks/js/dashboard/workers.mjs +5 -3
- django_cfg/apps/tasks/tasks/demo_tasks.py +12 -11
- django_cfg/apps/tasks/templates/tasks/components/tasks_mjs_integration.html +269 -0
- django_cfg/apps/tasks/templates/tasks/pages/dashboard-improved.html +168 -0
- django_cfg/apps/tasks/templates/tasks/pages/dashboard.html +21 -2
- django_cfg/apps/tasks/urls.py +3 -2
- django_cfg/apps/tasks/urls_admin.py +1 -0
- django_cfg/apps/tasks/utils/simulator.py +49 -52
- django_cfg/apps/tasks/views/api.py +75 -73
- django_cfg/apps/tasks/views/dashboard.py +5 -4
- django_cfg/apps/urls.py +20 -11
- django_cfg/apps.py +6 -5
- django_cfg/cli/commands/create_project.py +7 -6
- django_cfg/cli/commands/info.py +25 -25
- django_cfg/cli/utils.py +27 -27
- django_cfg/config.py +1 -1
- django_cfg/core/__init__.py +8 -8
- django_cfg/core/base/config_model.py +13 -12
- django_cfg/core/builders/apps_builder.py +2 -2
- django_cfg/core/builders/middleware_builder.py +1 -1
- django_cfg/core/builders/security_builder.py +1 -1
- django_cfg/core/config.py +2 -2
- django_cfg/core/environment/detector.py +27 -28
- django_cfg/core/exceptions.py +1 -1
- django_cfg/core/generation/core_generators/settings.py +1 -1
- django_cfg/core/generation/core_generators/static.py +11 -5
- django_cfg/core/generation/core_generators/templates.py +1 -1
- django_cfg/core/generation/data_generators/__init__.py +1 -1
- django_cfg/core/generation/data_generators/cache.py +1 -1
- django_cfg/core/generation/data_generators/database.py +1 -1
- django_cfg/core/generation/generation.py +1 -3
- django_cfg/core/generation/integration_generators/__init__.py +2 -2
- django_cfg/core/generation/integration_generators/api.py +12 -2
- django_cfg/core/generation/integration_generators/sessions.py +1 -1
- django_cfg/core/generation/integration_generators/tailwind.py +1 -1
- django_cfg/core/generation/integration_generators/tasks.py +1 -1
- django_cfg/core/generation/integration_generators/third_party.py +1 -1
- django_cfg/core/generation/orchestrator.py +1 -1
- django_cfg/core/generation/protocols.py +1 -1
- django_cfg/core/generation/utility_generators/__init__.py +1 -1
- django_cfg/core/generation/utility_generators/email.py +1 -1
- django_cfg/core/generation/utility_generators/i18n.py +1 -1
- django_cfg/core/generation/utility_generators/limits.py +1 -1
- django_cfg/core/generation/utility_generators/logging.py +1 -1
- django_cfg/core/generation/utility_generators/security.py +1 -1
- django_cfg/core/generation/utils/helpers.py +1 -1
- django_cfg/core/integration/__init__.py +5 -5
- django_cfg/core/integration/commands_collector.py +38 -39
- django_cfg/core/integration/display/__init__.py +2 -2
- django_cfg/core/integration/display/base.py +30 -30
- django_cfg/core/integration/display/ngrok.py +35 -36
- django_cfg/core/integration/display/startup.py +149 -139
- django_cfg/core/integration/url_integration.py +10 -10
- django_cfg/core/integration/version_checker.py +20 -19
- django_cfg/core/services/config_service.py +4 -4
- django_cfg/core/state/__init__.py +1 -1
- django_cfg/core/state/registry.py +1 -1
- django_cfg/core/types/__init__.py +8 -1
- django_cfg/core/validation.py +36 -39
- django_cfg/management/commands/check_endpoints.py +3 -1
- django_cfg/management/commands/check_settings.py +3 -1
- django_cfg/management/commands/clear_constance.py +3 -1
- django_cfg/management/commands/create_token.py +3 -1
- django_cfg/management/commands/generate_clients.py +3 -1
- django_cfg/management/commands/migrate_all.py +3 -1
- django_cfg/management/commands/rundramatiq.py +3 -1
- django_cfg/management/commands/rundramatiq_simulator.py +3 -1
- django_cfg/management/commands/runserver_ngrok.py +3 -1
- django_cfg/management/commands/show_config.py +3 -1
- django_cfg/management/commands/superuser.py +3 -1
- django_cfg/management/commands/task_clear.py +3 -1
- django_cfg/management/commands/task_status.py +3 -1
- django_cfg/management/commands/test_email.py +3 -1
- django_cfg/management/commands/test_telegram.py +3 -1
- django_cfg/management/commands/test_twilio.py +3 -1
- django_cfg/management/commands/validate_openapi.py +3 -1
- django_cfg/middleware/pagination.py +8 -8
- django_cfg/middleware/public_endpoints.py +24 -23
- django_cfg/middleware/user_activity.py +27 -25
- django_cfg/models/__init__.py +19 -20
- django_cfg/models/api/__init__.py +4 -4
- django_cfg/models/api/config.py +23 -21
- django_cfg/models/api/cors.py +17 -16
- django_cfg/models/api/drf/__init__.py +1 -1
- django_cfg/models/api/drf/config.py +2 -1
- django_cfg/models/api/drf/redoc.py +2 -1
- django_cfg/models/api/drf/spectacular.py +4 -2
- django_cfg/models/api/drf/swagger.py +2 -1
- django_cfg/models/api/jwt.py +37 -36
- django_cfg/models/api/keys.py +13 -12
- django_cfg/models/api/limits.py +31 -30
- django_cfg/models/base/config.py +40 -41
- django_cfg/models/base/module.py +8 -8
- django_cfg/models/django/__init__.py +1 -1
- django_cfg/models/django/constance.py +8 -7
- django_cfg/models/django/environment.py +5 -3
- django_cfg/models/django/openapi.py +6 -16
- django_cfg/models/django/revolution_legacy.py +17 -16
- django_cfg/models/infrastructure/__init__.py +1 -1
- django_cfg/models/infrastructure/cache.py +46 -45
- django_cfg/models/infrastructure/database/config.py +4 -6
- django_cfg/models/infrastructure/database/converters.py +1 -1
- django_cfg/models/infrastructure/database/parsers.py +1 -1
- django_cfg/models/infrastructure/database/validators.py +1 -1
- django_cfg/models/infrastructure/logging.py +59 -57
- django_cfg/models/infrastructure/security.py +26 -24
- django_cfg/models/ngrok/auth.py +2 -1
- django_cfg/models/ngrok/config.py +3 -2
- django_cfg/models/ngrok/tunnel.py +2 -1
- django_cfg/models/payments/__init__.py +1 -1
- django_cfg/models/payments/api_keys.py +3 -1
- django_cfg/models/payments/config.py +4 -1
- django_cfg/models/payments/providers/base.py +2 -1
- django_cfg/models/payments/providers/nowpayments.py +3 -1
- django_cfg/models/services/__init__.py +1 -1
- django_cfg/models/services/base.py +2 -1
- django_cfg/models/services/email.py +28 -26
- django_cfg/models/services/telegram.py +2 -1
- django_cfg/models/tasks/__init__.py +2 -2
- django_cfg/models/tasks/backends.py +4 -3
- django_cfg/models/tasks/config.py +6 -4
- django_cfg/models/tasks/utils.py +3 -3
- django_cfg/modules/base.py +18 -17
- django_cfg/modules/django_admin/__init__.py +14 -15
- django_cfg/modules/django_admin/decorators/__init__.py +1 -1
- django_cfg/modules/django_admin/decorators/actions.py +8 -7
- django_cfg/modules/django_admin/decorators/display.py +9 -7
- django_cfg/modules/django_admin/icons/__init__.py +1 -1
- django_cfg/modules/django_admin/icons/constants.py +27 -27
- django_cfg/modules/django_admin/icons/generate_icons.py +54 -54
- django_cfg/modules/django_admin/management/commands/check_endpoints.py +5 -3
- django_cfg/modules/django_admin/management/commands/check_settings.py +40 -44
- django_cfg/modules/django_admin/management/commands/clear_constance.py +29 -30
- django_cfg/modules/django_admin/management/commands/create_token.py +42 -42
- django_cfg/modules/django_admin/management/commands/list_urls.py +37 -38
- django_cfg/modules/django_admin/management/commands/migrate_all.py +13 -15
- django_cfg/modules/django_admin/management/commands/migrator.py +17 -17
- django_cfg/modules/django_admin/management/commands/script.py +58 -60
- django_cfg/modules/django_admin/management/commands/show_config.py +32 -30
- django_cfg/modules/django_admin/management/commands/show_urls.py +46 -44
- django_cfg/modules/django_admin/management/commands/superuser.py +47 -48
- django_cfg/modules/django_admin/management/commands/tree.py +50 -54
- django_cfg/modules/django_admin/mixins/display_mixin.py +16 -15
- django_cfg/modules/django_admin/mixins/optimization_mixin.py +9 -8
- django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +25 -24
- django_cfg/modules/django_admin/models/__init__.py +4 -4
- django_cfg/modules/django_admin/models/action_models.py +3 -1
- django_cfg/modules/django_admin/models/badge_models.py +4 -2
- django_cfg/modules/django_admin/models/base.py +3 -3
- django_cfg/modules/django_admin/models/display_models.py +1 -0
- django_cfg/modules/django_admin/utils/badges.py +27 -26
- django_cfg/modules/django_admin/utils/displays.py +49 -49
- django_cfg/modules/django_client/apps.py +21 -3
- django_cfg/modules/django_client/core/__init__.py +9 -10
- django_cfg/modules/django_client/core/archive/manager.py +2 -2
- django_cfg/modules/django_client/core/cli/main.py +1 -3
- django_cfg/modules/django_client/core/config/config.py +3 -1
- django_cfg/modules/django_client/core/config/group.py +1 -0
- django_cfg/modules/django_client/core/config/service.py +2 -1
- django_cfg/modules/django_client/core/generator/__init__.py +1 -1
- django_cfg/modules/django_client/core/generator/base.py +2 -2
- django_cfg/modules/django_client/core/generator/python/async_client_gen.py +1 -1
- django_cfg/modules/django_client/core/generator/python/files_generator.py +1 -1
- django_cfg/modules/django_client/core/generator/python/generator.py +4 -4
- django_cfg/modules/django_client/core/generator/python/models_generator.py +1 -1
- django_cfg/modules/django_client/core/generator/python/operations_generator.py +2 -2
- django_cfg/modules/django_client/core/generator/python/sync_client_gen.py +1 -1
- django_cfg/modules/django_client/core/generator/typescript/client_generator.py +3 -1
- django_cfg/modules/django_client/core/generator/typescript/fetchers_generator.py +14 -13
- django_cfg/modules/django_client/core/generator/typescript/files_generator.py +1 -0
- django_cfg/modules/django_client/core/generator/typescript/generator.py +6 -6
- django_cfg/modules/django_client/core/generator/typescript/hooks_generator.py +12 -10
- django_cfg/modules/django_client/core/generator/typescript/models_generator.py +2 -1
- django_cfg/modules/django_client/core/generator/typescript/naming.py +2 -3
- django_cfg/modules/django_client/core/generator/typescript/operations_generator.py +12 -10
- django_cfg/modules/django_client/core/generator/typescript/schemas_generator.py +3 -2
- django_cfg/modules/django_client/core/generator/typescript/templates/client/client.ts.jinja +14 -6
- django_cfg/modules/django_client/core/generator/typescript/templates/main_index.ts.jinja +4 -10
- django_cfg/modules/django_client/core/groups/__init__.py +1 -1
- django_cfg/modules/django_client/core/groups/detector.py +2 -1
- django_cfg/modules/django_client/core/groups/manager.py +2 -1
- django_cfg/modules/django_client/core/ir/schema.py +1 -1
- django_cfg/modules/django_client/core/parser/base.py +0 -2
- django_cfg/modules/django_client/core/parser/models/schema.py +1 -1
- django_cfg/modules/django_client/core/validation/__init__.py +1 -1
- django_cfg/modules/django_client/core/validation/fixer.py +1 -2
- django_cfg/modules/django_client/core/validation/reporter.py +2 -2
- django_cfg/modules/django_client/core/validation/safety.py +1 -1
- django_cfg/modules/django_client/management/commands/generate_client.py +14 -11
- django_cfg/modules/django_client/management/commands/validate_openapi.py +4 -6
- django_cfg/modules/django_client/spectacular/__init__.py +1 -1
- django_cfg/modules/django_client/spectacular/async_detection.py +3 -2
- django_cfg/modules/django_client/spectacular/enum_naming.py +1 -1
- django_cfg/modules/django_client/spectacular/schema.py +5 -5
- django_cfg/modules/django_client/system/__init__.py +24 -0
- django_cfg/modules/django_client/system/base_generator.py +123 -0
- django_cfg/modules/django_client/system/generate_mjs_clients.py +174 -0
- django_cfg/modules/django_client/system/mjs_generator.py +219 -0
- django_cfg/modules/django_client/system/schema_parser.py +195 -0
- django_cfg/modules/django_client/system/templates/api_client.js.j2 +87 -0
- django_cfg/modules/django_client/system/templates/app_index.js.j2 +13 -0
- django_cfg/modules/django_client/system/templates/base_client.js.j2 +166 -0
- django_cfg/modules/django_client/system/templates/main_index.js.j2 +80 -0
- django_cfg/modules/django_client/system/templates/types.js.j2 +24 -0
- django_cfg/modules/django_client/urls.py +3 -2
- django_cfg/modules/django_currency/__init__.py +17 -18
- django_cfg/modules/django_currency/clients/__init__.py +2 -2
- django_cfg/modules/django_currency/clients/coinpaprika_client.py +48 -48
- django_cfg/modules/django_currency/clients/hybrid_client.py +76 -75
- django_cfg/modules/django_currency/core/__init__.py +7 -13
- django_cfg/modules/django_currency/core/converter.py +25 -24
- django_cfg/modules/django_currency/core/models.py +9 -8
- django_cfg/modules/django_currency/database/__init__.py +4 -4
- django_cfg/modules/django_currency/database/database_loader.py +65 -66
- django_cfg/modules/django_currency/examples/example_database_usage.py +29 -28
- django_cfg/modules/django_currency/utils/cache.py +10 -11
- django_cfg/modules/django_dashboard/__init__.py +4 -5
- django_cfg/modules/django_dashboard/components.py +11 -7
- django_cfg/modules/django_dashboard/debug.py +1 -3
- django_cfg/modules/django_dashboard/management/commands/debug_dashboard.py +3 -3
- django_cfg/modules/django_dashboard/sections/base.py +2 -1
- django_cfg/modules/django_dashboard/sections/commands.py +3 -2
- django_cfg/modules/django_dashboard/sections/documentation.py +8 -6
- django_cfg/modules/django_dashboard/sections/overview.py +13 -9
- django_cfg/modules/django_dashboard/sections/stats.py +2 -2
- django_cfg/modules/django_dashboard/sections/system.py +2 -1
- django_cfg/modules/django_drf_theme/templatetags/tailwind_tags.py +12 -4
- django_cfg/modules/django_email/management/commands/test_email.py +8 -7
- django_cfg/modules/django_email/service.py +5 -4
- django_cfg/modules/django_health/service.py +46 -44
- django_cfg/modules/django_import_export/__init__.py +7 -3
- django_cfg/modules/django_llm/__init__.py +3 -2
- django_cfg/modules/django_llm/example.py +58 -56
- django_cfg/modules/django_llm/llm/__init__.py +1 -1
- django_cfg/modules/django_llm/llm/cache.py +21 -20
- django_cfg/modules/django_llm/llm/client.py +9 -9
- django_cfg/modules/django_llm/llm/costs.py +14 -14
- django_cfg/modules/django_llm/llm/embeddings/__init__.py +1 -1
- django_cfg/modules/django_llm/llm/embeddings/mock_embedder.py +1 -2
- django_cfg/modules/django_llm/llm/embeddings/openai_embedder.py +1 -2
- django_cfg/modules/django_llm/llm/extractor.py +8 -8
- django_cfg/modules/django_llm/llm/models.py +5 -5
- django_cfg/modules/django_llm/llm/models_api/models_query.py +2 -2
- django_cfg/modules/django_llm/llm/models_cache.py +91 -92
- django_cfg/modules/django_llm/llm/providers/config_builder.py +1 -1
- django_cfg/modules/django_llm/llm/providers/provider_manager.py +2 -1
- django_cfg/modules/django_llm/llm/requests/cache_manager.py +1 -1
- django_cfg/modules/django_llm/llm/requests/chat_handler.py +2 -2
- django_cfg/modules/django_llm/llm/requests/embedding_handler.py +1 -1
- django_cfg/modules/django_llm/llm/responses/response_builder.py +2 -2
- django_cfg/modules/django_llm/llm/stats/stats_manager.py +1 -1
- django_cfg/modules/django_llm/llm/tokenizer.py +10 -9
- django_cfg/modules/django_llm/translator/__init__.py +1 -1
- django_cfg/modules/django_llm/translator/cache.py +36 -35
- django_cfg/modules/django_llm/translator/detectors/__init__.py +1 -1
- django_cfg/modules/django_llm/translator/detectors/script_detector.py +0 -1
- django_cfg/modules/django_llm/translator/stats/stats_tracker.py +1 -1
- django_cfg/modules/django_llm/translator/translator.py +5 -4
- django_cfg/modules/django_llm/translator/translators/__init__.py +1 -1
- django_cfg/modules/django_llm/translator/translators/json_translator.py +1 -1
- django_cfg/modules/django_llm/translator/utils/__init__.py +1 -1
- django_cfg/modules/django_llm/translator/utils/prompt_builder.py +0 -1
- django_cfg/modules/django_logging/__init__.py +1 -1
- django_cfg/modules/django_logging/django_logger.py +33 -34
- django_cfg/modules/django_logging/logger.py +3 -7
- django_cfg/modules/django_ngrok/__init__.py +7 -7
- django_cfg/modules/django_ngrok/management/commands/runserver_ngrok.py +33 -30
- django_cfg/modules/django_ngrok/service.py +33 -32
- django_cfg/modules/django_tailwind/templates/django_tailwind/base.html +4 -36
- django_cfg/modules/django_tailwind/templates/django_tailwind/components/navbar.html +1 -1
- django_cfg/modules/django_tasks/__init__.py +5 -5
- django_cfg/modules/django_tasks/dramatiq_setup.py +1 -1
- django_cfg/modules/django_tasks/factory.py +1 -1
- django_cfg/modules/django_tasks/management/commands/rundramatiq.py +39 -40
- django_cfg/modules/django_tasks/management/commands/rundramatiq_simulator.py +79 -80
- django_cfg/modules/django_tasks/management/commands/task_clear.py +34 -34
- django_cfg/modules/django_tasks/management/commands/task_status.py +34 -34
- django_cfg/modules/django_tasks/service.py +4 -3
- django_cfg/modules/django_tasks/settings.py +1 -1
- django_cfg/modules/django_telegram/__init__.py +4 -4
- django_cfg/modules/django_telegram/management/commands/test_telegram.py +4 -5
- django_cfg/modules/django_telegram/service.py +4 -3
- django_cfg/modules/django_telegram/utils.py +1 -1
- django_cfg/modules/django_twilio/__init__.py +15 -16
- django_cfg/modules/django_twilio/_imports.py +1 -1
- django_cfg/modules/django_twilio/base.py +9 -5
- django_cfg/modules/django_twilio/email_otp.py +4 -3
- django_cfg/modules/django_twilio/exceptions.py +36 -36
- django_cfg/modules/django_twilio/management/commands/test_twilio.py +6 -7
- django_cfg/modules/django_twilio/models.py +54 -53
- django_cfg/modules/django_twilio/sendgrid_service.py +70 -72
- django_cfg/modules/django_twilio/simple_service.py +42 -41
- django_cfg/modules/django_twilio/sms.py +1 -0
- django_cfg/modules/django_twilio/twilio_service.py +79 -83
- django_cfg/modules/django_twilio/unified.py +6 -5
- django_cfg/modules/django_twilio/utils.py +2 -3
- django_cfg/modules/django_twilio/whatsapp.py +3 -2
- django_cfg/modules/django_unfold/__init__.py +7 -6
- django_cfg/modules/django_unfold/callbacks/actions.py +6 -5
- django_cfg/modules/django_unfold/callbacks/apizones.py +122 -0
- django_cfg/modules/django_unfold/callbacks/base.py +9 -8
- django_cfg/modules/django_unfold/callbacks/charts.py +36 -37
- django_cfg/modules/django_unfold/callbacks/commands.py +2 -2
- django_cfg/modules/django_unfold/callbacks/main.py +27 -27
- django_cfg/modules/django_unfold/callbacks/statistics.py +12 -12
- django_cfg/modules/django_unfold/callbacks/system.py +5 -5
- django_cfg/modules/django_unfold/callbacks/users.py +4 -4
- django_cfg/modules/django_unfold/dashboard.py +29 -29
- django_cfg/modules/django_unfold/models/__init__.py +23 -8
- django_cfg/modules/django_unfold/models/config.py +84 -81
- django_cfg/modules/django_unfold/models/dashboard.py +20 -19
- django_cfg/modules/django_unfold/models/dropdown.py +6 -4
- django_cfg/modules/django_unfold/models/navigation.py +6 -4
- django_cfg/modules/django_unfold/models/tabs.py +4 -3
- django_cfg/modules/django_unfold/models.py +2 -3
- django_cfg/modules/django_unfold/system_monitor.py +27 -25
- django_cfg/modules/django_unfold/tailwind.py +12 -14
- django_cfg/modules/django_unfold/utils.py +7 -6
- django_cfg/pyproject.toml +1 -1
- django_cfg/registry/__init__.py +3 -3
- django_cfg/registry/core.py +8 -8
- django_cfg/registry/modules.py +2 -2
- django_cfg/registry/services.py +2 -2
- django_cfg/registry/third_party.py +3 -3
- django_cfg/routing/__init__.py +3 -3
- django_cfg/routing/callbacks.py +27 -26
- django_cfg/routing/routers.py +2 -2
- django_cfg/static/js/api/accounts/client.mjs +69 -0
- django_cfg/static/js/api/accounts/index.mjs +13 -0
- django_cfg/static/js/api/base.mjs +166 -0
- django_cfg/static/js/api/index.mjs +100 -0
- django_cfg/static/js/api/ipc/client.mjs +74 -0
- django_cfg/static/js/api/ipc/index.mjs +13 -0
- django_cfg/static/js/api/leads/client.mjs +71 -0
- django_cfg/static/js/api/leads/index.mjs +13 -0
- django_cfg/static/js/api/newsletter/client.mjs +109 -0
- django_cfg/static/js/api/newsletter/index.mjs +13 -0
- django_cfg/static/js/api/payments/client.mjs +1264 -0
- django_cfg/static/js/api/payments/index.mjs +13 -0
- django_cfg/static/js/api/support/client.mjs +84 -0
- django_cfg/static/js/api/support/index.mjs +13 -0
- django_cfg/static/js/api/tasks/client.mjs +74 -0
- django_cfg/static/js/api/tasks/index.mjs +13 -0
- django_cfg/static/js/api/types.mjs +729 -0
- django_cfg/static/js/api-loader.mjs +169 -0
- django_cfg/templates/admin/snippets/zones/zones_table.html +4 -3
- django_cfg/templatetags/django_cfg.py +4 -4
- django_cfg/utils/path_resolution.py +49 -50
- django_cfg/utils/smart_defaults.py +27 -29
- django_cfg/utils/version_check.py +14 -14
- {django_cfg-1.4.20.dist-info → django_cfg-1.4.23.dist-info}/METADATA +1 -1
- django_cfg-1.4.23.dist-info/RECORD +1137 -0
- django_cfg/apps/payments/static/payments/js/api-client.js +0 -408
- django_cfg/modules/django_ipc_client/dashboard/README.md +0 -517
- django_cfg/modules/django_ipc_client/dashboard/UNFOLD_INTEGRATION.md +0 -439
- django_cfg/modules/django_ipc_client/dashboard/__init__.py +0 -11
- django_cfg/modules/django_ipc_client/dashboard/apps.py +0 -22
- django_cfg/modules/django_ipc_client/dashboard/templates/django_ipc_dashboard/dashboard.html +0 -200
- django_cfg/modules/django_ipc_client/dashboard/urls.py +0 -22
- django_cfg/modules/django_ipc_client/dashboard/urls_admin.py +0 -9
- django_cfg/modules/django_ipc_client/dashboard/views.py +0 -251
- django_cfg/modules/django_rpc_old/POETRY.md +0 -344
- django_cfg/modules/django_rpc_old/README.md +0 -397
- django_cfg/modules/django_rpc_old/TESTING.md +0 -358
- django_cfg/modules/django_rpc_old/__init__.py +0 -39
- django_cfg/modules/django_rpc_old/client.py +0 -531
- django_cfg/modules/django_rpc_old/config.py +0 -279
- django_cfg/modules/django_rpc_old/exceptions.py +0 -172
- django_cfg/modules/django_unfold/callbacks/revolution.py +0 -81
- django_cfg-1.4.20.dist-info/RECORD +0 -1110
- /django_cfg/{modules/django_ipc_client → apps/ipc}/README.md +0 -0
- /django_cfg/{modules/django_ipc_client → apps/ipc/services/client}/config.py +0 -0
- {django_cfg-1.4.20.dist-info → django_cfg-1.4.23.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.20.dist-info → django_cfg-1.4.23.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.20.dist-info → django_cfg-1.4.23.dist-info}/licenses/LICENSE +0 -0
@@ -6,14 +6,16 @@ Lightweight middleware for tracking API usage and analytics.
|
|
6
6
|
|
7
7
|
import time
|
8
8
|
from typing import Optional
|
9
|
+
|
10
|
+
from django.core.cache import cache
|
9
11
|
from django.http import HttpRequest, HttpResponse
|
10
|
-
from django.utils.deprecation import MiddlewareMixin
|
11
12
|
from django.utils import timezone
|
12
|
-
from django.
|
13
|
+
from django.utils.deprecation import MiddlewareMixin
|
13
14
|
|
14
|
-
from ..config.helpers import MiddlewareConfigHelper
|
15
15
|
from django_cfg.modules.django_logging import get_logger
|
16
16
|
|
17
|
+
from ..config.helpers import MiddlewareConfigHelper
|
18
|
+
|
17
19
|
logger = get_logger("usage_tracking_middleware")
|
18
20
|
|
19
21
|
|
@@ -28,20 +30,20 @@ class UsageTrackingMiddleware(MiddlewareMixin):
|
|
28
30
|
- Performance metrics
|
29
31
|
- Error rate tracking
|
30
32
|
"""
|
31
|
-
|
33
|
+
|
32
34
|
def __init__(self, get_response=None):
|
33
35
|
super().__init__(get_response)
|
34
|
-
|
36
|
+
|
35
37
|
# Load configuration from django-cfg
|
36
38
|
try:
|
37
39
|
middleware_config = MiddlewareConfigHelper.get_middleware_config()
|
38
|
-
|
40
|
+
|
39
41
|
# Configuration from django-cfg
|
40
42
|
self.enabled = middleware_config['usage_tracking_enabled']
|
41
43
|
self.track_anonymous = middleware_config['track_anonymous_usage']
|
42
44
|
self.api_prefixes = middleware_config['api_prefixes']
|
43
45
|
self.cache_timeout = middleware_config['cache_timeouts']['default']
|
44
|
-
|
46
|
+
|
45
47
|
# Static exempt paths
|
46
48
|
self.exempt_paths = [
|
47
49
|
'/api/health/',
|
@@ -49,7 +51,7 @@ class UsageTrackingMiddleware(MiddlewareMixin):
|
|
49
51
|
'/static/',
|
50
52
|
'/media/',
|
51
53
|
]
|
52
|
-
|
54
|
+
|
53
55
|
except Exception as e:
|
54
56
|
logger.warning(f"Failed to load usage tracking config, using defaults: {e}")
|
55
57
|
# Fallback defaults
|
@@ -58,12 +60,12 @@ class UsageTrackingMiddleware(MiddlewareMixin):
|
|
58
60
|
self.api_prefixes = ['/api/']
|
59
61
|
self.exempt_paths = ['/api/health/', '/admin/']
|
60
62
|
self.cache_timeout = 3600
|
61
|
-
|
62
|
-
logger.info(
|
63
|
+
|
64
|
+
logger.info("Usage Tracking Middleware initialized", extra={
|
63
65
|
'enabled': self.enabled,
|
64
66
|
'track_anonymous': self.track_anonymous
|
65
67
|
})
|
66
|
-
|
68
|
+
|
67
69
|
def process_request(self, request: HttpRequest) -> Optional[HttpResponse]:
|
68
70
|
"""
|
69
71
|
Process incoming request - start timing and prepare tracking.
|
@@ -78,10 +80,10 @@ class UsageTrackingMiddleware(MiddlewareMixin):
|
|
78
80
|
# Check if we should track this request
|
79
81
|
if not self._should_track_request(request):
|
80
82
|
return None
|
81
|
-
|
83
|
+
|
82
84
|
# Start timing
|
83
85
|
request._usage_start_time = time.time()
|
84
|
-
|
86
|
+
|
85
87
|
# Store request info for tracking
|
86
88
|
request._usage_info = {
|
87
89
|
'method': request.method,
|
@@ -90,59 +92,59 @@ class UsageTrackingMiddleware(MiddlewareMixin):
|
|
90
92
|
'ip_address': self._get_client_ip(request),
|
91
93
|
'authenticated': hasattr(request, 'api_key') or (hasattr(request, 'user') and request.user.is_authenticated)
|
92
94
|
}
|
93
|
-
|
95
|
+
|
94
96
|
return None
|
95
|
-
|
97
|
+
|
96
98
|
def process_response(self, request: HttpRequest, response: HttpResponse) -> HttpResponse:
|
97
99
|
"""
|
98
100
|
Process response - track usage and performance metrics.
|
99
101
|
"""
|
100
102
|
if not self.enabled or not hasattr(request, '_usage_start_time'):
|
101
103
|
return response
|
102
|
-
|
104
|
+
|
103
105
|
try:
|
104
106
|
# Calculate response time
|
105
107
|
response_time = (time.time() - request._usage_start_time) * 1000 # ms
|
106
|
-
|
108
|
+
|
107
109
|
# Get usage info
|
108
110
|
usage_info = getattr(request, '_usage_info', {})
|
109
|
-
|
111
|
+
|
110
112
|
# Track the request
|
111
113
|
self._track_request(request, response, response_time, usage_info)
|
112
|
-
|
114
|
+
|
113
115
|
# Add performance headers
|
114
116
|
response['X-Response-Time'] = f"{response_time:.2f}ms"
|
115
|
-
|
117
|
+
|
116
118
|
except Exception as e:
|
117
119
|
logger.warning(f"Usage tracking failed: {e}")
|
118
|
-
|
120
|
+
|
119
121
|
return response
|
120
|
-
|
122
|
+
|
121
123
|
def _should_track_request(self, request: HttpRequest) -> bool:
|
122
124
|
"""
|
123
125
|
Determine if we should track this request.
|
124
126
|
"""
|
125
127
|
# Check if path is in API prefixes
|
126
128
|
is_api_request = any(request.path.startswith(prefix) for prefix in self.api_prefixes)
|
127
|
-
|
129
|
+
|
128
130
|
if not is_api_request:
|
129
131
|
return False
|
130
|
-
|
132
|
+
|
131
133
|
# Check exempt paths
|
132
134
|
if request.path in self.exempt_paths:
|
133
135
|
return False
|
134
|
-
|
136
|
+
|
135
137
|
# Check if we should track anonymous requests
|
136
138
|
if not self.track_anonymous:
|
137
139
|
is_authenticated = (
|
138
|
-
hasattr(request, 'api_key') or
|
140
|
+
hasattr(request, 'api_key') or
|
139
141
|
(hasattr(request, 'user') and request.user.is_authenticated)
|
140
142
|
)
|
141
143
|
if not is_authenticated:
|
142
144
|
return False
|
143
|
-
|
145
|
+
|
144
146
|
return True
|
145
|
-
|
147
|
+
|
146
148
|
def _track_request(self, request: HttpRequest, response: HttpResponse, response_time: float, usage_info: dict):
|
147
149
|
"""
|
148
150
|
Track request usage and performance metrics.
|
@@ -154,23 +156,23 @@ class UsageTrackingMiddleware(MiddlewareMixin):
|
|
154
156
|
user_id = request.api_key.user.id
|
155
157
|
elif hasattr(request, 'user') and request.user.is_authenticated:
|
156
158
|
user_id = request.user.id
|
157
|
-
|
159
|
+
|
158
160
|
# Track endpoint usage
|
159
161
|
self._track_endpoint_usage(usage_info['path'], usage_info['method'], response.status_code)
|
160
|
-
|
162
|
+
|
161
163
|
# Track user activity
|
162
164
|
if user_id:
|
163
165
|
self._track_user_activity(user_id, usage_info['path'], response_time)
|
164
|
-
|
166
|
+
|
165
167
|
# Track performance metrics
|
166
168
|
self._track_performance_metrics(usage_info['path'], response_time, response.status_code)
|
167
|
-
|
169
|
+
|
168
170
|
# Track errors
|
169
171
|
if response.status_code >= 400:
|
170
172
|
self._track_error(usage_info, response.status_code)
|
171
|
-
|
173
|
+
|
172
174
|
# Log request
|
173
|
-
logger.debug(
|
175
|
+
logger.debug("Request tracked", extra={
|
174
176
|
'path': usage_info['path'],
|
175
177
|
'method': usage_info['method'],
|
176
178
|
'status_code': response.status_code,
|
@@ -178,10 +180,10 @@ class UsageTrackingMiddleware(MiddlewareMixin):
|
|
178
180
|
'user_id': user_id,
|
179
181
|
'authenticated': usage_info['authenticated']
|
180
182
|
})
|
181
|
-
|
183
|
+
|
182
184
|
except Exception as e:
|
183
185
|
logger.warning(f"Failed to track request: {e}")
|
184
|
-
|
186
|
+
|
185
187
|
def _track_endpoint_usage(self, path: str, method: str, status_code: int):
|
186
188
|
"""
|
187
189
|
Track endpoint usage statistics.
|
@@ -189,59 +191,59 @@ class UsageTrackingMiddleware(MiddlewareMixin):
|
|
189
191
|
try:
|
190
192
|
today = timezone.now().date().isoformat()
|
191
193
|
hour = timezone.now().hour
|
192
|
-
|
194
|
+
|
193
195
|
# Daily endpoint usage
|
194
196
|
daily_key = f"endpoint_usage:{path}:{method}:{today}"
|
195
197
|
cache.set(daily_key, cache.get(daily_key, 0) + 1, timeout=86400 * 2)
|
196
|
-
|
198
|
+
|
197
199
|
# Hourly endpoint usage
|
198
200
|
hourly_key = f"endpoint_usage_hourly:{path}:{method}:{today}:{hour}"
|
199
201
|
cache.set(hourly_key, cache.get(hourly_key, 0) + 1, timeout=86400)
|
200
|
-
|
202
|
+
|
201
203
|
# Status code tracking
|
202
204
|
status_key = f"endpoint_status:{path}:{method}:{status_code}:{today}"
|
203
205
|
cache.set(status_key, cache.get(status_key, 0) + 1, timeout=86400 * 2)
|
204
|
-
|
206
|
+
|
205
207
|
except Exception as e:
|
206
208
|
logger.warning(f"Failed to track endpoint usage: {e}")
|
207
|
-
|
209
|
+
|
208
210
|
def _track_user_activity(self, user_id: int, path: str, response_time: float):
|
209
211
|
"""
|
210
212
|
Track user activity and performance.
|
211
213
|
"""
|
212
214
|
try:
|
213
215
|
today = timezone.now().date().isoformat()
|
214
|
-
|
216
|
+
|
215
217
|
# Update last activity
|
216
218
|
cache.set(f"user_last_activity:{user_id}", timezone.now().isoformat(), timeout=86400 * 30)
|
217
|
-
|
219
|
+
|
218
220
|
# Daily user requests
|
219
221
|
daily_requests_key = f"user_requests:{user_id}:{today}"
|
220
222
|
cache.set(daily_requests_key, cache.get(daily_requests_key, 0) + 1, timeout=86400 * 2)
|
221
|
-
|
223
|
+
|
222
224
|
# User endpoint usage
|
223
225
|
user_endpoint_key = f"user_endpoint:{user_id}:{path}:{today}"
|
224
226
|
cache.set(user_endpoint_key, cache.get(user_endpoint_key, 0) + 1, timeout=86400 * 2)
|
225
|
-
|
227
|
+
|
226
228
|
# User performance tracking
|
227
229
|
perf_key = f"user_performance:{user_id}:{today}"
|
228
230
|
perf_data = cache.get(perf_key, {'total_time': 0.0, 'request_count': 0})
|
229
231
|
perf_data['total_time'] += response_time
|
230
232
|
perf_data['request_count'] += 1
|
231
233
|
perf_data['avg_response_time'] = perf_data['total_time'] / perf_data['request_count']
|
232
|
-
|
234
|
+
|
233
235
|
cache.set(perf_key, perf_data, timeout=86400 * 2)
|
234
|
-
|
236
|
+
|
235
237
|
except Exception as e:
|
236
238
|
logger.warning(f"Failed to track user activity: {e}")
|
237
|
-
|
239
|
+
|
238
240
|
def _track_performance_metrics(self, path: str, response_time: float, status_code: int):
|
239
241
|
"""
|
240
242
|
Track performance metrics for monitoring.
|
241
243
|
"""
|
242
244
|
try:
|
243
245
|
today = timezone.now().date().isoformat()
|
244
|
-
|
246
|
+
|
245
247
|
# Global performance metrics
|
246
248
|
global_perf_key = f"global_performance:{today}"
|
247
249
|
global_perf = cache.get(global_perf_key, {
|
@@ -250,53 +252,53 @@ class UsageTrackingMiddleware(MiddlewareMixin):
|
|
250
252
|
'slow_requests': 0, # > 1000ms
|
251
253
|
'fast_requests': 0, # < 100ms
|
252
254
|
})
|
253
|
-
|
255
|
+
|
254
256
|
global_perf['total_requests'] += 1
|
255
257
|
global_perf['total_time'] += response_time
|
256
|
-
|
258
|
+
|
257
259
|
if response_time > 1000:
|
258
260
|
global_perf['slow_requests'] += 1
|
259
261
|
elif response_time < 100:
|
260
262
|
global_perf['fast_requests'] += 1
|
261
|
-
|
263
|
+
|
262
264
|
global_perf['avg_response_time'] = global_perf['total_time'] / global_perf['total_requests']
|
263
|
-
|
265
|
+
|
264
266
|
cache.set(global_perf_key, global_perf, timeout=86400 * 2)
|
265
|
-
|
267
|
+
|
266
268
|
# Update system average response time for adaptive rate limiting
|
267
269
|
cache.set('system_avg_response_time', global_perf['avg_response_time'], timeout=300)
|
268
|
-
|
270
|
+
|
269
271
|
except Exception as e:
|
270
272
|
logger.warning(f"Failed to track performance metrics: {e}")
|
271
|
-
|
273
|
+
|
272
274
|
def _track_error(self, usage_info: dict, status_code: int):
|
273
275
|
"""
|
274
276
|
Track error occurrences for monitoring.
|
275
277
|
"""
|
276
278
|
try:
|
277
279
|
today = timezone.now().date().isoformat()
|
278
|
-
|
280
|
+
|
279
281
|
# Global error tracking
|
280
282
|
error_key = f"errors:{status_code}:{today}"
|
281
283
|
cache.set(error_key, cache.get(error_key, 0) + 1, timeout=86400 * 7)
|
282
|
-
|
284
|
+
|
283
285
|
# Endpoint-specific error tracking
|
284
286
|
endpoint_error_key = f"endpoint_errors:{usage_info['path']}:{status_code}:{today}"
|
285
287
|
cache.set(endpoint_error_key, cache.get(endpoint_error_key, 0) + 1, timeout=86400 * 7)
|
286
|
-
|
288
|
+
|
287
289
|
# Log significant errors
|
288
290
|
if status_code >= 500:
|
289
|
-
logger.error(
|
291
|
+
logger.error("Server error tracked", extra={
|
290
292
|
'status_code': status_code,
|
291
293
|
'path': usage_info['path'],
|
292
294
|
'method': usage_info['method'],
|
293
295
|
'ip_address': usage_info['ip_address'],
|
294
296
|
'user_agent': usage_info['user_agent']
|
295
297
|
})
|
296
|
-
|
298
|
+
|
297
299
|
except Exception as e:
|
298
300
|
logger.warning(f"Failed to track error: {e}")
|
299
|
-
|
301
|
+
|
300
302
|
def _get_client_ip(self, request: HttpRequest) -> str:
|
301
303
|
"""
|
302
304
|
Get client IP address from request.
|
@@ -304,9 +306,9 @@ class UsageTrackingMiddleware(MiddlewareMixin):
|
|
304
306
|
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
|
305
307
|
if x_forwarded_for:
|
306
308
|
return x_forwarded_for.split(',')[0].strip()
|
307
|
-
|
309
|
+
|
308
310
|
x_real_ip = request.META.get('HTTP_X_REAL_IP')
|
309
311
|
if x_real_ip:
|
310
312
|
return x_real_ip
|
311
|
-
|
313
|
+
|
312
314
|
return request.META.get('REMOTE_ADDR', 'unknown')
|
@@ -6,26 +6,25 @@ All models follow the data typing requirements: Django ORM for database layer.
|
|
6
6
|
"""
|
7
7
|
|
8
8
|
# Base models
|
9
|
+
# API Keys
|
10
|
+
from .api_keys import APIKey
|
11
|
+
|
12
|
+
# Balance models
|
13
|
+
from .balance import Transaction, UserBalance
|
9
14
|
from .base import UUIDTimestampedModel
|
10
15
|
|
11
16
|
# Currency models
|
12
17
|
from .currencies import Currency, Network, ProviderCurrency
|
13
18
|
|
14
|
-
# Payment models
|
19
|
+
# Payment models
|
15
20
|
from .payments import UniversalPayment
|
16
21
|
|
17
|
-
# Balance models
|
18
|
-
from .balance import UserBalance, Transaction
|
19
|
-
|
20
22
|
# Subscription models
|
21
|
-
from .subscriptions import
|
23
|
+
from .subscriptions import EndpointGroup, Subscription
|
22
24
|
|
23
25
|
# Tariff models
|
24
26
|
from .tariffs import Tariff, TariffEndpointGroup
|
25
27
|
|
26
|
-
# API Keys
|
27
|
-
from .api_keys import APIKey
|
28
|
-
|
29
28
|
# Export TextChoices for external use
|
30
29
|
PaymentStatus = UniversalPayment.PaymentStatus
|
31
30
|
PaymentProvider = UniversalPayment.PaymentProvider
|
@@ -37,22 +36,22 @@ SubscriptionTier = Subscription.SubscriptionTier
|
|
37
36
|
__all__ = [
|
38
37
|
# Base
|
39
38
|
'UUIDTimestampedModel',
|
40
|
-
|
39
|
+
|
41
40
|
# Currencies
|
42
41
|
'Currency',
|
43
42
|
'Network',
|
44
43
|
'ProviderCurrency',
|
45
|
-
|
44
|
+
|
46
45
|
# Core Models
|
47
46
|
'UniversalPayment',
|
48
47
|
'UserBalance',
|
49
|
-
'Transaction',
|
48
|
+
'Transaction',
|
50
49
|
'Subscription',
|
51
50
|
'EndpointGroup',
|
52
51
|
'Tariff',
|
53
52
|
'TariffEndpointGroup',
|
54
53
|
'APIKey',
|
55
|
-
|
54
|
+
|
56
55
|
# TextChoices
|
57
56
|
'PaymentStatus',
|
58
57
|
'PaymentProvider',
|
@@ -5,11 +5,13 @@ Handles API key management and access control.
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
import secrets
|
8
|
-
|
8
|
+
|
9
9
|
from django.contrib.auth import get_user_model
|
10
|
-
from django.core.validators import MinLengthValidator
|
11
10
|
from django.core.exceptions import ValidationError
|
11
|
+
from django.core.validators import MinLengthValidator
|
12
|
+
from django.db import models
|
12
13
|
from django.utils import timezone
|
14
|
+
|
13
15
|
from .base import UUIDTimestampedModel
|
14
16
|
|
15
17
|
User = get_user_model()
|
@@ -21,61 +23,61 @@ class APIKey(UUIDTimestampedModel):
|
|
21
23
|
|
22
24
|
Provides secure API access with usage tracking and rate limiting.
|
23
25
|
"""
|
24
|
-
|
26
|
+
|
25
27
|
user = models.ForeignKey(
|
26
28
|
User,
|
27
29
|
on_delete=models.CASCADE,
|
28
30
|
related_name='api_keys',
|
29
31
|
help_text="User who owns this API key"
|
30
32
|
)
|
31
|
-
|
33
|
+
|
32
34
|
name = models.CharField(
|
33
35
|
max_length=100,
|
34
36
|
help_text="Human-readable name for this API key"
|
35
37
|
)
|
36
|
-
|
38
|
+
|
37
39
|
key = models.CharField(
|
38
40
|
max_length=64,
|
39
41
|
unique=True,
|
40
42
|
validators=[MinLengthValidator(32)],
|
41
43
|
help_text="The actual API key (auto-generated)"
|
42
44
|
)
|
43
|
-
|
45
|
+
|
44
46
|
# Access control
|
45
47
|
is_active = models.BooleanField(
|
46
48
|
default=True,
|
47
49
|
help_text="Whether this API key is active"
|
48
50
|
)
|
49
|
-
|
51
|
+
|
50
52
|
# Usage tracking
|
51
53
|
total_requests = models.PositiveIntegerField(
|
52
54
|
default=0,
|
53
55
|
help_text="Total number of requests made with this key"
|
54
56
|
)
|
55
|
-
|
57
|
+
|
56
58
|
last_used_at = models.DateTimeField(
|
57
59
|
null=True,
|
58
60
|
blank=True,
|
59
61
|
help_text="When this API key was last used"
|
60
62
|
)
|
61
|
-
|
63
|
+
|
62
64
|
# Expiration
|
63
65
|
expires_at = models.DateTimeField(
|
64
66
|
null=True,
|
65
67
|
blank=True,
|
66
68
|
help_text="When this API key expires (null = never expires)"
|
67
69
|
)
|
68
|
-
|
70
|
+
|
69
71
|
# IP restrictions
|
70
72
|
allowed_ips = models.TextField(
|
71
73
|
blank=True,
|
72
74
|
help_text="Comma-separated list of allowed IP addresses (empty = any IP)"
|
73
75
|
)
|
74
|
-
|
76
|
+
|
75
77
|
# Manager
|
76
78
|
from .managers.api_key_managers import APIKeyManager
|
77
79
|
objects = APIKeyManager()
|
78
|
-
|
80
|
+
|
79
81
|
class Meta:
|
80
82
|
db_table = 'payments_api_keys'
|
81
83
|
verbose_name = 'API Key'
|
@@ -86,45 +88,45 @@ class APIKey(UUIDTimestampedModel):
|
|
86
88
|
models.Index(fields=['user', 'is_active']),
|
87
89
|
models.Index(fields=['expires_at']),
|
88
90
|
]
|
89
|
-
|
91
|
+
|
90
92
|
def __str__(self):
|
91
93
|
return f"{self.user.username} - {self.name}"
|
92
|
-
|
94
|
+
|
93
95
|
def save(self, *args, **kwargs):
|
94
96
|
"""Override save to generate API key."""
|
95
97
|
if not self.key:
|
96
98
|
self.key = self.generate_api_key()
|
97
99
|
super().save(*args, **kwargs)
|
98
|
-
|
100
|
+
|
99
101
|
def clean(self):
|
100
102
|
"""Validate API key data."""
|
101
103
|
if self.expires_at and self.expires_at <= timezone.now():
|
102
104
|
raise ValidationError("Expiration time must be in the future")
|
103
|
-
|
105
|
+
|
104
106
|
@staticmethod
|
105
107
|
def generate_api_key() -> str:
|
106
108
|
"""Generate a secure API key."""
|
107
109
|
return secrets.token_urlsafe(32)
|
108
|
-
|
110
|
+
|
109
111
|
@property
|
110
112
|
def is_expired(self) -> bool:
|
111
113
|
"""Check if API key is expired."""
|
112
114
|
if not self.expires_at:
|
113
115
|
return False
|
114
116
|
return timezone.now() > self.expires_at
|
115
|
-
|
117
|
+
|
116
118
|
@property
|
117
119
|
def is_valid(self) -> bool:
|
118
120
|
"""Check if API key is valid (active and not expired)."""
|
119
121
|
return self.is_active and not self.is_expired
|
120
|
-
|
122
|
+
|
121
123
|
@property
|
122
124
|
def masked_key(self) -> str:
|
123
125
|
"""Get masked version of API key for display."""
|
124
126
|
if len(self.key) < 8:
|
125
127
|
return self.key
|
126
128
|
return f"{self.key[:4]}...{self.key[-4:]}"
|
127
|
-
|
129
|
+
|
128
130
|
@property
|
129
131
|
def days_until_expiry(self) -> int:
|
130
132
|
"""Get days until expiration."""
|
@@ -134,7 +136,7 @@ class APIKey(UUIDTimestampedModel):
|
|
134
136
|
return 0
|
135
137
|
delta = self.expires_at - timezone.now()
|
136
138
|
return max(0, delta.days)
|
137
|
-
|
139
|
+
|
138
140
|
def is_ip_allowed(self, ip_address: str) -> bool:
|
139
141
|
"""
|
140
142
|
Check if IP address is allowed to use this API key.
|
@@ -147,27 +149,27 @@ class APIKey(UUIDTimestampedModel):
|
|
147
149
|
"""
|
148
150
|
if not self.allowed_ips.strip():
|
149
151
|
return True # No restrictions
|
150
|
-
|
152
|
+
|
151
153
|
allowed_list = [ip.strip() for ip in self.allowed_ips.split(',') if ip.strip()]
|
152
154
|
return ip_address in allowed_list
|
153
|
-
|
155
|
+
|
154
156
|
def increment_usage(self, ip_address: str = None):
|
155
157
|
"""Increment usage counter (delegates to manager)."""
|
156
158
|
return self.__class__.objects.increment_api_key_usage(self, ip_address)
|
157
|
-
|
159
|
+
|
158
160
|
def deactivate(self, reason: str = None):
|
159
161
|
"""Deactivate this API key (delegates to manager)."""
|
160
162
|
return self.__class__.objects.deactivate_api_key(self, reason)
|
161
|
-
|
163
|
+
|
162
164
|
def extend_expiry(self, days: int):
|
163
165
|
"""Extend API key expiration (delegates to manager)."""
|
164
166
|
return self.__class__.objects.extend_api_key_expiry(self, days)
|
165
|
-
|
167
|
+
|
166
168
|
@classmethod
|
167
169
|
def create_for_user(cls, user, name="Default API Key", expires_in_days=None):
|
168
170
|
"""Create new API key for user (delegates to manager)."""
|
169
171
|
return cls.objects.create_api_key_for_user(user, name, expires_in_days)
|
170
|
-
|
172
|
+
|
171
173
|
@classmethod
|
172
174
|
def get_valid_key(cls, key_value: str):
|
173
175
|
"""Get valid API key by key value (delegates to manager)."""
|