@adonis-agora/durable 0.21.1 → 0.22.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/CHANGELOG.md +41 -0
- package/dist/assets/spa/assets/index-BpH1yTMa.js +81 -0
- package/dist/assets/spa/assets/index-BpH1yTMa.js.map +1 -0
- package/dist/assets/spa/assets/index-CTsYsi6p.css +1 -0
- package/dist/assets/spa/index.html +19 -0
- package/dist/providers/dashboard_provider.d.ts +51 -52
- package/dist/providers/dashboard_provider.d.ts.map +1 -1
- package/dist/providers/dashboard_provider.js +234 -121
- package/dist/providers/dashboard_provider.js.map +1 -1
- package/dist/src/dashboard/attr-filter.d.ts +8 -0
- package/dist/src/dashboard/attr-filter.d.ts.map +1 -0
- package/dist/src/dashboard/attr-filter.js +35 -0
- package/dist/src/dashboard/attr-filter.js.map +1 -0
- package/dist/src/dashboard/auth.d.ts +55 -10
- package/dist/src/dashboard/auth.d.ts.map +1 -1
- package/dist/src/dashboard/auth.js +50 -11
- package/dist/src/dashboard/auth.js.map +1 -1
- package/dist/src/dashboard/gateway-adapter.d.ts +52 -5
- package/dist/src/dashboard/gateway-adapter.d.ts.map +1 -1
- package/dist/src/dashboard/gateway-adapter.js +48 -6
- package/dist/src/dashboard/gateway-adapter.js.map +1 -1
- package/dist/src/dashboard/handlers.d.ts +56 -8
- package/dist/src/dashboard/handlers.d.ts.map +1 -1
- package/dist/src/dashboard/handlers.js +116 -14
- package/dist/src/dashboard/handlers.js.map +1 -1
- package/dist/src/dashboard/index.d.ts +4 -4
- package/dist/src/dashboard/index.d.ts.map +1 -1
- package/dist/src/dashboard/index.js +3 -3
- package/dist/src/dashboard/index.js.map +1 -1
- package/dist/src/dashboard/spa.d.ts +22 -0
- package/dist/src/dashboard/spa.d.ts.map +1 -0
- package/dist/src/dashboard/spa.js +43 -0
- package/dist/src/dashboard/spa.js.map +1 -0
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/transports/queue-mock-adapter.d.ts +1 -0
- package/dist/src/transports/queue-mock-adapter.d.ts.map +1 -1
- package/dist/src/transports/queue-mock-adapter.js +1 -0
- package/dist/src/transports/queue-mock-adapter.js.map +1 -1
- package/dist/stubs/config/durable_dashboard.stub +19 -0
- package/package.json +18 -17
|
@@ -1,34 +1,60 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { basename, resolve as resolvePath } from 'node:path';
|
|
3
|
+
import { PassThrough } from 'node:stream';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { SESSION_COOKIE_NAME, performLogin, performSession, readSession, } from '../src/dashboard/auth.js';
|
|
2
6
|
import { compat, enumerateLiveFleet, mergeFleets, } from '../src/dashboard/compat.js';
|
|
3
7
|
import { resolveConfig, } from '../src/dashboard/define_config.js';
|
|
4
8
|
import { BlockedDiagnosticsRecorder } from '../src/dashboard/diagnostics-recorder.js';
|
|
5
9
|
import { dashboardEngineForRole } from '../src/dashboard/gateway-adapter.js';
|
|
6
|
-
import { cancelRun, getRun, health, listRuns, redispatchPendingRun, retryRun, } from '../src/dashboard/handlers.js';
|
|
10
|
+
import { bulkAction, cancelRun, continueRun, getRun, health, listRuns, redispatchPendingRun, retryRun, retryWithInputRun, topology, workers, } from '../src/dashboard/handlers.js';
|
|
7
11
|
import { renderDashboard } from '../src/dashboard/html.js';
|
|
8
12
|
import { renderLoginPage } from '../src/dashboard/login_page.js';
|
|
13
|
+
import { contentTypeFor, renderIndexHtml } from '../src/dashboard/spa.js';
|
|
9
14
|
import { WorkflowEngine } from '../src/index.js';
|
|
10
15
|
import { DURABLE_TRANSPORT } from '../src/role_bindings.js';
|
|
11
16
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* `
|
|
17
|
+
* Directory of the built SPA (`dist/spa`, copied in by `copy:stubs` — see `package.json`), relative to
|
|
18
|
+
* this compiled provider (`dist/providers`). Resolved lazily (not at module scope) for the same reason
|
|
19
|
+
* `@adonis-agora/media-dashboard`'s provider resolves its SPA directory lazily: `fileURLToPath` throws
|
|
20
|
+
* on any non-`file:` `import.meta.url`, which would make this provider unimportable under a test
|
|
21
|
+
* runner that doesn't use real file URLs.
|
|
22
|
+
*/
|
|
23
|
+
let spaDir;
|
|
24
|
+
function spaDirectory() {
|
|
25
|
+
spaDir ??= fileURLToPath(new URL('../assets/spa/', import.meta.url));
|
|
26
|
+
return spaDir;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Mounts the durable dashboard into an AdonisJS app: the `@adonis-agora/durable-dashboard` React SPA
|
|
30
|
+
* (a JSON API over the {@link WorkflowEngine}'s read/control surface, served under a configurable
|
|
31
|
+
* path) plus, for backward compatibility, the original hand-rolled `assets/dashboard.html` at
|
|
32
|
+
* `<path>/legacy`.
|
|
16
33
|
*
|
|
17
34
|
* Routes (relative to the configured `path`, default `/durable`):
|
|
18
|
-
* - `GET /`
|
|
19
|
-
* - `GET /
|
|
20
|
-
* - `GET /
|
|
21
|
-
* - `
|
|
22
|
-
* - `
|
|
23
|
-
* - `
|
|
24
|
-
* - `
|
|
35
|
+
* - `GET /` -> the dashboard SPA's `index.html`
|
|
36
|
+
* - `GET /assets/:file` -> the SPA's hashed JS/CSS bundle
|
|
37
|
+
* - `GET /legacy` -> the original static dashboard (compat fallback)
|
|
38
|
+
* - `GET /api/runs` -> list runs (status/workflow/tag/namespace/attr filters, paged)
|
|
39
|
+
* - `GET /api/runs/:id` -> run detail (run + step timeline + children)
|
|
40
|
+
* - `GET /api/runs/:id/stream` -> SSE live-tail of one run's lifecycle events
|
|
41
|
+
* - `POST /api/runs/:id/retry` -> re-enqueue the run
|
|
42
|
+
* - `POST /api/runs/:id/retry-with-input` -> fix-and-replay: start a corrected linked run
|
|
43
|
+
* - `POST /api/runs/:id/redispatch` -> re-dispatch a run's lost pending remote steps
|
|
44
|
+
* - `POST /api/runs/:id/cancel` -> cancel the run
|
|
45
|
+
* - `POST /api/runs/:id/continue` -> resume a run paused at a breakpoint
|
|
46
|
+
* - `POST /api/bulk/:action` -> bulk retry/cancel every run matching a filter
|
|
47
|
+
* - `GET /api/health` -> worker-group health (compact; legacy HTML)
|
|
48
|
+
* - `GET /api/workers` -> worker-group health (full heartbeats; SPA)
|
|
49
|
+
* - `GET /api/topology` -> this deployment's durable role
|
|
50
|
+
* - `GET /api/compat` -> fleet health / protocol-compatibility panel
|
|
25
51
|
*/
|
|
26
52
|
export default class DashboardProvider {
|
|
27
53
|
app;
|
|
28
54
|
constructor(app) {
|
|
29
55
|
this.app = app;
|
|
30
56
|
}
|
|
31
|
-
/** Warn once so a throwing `login` hook doesn't spam the logs on every failed attempt. */
|
|
57
|
+
/** Warn once so a throwing `login`/`session` hook doesn't spam the logs on every failed attempt. */
|
|
32
58
|
warnedOnHookThrow = false;
|
|
33
59
|
/**
|
|
34
60
|
* Captures the engine's `capability.unavailable` / `protocol.incompatible` diagnostics events so the
|
|
@@ -47,34 +73,15 @@ export default class DashboardProvider {
|
|
|
47
73
|
if (!config.enabled)
|
|
48
74
|
return;
|
|
49
75
|
const role = this.durableRole();
|
|
50
|
-
// Route registration can't happen synchronously in `boot()
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
// `@adonisjs/core/services/router` singleton is only assigned once the app's "booted" hooks run
|
|
54
|
-
// (`await app.booted(async () => { router = ... })` inside that service module itself), which
|
|
55
|
-
// fire strictly AFTER every provider's own `boot()`. A provider that imports that singleton and
|
|
56
|
-
// calls `router.get(...)` directly inside `boot()` crashes every entrypoint (serve/ace/tests)
|
|
57
|
-
// that registers it, because `router` is still `undefined` at that point.
|
|
58
|
-
//
|
|
59
|
-
// Deferring to `app.booted(...)` runs our route registration as another "booted" hook — the
|
|
60
|
-
// same mechanism the router service uses to become available in the first place — which is
|
|
61
|
-
// guaranteed to fire BEFORE `app.start()`'s callback boots the HTTP server and commits the
|
|
62
|
-
// router (the last point at which routes can still be added). Resolving `router` fresh from the
|
|
63
|
-
// container here (rather than depending on that service singleton) is also the same pattern
|
|
64
|
-
// `@adonisjs/core`'s own `AppServiceProvider` uses internally.
|
|
76
|
+
// Route registration can't happen synchronously in `boot()` — see the long-standing note this
|
|
77
|
+
// provider always carried: the router singleton isn't committed until the app's "booted" hooks
|
|
78
|
+
// run, which fire strictly AFTER every provider's own `boot()`.
|
|
65
79
|
await this.app.booted(async () => {
|
|
66
80
|
const router = await this.app.container.make('router');
|
|
67
81
|
this.registerRoutes(router, config, role);
|
|
68
82
|
await this.attachDiagnostics(role);
|
|
69
83
|
});
|
|
70
84
|
}
|
|
71
|
-
/**
|
|
72
|
-
* Subscribe the {@link diagnostics} recorder to the store-backed engine's lifecycle events so the
|
|
73
|
-
* `/compat` panel is fed live (design §10). Store-role only: a `tenant` pod owns no engine (structural
|
|
74
|
-
* isolation), so its panel shows blocked runs reason-only. Defensive: if the engine can't be resolved
|
|
75
|
-
* (the dashboard mounted without `@adonis-agora/durable`'s provider), the recorder simply stays empty
|
|
76
|
-
* rather than crashing boot.
|
|
77
|
-
*/
|
|
78
85
|
async attachDiagnostics(role) {
|
|
79
86
|
if (role === 'tenant')
|
|
80
87
|
return;
|
|
@@ -89,27 +96,17 @@ export default class DashboardProvider {
|
|
|
89
96
|
registerRoutes(router, config, role) {
|
|
90
97
|
const apiBase = `${config.path}/api`;
|
|
91
98
|
// Resolve the dashboard's read/control port lazily per request, branched by role (design §5/§8):
|
|
92
|
-
// a store role
|
|
99
|
+
// a store role adapts the engine (built by @adonis-agora/durable's provider); a store-less `tenant`
|
|
93
100
|
// pod resolves the DURABLE_RUN_GATEWAY token (a ProxyRunGateway) and adapts it — NO engine, NO store.
|
|
94
101
|
const resolveEngine = () => dashboardEngineForRole(role, this.app.container, WorkflowEngine);
|
|
95
102
|
const deps = async () => ({ engine: await resolveEngine() });
|
|
96
|
-
// Built-in `dashboardAuth` login
|
|
97
|
-
// `dashboardAuth` leaves route registration byte-for-byte as it was. These
|
|
98
|
-
// (behind NEITHER guard): they MINT the session the guard checks for
|
|
99
|
-
// stay reachable while unauthenticated — including in production, where the default `authorize`
|
|
100
|
-
// hook would otherwise deny it.
|
|
103
|
+
// Built-in `dashboardAuth` (Mode A `session` and/or Mode B `login`, opt-in). Registered ONLY when
|
|
104
|
+
// configured, so omitting `dashboardAuth` leaves route registration byte-for-byte as it was. These
|
|
105
|
+
// endpoints are public (behind NEITHER guard): they MINT the session the guard checks for.
|
|
101
106
|
if (config.dashboardAuth) {
|
|
102
107
|
this.registerAuthRoutes(router, config, config.dashboardAuth);
|
|
103
108
|
}
|
|
104
|
-
|
|
105
|
-
router
|
|
106
|
-
.get(config.path === '' ? '/' : config.path, async (ctx) => {
|
|
107
|
-
if (!(await this.enforce(config, ctx, 'page')))
|
|
108
|
-
return;
|
|
109
|
-
ctx.response.header('content-type', 'text/html; charset=utf-8');
|
|
110
|
-
return ctx.response.send(renderDashboard(apiBase));
|
|
111
|
-
})
|
|
112
|
-
.as('durable_dashboard.index');
|
|
109
|
+
this.registerSpaRoutes(router, config, apiBase);
|
|
113
110
|
// JSON API.
|
|
114
111
|
const json = (handler) => {
|
|
115
112
|
return async (ctx) => {
|
|
@@ -129,13 +126,46 @@ export default class DashboardProvider {
|
|
|
129
126
|
router.get(`${apiBase}/runs`, json(listRuns)).as('durable_dashboard.runs.index');
|
|
130
127
|
router.get(`${apiBase}/runs/:id`, json(getRun)).as('durable_dashboard.runs.show');
|
|
131
128
|
router.post(`${apiBase}/runs/:id/retry`, json(retryRun)).as('durable_dashboard.runs.retry');
|
|
129
|
+
router
|
|
130
|
+
.post(`${apiBase}/runs/:id/retry-with-input`, json(retryWithInputRun))
|
|
131
|
+
.as('durable_dashboard.runs.retry_with_input');
|
|
132
132
|
router
|
|
133
133
|
.post(`${apiBase}/runs/:id/redispatch`, json(redispatchPendingRun))
|
|
134
134
|
.as('durable_dashboard.runs.redispatch');
|
|
135
135
|
router.post(`${apiBase}/runs/:id/cancel`, json(cancelRun)).as('durable_dashboard.runs.cancel');
|
|
136
|
+
router
|
|
137
|
+
.post(`${apiBase}/runs/:id/continue`, json(continueRun))
|
|
138
|
+
.as('durable_dashboard.runs.continue');
|
|
139
|
+
router.post(`${apiBase}/bulk/:action`, json(bulkAction)).as('durable_dashboard.bulk');
|
|
136
140
|
router
|
|
137
141
|
.get(`${apiBase}/health`, json((d) => health(d)))
|
|
138
142
|
.as('durable_dashboard.health');
|
|
143
|
+
router
|
|
144
|
+
.get(`${apiBase}/workers`, json((d) => workers(d)))
|
|
145
|
+
.as('durable_dashboard.workers');
|
|
146
|
+
router
|
|
147
|
+
.get(`${apiBase}/topology`, async (ctx) => {
|
|
148
|
+
if (!(await this.enforce(config, ctx, 'api')))
|
|
149
|
+
return;
|
|
150
|
+
// Only a `TenantConfig` carries a `partition` (its `<name>@<tenant>` routing suffix, spec
|
|
151
|
+
// §6.1) — the field this dashboard's `DurableTopology.tenant` badge actually names.
|
|
152
|
+
const durableConfig = this.app.config.get('durable', {});
|
|
153
|
+
const tenant = durableConfig.role === 'tenant' ? durableConfig.partition : undefined;
|
|
154
|
+
const result = topology(role, tenant);
|
|
155
|
+
return ctx.response.status(result.status).json(result.body);
|
|
156
|
+
})
|
|
157
|
+
.as('durable_dashboard.topology');
|
|
158
|
+
// Live-tail one run's lifecycle events over SSE — needs the raw HTTP response, so it's wired
|
|
159
|
+
// directly here rather than through the JSON `ApiResponse` convention the other routes share.
|
|
160
|
+
router
|
|
161
|
+
.get(`${apiBase}/runs/:id/stream`, async (ctx) => {
|
|
162
|
+
if (!(await this.enforce(config, ctx, 'api')))
|
|
163
|
+
return;
|
|
164
|
+
const id = ctx.params.id;
|
|
165
|
+
const engine = await resolveEngine();
|
|
166
|
+
await this.streamRun(ctx, engine, id);
|
|
167
|
+
})
|
|
168
|
+
.as('durable_dashboard.runs.stream');
|
|
139
169
|
// Fleet health / protocol-compatibility panel (design §7.6, §10): per queue/group/pod protocol +
|
|
140
170
|
// negotiated level + red-flag reason on incompatibility, plus blocked runs with their structured delta.
|
|
141
171
|
router
|
|
@@ -155,17 +185,85 @@ export default class DashboardProvider {
|
|
|
155
185
|
.as('durable_dashboard.compat');
|
|
156
186
|
}
|
|
157
187
|
/**
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
188
|
+
* Mount the React SPA at `config.path` (default) plus a `<path>/legacy` fallback serving the
|
|
189
|
+
* original hand-rolled `assets/dashboard.html` — kept for any bookmark/integration built against it,
|
|
190
|
+
* but no longer the default (per the SPA rollout, the built React console is now `GET <path>`).
|
|
191
|
+
*/
|
|
192
|
+
registerSpaRoutes(router, config, apiBase) {
|
|
193
|
+
const indexPath = config.path === '' ? '/' : config.path;
|
|
194
|
+
router
|
|
195
|
+
.get(indexPath, async (ctx) => {
|
|
196
|
+
if (!(await this.enforce(config, ctx, 'page')))
|
|
197
|
+
return;
|
|
198
|
+
let html;
|
|
199
|
+
try {
|
|
200
|
+
html = await readFile(resolvePath(spaDirectory(), 'index.html'), 'utf8');
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
return ctx.response
|
|
204
|
+
.status(404)
|
|
205
|
+
.send('The durable dashboard SPA is not built. Run `pnpm --filter @adonis-agora/durable-dashboard build` (or the package build) to emit dist/spa.');
|
|
206
|
+
}
|
|
207
|
+
return ctx.response
|
|
208
|
+
.header('content-type', 'text/html; charset=utf-8')
|
|
209
|
+
.header('cache-control', 'no-store, must-revalidate')
|
|
210
|
+
.send(renderIndexHtml(html, config.path, apiBase));
|
|
211
|
+
})
|
|
212
|
+
.as('durable_dashboard.index');
|
|
213
|
+
router
|
|
214
|
+
.get(`${config.path}/assets/:file`, async (ctx) => {
|
|
215
|
+
if (!(await this.enforce(config, ctx, 'page')))
|
|
216
|
+
return;
|
|
217
|
+
const file = basename(String(ctx.params.file));
|
|
218
|
+
const root = resolvePath(spaDirectory(), 'assets');
|
|
219
|
+
const assetPath = resolvePath(root, file);
|
|
220
|
+
if (!assetPath.startsWith(root))
|
|
221
|
+
return ctx.response.status(404).send('');
|
|
222
|
+
let bytes;
|
|
223
|
+
try {
|
|
224
|
+
bytes = await readFile(assetPath);
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
return ctx.response.status(404).send('');
|
|
228
|
+
}
|
|
229
|
+
return ctx.response
|
|
230
|
+
.header('content-type', contentTypeFor(file))
|
|
231
|
+
.header('cache-control', 'public, max-age=31536000, immutable')
|
|
232
|
+
.send(bytes);
|
|
233
|
+
})
|
|
234
|
+
.as('durable_dashboard.assets');
|
|
235
|
+
router
|
|
236
|
+
.get(`${config.path}/legacy`, async (ctx) => {
|
|
237
|
+
if (!(await this.enforce(config, ctx, 'page')))
|
|
238
|
+
return;
|
|
239
|
+
ctx.response.header('content-type', 'text/html; charset=utf-8');
|
|
240
|
+
return ctx.response.send(renderDashboard(apiBase));
|
|
241
|
+
})
|
|
242
|
+
.as('durable_dashboard.legacy');
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Stream one run's lifecycle events as `text/event-stream`, via AdonisJS's `response.stream()` (a
|
|
246
|
+
* managed pipe with graceful error handling — no raw `ServerResponse` writes). The stream stays
|
|
247
|
+
* open until the client disconnects, at which point the engine subscription is torn down and the
|
|
248
|
+
* stream ended, mirroring the NestJS sibling's `@Sse` route (`gateway.subscribe` unsubscribed on
|
|
249
|
+
* teardown).
|
|
168
250
|
*/
|
|
251
|
+
async streamRun(ctx, engine, runId) {
|
|
252
|
+
ctx.response.header('content-type', 'text/event-stream');
|
|
253
|
+
ctx.response.header('cache-control', 'no-cache');
|
|
254
|
+
ctx.response.header('connection', 'keep-alive');
|
|
255
|
+
ctx.response.header('x-accel-buffering', 'no');
|
|
256
|
+
const stream = new PassThrough();
|
|
257
|
+
const unsubscribe = engine.subscribe(runId, (event) => {
|
|
258
|
+
stream.write(`data: ${JSON.stringify(event)}\n\n`);
|
|
259
|
+
});
|
|
260
|
+
const cleanup = () => {
|
|
261
|
+
unsubscribe();
|
|
262
|
+
stream.end();
|
|
263
|
+
};
|
|
264
|
+
ctx.request.request.on('close', cleanup);
|
|
265
|
+
ctx.response.stream(stream);
|
|
266
|
+
}
|
|
169
267
|
async compatSource(engine) {
|
|
170
268
|
const live = await enumerateLiveFleet(await this.fleetTransport());
|
|
171
269
|
const fleet = mergeFleets(this.diagnostics.fleet(), live);
|
|
@@ -176,9 +274,6 @@ export default class DashboardProvider {
|
|
|
176
274
|
diagnosticsFor: (runId) => this.diagnostics.diagnosticsFor(runId),
|
|
177
275
|
};
|
|
178
276
|
}
|
|
179
|
-
/** Resolve the store role's task transport (published under {@link DURABLE_TRANSPORT}) for LIVE fleet
|
|
180
|
-
* enumeration, or `null` when unavailable — a `tenant` pod never binds it, and a mis-mounted dashboard
|
|
181
|
-
* degrades cleanly to the diagnostics-only view rather than crashing the panel. */
|
|
182
277
|
async fleetTransport() {
|
|
183
278
|
try {
|
|
184
279
|
return (await this.app.container.make(DURABLE_TRANSPORT));
|
|
@@ -188,64 +283,84 @@ export default class DashboardProvider {
|
|
|
188
283
|
}
|
|
189
284
|
}
|
|
190
285
|
/**
|
|
191
|
-
* Mount the built-in `dashboardAuth` endpoints under `basePath`. All
|
|
192
|
-
*
|
|
286
|
+
* Mount the built-in `dashboardAuth` endpoints under `basePath`. All are public (no guard): they
|
|
287
|
+
* create/destroy the session the {@link enforce} guard checks for.
|
|
193
288
|
*
|
|
194
|
-
* - `GET <base>/login`
|
|
195
|
-
*
|
|
196
|
-
* - `POST <base>/
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
289
|
+
* - `GET <base>/login` -> the server-rendered login page (Mode B only).
|
|
290
|
+
* - `POST <base>/login` -> verifies credentials via the host `login` hook and mints the cookie.
|
|
291
|
+
* - `POST <base>/session` -> Mode A: verifies the HOST APP's own auth (off the raw request) via the
|
|
292
|
+
* `session` hook and mints the cookie. No body — the hook reads whatever it needs off `request`.
|
|
293
|
+
* `204` on success, uniform `401` on denial. Mirrors `@dudousxd/nestjs-durable-dashboard`'s
|
|
294
|
+
* `DurableAuthController.session` and `client/console-session.ts`'s `mintDurableConsoleSession`.
|
|
295
|
+
* - `GET <base>/logout` -> clears the cookie and redirects to the login page (Mode B) or the
|
|
296
|
+
* dashboard root (Mode A only). A plain `GET` (idempotent, only ever destroys the caller's own
|
|
297
|
+
* session) so a simple `<a href>` works.
|
|
201
298
|
*/
|
|
202
299
|
registerAuthRoutes(router, config, auth) {
|
|
203
300
|
const loginPath = `${config.path}/login`;
|
|
301
|
+
const sessionPath = `${config.path}/session`;
|
|
204
302
|
const logoutPath = `${config.path}/logout`;
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
if (outcome.kind === 'unauthorized') {
|
|
219
|
-
// A throwing hook is a denial (never a 500), warn-logged once so a buggy hook doesn't
|
|
220
|
-
// flood the logs. The client sees the same uniform 401 either way.
|
|
221
|
-
if (outcome.hookError !== undefined && !this.warnedOnHookThrow) {
|
|
222
|
-
this.warnedOnHookThrow = true;
|
|
223
|
-
const message = outcome.hookError instanceof Error
|
|
224
|
-
? outcome.hookError.message
|
|
225
|
-
: String(outcome.hookError);
|
|
226
|
-
const logger = await this.app.container.make('logger');
|
|
227
|
-
logger.warn(`dashboardAuth login hook threw; treating as denial. ${message}`);
|
|
303
|
+
if (auth.login) {
|
|
304
|
+
router
|
|
305
|
+
.get(loginPath, async (ctx) => {
|
|
306
|
+
ctx.response.header('content-type', 'text/html; charset=utf-8');
|
|
307
|
+
ctx.response.header('cache-control', 'no-store, must-revalidate');
|
|
308
|
+
return ctx.response.send(renderLoginPage(config.path));
|
|
309
|
+
})
|
|
310
|
+
.as('durable_dashboard.login.page');
|
|
311
|
+
router
|
|
312
|
+
.post(loginPath, async (ctx) => {
|
|
313
|
+
const outcome = await performLogin(auth, ctx.request.body(), config.path);
|
|
314
|
+
if (outcome.kind === 'bad-request') {
|
|
315
|
+
return ctx.response.status(400).json({ error: outcome.message });
|
|
228
316
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
317
|
+
if (outcome.kind === 'unauthorized') {
|
|
318
|
+
this.warnHookThrow(outcome.hookError);
|
|
319
|
+
return ctx.response.status(401).json({ error: outcome.message });
|
|
320
|
+
}
|
|
321
|
+
this.writeSessionCookie(ctx, auth, outcome.cookieValue);
|
|
322
|
+
return ctx.response.status(200).json({ redirectTo: outcome.redirectTo });
|
|
323
|
+
})
|
|
324
|
+
.as('durable_dashboard.login.submit');
|
|
325
|
+
}
|
|
326
|
+
if (auth.session) {
|
|
327
|
+
router
|
|
328
|
+
.post(sessionPath, async (ctx) => {
|
|
329
|
+
const outcome = await performSession(auth, ctx.request.request);
|
|
330
|
+
if (outcome.kind === 'unauthorized') {
|
|
331
|
+
this.warnHookThrow(outcome.hookError);
|
|
332
|
+
return ctx.response.status(401).json({ error: 'unauthorized' });
|
|
333
|
+
}
|
|
334
|
+
this.writeSessionCookie(ctx, auth, outcome.cookieValue);
|
|
335
|
+
return ctx.response.status(204).send('');
|
|
336
|
+
})
|
|
337
|
+
.as('durable_dashboard.session.mint');
|
|
338
|
+
}
|
|
235
339
|
router
|
|
236
340
|
.get(logoutPath, async (ctx) => {
|
|
237
341
|
ctx.response.clearCookie(SESSION_COOKIE_NAME, { path: '/' });
|
|
238
|
-
return ctx.response.redirect().toPath(loginPath);
|
|
342
|
+
return ctx.response.redirect().toPath(auth.login ? loginPath : config.path || '/');
|
|
239
343
|
})
|
|
240
344
|
.as('durable_dashboard.logout');
|
|
241
345
|
}
|
|
346
|
+
async warnHookThrow(hookError) {
|
|
347
|
+
if (hookError === undefined || this.warnedOnHookThrow)
|
|
348
|
+
return;
|
|
349
|
+
this.warnedOnHookThrow = true;
|
|
350
|
+
const message = hookError instanceof Error ? hookError.message : String(hookError);
|
|
351
|
+
const logger = await this.app.container.make('logger');
|
|
352
|
+
logger.warn(`dashboardAuth login/session hook threw; treating as denial. ${message}`);
|
|
353
|
+
}
|
|
242
354
|
/**
|
|
243
355
|
* Run the guards for a dashboard resource. Composes the existing `authorize` hook (bearer
|
|
244
356
|
* token/custom) with the optional `dashboardAuth` session guard — BOTH must pass:
|
|
245
357
|
*
|
|
246
|
-
* 1. `authorize` fails
|
|
247
|
-
* 2. `dashboardAuth` configured AND no valid session
|
|
248
|
-
* the login page carrying a sanitized `returnTo
|
|
358
|
+
* 1. `authorize` fails -> `403` (unchanged behavior).
|
|
359
|
+
* 2. `dashboardAuth` configured AND no valid session -> for a `page` request, redirect `302` to
|
|
360
|
+
* the login page (Mode B) carrying a sanitized `returnTo`, or a `401` "session required" notice
|
|
361
|
+
* (Mode A only, no login page to redirect to); for an `api` request, a plain
|
|
362
|
+
* `401 { error: 'unauthorized', auth: { modes } }` — the `modes` list lets the SPA's client
|
|
363
|
+
* (`durable-client.ts`) decide whether to offer the login page.
|
|
249
364
|
*
|
|
250
365
|
* When `dashboardAuth` is unconfigured only step 1 runs, so behavior is byte-for-byte unchanged.
|
|
251
366
|
* Returns `false` (and has already written the response) when the request must short-circuit.
|
|
@@ -253,10 +368,6 @@ export default class DashboardProvider {
|
|
|
253
368
|
async enforce(config, ctx, mode) {
|
|
254
369
|
const allowed = await config.authorize(ctx);
|
|
255
370
|
if (!allowed) {
|
|
256
|
-
// A custom hook may have WRITTEN its own denial before returning false — typically a redirect
|
|
257
|
-
// to the host app's login page (`ctx.response.redirect('/login')`), the natural UX when the
|
|
258
|
-
// dashboard is guarded by the app's own session instead of a bearer token. Respect it: only
|
|
259
|
-
// fall back to the uniform 403 when the hook left the response untouched (no Location header).
|
|
260
371
|
if (!ctx.response.getHeader('location')) {
|
|
261
372
|
ctx.response.status(403).json({ error: 'forbidden' });
|
|
262
373
|
}
|
|
@@ -269,24 +380,27 @@ export default class DashboardProvider {
|
|
|
269
380
|
if (session)
|
|
270
381
|
return true;
|
|
271
382
|
if (mode === 'page') {
|
|
272
|
-
|
|
273
|
-
|
|
383
|
+
if (auth.login) {
|
|
384
|
+
const returnTo = ctx.request.url(true);
|
|
385
|
+
ctx.response.redirect().withQs('returnTo', returnTo).toPath(`${config.path}/login`);
|
|
386
|
+
return false;
|
|
387
|
+
}
|
|
388
|
+
// Mode A only: there's no login page to send the browser to — this deployment expects the
|
|
389
|
+
// host app to mint a session via `POST <path>/session` before ever navigating here.
|
|
390
|
+
ctx.response
|
|
391
|
+
.status(401)
|
|
392
|
+
.header('content-type', 'text/html; charset=utf-8')
|
|
393
|
+
.header('cache-control', 'no-store, must-revalidate')
|
|
394
|
+
.send('<!doctype html><html><body style="font-family:ui-monospace,monospace;background:#09090b;color:#e7e7ea;display:flex;align-items:center;justify-content:center;height:100vh;margin:0"><p>Open this console from your application.</p></body></html>');
|
|
274
395
|
return false;
|
|
275
396
|
}
|
|
276
|
-
ctx.response.status(401).json({ error: 'unauthorized' });
|
|
397
|
+
ctx.response.status(401).json({ error: 'unauthorized', auth: { modes: auth.modes } });
|
|
277
398
|
return false;
|
|
278
399
|
}
|
|
279
|
-
/** Read the raw (unencoded) session cookie value, or `undefined` when absent. */
|
|
280
400
|
readSessionCookie(ctx) {
|
|
281
401
|
const value = ctx.request.plainCookie(SESSION_COOKIE_NAME, undefined, false);
|
|
282
402
|
return typeof value === 'string' && value !== '' ? value : undefined;
|
|
283
403
|
}
|
|
284
|
-
/**
|
|
285
|
-
* Write the signed session as an unsigned (`plainCookie`, `encode: false`) cookie — the value
|
|
286
|
-
* carries its own HMAC signature, so AdonisJS's cookie signing would be redundant double-wrapping.
|
|
287
|
-
* `HttpOnly` + `SameSite=Lax` (blocks cross-site POSTs carrying the cookie — CSRF coverage) +
|
|
288
|
-
* `Secure` on https. `Path=/` so it reaches both the UI and API mounts regardless of prefix.
|
|
289
|
-
*/
|
|
290
404
|
writeSessionCookie(ctx, auth, value) {
|
|
291
405
|
ctx.response.plainCookie(SESSION_COOKIE_NAME, value, {
|
|
292
406
|
httpOnly: true,
|
|
@@ -297,7 +411,6 @@ export default class DashboardProvider {
|
|
|
297
411
|
encode: false,
|
|
298
412
|
});
|
|
299
413
|
}
|
|
300
|
-
/** Detach the diagnostics subscription so the recorder stops listening on a clean shutdown/redeploy. */
|
|
301
414
|
async shutdown() {
|
|
302
415
|
this.detachDiagnostics?.();
|
|
303
416
|
this.detachDiagnostics = null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard_provider.js","sourceRoot":"","sources":["../../providers/dashboard_provider.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dashboard_provider.js","sourceRoot":"","sources":["../../providers/dashboard_provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AttributeFilter } from '../interfaces.js';
|
|
2
|
+
/**
|
|
3
|
+
* Parse `attr=key:op:value` query params (repeatable, ANDed) into {@link AttributeFilter}s — e.g.
|
|
4
|
+
* `?attr=amount:gte:200&attr=tier:eq:pro`. `op` must be a known operator; a colon in the value is
|
|
5
|
+
* preserved (only the first two colons delimit). Malformed entries are skipped.
|
|
6
|
+
*/
|
|
7
|
+
export declare function parseAttrFilters(attr?: string | string[]): AttributeFilter[] | undefined;
|
|
8
|
+
//# sourceMappingURL=attr-filter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attr-filter.d.ts","sourceRoot":"","sources":["../../../src/dashboard/attr-filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAe,MAAM,kBAAkB,CAAC;AAkBrE;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,eAAe,EAAE,GAAG,SAAS,CAUxF"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ported from `@dudousxd/nestjs-durable-dashboard`'s `attr-filter.ts` — parses the same
|
|
3
|
+
* `attr=key:op:value` query convention so the dashboard's search-attribute filtering behaves
|
|
4
|
+
* identically across both ecosystems.
|
|
5
|
+
*/
|
|
6
|
+
const ATTR_OPS = new Set(['eq', 'ne', 'gt', 'gte', 'lt', 'lte']);
|
|
7
|
+
/** Coerce a query-string value: `true`/`false` -> boolean, numeric -> number, else the raw string. */
|
|
8
|
+
function coerce(v) {
|
|
9
|
+
if (v === 'true')
|
|
10
|
+
return true;
|
|
11
|
+
if (v === 'false')
|
|
12
|
+
return false;
|
|
13
|
+
if (v !== '' && !Number.isNaN(Number(v)))
|
|
14
|
+
return Number(v);
|
|
15
|
+
return v;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Parse `attr=key:op:value` query params (repeatable, ANDed) into {@link AttributeFilter}s — e.g.
|
|
19
|
+
* `?attr=amount:gte:200&attr=tier:eq:pro`. `op` must be a known operator; a colon in the value is
|
|
20
|
+
* preserved (only the first two colons delimit). Malformed entries are skipped.
|
|
21
|
+
*/
|
|
22
|
+
export function parseAttrFilters(attr) {
|
|
23
|
+
if (!attr)
|
|
24
|
+
return undefined;
|
|
25
|
+
const raw = Array.isArray(attr) ? attr : [attr];
|
|
26
|
+
const filters = [];
|
|
27
|
+
for (const entry of raw) {
|
|
28
|
+
const [key, op, ...rest] = entry.split(':');
|
|
29
|
+
if (!key || !ATTR_OPS.has(op) || rest.length === 0)
|
|
30
|
+
continue;
|
|
31
|
+
filters.push({ key, op: op, value: coerce(rest.join(':')) });
|
|
32
|
+
}
|
|
33
|
+
return filters.length ? filters : undefined;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=attr-filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attr-filter.js","sourceRoot":"","sources":["../../../src/dashboard/attr-filter.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAc,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;AAE9E,sGAAsG;AACtG,SAAS,MAAM,CAAC,CAAS;IACvB,IAAI,CAAC,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IAC9B,IAAI,CAAC,KAAK,OAAO;QAAE,OAAO,KAAK,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IAC3D,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAwB;IACvD,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAC;IAC5B,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,OAAO,GAAsB,EAAE,CAAC;IACtC,KAAK,MAAM,KAAK,IAAI,GAAG,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5C,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAiB,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAC5E,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,EAAiB,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9C,CAAC"}
|