createsonline 0.1.26__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.
- createsonline/__init__.py +46 -0
- createsonline/admin/__init__.py +7 -0
- createsonline/admin/content.py +526 -0
- createsonline/admin/crud.py +805 -0
- createsonline/admin/field_builder.py +559 -0
- createsonline/admin/integration.py +482 -0
- createsonline/admin/interface.py +2562 -0
- createsonline/admin/model_creator.py +513 -0
- createsonline/admin/model_manager.py +388 -0
- createsonline/admin/modern_dashboard.py +498 -0
- createsonline/admin/permissions.py +264 -0
- createsonline/admin/user_forms.py +594 -0
- createsonline/ai/__init__.py +202 -0
- createsonline/ai/fields.py +1226 -0
- createsonline/ai/orm.py +325 -0
- createsonline/ai/services.py +1244 -0
- createsonline/app.py +506 -0
- createsonline/auth/__init__.py +8 -0
- createsonline/auth/management.py +228 -0
- createsonline/auth/models.py +552 -0
- createsonline/cli/__init__.py +5 -0
- createsonline/cli/commands/__init__.py +122 -0
- createsonline/cli/commands/database.py +416 -0
- createsonline/cli/commands/info.py +173 -0
- createsonline/cli/commands/initdb.py +218 -0
- createsonline/cli/commands/project.py +545 -0
- createsonline/cli/commands/serve.py +173 -0
- createsonline/cli/commands/shell.py +93 -0
- createsonline/cli/commands/users.py +148 -0
- createsonline/cli/main.py +2041 -0
- createsonline/cli/manage.py +274 -0
- createsonline/config/__init__.py +9 -0
- createsonline/config/app.py +2577 -0
- createsonline/config/database.py +179 -0
- createsonline/config/docs.py +384 -0
- createsonline/config/errors.py +160 -0
- createsonline/config/orm.py +43 -0
- createsonline/config/request.py +93 -0
- createsonline/config/settings.py +176 -0
- createsonline/data/__init__.py +23 -0
- createsonline/data/dataframe.py +925 -0
- createsonline/data/io.py +453 -0
- createsonline/data/series.py +557 -0
- createsonline/database/__init__.py +60 -0
- createsonline/database/abstraction.py +440 -0
- createsonline/database/assistant.py +585 -0
- createsonline/database/fields.py +442 -0
- createsonline/database/migrations.py +132 -0
- createsonline/database/models.py +604 -0
- createsonline/database.py +438 -0
- createsonline/http/__init__.py +28 -0
- createsonline/http/client.py +535 -0
- createsonline/ml/__init__.py +55 -0
- createsonline/ml/classification.py +552 -0
- createsonline/ml/clustering.py +680 -0
- createsonline/ml/metrics.py +542 -0
- createsonline/ml/neural.py +560 -0
- createsonline/ml/preprocessing.py +784 -0
- createsonline/ml/regression.py +501 -0
- createsonline/performance/__init__.py +19 -0
- createsonline/performance/cache.py +444 -0
- createsonline/performance/compression.py +335 -0
- createsonline/performance/core.py +419 -0
- createsonline/project_init.py +789 -0
- createsonline/routing.py +528 -0
- createsonline/security/__init__.py +34 -0
- createsonline/security/core.py +811 -0
- createsonline/security/encryption.py +349 -0
- createsonline/server.py +295 -0
- createsonline/static/css/admin.css +263 -0
- createsonline/static/css/common.css +358 -0
- createsonline/static/css/dashboard.css +89 -0
- createsonline/static/favicon.ico +0 -0
- createsonline/static/icons/icon-128x128.png +0 -0
- createsonline/static/icons/icon-128x128.webp +0 -0
- createsonline/static/icons/icon-16x16.png +0 -0
- createsonline/static/icons/icon-16x16.webp +0 -0
- createsonline/static/icons/icon-180x180.png +0 -0
- createsonline/static/icons/icon-180x180.webp +0 -0
- createsonline/static/icons/icon-192x192.png +0 -0
- createsonline/static/icons/icon-192x192.webp +0 -0
- createsonline/static/icons/icon-256x256.png +0 -0
- createsonline/static/icons/icon-256x256.webp +0 -0
- createsonline/static/icons/icon-32x32.png +0 -0
- createsonline/static/icons/icon-32x32.webp +0 -0
- createsonline/static/icons/icon-384x384.png +0 -0
- createsonline/static/icons/icon-384x384.webp +0 -0
- createsonline/static/icons/icon-48x48.png +0 -0
- createsonline/static/icons/icon-48x48.webp +0 -0
- createsonline/static/icons/icon-512x512.png +0 -0
- createsonline/static/icons/icon-512x512.webp +0 -0
- createsonline/static/icons/icon-64x64.png +0 -0
- createsonline/static/icons/icon-64x64.webp +0 -0
- createsonline/static/image/android-chrome-192x192.png +0 -0
- createsonline/static/image/android-chrome-512x512.png +0 -0
- createsonline/static/image/apple-touch-icon.png +0 -0
- createsonline/static/image/favicon-16x16.png +0 -0
- createsonline/static/image/favicon-32x32.png +0 -0
- createsonline/static/image/favicon.ico +0 -0
- createsonline/static/image/favicon.svg +17 -0
- createsonline/static/image/icon-128x128.png +0 -0
- createsonline/static/image/icon-128x128.webp +0 -0
- createsonline/static/image/icon-16x16.png +0 -0
- createsonline/static/image/icon-16x16.webp +0 -0
- createsonline/static/image/icon-180x180.png +0 -0
- createsonline/static/image/icon-180x180.webp +0 -0
- createsonline/static/image/icon-192x192.png +0 -0
- createsonline/static/image/icon-192x192.webp +0 -0
- createsonline/static/image/icon-256x256.png +0 -0
- createsonline/static/image/icon-256x256.webp +0 -0
- createsonline/static/image/icon-32x32.png +0 -0
- createsonline/static/image/icon-32x32.webp +0 -0
- createsonline/static/image/icon-384x384.png +0 -0
- createsonline/static/image/icon-384x384.webp +0 -0
- createsonline/static/image/icon-48x48.png +0 -0
- createsonline/static/image/icon-48x48.webp +0 -0
- createsonline/static/image/icon-512x512.png +0 -0
- createsonline/static/image/icon-512x512.webp +0 -0
- createsonline/static/image/icon-64x64.png +0 -0
- createsonline/static/image/icon-64x64.webp +0 -0
- createsonline/static/image/logo-header-h100.png +0 -0
- createsonline/static/image/logo-header-h100.webp +0 -0
- createsonline/static/image/logo-header-h200@2x.png +0 -0
- createsonline/static/image/logo-header-h200@2x.webp +0 -0
- createsonline/static/image/logo.png +0 -0
- createsonline/static/js/admin.js +274 -0
- createsonline/static/site.webmanifest +35 -0
- createsonline/static/templates/admin/base.html +87 -0
- createsonline/static/templates/admin/dashboard.html +217 -0
- createsonline/static/templates/admin/model_form.html +270 -0
- createsonline/static/templates/admin/model_list.html +202 -0
- createsonline/static/test_script.js +15 -0
- createsonline/static/test_styles.css +59 -0
- createsonline/static_files.py +365 -0
- createsonline/templates/404.html +100 -0
- createsonline/templates/admin_login.html +169 -0
- createsonline/templates/base.html +102 -0
- createsonline/templates/index.html +151 -0
- createsonline/templates.py +205 -0
- createsonline/testing.py +322 -0
- createsonline/utils.py +448 -0
- createsonline/validation/__init__.py +49 -0
- createsonline/validation/fields.py +598 -0
- createsonline/validation/models.py +504 -0
- createsonline/validation/validators.py +561 -0
- createsonline/views.py +184 -0
- createsonline-0.1.26.dist-info/METADATA +46 -0
- createsonline-0.1.26.dist-info/RECORD +152 -0
- createsonline-0.1.26.dist-info/WHEEL +5 -0
- createsonline-0.1.26.dist-info/entry_points.txt +2 -0
- createsonline-0.1.26.dist-info/licenses/LICENSE +21 -0
- createsonline-0.1.26.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# createsonline/cli/commands/serve.py
|
|
2
|
+
"""
|
|
3
|
+
CREATESONLINE Server Commands - Pure Internal Implementation
|
|
4
|
+
|
|
5
|
+
Provides serve, dev, and prod commands for running the framework.
|
|
6
|
+
Uses CREATESONLINE's internal pure Python server - NO uvicorn needed!
|
|
7
|
+
"""
|
|
8
|
+
import os
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
# Internal console implementation (fallback for rich)
|
|
13
|
+
try:
|
|
14
|
+
from rich.console import Console
|
|
15
|
+
from rich.panel import Panel
|
|
16
|
+
RICH_AVAILABLE = True
|
|
17
|
+
console = Console()
|
|
18
|
+
except ImportError:
|
|
19
|
+
RICH_AVAILABLE = False
|
|
20
|
+
# Internal console fallback
|
|
21
|
+
class SimpleConsole:
|
|
22
|
+
def print(self, text, **kwargs):
|
|
23
|
+
if isinstance(text, str):
|
|
24
|
+
print(text)
|
|
25
|
+
else:
|
|
26
|
+
print(str(text))
|
|
27
|
+
console = SimpleConsole()
|
|
28
|
+
|
|
29
|
+
# Internal dotenv fallback
|
|
30
|
+
try:
|
|
31
|
+
from dotenv import load_dotenv
|
|
32
|
+
DOTENV_AVAILABLE = True
|
|
33
|
+
except ImportError:
|
|
34
|
+
DOTENV_AVAILABLE = False
|
|
35
|
+
def load_dotenv():
|
|
36
|
+
"""Internal dotenv fallback - reads .env file manually"""
|
|
37
|
+
env_file = Path('.env')
|
|
38
|
+
if env_file.exists():
|
|
39
|
+
with open(env_file, 'r') as f:
|
|
40
|
+
for line in f:
|
|
41
|
+
line = line.strip()
|
|
42
|
+
if line and not line.startswith('#') and '=' in line:
|
|
43
|
+
key, value = line.split('=', 1)
|
|
44
|
+
os.environ[key.strip()] = value.strip()
|
|
45
|
+
|
|
46
|
+
def serve_command(host="0.0.0.0", port=8000, reload=True, workers=1, app_module="main:app"):
|
|
47
|
+
"""🚀 Start CREATESONLINE development server - Pure Internal Implementation"""
|
|
48
|
+
|
|
49
|
+
load_dotenv()
|
|
50
|
+
|
|
51
|
+
if RICH_AVAILABLE:
|
|
52
|
+
console.print(Panel(
|
|
53
|
+
"[bold blue]🚀 CREATESONLINE Framework - Internal Server[/bold blue]\n"
|
|
54
|
+
"[cyan]AI-Native Web Framework[/cyan]\n\n"
|
|
55
|
+
f"[green]Server:[/green] http://{host}:{port}\n"
|
|
56
|
+
f"[green]Mode:[/green] {'Development' if reload else 'Production'}\n"
|
|
57
|
+
f"[green]Workers:[/green] {workers if not reload else 1}\n"
|
|
58
|
+
f"[green]App:[/green] {app_module}\n"
|
|
59
|
+
f"[yellow]Server:[/yellow] CREATESONLINE Internal (Pure Python)",
|
|
60
|
+
title="🌐 Server Starting",
|
|
61
|
+
border_style="blue"
|
|
62
|
+
))
|
|
63
|
+
else:
|
|
64
|
+
print("🚀 CREATESONLINE Framework - Internal Server")
|
|
65
|
+
print("AI-Native Web Framework")
|
|
66
|
+
print(f"Server: http://{host}:{port}")
|
|
67
|
+
print(f"Mode: {'Development' if reload else 'Production'}")
|
|
68
|
+
print(f"Workers: {workers if not reload else 1}")
|
|
69
|
+
print(f"App: {app_module}")
|
|
70
|
+
print("Server: CREATESONLINE Internal (Pure Python)")
|
|
71
|
+
|
|
72
|
+
# Use internal server - just run the app file directly
|
|
73
|
+
try:
|
|
74
|
+
if os.path.exists("main.py"):
|
|
75
|
+
sys.exit(os.system(f"{sys.executable} main.py"))
|
|
76
|
+
elif os.path.exists("app.py"):
|
|
77
|
+
sys.exit(os.system(f"{sys.executable} app.py"))
|
|
78
|
+
else:
|
|
79
|
+
console.print("❌ No main.py or app.py found. Create one to run your app.")
|
|
80
|
+
return
|
|
81
|
+
except KeyboardInterrupt:
|
|
82
|
+
console.print("\nServer stopped by user")
|
|
83
|
+
except Exception as e:
|
|
84
|
+
console.print(f"Server error: {e}")
|
|
85
|
+
|
|
86
|
+
def dev_command(host="127.0.0.1", port=8000, app_module="main:app"):
|
|
87
|
+
"""🔧 Start development server with auto-reload and debugging - Pure Independence"""
|
|
88
|
+
|
|
89
|
+
load_dotenv()
|
|
90
|
+
|
|
91
|
+
if RICH_AVAILABLE:
|
|
92
|
+
console.print(Panel(
|
|
93
|
+
"[bold green]🔧 CREATESONLINE Development Mode - Pure Independence[/bold green]\n"
|
|
94
|
+
"[cyan]Enhanced development experience - Zero external dependencies[/cyan]\n\n"
|
|
95
|
+
"[green]Features:[/green]\n"
|
|
96
|
+
"• Auto-reload on file changes\n"
|
|
97
|
+
"• Verbose logging\n"
|
|
98
|
+
"• Error debugging\n"
|
|
99
|
+
"• Hot module reloading\n"
|
|
100
|
+
"• Pure internal implementation",
|
|
101
|
+
title="🛠️ Pure Development Server",
|
|
102
|
+
border_style="green"
|
|
103
|
+
))
|
|
104
|
+
else:
|
|
105
|
+
print("🔧 CREATESONLINE Development Mode - Pure Independence")
|
|
106
|
+
print("Enhanced development experience - Zero external dependencies")
|
|
107
|
+
print("Features: Auto-reload, Verbose logging, Error debugging, Hot module reloading")
|
|
108
|
+
|
|
109
|
+
# Use internal server - just run the app file directly
|
|
110
|
+
try:
|
|
111
|
+
if os.path.exists("main.py"):
|
|
112
|
+
sys.exit(os.system(f"{sys.executable} main.py"))
|
|
113
|
+
elif os.path.exists("app.py"):
|
|
114
|
+
sys.exit(os.system(f"{sys.executable} app.py"))
|
|
115
|
+
else:
|
|
116
|
+
console.print("❌ No main.py or app.py found. Create one to run your app.")
|
|
117
|
+
return
|
|
118
|
+
except KeyboardInterrupt:
|
|
119
|
+
console.print("\nDevelopment server stopped")
|
|
120
|
+
except Exception as e:
|
|
121
|
+
console.print(f"Development server error: {e}")
|
|
122
|
+
|
|
123
|
+
def prod_command(host="0.0.0.0", port=8000, workers=4, app_module="main:app"):
|
|
124
|
+
"""🏭 Start production server with optimized settings - Pure Independence"""
|
|
125
|
+
|
|
126
|
+
load_dotenv()
|
|
127
|
+
|
|
128
|
+
if RICH_AVAILABLE:
|
|
129
|
+
console.print(Panel(
|
|
130
|
+
"[bold red]🏭 CREATESONLINE Production Mode - Pure Independence[/bold red]\n"
|
|
131
|
+
"[cyan]Pure Independence - Optimized for performance and stability[/cyan]\n\n"
|
|
132
|
+
f"[green]Workers:[/green] {workers}\n"
|
|
133
|
+
f"[green]Host:[/green] {host}:{port}\n"
|
|
134
|
+
"[green]Features:[/green]\n"
|
|
135
|
+
"• Multiple worker processes\n"
|
|
136
|
+
"• Optimized logging\n"
|
|
137
|
+
"• Production error handling\n"
|
|
138
|
+
"• Pure internal implementation\n"
|
|
139
|
+
"• Zero external performance dependencies",
|
|
140
|
+
title="🚀 Production Server",
|
|
141
|
+
border_style="red"
|
|
142
|
+
))
|
|
143
|
+
else:
|
|
144
|
+
print("🏭 CREATESONLINE Production Mode - Pure Independence")
|
|
145
|
+
print("Pure Independence - Optimized for performance and stability")
|
|
146
|
+
print(f"Workers: {workers}")
|
|
147
|
+
print(f"Host: {host}:{port}")
|
|
148
|
+
print("Features: Multiple workers, Optimized logging, Production error handling")
|
|
149
|
+
|
|
150
|
+
# Use internal server - just run the app file directly
|
|
151
|
+
try:
|
|
152
|
+
if os.path.exists("main.py"):
|
|
153
|
+
sys.exit(os.system(f"{sys.executable} main.py"))
|
|
154
|
+
elif os.path.exists("app.py"):
|
|
155
|
+
sys.exit(os.system(f"{sys.executable} app.py"))
|
|
156
|
+
else:
|
|
157
|
+
console.print("❌ No main.py or app.py found for production!")
|
|
158
|
+
console.print("Create your application file first")
|
|
159
|
+
sys.exit(1)
|
|
160
|
+
except KeyboardInterrupt:
|
|
161
|
+
console.print("\nProduction server stopped")
|
|
162
|
+
except Exception as e:
|
|
163
|
+
console.print(f"Production server error: {e}")
|
|
164
|
+
|
|
165
|
+
# Internal command registry (no typer dependency)
|
|
166
|
+
SERVE_COMMANDS = {
|
|
167
|
+
'start': serve_command,
|
|
168
|
+
'serve': serve_command,
|
|
169
|
+
'dev': dev_command,
|
|
170
|
+
'development': dev_command,
|
|
171
|
+
'prod': prod_command,
|
|
172
|
+
'production': prod_command
|
|
173
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# createsonline/cli/commands/shell.py
|
|
2
|
+
"""
|
|
3
|
+
CREATESONLINE Interactive Shell
|
|
4
|
+
|
|
5
|
+
Launch an interactive Python shell with CREATESONLINE imports.
|
|
6
|
+
"""
|
|
7
|
+
from rich.console import Console
|
|
8
|
+
|
|
9
|
+
console = Console()
|
|
10
|
+
|
|
11
|
+
def shell_command():
|
|
12
|
+
"""🐚 Interactive CREATESONLINE shell with pre-loaded imports"""
|
|
13
|
+
|
|
14
|
+
console.print("🐚 [bold blue]CREATESONLINE Interactive Shell[/bold blue]")
|
|
15
|
+
console.print("[cyan]Pre-loaded imports available:[/cyan]")
|
|
16
|
+
console.print(" • [yellow]createsonline[/yellow] - Main framework")
|
|
17
|
+
console.print(" • [yellow]createsonline.ai[/yellow] - AI capabilities")
|
|
18
|
+
console.print(" • [yellow]app[/yellow] - Application instance (if main.py exists)")
|
|
19
|
+
console.print(" • [yellow]models[/yellow] - Database models (if available)")
|
|
20
|
+
console.print()
|
|
21
|
+
|
|
22
|
+
# Prepare the shell environment
|
|
23
|
+
import sys
|
|
24
|
+
import os
|
|
25
|
+
|
|
26
|
+
# Try to import createsonline
|
|
27
|
+
shell_globals = {}
|
|
28
|
+
shell_locals = {}
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
import createsonline
|
|
32
|
+
shell_globals['createsonline'] = createsonline
|
|
33
|
+
console.print("✅ [green]createsonline imported[/green]")
|
|
34
|
+
except ImportError:
|
|
35
|
+
console.print("⚠️ [yellow]createsonline not available[/yellow]")
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
import createsonline.ai as ai
|
|
39
|
+
shell_globals['ai'] = ai
|
|
40
|
+
console.print("✅ [green]createsonline.ai imported[/green]")
|
|
41
|
+
except ImportError:
|
|
42
|
+
console.print("⚠️ [yellow]createsonline.ai not available[/yellow]")
|
|
43
|
+
|
|
44
|
+
# Try to import app from main.py
|
|
45
|
+
if os.path.exists("main.py"):
|
|
46
|
+
try:
|
|
47
|
+
sys.path.insert(0, os.getcwd())
|
|
48
|
+
import main
|
|
49
|
+
if hasattr(main, 'app'):
|
|
50
|
+
shell_globals['app'] = main.app
|
|
51
|
+
console.print("✅ [green]app imported from main.py[/green]")
|
|
52
|
+
except Exception as e:
|
|
53
|
+
console.print(f"⚠️ [yellow]Could not import app: {e}[/yellow]")
|
|
54
|
+
|
|
55
|
+
# Try to import models
|
|
56
|
+
if os.path.exists("models"):
|
|
57
|
+
try:
|
|
58
|
+
import models
|
|
59
|
+
shell_globals['models'] = models
|
|
60
|
+
console.print("✅ [green]models imported[/green]")
|
|
61
|
+
except Exception:
|
|
62
|
+
pass
|
|
63
|
+
|
|
64
|
+
# Common imports
|
|
65
|
+
shell_globals.update({
|
|
66
|
+
'os': os,
|
|
67
|
+
'sys': sys,
|
|
68
|
+
'Path': __import__('pathlib').Path,
|
|
69
|
+
'json': __import__('json'),
|
|
70
|
+
'asyncio': __import__('asyncio'),
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
console.print()
|
|
74
|
+
console.print("[dim]Type 'exit()' or Ctrl+D to quit[/dim]")
|
|
75
|
+
console.print()
|
|
76
|
+
|
|
77
|
+
# Launch the shell
|
|
78
|
+
try:
|
|
79
|
+
# Try IPython first (better experience)
|
|
80
|
+
try:
|
|
81
|
+
from IPython import start_ipython
|
|
82
|
+
start_ipython(argv=[], user_ns=shell_globals)
|
|
83
|
+
except ImportError:
|
|
84
|
+
# Fallback to standard Python shell
|
|
85
|
+
import code
|
|
86
|
+
code.interact(
|
|
87
|
+
banner="Python shell with CREATESONLINE",
|
|
88
|
+
local=shell_globals
|
|
89
|
+
)
|
|
90
|
+
except (EOFError, KeyboardInterrupt):
|
|
91
|
+
console.print("\n[yellow]Shell session ended[/yellow]")
|
|
92
|
+
except Exception as e:
|
|
93
|
+
console.print(f"[red]Shell error: {e}[/red]")
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CREATESONLINE User Management Commands
|
|
3
|
+
|
|
4
|
+
Create and manage users for the admin interface.
|
|
5
|
+
Lazy imports are used to avoid hard dependencies when not needed.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
|
|
10
|
+
_cli_logger = logging.getLogger("createsonline.cli.users")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def createsuperuser_command():
|
|
14
|
+
"""Create admin superuser interactively"""
|
|
15
|
+
|
|
16
|
+
# Import dependencies only when command is used
|
|
17
|
+
try:
|
|
18
|
+
import typer
|
|
19
|
+
from rich.console import Console
|
|
20
|
+
from rich.prompt import Prompt, Confirm
|
|
21
|
+
from rich.panel import Panel
|
|
22
|
+
except ImportError as e:
|
|
23
|
+
_cli_logger.error("This command requires additional dependencies. Install with: pip install rich typer")
|
|
24
|
+
# handled above
|
|
25
|
+
return
|
|
26
|
+
|
|
27
|
+
console = Console()
|
|
28
|
+
|
|
29
|
+
console.print(Panel(
|
|
30
|
+
"[bold blue]CREATESONLINE Admin User Creation[/bold blue]\n\n"
|
|
31
|
+
"[cyan]Create a superuser account for the admin interface.[/cyan]\n"
|
|
32
|
+
"[dim]This user will have full administrative privileges.[/dim]",
|
|
33
|
+
title="Create Superuser",
|
|
34
|
+
border_style="blue"
|
|
35
|
+
))
|
|
36
|
+
|
|
37
|
+
# Get user information
|
|
38
|
+
try:
|
|
39
|
+
username = Prompt.ask("[cyan]Username[/cyan]", default="admin")
|
|
40
|
+
email = Prompt.ask("[cyan]Email address[/cyan]", default=f"{username}@example.com")
|
|
41
|
+
password = Prompt.ask("[cyan]Password[/cyan]", password=True)
|
|
42
|
+
password_confirm = Prompt.ask("[cyan]Confirm password[/cyan]", password=True)
|
|
43
|
+
|
|
44
|
+
if password != password_confirm:
|
|
45
|
+
console.print("[red]Passwords don't match![/red]")
|
|
46
|
+
raise typer.Exit(1)
|
|
47
|
+
|
|
48
|
+
# Confirm creation
|
|
49
|
+
console.print(f"\n[green]Creating superuser:[/green]")
|
|
50
|
+
console.print(f" Username: [cyan]{username}[/cyan]")
|
|
51
|
+
console.print(f" Email: [cyan]{email}[/cyan]")
|
|
52
|
+
|
|
53
|
+
if not Confirm.ask("\n[yellow]Create this superuser?[/yellow]"):
|
|
54
|
+
console.print("[yellow]Cancelled[/yellow]")
|
|
55
|
+
return
|
|
56
|
+
|
|
57
|
+
# Create the user
|
|
58
|
+
success = create_superuser(username, email, password, console)
|
|
59
|
+
|
|
60
|
+
if success:
|
|
61
|
+
console.print(Panel(
|
|
62
|
+
f"[bold green]✅ Superuser '{username}' created successfully![/bold green]\n\n"
|
|
63
|
+
"[cyan]You can now:[/cyan]\n"
|
|
64
|
+
"• Login to admin interface\n"
|
|
65
|
+
"• Manage users and permissions\n"
|
|
66
|
+
"• Configure application settings\n\n"
|
|
67
|
+
"[green]Admin URL:[/green] http://localhost:8000/admin/",
|
|
68
|
+
title="Success!",
|
|
69
|
+
border_style="green"
|
|
70
|
+
))
|
|
71
|
+
else:
|
|
72
|
+
console.print("[red]Failed to create superuser[/red]")
|
|
73
|
+
raise typer.Exit(1)
|
|
74
|
+
|
|
75
|
+
except KeyboardInterrupt:
|
|
76
|
+
console.print("\n[yellow]Cancelled by user[/yellow]")
|
|
77
|
+
except Exception as e:
|
|
78
|
+
console.print(f"[red]Error creating superuser: {e}[/red]")
|
|
79
|
+
raise typer.Exit(1)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def create_superuser(username: str, email: str, password: str, console=None) -> bool:
|
|
83
|
+
"""Create a superuser in the database.
|
|
84
|
+
|
|
85
|
+
Returns True on success, False otherwise. Accepts optional `console`
|
|
86
|
+
for rich output; falls back to print when not provided.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
try:
|
|
90
|
+
# Try to import and use the auth models
|
|
91
|
+
from createsonline.auth.models import User, Group, Permission, hash_password
|
|
92
|
+
from sqlalchemy import create_engine
|
|
93
|
+
from sqlalchemy.orm import sessionmaker
|
|
94
|
+
import os
|
|
95
|
+
|
|
96
|
+
# Get database URL from environment or use default
|
|
97
|
+
database_url = os.getenv("DATABASE_URL", "sqlite:///./app.db")
|
|
98
|
+
|
|
99
|
+
# Create database engine and session
|
|
100
|
+
engine = create_engine(database_url)
|
|
101
|
+
|
|
102
|
+
# Create tables if they don't exist
|
|
103
|
+
User.metadata.create_all(engine)
|
|
104
|
+
|
|
105
|
+
SessionLocal = sessionmaker(bind=engine)
|
|
106
|
+
session = SessionLocal()
|
|
107
|
+
|
|
108
|
+
try:
|
|
109
|
+
# Check if user already exists
|
|
110
|
+
existing_user = session.query(User).filter(User.username == username).first()
|
|
111
|
+
if existing_user:
|
|
112
|
+
(console.print(f"[yellow]User '{username}' already exists![/yellow]") if console else _cli_logger.info(f"User '{username}' already exists!"))
|
|
113
|
+
return False
|
|
114
|
+
|
|
115
|
+
# Hash the password
|
|
116
|
+
hashed_password = hash_password(password)
|
|
117
|
+
|
|
118
|
+
# Create the user
|
|
119
|
+
user = User(
|
|
120
|
+
username=username,
|
|
121
|
+
email=email,
|
|
122
|
+
password_hash=hashed_password,
|
|
123
|
+
is_active=True,
|
|
124
|
+
is_superuser=True,
|
|
125
|
+
is_staff=True
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
session.add(user)
|
|
129
|
+
session.commit()
|
|
130
|
+
|
|
131
|
+
(console.print(f"[green]User '{username}' created in database[/green]") if console else _cli_logger.info(f"User '{username}' created in database"))
|
|
132
|
+
return True
|
|
133
|
+
|
|
134
|
+
finally:
|
|
135
|
+
session.close()
|
|
136
|
+
|
|
137
|
+
except ImportError:
|
|
138
|
+
# Fallback to simple file-based storage for demo
|
|
139
|
+
_cli_logger.error("Database models not available. Configure your database and try again.")
|
|
140
|
+
return False
|
|
141
|
+
except Exception as e:
|
|
142
|
+
_cli_logger.error(f"Database error: {e}")
|
|
143
|
+
_cli_logger.info("User creation aborted due to configuration error.")
|
|
144
|
+
return False
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
|