django-cfg 1.3.11__py3-none-any.whl → 1.4.0__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 +1 -1
- django_cfg/apps/accounts/admin/inlines.py +11 -5
- django_cfg/apps/accounts/admin/user_admin.py +39 -16
- django_cfg/apps/accounts/serializers/profile.py +1 -1
- django_cfg/apps/accounts/services/otp_service.py +18 -11
- django_cfg/apps/accounts/signals.py +15 -24
- django_cfg/apps/accounts/utils/notifications.py +217 -358
- django_cfg/apps/accounts/views/otp.py +2 -2
- django_cfg/apps/accounts/views/webhook.py +1 -1
- django_cfg/apps/agents/core/django_agent.py +1 -1
- django_cfg/apps/api/commands/views.py +66 -83
- django_cfg/apps/api/health/drf_views.py +269 -0
- django_cfg/apps/api/health/serializers.py +45 -0
- django_cfg/apps/api/health/urls.py +6 -1
- django_cfg/apps/knowbase/admin/actions/__init__.py +13 -0
- django_cfg/apps/knowbase/admin/actions/visibility_actions.py +56 -0
- django_cfg/apps/knowbase/admin/document_admin.py +136 -270
- django_cfg/apps/knowbase/admin/helpers/__init__.py +17 -0
- django_cfg/apps/knowbase/admin/helpers/configs.py +72 -0
- django_cfg/apps/knowbase/admin/helpers/display_helpers.py +156 -0
- django_cfg/apps/knowbase/admin/helpers/statistics.py +108 -0
- django_cfg/apps/knowbase/config/constance_fields.py +1 -1
- django_cfg/apps/knowbase/config/settings.py +2 -2
- django_cfg/apps/knowbase/mixins/__init__.py +19 -2
- django_cfg/apps/knowbase/mixins/config/__init__.py +14 -0
- django_cfg/apps/knowbase/mixins/config/defaults.py +75 -0
- django_cfg/apps/knowbase/mixins/config/meta_config.py +120 -0
- django_cfg/apps/knowbase/mixins/creator.py +10 -10
- django_cfg/apps/knowbase/mixins/external_data_mixin.py +105 -403
- django_cfg/apps/knowbase/mixins/generators/__init__.py +16 -0
- django_cfg/apps/knowbase/mixins/generators/content_generator.py +218 -0
- django_cfg/apps/knowbase/mixins/generators/field_analyzer.py +76 -0
- django_cfg/apps/knowbase/mixins/generators/metadata_generator.py +124 -0
- django_cfg/apps/knowbase/mixins/service.py +2 -2
- django_cfg/apps/knowbase/services/archive/__init__.py +1 -0
- django_cfg/apps/knowbase/services/archive/analyzers/__init__.py +17 -0
- django_cfg/apps/knowbase/services/archive/analyzers/complexity_analyzer.py +33 -0
- django_cfg/apps/knowbase/services/archive/analyzers/purpose_detector.py +36 -0
- django_cfg/apps/knowbase/services/archive/analyzers/quality_analyzer.py +39 -0
- django_cfg/apps/knowbase/services/archive/analyzers/tag_generator.py +103 -0
- django_cfg/apps/knowbase/services/archive/chunking/__init__.py +19 -0
- django_cfg/apps/knowbase/services/archive/chunking/base.py +81 -0
- django_cfg/apps/knowbase/services/archive/chunking/json_chunker.py +62 -0
- django_cfg/apps/knowbase/services/archive/chunking/markdown_chunker.py +107 -0
- django_cfg/apps/knowbase/services/archive/chunking/python_chunker.py +248 -0
- django_cfg/apps/knowbase/services/archive/chunking/text_chunker.py +70 -0
- django_cfg/apps/knowbase/services/archive/chunking_service.py +110 -729
- django_cfg/apps/knowbase/services/archive/context/__init__.py +14 -0
- django_cfg/apps/knowbase/services/archive/context/builders.py +220 -0
- django_cfg/apps/knowbase/services/archive/context/models.py +38 -0
- django_cfg/apps/knowbase/services/embedding/models.py +18 -14
- django_cfg/apps/knowbase/services/embedding/processors.py +6 -3
- django_cfg/apps/knowbase/tasks/document_processing.py +11 -3
- django_cfg/apps/leads/tests.py +1 -1
- django_cfg/apps/payments/admin/api_keys_admin.py +1 -1
- django_cfg/apps/payments/admin/balance_admin.py +1 -1
- django_cfg/apps/payments/admin/currencies_admin.py +1 -1
- django_cfg/apps/payments/admin/payments_admin.py +1 -1
- django_cfg/apps/payments/admin/subscriptions_admin.py +1 -1
- django_cfg/apps/payments/admin_interface/templates/payments/base.html +59 -126
- django_cfg/apps/payments/admin_interface/views/api/payments.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/stats.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/users.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +1 -1
- django_cfg/apps/payments/admin_interface/views/api/webhook_public.py +1 -1
- django_cfg/apps/payments/admin_interface/views/base.py +29 -2
- django_cfg/apps/payments/apps.py +1 -1
- django_cfg/apps/payments/config/django_cfg_integration.py +2 -2
- django_cfg/apps/payments/config/helpers.py +3 -2
- django_cfg/apps/payments/management/commands/cleanup_expired_data.py +1 -1
- django_cfg/apps/payments/management/commands/currency_stats.py +1 -1
- django_cfg/apps/payments/management/commands/manage_currencies.py +1 -1
- django_cfg/apps/payments/management/commands/manage_providers.py +1 -1
- django_cfg/apps/payments/management/commands/process_pending_payments.py +1 -1
- django_cfg/apps/payments/management/commands/test_providers.py +1 -1
- django_cfg/apps/payments/middleware/api_access.py +1 -1
- django_cfg/apps/payments/middleware/rate_limiting.py +1 -1
- django_cfg/apps/payments/middleware/usage_tracking.py +1 -1
- django_cfg/apps/payments/models/balance.py +2 -2
- django_cfg/apps/payments/models/managers/api_key_managers.py +1 -1
- django_cfg/apps/payments/models/managers/balance_managers.py +1 -1
- django_cfg/apps/payments/models/managers/currency_managers.py +1 -1
- django_cfg/apps/payments/models/managers/payment_managers.py +1 -1
- django_cfg/apps/payments/models/managers/subscription_managers.py +1 -1
- django_cfg/apps/payments/models/payments.py +2 -2
- django_cfg/apps/payments/services/cache_service/__init__.py +1 -1
- django_cfg/apps/payments/services/cache_service/simple_cache.py +10 -5
- django_cfg/apps/payments/services/core/base.py +1 -1
- django_cfg/apps/payments/services/core/currency/__init__.py +13 -0
- django_cfg/apps/payments/services/core/currency/currency_converter.py +57 -0
- django_cfg/apps/payments/services/core/currency/currency_validator.py +61 -0
- django_cfg/apps/payments/services/core/operations/__init__.py +15 -0
- django_cfg/apps/payments/services/core/operations/payment_canceller.py +100 -0
- django_cfg/apps/payments/services/core/operations/payment_creator.py +196 -0
- django_cfg/apps/payments/services/core/operations/status_checker.py +100 -0
- django_cfg/apps/payments/services/core/payment_service.py +124 -612
- django_cfg/apps/payments/services/core/providers/__init__.py +13 -0
- django_cfg/apps/payments/services/core/providers/provider_client.py +132 -0
- django_cfg/apps/payments/services/core/providers/status_mapper.py +89 -0
- django_cfg/apps/payments/services/core/utils/__init__.py +13 -0
- django_cfg/apps/payments/services/core/utils/data_converter.py +48 -0
- django_cfg/apps/payments/services/core/utils/statistics_calculator.py +69 -0
- django_cfg/apps/payments/services/providers/base.py +1 -1
- django_cfg/apps/payments/services/providers/nowpayments/__init__.py +3 -3
- django_cfg/apps/payments/services/providers/nowpayments/parsers/__init__.py +9 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/__init__.py +23 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/constants.py +23 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/currency_names.py +244 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/patterns.py +511 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers/parser.py +168 -0
- django_cfg/apps/payments/services/providers/nowpayments/provider.py +1 -1
- django_cfg/apps/payments/services/providers/nowpayments/sync.py +1 -1
- django_cfg/apps/payments/services/providers/registry.py +1 -1
- django_cfg/apps/payments/services/providers/sync_service.py +1 -1
- django_cfg/apps/payments/signals/__init__.py +1 -1
- django_cfg/apps/payments/signals/api_key_signals.py +1 -1
- django_cfg/apps/payments/signals/balance_signals.py +1 -1
- django_cfg/apps/payments/signals/payment_signals.py +1 -1
- django_cfg/apps/payments/signals/subscription_signals.py +1 -1
- django_cfg/apps/payments/views/api/api_keys.py +1 -1
- django_cfg/apps/payments/views/api/balances.py +1 -1
- django_cfg/apps/payments/views/api/base.py +1 -1
- django_cfg/apps/payments/views/api/currencies.py +1 -1
- django_cfg/apps/payments/views/api/payments.py +1 -1
- django_cfg/apps/payments/views/api/subscriptions.py +1 -1
- django_cfg/apps/payments/views/api/webhooks.py +1 -1
- django_cfg/apps/payments/views/serializers/api_keys.py +1 -1
- django_cfg/apps/payments/views/serializers/balances.py +1 -1
- django_cfg/apps/payments/views/serializers/currencies.py +1 -1
- django_cfg/apps/payments/views/serializers/payments.py +1 -1
- django_cfg/apps/payments/views/serializers/subscriptions.py +1 -1
- django_cfg/apps/payments/views/serializers/webhooks.py +1 -1
- django_cfg/apps/support/admin/support_admin.py +21 -13
- django_cfg/apps/support/templates/support/chat/access_denied.html +21 -27
- django_cfg/apps/support/templates/support/chat/ticket_chat.html +183 -254
- django_cfg/apps/support/utils/support_email_service.py +1 -1
- django_cfg/apps/tasks/templates/tasks/layout/base.html +20 -115
- django_cfg/apps/tasks/utils/simulator.py +1 -1
- django_cfg/apps/tasks/views/dashboard.py +33 -3
- django_cfg/apps/urls.py +5 -1
- django_cfg/cli/README.md +57 -471
- django_cfg/cli/commands/create_project.py +140 -529
- django_cfg/cli/main.py +13 -10
- django_cfg/core/__init__.py +63 -6
- django_cfg/core/base/__init__.py +5 -0
- django_cfg/core/base/config_model.py +652 -0
- django_cfg/core/builders/__init__.py +11 -0
- django_cfg/core/builders/apps_builder.py +258 -0
- django_cfg/core/builders/middleware_builder.py +115 -0
- django_cfg/core/builders/security_builder.py +96 -0
- django_cfg/core/config.py +20 -892
- django_cfg/core/constants.py +69 -0
- django_cfg/core/environment/__init__.py +9 -0
- django_cfg/core/exceptions.py +45 -298
- django_cfg/core/generation/__init__.py +51 -0
- django_cfg/core/generation/core_generators/__init__.py +0 -0
- django_cfg/core/generation/core_generators/settings.py +90 -0
- django_cfg/core/generation/core_generators/static.py +82 -0
- django_cfg/core/generation/core_generators/templates.py +141 -0
- django_cfg/core/generation/data_generators/__init__.py +15 -0
- django_cfg/core/generation/data_generators/cache.py +132 -0
- django_cfg/core/generation/data_generators/database.py +117 -0
- django_cfg/core/generation/generation.py +92 -0
- django_cfg/core/generation/integration_generators/__init__.py +21 -0
- django_cfg/core/generation/integration_generators/api.py +237 -0
- django_cfg/core/generation/integration_generators/sessions.py +65 -0
- django_cfg/core/generation/integration_generators/tailwind.py +54 -0
- django_cfg/core/generation/integration_generators/tasks.py +92 -0
- django_cfg/core/generation/integration_generators/third_party.py +144 -0
- django_cfg/core/generation/orchestrator.py +285 -0
- django_cfg/core/generation/protocols.py +30 -0
- django_cfg/core/generation/security_generators/__init__.py +0 -0
- django_cfg/core/generation/utility_generators/__init__.py +24 -0
- django_cfg/core/generation/utility_generators/email.py +58 -0
- django_cfg/core/generation/utility_generators/i18n.py +66 -0
- django_cfg/core/generation/utility_generators/limits.py +58 -0
- django_cfg/core/generation/utility_generators/logging.py +66 -0
- django_cfg/core/generation/utility_generators/security.py +101 -0
- django_cfg/core/generation/utils/__init__.py +0 -0
- django_cfg/core/generation/utils/helpers.py +32 -0
- django_cfg/core/integration/__init__.py +18 -25
- django_cfg/core/integration/display/startup.py +146 -133
- django_cfg/core/integration/url_integration.py +13 -2
- django_cfg/core/services/__init__.py +5 -0
- django_cfg/core/services/config_service.py +121 -0
- django_cfg/core/state/__init__.py +9 -0
- django_cfg/core/state/registry.py +84 -0
- django_cfg/core/types/__init__.py +15 -0
- django_cfg/core/types/aliases.py +15 -0
- django_cfg/core/types/enums.py +49 -0
- django_cfg/dashboard/DEBUG_README.md +105 -0
- django_cfg/dashboard/REFACTORING_SUMMARY.md +237 -0
- django_cfg/dashboard/__init__.py +24 -0
- django_cfg/dashboard/components.py +308 -0
- django_cfg/dashboard/debug.py +176 -0
- django_cfg/dashboard/management/__init__.py +0 -0
- django_cfg/dashboard/management/commands/__init__.py +0 -0
- django_cfg/dashboard/management/commands/debug_dashboard.py +109 -0
- django_cfg/dashboard/sections/__init__.py +1 -0
- django_cfg/dashboard/sections/base.py +128 -0
- django_cfg/dashboard/sections/commands.py +32 -0
- django_cfg/dashboard/sections/overview.py +394 -0
- django_cfg/dashboard/sections/stats.py +48 -0
- django_cfg/dashboard/sections/system.py +73 -0
- django_cfg/management/commands/check_settings.py +6 -2
- django_cfg/management/commands/clear_constance.py +6 -1
- django_cfg/management/commands/create_token.py +5 -4
- django_cfg/management/commands/generate.py +5 -0
- django_cfg/management/commands/list_urls.py +7 -2
- django_cfg/management/commands/migrate_all.py +6 -2
- django_cfg/management/commands/migrator.py +6 -1
- django_cfg/management/commands/rundramatiq.py +6 -1
- django_cfg/management/commands/rundramatiq_simulator.py +11 -4
- django_cfg/management/commands/runserver_ngrok.py +9 -7
- django_cfg/management/commands/script.py +25 -21
- django_cfg/management/commands/show_config.py +6 -1
- django_cfg/management/commands/show_urls.py +8 -3
- django_cfg/management/commands/superuser.py +5 -4
- django_cfg/management/commands/task_clear.py +8 -3
- django_cfg/management/commands/task_status.py +8 -3
- django_cfg/management/commands/test_email.py +6 -1
- django_cfg/management/commands/test_telegram.py +6 -1
- django_cfg/management/commands/test_twilio.py +6 -1
- django_cfg/management/commands/tree.py +7 -4
- django_cfg/models/__init__.py +88 -3
- django_cfg/models/api/__init__.py +27 -0
- django_cfg/models/{api.py → api/config.py} +1 -1
- django_cfg/models/api/drf/__init__.py +21 -0
- django_cfg/models/api/drf/config.py +101 -0
- django_cfg/models/api/drf/redoc.py +31 -0
- django_cfg/models/api/drf/spectacular.py +129 -0
- django_cfg/models/api/drf/swagger.py +59 -0
- django_cfg/models/{api_keys.py → api/keys.py} +16 -6
- django_cfg/models/{limits.py → api/limits.py} +0 -1
- django_cfg/models/base/__init__.py +14 -0
- django_cfg/models/django/__init__.py +16 -0
- django_cfg/models/{constance.py → django/constance.py} +1 -1
- django_cfg/models/{environment.py → django/environment.py} +1 -1
- django_cfg/models/infrastructure/__init__.py +17 -0
- django_cfg/models/{cache.py → infrastructure/cache.py} +3 -2
- django_cfg/models/infrastructure/database/__init__.py +22 -0
- django_cfg/models/infrastructure/database/config.py +265 -0
- django_cfg/models/infrastructure/database/converters.py +91 -0
- django_cfg/models/infrastructure/database/parsers.py +96 -0
- django_cfg/models/infrastructure/database/routing.py +85 -0
- django_cfg/models/infrastructure/database/validators.py +170 -0
- django_cfg/models/{logging.py → infrastructure/logging.py} +1 -1
- django_cfg/models/{security.py → infrastructure/security.py} +2 -2
- django_cfg/models/ngrok/__init__.py +11 -0
- django_cfg/models/ngrok/auth.py +37 -0
- django_cfg/models/ngrok/config.py +77 -0
- django_cfg/models/ngrok/tunnel.py +35 -0
- django_cfg/models/payments/__init__.py +20 -0
- django_cfg/models/payments/api_keys.py +57 -0
- django_cfg/models/{payments.py → payments/config.py} +56 -154
- django_cfg/models/payments/providers/__init__.py +15 -0
- django_cfg/models/payments/providers/base.py +25 -0
- django_cfg/models/payments/providers/nowpayments.py +48 -0
- django_cfg/models/services/__init__.py +18 -0
- django_cfg/models/services/base.py +65 -0
- django_cfg/models/{email.py → services/email.py} +1 -1
- django_cfg/models/services/telegram.py +172 -0
- django_cfg/models/tasks/__init__.py +51 -0
- django_cfg/models/tasks/backends.py +250 -0
- django_cfg/models/tasks/config.py +314 -0
- django_cfg/models/tasks/utils.py +174 -0
- django_cfg/modules/base.py +18 -3
- django_cfg/modules/django_admin/decorators/actions.py +1 -1
- django_cfg/modules/django_admin/decorators/display.py +1 -1
- django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +1 -1
- django_cfg/modules/django_cfg_rpc_client/README.md +346 -0
- django_cfg/modules/django_cfg_rpc_client/__init__.py +51 -0
- django_cfg/modules/django_cfg_rpc_client/client.py +540 -0
- django_cfg/modules/django_cfg_rpc_client/config.py +207 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/README.md +517 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/UNFOLD_INTEGRATION.md +439 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/__init__.py +11 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/apps.py +22 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/monitor.py +435 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/static/django_cfg_rpc_dashboard/js/dashboard.js +373 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/templates/django_cfg_rpc_dashboard/base.html +76 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/templates/django_cfg_rpc_dashboard/dashboard.html +200 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/urls.py +22 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/urls_admin.py +9 -0
- django_cfg/modules/django_cfg_rpc_client/dashboard/views.py +251 -0
- django_cfg/modules/django_cfg_rpc_client/exceptions.py +201 -0
- django_cfg/modules/django_drf_theme/CHANGELOG.md +210 -0
- django_cfg/modules/django_drf_theme/EXAMPLE.md +465 -0
- django_cfg/modules/django_drf_theme/IMPLEMENTATION.md +232 -0
- django_cfg/modules/django_drf_theme/README.md +207 -0
- django_cfg/modules/django_drf_theme/TAILWIND_CDN_GUIDE.md +274 -0
- django_cfg/modules/django_drf_theme/__init__.py +23 -0
- django_cfg/modules/django_drf_theme/apps.py +15 -0
- django_cfg/modules/django_drf_theme/renderers.py +58 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/api.html +375 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/base.html +938 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/forms/filter_form.html +132 -0
- django_cfg/modules/django_drf_theme/templates/rest_framework/tailwind/forms/raw_data_form.html +123 -0
- django_cfg/modules/django_drf_theme/templatetags/__init__.py +1 -0
- django_cfg/modules/django_drf_theme/templatetags/tailwind_tags.py +57 -0
- django_cfg/modules/django_email/__init__.py +14 -0
- django_cfg/modules/{django_email.py → django_email/service.py} +78 -113
- django_cfg/modules/django_email/utils.py +40 -0
- django_cfg/modules/django_health/__init__.py +9 -0
- django_cfg/modules/{django_health.py → django_health/service.py} +23 -21
- django_cfg/modules/django_llm/llm/client.py +155 -550
- django_cfg/modules/django_llm/llm/embeddings/__init__.py +13 -0
- django_cfg/modules/django_llm/llm/embeddings/mock_embedder.py +106 -0
- django_cfg/modules/django_llm/llm/embeddings/openai_embedder.py +79 -0
- django_cfg/modules/django_llm/llm/models_api/__init__.py +9 -0
- django_cfg/modules/django_llm/llm/models_api/models_query.py +163 -0
- django_cfg/modules/django_llm/llm/providers/__init__.py +15 -0
- django_cfg/modules/django_llm/llm/providers/config_builder.py +103 -0
- django_cfg/modules/django_llm/llm/providers/provider_manager.py +148 -0
- django_cfg/modules/django_llm/llm/providers/provider_selector.py +60 -0
- django_cfg/modules/django_llm/llm/requests/__init__.py +15 -0
- django_cfg/modules/django_llm/llm/requests/cache_manager.py +170 -0
- django_cfg/modules/django_llm/llm/requests/chat_handler.py +199 -0
- django_cfg/modules/django_llm/llm/requests/embedding_handler.py +113 -0
- django_cfg/modules/django_llm/llm/responses/__init__.py +9 -0
- django_cfg/modules/django_llm/llm/responses/response_builder.py +131 -0
- django_cfg/modules/django_llm/llm/stats/__init__.py +9 -0
- django_cfg/modules/django_llm/llm/stats/stats_manager.py +107 -0
- django_cfg/modules/django_llm/translator/detectors/__init__.py +13 -0
- django_cfg/modules/django_llm/translator/detectors/language_detector.py +90 -0
- django_cfg/modules/django_llm/translator/detectors/script_detector.py +153 -0
- django_cfg/modules/django_llm/translator/stats/__init__.py +11 -0
- django_cfg/modules/django_llm/translator/stats/stats_tracker.py +85 -0
- django_cfg/modules/django_llm/translator/translator.py +150 -603
- django_cfg/modules/django_llm/translator/translators/__init__.py +15 -0
- django_cfg/modules/django_llm/translator/translators/json_translator.py +316 -0
- django_cfg/modules/django_llm/translator/translators/text_translator.py +139 -0
- django_cfg/modules/django_llm/translator/utils/__init__.py +13 -0
- django_cfg/modules/django_llm/translator/utils/prompt_builder.py +110 -0
- django_cfg/modules/django_llm/translator/utils/text_utils.py +114 -0
- django_cfg/modules/django_logging/FIXES_SUMMARY.md +276 -0
- django_cfg/modules/django_logging/LOGGING_GUIDE.md +504 -0
- django_cfg/modules/django_logging/__init__.py +14 -0
- django_cfg/modules/{django_logger.py → django_logging/django_logger.py} +13 -13
- django_cfg/modules/{logger.py → django_logging/logger.py} +14 -4
- django_cfg/modules/django_ngrok/__init__.py +39 -0
- django_cfg/modules/{django_ngrok.py → django_ngrok/service.py} +14 -42
- django_cfg/modules/django_rpc_old/POETRY.md +344 -0
- django_cfg/modules/django_rpc_old/README.md +397 -0
- django_cfg/modules/django_rpc_old/TESTING.md +358 -0
- django_cfg/modules/django_rpc_old/__init__.py +39 -0
- django_cfg/modules/django_rpc_old/client.py +531 -0
- django_cfg/modules/django_rpc_old/config.py +279 -0
- django_cfg/modules/django_rpc_old/exceptions.py +172 -0
- django_cfg/modules/django_tailwind/README.md +478 -0
- django_cfg/modules/django_tailwind/__init__.py +7 -0
- django_cfg/modules/django_tailwind/apps.py +10 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/app.html +5 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/base.html +117 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/components/navbar.html +124 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/components/theme_toggle.html +54 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/components/user_menu.html +116 -0
- django_cfg/modules/django_tailwind/templates/django_tailwind/simple.html +46 -0
- django_cfg/modules/django_tailwind/templatetags/__init__.py +1 -0
- django_cfg/modules/django_tailwind/templatetags/tailwind_info.py +185 -0
- django_cfg/modules/django_tasks/__init__.py +29 -0
- django_cfg/modules/django_tasks/factory.py +127 -0
- django_cfg/modules/{django_tasks.py → django_tasks/service.py} +45 -274
- django_cfg/modules/django_tasks/settings.py +107 -0
- django_cfg/modules/django_telegram/__init__.py +29 -0
- django_cfg/modules/{django_telegram.py → django_telegram/service.py} +45 -113
- django_cfg/modules/django_telegram/utils.py +62 -0
- django_cfg/modules/django_twilio/__init__.py +54 -107
- django_cfg/modules/django_twilio/_imports.py +30 -0
- django_cfg/modules/django_twilio/base.py +192 -0
- django_cfg/modules/django_twilio/email_otp.py +227 -0
- django_cfg/modules/django_twilio/sendgrid_service.py +1 -1
- django_cfg/modules/django_twilio/simple_service.py +1 -2
- django_cfg/modules/django_twilio/sms.py +94 -0
- django_cfg/modules/django_twilio/twilio_service.py +2 -3
- django_cfg/modules/django_twilio/unified.py +310 -0
- django_cfg/modules/django_twilio/utils.py +190 -0
- django_cfg/modules/django_twilio/whatsapp.py +137 -0
- django_cfg/modules/django_unfold/callbacks/base.py +198 -7
- django_cfg/modules/django_unfold/callbacks/main.py +102 -10
- django_cfg/modules/django_unfold/dashboard.py +65 -43
- django_cfg/modules/django_unfold/models/config.py +13 -12
- django_cfg/modules/django_unfold/models/navigation.py +8 -3
- django_cfg/modules/django_unfold/models/tabs.py +2 -2
- django_cfg/modules/django_unfold/templates/unfold/helpers/app_list.html +102 -0
- django_cfg/registry/core.py +24 -26
- django_cfg/registry/modules.py +5 -2
- django_cfg/registry/services.py +20 -3
- django_cfg/registry/third_party.py +8 -8
- django_cfg/static/admin/css/dashboard.css +260 -0
- django_cfg/static/admin/js/commands.js +171 -0
- django_cfg/static/admin/js/dashboard.js +126 -0
- django_cfg/templates/admin/components/management_commands.js +375 -0
- django_cfg/templates/admin/components/progress_bar.html +18 -23
- django_cfg/templates/admin/index.html +48 -20
- django_cfg/templates/admin/index_new.html +106 -0
- django_cfg/templates/admin/layouts/base_dashboard.html +60 -0
- django_cfg/templates/admin/layouts/dashboard_with_tabs.html +1 -20
- django_cfg/templates/admin/sections/commands_section.html +626 -0
- django_cfg/templates/admin/sections/overview_section.html +112 -0
- django_cfg/templates/admin/sections/stats_section.html +35 -0
- django_cfg/templates/admin/sections/system_section.html +99 -0
- django_cfg/templates/admin/snippets/components/CHARTS_GUIDE.md +322 -0
- django_cfg/templates/admin/snippets/components/activity_tracker.html +85 -47
- django_cfg/templates/admin/snippets/components/charts_section.html +154 -64
- django_cfg/templates/admin/snippets/components/django_commands.html +3 -3
- django_cfg/templates/admin/snippets/components/recent_activity_improved.html +25 -0
- django_cfg/templates/admin/snippets/components/recent_users_table.html +1 -1
- django_cfg/templates/admin/snippets/components/system_metrics.html +179 -93
- django_cfg/templates/admin/snippets/zones/zones_table.html +2 -2
- django_cfg/templatetags/django_cfg.py +7 -1
- django_cfg/utils/smart_defaults.py +4 -4
- django_cfg-1.4.0.dist-info/METADATA +920 -0
- {django_cfg-1.3.11.dist-info → django_cfg-1.4.0.dist-info}/RECORD +425 -196
- django_cfg/apps/accounts/utils/auth_email_service.py +0 -84
- django_cfg/apps/payments/services/providers/nowpayments/parsers.py +0 -879
- django_cfg/core/generation.py +0 -621
- django_cfg/management/commands/validate_config.py +0 -189
- django_cfg/models/database.py +0 -480
- django_cfg/models/drf.py +0 -272
- django_cfg/models/ngrok.py +0 -122
- django_cfg/models/services.py +0 -440
- django_cfg/models/tasks.py +0 -550
- django_cfg/modules/django_twilio/service.py +0 -942
- django_cfg/template_archive/django_sample.zip +0 -0
- django_cfg/templates/rest_framework/api.html +0 -12
- django_cfg/utils/toolkit.py +0 -703
- django_cfg-1.3.11.dist-info/METADATA +0 -1029
- /django_cfg/apps/accounts/management/commands/{test_otp.py → otp_test.py} +0 -0
- /django_cfg/core/{environment.py → environment/detector.py} +0 -0
- /django_cfg/models/{cors.py → api/cors.py} +0 -0
- /django_cfg/models/{jwt.py → api/jwt.py} +0 -0
- /django_cfg/models/{base.py → base/config.py} +0 -0
- /django_cfg/models/{cfg.py → base/module.py} +0 -0
- /django_cfg/models/{revolution.py → django/revolution.py} +0 -0
- /django_cfg/modules/{dramatiq_setup.py → django_tasks/dramatiq_setup.py} +0 -0
- {django_cfg-1.3.11.dist-info → django_cfg-1.4.0.dist-info}/WHEEL +0 -0
- {django_cfg-1.3.11.dist-info → django_cfg-1.4.0.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.3.11.dist-info → django_cfg-1.4.0.dist-info}/licenses/LICENSE +0 -0
@@ -8,7 +8,7 @@ from django.contrib.auth import get_user_model
|
|
8
8
|
from django_cfg.modules.django_telegram import DjangoTelegram
|
9
9
|
from django_cfg.modules.django_email import DjangoEmailService
|
10
10
|
from django_cfg.modules.django_twilio import SimpleTwilioService
|
11
|
-
from django_cfg.core.
|
11
|
+
from django_cfg.core.state import get_current_config
|
12
12
|
|
13
13
|
# Get config once
|
14
14
|
config = get_current_config()
|
@@ -32,30 +32,25 @@ class AccountNotifications:
|
|
32
32
|
template_name: str = "emails/base_email",
|
33
33
|
):
|
34
34
|
"""Private method for sending templated emails."""
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
)
|
55
|
-
return True
|
56
|
-
except Exception as e:
|
57
|
-
logger.error(f"Failed to send email to {user.email}: {e}")
|
58
|
-
return False
|
35
|
+
email_service = DjangoEmailService()
|
36
|
+
|
37
|
+
# Prepare context for template
|
38
|
+
context = {
|
39
|
+
"user": user,
|
40
|
+
"subject": subject,
|
41
|
+
"main_text": main_text,
|
42
|
+
"main_html_content": main_html_content,
|
43
|
+
"secondary_text": secondary_text,
|
44
|
+
"button_text": button_text,
|
45
|
+
"button_url": button_url,
|
46
|
+
}
|
47
|
+
|
48
|
+
email_service.send_template(
|
49
|
+
subject=subject,
|
50
|
+
template_name=template_name,
|
51
|
+
context=context,
|
52
|
+
recipient_list=[user.email],
|
53
|
+
)
|
59
54
|
|
60
55
|
# === EMAIL NOTIFICATIONS ===
|
61
56
|
|
@@ -63,7 +58,7 @@ class AccountNotifications:
|
|
63
58
|
def send_welcome_email(user, send_email=True, send_telegram=True):
|
64
59
|
"""Send welcome email and telegram notification for new user"""
|
65
60
|
if send_email:
|
66
|
-
|
61
|
+
AccountNotifications._send_email(
|
67
62
|
user=user,
|
68
63
|
subject=f"Welcome to {config.project_name}",
|
69
64
|
main_text=f"Welcome {user.username}! Your account has been successfully created.",
|
@@ -72,35 +67,31 @@ class AccountNotifications:
|
|
72
67
|
button_text="Go to Dashboard",
|
73
68
|
button_url=f"{config.site_url}/dashboard",
|
74
69
|
)
|
75
|
-
|
76
|
-
|
77
|
-
|
70
|
+
logger.info(f"Welcome email sent to {user.email}")
|
71
|
+
|
78
72
|
if send_telegram:
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
logger.info(f"Welcome telegram notification sent for {user.email}")
|
91
|
-
except Exception as e:
|
92
|
-
logger.error(f"Failed to send welcome telegram notification: {e}")
|
73
|
+
DjangoTelegram.send_success(
|
74
|
+
"👤 New User Registered!",
|
75
|
+
{
|
76
|
+
"email": user.email,
|
77
|
+
"username": user.username,
|
78
|
+
"date_joined": user.date_joined.strftime("%Y-%m-%d %H:%M"),
|
79
|
+
"is_active": user.is_active,
|
80
|
+
"is_staff": user.is_staff
|
81
|
+
}
|
82
|
+
)
|
83
|
+
logger.info(f"Welcome telegram notification sent for {user.email}")
|
93
84
|
|
94
85
|
@staticmethod
|
95
86
|
def send_profile_update_notification(user, changes, send_email=True, send_telegram=True):
|
96
87
|
"""Send profile update notification"""
|
97
88
|
if not changes:
|
98
89
|
return
|
99
|
-
|
90
|
+
|
100
91
|
change_text = ", ".join(changes)
|
101
|
-
|
92
|
+
|
102
93
|
if send_email:
|
103
|
-
|
94
|
+
AccountNotifications._send_email(
|
104
95
|
user=user,
|
105
96
|
subject=f"Security Alert: Profile Updated ⚠️",
|
106
97
|
main_text="A security alert has been triggered for your account.",
|
@@ -108,30 +99,26 @@ class AccountNotifications:
|
|
108
99
|
secondary_text=f"Details: Your {change_text} has been updated. If this wasn't you, please contact support immediately.",
|
109
100
|
button_text="Review Account",
|
110
101
|
)
|
111
|
-
|
112
|
-
|
113
|
-
|
102
|
+
logger.info(f"Profile update notification sent to {user.email}")
|
103
|
+
|
114
104
|
if send_telegram:
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
logger.info(f"Profile update telegram notification sent for {user.email}")
|
126
|
-
except Exception as e:
|
127
|
-
logger.error(f"Failed to send profile update telegram notification: {e}")
|
105
|
+
DjangoTelegram.send_warning(
|
106
|
+
"👤 User Profile Updated",
|
107
|
+
{
|
108
|
+
"user": user.email,
|
109
|
+
"changes": change_text,
|
110
|
+
"timestamp": timezone.now().strftime("%Y-%m-%d %H:%M:%S UTC"),
|
111
|
+
"user_id": user.id
|
112
|
+
}
|
113
|
+
)
|
114
|
+
logger.info(f"Profile update telegram notification sent for {user.email}")
|
128
115
|
|
129
116
|
@staticmethod
|
130
117
|
def send_account_status_change(user, status_type, reason=None, send_email=True, send_telegram=True):
|
131
118
|
"""Send account status change notification (activated/deactivated)"""
|
132
119
|
if send_email:
|
133
120
|
if status_type == "activated":
|
134
|
-
|
121
|
+
AccountNotifications._send_email(
|
135
122
|
user=user,
|
136
123
|
subject=f"Account Activated - {config.project_name} ✅",
|
137
124
|
main_text="Your account has been activated and is now ready to use!",
|
@@ -140,11 +127,10 @@ class AccountNotifications:
|
|
140
127
|
button_text="Access Dashboard",
|
141
128
|
button_url=f"{config.site_url}/dashboard",
|
142
129
|
)
|
143
|
-
|
144
|
-
|
145
|
-
|
130
|
+
logger.info(f"Account activation email sent to {user.email}")
|
131
|
+
|
146
132
|
elif status_type == "deactivated":
|
147
|
-
|
133
|
+
AccountNotifications._send_email(
|
148
134
|
user=user,
|
149
135
|
subject=f"Account Status Update - {config.project_name} ⚠️",
|
150
136
|
main_text="Your account status has been updated.",
|
@@ -152,32 +138,28 @@ class AccountNotifications:
|
|
152
138
|
secondary_text=f"Reason: {reason or 'Account deactivated by administrator'}\nIf you believe this is an error, please contact our support team.",
|
153
139
|
button_text="Contact Support",
|
154
140
|
)
|
155
|
-
|
156
|
-
|
157
|
-
|
141
|
+
logger.info(f"Account deactivation email sent to {user.email}")
|
142
|
+
|
158
143
|
if send_telegram:
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
logger.info(f"Account status change telegram notification sent for {user.email}")
|
179
|
-
except Exception as e:
|
180
|
-
logger.error(f"Failed to send status change telegram notification: {e}")
|
144
|
+
emoji = "✅" if status_type == "activated" else "❌"
|
145
|
+
title = f"{emoji} Account {status_type.title()}"
|
146
|
+
|
147
|
+
data = {
|
148
|
+
"user": user.email,
|
149
|
+
"status": status_type,
|
150
|
+
"timestamp": timezone.now().strftime("%Y-%m-%d %H:%M:%S UTC"),
|
151
|
+
"user_id": user.id
|
152
|
+
}
|
153
|
+
|
154
|
+
if reason:
|
155
|
+
data["reason"] = reason
|
156
|
+
|
157
|
+
if status_type == "activated":
|
158
|
+
DjangoTelegram.send_success(title, data)
|
159
|
+
else:
|
160
|
+
DjangoTelegram.send_warning(title, data)
|
161
|
+
|
162
|
+
logger.info(f"Account status change telegram notification sent for {user.email}")
|
181
163
|
|
182
164
|
@staticmethod
|
183
165
|
def send_login_notification(user, ip_address=None, send_email=False, send_telegram=True):
|
@@ -185,7 +167,7 @@ class AccountNotifications:
|
|
185
167
|
if send_email:
|
186
168
|
login_time = timezone.now().strftime("%Y-%m-%d %H:%M:%S UTC")
|
187
169
|
ip_text = f" from IP address {ip_address}" if ip_address else ""
|
188
|
-
|
170
|
+
AccountNotifications._send_email(
|
189
171
|
user=user,
|
190
172
|
subject=f"Login Notification - {config.project_name} 🔐",
|
191
173
|
main_text=f"We detected a login to your account at {login_time}{ip_text}.",
|
@@ -193,126 +175,103 @@ class AccountNotifications:
|
|
193
175
|
secondary_text="If this wasn't you, please secure your account immediately and contact support.",
|
194
176
|
button_text="Review Account Security",
|
195
177
|
)
|
196
|
-
|
197
|
-
|
198
|
-
|
178
|
+
logger.info(f"Login notification email sent to {user.email}")
|
179
|
+
|
199
180
|
if send_telegram:
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
logger.info(f"Login telegram notification sent for {user.email}")
|
212
|
-
except Exception as e:
|
213
|
-
logger.error(f"Failed to send login telegram notification: {e}")
|
181
|
+
DjangoTelegram.send_info(
|
182
|
+
"🔐 User Login",
|
183
|
+
{
|
184
|
+
"user": user.email,
|
185
|
+
"username": user.username,
|
186
|
+
"login_time": timezone.now().strftime("%Y-%m-%d %H:%M:%S UTC"),
|
187
|
+
"ip_address": ip_address or "Unknown",
|
188
|
+
"user_id": user.id
|
189
|
+
}
|
190
|
+
)
|
191
|
+
logger.info(f"Login telegram notification sent for {user.email}")
|
214
192
|
|
215
193
|
@staticmethod
|
216
194
|
def send_otp_notification(user, otp_code, is_new_user=False, source_url=None, channel='email', send_email=True, send_telegram=True):
|
217
195
|
"""Send OTP notification via email"""
|
218
196
|
if send_email:
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
logger.info(f"OTP email sent to {user.email}")
|
233
|
-
except Exception as e:
|
234
|
-
logger.error(f"Failed to send OTP email to {user.email}: {e}")
|
235
|
-
|
197
|
+
from ..services.otp_service import OTPService
|
198
|
+
otp_link = OTPService._get_otp_url(otp_code)
|
199
|
+
AccountNotifications._send_email(
|
200
|
+
user=user,
|
201
|
+
subject=f"Your OTP code: {otp_code}",
|
202
|
+
main_text="Use the code below or click the button to authenticate:",
|
203
|
+
main_html_content=f'<p style="font-size: 2em; font-weight: bold; color: #007bff;">{otp_code}</p>',
|
204
|
+
secondary_text="This code expires in 10 minutes.",
|
205
|
+
button_text="Login with OTP",
|
206
|
+
button_url=otp_link,
|
207
|
+
)
|
208
|
+
logger.info(f"OTP email sent to {user.email}")
|
209
|
+
|
236
210
|
if send_telegram:
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
logger.info(f"OTP telegram notification sent for {user.email}")
|
252
|
-
except Exception as e:
|
253
|
-
logger.error(f"Failed to send OTP telegram notification: {e}")
|
211
|
+
notification_data = {
|
212
|
+
"email": user.email,
|
213
|
+
"user_type": "New User" if is_new_user else "Existing User",
|
214
|
+
"otp_code": otp_code,
|
215
|
+
"source_url": source_url or "Direct",
|
216
|
+
"timestamp": timezone.now().strftime("%Y-%m-%d %H:%M:%S UTC")
|
217
|
+
}
|
218
|
+
|
219
|
+
if is_new_user:
|
220
|
+
DjangoTelegram.send_success("🆕 New User OTP Request", notification_data)
|
221
|
+
else:
|
222
|
+
DjangoTelegram.send_info("🔑 OTP Login Request", notification_data)
|
223
|
+
|
224
|
+
logger.info(f"OTP telegram notification sent for {user.email}")
|
254
225
|
|
255
226
|
@staticmethod
|
256
227
|
def send_phone_otp_notification(user, otp_code, phone_number, is_new_user=False, source_url=None):
|
257
228
|
"""Send OTP notification via SMS to client and system notification to Telegram"""
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
if is_new_user:
|
286
|
-
DjangoTelegram.send_success("🆕📱 New User Phone OTP Request", notification_data)
|
287
|
-
else:
|
288
|
-
DjangoTelegram.send_info("🔑📱 Phone OTP Login Request", notification_data)
|
289
|
-
|
290
|
-
logger.info(f"Phone OTP system notification sent to Telegram for {phone_number}")
|
291
|
-
except Exception as e:
|
292
|
-
logger.error(f"Failed to send phone OTP system notification: {e}")
|
229
|
+
# Import here to avoid circular imports
|
230
|
+
from django_cfg.modules.django_twilio import send_sms
|
231
|
+
|
232
|
+
# Format SMS message for client
|
233
|
+
app_name = config.project_name if config else "App"
|
234
|
+
sms_message = f"Your {app_name} verification code is: {otp_code}. This code expires in 10 minutes."
|
235
|
+
|
236
|
+
# Send SMS to client using the convenience function
|
237
|
+
result = send_sms(
|
238
|
+
to=phone_number,
|
239
|
+
body=sms_message
|
240
|
+
)
|
241
|
+
|
242
|
+
if result:
|
243
|
+
logger.info(f"OTP SMS sent to client {phone_number}")
|
244
|
+
|
245
|
+
# Send SYSTEM notification to Telegram (for admins) - WITHOUT OTP code for security
|
246
|
+
notification_data = {
|
247
|
+
"phone": phone_number,
|
248
|
+
"user_type": "New User" if is_new_user else "Existing User",
|
249
|
+
"source_url": source_url or "Direct",
|
250
|
+
"timestamp": timezone.now().strftime("%Y-%m-%d %H:%M:%S UTC"),
|
251
|
+
"user_id": user.id if user else "Unknown"
|
252
|
+
}
|
253
|
+
|
254
|
+
if is_new_user:
|
255
|
+
DjangoTelegram.send_success("🆕📱 New User Phone OTP Request", notification_data)
|
293
256
|
else:
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
logger.error(f"Failed to send OTP SMS to client {phone_number}: {e}")
|
257
|
+
DjangoTelegram.send_info("🔑📱 Phone OTP Login Request", notification_data)
|
258
|
+
|
259
|
+
logger.info(f"Phone OTP system notification sent to Telegram for {phone_number}")
|
298
260
|
|
299
261
|
@staticmethod
|
300
262
|
def send_otp_verification_success(user, source_url=None, send_telegram=True):
|
301
263
|
"""Send successful OTP verification notification"""
|
302
264
|
if send_telegram:
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
logger.info(f"OTP verification telegram notification sent for {user.email}")
|
314
|
-
except Exception as e:
|
315
|
-
logger.error(f"Failed to send OTP verification telegram notification: {e}")
|
265
|
+
verification_data = {
|
266
|
+
"email": user.email,
|
267
|
+
"username": user.username,
|
268
|
+
"source_url": source_url or "Direct",
|
269
|
+
"login_time": timezone.now().strftime("%Y-%m-%d %H:%M:%S UTC"),
|
270
|
+
"user_id": user.id
|
271
|
+
}
|
272
|
+
|
273
|
+
DjangoTelegram.send_success("✅ Successful OTP Login", verification_data)
|
274
|
+
logger.info(f"OTP verification telegram notification sent for {user.email}")
|
316
275
|
|
317
276
|
# === SECURITY NOTIFICATIONS ===
|
318
277
|
|
@@ -320,7 +279,7 @@ class AccountNotifications:
|
|
320
279
|
def send_security_alert(user, alert_type, details, send_email=True, send_telegram=True):
|
321
280
|
"""Send security alert notification"""
|
322
281
|
if send_email:
|
323
|
-
|
282
|
+
AccountNotifications._send_email(
|
324
283
|
user=user,
|
325
284
|
subject=f"Security Alert: {alert_type} ⚠️",
|
326
285
|
main_text="A security alert has been triggered for your account.",
|
@@ -328,48 +287,41 @@ class AccountNotifications:
|
|
328
287
|
secondary_text=f"Details: {details}\nIf this wasn't you, please contact support immediately.",
|
329
288
|
button_text="Review Account",
|
330
289
|
)
|
331
|
-
|
332
|
-
|
333
|
-
|
290
|
+
logger.info(f"Security alert email sent to {user.email}")
|
291
|
+
|
334
292
|
if send_telegram:
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
logger.info(f"Security alert telegram notification sent for {user.email}")
|
346
|
-
except Exception as e:
|
347
|
-
logger.error(f"Failed to send security alert telegram notification: {e}")
|
293
|
+
alert_data = {
|
294
|
+
"user": user.email,
|
295
|
+
"alert_type": alert_type,
|
296
|
+
"details": details,
|
297
|
+
"timestamp": timezone.now().strftime("%Y-%m-%d %H:%M:%S UTC"),
|
298
|
+
"user_id": user.id
|
299
|
+
}
|
300
|
+
|
301
|
+
DjangoTelegram.send_warning(f"🚨 Security Alert: {alert_type}", alert_data)
|
302
|
+
logger.info(f"Security alert telegram notification sent for {user.email}")
|
348
303
|
|
349
304
|
@staticmethod
|
350
305
|
def send_failed_otp_attempt(identifier, channel='email', ip_address=None, reason="Invalid OTP", send_telegram=True):
|
351
306
|
"""Send notification about failed OTP attempt"""
|
352
307
|
if send_telegram:
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
logger.info(f"Failed OTP attempt telegram notification sent for {identifier} ({channel})")
|
365
|
-
except Exception as e:
|
366
|
-
logger.error(f"Failed to send failed OTP telegram notification: {e}")
|
308
|
+
details = {
|
309
|
+
"identifier": identifier,
|
310
|
+
"channel": channel,
|
311
|
+
"reason": reason,
|
312
|
+
"ip_address": ip_address or "Unknown",
|
313
|
+
"attempt_time": timezone.now().strftime("%Y-%m-%d %H:%M:%S UTC")
|
314
|
+
}
|
315
|
+
|
316
|
+
channel_emoji = "📧" if channel == 'email' else "📱"
|
317
|
+
DjangoTelegram.send_warning(f"❌ Failed {channel.title()} OTP Attempt {channel_emoji}", details)
|
318
|
+
logger.info(f"Failed OTP attempt telegram notification sent for {identifier} ({channel})")
|
367
319
|
|
368
320
|
@staticmethod
|
369
321
|
def send_suspicious_activity(user, activity_type, details, send_email=True, send_telegram=True):
|
370
322
|
"""Send suspicious activity notification"""
|
371
323
|
if send_email:
|
372
|
-
|
324
|
+
AccountNotifications._send_email(
|
373
325
|
user=user,
|
374
326
|
subject=f"Security Alert: Suspicious Activity: {activity_type} ⚠️",
|
375
327
|
main_text="A security alert has been triggered for your account.",
|
@@ -377,25 +329,21 @@ class AccountNotifications:
|
|
377
329
|
secondary_text=f"Details: We detected suspicious activity on your account: {details.get('description', 'Unknown activity')}\nIf this wasn't you, please contact support immediately.",
|
378
330
|
button_text="Review Account",
|
379
331
|
)
|
380
|
-
|
381
|
-
|
382
|
-
|
332
|
+
logger.info(f"Suspicious activity email sent to {user.email}")
|
333
|
+
|
383
334
|
if send_telegram:
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
logger.info(f"Suspicious activity telegram notification sent for {user.email}")
|
397
|
-
except Exception as e:
|
398
|
-
logger.error(f"Failed to send suspicious activity telegram notification: {e}")
|
335
|
+
alert_data = {
|
336
|
+
"user": user.email,
|
337
|
+
"activity_type": activity_type,
|
338
|
+
"details": details,
|
339
|
+
"timestamp": details.get("timestamp", timezone.now().strftime("%Y-%m-%d %H:%M:%S UTC")),
|
340
|
+
"ip_address": details.get("ip_address", "Unknown"),
|
341
|
+
"user_agent": details.get("user_agent", "Unknown"),
|
342
|
+
"requires_attention": True
|
343
|
+
}
|
344
|
+
|
345
|
+
DjangoTelegram.send_error(f"🚨 Suspicious Activity: {activity_type}", alert_data)
|
346
|
+
logger.info(f"Suspicious activity telegram notification sent for {user.email}")
|
399
347
|
|
400
348
|
# === ADMIN NOTIFICATIONS ===
|
401
349
|
|
@@ -403,120 +351,31 @@ class AccountNotifications:
|
|
403
351
|
def send_admin_user_created(user, created_by=None, send_telegram=True):
|
404
352
|
"""Send notification when admin creates user"""
|
405
353
|
if send_telegram:
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
logger.info(f"Admin user creation telegram notification sent for {user.email}")
|
419
|
-
except Exception as e:
|
420
|
-
logger.error(f"Failed to send admin user creation telegram notification: {e}")
|
354
|
+
data = {
|
355
|
+
"user": user.email,
|
356
|
+
"username": user.username,
|
357
|
+
"created_by": created_by.email if created_by else "System",
|
358
|
+
"is_active": user.is_active,
|
359
|
+
"is_staff": user.is_staff,
|
360
|
+
"is_superuser": user.is_superuser,
|
361
|
+
"date_created": user.date_joined.strftime("%Y-%m-%d %H:%M:%S UTC")
|
362
|
+
}
|
363
|
+
|
364
|
+
DjangoTelegram.send_info("👨💼 Admin Created User", data)
|
365
|
+
logger.info(f"Admin user creation telegram notification sent for {user.email}")
|
421
366
|
|
422
367
|
@staticmethod
|
423
368
|
def send_bulk_operation_notification(operation_type, count, details=None, send_telegram=True):
|
424
369
|
"""Send notification about bulk operations"""
|
425
370
|
if send_telegram:
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
logger.info(f"Bulk operation telegram notification sent: {operation_type}")
|
438
|
-
except Exception as e:
|
439
|
-
logger.error(f"Failed to send bulk operation telegram notification: {e}")
|
440
|
-
|
441
|
-
|
442
|
-
# === BACKWARD COMPATIBILITY ===
|
443
|
-
# For compatibility with existing code that uses AuthEmailService
|
444
|
-
|
445
|
-
class AuthEmailService:
|
446
|
-
"""
|
447
|
-
Backward compatibility wrapper for AccountNotifications.
|
448
|
-
DEPRECATED: Use AccountNotifications directly instead.
|
449
|
-
"""
|
450
|
-
|
451
|
-
def __init__(self, user):
|
452
|
-
self.user = user
|
453
|
-
|
454
|
-
def send_otp_email(self, otp_code: str, otp_link: str):
|
455
|
-
"""Send OTP email notification."""
|
456
|
-
return AccountNotifications._send_email(
|
457
|
-
user=self.user,
|
458
|
-
subject=f"Your OTP code: {otp_code}",
|
459
|
-
main_text="Use the code below or click the button to authenticate:",
|
460
|
-
main_html_content=f'<p style="font-size: 2em; font-weight: bold; color: #007bff;">{otp_code}</p>',
|
461
|
-
secondary_text="This code expires in 10 minutes.",
|
462
|
-
button_text="Login with OTP",
|
463
|
-
button_url=otp_link,
|
464
|
-
)
|
465
|
-
|
466
|
-
def send_welcome_email(self, username: str):
|
467
|
-
"""Send welcome email for new user registration."""
|
468
|
-
return AccountNotifications._send_email(
|
469
|
-
user=self.user,
|
470
|
-
subject=f"Welcome to {config.project_name}",
|
471
|
-
main_text=f"Welcome {username}! Your account has been successfully created.",
|
472
|
-
main_html_content=f'<p style="font-size: 1.5em; font-weight: bold; color: #28a745;">Welcome {username}!</p>',
|
473
|
-
secondary_text="You can now access all our services and start exploring our API.",
|
474
|
-
button_text="Go to Dashboard",
|
475
|
-
button_url=f"{config.site_url}/dashboard",
|
476
|
-
)
|
477
|
-
|
478
|
-
def send_security_alert_email(self, alert_type: str, details: str):
|
479
|
-
"""Send security alert email."""
|
480
|
-
return AccountNotifications._send_email(
|
481
|
-
user=self.user,
|
482
|
-
subject=f"Security Alert: {alert_type} ⚠️",
|
483
|
-
main_text="A security alert has been triggered for your account.",
|
484
|
-
main_html_content=f'<p style="font-size: 1.5em; font-weight: bold; color: #dc3545;">{alert_type}</p>',
|
485
|
-
secondary_text=f"Details: {details}\nIf this wasn't you, please contact support immediately.",
|
486
|
-
button_text="Review Account",
|
487
|
-
)
|
488
|
-
|
489
|
-
def send_account_activated_email(self):
|
490
|
-
"""Send account activation email."""
|
491
|
-
return AccountNotifications._send_email(
|
492
|
-
user=self.user,
|
493
|
-
subject=f"Account Activated - {config.project_name} ✅",
|
494
|
-
main_text="Your account has been activated and is now ready to use!",
|
495
|
-
main_html_content='<p style="font-size: 1.5em; font-weight: bold; color: #28a745;">Account Activated!</p>',
|
496
|
-
secondary_text="You now have full access to all our services and features.",
|
497
|
-
button_text="Access Dashboard",
|
498
|
-
button_url=f"{config.site_url}/dashboard",
|
499
|
-
)
|
500
|
-
|
501
|
-
def send_account_locked_email(self, reason: str):
|
502
|
-
"""Send account locked/deactivated email."""
|
503
|
-
return AccountNotifications._send_email(
|
504
|
-
user=self.user,
|
505
|
-
subject=f"Account Status Update - {config.project_name} ⚠️",
|
506
|
-
main_text="Your account status has been updated.",
|
507
|
-
main_html_content='<p style="font-size: 1.5em; font-weight: bold; color: #dc3545;">Account Deactivated</p>',
|
508
|
-
secondary_text=f"Reason: {reason}\nIf you believe this is an error, please contact our support team.",
|
509
|
-
button_text="Contact Support",
|
510
|
-
)
|
511
|
-
|
512
|
-
def send_login_notification_email(self, login_time: str, ip_address: str = None):
|
513
|
-
"""Send login notification email."""
|
514
|
-
ip_text = f" from IP address {ip_address}" if ip_address else ""
|
515
|
-
return AccountNotifications._send_email(
|
516
|
-
user=self.user,
|
517
|
-
subject=f"Login Notification - {config.project_name} 🔐",
|
518
|
-
main_text=f"We detected a login to your account at {login_time}{ip_text}.",
|
519
|
-
main_html_content=f'<p style="font-size: 1.2em; color: #007bff;">Login at {login_time}</p>',
|
520
|
-
secondary_text="If this wasn't you, please secure your account immediately and contact support.",
|
521
|
-
button_text="Review Account Security",
|
522
|
-
)
|
371
|
+
data = {
|
372
|
+
"operation": operation_type,
|
373
|
+
"count": count,
|
374
|
+
"timestamp": timezone.now().strftime("%Y-%m-%d %H:%M:%S UTC")
|
375
|
+
}
|
376
|
+
|
377
|
+
if details:
|
378
|
+
data.update(details)
|
379
|
+
|
380
|
+
DjangoTelegram.send_info(f"📊 Bulk Operation: {operation_type}", data)
|
381
|
+
logger.info(f"Bulk operation telegram notification sent: {operation_type}")
|