@dudousxd/nestjs-media-dashboard 0.1.3 → 0.2.1

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.
@@ -35,18 +35,260 @@ var getImportMetaUrl = /* @__PURE__ */ __name(() => typeof document === "undefin
35
35
  var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
36
36
 
37
37
  // src/server/media-dashboard.module.ts
38
- var import_common6 = require("@nestjs/common");
38
+ var import_common8 = require("@nestjs/common");
39
39
  var import_core = require("@nestjs/core");
40
40
 
41
+ // src/server/auth/config.ts
42
+ var DEFAULT_TTL_MS = 8 * 60 * 60 * 1e3;
43
+ var DURATION_UNITS = {
44
+ s: 1e3,
45
+ m: 60 * 1e3,
46
+ h: 60 * 60 * 1e3,
47
+ d: 24 * 60 * 60 * 1e3
48
+ };
49
+ function durationToMs(ttl) {
50
+ if (ttl === void 0) return DEFAULT_TTL_MS;
51
+ const match = /^(\d+)([smhd])$/.exec(ttl.trim());
52
+ if (!match) return DEFAULT_TTL_MS;
53
+ const unit = DURATION_UNITS[match[2] ?? ""];
54
+ if (unit === void 0) return DEFAULT_TTL_MS;
55
+ return Number(match[1]) * unit;
56
+ }
57
+ __name(durationToMs, "durationToMs");
58
+ function resolveConsoleAuth(options) {
59
+ if (!options) return null;
60
+ if (!options.secret) {
61
+ throw new Error("MediaDashboardModule: auth.secret is required when `auth` is configured.");
62
+ }
63
+ const modes = [];
64
+ if (options.session) modes.push("session");
65
+ if (options.login) modes.push("login");
66
+ if (modes.length === 0) {
67
+ throw new Error("MediaDashboardModule: auth needs a `login` and/or `session` hook.");
68
+ }
69
+ return {
70
+ secret: options.secret,
71
+ ttlMs: durationToMs(options.ttl),
72
+ modes,
73
+ ...options.session ? {
74
+ session: options.session
75
+ } : {},
76
+ ...options.login ? {
77
+ login: options.login
78
+ } : {}
79
+ };
80
+ }
81
+ __name(resolveConsoleAuth, "resolveConsoleAuth");
82
+
41
83
  // src/server/media-console-api.module.ts
42
- var import_common4 = require("@nestjs/common");
84
+ var import_common6 = require("@nestjs/common");
43
85
 
44
86
  // src/server/media-console-actions.controller.ts
45
- var import_common2 = require("@nestjs/common");
87
+ var import_common3 = require("@nestjs/common");
46
88
 
47
- // src/server/media-console.service.ts
89
+ // src/server/media-console.guard.ts
48
90
  var import_common = require("@nestjs/common");
49
91
 
92
+ // src/server/auth/cookie-header.ts
93
+ function parseCookieHeader(header) {
94
+ const cookies = {};
95
+ if (typeof header !== "string" || header === "") return cookies;
96
+ for (const segment of header.split(";")) {
97
+ const eq = segment.indexOf("=");
98
+ if (eq <= 0) continue;
99
+ const name = segment.slice(0, eq).trim();
100
+ if (name === "") continue;
101
+ let rawValue = segment.slice(eq + 1).trim();
102
+ if (rawValue.length >= 2 && rawValue.startsWith('"') && rawValue.endsWith('"')) {
103
+ rawValue = rawValue.slice(1, -1);
104
+ }
105
+ if (name in cookies) continue;
106
+ try {
107
+ cookies[name] = decodeURIComponent(rawValue);
108
+ } catch {
109
+ cookies[name] = rawValue;
110
+ }
111
+ }
112
+ return cookies;
113
+ }
114
+ __name(parseCookieHeader, "parseCookieHeader");
115
+ function serializeSetCookie(name, value, options) {
116
+ const parts = [
117
+ `${name}=${options.clear ? "" : encodeURIComponent(value)}`
118
+ ];
119
+ parts.push(`Path=${options.path}`);
120
+ parts.push("HttpOnly");
121
+ parts.push("SameSite=Lax");
122
+ if (options.secure) parts.push("Secure");
123
+ if (options.clear) {
124
+ parts.push("Max-Age=0");
125
+ parts.push("Expires=Thu, 01 Jan 1970 00:00:00 GMT");
126
+ } else {
127
+ parts.push(`Max-Age=${options.maxAgeSeconds}`);
128
+ }
129
+ return parts.join("; ");
130
+ }
131
+ __name(serializeSetCookie, "serializeSetCookie");
132
+
133
+ // src/server/auth/request.ts
134
+ function isRecord(value) {
135
+ return typeof value === "object" && value !== null;
136
+ }
137
+ __name(isRecord, "isRecord");
138
+ function readHeaders(request) {
139
+ if (!isRecord(request)) return {};
140
+ const headers = request.headers;
141
+ return isRecord(headers) ? headers : {};
142
+ }
143
+ __name(readHeaders, "readHeaders");
144
+ function headerToString(value) {
145
+ if (typeof value === "string") return value;
146
+ if (Array.isArray(value) && value.every((part) => typeof part === "string")) {
147
+ return value.join(",");
148
+ }
149
+ return void 0;
150
+ }
151
+ __name(headerToString, "headerToString");
152
+ function readCookieHeader(request) {
153
+ return headerToString(readHeaders(request).cookie);
154
+ }
155
+ __name(readCookieHeader, "readCookieHeader");
156
+ function isHttpsRequest(request) {
157
+ if (isRecord(request) && request.protocol === "https") return true;
158
+ const forwarded = headerToString(readHeaders(request)["x-forwarded-proto"]);
159
+ if (forwarded === void 0) return false;
160
+ return forwarded.split(",").map((proto) => proto.trim().toLowerCase()).includes("https");
161
+ }
162
+ __name(isHttpsRequest, "isHttpsRequest");
163
+ function attachSession(request, session) {
164
+ if (!isRecord(request)) return;
165
+ request.consoleSession = session;
166
+ }
167
+ __name(attachSession, "attachSession");
168
+
169
+ // src/server/auth/response.ts
170
+ function isRecord2(value) {
171
+ return typeof value === "object" && value !== null;
172
+ }
173
+ __name(isRecord2, "isRecord");
174
+ function isRawNodeResponse(value) {
175
+ return isRecord2(value) && typeof value.getHeader === "function" && typeof value.setHeader === "function";
176
+ }
177
+ __name(isRawNodeResponse, "isRawNodeResponse");
178
+ function resolveRawResponse(response) {
179
+ if (isRawNodeResponse(response)) return response;
180
+ if (isRecord2(response) && isRawNodeResponse(response.raw)) return response.raw;
181
+ return null;
182
+ }
183
+ __name(resolveRawResponse, "resolveRawResponse");
184
+ function existingSetCookies(response) {
185
+ const current = response.getHeader("set-cookie");
186
+ if (Array.isArray(current)) return current;
187
+ if (typeof current === "string") return [
188
+ current
189
+ ];
190
+ return [];
191
+ }
192
+ __name(existingSetCookies, "existingSetCookies");
193
+ function appendSetCookie(response, cookie) {
194
+ const raw = resolveRawResponse(response);
195
+ if (!raw) return;
196
+ raw.setHeader("set-cookie", [
197
+ ...existingSetCookies(raw),
198
+ cookie
199
+ ]);
200
+ }
201
+ __name(appendSetCookie, "appendSetCookie");
202
+
203
+ // src/server/auth/session-cookie.ts
204
+ var import_node_crypto = require("crypto");
205
+ var EXP_GRACE_MS = 3e4;
206
+ function base64urlEncode(value) {
207
+ return Buffer.from(value, "utf8").toString("base64url");
208
+ }
209
+ __name(base64urlEncode, "base64urlEncode");
210
+ function base64urlDecode(value) {
211
+ return Buffer.from(value, "base64url").toString("utf8");
212
+ }
213
+ __name(base64urlDecode, "base64urlDecode");
214
+ function hmac(secret, payload) {
215
+ return (0, import_node_crypto.createHmac)("sha256", secret).update(payload).digest("base64url");
216
+ }
217
+ __name(hmac, "hmac");
218
+ function signSessionCookie(user, options) {
219
+ const issuedAt = options.now ?? Date.now();
220
+ const session = {
221
+ sub: user.id,
222
+ ...user.name !== void 0 ? {
223
+ name: user.name
224
+ } : {},
225
+ roles: user.roles ?? [],
226
+ iat: issuedAt,
227
+ exp: issuedAt + options.ttlMs
228
+ };
229
+ const encodedPayload = base64urlEncode(JSON.stringify(session));
230
+ return `${encodedPayload}.${hmac(options.secret, encodedPayload)}`;
231
+ }
232
+ __name(signSessionCookie, "signSessionCookie");
233
+ function isSessionPayload(value) {
234
+ if (typeof value !== "object" || value === null) return false;
235
+ const record = value;
236
+ if (typeof record.sub !== "string") return false;
237
+ if (record.name !== void 0 && typeof record.name !== "string") return false;
238
+ if (!Array.isArray(record.roles)) return false;
239
+ if (!record.roles.every((role) => typeof role === "string")) return false;
240
+ if (typeof record.iat !== "number" || !Number.isFinite(record.iat)) return false;
241
+ if (typeof record.exp !== "number" || !Number.isFinite(record.exp)) return false;
242
+ return true;
243
+ }
244
+ __name(isSessionPayload, "isSessionPayload");
245
+ function verifySessionCookie(value, options) {
246
+ try {
247
+ const dot = value.indexOf(".");
248
+ if (dot <= 0 || dot === value.length - 1) return null;
249
+ const encodedPayload = value.slice(0, dot);
250
+ const provided = Buffer.from(value.slice(dot + 1), "base64url");
251
+ const expected = Buffer.from(hmac(options.secret, encodedPayload), "base64url");
252
+ if (provided.length !== expected.length) return null;
253
+ if (!(0, import_node_crypto.timingSafeEqual)(provided, expected)) return null;
254
+ const decoded = JSON.parse(base64urlDecode(encodedPayload));
255
+ if (!isSessionPayload(decoded)) return null;
256
+ const now = options.now ?? Date.now();
257
+ if (now > decoded.exp + EXP_GRACE_MS) return null;
258
+ return decoded;
259
+ } catch {
260
+ return null;
261
+ }
262
+ }
263
+ __name(verifySessionCookie, "verifySessionCookie");
264
+
265
+ // src/server/auth/session-cookie-io.ts
266
+ var SESSION_COOKIE_NAME = "media_console_session";
267
+ function issueSessionCookie(user, context) {
268
+ const value = signSessionCookie(user, {
269
+ secret: context.auth.secret,
270
+ ttlMs: context.auth.ttlMs,
271
+ ...context.now !== void 0 ? {
272
+ now: context.now
273
+ } : {}
274
+ });
275
+ appendSetCookie(context.response, serializeSetCookie(SESSION_COOKIE_NAME, value, {
276
+ path: context.cookiePath,
277
+ maxAgeSeconds: Math.floor(context.auth.ttlMs / 1e3),
278
+ secure: isHttpsRequest(context.request)
279
+ }));
280
+ }
281
+ __name(issueSessionCookie, "issueSessionCookie");
282
+ function clearSessionCookie(context) {
283
+ appendSetCookie(context.response, serializeSetCookie(SESSION_COOKIE_NAME, "", {
284
+ path: context.cookiePath,
285
+ maxAgeSeconds: 0,
286
+ secure: isHttpsRequest(context.request),
287
+ clear: true
288
+ }));
289
+ }
290
+ __name(clearSessionCookie, "clearSessionCookie");
291
+
50
292
  // src/server/tokens.ts
51
293
  var MEDIA_STORE = Symbol.for("nestjs-media:store");
52
294
  var MEDIA_UPLOAD_SESSIONS = Symbol.for("nestjs-media:upload-sessions");
@@ -54,8 +296,10 @@ var MEDIA_STORAGE_SHARED = Symbol.for("nestjs-media:storage");
54
296
  var MEDIA_DASHBOARD_BASE_PATH = Symbol("MEDIA_DASHBOARD_BASE_PATH");
55
297
  var MEDIA_DASHBOARD_API_PATH = Symbol("MEDIA_DASHBOARD_API_PATH");
56
298
  var MEDIA_DASHBOARD_ACTIONS = Symbol("MEDIA_DASHBOARD_ACTIONS");
299
+ var MEDIA_CONSOLE_AUTH = Symbol("MEDIA_CONSOLE_AUTH");
300
+ var MEDIA_CONSOLE_COOKIE_PATH = Symbol("MEDIA_CONSOLE_COOKIE_PATH");
57
301
 
58
- // src/server/media-console.service.ts
302
+ // src/server/media-console.guard.ts
59
303
  function _ts_decorate(decorators, target, key, desc) {
60
304
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
61
305
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -73,6 +317,89 @@ function _ts_param(paramIndex, decorator) {
73
317
  };
74
318
  }
75
319
  __name(_ts_param, "_ts_param");
320
+ var MediaConsoleGuard = class {
321
+ static {
322
+ __name(this, "MediaConsoleGuard");
323
+ }
324
+ auth;
325
+ cookiePath;
326
+ constructor(auth, cookiePath) {
327
+ this.auth = auth;
328
+ this.cookiePath = cookiePath;
329
+ }
330
+ canActivate(context) {
331
+ if (!this.auth) return true;
332
+ const http = context.switchToHttp();
333
+ const request = http.getRequest();
334
+ const session = this.verifyRequestSession(request);
335
+ if (!session) throw new import_common.UnauthorizedException();
336
+ attachSession(request, session);
337
+ this.maybeRenew(http.getResponse(), request, session);
338
+ return true;
339
+ }
340
+ verifyRequestSession(request) {
341
+ if (!this.auth) return null;
342
+ const cookieValue = parseCookieHeader(readCookieHeader(request))[SESSION_COOKIE_NAME];
343
+ if (cookieValue === void 0) return null;
344
+ return verifySessionCookie(cookieValue, {
345
+ secret: this.auth.secret
346
+ });
347
+ }
348
+ /**
349
+ * Sliding renewal: when a valid cookie is past half its TTL, re-issue a fresh one so active users
350
+ * never get logged out mid-session. Appends a new Set-Cookie (preserving any others already set).
351
+ */
352
+ maybeRenew(response, request, session) {
353
+ if (!this.auth) return;
354
+ const now = Date.now();
355
+ if (now - session.iat <= this.auth.ttlMs / 2) return;
356
+ issueSessionCookie({
357
+ id: session.sub,
358
+ ...session.name !== void 0 ? {
359
+ name: session.name
360
+ } : {},
361
+ roles: session.roles
362
+ }, {
363
+ auth: this.auth,
364
+ cookiePath: this.cookiePath ?? "/",
365
+ request,
366
+ response,
367
+ now
368
+ });
369
+ }
370
+ };
371
+ MediaConsoleGuard = _ts_decorate([
372
+ (0, import_common.Injectable)(),
373
+ _ts_param(0, (0, import_common.Optional)()),
374
+ _ts_param(0, (0, import_common.Inject)(MEDIA_CONSOLE_AUTH)),
375
+ _ts_param(1, (0, import_common.Optional)()),
376
+ _ts_param(1, (0, import_common.Inject)(MEDIA_CONSOLE_COOKIE_PATH)),
377
+ _ts_metadata("design:type", Function),
378
+ _ts_metadata("design:paramtypes", [
379
+ Object,
380
+ Object
381
+ ])
382
+ ], MediaConsoleGuard);
383
+
384
+ // src/server/media-console.service.ts
385
+ var import_common2 = require("@nestjs/common");
386
+ function _ts_decorate2(decorators, target, key, desc) {
387
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
388
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
389
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
390
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
391
+ }
392
+ __name(_ts_decorate2, "_ts_decorate");
393
+ function _ts_metadata2(k, v) {
394
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
395
+ }
396
+ __name(_ts_metadata2, "_ts_metadata");
397
+ function _ts_param2(paramIndex, decorator) {
398
+ return function(target, key) {
399
+ decorator(target, key, paramIndex);
400
+ };
401
+ }
402
+ __name(_ts_param2, "_ts_param");
76
403
  var URL_TTL_SECONDS = 300;
77
404
  var DEFAULT_PAGE_LIMIT = 50;
78
405
  function lastSegment(prefix) {
@@ -130,7 +457,7 @@ var MediaConsoleService = class {
130
457
  }
131
458
  diskOrThrow(disk) {
132
459
  if (!this.storage || !this.storage.diskNames().includes(disk)) {
133
- throw new import_common.NotFoundException(`Unknown disk: ${disk}`);
460
+ throw new import_common2.NotFoundException(`Unknown disk: ${disk}`);
134
461
  }
135
462
  return this.storage.disk(disk);
136
463
  }
@@ -177,9 +504,7 @@ var MediaConsoleService = class {
177
504
  }
178
505
  async objectDetail(disk, key) {
179
506
  const driver = this.diskOrThrow(disk);
180
- const stat = driver.stat ? await driver.stat(key) : {
181
- size: await driver.size(key)
182
- };
507
+ const stat = await driver.stat(key);
183
508
  const url = driver.capabilities.presign ? await driver.temporaryUrl(key, URL_TTL_SECONDS) : await driver.url(key);
184
509
  return {
185
510
  key,
@@ -198,9 +523,7 @@ var MediaConsoleService = class {
198
523
  * (and so a CORS-locked bucket is still previewable). */
199
524
  async objectStream(disk, key) {
200
525
  const driver = this.diskOrThrow(disk);
201
- const stat = driver.stat ? await driver.stat(key) : {
202
- size: await driver.size(key)
203
- };
526
+ const stat = await driver.stat(key);
204
527
  const stream = await driver.stream(key);
205
528
  return {
206
529
  stream,
@@ -219,7 +542,7 @@ var MediaConsoleService = class {
219
542
  * as a navigable folder. Normalizes to exactly one trailing slash; rejects an empty prefix. */
220
543
  async createFolder(disk, prefix) {
221
544
  const normalized = prefix.replace(/^\/+/, "").replace(/\/+$/, "");
222
- if (normalized === "") throw new import_common.BadRequestException("Folder name is required");
545
+ if (normalized === "") throw new import_common2.BadRequestException("Folder name is required");
223
546
  await this.diskOrThrow(disk).put(`${normalized}/`, Buffer.alloc(0));
224
547
  }
225
548
  async deleteObject(disk, key) {
@@ -248,9 +571,9 @@ var MediaConsoleService = class {
248
571
  };
249
572
  }
250
573
  async uploadDetail(id) {
251
- if (!this.uploads) throw new import_common.NotFoundException("No upload store configured");
574
+ if (!this.uploads) throw new import_common2.NotFoundException("No upload store configured");
252
575
  const session = await this.uploads.get(id);
253
- if (!session) throw new import_common.NotFoundException(`Unknown upload: ${id}`);
576
+ if (!session) throw new import_common2.NotFoundException(`Unknown upload: ${id}`);
254
577
  const parts = this.uploads.listParts ? await this.uploads.listParts(id) : [];
255
578
  return {
256
579
  upload: mapUpload(session),
@@ -265,7 +588,7 @@ var MediaConsoleService = class {
265
588
  * multipart is reaped by the bucket's lifecycle policy. Surfaced as "Cancel session" in the UI.
266
589
  */
267
590
  async abortUpload(id) {
268
- if (!this.uploads) throw new import_common.NotFoundException("No upload store configured");
591
+ if (!this.uploads) throw new import_common2.NotFoundException("No upload store configured");
269
592
  await this.uploads.delete(id);
270
593
  }
271
594
  async listCollections() {
@@ -305,9 +628,9 @@ var MediaConsoleService = class {
305
628
  };
306
629
  }
307
630
  async libraryDetail(id) {
308
- if (!this.store) throw new import_common.NotFoundException("No media store configured");
631
+ if (!this.store) throw new import_common2.NotFoundException("No media store configured");
309
632
  const record = await this.store.find(id);
310
- if (!record) throw new import_common.NotFoundException(`Unknown media record: ${id}`);
633
+ if (!record) throw new import_common2.NotFoundException(`Unknown media record: ${id}`);
311
634
  const variants = await Promise.all(Object.entries(record.conversions).map(async ([name, conversion]) => {
312
635
  const driver = this.storage?.diskNames().includes(conversion.disk) ? this.storage.disk(conversion.disk) : null;
313
636
  const url = driver?.capabilities.presign ? await driver.temporaryUrl(conversion.path, URL_TTL_SECONDS) : await driver?.url(conversion.path) ?? "";
@@ -322,7 +645,7 @@ var MediaConsoleService = class {
322
645
  };
323
646
  }
324
647
  async deleteLibraryRecord(id) {
325
- if (!this.store) throw new import_common.NotFoundException("No media store configured");
648
+ if (!this.store) throw new import_common2.NotFoundException("No media store configured");
326
649
  await this.store.delete(id);
327
650
  }
328
651
  topology() {
@@ -334,18 +657,18 @@ var MediaConsoleService = class {
334
657
  };
335
658
  }
336
659
  };
337
- MediaConsoleService = _ts_decorate([
338
- (0, import_common.Injectable)(),
339
- _ts_param(0, (0, import_common.Optional)()),
340
- _ts_param(0, (0, import_common.Inject)(MEDIA_STORAGE_SHARED)),
341
- _ts_param(1, (0, import_common.Optional)()),
342
- _ts_param(1, (0, import_common.Inject)(MEDIA_STORE)),
343
- _ts_param(2, (0, import_common.Optional)()),
344
- _ts_param(2, (0, import_common.Inject)(MEDIA_UPLOAD_SESSIONS)),
345
- _ts_param(3, (0, import_common.Optional)()),
346
- _ts_param(3, (0, import_common.Inject)(MEDIA_DASHBOARD_ACTIONS)),
347
- _ts_metadata("design:type", Function),
348
- _ts_metadata("design:paramtypes", [
660
+ MediaConsoleService = _ts_decorate2([
661
+ (0, import_common2.Injectable)(),
662
+ _ts_param2(0, (0, import_common2.Optional)()),
663
+ _ts_param2(0, (0, import_common2.Inject)(MEDIA_STORAGE_SHARED)),
664
+ _ts_param2(1, (0, import_common2.Optional)()),
665
+ _ts_param2(1, (0, import_common2.Inject)(MEDIA_STORE)),
666
+ _ts_param2(2, (0, import_common2.Optional)()),
667
+ _ts_param2(2, (0, import_common2.Inject)(MEDIA_UPLOAD_SESSIONS)),
668
+ _ts_param2(3, (0, import_common2.Optional)()),
669
+ _ts_param2(3, (0, import_common2.Inject)(MEDIA_DASHBOARD_ACTIONS)),
670
+ _ts_metadata2("design:type", Function),
671
+ _ts_metadata2("design:paramtypes", [
349
672
  Object,
350
673
  Object,
351
674
  Object,
@@ -354,23 +677,23 @@ MediaConsoleService = _ts_decorate([
354
677
  ], MediaConsoleService);
355
678
 
356
679
  // src/server/media-console-actions.controller.ts
357
- function _ts_decorate2(decorators, target, key, desc) {
680
+ function _ts_decorate3(decorators, target, key, desc) {
358
681
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
359
682
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
360
683
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
361
684
  return c > 3 && r && Object.defineProperty(target, key, r), r;
362
685
  }
363
- __name(_ts_decorate2, "_ts_decorate");
364
- function _ts_metadata2(k, v) {
686
+ __name(_ts_decorate3, "_ts_decorate");
687
+ function _ts_metadata3(k, v) {
365
688
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
366
689
  }
367
- __name(_ts_metadata2, "_ts_metadata");
368
- function _ts_param2(paramIndex, decorator) {
690
+ __name(_ts_metadata3, "_ts_metadata");
691
+ function _ts_param3(paramIndex, decorator) {
369
692
  return function(target, key) {
370
693
  decorator(target, key, paramIndex);
371
694
  };
372
695
  }
373
- __name(_ts_param2, "_ts_param");
696
+ __name(_ts_param3, "_ts_param");
374
697
  var MediaConsoleActionsController = class {
375
698
  static {
376
699
  __name(this, "MediaConsoleActionsController");
@@ -406,118 +729,303 @@ var MediaConsoleActionsController = class {
406
729
  return this.service.deleteLibraryRecord(id);
407
730
  }
408
731
  };
409
- _ts_decorate2([
410
- (0, import_common2.Delete)("disks/:disk/object"),
411
- (0, import_common2.HttpCode)(204),
412
- _ts_param2(0, (0, import_common2.Param)("disk")),
413
- _ts_param2(1, (0, import_common2.Query)("key")),
414
- _ts_metadata2("design:type", Function),
415
- _ts_metadata2("design:paramtypes", [
732
+ _ts_decorate3([
733
+ (0, import_common3.Delete)("disks/:disk/object"),
734
+ (0, import_common3.HttpCode)(204),
735
+ _ts_param3(0, (0, import_common3.Param)("disk")),
736
+ _ts_param3(1, (0, import_common3.Query)("key")),
737
+ _ts_metadata3("design:type", Function),
738
+ _ts_metadata3("design:paramtypes", [
416
739
  String,
417
740
  String
418
741
  ]),
419
- _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
742
+ _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
420
743
  ], MediaConsoleActionsController.prototype, "deleteObject", null);
421
- _ts_decorate2([
422
- (0, import_common2.Post)("disks/:disk/copy"),
423
- (0, import_common2.HttpCode)(204),
424
- _ts_param2(0, (0, import_common2.Param)("disk")),
425
- _ts_param2(1, (0, import_common2.Body)()),
426
- _ts_metadata2("design:type", Function),
427
- _ts_metadata2("design:paramtypes", [
744
+ _ts_decorate3([
745
+ (0, import_common3.Post)("disks/:disk/copy"),
746
+ (0, import_common3.HttpCode)(204),
747
+ _ts_param3(0, (0, import_common3.Param)("disk")),
748
+ _ts_param3(1, (0, import_common3.Body)()),
749
+ _ts_metadata3("design:type", Function),
750
+ _ts_metadata3("design:paramtypes", [
428
751
  String,
429
752
  typeof CopyMoveBody === "undefined" ? Object : CopyMoveBody
430
753
  ]),
431
- _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
754
+ _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
432
755
  ], MediaConsoleActionsController.prototype, "copyObject", null);
433
- _ts_decorate2([
434
- (0, import_common2.Post)("disks/:disk/move"),
435
- (0, import_common2.HttpCode)(204),
436
- _ts_param2(0, (0, import_common2.Param)("disk")),
437
- _ts_param2(1, (0, import_common2.Body)()),
438
- _ts_metadata2("design:type", Function),
439
- _ts_metadata2("design:paramtypes", [
756
+ _ts_decorate3([
757
+ (0, import_common3.Post)("disks/:disk/move"),
758
+ (0, import_common3.HttpCode)(204),
759
+ _ts_param3(0, (0, import_common3.Param)("disk")),
760
+ _ts_param3(1, (0, import_common3.Body)()),
761
+ _ts_metadata3("design:type", Function),
762
+ _ts_metadata3("design:paramtypes", [
440
763
  String,
441
764
  typeof CopyMoveBody === "undefined" ? Object : CopyMoveBody
442
765
  ]),
443
- _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
766
+ _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
444
767
  ], MediaConsoleActionsController.prototype, "moveObject", null);
445
- _ts_decorate2([
446
- (0, import_common2.Post)("disks/:disk/upload"),
447
- (0, import_common2.HttpCode)(204),
448
- _ts_param2(0, (0, import_common2.Param)("disk")),
449
- _ts_param2(1, (0, import_common2.Query)("key")),
450
- _ts_param2(2, (0, import_common2.Req)()),
451
- _ts_param2(3, (0, import_common2.Query)("type")),
452
- _ts_metadata2("design:type", Function),
453
- _ts_metadata2("design:paramtypes", [
768
+ _ts_decorate3([
769
+ (0, import_common3.Post)("disks/:disk/upload"),
770
+ (0, import_common3.HttpCode)(204),
771
+ _ts_param3(0, (0, import_common3.Param)("disk")),
772
+ _ts_param3(1, (0, import_common3.Query)("key")),
773
+ _ts_param3(2, (0, import_common3.Req)()),
774
+ _ts_param3(3, (0, import_common3.Query)("type")),
775
+ _ts_metadata3("design:type", Function),
776
+ _ts_metadata3("design:paramtypes", [
454
777
  String,
455
778
  String,
456
779
  typeof Readable === "undefined" ? Object : Readable,
457
780
  String
458
781
  ]),
459
- _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
782
+ _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
460
783
  ], MediaConsoleActionsController.prototype, "uploadObject", null);
461
- _ts_decorate2([
462
- (0, import_common2.Post)("disks/:disk/folder"),
463
- (0, import_common2.HttpCode)(204),
464
- _ts_param2(0, (0, import_common2.Param)("disk")),
465
- _ts_param2(1, (0, import_common2.Body)()),
466
- _ts_metadata2("design:type", Function),
467
- _ts_metadata2("design:paramtypes", [
784
+ _ts_decorate3([
785
+ (0, import_common3.Post)("disks/:disk/folder"),
786
+ (0, import_common3.HttpCode)(204),
787
+ _ts_param3(0, (0, import_common3.Param)("disk")),
788
+ _ts_param3(1, (0, import_common3.Body)()),
789
+ _ts_metadata3("design:type", Function),
790
+ _ts_metadata3("design:paramtypes", [
468
791
  String,
469
792
  typeof CreateFolderBody === "undefined" ? Object : CreateFolderBody
470
793
  ]),
471
- _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
794
+ _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
472
795
  ], MediaConsoleActionsController.prototype, "createFolder", null);
473
- _ts_decorate2([
474
- (0, import_common2.Post)("uploads/:id/abort"),
475
- (0, import_common2.HttpCode)(204),
476
- _ts_param2(0, (0, import_common2.Param)("id")),
477
- _ts_metadata2("design:type", Function),
478
- _ts_metadata2("design:paramtypes", [
796
+ _ts_decorate3([
797
+ (0, import_common3.Post)("uploads/:id/abort"),
798
+ (0, import_common3.HttpCode)(204),
799
+ _ts_param3(0, (0, import_common3.Param)("id")),
800
+ _ts_metadata3("design:type", Function),
801
+ _ts_metadata3("design:paramtypes", [
479
802
  String
480
803
  ]),
481
- _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
804
+ _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
482
805
  ], MediaConsoleActionsController.prototype, "abortUpload", null);
483
- _ts_decorate2([
484
- (0, import_common2.Delete)("library/:id"),
485
- (0, import_common2.HttpCode)(204),
486
- _ts_param2(0, (0, import_common2.Param)("id")),
487
- _ts_metadata2("design:type", Function),
488
- _ts_metadata2("design:paramtypes", [
806
+ _ts_decorate3([
807
+ (0, import_common3.Delete)("library/:id"),
808
+ (0, import_common3.HttpCode)(204),
809
+ _ts_param3(0, (0, import_common3.Param)("id")),
810
+ _ts_metadata3("design:type", Function),
811
+ _ts_metadata3("design:paramtypes", [
489
812
  String
490
813
  ]),
491
- _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
814
+ _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
492
815
  ], MediaConsoleActionsController.prototype, "deleteLibraryRecord", null);
493
- MediaConsoleActionsController = _ts_decorate2([
494
- (0, import_common2.Controller)(),
495
- _ts_param2(0, (0, import_common2.Inject)(MediaConsoleService)),
496
- _ts_metadata2("design:type", Function),
497
- _ts_metadata2("design:paramtypes", [
816
+ MediaConsoleActionsController = _ts_decorate3([
817
+ (0, import_common3.UseGuards)(MediaConsoleGuard),
818
+ (0, import_common3.Controller)(),
819
+ _ts_param3(0, (0, import_common3.Inject)(MediaConsoleService)),
820
+ _ts_metadata3("design:type", Function),
821
+ _ts_metadata3("design:paramtypes", [
498
822
  typeof MediaConsoleService === "undefined" ? Object : MediaConsoleService
499
823
  ])
500
824
  ], MediaConsoleActionsController);
501
825
 
826
+ // src/server/media-console-auth.controller.ts
827
+ var import_common4 = require("@nestjs/common");
828
+ function _ts_decorate4(decorators, target, key, desc) {
829
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
830
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
831
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
832
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
833
+ }
834
+ __name(_ts_decorate4, "_ts_decorate");
835
+ function _ts_metadata4(k, v) {
836
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
837
+ }
838
+ __name(_ts_metadata4, "_ts_metadata");
839
+ function _ts_param4(paramIndex, decorator) {
840
+ return function(target, key) {
841
+ decorator(target, key, paramIndex);
842
+ };
843
+ }
844
+ __name(_ts_param4, "_ts_param");
845
+ var MediaConsoleAuthController = class _MediaConsoleAuthController {
846
+ static {
847
+ __name(this, "MediaConsoleAuthController");
848
+ }
849
+ auth;
850
+ cookiePath;
851
+ logger = new import_common4.Logger(_MediaConsoleAuthController.name);
852
+ /** One warn per hook kind, so a flaky hook doesn't spam logs every request. */
853
+ warnedHooks = /* @__PURE__ */ new Set();
854
+ constructor(auth, cookiePath) {
855
+ this.auth = auth;
856
+ this.cookiePath = cookiePath;
857
+ }
858
+ me(request) {
859
+ if (!this.auth) return {
860
+ authRequired: false
861
+ };
862
+ const cookieValue = parseCookieHeader(readCookieHeader(request))[SESSION_COOKIE_NAME];
863
+ const session = cookieValue !== void 0 ? verifySessionCookie(cookieValue, {
864
+ secret: this.auth.secret
865
+ }) : null;
866
+ if (!session) throw new import_common4.UnauthorizedException({
867
+ auth: {
868
+ modes: this.auth.modes
869
+ }
870
+ });
871
+ return {
872
+ user: {
873
+ id: session.sub,
874
+ ...session.name !== void 0 ? {
875
+ name: session.name
876
+ } : {},
877
+ roles: session.roles
878
+ }
879
+ };
880
+ }
881
+ async login(body, request, response) {
882
+ const auth = this.requireAuth();
883
+ if (!auth.login) throw new import_common4.NotFoundException();
884
+ if (typeof body?.username !== "string" || typeof body?.password !== "string") {
885
+ throw new import_common4.BadRequestException("Body must include string `username` and `password`.");
886
+ }
887
+ const username = body.username;
888
+ const password = body.password;
889
+ const user = await this.runHook("login", () => auth.login?.(username, password) ?? null);
890
+ if (!user) throw new import_common4.UnauthorizedException({
891
+ message: "Invalid credentials"
892
+ });
893
+ return this.mint(user, request, response);
894
+ }
895
+ async session(request, response) {
896
+ const auth = this.requireAuth();
897
+ if (!auth.session) throw new import_common4.NotFoundException();
898
+ const user = await this.runHook("session", () => auth.session?.(request) ?? null);
899
+ if (!user) throw new import_common4.UnauthorizedException();
900
+ return this.mint(user, request, response);
901
+ }
902
+ logout(request, response) {
903
+ clearSessionCookie({
904
+ cookiePath: this.cookiePath ?? "/",
905
+ request,
906
+ response
907
+ });
908
+ }
909
+ requireAuth() {
910
+ if (!this.auth) throw new import_common4.NotFoundException();
911
+ return this.auth;
912
+ }
913
+ mint(user, request, response) {
914
+ const auth = this.requireAuth();
915
+ issueSessionCookie(user, {
916
+ auth,
917
+ cookiePath: this.cookiePath ?? "/",
918
+ request,
919
+ response
920
+ });
921
+ return {
922
+ user: {
923
+ id: user.id,
924
+ ...user.name !== void 0 ? {
925
+ name: user.name
926
+ } : {},
927
+ roles: user.roles ?? []
928
+ }
929
+ };
930
+ }
931
+ /** Run a host hook defensively: a throw is a denial (null), warn-logged once per kind. */
932
+ async runHook(kind, run) {
933
+ try {
934
+ return await run() ?? null;
935
+ } catch (error) {
936
+ if (!this.warnedHooks.has(kind)) {
937
+ this.warnedHooks.add(kind);
938
+ this.logger.warn(`Console auth ${kind} hook threw; treating as denial. ${String(error)}`);
939
+ }
940
+ return null;
941
+ }
942
+ }
943
+ };
944
+ _ts_decorate4([
945
+ (0, import_common4.Get)("me"),
946
+ _ts_param4(0, (0, import_common4.Req)()),
947
+ _ts_metadata4("design:type", Function),
948
+ _ts_metadata4("design:paramtypes", [
949
+ Object
950
+ ]),
951
+ _ts_metadata4("design:returntype", typeof MeResponse === "undefined" ? Object : MeResponse)
952
+ ], MediaConsoleAuthController.prototype, "me", null);
953
+ _ts_decorate4([
954
+ (0, import_common4.Post)("login"),
955
+ (0, import_common4.HttpCode)(200),
956
+ _ts_param4(0, (0, import_common4.Body)()),
957
+ _ts_param4(1, (0, import_common4.Req)()),
958
+ _ts_param4(2, (0, import_common4.Res)({
959
+ passthrough: true
960
+ })),
961
+ _ts_metadata4("design:type", Function),
962
+ _ts_metadata4("design:paramtypes", [
963
+ typeof LoginBody === "undefined" ? Object : LoginBody,
964
+ Object,
965
+ Object
966
+ ]),
967
+ _ts_metadata4("design:returntype", Promise)
968
+ ], MediaConsoleAuthController.prototype, "login", null);
969
+ _ts_decorate4([
970
+ (0, import_common4.Post)("session"),
971
+ (0, import_common4.HttpCode)(200),
972
+ _ts_param4(0, (0, import_common4.Req)()),
973
+ _ts_param4(1, (0, import_common4.Res)({
974
+ passthrough: true
975
+ })),
976
+ _ts_metadata4("design:type", Function),
977
+ _ts_metadata4("design:paramtypes", [
978
+ Object,
979
+ Object
980
+ ]),
981
+ _ts_metadata4("design:returntype", Promise)
982
+ ], MediaConsoleAuthController.prototype, "session", null);
983
+ _ts_decorate4([
984
+ (0, import_common4.Post)("logout"),
985
+ (0, import_common4.HttpCode)(204),
986
+ _ts_param4(0, (0, import_common4.Req)()),
987
+ _ts_param4(1, (0, import_common4.Res)({
988
+ passthrough: true
989
+ })),
990
+ _ts_metadata4("design:type", Function),
991
+ _ts_metadata4("design:paramtypes", [
992
+ Object,
993
+ Object
994
+ ]),
995
+ _ts_metadata4("design:returntype", void 0)
996
+ ], MediaConsoleAuthController.prototype, "logout", null);
997
+ MediaConsoleAuthController = _ts_decorate4([
998
+ (0, import_common4.Controller)(),
999
+ _ts_param4(0, (0, import_common4.Optional)()),
1000
+ _ts_param4(0, (0, import_common4.Inject)(MEDIA_CONSOLE_AUTH)),
1001
+ _ts_param4(1, (0, import_common4.Optional)()),
1002
+ _ts_param4(1, (0, import_common4.Inject)(MEDIA_CONSOLE_COOKIE_PATH)),
1003
+ _ts_metadata4("design:type", Function),
1004
+ _ts_metadata4("design:paramtypes", [
1005
+ Object,
1006
+ Object
1007
+ ])
1008
+ ], MediaConsoleAuthController);
1009
+
502
1010
  // src/server/media-console-read.controller.ts
503
- var import_common3 = require("@nestjs/common");
504
- function _ts_decorate3(decorators, target, key, desc) {
1011
+ var import_common5 = require("@nestjs/common");
1012
+ function _ts_decorate5(decorators, target, key, desc) {
505
1013
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
506
1014
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
507
1015
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
508
1016
  return c > 3 && r && Object.defineProperty(target, key, r), r;
509
1017
  }
510
- __name(_ts_decorate3, "_ts_decorate");
511
- function _ts_metadata3(k, v) {
1018
+ __name(_ts_decorate5, "_ts_decorate");
1019
+ function _ts_metadata5(k, v) {
512
1020
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
513
1021
  }
514
- __name(_ts_metadata3, "_ts_metadata");
515
- function _ts_param3(paramIndex, decorator) {
1022
+ __name(_ts_metadata5, "_ts_metadata");
1023
+ function _ts_param5(paramIndex, decorator) {
516
1024
  return function(target, key) {
517
1025
  decorator(target, key, paramIndex);
518
1026
  };
519
1027
  }
520
- __name(_ts_param3, "_ts_param");
1028
+ __name(_ts_param5, "_ts_param");
521
1029
  function toLimit(value) {
522
1030
  if (value === void 0) return void 0;
523
1031
  const parsed = Number(value);
@@ -556,7 +1064,7 @@ var MediaConsoleReadController = class {
556
1064
  * can render text/PDF previews the browser would otherwise download, and read text past CORS. */
557
1065
  async objectRaw(disk, key) {
558
1066
  const { stream, contentType, size } = await this.service.objectStream(disk, key);
559
- return new import_common3.StreamableFile(stream, {
1067
+ return new import_common5.StreamableFile(stream, {
560
1068
  type: contentType,
561
1069
  disposition: "inline",
562
1070
  ...Number.isFinite(size) ? {
@@ -604,141 +1112,150 @@ var MediaConsoleReadController = class {
604
1112
  return this.service.topology();
605
1113
  }
606
1114
  };
607
- _ts_decorate3([
608
- (0, import_common3.Get)("disks"),
609
- _ts_metadata3("design:type", Function),
610
- _ts_metadata3("design:paramtypes", []),
611
- _ts_metadata3("design:returntype", typeof DiskListResponse === "undefined" ? Object : DiskListResponse)
1115
+ _ts_decorate5([
1116
+ (0, import_common5.Get)("disks"),
1117
+ _ts_metadata5("design:type", Function),
1118
+ _ts_metadata5("design:paramtypes", []),
1119
+ _ts_metadata5("design:returntype", typeof DiskListResponse === "undefined" ? Object : DiskListResponse)
612
1120
  ], MediaConsoleReadController.prototype, "disks", null);
613
- _ts_decorate3([
614
- (0, import_common3.Get)("disks/:disk/objects"),
615
- _ts_param3(0, (0, import_common3.Param)("disk")),
616
- _ts_param3(1, (0, import_common3.Query)("prefix")),
617
- _ts_param3(2, (0, import_common3.Query)("cursor")),
618
- _ts_param3(3, (0, import_common3.Query)("limit")),
619
- _ts_metadata3("design:type", Function),
620
- _ts_metadata3("design:paramtypes", [
1121
+ _ts_decorate5([
1122
+ (0, import_common5.Get)("disks/:disk/objects"),
1123
+ _ts_param5(0, (0, import_common5.Param)("disk")),
1124
+ _ts_param5(1, (0, import_common5.Query)("prefix")),
1125
+ _ts_param5(2, (0, import_common5.Query)("cursor")),
1126
+ _ts_param5(3, (0, import_common5.Query)("limit")),
1127
+ _ts_metadata5("design:type", Function),
1128
+ _ts_metadata5("design:paramtypes", [
621
1129
  String,
622
1130
  String,
623
1131
  String,
624
1132
  String
625
1133
  ]),
626
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1134
+ _ts_metadata5("design:returntype", typeof Promise === "undefined" ? Object : Promise)
627
1135
  ], MediaConsoleReadController.prototype, "objects", null);
628
- _ts_decorate3([
629
- (0, import_common3.Get)("disks/:disk/object"),
630
- _ts_param3(0, (0, import_common3.Param)("disk")),
631
- _ts_param3(1, (0, import_common3.Query)("key")),
632
- _ts_metadata3("design:type", Function),
633
- _ts_metadata3("design:paramtypes", [
1136
+ _ts_decorate5([
1137
+ (0, import_common5.Get)("disks/:disk/object"),
1138
+ _ts_param5(0, (0, import_common5.Param)("disk")),
1139
+ _ts_param5(1, (0, import_common5.Query)("key")),
1140
+ _ts_metadata5("design:type", Function),
1141
+ _ts_metadata5("design:paramtypes", [
634
1142
  String,
635
1143
  String
636
1144
  ]),
637
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1145
+ _ts_metadata5("design:returntype", typeof Promise === "undefined" ? Object : Promise)
638
1146
  ], MediaConsoleReadController.prototype, "object", null);
639
- _ts_decorate3([
640
- (0, import_common3.Get)("disks/:disk/object/raw"),
641
- _ts_param3(0, (0, import_common3.Param)("disk")),
642
- _ts_param3(1, (0, import_common3.Query)("key")),
643
- _ts_metadata3("design:type", Function),
644
- _ts_metadata3("design:paramtypes", [
1147
+ _ts_decorate5([
1148
+ (0, import_common5.Get)("disks/:disk/object/raw"),
1149
+ _ts_param5(0, (0, import_common5.Param)("disk")),
1150
+ _ts_param5(1, (0, import_common5.Query)("key")),
1151
+ _ts_metadata5("design:type", Function),
1152
+ _ts_metadata5("design:paramtypes", [
645
1153
  String,
646
1154
  String
647
1155
  ]),
648
- _ts_metadata3("design:returntype", Promise)
1156
+ _ts_metadata5("design:returntype", Promise)
649
1157
  ], MediaConsoleReadController.prototype, "objectRaw", null);
650
- _ts_decorate3([
651
- (0, import_common3.Get)("uploads"),
652
- _ts_param3(0, (0, import_common3.Query)("disk")),
653
- _ts_param3(1, (0, import_common3.Query)("prefix")),
654
- _ts_metadata3("design:type", Function),
655
- _ts_metadata3("design:paramtypes", [
1158
+ _ts_decorate5([
1159
+ (0, import_common5.Get)("uploads"),
1160
+ _ts_param5(0, (0, import_common5.Query)("disk")),
1161
+ _ts_param5(1, (0, import_common5.Query)("prefix")),
1162
+ _ts_metadata5("design:type", Function),
1163
+ _ts_metadata5("design:paramtypes", [
656
1164
  String,
657
1165
  String
658
1166
  ]),
659
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1167
+ _ts_metadata5("design:returntype", typeof Promise === "undefined" ? Object : Promise)
660
1168
  ], MediaConsoleReadController.prototype, "uploads", null);
661
- _ts_decorate3([
662
- (0, import_common3.Get)("uploads/:id"),
663
- _ts_param3(0, (0, import_common3.Param)("id")),
664
- _ts_metadata3("design:type", Function),
665
- _ts_metadata3("design:paramtypes", [
1169
+ _ts_decorate5([
1170
+ (0, import_common5.Get)("uploads/:id"),
1171
+ _ts_param5(0, (0, import_common5.Param)("id")),
1172
+ _ts_metadata5("design:type", Function),
1173
+ _ts_metadata5("design:paramtypes", [
666
1174
  String
667
1175
  ]),
668
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1176
+ _ts_metadata5("design:returntype", typeof Promise === "undefined" ? Object : Promise)
669
1177
  ], MediaConsoleReadController.prototype, "upload", null);
670
- _ts_decorate3([
671
- (0, import_common3.Get)("library/collections"),
672
- _ts_metadata3("design:type", Function),
673
- _ts_metadata3("design:paramtypes", []),
674
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1178
+ _ts_decorate5([
1179
+ (0, import_common5.Get)("library/collections"),
1180
+ _ts_metadata5("design:type", Function),
1181
+ _ts_metadata5("design:paramtypes", []),
1182
+ _ts_metadata5("design:returntype", typeof Promise === "undefined" ? Object : Promise)
675
1183
  ], MediaConsoleReadController.prototype, "collections", null);
676
- _ts_decorate3([
677
- (0, import_common3.Get)("library"),
678
- _ts_param3(0, (0, import_common3.Query)("collection")),
679
- _ts_param3(1, (0, import_common3.Query)("disk")),
680
- _ts_param3(2, (0, import_common3.Query)("cursor")),
681
- _ts_param3(3, (0, import_common3.Query)("limit")),
682
- _ts_metadata3("design:type", Function),
683
- _ts_metadata3("design:paramtypes", [
1184
+ _ts_decorate5([
1185
+ (0, import_common5.Get)("library"),
1186
+ _ts_param5(0, (0, import_common5.Query)("collection")),
1187
+ _ts_param5(1, (0, import_common5.Query)("disk")),
1188
+ _ts_param5(2, (0, import_common5.Query)("cursor")),
1189
+ _ts_param5(3, (0, import_common5.Query)("limit")),
1190
+ _ts_metadata5("design:type", Function),
1191
+ _ts_metadata5("design:paramtypes", [
684
1192
  String,
685
1193
  String,
686
1194
  String,
687
1195
  String
688
1196
  ]),
689
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1197
+ _ts_metadata5("design:returntype", typeof Promise === "undefined" ? Object : Promise)
690
1198
  ], MediaConsoleReadController.prototype, "library", null);
691
- _ts_decorate3([
692
- (0, import_common3.Get)("library/:id"),
693
- _ts_param3(0, (0, import_common3.Param)("id")),
694
- _ts_metadata3("design:type", Function),
695
- _ts_metadata3("design:paramtypes", [
1199
+ _ts_decorate5([
1200
+ (0, import_common5.Get)("library/:id"),
1201
+ _ts_param5(0, (0, import_common5.Param)("id")),
1202
+ _ts_metadata5("design:type", Function),
1203
+ _ts_metadata5("design:paramtypes", [
696
1204
  String
697
1205
  ]),
698
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1206
+ _ts_metadata5("design:returntype", typeof Promise === "undefined" ? Object : Promise)
699
1207
  ], MediaConsoleReadController.prototype, "libraryRecord", null);
700
- _ts_decorate3([
701
- (0, import_common3.Get)("topology"),
702
- _ts_metadata3("design:type", Function),
703
- _ts_metadata3("design:paramtypes", []),
704
- _ts_metadata3("design:returntype", typeof Topology === "undefined" ? Object : Topology)
1208
+ _ts_decorate5([
1209
+ (0, import_common5.Get)("topology"),
1210
+ _ts_metadata5("design:type", Function),
1211
+ _ts_metadata5("design:paramtypes", []),
1212
+ _ts_metadata5("design:returntype", typeof Topology === "undefined" ? Object : Topology)
705
1213
  ], MediaConsoleReadController.prototype, "topology", null);
706
- MediaConsoleReadController = _ts_decorate3([
707
- (0, import_common3.Controller)(),
708
- _ts_param3(0, (0, import_common3.Inject)(MediaConsoleService)),
709
- _ts_metadata3("design:type", Function),
710
- _ts_metadata3("design:paramtypes", [
1214
+ MediaConsoleReadController = _ts_decorate5([
1215
+ (0, import_common5.UseGuards)(MediaConsoleGuard),
1216
+ (0, import_common5.Controller)(),
1217
+ _ts_param5(0, (0, import_common5.Inject)(MediaConsoleService)),
1218
+ _ts_metadata5("design:type", Function),
1219
+ _ts_metadata5("design:paramtypes", [
711
1220
  typeof MediaConsoleService === "undefined" ? Object : MediaConsoleService
712
1221
  ])
713
1222
  ], MediaConsoleReadController);
714
1223
 
715
1224
  // src/server/media-console-api.module.ts
716
- function _ts_decorate4(decorators, target, key, desc) {
1225
+ function _ts_decorate6(decorators, target, key, desc) {
717
1226
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
718
1227
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
719
1228
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
720
1229
  return c > 3 && r && Object.defineProperty(target, key, r), r;
721
1230
  }
722
- __name(_ts_decorate4, "_ts_decorate");
1231
+ __name(_ts_decorate6, "_ts_decorate");
723
1232
  var MediaConsoleApiModule = class _MediaConsoleApiModule {
724
1233
  static {
725
1234
  __name(this, "MediaConsoleApiModule");
726
1235
  }
727
- static register(actions) {
1236
+ static register(options) {
728
1237
  return {
729
1238
  module: _MediaConsoleApiModule,
730
- controllers: actions ? [
1239
+ imports: options.imports ?? [],
1240
+ controllers: [
731
1241
  MediaConsoleReadController,
732
- MediaConsoleActionsController
733
- ] : [
734
- MediaConsoleReadController
1242
+ MediaConsoleAuthController,
1243
+ ...options.actions ? [
1244
+ MediaConsoleActionsController
1245
+ ] : []
735
1246
  ],
736
1247
  providers: [
737
1248
  MediaConsoleService,
1249
+ MediaConsoleGuard,
738
1250
  {
739
1251
  provide: MEDIA_DASHBOARD_ACTIONS,
740
- useValue: actions
741
- }
1252
+ useValue: options.actions
1253
+ },
1254
+ {
1255
+ provide: MEDIA_CONSOLE_COOKIE_PATH,
1256
+ useValue: options.cookiePath
1257
+ },
1258
+ options.authProvider
742
1259
  ],
743
1260
  exports: [
744
1261
  MediaConsoleService
@@ -746,32 +1263,32 @@ var MediaConsoleApiModule = class _MediaConsoleApiModule {
746
1263
  };
747
1264
  }
748
1265
  };
749
- MediaConsoleApiModule = _ts_decorate4([
750
- (0, import_common4.Module)({})
1266
+ MediaConsoleApiModule = _ts_decorate6([
1267
+ (0, import_common6.Module)({})
751
1268
  ], MediaConsoleApiModule);
752
1269
 
753
1270
  // src/server/media-dashboard-ui.controller.ts
754
1271
  var import_node_fs = require("fs");
755
1272
  var import_node_path = require("path");
756
1273
  var import_node_url = require("url");
757
- var import_common5 = require("@nestjs/common");
758
- function _ts_decorate5(decorators, target, key, desc) {
1274
+ var import_common7 = require("@nestjs/common");
1275
+ function _ts_decorate7(decorators, target, key, desc) {
759
1276
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
760
1277
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
761
1278
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
762
1279
  return c > 3 && r && Object.defineProperty(target, key, r), r;
763
1280
  }
764
- __name(_ts_decorate5, "_ts_decorate");
765
- function _ts_metadata4(k, v) {
1281
+ __name(_ts_decorate7, "_ts_decorate");
1282
+ function _ts_metadata6(k, v) {
766
1283
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
767
1284
  }
768
- __name(_ts_metadata4, "_ts_metadata");
769
- function _ts_param4(paramIndex, decorator) {
1285
+ __name(_ts_metadata6, "_ts_metadata");
1286
+ function _ts_param6(paramIndex, decorator) {
770
1287
  return function(target, key) {
771
1288
  decorator(target, key, paramIndex);
772
1289
  };
773
1290
  }
774
- __name(_ts_param4, "_ts_param");
1291
+ __name(_ts_param6, "_ts_param");
775
1292
  var BUILD_BASE = "/media";
776
1293
  function spaDir() {
777
1294
  return (0, import_node_url.fileURLToPath)(new URL("../spa", importMetaUrl));
@@ -802,7 +1319,7 @@ var MediaDashboardUiController = class {
802
1319
  index() {
803
1320
  const indexPath = (0, import_node_path.join)(this.dir, "index.html");
804
1321
  if (!(0, import_node_fs.existsSync)(indexPath)) {
805
- throw new import_common5.NotFoundException("Console SPA is not built. Run the package build.");
1322
+ throw new import_common7.NotFoundException("Console SPA is not built. Run the package build.");
806
1323
  }
807
1324
  const html = (0, import_node_fs.readFileSync)(indexPath, "utf8").replaceAll(`="${BUILD_BASE}/`, `="${this.basePath}/`);
808
1325
  const inject = `<script>window.__MEDIA_BASE__='${this.basePath}';window.__MEDIA_API__='${this.apiBasePath}';</script>`;
@@ -810,55 +1327,55 @@ var MediaDashboardUiController = class {
810
1327
  }
811
1328
  asset(file) {
812
1329
  const safe = (0, import_node_path.basename)(file);
813
- if (safe !== file) throw new import_common5.NotFoundException();
1330
+ if (safe !== file) throw new import_common7.NotFoundException();
814
1331
  const root = (0, import_node_path.resolve)(this.dir, "assets");
815
1332
  const assetPath = (0, import_node_path.resolve)(root, safe);
816
1333
  if (!assetPath.startsWith(root + import_node_path.sep) || !(0, import_node_fs.existsSync)(assetPath)) {
817
- throw new import_common5.NotFoundException();
1334
+ throw new import_common7.NotFoundException();
818
1335
  }
819
1336
  const type = CONTENT_TYPES[(0, import_node_path.extname)(safe)] ?? "application/octet-stream";
820
- return new import_common5.StreamableFile((0, import_node_fs.readFileSync)(assetPath), {
1337
+ return new import_common7.StreamableFile((0, import_node_fs.readFileSync)(assetPath), {
821
1338
  type
822
1339
  });
823
1340
  }
824
1341
  };
825
- _ts_decorate5([
826
- (0, import_common5.Get)(),
827
- (0, import_common5.Header)("Content-Type", "text/html; charset=utf-8"),
828
- (0, import_common5.Header)("Cache-Control", "no-store, must-revalidate"),
829
- _ts_metadata4("design:type", Function),
830
- _ts_metadata4("design:paramtypes", []),
831
- _ts_metadata4("design:returntype", String)
1342
+ _ts_decorate7([
1343
+ (0, import_common7.Get)(),
1344
+ (0, import_common7.Header)("Content-Type", "text/html; charset=utf-8"),
1345
+ (0, import_common7.Header)("Cache-Control", "no-store, must-revalidate"),
1346
+ _ts_metadata6("design:type", Function),
1347
+ _ts_metadata6("design:paramtypes", []),
1348
+ _ts_metadata6("design:returntype", String)
832
1349
  ], MediaDashboardUiController.prototype, "index", null);
833
- _ts_decorate5([
834
- (0, import_common5.Get)("assets/:file"),
835
- (0, import_common5.Header)("Cache-Control", "public, max-age=31536000, immutable"),
836
- _ts_param4(0, (0, import_common5.Param)("file")),
837
- _ts_metadata4("design:type", Function),
838
- _ts_metadata4("design:paramtypes", [
1350
+ _ts_decorate7([
1351
+ (0, import_common7.Get)("assets/:file"),
1352
+ (0, import_common7.Header)("Cache-Control", "public, max-age=31536000, immutable"),
1353
+ _ts_param6(0, (0, import_common7.Param)("file")),
1354
+ _ts_metadata6("design:type", Function),
1355
+ _ts_metadata6("design:paramtypes", [
839
1356
  String
840
1357
  ]),
841
- _ts_metadata4("design:returntype", typeof import_common5.StreamableFile === "undefined" ? Object : import_common5.StreamableFile)
1358
+ _ts_metadata6("design:returntype", typeof import_common7.StreamableFile === "undefined" ? Object : import_common7.StreamableFile)
842
1359
  ], MediaDashboardUiController.prototype, "asset", null);
843
- MediaDashboardUiController = _ts_decorate5([
844
- (0, import_common5.Controller)(),
845
- _ts_param4(0, (0, import_common5.Inject)(MEDIA_DASHBOARD_BASE_PATH)),
846
- _ts_param4(1, (0, import_common5.Inject)(MEDIA_DASHBOARD_API_PATH)),
847
- _ts_metadata4("design:type", Function),
848
- _ts_metadata4("design:paramtypes", [
1360
+ MediaDashboardUiController = _ts_decorate7([
1361
+ (0, import_common7.Controller)(),
1362
+ _ts_param6(0, (0, import_common7.Inject)(MEDIA_DASHBOARD_BASE_PATH)),
1363
+ _ts_param6(1, (0, import_common7.Inject)(MEDIA_DASHBOARD_API_PATH)),
1364
+ _ts_metadata6("design:type", Function),
1365
+ _ts_metadata6("design:paramtypes", [
849
1366
  String,
850
1367
  String
851
1368
  ])
852
1369
  ], MediaDashboardUiController);
853
1370
 
854
1371
  // src/server/media-dashboard.module.ts
855
- function _ts_decorate6(decorators, target, key, desc) {
1372
+ function _ts_decorate8(decorators, target, key, desc) {
856
1373
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
857
1374
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
858
1375
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
859
1376
  return c > 3 && r && Object.defineProperty(target, key, r), r;
860
1377
  }
861
- __name(_ts_decorate6, "_ts_decorate");
1378
+ __name(_ts_decorate8, "_ts_decorate");
862
1379
  function normalize(path) {
863
1380
  return `/${path.replace(/^\/+|\/+$/g, "")}`;
864
1381
  }
@@ -868,13 +1385,34 @@ var MediaDashboardModule = class _MediaDashboardModule {
868
1385
  __name(this, "MediaDashboardModule");
869
1386
  }
870
1387
  static forRoot(options = {}) {
1388
+ const apiBasePath = normalize(options.apiBasePath ?? `${normalize(options.basePath ?? "/media")}/api`);
1389
+ return _MediaDashboardModule.build(options, apiBasePath, {
1390
+ provide: MEDIA_CONSOLE_AUTH,
1391
+ useValue: resolveConsoleAuth(options.auth)
1392
+ });
1393
+ }
1394
+ static forRootAsync(options) {
1395
+ const apiBasePath = normalize(options.apiBasePath ?? `${normalize(options.basePath ?? "/media")}/api`);
1396
+ const authProvider = {
1397
+ provide: MEDIA_CONSOLE_AUTH,
1398
+ inject: options.inject ?? [],
1399
+ useFactory: /* @__PURE__ */ __name(async (...deps) => resolveConsoleAuth(await options.useAuth(...deps)), "useFactory")
1400
+ };
1401
+ return _MediaDashboardModule.build(options, apiBasePath, authProvider, options.imports);
1402
+ }
1403
+ /** Shared wiring: static routing + the API module, with `auth` supplied by the given provider. */
1404
+ static build(options, apiBasePath, authProvider, imports) {
871
1405
  const basePath = normalize(options.basePath ?? "/media");
872
- const apiBasePath = normalize(options.apiBasePath ?? `${basePath}/api`);
873
1406
  const actions = options.actions === true;
874
1407
  return {
875
1408
  module: _MediaDashboardModule,
876
1409
  imports: [
877
- MediaConsoleApiModule.register(actions),
1410
+ MediaConsoleApiModule.register({
1411
+ actions,
1412
+ cookiePath: apiBasePath,
1413
+ authProvider,
1414
+ imports
1415
+ }),
878
1416
  import_core.RouterModule.register([
879
1417
  {
880
1418
  path: basePath,
@@ -906,8 +1444,8 @@ var MediaDashboardModule = class _MediaDashboardModule {
906
1444
  };
907
1445
  }
908
1446
  };
909
- MediaDashboardModule = _ts_decorate6([
910
- (0, import_common6.Module)({})
1447
+ MediaDashboardModule = _ts_decorate8([
1448
+ (0, import_common8.Module)({})
911
1449
  ], MediaDashboardModule);
912
1450
  // Annotate the CommonJS export names for ESM import in node:
913
1451
  0 && (module.exports = {