django-cfg 1.4.9__py3-none-any.whl → 1.4.11__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/apps/agents/management/commands/create_agent.py +1 -1
- django_cfg/apps/agents/management/commands/orchestrator_status.py +3 -3
- django_cfg/apps/newsletter/serializers.py +40 -3
- django_cfg/apps/newsletter/views/campaigns.py +12 -3
- django_cfg/apps/newsletter/views/emails.py +14 -3
- django_cfg/apps/newsletter/views/subscriptions.py +12 -2
- django_cfg/apps/payments/middleware/api_access.py +6 -2
- django_cfg/apps/payments/middleware/rate_limiting.py +2 -1
- django_cfg/apps/payments/middleware/usage_tracking.py +5 -1
- django_cfg/apps/payments/models/managers/api_key_managers.py +0 -1
- django_cfg/apps/payments/models/managers/subscription_managers.py +0 -1
- django_cfg/apps/payments/services/core/balance_service.py +5 -5
- django_cfg/apps/payments/services/core/subscription_service.py +1 -2
- django_cfg/apps/payments/views/api/balances.py +8 -7
- django_cfg/apps/payments/views/api/base.py +10 -6
- django_cfg/apps/payments/views/api/currencies.py +53 -10
- django_cfg/apps/payments/views/api/payments.py +3 -1
- django_cfg/apps/payments/views/api/subscriptions.py +2 -5
- django_cfg/apps/payments/views/api/webhooks.py +72 -7
- django_cfg/apps/payments/views/overview/serializers.py +34 -1
- django_cfg/apps/payments/views/overview/views.py +2 -1
- django_cfg/apps/payments/views/serializers/payments.py +6 -6
- django_cfg/apps/urls.py +106 -45
- django_cfg/core/base/config_model.py +2 -2
- django_cfg/core/constants.py +1 -1
- django_cfg/core/generation/integration_generators/__init__.py +1 -1
- django_cfg/core/generation/integration_generators/api.py +82 -41
- django_cfg/core/integration/display/startup.py +30 -22
- django_cfg/core/integration/url_integration.py +15 -16
- django_cfg/dashboard/sections/documentation.py +391 -0
- django_cfg/management/commands/check_endpoints.py +11 -160
- django_cfg/management/commands/check_settings.py +13 -265
- django_cfg/management/commands/clear_constance.py +13 -201
- django_cfg/management/commands/create_token.py +13 -321
- django_cfg/management/commands/generate_clients.py +23 -0
- django_cfg/management/commands/list_urls.py +13 -306
- django_cfg/management/commands/migrate_all.py +13 -126
- django_cfg/management/commands/migrator.py +13 -396
- django_cfg/management/commands/rundramatiq.py +15 -247
- django_cfg/management/commands/rundramatiq_simulator.py +12 -429
- django_cfg/management/commands/runserver_ngrok.py +15 -160
- django_cfg/management/commands/script.py +12 -488
- django_cfg/management/commands/show_config.py +12 -215
- django_cfg/management/commands/show_urls.py +12 -342
- django_cfg/management/commands/superuser.py +15 -295
- django_cfg/management/commands/task_clear.py +14 -217
- django_cfg/management/commands/task_status.py +13 -248
- django_cfg/management/commands/test_email.py +15 -86
- django_cfg/management/commands/test_telegram.py +14 -61
- django_cfg/management/commands/test_twilio.py +15 -105
- django_cfg/management/commands/tree.py +13 -383
- django_cfg/management/commands/validate_openapi.py +10 -0
- django_cfg/middleware/README.md +1 -1
- django_cfg/middleware/user_activity.py +3 -3
- django_cfg/models/__init__.py +2 -2
- django_cfg/models/api/drf/spectacular.py +6 -6
- django_cfg/models/django/__init__.py +2 -2
- django_cfg/models/django/openapi.py +238 -0
- django_cfg/models/django/{revolution.py → revolution_legacy.py} +8 -0
- django_cfg/modules/django_admin/management/__init__.py +0 -0
- django_cfg/modules/django_admin/management/commands/__init__.py +0 -0
- django_cfg/modules/django_admin/management/commands/check_endpoints.py +169 -0
- django_cfg/modules/django_admin/management/commands/check_settings.py +355 -0
- django_cfg/modules/django_admin/management/commands/clear_constance.py +208 -0
- django_cfg/modules/django_admin/management/commands/create_token.py +328 -0
- django_cfg/modules/django_admin/management/commands/list_urls.py +313 -0
- django_cfg/modules/django_admin/management/commands/migrate_all.py +133 -0
- django_cfg/modules/django_admin/management/commands/migrator.py +403 -0
- django_cfg/modules/django_admin/management/commands/script.py +496 -0
- django_cfg/modules/django_admin/management/commands/show_config.py +225 -0
- django_cfg/modules/django_admin/management/commands/show_urls.py +361 -0
- django_cfg/modules/django_admin/management/commands/superuser.py +302 -0
- django_cfg/modules/django_admin/management/commands/tree.py +390 -0
- django_cfg/modules/django_client/__init__.py +20 -0
- django_cfg/modules/django_client/apps.py +35 -0
- django_cfg/modules/django_client/core/__init__.py +56 -0
- django_cfg/modules/django_client/core/archive/__init__.py +11 -0
- django_cfg/modules/django_client/core/archive/manager.py +134 -0
- django_cfg/modules/django_client/core/cli/__init__.py +12 -0
- django_cfg/modules/django_client/core/cli/main.py +235 -0
- django_cfg/modules/django_client/core/config/__init__.py +18 -0
- django_cfg/modules/django_client/core/config/config.py +188 -0
- django_cfg/modules/django_client/core/config/group.py +101 -0
- django_cfg/modules/django_client/core/config/service.py +209 -0
- django_cfg/modules/django_client/core/generator/__init__.py +115 -0
- django_cfg/modules/django_client/core/generator/base.py +767 -0
- django_cfg/modules/django_client/core/generator/python.py +751 -0
- django_cfg/modules/django_client/core/generator/templates/python/__init__.py.jinja +9 -0
- django_cfg/modules/django_client/core/generator/templates/python/api_wrapper.py.jinja +130 -0
- django_cfg/modules/django_client/core/generator/templates/python/app_init.py.jinja +6 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/app_client.py.jinja +18 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/flat_client.py.jinja +38 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/main_client.py.jinja +50 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/main_client_file.py.jinja +13 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/operation_method.py.jinja +7 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/sub_client.py.jinja +11 -0
- django_cfg/modules/django_client/core/generator/templates/python/client_file.py.jinja +13 -0
- django_cfg/modules/django_client/core/generator/templates/python/main_init.py.jinja +50 -0
- django_cfg/modules/django_client/core/generator/templates/python/models/app_models.py.jinja +17 -0
- django_cfg/modules/django_client/core/generator/templates/python/models/enum_class.py.jinja +15 -0
- django_cfg/modules/django_client/core/generator/templates/python/models/enums.py.jinja +8 -0
- django_cfg/modules/django_client/core/generator/templates/python/models/models.py.jinja +17 -0
- django_cfg/modules/django_client/core/generator/templates/python/models/schema_class.py.jinja +19 -0
- django_cfg/modules/django_client/core/generator/templates/python/utils/logger.py.jinja +255 -0
- django_cfg/modules/django_client/core/generator/templates/python/utils/schema.py.jinja +12 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/app_index.ts.jinja +2 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/app_client.ts.jinja +18 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/client.ts.jinja +327 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/flat_client.ts.jinja +109 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/main_client_file.ts.jinja +9 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/operation.ts.jinja +61 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/sub_client.ts.jinja +15 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client_file.ts.jinja +9 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/index.ts.jinja +5 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/main_index.ts.jinja +206 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/models/app_models.ts.jinja +8 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/models/enums.ts.jinja +4 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/models/models.ts.jinja +8 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/utils/errors.ts.jinja +114 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/utils/http.ts.jinja +98 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/utils/logger.ts.jinja +251 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/utils/schema.ts.jinja +7 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/utils/storage.ts.jinja +114 -0
- django_cfg/modules/django_client/core/generator/typescript.py +872 -0
- django_cfg/modules/django_client/core/groups/__init__.py +13 -0
- django_cfg/modules/django_client/core/groups/detector.py +178 -0
- django_cfg/modules/django_client/core/groups/manager.py +314 -0
- django_cfg/modules/django_client/core/ir/__init__.py +57 -0
- django_cfg/modules/django_client/core/ir/context.py +387 -0
- django_cfg/modules/django_client/core/ir/operation.py +518 -0
- django_cfg/modules/django_client/core/ir/schema.py +353 -0
- django_cfg/modules/django_client/core/parser/__init__.py +74 -0
- django_cfg/modules/django_client/core/parser/base.py +648 -0
- django_cfg/modules/django_client/core/parser/models/__init__.py +74 -0
- django_cfg/modules/django_client/core/parser/models/base.py +212 -0
- django_cfg/modules/django_client/core/parser/models/components.py +160 -0
- django_cfg/modules/django_client/core/parser/models/openapi.py +203 -0
- django_cfg/modules/django_client/core/parser/models/operation.py +207 -0
- django_cfg/modules/django_client/core/parser/models/schema.py +266 -0
- django_cfg/modules/django_client/core/parser/openapi30.py +56 -0
- django_cfg/modules/django_client/core/parser/openapi31.py +64 -0
- django_cfg/modules/django_client/core/validation/__init__.py +22 -0
- django_cfg/modules/django_client/core/validation/checker.py +134 -0
- django_cfg/modules/django_client/core/validation/fixer.py +216 -0
- django_cfg/modules/django_client/core/validation/reporter.py +480 -0
- django_cfg/modules/django_client/core/validation/rules/__init__.py +11 -0
- django_cfg/modules/django_client/core/validation/rules/base.py +96 -0
- django_cfg/modules/django_client/core/validation/rules/type_hints.py +288 -0
- django_cfg/modules/django_client/core/validation/safety.py +266 -0
- django_cfg/modules/django_client/management/__init__.py +3 -0
- django_cfg/modules/django_client/management/commands/__init__.py +3 -0
- django_cfg/modules/django_client/management/commands/generate_client.py +422 -0
- django_cfg/modules/django_client/management/commands/validate_openapi.py +343 -0
- django_cfg/modules/django_client/spectacular/__init__.py +9 -0
- django_cfg/modules/django_client/spectacular/enum_naming.py +192 -0
- django_cfg/modules/django_client/urls.py +72 -0
- django_cfg/modules/django_email/management/__init__.py +0 -0
- django_cfg/modules/django_email/management/commands/__init__.py +0 -0
- django_cfg/modules/django_email/management/commands/test_email.py +93 -0
- django_cfg/modules/django_logging/django_logger.py +6 -6
- django_cfg/modules/django_ngrok/management/__init__.py +0 -0
- django_cfg/modules/django_ngrok/management/commands/__init__.py +0 -0
- django_cfg/modules/django_ngrok/management/commands/runserver_ngrok.py +167 -0
- django_cfg/modules/django_tasks/management/__init__.py +0 -0
- django_cfg/modules/django_tasks/management/commands/__init__.py +0 -0
- django_cfg/modules/django_tasks/management/commands/rundramatiq.py +254 -0
- django_cfg/modules/django_tasks/management/commands/rundramatiq_simulator.py +437 -0
- django_cfg/modules/django_tasks/management/commands/task_clear.py +226 -0
- django_cfg/modules/django_tasks/management/commands/task_status.py +257 -0
- django_cfg/modules/django_telegram/management/__init__.py +0 -0
- django_cfg/modules/django_telegram/management/commands/__init__.py +0 -0
- django_cfg/modules/django_telegram/management/commands/test_telegram.py +68 -0
- django_cfg/modules/django_twilio/management/__init__.py +0 -0
- django_cfg/modules/django_twilio/management/commands/__init__.py +0 -0
- django_cfg/modules/django_twilio/management/commands/test_twilio.py +112 -0
- django_cfg/modules/django_unfold/callbacks/main.py +16 -5
- django_cfg/modules/django_unfold/callbacks/revolution.py +41 -36
- django_cfg/modules/django_unfold/dashboard.py +1 -1
- django_cfg/pyproject.toml +2 -6
- django_cfg/registry/third_party.py +5 -7
- django_cfg/routing/callbacks.py +1 -1
- django_cfg/static/admin/css/prose-unfold.css +666 -0
- django_cfg/templates/admin/index.html +8 -0
- django_cfg/templates/admin/index_new.html +13 -0
- django_cfg/templates/admin/layouts/dashboard_with_tabs.html +15 -3
- django_cfg/templates/admin/sections/documentation_section.html +172 -0
- django_cfg/templates/admin/snippets/tabs/documentation_tab.html +231 -0
- {django_cfg-1.4.9.dist-info → django_cfg-1.4.11.dist-info}/METADATA +2 -2
- {django_cfg-1.4.9.dist-info → django_cfg-1.4.11.dist-info}/RECORD +192 -71
- django_cfg/management/commands/generate.py +0 -107
- {django_cfg-1.4.9.dist-info → django_cfg-1.4.11.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.9.dist-info → django_cfg-1.4.11.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.9.dist-info → django_cfg-1.4.11.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,238 @@
|
|
1
|
+
"""
|
2
|
+
Django Client (OpenAPI) Configuration with DRF Integration
|
3
|
+
|
4
|
+
Extended configuration model that integrates openapi_client for automatic
|
5
|
+
TypeScript and Python client generation from Django REST Framework endpoints.
|
6
|
+
|
7
|
+
This replaces django-revolution with a cleaner, faster, type-safe implementation.
|
8
|
+
"""
|
9
|
+
|
10
|
+
from typing import Dict, Any, Optional
|
11
|
+
from pydantic import BaseModel, Field
|
12
|
+
from django_cfg.modules.django_client.core.config import OpenAPIConfig, OpenAPIGroupConfig
|
13
|
+
|
14
|
+
|
15
|
+
class ExtendedOpenAPIConfig(OpenAPIConfig):
|
16
|
+
"""
|
17
|
+
Extended OpenAPI configuration with DRF parameters for django-cfg integration.
|
18
|
+
|
19
|
+
This extends the base OpenAPIConfig to include DRF-specific
|
20
|
+
parameters and django-cfg integration helpers.
|
21
|
+
|
22
|
+
Example:
|
23
|
+
```python
|
24
|
+
from django_cfg import ExtendedOpenAPIConfig, OpenAPIGroupConfig
|
25
|
+
|
26
|
+
config = ExtendedOpenAPIConfig(
|
27
|
+
enabled=True,
|
28
|
+
groups=[
|
29
|
+
OpenAPIGroupConfig(
|
30
|
+
name='api',
|
31
|
+
apps=['users', 'posts'],
|
32
|
+
title='Main API',
|
33
|
+
version='v1',
|
34
|
+
),
|
35
|
+
],
|
36
|
+
drf_title='My API',
|
37
|
+
drf_description='REST API for my project',
|
38
|
+
)
|
39
|
+
```
|
40
|
+
"""
|
41
|
+
|
42
|
+
# DRF Configuration parameters for automatic DRF setup
|
43
|
+
drf_title: str = Field(
|
44
|
+
default="API",
|
45
|
+
description="API title for DRF Spectacular"
|
46
|
+
)
|
47
|
+
drf_description: str = Field(
|
48
|
+
default="RESTful API",
|
49
|
+
description="API description for DRF Spectacular"
|
50
|
+
)
|
51
|
+
drf_version: str = Field(
|
52
|
+
default="1.0.0",
|
53
|
+
description="API version for DRF Spectacular"
|
54
|
+
)
|
55
|
+
drf_schema_path_prefix: Optional[str] = Field(
|
56
|
+
default=None, # Will default to "/api/" if None
|
57
|
+
description="Schema path prefix for DRF Spectacular"
|
58
|
+
)
|
59
|
+
drf_enable_browsable_api: bool = Field(
|
60
|
+
default=False,
|
61
|
+
description="Enable DRF browsable API"
|
62
|
+
)
|
63
|
+
drf_enable_throttling: bool = Field(
|
64
|
+
default=False,
|
65
|
+
description="Enable DRF throttling"
|
66
|
+
)
|
67
|
+
drf_serve_include_schema: bool = Field(
|
68
|
+
default=False,
|
69
|
+
description="Include schema in Spectacular UI"
|
70
|
+
)
|
71
|
+
|
72
|
+
# Django-cfg specific integration
|
73
|
+
api_prefix: str = Field(
|
74
|
+
default="api",
|
75
|
+
description="API prefix for URL routing (e.g., 'api' -> /api/...)"
|
76
|
+
)
|
77
|
+
|
78
|
+
def get_drf_schema_path_prefix(self) -> str:
|
79
|
+
"""Get the schema path prefix, defaulting to api_prefix if not set."""
|
80
|
+
if self.drf_schema_path_prefix:
|
81
|
+
return self.drf_schema_path_prefix
|
82
|
+
return f"/{self.api_prefix}/"
|
83
|
+
|
84
|
+
def get_drf_config_kwargs(self) -> Dict[str, Any]:
|
85
|
+
"""
|
86
|
+
Get kwargs for DRF configuration from this config.
|
87
|
+
|
88
|
+
Returns:
|
89
|
+
Dict of parameters for DRF + Spectacular setup
|
90
|
+
"""
|
91
|
+
return {
|
92
|
+
"title": self.drf_title,
|
93
|
+
"description": self.drf_description,
|
94
|
+
"version": self.drf_version,
|
95
|
+
"schema_path_prefix": self.get_drf_schema_path_prefix(),
|
96
|
+
"enable_browsable_api": self.drf_enable_browsable_api,
|
97
|
+
"enable_throttling": self.drf_enable_throttling,
|
98
|
+
"serve_include_schema": self.drf_serve_include_schema,
|
99
|
+
# REQUIRED by django-client for correct Request/Response split
|
100
|
+
"component_split_request": True,
|
101
|
+
"component_split_patch": True,
|
102
|
+
}
|
103
|
+
|
104
|
+
def get_groups_with_defaults(self) -> Dict[str, OpenAPIGroupConfig]:
|
105
|
+
"""
|
106
|
+
Get groups with django-cfg default groups automatically added.
|
107
|
+
|
108
|
+
Returns:
|
109
|
+
Dict of groups including default django-cfg groups
|
110
|
+
"""
|
111
|
+
# Convert list to dict for compatibility
|
112
|
+
groups_dict = {group.name: group for group in self.groups}
|
113
|
+
|
114
|
+
# Add default django-cfg groups if enabled
|
115
|
+
try:
|
116
|
+
from django_cfg.modules.base import BaseCfgModule
|
117
|
+
base_module = BaseCfgModule()
|
118
|
+
|
119
|
+
support_enabled = base_module.is_support_enabled()
|
120
|
+
accounts_enabled = base_module.is_accounts_enabled()
|
121
|
+
newsletter_enabled = base_module.is_newsletter_enabled()
|
122
|
+
leads_enabled = base_module.is_leads_enabled()
|
123
|
+
knowbase_enabled = base_module.is_knowbase_enabled()
|
124
|
+
agents_enabled = base_module.is_agents_enabled()
|
125
|
+
tasks_enabled = base_module.should_enable_tasks()
|
126
|
+
payments_enabled = base_module.is_payments_enabled()
|
127
|
+
|
128
|
+
# Collect all enabled django-cfg apps for unified group
|
129
|
+
enabled_cfg_apps = []
|
130
|
+
if support_enabled:
|
131
|
+
enabled_cfg_apps.append("django_cfg.apps.support")
|
132
|
+
if accounts_enabled:
|
133
|
+
enabled_cfg_apps.append("django_cfg.apps.accounts")
|
134
|
+
if newsletter_enabled:
|
135
|
+
enabled_cfg_apps.append("django_cfg.apps.newsletter")
|
136
|
+
if leads_enabled:
|
137
|
+
enabled_cfg_apps.append("django_cfg.apps.leads")
|
138
|
+
if knowbase_enabled:
|
139
|
+
enabled_cfg_apps.append("django_cfg.apps.knowbase")
|
140
|
+
if agents_enabled:
|
141
|
+
enabled_cfg_apps.append("django_cfg.apps.agents")
|
142
|
+
if tasks_enabled:
|
143
|
+
enabled_cfg_apps.append("django_cfg.apps.tasks")
|
144
|
+
if payments_enabled:
|
145
|
+
enabled_cfg_apps.append("django_cfg.apps.payments")
|
146
|
+
|
147
|
+
# Add unified 'cfg' group with all enabled apps
|
148
|
+
if enabled_cfg_apps and 'cfg' not in groups_dict:
|
149
|
+
groups_dict['cfg'] = OpenAPIGroupConfig(
|
150
|
+
name="cfg",
|
151
|
+
apps=enabled_cfg_apps,
|
152
|
+
title="Django-CFG API",
|
153
|
+
description="All django-cfg built-in applications",
|
154
|
+
)
|
155
|
+
|
156
|
+
# Skip individual cfg_* groups - use unified 'cfg' instead
|
157
|
+
return groups_dict
|
158
|
+
|
159
|
+
# Add Support group if enabled
|
160
|
+
if support_enabled and 'cfg_support' not in groups_dict:
|
161
|
+
groups_dict['cfg_support'] = OpenAPIGroupConfig(
|
162
|
+
name="cfg_support",
|
163
|
+
apps=["django_cfg.apps.support"],
|
164
|
+
title="Support API",
|
165
|
+
description="Support tickets and messages API",
|
166
|
+
)
|
167
|
+
|
168
|
+
# Add Accounts group if enabled
|
169
|
+
if accounts_enabled and 'cfg_accounts' not in groups_dict:
|
170
|
+
groups_dict['cfg_accounts'] = OpenAPIGroupConfig(
|
171
|
+
name="cfg_accounts",
|
172
|
+
apps=["django_cfg.apps.accounts"],
|
173
|
+
title="Accounts API",
|
174
|
+
description="User management, OTP, profiles, and activity tracking API",
|
175
|
+
)
|
176
|
+
|
177
|
+
# Add Newsletter group if enabled
|
178
|
+
if newsletter_enabled and 'cfg_newsletter' not in groups_dict:
|
179
|
+
groups_dict['cfg_newsletter'] = OpenAPIGroupConfig(
|
180
|
+
name="cfg_newsletter",
|
181
|
+
apps=["django_cfg.apps.newsletter"],
|
182
|
+
title="Newsletter API",
|
183
|
+
description="Email campaigns, subscriptions, and newsletter management API",
|
184
|
+
)
|
185
|
+
|
186
|
+
# Add Leads group if enabled
|
187
|
+
if leads_enabled and 'cfg_leads' not in groups_dict:
|
188
|
+
groups_dict['cfg_leads'] = OpenAPIGroupConfig(
|
189
|
+
name="cfg_leads",
|
190
|
+
apps=["django_cfg.apps.leads"],
|
191
|
+
title="Leads API",
|
192
|
+
description="Lead collection, contact forms, and CRM integration API",
|
193
|
+
)
|
194
|
+
|
195
|
+
# Add Knowbase group if enabled
|
196
|
+
if knowbase_enabled and 'cfg_knowbase' not in groups_dict:
|
197
|
+
groups_dict['cfg_knowbase'] = OpenAPIGroupConfig(
|
198
|
+
name="cfg_knowbase",
|
199
|
+
apps=["django_cfg.apps.knowbase"],
|
200
|
+
title="Knowbase API",
|
201
|
+
description="Knowledge base, AI chat, embeddings, and search API",
|
202
|
+
)
|
203
|
+
|
204
|
+
# Add Agents group if enabled
|
205
|
+
if agents_enabled and 'cfg_agents' not in groups_dict:
|
206
|
+
groups_dict['cfg_agents'] = OpenAPIGroupConfig(
|
207
|
+
name="cfg_agents",
|
208
|
+
apps=["django_cfg.apps.agents"],
|
209
|
+
title="Agents API",
|
210
|
+
description="Agent definitions, executions, workflows, and tools API",
|
211
|
+
)
|
212
|
+
|
213
|
+
# Add Tasks group if enabled
|
214
|
+
if tasks_enabled and 'cfg_tasks' not in groups_dict:
|
215
|
+
groups_dict['cfg_tasks'] = OpenAPIGroupConfig(
|
216
|
+
name="cfg_tasks",
|
217
|
+
apps=["django_cfg.apps.tasks"],
|
218
|
+
title="Tasks API",
|
219
|
+
description="Tasks, workflows, and automation API",
|
220
|
+
)
|
221
|
+
|
222
|
+
# Add Payments group if enabled
|
223
|
+
if payments_enabled and 'cfg_payments' not in groups_dict:
|
224
|
+
groups_dict['cfg_payments'] = OpenAPIGroupConfig(
|
225
|
+
name="cfg_payments",
|
226
|
+
apps=["django_cfg.apps.payments"],
|
227
|
+
title="Payments API",
|
228
|
+
description="Payments, subscriptions, and billing API",
|
229
|
+
)
|
230
|
+
|
231
|
+
except Exception:
|
232
|
+
pass
|
233
|
+
|
234
|
+
return groups_dict
|
235
|
+
|
236
|
+
|
237
|
+
# Alias for easier import
|
238
|
+
OpenAPIClientConfig = ExtendedOpenAPIConfig
|
@@ -117,6 +117,7 @@ class ExtendedRevolutionConfig(BaseDjangoRevolutionConfig):
|
|
117
117
|
description="Support tickets and messages API",
|
118
118
|
public=False,
|
119
119
|
auth_required=True,
|
120
|
+
group="cfg",
|
120
121
|
# version="v1",
|
121
122
|
)
|
122
123
|
|
@@ -129,6 +130,7 @@ class ExtendedRevolutionConfig(BaseDjangoRevolutionConfig):
|
|
129
130
|
description="User management, OTP, profiles, and activity tracking API",
|
130
131
|
public=False,
|
131
132
|
auth_required=True,
|
133
|
+
group="cfg",
|
132
134
|
# version="v1",
|
133
135
|
)
|
134
136
|
|
@@ -141,6 +143,7 @@ class ExtendedRevolutionConfig(BaseDjangoRevolutionConfig):
|
|
141
143
|
description="Email campaigns, subscriptions, and newsletter management API",
|
142
144
|
public=False,
|
143
145
|
auth_required=True,
|
146
|
+
group="cfg",
|
144
147
|
# version="v1",
|
145
148
|
)
|
146
149
|
|
@@ -153,6 +156,7 @@ class ExtendedRevolutionConfig(BaseDjangoRevolutionConfig):
|
|
153
156
|
description="Lead collection, contact forms, and CRM integration API",
|
154
157
|
public=True, # Leads can be public for contact forms
|
155
158
|
auth_required=False,
|
159
|
+
group="cfg",
|
156
160
|
# version="v1",
|
157
161
|
)
|
158
162
|
|
@@ -165,6 +169,7 @@ class ExtendedRevolutionConfig(BaseDjangoRevolutionConfig):
|
|
165
169
|
description="Knowledge base, AI chat, embeddings, and search API",
|
166
170
|
public=False,
|
167
171
|
auth_required=True,
|
172
|
+
group="cfg",
|
168
173
|
# version="v1",
|
169
174
|
)
|
170
175
|
|
@@ -177,6 +182,7 @@ class ExtendedRevolutionConfig(BaseDjangoRevolutionConfig):
|
|
177
182
|
description="Agent definitions, executions, workflows, and tools API",
|
178
183
|
public=False,
|
179
184
|
auth_required=True,
|
185
|
+
group="cfg",
|
180
186
|
# version="v1",
|
181
187
|
)
|
182
188
|
|
@@ -189,6 +195,7 @@ class ExtendedRevolutionConfig(BaseDjangoRevolutionConfig):
|
|
189
195
|
description="Tasks, workflows, and automation API",
|
190
196
|
public=False,
|
191
197
|
auth_required=True,
|
198
|
+
group="cfg",
|
192
199
|
# version="v1",
|
193
200
|
)
|
194
201
|
|
@@ -201,6 +208,7 @@ class ExtendedRevolutionConfig(BaseDjangoRevolutionConfig):
|
|
201
208
|
description="Payments, subscriptions, and billing API",
|
202
209
|
public=False,
|
203
210
|
auth_required=True,
|
211
|
+
group="cfg",
|
204
212
|
# version="v1",
|
205
213
|
)
|
206
214
|
|
File without changes
|
File without changes
|
@@ -0,0 +1,169 @@
|
|
1
|
+
"""
|
2
|
+
Django management command to check all API endpoints status.
|
3
|
+
|
4
|
+
Usage:
|
5
|
+
python manage.py check_endpoints
|
6
|
+
python manage.py check_endpoints --include-unnamed
|
7
|
+
python manage.py check_endpoints --timeout 10
|
8
|
+
python manage.py check_endpoints --json
|
9
|
+
"""
|
10
|
+
|
11
|
+
from django.core.management.base import BaseCommand
|
12
|
+
from django.urls import reverse
|
13
|
+
from django_cfg.apps.api.endpoints.checker import check_all_endpoints
|
14
|
+
import json
|
15
|
+
|
16
|
+
|
17
|
+
class Command(BaseCommand):
|
18
|
+
help = 'Check status of all Django CFG API endpoints'
|
19
|
+
|
20
|
+
def add_arguments(self, parser):
|
21
|
+
parser.add_argument(
|
22
|
+
'--include-unnamed',
|
23
|
+
action='store_true',
|
24
|
+
help='Include unnamed URL patterns in the check',
|
25
|
+
)
|
26
|
+
parser.add_argument(
|
27
|
+
'--timeout',
|
28
|
+
type=int,
|
29
|
+
default=5,
|
30
|
+
help='Request timeout in seconds (default: 5)',
|
31
|
+
)
|
32
|
+
parser.add_argument(
|
33
|
+
'--json',
|
34
|
+
action='store_true',
|
35
|
+
help='Output results as JSON',
|
36
|
+
)
|
37
|
+
parser.add_argument(
|
38
|
+
'--url',
|
39
|
+
type=str,
|
40
|
+
help='Check specific endpoint by URL name (e.g., "endpoints_status")',
|
41
|
+
)
|
42
|
+
parser.add_argument(
|
43
|
+
'--no-auth',
|
44
|
+
action='store_true',
|
45
|
+
help='Disable automatic JWT authentication retry (default: enabled)',
|
46
|
+
)
|
47
|
+
|
48
|
+
def handle(self, *args, **options):
|
49
|
+
include_unnamed = options['include_unnamed']
|
50
|
+
timeout = options['timeout']
|
51
|
+
output_json = options['json']
|
52
|
+
url_name = options.get('url')
|
53
|
+
auto_auth = not options['no_auth'] # Auto-auth enabled by default
|
54
|
+
|
55
|
+
# If specific URL requested, just resolve and display it
|
56
|
+
if url_name:
|
57
|
+
try:
|
58
|
+
url = reverse(url_name)
|
59
|
+
self.stdout.write(self.style.SUCCESS(f'✅ URL name "{url_name}" resolves to: {url}'))
|
60
|
+
return
|
61
|
+
except Exception as e:
|
62
|
+
self.stdout.write(self.style.ERROR(f'❌ Error resolving URL "{url_name}": {e}'))
|
63
|
+
return
|
64
|
+
|
65
|
+
# Check all endpoints
|
66
|
+
auth_msg = "with auto-auth" if auto_auth else "without auth"
|
67
|
+
self.stdout.write(self.style.WARNING(f'🔍 Checking endpoints (timeout: {timeout}s, {auth_msg})...'))
|
68
|
+
|
69
|
+
status_data = check_all_endpoints(
|
70
|
+
include_unnamed=include_unnamed,
|
71
|
+
timeout=timeout,
|
72
|
+
auto_auth=auto_auth
|
73
|
+
)
|
74
|
+
|
75
|
+
# Output as JSON if requested
|
76
|
+
if output_json:
|
77
|
+
self.stdout.write(json.dumps(status_data, indent=2))
|
78
|
+
return
|
79
|
+
|
80
|
+
# Pretty print results
|
81
|
+
self._print_results(status_data)
|
82
|
+
|
83
|
+
def _print_results(self, data):
|
84
|
+
"""Print formatted results to console."""
|
85
|
+
|
86
|
+
# Overall status
|
87
|
+
status = data['status']
|
88
|
+
if status == 'healthy':
|
89
|
+
status_style = self.style.SUCCESS
|
90
|
+
emoji = '✅'
|
91
|
+
elif status == 'degraded':
|
92
|
+
status_style = self.style.WARNING
|
93
|
+
emoji = '⚠️'
|
94
|
+
else:
|
95
|
+
status_style = self.style.ERROR
|
96
|
+
emoji = '❌'
|
97
|
+
|
98
|
+
self.stdout.write('')
|
99
|
+
self.stdout.write(status_style(f'{emoji} Overall Status: {status.upper()}'))
|
100
|
+
self.stdout.write('')
|
101
|
+
|
102
|
+
# Summary
|
103
|
+
self.stdout.write(self.style.HTTP_INFO('📊 Summary:'))
|
104
|
+
self.stdout.write(f' Total endpoints: {data["total_endpoints"]}')
|
105
|
+
self.stdout.write(self.style.SUCCESS(f' ✅ Healthy: {data["healthy"]}'))
|
106
|
+
self.stdout.write(self.style.WARNING(f' ⚠️ Warnings: {data["warnings"]}'))
|
107
|
+
self.stdout.write(self.style.ERROR(f' ❌ Unhealthy: {data["unhealthy"]}'))
|
108
|
+
self.stdout.write(self.style.ERROR(f' ❌ Errors: {data["errors"]}'))
|
109
|
+
self.stdout.write(f' ⏭️ Skipped: {data["skipped"]}')
|
110
|
+
self.stdout.write('')
|
111
|
+
|
112
|
+
# Endpoints details
|
113
|
+
self.stdout.write(self.style.HTTP_INFO('🔗 Endpoints:'))
|
114
|
+
|
115
|
+
for endpoint in data['endpoints']:
|
116
|
+
name = endpoint.get('url_name') or 'unnamed'
|
117
|
+
url = endpoint['url']
|
118
|
+
status = endpoint['status']
|
119
|
+
|
120
|
+
if status == 'healthy':
|
121
|
+
icon = '✅'
|
122
|
+
style = self.style.SUCCESS
|
123
|
+
elif status == 'degraded':
|
124
|
+
icon = '⚠️'
|
125
|
+
style = self.style.WARNING
|
126
|
+
else:
|
127
|
+
icon = '❌'
|
128
|
+
style = self.style.ERROR
|
129
|
+
|
130
|
+
self.stdout.write(f' {icon} {name}')
|
131
|
+
|
132
|
+
# Show both pattern and resolved URL for parametrized endpoints
|
133
|
+
if endpoint.get('has_parameters') and endpoint.get('url_pattern'):
|
134
|
+
self.stdout.write(f' Pattern: {endpoint["url_pattern"]}')
|
135
|
+
self.stdout.write(f' Resolved: {url}')
|
136
|
+
else:
|
137
|
+
self.stdout.write(f' URL: {url}')
|
138
|
+
|
139
|
+
# Show status with status code
|
140
|
+
status_code = endpoint.get('status_code')
|
141
|
+
if status_code:
|
142
|
+
self.stdout.write(style(f' Status: {status} ({status_code})'))
|
143
|
+
else:
|
144
|
+
self.stdout.write(style(f' Status: {status}'))
|
145
|
+
|
146
|
+
if endpoint.get('response_time_ms'):
|
147
|
+
self.stdout.write(f' Response time: {endpoint["response_time_ms"]:.2f}ms')
|
148
|
+
|
149
|
+
if endpoint.get('error'):
|
150
|
+
error_type = endpoint.get('error_type', 'general')
|
151
|
+
if error_type == 'database':
|
152
|
+
self.stdout.write(self.style.WARNING(f' ⚠️ DB Error (multi-db): {endpoint["error"]}'))
|
153
|
+
else:
|
154
|
+
self.stdout.write(self.style.ERROR(f' Error: {endpoint["error"]}'))
|
155
|
+
|
156
|
+
# Show reason for warnings (e.g., 404 explanations)
|
157
|
+
if endpoint.get('reason') and status == 'warning':
|
158
|
+
self.stdout.write(self.style.WARNING(f' ⚠️ {endpoint["reason"]}'))
|
159
|
+
|
160
|
+
if endpoint.get('required_auth'):
|
161
|
+
self.stdout.write(f' 🔐 Required JWT authentication')
|
162
|
+
|
163
|
+
if endpoint.get('rate_limited'):
|
164
|
+
self.stdout.write(f' ⏱️ Rate limited (429)')
|
165
|
+
|
166
|
+
self.stdout.write('')
|
167
|
+
|
168
|
+
# Timestamp
|
169
|
+
self.stdout.write(self.style.HTTP_INFO(f'🕐 Checked at: {data["timestamp"]}'))
|