django-cfg 1.4.10__py3-none-any.whl → 1.4.13__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/views/api/currencies.py +49 -6
- 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 +73 -49
- django_cfg/core/integration/display/startup.py +30 -22
- django_cfg/core/integration/url_integration.py +15 -16
- django_cfg/management/commands/check_endpoints.py +11 -160
- django_cfg/management/commands/check_settings.py +13 -348
- 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 +162 -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 +208 -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 +838 -0
- django_cfg/modules/django_client/core/generator/python/__init__.py +16 -0
- django_cfg/modules/django_client/core/generator/python/async_client_gen.py +174 -0
- django_cfg/modules/django_client/core/generator/python/files_generator.py +180 -0
- django_cfg/modules/django_client/core/generator/python/generator.py +182 -0
- django_cfg/modules/django_client/core/generator/python/models_generator.py +318 -0
- django_cfg/modules/django_client/core/generator/python/operations_generator.py +278 -0
- django_cfg/modules/django_client/core/generator/python/sync_client_gen.py +102 -0
- django_cfg/modules/django_client/core/generator/python/templates/__init__.py.jinja +9 -0
- django_cfg/modules/django_client/core/generator/python/templates/api_wrapper.py.jinja +153 -0
- django_cfg/modules/django_client/core/generator/python/templates/app_init.py.jinja +6 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/app_client.py.jinja +18 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/flat_client.py.jinja +38 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/main_client.py.jinja +68 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/main_client_file.py.jinja +14 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/operation_method.py.jinja +9 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/sub_client.py.jinja +18 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/sync_main_client.py.jinja +50 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/sync_operation_method.py.jinja +9 -0
- django_cfg/modules/django_client/core/generator/python/templates/client/sync_sub_client.py.jinja +18 -0
- django_cfg/modules/django_client/core/generator/python/templates/client_file.py.jinja +13 -0
- django_cfg/modules/django_client/core/generator/python/templates/main_init.py.jinja +52 -0
- django_cfg/modules/django_client/core/generator/python/templates/models/app_models.py.jinja +17 -0
- django_cfg/modules/django_client/core/generator/python/templates/models/enum_class.py.jinja +17 -0
- django_cfg/modules/django_client/core/generator/python/templates/models/enums.py.jinja +8 -0
- django_cfg/modules/django_client/core/generator/python/templates/models/models.py.jinja +17 -0
- django_cfg/modules/django_client/core/generator/python/templates/models/schema_class.py.jinja +21 -0
- django_cfg/modules/django_client/core/generator/python/templates/pyproject.toml.jinja +55 -0
- django_cfg/modules/django_client/core/generator/python/templates/utils/logger.py.jinja +255 -0
- django_cfg/modules/django_client/core/generator/python/templates/utils/retry.py.jinja +271 -0
- django_cfg/modules/django_client/core/generator/python/templates/utils/schema.py.jinja +12 -0
- django_cfg/modules/django_client/core/generator/typescript/__init__.py +14 -0
- django_cfg/modules/django_client/core/generator/typescript/client_generator.py +165 -0
- django_cfg/modules/django_client/core/generator/typescript/fetchers_generator.py +428 -0
- django_cfg/modules/django_client/core/generator/typescript/files_generator.py +207 -0
- django_cfg/modules/django_client/core/generator/typescript/generator.py +432 -0
- django_cfg/modules/django_client/core/generator/typescript/hooks_generator.py +536 -0
- django_cfg/modules/django_client/core/generator/typescript/models_generator.py +245 -0
- django_cfg/modules/django_client/core/generator/typescript/operations_generator.py +298 -0
- django_cfg/modules/django_client/core/generator/typescript/schemas_generator.py +329 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/api_instance.ts.jinja +131 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/app_index.ts.jinja +2 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/client/app_client.ts.jinja +18 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/client/client.ts.jinja +403 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/client/flat_client.ts.jinja +109 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/client/main_client_file.ts.jinja +10 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/client/operation.ts.jinja +61 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/client/sub_client.ts.jinja +15 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/client_file.ts.jinja +9 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/fetchers/fetchers.ts.jinja +45 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/fetchers/index.ts.jinja +30 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/index.ts.jinja +5 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/main_index.ts.jinja +268 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/models/app_models.ts.jinja +8 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/models/enums.ts.jinja +4 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/models/models.ts.jinja +8 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/package.json.jinja +52 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/schemas/index.ts.jinja +21 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/schemas/schema.ts.jinja +24 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/tsconfig.json.jinja +20 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/utils/errors.ts.jinja +116 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/utils/http.ts.jinja +98 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/utils/logger.ts.jinja +259 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/utils/retry.ts.jinja +175 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/utils/schema.ts.jinja +7 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/utils/storage.ts.jinja +158 -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 +427 -0
- django_cfg/modules/django_client/management/commands/validate_openapi.py +343 -0
- django_cfg/modules/django_client/pytest.ini +30 -0
- django_cfg/modules/django_client/spectacular/__init__.py +10 -0
- django_cfg/modules/django_client/spectacular/async_detection.py +187 -0
- django_cfg/modules/django_client/spectacular/enum_naming.py +192 -0
- django_cfg/modules/django_client/urls.py +72 -0
- django_cfg/{dashboard → modules/django_dashboard}/DEBUG_README.md +2 -2
- django_cfg/{dashboard → modules/django_dashboard}/REFACTORING_SUMMARY.md +1 -1
- django_cfg/modules/django_dashboard/management/__init__.py +0 -0
- django_cfg/modules/django_dashboard/management/commands/__init__.py +0 -0
- django_cfg/{dashboard → modules/django_dashboard}/management/commands/debug_dashboard.py +5 -5
- django_cfg/modules/django_dashboard/sections/documentation.py +391 -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/LOGGING_GUIDE.md +1 -1
- 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 +21 -10
- django_cfg/modules/django_unfold/callbacks/revolution.py +41 -36
- 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.10.dist-info → django_cfg-1.4.13.dist-info}/METADATA +2 -2
- {django_cfg-1.4.10.dist-info → django_cfg-1.4.13.dist-info}/RECORD +224 -74
- django_cfg/management/commands/generate.py +0 -107
- /django_cfg/models/django/{revolution.py → revolution_legacy.py} +0 -0
- /django_cfg/{dashboard → modules/django_admin}/management/__init__.py +0 -0
- /django_cfg/{dashboard → modules/django_admin}/management/commands/__init__.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/__init__.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/components.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/debug.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/sections/__init__.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/sections/base.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/sections/commands.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/sections/overview.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/sections/stats.py +0 -0
- /django_cfg/{dashboard → modules/django_dashboard}/sections/system.py +0 -0
- {django_cfg-1.4.10.dist-info → django_cfg-1.4.13.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.10.dist-info → django_cfg-1.4.13.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.10.dist-info → django_cfg-1.4.13.dist-info}/licenses/LICENSE +0 -0
@@ -1,302 +1,22 @@
|
|
1
1
|
"""
|
2
|
-
|
3
|
-
Enhanced superuser creation with validation and configuration.
|
4
|
-
"""
|
5
|
-
|
6
|
-
import os
|
7
|
-
import getpass
|
8
|
-
from pathlib import Path
|
9
|
-
from django.core.management.base import BaseCommand
|
10
|
-
from django.core.management import call_command
|
11
|
-
from django.contrib.auth import get_user_model
|
12
|
-
from django.core.validators import validate_email
|
13
|
-
from django.core.exceptions import ValidationError
|
14
|
-
from django.conf import settings
|
15
|
-
import questionary
|
16
|
-
from datetime import datetime
|
17
|
-
from django_cfg.modules.django_logging import get_logger
|
18
|
-
|
19
|
-
User = get_user_model()
|
20
|
-
|
21
|
-
|
22
|
-
logger = get_logger('superuser')
|
23
|
-
|
24
|
-
class Command(BaseCommand):
|
25
|
-
# Web execution metadata
|
26
|
-
web_executable = False
|
27
|
-
requires_input = True
|
28
|
-
is_destructive = False
|
29
|
-
|
30
|
-
help = 'Create a superuser with enhanced validation and configuration'
|
2
|
+
Django-CFG wrapper for superuser command.
|
31
3
|
|
32
|
-
|
33
|
-
|
34
|
-
'--username',
|
35
|
-
type=str,
|
36
|
-
help='Username for superuser'
|
37
|
-
)
|
38
|
-
parser.add_argument(
|
39
|
-
'--email',
|
40
|
-
type=str,
|
41
|
-
help='Email for superuser'
|
42
|
-
)
|
43
|
-
parser.add_argument(
|
44
|
-
'--password',
|
45
|
-
type=str,
|
46
|
-
help='Password for superuser'
|
47
|
-
)
|
48
|
-
parser.add_argument(
|
49
|
-
'--first-name',
|
50
|
-
type=str,
|
51
|
-
help='First name for superuser'
|
52
|
-
)
|
53
|
-
parser.add_argument(
|
54
|
-
'--last-name',
|
55
|
-
type=str,
|
56
|
-
help='Last name for superuser'
|
57
|
-
)
|
58
|
-
parser.add_argument(
|
59
|
-
'--interactive',
|
60
|
-
action='store_true',
|
61
|
-
help='Run in interactive mode'
|
62
|
-
)
|
4
|
+
This is a simple alias for django_admin.management.commands.superuser.
|
5
|
+
All logic is in django_admin module.
|
63
6
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
self.create_superuser_non_interactive(options)
|
70
|
-
|
71
|
-
def create_superuser_interactive(self):
|
72
|
-
"""Create superuser interactively"""
|
73
|
-
self.stdout.write(self.style.SUCCESS('\n👑 Superuser Creation Tool - Django Config Toolkit\n'))
|
74
|
-
|
75
|
-
# Check if superuser already exists
|
76
|
-
if User.objects.filter(is_superuser=True).exists():
|
77
|
-
self.stdout.write(self.style.WARNING('⚠️ Superuser already exists'))
|
78
|
-
overwrite = questionary.confirm('Do you want to create another superuser?').ask()
|
79
|
-
if not overwrite:
|
80
|
-
self.stdout.write('Goodbye! 👋')
|
81
|
-
return
|
82
|
-
|
83
|
-
# Get user details
|
84
|
-
user_data = self.get_user_details_interactive()
|
85
|
-
|
86
|
-
# Validate data
|
87
|
-
if not self.validate_user_data(user_data):
|
88
|
-
return
|
89
|
-
|
90
|
-
# Create superuser
|
91
|
-
self.create_superuser(user_data)
|
92
|
-
|
93
|
-
def create_superuser_non_interactive(self, options):
|
94
|
-
"""Create superuser non-interactively"""
|
95
|
-
user_data = {
|
96
|
-
'username': options['username'],
|
97
|
-
'email': options['email'],
|
98
|
-
'password': options['password'],
|
99
|
-
'first_name': options['first_name'] or '',
|
100
|
-
'last_name': options['last_name'] or '',
|
101
|
-
}
|
102
|
-
|
103
|
-
# Validate required fields
|
104
|
-
if not all([user_data['username'], user_data['email'], user_data['password']]):
|
105
|
-
self.stdout.write(self.style.ERROR('❌ Username, email, and password are required'))
|
106
|
-
return
|
107
|
-
|
108
|
-
# Validate data
|
109
|
-
if not self.validate_user_data(user_data):
|
110
|
-
return
|
111
|
-
|
112
|
-
# Create superuser
|
113
|
-
self.create_superuser(user_data)
|
114
|
-
|
115
|
-
def get_user_details_interactive(self):
|
116
|
-
"""Get user details interactively"""
|
117
|
-
user_data = {}
|
118
|
-
|
119
|
-
# Username
|
120
|
-
while True:
|
121
|
-
username = questionary.text('Username:').ask()
|
122
|
-
if not username:
|
123
|
-
self.stdout.write(self.style.ERROR('❌ Username is required'))
|
124
|
-
continue
|
125
|
-
|
126
|
-
if User.objects.filter(username=username).exists():
|
127
|
-
self.stdout.write(self.style.ERROR('❌ Username already exists'))
|
128
|
-
continue
|
129
|
-
|
130
|
-
user_data['username'] = username
|
131
|
-
break
|
132
|
-
|
133
|
-
# Email
|
134
|
-
while True:
|
135
|
-
email = questionary.text('Email:').ask()
|
136
|
-
if not email:
|
137
|
-
self.stdout.write(self.style.ERROR('❌ Email is required'))
|
138
|
-
continue
|
139
|
-
|
140
|
-
try:
|
141
|
-
validate_email(email)
|
142
|
-
except ValidationError:
|
143
|
-
self.stdout.write(self.style.ERROR('❌ Invalid email format'))
|
144
|
-
continue
|
145
|
-
|
146
|
-
if User.objects.filter(email=email).exists():
|
147
|
-
self.stdout.write(self.style.ERROR('❌ Email already exists'))
|
148
|
-
continue
|
149
|
-
|
150
|
-
user_data['email'] = email
|
151
|
-
break
|
152
|
-
|
153
|
-
# Password
|
154
|
-
while True:
|
155
|
-
password = questionary.password('Password:').ask()
|
156
|
-
if not password:
|
157
|
-
self.stdout.write(self.style.ERROR('❌ Password is required'))
|
158
|
-
continue
|
159
|
-
|
160
|
-
if len(password) < 8:
|
161
|
-
self.stdout.write(self.style.WARNING('⚠️ Password should be at least 8 characters'))
|
162
|
-
confirm = questionary.confirm('Continue with weak password?').ask()
|
163
|
-
if not confirm:
|
164
|
-
continue
|
165
|
-
|
166
|
-
confirm_password = questionary.password('Confirm password:').ask()
|
167
|
-
if password != confirm_password:
|
168
|
-
self.stdout.write(self.style.ERROR('❌ Passwords do not match'))
|
169
|
-
continue
|
170
|
-
|
171
|
-
user_data['password'] = password
|
172
|
-
break
|
173
|
-
|
174
|
-
# Optional fields
|
175
|
-
user_data['first_name'] = questionary.text('First name (optional):').ask() or ''
|
176
|
-
user_data['last_name'] = questionary.text('Last name (optional):').ask() or ''
|
177
|
-
|
178
|
-
return user_data
|
179
|
-
|
180
|
-
def validate_user_data(self, user_data):
|
181
|
-
"""Validate user data"""
|
182
|
-
errors = []
|
183
|
-
|
184
|
-
# Check required fields
|
185
|
-
if not user_data.get('username'):
|
186
|
-
errors.append('Username is required')
|
187
|
-
|
188
|
-
if not user_data.get('email'):
|
189
|
-
errors.append('Email is required')
|
190
|
-
|
191
|
-
if not user_data.get('password'):
|
192
|
-
errors.append('Password is required')
|
193
|
-
|
194
|
-
# Validate email format
|
195
|
-
if user_data.get('email'):
|
196
|
-
try:
|
197
|
-
validate_email(user_data['email'])
|
198
|
-
except ValidationError:
|
199
|
-
errors.append('Invalid email format')
|
200
|
-
|
201
|
-
# Check if user already exists
|
202
|
-
if user_data.get('username') and User.objects.filter(username=user_data['username']).exists():
|
203
|
-
errors.append('Username already exists')
|
204
|
-
|
205
|
-
if user_data.get('email') and User.objects.filter(email=user_data['email']).exists():
|
206
|
-
errors.append('Email already exists')
|
207
|
-
|
208
|
-
# Password strength
|
209
|
-
if user_data.get('password') and len(user_data['password']) < 8:
|
210
|
-
errors.append('Password should be at least 8 characters')
|
211
|
-
|
212
|
-
if errors:
|
213
|
-
self.stdout.write(self.style.ERROR('❌ Validation errors:'))
|
214
|
-
for error in errors:
|
215
|
-
self.stdout.write(f' - {error}')
|
216
|
-
return False
|
217
|
-
|
218
|
-
return True
|
7
|
+
Usage:
|
8
|
+
python manage.py superuser
|
9
|
+
python manage.py superuser --interactive
|
10
|
+
python manage.py superuser --username admin --email admin@example.com --password secret
|
11
|
+
"""
|
219
12
|
|
220
|
-
|
221
|
-
"""Create the superuser"""
|
222
|
-
try:
|
223
|
-
# Create user
|
224
|
-
user = User.objects.create_user(
|
225
|
-
username=user_data['username'],
|
226
|
-
email=user_data['email'],
|
227
|
-
password=user_data['password'],
|
228
|
-
first_name=user_data['first_name'],
|
229
|
-
last_name=user_data['last_name'],
|
230
|
-
is_staff=True,
|
231
|
-
is_superuser=True,
|
232
|
-
is_active=True
|
233
|
-
)
|
234
|
-
|
235
|
-
# Save user details to file
|
236
|
-
self.save_superuser_details(user, user_data['password'])
|
237
|
-
|
238
|
-
self.stdout.write(self.style.SUCCESS(f'✅ Superuser created successfully!'))
|
239
|
-
self.stdout.write(f'👤 Username: {user.username}')
|
240
|
-
self.stdout.write(f'📧 Email: {user.email}')
|
241
|
-
self.stdout.write(f'👑 Is Superuser: {user.is_superuser}')
|
242
|
-
self.stdout.write(f'🔧 Is Staff: {user.is_staff}')
|
243
|
-
self.stdout.write(f'✅ Is Active: {user.is_active}')
|
244
|
-
|
245
|
-
# Show next steps
|
246
|
-
self.show_next_steps()
|
247
|
-
|
248
|
-
except Exception as e:
|
249
|
-
self.stdout.write(self.style.ERROR(f'❌ Error creating superuser: {e}'))
|
13
|
+
from django_cfg.modules.django_admin.management.commands.superuser import Command as SuperuserCommand
|
250
14
|
|
251
|
-
def save_superuser_details(self, user, password):
|
252
|
-
"""Save superuser details to file"""
|
253
|
-
# Create superusers directory
|
254
|
-
superusers_dir = Path('superusers')
|
255
|
-
superusers_dir.mkdir(exist_ok=True)
|
256
|
-
|
257
|
-
# Create details file
|
258
|
-
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
259
|
-
filename = f"superuser_{user.username}_{timestamp}.txt"
|
260
|
-
filepath = superusers_dir / filename
|
261
|
-
|
262
|
-
with open(filepath, 'w') as f:
|
263
|
-
f.write(f"Superuser Details\n")
|
264
|
-
f.write(f"================\n\n")
|
265
|
-
f.write(f"Username: {user.username}\n")
|
266
|
-
f.write(f"Email: {user.email}\n")
|
267
|
-
f.write(f"First Name: {user.first_name}\n")
|
268
|
-
f.write(f"Is Superuser: {user.is_superuser}\n")
|
269
|
-
f.write(f"Is Staff: {user.is_staff}\n")
|
270
|
-
f.write(f"Is Active: {user.is_active}\n")
|
271
|
-
f.write(f"Date Created: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
|
272
|
-
f.write(f"\n⚠️ IMPORTANT: Store this password securely!\n")
|
273
|
-
f.write(f"Password: {password}\n")
|
274
|
-
|
275
|
-
self.stdout.write(f'💾 Superuser details saved to: {filepath}')
|
276
15
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
self.stdout.write('1. 🚀 Start your Django server: python manage.py runserver')
|
281
|
-
self.stdout.write('2. 🌐 Visit Django admin: http://localhost:8000/admin/')
|
282
|
-
self.stdout.write('3. 🔑 Login with your superuser credentials')
|
283
|
-
self.stdout.write('4. ⚙️ Configure your application settings')
|
284
|
-
self.stdout.write('5. 📚 Read the Django Config Toolkit documentation')
|
285
|
-
|
286
|
-
# Show health check
|
287
|
-
self.stdout.write('\n🔍 Health Check:')
|
288
|
-
try:
|
289
|
-
call_command('check', verbosity=0)
|
290
|
-
self.stdout.write('✅ Django configuration is valid')
|
291
|
-
except Exception as e:
|
292
|
-
self.stdout.write(f'⚠️ Django configuration issues: {e}')
|
16
|
+
class Command(SuperuserCommand):
|
17
|
+
"""
|
18
|
+
Alias for superuser command.
|
293
19
|
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
if superusers.exists():
|
298
|
-
self.stdout.write(self.style.WARNING(f'⚠️ Found {superusers.count()} existing superuser(s):'))
|
299
|
-
for user in superusers:
|
300
|
-
self.stdout.write(f' - {user.username} ({user.email})')
|
301
|
-
return True
|
302
|
-
return False
|
20
|
+
Simply inherits from SuperuserCommand without any changes.
|
21
|
+
"""
|
22
|
+
pass
|
@@ -1,226 +1,23 @@
|
|
1
1
|
"""
|
2
|
-
Django
|
2
|
+
Django-CFG wrapper for task_clear command.
|
3
3
|
|
4
|
-
This
|
5
|
-
|
6
|
-
"""
|
4
|
+
This is a simple alias for django_tasks.management.commands.task_clear.
|
5
|
+
All logic is in django_tasks module.
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
Usage:
|
8
|
+
python manage.py task_clear
|
9
|
+
python manage.py task_clear --queue default
|
10
|
+
python manage.py task_clear --failed-only
|
11
|
+
python manage.py task_clear --confirm
|
12
|
+
"""
|
13
13
|
|
14
|
-
|
14
|
+
from django_cfg.modules.django_tasks.management.commands.task_clear import Command as TaskClearCommand
|
15
15
|
|
16
16
|
|
17
|
-
class Command(
|
17
|
+
class Command(TaskClearCommand):
|
18
18
|
"""
|
19
|
-
|
19
|
+
Alias for task_clear command.
|
20
20
|
|
21
|
-
|
22
|
-
- Clear all tasks from specific queues
|
23
|
-
- Clear only failed tasks
|
24
|
-
- Clear all tasks from all queues
|
21
|
+
Simply inherits from TaskClearCommand without any changes.
|
25
22
|
"""
|
26
|
-
|
27
|
-
# Web execution metadata
|
28
|
-
web_executable = False
|
29
|
-
requires_input = True
|
30
|
-
is_destructive = True
|
31
|
-
|
32
|
-
help = "Clear tasks from Dramatiq queues"
|
33
|
-
|
34
|
-
def add_arguments(self, parser):
|
35
|
-
"""Add command line arguments."""
|
36
|
-
parser.add_argument(
|
37
|
-
"--queue",
|
38
|
-
type=str,
|
39
|
-
help="Specific queue to clear (default: all queues)",
|
40
|
-
)
|
41
|
-
parser.add_argument(
|
42
|
-
"--failed-only",
|
43
|
-
action="store_true",
|
44
|
-
help="Clear only failed tasks",
|
45
|
-
)
|
46
|
-
parser.add_argument(
|
47
|
-
"--confirm",
|
48
|
-
action="store_true",
|
49
|
-
help="Skip confirmation prompt",
|
50
|
-
)
|
51
|
-
parser.add_argument(
|
52
|
-
"--dry-run",
|
53
|
-
action="store_true",
|
54
|
-
help="Show what would be cleared without actually clearing",
|
55
|
-
)
|
56
|
-
|
57
|
-
def handle(self, *args, **options):
|
58
|
-
"""Handle the command execution."""
|
59
|
-
logger.info("Starting task_clear command")
|
60
|
-
|
61
|
-
try:
|
62
|
-
# Import here to avoid issues if dramatiq is not installed
|
63
|
-
from django_cfg.modules.django_tasks import get_task_service
|
64
|
-
|
65
|
-
# Get task service
|
66
|
-
task_service = get_task_service()
|
67
|
-
|
68
|
-
# Check if task system is enabled
|
69
|
-
if not task_service.is_enabled():
|
70
|
-
raise CommandError(
|
71
|
-
"Task system is not enabled. "
|
72
|
-
"Please configure 'tasks' in your Django-CFG configuration."
|
73
|
-
)
|
74
|
-
|
75
|
-
# Get task manager
|
76
|
-
manager = task_service.manager
|
77
|
-
if not manager:
|
78
|
-
raise CommandError("Task manager not available")
|
79
|
-
|
80
|
-
# Get configuration
|
81
|
-
config = task_service.config
|
82
|
-
if not config:
|
83
|
-
raise CommandError("Task configuration not available")
|
84
|
-
|
85
|
-
# Determine queues to clear
|
86
|
-
if options.get("queue"):
|
87
|
-
queues_to_clear = [options["queue"]]
|
88
|
-
# Validate queue exists
|
89
|
-
if options["queue"] not in config.get_effective_queues():
|
90
|
-
self.stdout.write(
|
91
|
-
self.style.WARNING(
|
92
|
-
f"Queue '{options['queue']}' not in configured queues: "
|
93
|
-
f"{', '.join(config.get_effective_queues())}"
|
94
|
-
)
|
95
|
-
)
|
96
|
-
else:
|
97
|
-
queues_to_clear = config.get_effective_queues()
|
98
|
-
|
99
|
-
# Show what will be cleared
|
100
|
-
self._show_clear_plan(queues_to_clear, options)
|
101
|
-
|
102
|
-
if options["dry_run"]:
|
103
|
-
self.stdout.write(
|
104
|
-
self.style.SUCCESS("Dry run completed - no tasks were cleared")
|
105
|
-
)
|
106
|
-
return
|
107
|
-
|
108
|
-
# Confirm action
|
109
|
-
if not options["confirm"]:
|
110
|
-
if not self._confirm_clear(queues_to_clear, options):
|
111
|
-
self.stdout.write("Operation cancelled")
|
112
|
-
return
|
113
|
-
|
114
|
-
# Perform clearing
|
115
|
-
self._clear_queues(manager, queues_to_clear, options)
|
116
|
-
|
117
|
-
except ImportError:
|
118
|
-
raise CommandError(
|
119
|
-
"Dramatiq dependencies not installed. "
|
120
|
-
"Install with: pip install django-cfg[tasks]"
|
121
|
-
)
|
122
|
-
except Exception as e:
|
123
|
-
logger.exception("Failed to clear tasks")
|
124
|
-
raise CommandError(f"Failed to clear tasks: {e}")
|
125
|
-
|
126
|
-
def _show_clear_plan(self, queues: List[str], options):
|
127
|
-
"""Show what will be cleared."""
|
128
|
-
self.stdout.write(
|
129
|
-
self.style.SUCCESS("=== Clear Plan ===")
|
130
|
-
)
|
131
|
-
|
132
|
-
if options.get("failed_only"):
|
133
|
-
self.stdout.write("Action: Clear FAILED tasks only")
|
134
|
-
else:
|
135
|
-
self.stdout.write("Action: Clear ALL tasks")
|
136
|
-
|
137
|
-
self.stdout.write(f"Queues: {', '.join(queues)}")
|
138
|
-
|
139
|
-
# Get current queue statistics
|
140
|
-
try:
|
141
|
-
from django_cfg.modules.django_tasks import get_task_service
|
142
|
-
task_service = get_task_service()
|
143
|
-
manager = task_service.manager
|
144
|
-
|
145
|
-
if manager:
|
146
|
-
queue_stats = manager.get_queue_stats()
|
147
|
-
|
148
|
-
self.stdout.write("\nCurrent Queue Statistics:")
|
149
|
-
for stat in queue_stats:
|
150
|
-
if stat["name"] in queues:
|
151
|
-
name = stat["name"]
|
152
|
-
pending = stat.get("pending", 0)
|
153
|
-
failed = stat.get("failed", 0)
|
154
|
-
|
155
|
-
if options.get("failed_only"):
|
156
|
-
self.stdout.write(f" {name}: {failed} failed tasks")
|
157
|
-
else:
|
158
|
-
total = pending + stat.get("running", 0) + failed
|
159
|
-
self.stdout.write(f" {name}: {total} total tasks")
|
160
|
-
except Exception as e:
|
161
|
-
self.stdout.write(f"Could not get queue statistics: {e}")
|
162
|
-
|
163
|
-
self.stdout.write()
|
164
|
-
|
165
|
-
def _confirm_clear(self, queues: List[str], options) -> bool:
|
166
|
-
"""Confirm the clear operation with user."""
|
167
|
-
if options.get("failed_only"):
|
168
|
-
action = "clear FAILED tasks"
|
169
|
-
else:
|
170
|
-
action = "clear ALL tasks"
|
171
|
-
|
172
|
-
queue_list = ", ".join(queues)
|
173
|
-
|
174
|
-
self.stdout.write(
|
175
|
-
self.style.WARNING(
|
176
|
-
f"This will {action} from queues: {queue_list}"
|
177
|
-
)
|
178
|
-
)
|
179
|
-
|
180
|
-
response = input("Are you sure? [y/N]: ").lower().strip()
|
181
|
-
return response in ["y", "yes"]
|
182
|
-
|
183
|
-
def _clear_queues(self, manager, queues: List[str], options):
|
184
|
-
"""Clear the specified queues."""
|
185
|
-
cleared_count = 0
|
186
|
-
|
187
|
-
self.stdout.write(
|
188
|
-
self.style.SUCCESS("Starting queue clearing...")
|
189
|
-
)
|
190
|
-
|
191
|
-
for queue_name in queues:
|
192
|
-
try:
|
193
|
-
self.stdout.write(f"Clearing queue: {queue_name}")
|
194
|
-
|
195
|
-
if options.get("failed_only"):
|
196
|
-
# Clear only failed tasks
|
197
|
-
# TODO: Implement failed task clearing
|
198
|
-
# This would require specific Dramatiq broker methods
|
199
|
-
count = 0 # Placeholder
|
200
|
-
self.stdout.write(f" Cleared {count} failed tasks")
|
201
|
-
else:
|
202
|
-
# Clear all tasks
|
203
|
-
success = manager.clear_queue(queue_name)
|
204
|
-
if success:
|
205
|
-
# TODO: Get actual count of cleared tasks
|
206
|
-
count = 0 # Placeholder
|
207
|
-
self.stdout.write(f" Cleared {count} tasks")
|
208
|
-
cleared_count += count
|
209
|
-
else:
|
210
|
-
self.stdout.write(
|
211
|
-
self.style.ERROR(f" Failed to clear queue: {queue_name}")
|
212
|
-
)
|
213
|
-
|
214
|
-
except Exception as e:
|
215
|
-
self.stdout.write(
|
216
|
-
self.style.ERROR(f" Error clearing queue {queue_name}: {e}")
|
217
|
-
)
|
218
|
-
|
219
|
-
if cleared_count > 0:
|
220
|
-
self.stdout.write(
|
221
|
-
self.style.SUCCESS(f"Successfully cleared {cleared_count} tasks")
|
222
|
-
)
|
223
|
-
else:
|
224
|
-
self.stdout.write(
|
225
|
-
self.style.WARNING("No tasks were cleared")
|
226
|
-
)
|
23
|
+
pass
|