@serve.zone/dcrouter 13.28.0 → 13.30.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/.smartconfig.json +32 -10
- package/dist_serve/bundle.js +609 -592
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.dcrouter.d.ts +7 -0
- package/dist_ts/classes.dcrouter.js +12 -2
- package/dist_ts/config/classes.route-config-manager.js +8 -7
- package/dist_ts/opsserver/classes.opsserver.js +4 -1
- package/dist_ts/opsserver/handlers/admin.handler.d.ts +21 -6
- package/dist_ts/opsserver/handlers/admin.handler.js +188 -29
- package/dist_ts/opsserver/handlers/target-profile.handler.js +3 -1
- package/dist_ts/opsserver/handlers/users.handler.js +2 -2
- package/dist_ts/plugins.d.ts +2 -0
- package/dist_ts/plugins.js +4 -1
- package/dist_ts/vpn/classes.vpn-manager.d.ts +2 -0
- package/dist_ts/vpn/classes.vpn-manager.js +41 -20
- package/dist_ts_interfaces/requests/admin.d.ts +38 -0
- package/dist_ts_interfaces/requests/users.d.ts +2 -5
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/appstate.d.ts +17 -0
- package/dist_ts_web/appstate.js +27 -1
- package/dist_ts_web/elements/ops-dashboard.d.ts +4 -0
- package/dist_ts_web/elements/ops-dashboard.js +100 -3
- package/package.json +27 -34
- package/readme.md +15 -3
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.dcrouter.ts +20 -1
- package/ts/config/classes.route-config-manager.ts +8 -6
- package/ts/opsserver/classes.opsserver.ts +3 -0
- package/ts/opsserver/handlers/admin.handler.ts +244 -32
- package/ts/opsserver/handlers/target-profile.handler.ts +2 -0
- package/ts/opsserver/handlers/users.handler.ts +1 -1
- package/ts/plugins.ts +7 -0
- package/ts/readme.md +1 -1
- package/ts/vpn/classes.vpn-manager.ts +56 -25
- package/ts_apiclient/readme.md +4 -4
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/appstate.ts +49 -0
- package/ts_web/elements/ops-dashboard.ts +100 -0
- package/ts_web/readme.md +5 -3
|
@@ -66,6 +66,9 @@ export class OpsDashboard extends DeesElement {
|
|
|
66
66
|
isLoggedIn: false,
|
|
67
67
|
};
|
|
68
68
|
|
|
69
|
+
private bootstrapStepper?: any;
|
|
70
|
+
private bootstrapCheckPromise?: Promise<void>;
|
|
71
|
+
|
|
69
72
|
@state() accessor uiState: appstate.IUiState = {
|
|
70
73
|
activeView: 'overview',
|
|
71
74
|
activeSubview: null,
|
|
@@ -336,6 +339,7 @@ export class OpsDashboard extends DeesElement {
|
|
|
336
339
|
await (simpleLogin as any).switchToSlottedContent();
|
|
337
340
|
await appstate.statsStatePart.dispatchAction(appstate.fetchAllStatsAction, null);
|
|
338
341
|
await appstate.configStatePart.dispatchAction(appstate.fetchConfigurationAction, null);
|
|
342
|
+
await this.ensureAdminBootstrap();
|
|
339
343
|
} else {
|
|
340
344
|
// Server rejected the JWT — clear state, show login
|
|
341
345
|
await appstate.loginStatePart.dispatchAction(appstate.logoutAction, null);
|
|
@@ -370,10 +374,106 @@ export class OpsDashboard extends DeesElement {
|
|
|
370
374
|
await simpleLogin!.switchToSlottedContent();
|
|
371
375
|
await appstate.statsStatePart.dispatchAction(appstate.fetchAllStatsAction, null);
|
|
372
376
|
await appstate.configStatePart.dispatchAction(appstate.fetchConfigurationAction, null);
|
|
377
|
+
await this.ensureAdminBootstrap();
|
|
373
378
|
} else {
|
|
374
379
|
form!.setStatus('error', 'Login failed!');
|
|
375
380
|
await domtools.convenience.smartdelay.delayFor(2000);
|
|
376
381
|
form!.reset();
|
|
377
382
|
}
|
|
378
383
|
}
|
|
384
|
+
|
|
385
|
+
private async ensureAdminBootstrap(): Promise<void> {
|
|
386
|
+
if (!this.loginState.identity || this.bootstrapStepper?.isConnected) {
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
if (this.bootstrapCheckPromise) {
|
|
390
|
+
return this.bootstrapCheckPromise;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
this.bootstrapCheckPromise = (async () => {
|
|
394
|
+
try {
|
|
395
|
+
const status = await appstate.getAdminBootstrapStatus();
|
|
396
|
+
if (status.needsBootstrap) {
|
|
397
|
+
await this.showAdminBootstrapStepper(status);
|
|
398
|
+
}
|
|
399
|
+
} catch (error) {
|
|
400
|
+
console.error('Admin bootstrap status check failed:', error);
|
|
401
|
+
} finally {
|
|
402
|
+
this.bootstrapCheckPromise = undefined;
|
|
403
|
+
}
|
|
404
|
+
})();
|
|
405
|
+
|
|
406
|
+
return this.bootstrapCheckPromise;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
private async showAdminBootstrapStepper(statusArg: appstate.IAdminBootstrapStatus): Promise<void> {
|
|
410
|
+
const { DeesStepper } = await import('@design.estate/dees-catalog');
|
|
411
|
+
this.bootstrapStepper = await DeesStepper.createAndShow({
|
|
412
|
+
cancelable: false,
|
|
413
|
+
steps: [
|
|
414
|
+
{
|
|
415
|
+
title: 'Create Persisted Admin',
|
|
416
|
+
content: html`
|
|
417
|
+
<div style="display: grid; gap: 16px; color: var(--dees-color-text-secondary); font-size: 14px; line-height: 1.5;">
|
|
418
|
+
<p style="margin: 0;">
|
|
419
|
+
This router is currently using the temporary bootstrap admin. Create the first persisted admin account to continue.
|
|
420
|
+
</p>
|
|
421
|
+
<dees-form>
|
|
422
|
+
<dees-input-text .key=${'email'} .label=${'Admin email'} .required=${true}></dees-input-text>
|
|
423
|
+
<dees-input-text .key=${'name'} .label=${'Display name'}></dees-input-text>
|
|
424
|
+
<dees-input-text .key=${'password'} .label=${'Password'} .required=${true} .isPasswordBool=${true}></dees-input-text>
|
|
425
|
+
<dees-input-text .key=${'passwordConfirm'} .label=${'Confirm password'} .required=${true} .isPasswordBool=${true}></dees-input-text>
|
|
426
|
+
<dees-input-checkbox
|
|
427
|
+
.key=${'enableIdpGlobalAuth'}
|
|
428
|
+
.label=${'Allow idp.global login for this email'}
|
|
429
|
+
.description=${statusArg.idpGlobalConfigured
|
|
430
|
+
? 'The local account remains authoritative; idp.global only verifies identity.'
|
|
431
|
+
: 'Requires DCROUTER_IDP_GLOBAL_URL before idp.global logins can work.'}
|
|
432
|
+
></dees-input-checkbox>
|
|
433
|
+
</dees-form>
|
|
434
|
+
</div>
|
|
435
|
+
`,
|
|
436
|
+
menuOptions: [
|
|
437
|
+
{
|
|
438
|
+
name: 'Create admin',
|
|
439
|
+
action: async (stepperArg: any) => {
|
|
440
|
+
const form = stepperArg.shadowRoot?.querySelector('.selected dees-form') as any;
|
|
441
|
+
if (!form) return;
|
|
442
|
+
const formData = await form.collectFormData();
|
|
443
|
+
const email = String(formData.email || '').trim();
|
|
444
|
+
const name = String(formData.name || '').trim();
|
|
445
|
+
const password = String(formData.password || '');
|
|
446
|
+
const passwordConfirm = String(formData.passwordConfirm || '');
|
|
447
|
+
|
|
448
|
+
if (!email || !password) {
|
|
449
|
+
form.setStatus?.('error', 'Email and password are required.');
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
if (password !== passwordConfirm) {
|
|
453
|
+
form.setStatus?.('error', 'Passwords do not match.');
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
try {
|
|
458
|
+
form.setStatus?.('pending', 'Creating persisted admin...');
|
|
459
|
+
await appstate.createInitialAdminUser({
|
|
460
|
+
email,
|
|
461
|
+
name,
|
|
462
|
+
password,
|
|
463
|
+
enableIdpGlobalAuth: Boolean(formData.enableIdpGlobalAuth),
|
|
464
|
+
});
|
|
465
|
+
form.setStatus?.('success', 'Persisted admin created.');
|
|
466
|
+
await stepperArg.destroy();
|
|
467
|
+
this.bootstrapStepper = undefined;
|
|
468
|
+
await appstate.usersStatePart.dispatchAction(appstate.fetchUsersAction, null);
|
|
469
|
+
} catch (error) {
|
|
470
|
+
form.setStatus?.('error', error instanceof Error ? error.message : 'Failed to create admin.');
|
|
471
|
+
}
|
|
472
|
+
},
|
|
473
|
+
},
|
|
474
|
+
],
|
|
475
|
+
},
|
|
476
|
+
],
|
|
477
|
+
});
|
|
478
|
+
}
|
|
379
479
|
}
|
package/ts_web/readme.md
CHANGED
|
@@ -12,8 +12,8 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community
|
|
|
12
12
|
| --- | --- |
|
|
13
13
|
| `index.ts` | Initializes the app router and renders `<ops-dashboard>` into `document.body`. |
|
|
14
14
|
| `router.ts` | Defines top-level dashboard routes, subviews, redirects, and URL/state synchronization. |
|
|
15
|
-
| `appstate.ts` | Holds reactive login, UI, config, stats, route, DNS, email, remote ingress, VPN, and log state. |
|
|
16
|
-
| `elements/` | Contains the dashboard shell and feature-specific Dees web components. |
|
|
15
|
+
| `appstate.ts` | Holds reactive login, bootstrap, UI, config, stats, route, DNS, email, remote ingress, VPN, and log state. |
|
|
16
|
+
| `elements/` | Contains the dashboard shell, first-admin bootstrap stepper, and feature-specific Dees web components. |
|
|
17
17
|
|
|
18
18
|
## View Map
|
|
19
19
|
|
|
@@ -37,6 +37,8 @@ The dashboard talks to the dcrouter OpsServer through:
|
|
|
37
37
|
- Dees web components and app-state subscriptions for UI updates
|
|
38
38
|
- QR code rendering for VPN client UX
|
|
39
39
|
|
|
40
|
+
On a fresh DB-backed instance, the dashboard checks `getAdminBootstrapStatus` and shows a non-cancelable first-admin stepper before normal dashboard access.
|
|
41
|
+
|
|
40
42
|
## Usage
|
|
41
43
|
|
|
42
44
|
This package is primarily consumed by the main dcrouter build and served by OpsServer. Install it directly only when you intentionally need the dashboard module boundary.
|
|
@@ -79,7 +81,7 @@ Use of these trademarks must comply with Task Venture Capital GmbH's Trademark G
|
|
|
79
81
|
|
|
80
82
|
### Company Information
|
|
81
83
|
|
|
82
|
-
Task Venture Capital GmbH
|
|
84
|
+
Task Venture Capital GmbH
|
|
83
85
|
Registered at District Court Bremen HRB 35230 HB, Germany
|
|
84
86
|
|
|
85
87
|
For any legal inquiries or further information, please contact us via email at hello@task.vc.
|