admindb 2.2.1 → 2.3.0
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.
- package/README.md +368 -364
- package/dist/app.js +6 -9
- package/dist/auth/config.d.ts +1 -1
- package/dist/auth/config.js +18 -30
- package/dist/auth/crypto.js +11 -21
- package/dist/auth/middleware.js +9 -16
- package/dist/auth/routes.js +9 -15
- package/dist/cli/args.d.ts +1 -1
- package/dist/cli/args.js +15 -26
- package/dist/cli/config.js +6 -16
- package/dist/cli/runner.js +4 -7
- package/dist/data/chain.d.ts +1 -1
- package/dist/data/chain.js +40 -617
- package/dist/data/datasets.d.ts +1 -1
- package/dist/data/datasets.js +43 -1
- package/dist/data/detector.js +45 -21
- package/dist/data/engine.d.ts +1 -1
- package/dist/data/engine.js +483 -142
- package/dist/data/index.d.ts +1 -1
- package/dist/data/index.js +8 -0
- package/dist/data/prng.d.ts +1 -0
- package/dist/data/prng.js +73 -0
- package/dist/data/registry.d.ts +1 -0
- package/dist/data/registry.js +805 -0
- package/dist/data/schema-graph.d.ts +1 -0
- package/dist/data/schema-graph.js +210 -0
- package/dist/data/strategies.d.ts +1 -1
- package/dist/data/strategies.js +44 -283
- package/dist/data/templates.d.ts +1 -0
- package/dist/data/templates.js +134 -0
- package/dist/data/types.d.ts +1 -1
- package/dist/data/validator.d.ts +1 -0
- package/dist/data/validator.js +160 -0
- package/dist/db/database.js +9 -14
- package/dist/db/export.js +32 -55
- package/dist/db/filters.d.ts +1 -1
- package/dist/db/filters.js +15 -38
- package/dist/db/introspection.js +4 -7
- package/dist/db/manager.js +27 -51
- package/dist/db/migrations.js +7 -14
- package/dist/db/postgres.js +30 -78
- package/dist/index.d.ts +1 -1
- package/dist/public/css/app.css +1 -1
- package/dist/public/js/browse.js +1 -1
- package/dist/public/js/inspector.js +1 -1
- package/dist/public/js/query.js +1 -1
- package/dist/public/js/seed.js +1 -1
- package/dist/routes/api/erd.js +3 -8
- package/dist/routes/api/helpers.d.ts +1 -1
- package/dist/routes/api/helpers.js +75 -25
- package/dist/routes/api/import-export.js +1 -2
- package/dist/routes/api/query.js +2 -6
- package/dist/routes/api/rows.js +4 -8
- package/dist/routes/api/seed.js +35 -21
- package/dist/routes/api/tables.js +15 -30
- package/dist/routes/databases.js +8 -26
- package/dist/routes/pages.js +67 -18
- package/dist/serverless.js +15 -40
- package/dist/sql/generator.d.ts +1 -1
- package/dist/sql/generator.js +35 -109
- package/dist/types/api.d.ts +1 -1
- package/dist/utils/common.d.ts +1 -1
- package/dist/utils/common.js +45 -85
- package/dist/utils/csv.d.ts +1 -1
- package/dist/utils/csv.js +11 -17
- package/dist/utils/datatype.js +46 -60
- package/dist/utils/icons.js +8 -8
- package/dist/views/layouts/main.hbs +1 -87
- package/dist/views/pages/databases.hbs +1 -233
- package/dist/views/pages/designer.hbs +1 -89
- package/dist/views/pages/erd.hbs +1 -1241
- package/dist/views/pages/error.hbs +1 -10
- package/dist/views/pages/form.hbs +1 -59
- package/dist/views/pages/home.hbs +1 -220
- package/dist/views/pages/info.hbs +1 -107
- package/dist/views/pages/login.hbs +1 -98
- package/dist/views/pages/query.hbs +1 -129
- package/dist/views/pages/schema.hbs +1 -298
- package/dist/views/pages/seed-select.hbs +251 -0
- package/dist/views/pages/seed.hbs +256 -414
- package/dist/views/pages/table.hbs +1 -327
- package/dist/views/partials/navbar.hbs +1 -83
- package/dist/views/partials/sidebar.hbs +1 -129
- package/docs/API.md +149 -149
- package/docs/EXAMPLES.md +579 -579
- package/docs/SECURITY.md +265 -265
- package/package.json +79 -79
|
@@ -1,107 +1 @@
|
|
|
1
|
-
<div class="space-y-6">
|
|
2
|
-
<div class="flex flex-wrap items-center justify-between gap-3">
|
|
3
|
-
<div>
|
|
4
|
-
<p class="text-sm font-semibold uppercase tracking-wider text-primary">{{dialect}} Database</p>
|
|
5
|
-
<h1 class="mt-1 text-3xl font-extrabold tracking-tight">Info & Settings</h1>
|
|
6
|
-
<p class="mt-1.5 text-sm text-base-content/55">Database configuration, settings, and schema DDL overview.</p>
|
|
7
|
-
</div>
|
|
8
|
-
</div>
|
|
9
|
-
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
10
|
-
<div class="lg:col-span-1 space-y-6">
|
|
11
|
-
<div class="app-card overflow-hidden">
|
|
12
|
-
<div class="border-b border-base-200 bg-base-200/40 px-4 py-3">
|
|
13
|
-
<h2 class="text-sm font-bold uppercase tracking-wider text-base-content/80">Settings / Configuration</h2>
|
|
14
|
-
</div>
|
|
15
|
-
<div class="p-0">
|
|
16
|
-
<table class="table table-sm w-full">
|
|
17
|
-
<tbody>
|
|
18
|
-
{{#each settings}}
|
|
19
|
-
<tr class="hover:bg-base-200/20">
|
|
20
|
-
<td class="font-medium text-base-content/70 w-1/2">{{@key}}</td>
|
|
21
|
-
<td class="font-mono text-xs">{{this}}</td>
|
|
22
|
-
</tr>
|
|
23
|
-
{{else}}
|
|
24
|
-
<tr>
|
|
25
|
-
<td colspan="2" class="p-4 text-center text-sm text-base-content/40">No settings available</td>
|
|
26
|
-
</tr>
|
|
27
|
-
{{/each}}
|
|
28
|
-
</tbody>
|
|
29
|
-
</table>
|
|
30
|
-
</div>
|
|
31
|
-
</div>
|
|
32
|
-
</div>
|
|
33
|
-
<div class="lg:col-span-2 space-y-6">
|
|
34
|
-
<div class="app-card overflow-hidden flex flex-col h-[75vh]">
|
|
35
|
-
<div class="border-b border-base-200 bg-base-200/40 px-4 py-3 flex items-center justify-between">
|
|
36
|
-
<div class="flex items-center gap-3">
|
|
37
|
-
<h2 class="text-sm font-bold uppercase tracking-wider text-base-content/80">Schema DDL</h2>
|
|
38
|
-
<span class="badge badge-sm badge-ghost font-mono text-[10px] uppercase font-bold">{{dialect}}</span>
|
|
39
|
-
</div>
|
|
40
|
-
<button id="btn-copy-ddl" class="btn btn-sm btn-ghost gap-1.5" disabled>
|
|
41
|
-
{{{icon "copy" class="h-4 w-4"}}}
|
|
42
|
-
Copy
|
|
43
|
-
</button>
|
|
44
|
-
</div>
|
|
45
|
-
<div class="bg-base-300 p-4 overflow-y-auto flex-1 relative">
|
|
46
|
-
<div id="ddl-loader" class="absolute inset-0 flex flex-col items-center justify-center text-base-content/50 gap-3">
|
|
47
|
-
{{{icon "spinner" class="h-6 w-6 animate-spin text-primary"}}}
|
|
48
|
-
<p class="text-sm font-medium">Extracting schema definitions...</p>
|
|
49
|
-
</div>
|
|
50
|
-
<div id="ddl-error" class="hidden absolute inset-0 flex flex-col items-center justify-center text-error gap-3 bg-base-300">
|
|
51
|
-
{{{icon "error" class="h-8 w-8"}}}
|
|
52
|
-
<p class="text-sm font-medium">Failed to load schema.</p>
|
|
53
|
-
</div>
|
|
54
|
-
<pre id="ddl-container" class="hidden m-0 h-full"><code class="language-sql text-sm text-base-content/80 whitespace-pre-wrap"></code></pre>
|
|
55
|
-
</div>
|
|
56
|
-
</div>
|
|
57
|
-
</div>
|
|
58
|
-
</div>
|
|
59
|
-
</div>
|
|
60
|
-
<script>
|
|
61
|
-
document.addEventListener('DOMContentLoaded', async () => {
|
|
62
|
-
const loader = document.getElementById('ddl-loader');
|
|
63
|
-
const container = document.getElementById('ddl-container');
|
|
64
|
-
const codeBlock = container.querySelector('code');
|
|
65
|
-
const btnCopy = document.getElementById('btn-copy-ddl');
|
|
66
|
-
const errorBox = document.getElementById('ddl-error');
|
|
67
|
-
try {
|
|
68
|
-
const res = await fetch('{{basePath}}/api/info/ddl');
|
|
69
|
-
const json = await res.json();
|
|
70
|
-
loader.classList.add('hidden');
|
|
71
|
-
if (json.success && json.data) {
|
|
72
|
-
if (window.Utils && window.Utils.highlightSql) {
|
|
73
|
-
codeBlock.innerHTML = window.Utils.highlightSql(json.data);
|
|
74
|
-
} else {
|
|
75
|
-
codeBlock.textContent = json.data;
|
|
76
|
-
}
|
|
77
|
-
container.classList.remove('hidden');
|
|
78
|
-
btnCopy.disabled = false;
|
|
79
|
-
btnCopy.addEventListener('click', async () => {
|
|
80
|
-
try {
|
|
81
|
-
await navigator.clipboard.writeText(json.data);
|
|
82
|
-
const originalText = btnCopy.innerHTML;
|
|
83
|
-
btnCopy.innerHTML = `{{{icon "check" class="h-4 w-4"}}} Copied!`;
|
|
84
|
-
btnCopy.classList.add('text-success');
|
|
85
|
-
setTimeout(() => {
|
|
86
|
-
btnCopy.innerHTML = originalText;
|
|
87
|
-
btnCopy.classList.remove('text-success');
|
|
88
|
-
}, 2000);
|
|
89
|
-
} catch (err) {
|
|
90
|
-
console.error('Failed to copy', err);
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
} else {
|
|
94
|
-
if (json.success && !json.data) {
|
|
95
|
-
codeBlock.textContent = '-- No tables defined in the database.';
|
|
96
|
-
container.classList.remove('hidden');
|
|
97
|
-
} else {
|
|
98
|
-
throw new Error(json.error || 'Failed to fetch DDL');
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
} catch (err) {
|
|
102
|
-
loader.classList.add('hidden');
|
|
103
|
-
errorBox.classList.remove('hidden');
|
|
104
|
-
errorBox.querySelector('p').textContent = err.message || 'Failed to load schema.';
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
</script>
|
|
1
|
+
<div class="space-y-6">
|
|
108
2
|
<div class="page-header">
|
|
109
3
|
<div class="page-header-row">
|
|
110
4
|
<div>
|
|
111
5
|
<div class="page-pretitle">{{dialect}} Database</div>
|
|
112
6
|
<h1 class="page-title">Info & Settings</h1>
|
|
113
7
|
<p class="mt-0.5 text-xs text-base-content/60">Database configuration, settings, and schema DDL overview.</p>
|
|
114
8
|
</div>
|
|
115
9
|
</div>
|
|
116
10
|
</div>
|
|
117
11
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
118
12
|
<div class="lg:col-span-1 space-y-6">
|
|
119
13
|
{{#if isDefaultPassword}}
|
|
120
14
|
<div class="alert alert-warning text-xs shadow-xs rounded-2xl border border-warning/30 p-3.5">
|
|
121
15
|
{{{icon "warning" class="h-5 w-5 shrink-0 text-warning"}}}
|
|
122
16
|
<div>
|
|
123
17
|
<div class="font-bold text-sm">Default Password in Use</div>
|
|
124
18
|
<div class="text-base-content/80 mt-0.5 leading-relaxed">Console is running with default password (<code class="font-mono font-semibold">admin</code>). Run <code class="font-mono font-semibold">npm run generatehash</code> and set <code class="font-mono font-semibold">ADMINDB_PASSWORD</code>.</div>
|
|
125
19
|
</div>
|
|
126
20
|
</div>
|
|
127
21
|
{{/if}}
|
|
128
22
|
<div class="app-card overflow-hidden">
|
|
129
23
|
<div class="border-b border-base-200 bg-base-200/40 px-4 py-3">
|
|
130
24
|
<h2 class="text-sm font-bold uppercase tracking-wider text-base-content/80">Settings / Configuration</h2>
|
|
131
25
|
</div>
|
|
132
26
|
<div class="p-0">
|
|
133
27
|
<table class="table table-sm w-full">
|
|
134
28
|
<tbody>
|
|
135
29
|
{{#each settings}}
|
|
136
30
|
<tr class="hover:bg-base-200/20">
|
|
137
31
|
<td class="font-medium text-base-content/70 w-1/2">{{@key}}</td>
|
|
138
32
|
<td class="font-mono text-xs">{{this}}</td>
|
|
139
33
|
</tr>
|
|
140
34
|
{{else}}
|
|
141
35
|
<tr>
|
|
142
36
|
<td colspan="2" class="p-4 text-center text-sm text-base-content/40">No settings available</td>
|
|
143
37
|
</tr>
|
|
144
38
|
{{/each}}
|
|
145
39
|
</tbody>
|
|
146
40
|
</table>
|
|
147
41
|
</div>
|
|
148
42
|
</div>
|
|
149
43
|
</div>
|
|
150
44
|
<div class="lg:col-span-2 space-y-6">
|
|
151
45
|
<div class="app-card overflow-hidden flex flex-col h-[75vh]">
|
|
152
46
|
<div class="border-b border-base-200 bg-base-200/40 px-4 py-3 flex items-center justify-between">
|
|
153
47
|
<div class="flex items-center gap-3">
|
|
154
48
|
<h2 class="text-sm font-bold uppercase tracking-wider text-base-content/80">Schema DDL</h2>
|
|
155
49
|
<span class="badge badge-sm badge-ghost font-mono text-[10px] uppercase font-bold">{{dialect}}</span>
|
|
156
50
|
</div>
|
|
157
51
|
<button id="btn-copy-ddl" class="btn btn-sm btn-ghost gap-1.5" disabled>
|
|
158
52
|
{{{icon "copy" class="h-4 w-4"}}}
|
|
159
53
|
Copy
|
|
160
54
|
</button>
|
|
161
55
|
</div>
|
|
162
56
|
<div class="bg-base-300 p-4 overflow-y-auto flex-1 relative">
|
|
163
57
|
<div id="ddl-loader" class="absolute inset-0 flex flex-col items-center justify-center text-base-content/50 gap-3">
|
|
164
58
|
{{{icon "spinner" class="h-6 w-6 animate-spin text-primary"}}}
|
|
165
59
|
<p class="text-sm font-medium">Extracting schema definitions...</p>
|
|
166
60
|
</div>
|
|
167
61
|
<div id="ddl-error" class="hidden absolute inset-0 flex flex-col items-center justify-center text-error gap-3 bg-base-300">
|
|
168
62
|
{{{icon "error" class="h-8 w-8"}}}
|
|
169
63
|
<p class="text-sm font-medium">Failed to load schema.</p>
|
|
170
64
|
</div>
|
|
171
65
|
<pre id="ddl-container" class="hidden m-0 h-full"><code class="language-sql text-sm text-base-content/80 whitespace-pre-wrap"></code></pre>
|
|
172
66
|
</div>
|
|
173
67
|
</div>
|
|
174
68
|
</div>
|
|
175
69
|
</div>
|
|
176
70
|
document.addEventListener('DOMContentLoaded', async () => {
|
|
177
71
|
const loader = document.getElementById('ddl-loader');
|
|
178
72
|
const container = document.getElementById('ddl-container');
|
|
179
73
|
const codeBlock = container.querySelector('code');
|
|
180
74
|
const btnCopy = document.getElementById('btn-copy-ddl');
|
|
181
75
|
const errorBox = document.getElementById('ddl-error');
|
|
182
76
|
try {
|
|
183
77
|
const res = await fetch('{{basePath}}/api/info/ddl');
|
|
184
78
|
const json = await res.json();
|
|
185
79
|
loader.classList.add('hidden');
|
|
186
80
|
if (json.success && json.data) {
|
|
187
81
|
if (window.Utils && window.Utils.highlightSql) {
|
|
188
82
|
codeBlock.innerHTML = window.Utils.highlightSql(json.data);
|
|
189
83
|
} else {
|
|
190
84
|
codeBlock.textContent = json.data;
|
|
191
85
|
}
|
|
192
86
|
container.classList.remove('hidden');
|
|
193
87
|
btnCopy.disabled = false;
|
|
194
88
|
btnCopy.addEventListener('click', async () => {
|
|
195
89
|
try {
|
|
196
90
|
await navigator.clipboard.writeText(json.data);
|
|
197
91
|
const originalText = btnCopy.innerHTML;
|
|
198
92
|
btnCopy.innerHTML = `{{{icon "check" class="h-4 w-4"}}} Copied!`;
|
|
199
93
|
btnCopy.classList.add('text-success');
|
|
200
94
|
setTimeout(() => {
|
|
201
95
|
btnCopy.innerHTML = originalText;
|
|
202
96
|
btnCopy.classList.remove('text-success');
|
|
203
97
|
}, 2000);
|
|
204
98
|
} catch (err) {
|
|
205
99
|
console.error('Failed to copy', err);
|
|
206
100
|
}
|
|
207
101
|
});
|
|
208
102
|
} else {
|
|
209
103
|
if (json.success && !json.data) {
|
|
210
104
|
codeBlock.textContent = '-- No tables defined in the database.';
|
|
211
105
|
container.classList.remove('hidden');
|
|
212
106
|
} else {
|
|
213
107
|
throw new Error(json.error || 'Failed to fetch DDL');
|
|
214
108
|
}
|
|
215
109
|
}
|
|
216
110
|
} catch (err) {
|
|
217
111
|
loader.classList.add('hidden');
|
|
218
112
|
errorBox.classList.remove('hidden');
|
|
219
113
|
errorBox.querySelector('p').textContent = err.message || 'Failed to load schema.';
|
|
220
114
|
}
|
|
221
115
|
});
|
|
@@ -1,98 +1 @@
|
|
|
1
|
-
<div class="flex min-h-[75vh] items-center justify-center py-6 px-4">
|
|
2
|
-
<div class="w-full max-w-md">
|
|
3
|
-
<div class="mb-8 text-center">
|
|
4
|
-
<div class="mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-2xl bg-primary/10 text-primary shadow-soft">
|
|
5
|
-
{{{icon "database" class="h-8 w-8"}}}
|
|
6
|
-
</div>
|
|
7
|
-
<h1 class="text-2xl font-extrabold tracking-tight text-base-content sm:text-3xl">
|
|
8
|
-
Admin<span class="text-primary">DB</span>
|
|
9
|
-
</h1>
|
|
10
|
-
<p class="mt-1 text-sm text-base-content/60">
|
|
11
|
-
Sign in to access your database administration console
|
|
12
|
-
</p>
|
|
13
|
-
</div>
|
|
14
|
-
<div class="app-card border border-base-300/80 bg-base-100 p-6 sm:p-8 shadow-soft">
|
|
15
|
-
{{#if error}}
|
|
16
|
-
<div class="mb-6 flex items-start gap-3 rounded-xl bg-error/10 p-4 text-sm text-error border border-error/20" role="alert">
|
|
17
|
-
<span class="shrink-0 mt-0.5">
|
|
18
|
-
{{{icon "warning" class="h-5 w-5"}}}
|
|
19
|
-
</span>
|
|
20
|
-
<div class="font-medium">{{error}}</div>
|
|
21
|
-
</div>
|
|
22
|
-
{{/if}}
|
|
23
|
-
{{#if isDefaultPassword}}
|
|
24
|
-
<div class="mb-6 rounded-xl bg-info/10 p-3.5 text-xs text-info border border-info/20">
|
|
25
|
-
<div class="font-semibold flex items-center gap-1.5 mb-1">
|
|
26
|
-
{{{icon "warning" class="h-4 w-4 shrink-0"}}}
|
|
27
|
-
Default Credentials Active
|
|
28
|
-
</div>
|
|
29
|
-
<p class="text-base-content/70">
|
|
30
|
-
Username: <code class="font-mono font-semibold text-primary">admin</code> · Password: <code class="font-mono font-semibold text-primary">admin</code>
|
|
31
|
-
</p>
|
|
32
|
-
<p class="mt-1 text-[11px] text-base-content/50">
|
|
33
|
-
Set <code class="font-mono">ADMINDB_PASSWORD</code> in production to secure your console.
|
|
34
|
-
</p>
|
|
35
|
-
</div>
|
|
36
|
-
{{/if}}
|
|
37
|
-
<form method="POST" action="{{basePath}}/login" class="space-y-4">
|
|
38
|
-
{{#if next}}
|
|
39
|
-
<input type="hidden" name="next" value="{{next}}" />
|
|
40
|
-
{{/if}}
|
|
41
|
-
<div>
|
|
42
|
-
<label class="field-label" for="login-username">
|
|
43
|
-
<span>Username</span>
|
|
44
|
-
</label>
|
|
45
|
-
<div class="relative">
|
|
46
|
-
<input
|
|
47
|
-
id="login-username"
|
|
48
|
-
type="text"
|
|
49
|
-
name="username"
|
|
50
|
-
value="{{#if username}}{{username}}{{else}}admin{{/if}}"
|
|
51
|
-
required
|
|
52
|
-
autofocus
|
|
53
|
-
placeholder="Username"
|
|
54
|
-
class="field-input pl-10"
|
|
55
|
-
autocomplete="username"
|
|
56
|
-
/>
|
|
57
|
-
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3 text-base-content/40">
|
|
58
|
-
{{{icon "user" class="h-5 w-5"}}}
|
|
59
|
-
</div>
|
|
60
|
-
</div>
|
|
61
|
-
</div>
|
|
62
|
-
<div>
|
|
63
|
-
<label class="field-label" for="login-password">
|
|
64
|
-
<span>Password</span>
|
|
65
|
-
</label>
|
|
66
|
-
<div class="relative">
|
|
67
|
-
<input
|
|
68
|
-
id="login-password"
|
|
69
|
-
type="password"
|
|
70
|
-
name="password"
|
|
71
|
-
required
|
|
72
|
-
placeholder="••••••••"
|
|
73
|
-
class="field-input pl-10"
|
|
74
|
-
autocomplete="current-password"
|
|
75
|
-
/>
|
|
76
|
-
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3 text-base-content/40">
|
|
77
|
-
{{{icon "lock" class="h-5 w-5"}}}
|
|
78
|
-
</div>
|
|
79
|
-
</div>
|
|
80
|
-
</div>
|
|
81
|
-
<div class="pt-2">
|
|
82
|
-
<button type="submit" class="btn btn-primary w-full gap-2 font-semibold shadow-soft">
|
|
83
|
-
{{{icon "logout" class="h-4 w-4 rotate-180"}}}
|
|
84
|
-
Sign In
|
|
85
|
-
</button>
|
|
86
|
-
</div>
|
|
87
|
-
</form>
|
|
88
|
-
</div>
|
|
89
|
-
<div class="mt-6 space-y-2 text-center text-xs text-base-content/55">
|
|
90
|
-
<p class="leading-relaxed">
|
|
91
|
-
<span class="font-semibold text-base-content/80">Security Notice:</span> Built-in auth provides basic access control. For production, protect your admin routes using your own application authentication, VPN, or reverse proxy.
|
|
92
|
-
</p>
|
|
93
|
-
<p class="text-base-content/40">
|
|
94
|
-
Native authentication can be disabled via <code class="font-mono">--no-auth</code> or <code class="font-mono">auth: false</code>.
|
|
95
|
-
</p>
|
|
96
|
-
</div>
|
|
97
|
-
</div>
|
|
98
|
-
</div>
|
|
1
|
+
<div class="flex min-h-[75vh] items-center justify-center py-6 px-4">
|
|
99
2
|
<div class="w-full max-w-md">
|
|
100
3
|
<div class="mb-8 text-center">
|
|
101
4
|
<div class="mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-2xl bg-primary/10 text-primary shadow-soft">
|
|
102
5
|
{{{icon "database" class="h-8 w-8"}}}
|
|
103
6
|
</div>
|
|
104
7
|
<h1 class="font-headings text-2xl font-extrabold tracking-tight text-base-content sm:text-3xl">
|
|
105
8
|
Admin<span class="text-primary">DB</span>
|
|
106
9
|
</h1>
|
|
107
10
|
<p class="mt-1 text-sm text-base-content/60">
|
|
108
11
|
Sign in to access your database administration console
|
|
109
12
|
</p>
|
|
110
13
|
</div>
|
|
111
14
|
<div class="app-card border bg-base-100/90 p-6 sm:p-8 shadow-card backdrop-blur-md">
|
|
112
15
|
{{#if error}}
|
|
113
16
|
<div class="mb-6 flex items-start gap-3 rounded-xl bg-error/10 p-4 text-sm text-error border border-error/20" role="alert">
|
|
114
17
|
<span class="shrink-0 mt-0.5">
|
|
115
18
|
{{{icon "warning" class="h-5 w-5"}}}
|
|
116
19
|
</span>
|
|
117
20
|
<div class="font-medium">{{error}}</div>
|
|
118
21
|
</div>
|
|
119
22
|
{{/if}}
|
|
120
23
|
{{#if isDefaultPassword}}
|
|
121
24
|
<div class="mb-6 rounded-xl bg-info/10 p-3.5 text-xs text-info border border-info/20">
|
|
122
25
|
<div class="font-semibold flex items-center gap-1.5 mb-1">
|
|
123
26
|
{{{icon "warning" class="h-4 w-4 shrink-0"}}}
|
|
124
27
|
Default Credentials Active
|
|
125
28
|
</div>
|
|
126
29
|
<p class="text-base-content/70">
|
|
127
30
|
Username: <code class="font-mono font-semibold text-primary">admin</code> · Password: <code class="font-mono font-semibold text-primary">admin</code>
|
|
128
31
|
</p>
|
|
129
32
|
<p class="mt-1 text-[11px] text-base-content/50">
|
|
130
33
|
Set <code class="font-mono">ADMINDB_PASSWORD</code> in production to secure your console.
|
|
131
34
|
</p>
|
|
132
35
|
</div>
|
|
133
36
|
{{/if}}
|
|
134
37
|
<form method="POST" action="{{basePath}}/login" class="space-y-4">
|
|
135
38
|
{{#if next}}
|
|
136
39
|
<input type="hidden" name="next" value="{{next}}" />
|
|
137
40
|
{{/if}}
|
|
138
41
|
<div>
|
|
139
42
|
<label class="field-label" for="login-username">
|
|
140
43
|
<span>Username</span>
|
|
141
44
|
</label>
|
|
142
45
|
<div class="relative">
|
|
143
46
|
<input
|
|
144
47
|
id="login-username"
|
|
145
48
|
type="text"
|
|
146
49
|
name="username"
|
|
147
50
|
value="{{#if username}}{{username}}{{else}}admin{{/if}}"
|
|
148
51
|
required
|
|
149
52
|
autofocus
|
|
150
53
|
placeholder="Username"
|
|
151
54
|
class="field-input pl-10"
|
|
152
55
|
autocomplete="username"
|
|
153
56
|
/>
|
|
154
57
|
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3 text-base-content/40">
|
|
155
58
|
{{{icon "user" class="h-5 w-5"}}}
|
|
156
59
|
</div>
|
|
157
60
|
</div>
|
|
158
61
|
</div>
|
|
159
62
|
<div>
|
|
160
63
|
<label class="field-label" for="login-password">
|
|
161
64
|
<span>Password</span>
|
|
162
65
|
</label>
|
|
163
66
|
<div class="relative">
|
|
164
67
|
<input
|
|
165
68
|
id="login-password"
|
|
166
69
|
type="password"
|
|
167
70
|
name="password"
|
|
168
71
|
required
|
|
169
72
|
placeholder="••••••••"
|
|
170
73
|
class="field-input pl-10"
|
|
171
74
|
autocomplete="current-password"
|
|
172
75
|
/>
|
|
173
76
|
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3 text-base-content/40">
|
|
174
77
|
{{{icon "lock" class="h-5 w-5"}}}
|
|
175
78
|
</div>
|
|
176
79
|
</div>
|
|
177
80
|
</div>
|
|
178
81
|
<div class="pt-2">
|
|
179
82
|
<button type="submit" class="btn btn-primary w-full gap-2 font-semibold shadow-soft">
|
|
180
83
|
{{{icon "logout" class="h-4 w-4 rotate-180"}}}
|
|
181
84
|
Sign In
|
|
182
85
|
</button>
|
|
183
86
|
</div>
|
|
184
87
|
</form>
|
|
185
88
|
</div>
|
|
186
89
|
<div class="mt-6 space-y-2 text-center text-xs text-base-content/55">
|
|
187
90
|
<p class="leading-relaxed">
|
|
188
91
|
<span class="font-semibold text-base-content/80">Security Notice:</span> Built-in auth provides basic access control. For production, protect your admin routes using your own application authentication, VPN, or reverse proxy.
|
|
189
92
|
</p>
|
|
190
93
|
<p class="text-base-content/40">
|
|
191
94
|
Native authentication can be disabled via <code class="font-mono">--no-auth</code> or <code class="font-mono">auth: false</code>.
|
|
192
95
|
</p>
|
|
193
96
|
</div>
|
|
194
97
|
</div>
|