@dudousxd/nestjs-media-dashboard 0.1.2 → 0.2.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.
@@ -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
  }
@@ -219,7 +546,7 @@ var MediaConsoleService = class {
219
546
  * as a navigable folder. Normalizes to exactly one trailing slash; rejects an empty prefix. */
220
547
  async createFolder(disk, prefix) {
221
548
  const normalized = prefix.replace(/^\/+/, "").replace(/\/+$/, "");
222
- if (normalized === "") throw new import_common.BadRequestException("Folder name is required");
549
+ if (normalized === "") throw new import_common2.BadRequestException("Folder name is required");
223
550
  await this.diskOrThrow(disk).put(`${normalized}/`, Buffer.alloc(0));
224
551
  }
225
552
  async deleteObject(disk, key) {
@@ -248,9 +575,9 @@ var MediaConsoleService = class {
248
575
  };
249
576
  }
250
577
  async uploadDetail(id) {
251
- if (!this.uploads) throw new import_common.NotFoundException("No upload store configured");
578
+ if (!this.uploads) throw new import_common2.NotFoundException("No upload store configured");
252
579
  const session = await this.uploads.get(id);
253
- if (!session) throw new import_common.NotFoundException(`Unknown upload: ${id}`);
580
+ if (!session) throw new import_common2.NotFoundException(`Unknown upload: ${id}`);
254
581
  const parts = this.uploads.listParts ? await this.uploads.listParts(id) : [];
255
582
  return {
256
583
  upload: mapUpload(session),
@@ -265,7 +592,7 @@ var MediaConsoleService = class {
265
592
  * multipart is reaped by the bucket's lifecycle policy. Surfaced as "Cancel session" in the UI.
266
593
  */
267
594
  async abortUpload(id) {
268
- if (!this.uploads) throw new import_common.NotFoundException("No upload store configured");
595
+ if (!this.uploads) throw new import_common2.NotFoundException("No upload store configured");
269
596
  await this.uploads.delete(id);
270
597
  }
271
598
  async listCollections() {
@@ -305,9 +632,9 @@ var MediaConsoleService = class {
305
632
  };
306
633
  }
307
634
  async libraryDetail(id) {
308
- if (!this.store) throw new import_common.NotFoundException("No media store configured");
635
+ if (!this.store) throw new import_common2.NotFoundException("No media store configured");
309
636
  const record = await this.store.find(id);
310
- if (!record) throw new import_common.NotFoundException(`Unknown media record: ${id}`);
637
+ if (!record) throw new import_common2.NotFoundException(`Unknown media record: ${id}`);
311
638
  const variants = await Promise.all(Object.entries(record.conversions).map(async ([name, conversion]) => {
312
639
  const driver = this.storage?.diskNames().includes(conversion.disk) ? this.storage.disk(conversion.disk) : null;
313
640
  const url = driver?.capabilities.presign ? await driver.temporaryUrl(conversion.path, URL_TTL_SECONDS) : await driver?.url(conversion.path) ?? "";
@@ -322,7 +649,7 @@ var MediaConsoleService = class {
322
649
  };
323
650
  }
324
651
  async deleteLibraryRecord(id) {
325
- if (!this.store) throw new import_common.NotFoundException("No media store configured");
652
+ if (!this.store) throw new import_common2.NotFoundException("No media store configured");
326
653
  await this.store.delete(id);
327
654
  }
328
655
  topology() {
@@ -334,18 +661,18 @@ var MediaConsoleService = class {
334
661
  };
335
662
  }
336
663
  };
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", [
664
+ MediaConsoleService = _ts_decorate2([
665
+ (0, import_common2.Injectable)(),
666
+ _ts_param2(0, (0, import_common2.Optional)()),
667
+ _ts_param2(0, (0, import_common2.Inject)(MEDIA_STORAGE_SHARED)),
668
+ _ts_param2(1, (0, import_common2.Optional)()),
669
+ _ts_param2(1, (0, import_common2.Inject)(MEDIA_STORE)),
670
+ _ts_param2(2, (0, import_common2.Optional)()),
671
+ _ts_param2(2, (0, import_common2.Inject)(MEDIA_UPLOAD_SESSIONS)),
672
+ _ts_param2(3, (0, import_common2.Optional)()),
673
+ _ts_param2(3, (0, import_common2.Inject)(MEDIA_DASHBOARD_ACTIONS)),
674
+ _ts_metadata2("design:type", Function),
675
+ _ts_metadata2("design:paramtypes", [
349
676
  Object,
350
677
  Object,
351
678
  Object,
@@ -354,23 +681,23 @@ MediaConsoleService = _ts_decorate([
354
681
  ], MediaConsoleService);
355
682
 
356
683
  // src/server/media-console-actions.controller.ts
357
- function _ts_decorate2(decorators, target, key, desc) {
684
+ function _ts_decorate3(decorators, target, key, desc) {
358
685
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
359
686
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
360
687
  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
688
  return c > 3 && r && Object.defineProperty(target, key, r), r;
362
689
  }
363
- __name(_ts_decorate2, "_ts_decorate");
364
- function _ts_metadata2(k, v) {
690
+ __name(_ts_decorate3, "_ts_decorate");
691
+ function _ts_metadata3(k, v) {
365
692
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
366
693
  }
367
- __name(_ts_metadata2, "_ts_metadata");
368
- function _ts_param2(paramIndex, decorator) {
694
+ __name(_ts_metadata3, "_ts_metadata");
695
+ function _ts_param3(paramIndex, decorator) {
369
696
  return function(target, key) {
370
697
  decorator(target, key, paramIndex);
371
698
  };
372
699
  }
373
- __name(_ts_param2, "_ts_param");
700
+ __name(_ts_param3, "_ts_param");
374
701
  var MediaConsoleActionsController = class {
375
702
  static {
376
703
  __name(this, "MediaConsoleActionsController");
@@ -406,118 +733,303 @@ var MediaConsoleActionsController = class {
406
733
  return this.service.deleteLibraryRecord(id);
407
734
  }
408
735
  };
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", [
736
+ _ts_decorate3([
737
+ (0, import_common3.Delete)("disks/:disk/object"),
738
+ (0, import_common3.HttpCode)(204),
739
+ _ts_param3(0, (0, import_common3.Param)("disk")),
740
+ _ts_param3(1, (0, import_common3.Query)("key")),
741
+ _ts_metadata3("design:type", Function),
742
+ _ts_metadata3("design:paramtypes", [
416
743
  String,
417
744
  String
418
745
  ]),
419
- _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
746
+ _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
420
747
  ], 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", [
748
+ _ts_decorate3([
749
+ (0, import_common3.Post)("disks/:disk/copy"),
750
+ (0, import_common3.HttpCode)(204),
751
+ _ts_param3(0, (0, import_common3.Param)("disk")),
752
+ _ts_param3(1, (0, import_common3.Body)()),
753
+ _ts_metadata3("design:type", Function),
754
+ _ts_metadata3("design:paramtypes", [
428
755
  String,
429
756
  typeof CopyMoveBody === "undefined" ? Object : CopyMoveBody
430
757
  ]),
431
- _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
758
+ _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
432
759
  ], 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", [
760
+ _ts_decorate3([
761
+ (0, import_common3.Post)("disks/:disk/move"),
762
+ (0, import_common3.HttpCode)(204),
763
+ _ts_param3(0, (0, import_common3.Param)("disk")),
764
+ _ts_param3(1, (0, import_common3.Body)()),
765
+ _ts_metadata3("design:type", Function),
766
+ _ts_metadata3("design:paramtypes", [
440
767
  String,
441
768
  typeof CopyMoveBody === "undefined" ? Object : CopyMoveBody
442
769
  ]),
443
- _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
770
+ _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
444
771
  ], 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", [
772
+ _ts_decorate3([
773
+ (0, import_common3.Post)("disks/:disk/upload"),
774
+ (0, import_common3.HttpCode)(204),
775
+ _ts_param3(0, (0, import_common3.Param)("disk")),
776
+ _ts_param3(1, (0, import_common3.Query)("key")),
777
+ _ts_param3(2, (0, import_common3.Req)()),
778
+ _ts_param3(3, (0, import_common3.Query)("type")),
779
+ _ts_metadata3("design:type", Function),
780
+ _ts_metadata3("design:paramtypes", [
454
781
  String,
455
782
  String,
456
783
  typeof Readable === "undefined" ? Object : Readable,
457
784
  String
458
785
  ]),
459
- _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
786
+ _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
460
787
  ], 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", [
788
+ _ts_decorate3([
789
+ (0, import_common3.Post)("disks/:disk/folder"),
790
+ (0, import_common3.HttpCode)(204),
791
+ _ts_param3(0, (0, import_common3.Param)("disk")),
792
+ _ts_param3(1, (0, import_common3.Body)()),
793
+ _ts_metadata3("design:type", Function),
794
+ _ts_metadata3("design:paramtypes", [
468
795
  String,
469
796
  typeof CreateFolderBody === "undefined" ? Object : CreateFolderBody
470
797
  ]),
471
- _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
798
+ _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
472
799
  ], 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", [
800
+ _ts_decorate3([
801
+ (0, import_common3.Post)("uploads/:id/abort"),
802
+ (0, import_common3.HttpCode)(204),
803
+ _ts_param3(0, (0, import_common3.Param)("id")),
804
+ _ts_metadata3("design:type", Function),
805
+ _ts_metadata3("design:paramtypes", [
479
806
  String
480
807
  ]),
481
- _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
808
+ _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
482
809
  ], 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", [
810
+ _ts_decorate3([
811
+ (0, import_common3.Delete)("library/:id"),
812
+ (0, import_common3.HttpCode)(204),
813
+ _ts_param3(0, (0, import_common3.Param)("id")),
814
+ _ts_metadata3("design:type", Function),
815
+ _ts_metadata3("design:paramtypes", [
489
816
  String
490
817
  ]),
491
- _ts_metadata2("design:returntype", typeof Promise === "undefined" ? Object : Promise)
818
+ _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
492
819
  ], 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", [
820
+ MediaConsoleActionsController = _ts_decorate3([
821
+ (0, import_common3.UseGuards)(MediaConsoleGuard),
822
+ (0, import_common3.Controller)(),
823
+ _ts_param3(0, (0, import_common3.Inject)(MediaConsoleService)),
824
+ _ts_metadata3("design:type", Function),
825
+ _ts_metadata3("design:paramtypes", [
498
826
  typeof MediaConsoleService === "undefined" ? Object : MediaConsoleService
499
827
  ])
500
828
  ], MediaConsoleActionsController);
501
829
 
830
+ // src/server/media-console-auth.controller.ts
831
+ var import_common4 = require("@nestjs/common");
832
+ function _ts_decorate4(decorators, target, key, desc) {
833
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
834
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
835
+ 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;
836
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
837
+ }
838
+ __name(_ts_decorate4, "_ts_decorate");
839
+ function _ts_metadata4(k, v) {
840
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
841
+ }
842
+ __name(_ts_metadata4, "_ts_metadata");
843
+ function _ts_param4(paramIndex, decorator) {
844
+ return function(target, key) {
845
+ decorator(target, key, paramIndex);
846
+ };
847
+ }
848
+ __name(_ts_param4, "_ts_param");
849
+ var MediaConsoleAuthController = class _MediaConsoleAuthController {
850
+ static {
851
+ __name(this, "MediaConsoleAuthController");
852
+ }
853
+ auth;
854
+ cookiePath;
855
+ logger = new import_common4.Logger(_MediaConsoleAuthController.name);
856
+ /** One warn per hook kind, so a flaky hook doesn't spam logs every request. */
857
+ warnedHooks = /* @__PURE__ */ new Set();
858
+ constructor(auth, cookiePath) {
859
+ this.auth = auth;
860
+ this.cookiePath = cookiePath;
861
+ }
862
+ me(request) {
863
+ if (!this.auth) return {
864
+ authRequired: false
865
+ };
866
+ const cookieValue = parseCookieHeader(readCookieHeader(request))[SESSION_COOKIE_NAME];
867
+ const session = cookieValue !== void 0 ? verifySessionCookie(cookieValue, {
868
+ secret: this.auth.secret
869
+ }) : null;
870
+ if (!session) throw new import_common4.UnauthorizedException({
871
+ auth: {
872
+ modes: this.auth.modes
873
+ }
874
+ });
875
+ return {
876
+ user: {
877
+ id: session.sub,
878
+ ...session.name !== void 0 ? {
879
+ name: session.name
880
+ } : {},
881
+ roles: session.roles
882
+ }
883
+ };
884
+ }
885
+ async login(body, request, response) {
886
+ const auth = this.requireAuth();
887
+ if (!auth.login) throw new import_common4.NotFoundException();
888
+ if (typeof body?.username !== "string" || typeof body?.password !== "string") {
889
+ throw new import_common4.BadRequestException("Body must include string `username` and `password`.");
890
+ }
891
+ const username = body.username;
892
+ const password = body.password;
893
+ const user = await this.runHook("login", () => auth.login?.(username, password) ?? null);
894
+ if (!user) throw new import_common4.UnauthorizedException({
895
+ message: "Invalid credentials"
896
+ });
897
+ return this.mint(user, request, response);
898
+ }
899
+ async session(request, response) {
900
+ const auth = this.requireAuth();
901
+ if (!auth.session) throw new import_common4.NotFoundException();
902
+ const user = await this.runHook("session", () => auth.session?.(request) ?? null);
903
+ if (!user) throw new import_common4.UnauthorizedException();
904
+ return this.mint(user, request, response);
905
+ }
906
+ logout(request, response) {
907
+ clearSessionCookie({
908
+ cookiePath: this.cookiePath ?? "/",
909
+ request,
910
+ response
911
+ });
912
+ }
913
+ requireAuth() {
914
+ if (!this.auth) throw new import_common4.NotFoundException();
915
+ return this.auth;
916
+ }
917
+ mint(user, request, response) {
918
+ const auth = this.requireAuth();
919
+ issueSessionCookie(user, {
920
+ auth,
921
+ cookiePath: this.cookiePath ?? "/",
922
+ request,
923
+ response
924
+ });
925
+ return {
926
+ user: {
927
+ id: user.id,
928
+ ...user.name !== void 0 ? {
929
+ name: user.name
930
+ } : {},
931
+ roles: user.roles ?? []
932
+ }
933
+ };
934
+ }
935
+ /** Run a host hook defensively: a throw is a denial (null), warn-logged once per kind. */
936
+ async runHook(kind, run) {
937
+ try {
938
+ return await run() ?? null;
939
+ } catch (error) {
940
+ if (!this.warnedHooks.has(kind)) {
941
+ this.warnedHooks.add(kind);
942
+ this.logger.warn(`Console auth ${kind} hook threw; treating as denial. ${String(error)}`);
943
+ }
944
+ return null;
945
+ }
946
+ }
947
+ };
948
+ _ts_decorate4([
949
+ (0, import_common4.Get)("me"),
950
+ _ts_param4(0, (0, import_common4.Req)()),
951
+ _ts_metadata4("design:type", Function),
952
+ _ts_metadata4("design:paramtypes", [
953
+ Object
954
+ ]),
955
+ _ts_metadata4("design:returntype", typeof MeResponse === "undefined" ? Object : MeResponse)
956
+ ], MediaConsoleAuthController.prototype, "me", null);
957
+ _ts_decorate4([
958
+ (0, import_common4.Post)("login"),
959
+ (0, import_common4.HttpCode)(200),
960
+ _ts_param4(0, (0, import_common4.Body)()),
961
+ _ts_param4(1, (0, import_common4.Req)()),
962
+ _ts_param4(2, (0, import_common4.Res)({
963
+ passthrough: true
964
+ })),
965
+ _ts_metadata4("design:type", Function),
966
+ _ts_metadata4("design:paramtypes", [
967
+ typeof LoginBody === "undefined" ? Object : LoginBody,
968
+ Object,
969
+ Object
970
+ ]),
971
+ _ts_metadata4("design:returntype", Promise)
972
+ ], MediaConsoleAuthController.prototype, "login", null);
973
+ _ts_decorate4([
974
+ (0, import_common4.Post)("session"),
975
+ (0, import_common4.HttpCode)(200),
976
+ _ts_param4(0, (0, import_common4.Req)()),
977
+ _ts_param4(1, (0, import_common4.Res)({
978
+ passthrough: true
979
+ })),
980
+ _ts_metadata4("design:type", Function),
981
+ _ts_metadata4("design:paramtypes", [
982
+ Object,
983
+ Object
984
+ ]),
985
+ _ts_metadata4("design:returntype", Promise)
986
+ ], MediaConsoleAuthController.prototype, "session", null);
987
+ _ts_decorate4([
988
+ (0, import_common4.Post)("logout"),
989
+ (0, import_common4.HttpCode)(204),
990
+ _ts_param4(0, (0, import_common4.Req)()),
991
+ _ts_param4(1, (0, import_common4.Res)({
992
+ passthrough: true
993
+ })),
994
+ _ts_metadata4("design:type", Function),
995
+ _ts_metadata4("design:paramtypes", [
996
+ Object,
997
+ Object
998
+ ]),
999
+ _ts_metadata4("design:returntype", void 0)
1000
+ ], MediaConsoleAuthController.prototype, "logout", null);
1001
+ MediaConsoleAuthController = _ts_decorate4([
1002
+ (0, import_common4.Controller)(),
1003
+ _ts_param4(0, (0, import_common4.Optional)()),
1004
+ _ts_param4(0, (0, import_common4.Inject)(MEDIA_CONSOLE_AUTH)),
1005
+ _ts_param4(1, (0, import_common4.Optional)()),
1006
+ _ts_param4(1, (0, import_common4.Inject)(MEDIA_CONSOLE_COOKIE_PATH)),
1007
+ _ts_metadata4("design:type", Function),
1008
+ _ts_metadata4("design:paramtypes", [
1009
+ Object,
1010
+ Object
1011
+ ])
1012
+ ], MediaConsoleAuthController);
1013
+
502
1014
  // src/server/media-console-read.controller.ts
503
- var import_common3 = require("@nestjs/common");
504
- function _ts_decorate3(decorators, target, key, desc) {
1015
+ var import_common5 = require("@nestjs/common");
1016
+ function _ts_decorate5(decorators, target, key, desc) {
505
1017
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
506
1018
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
507
1019
  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
1020
  return c > 3 && r && Object.defineProperty(target, key, r), r;
509
1021
  }
510
- __name(_ts_decorate3, "_ts_decorate");
511
- function _ts_metadata3(k, v) {
1022
+ __name(_ts_decorate5, "_ts_decorate");
1023
+ function _ts_metadata5(k, v) {
512
1024
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
513
1025
  }
514
- __name(_ts_metadata3, "_ts_metadata");
515
- function _ts_param3(paramIndex, decorator) {
1026
+ __name(_ts_metadata5, "_ts_metadata");
1027
+ function _ts_param5(paramIndex, decorator) {
516
1028
  return function(target, key) {
517
1029
  decorator(target, key, paramIndex);
518
1030
  };
519
1031
  }
520
- __name(_ts_param3, "_ts_param");
1032
+ __name(_ts_param5, "_ts_param");
521
1033
  function toLimit(value) {
522
1034
  if (value === void 0) return void 0;
523
1035
  const parsed = Number(value);
@@ -556,7 +1068,7 @@ var MediaConsoleReadController = class {
556
1068
  * can render text/PDF previews the browser would otherwise download, and read text past CORS. */
557
1069
  async objectRaw(disk, key) {
558
1070
  const { stream, contentType, size } = await this.service.objectStream(disk, key);
559
- return new import_common3.StreamableFile(stream, {
1071
+ return new import_common5.StreamableFile(stream, {
560
1072
  type: contentType,
561
1073
  disposition: "inline",
562
1074
  ...Number.isFinite(size) ? {
@@ -604,141 +1116,150 @@ var MediaConsoleReadController = class {
604
1116
  return this.service.topology();
605
1117
  }
606
1118
  };
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)
1119
+ _ts_decorate5([
1120
+ (0, import_common5.Get)("disks"),
1121
+ _ts_metadata5("design:type", Function),
1122
+ _ts_metadata5("design:paramtypes", []),
1123
+ _ts_metadata5("design:returntype", typeof DiskListResponse === "undefined" ? Object : DiskListResponse)
612
1124
  ], 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", [
1125
+ _ts_decorate5([
1126
+ (0, import_common5.Get)("disks/:disk/objects"),
1127
+ _ts_param5(0, (0, import_common5.Param)("disk")),
1128
+ _ts_param5(1, (0, import_common5.Query)("prefix")),
1129
+ _ts_param5(2, (0, import_common5.Query)("cursor")),
1130
+ _ts_param5(3, (0, import_common5.Query)("limit")),
1131
+ _ts_metadata5("design:type", Function),
1132
+ _ts_metadata5("design:paramtypes", [
621
1133
  String,
622
1134
  String,
623
1135
  String,
624
1136
  String
625
1137
  ]),
626
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1138
+ _ts_metadata5("design:returntype", typeof Promise === "undefined" ? Object : Promise)
627
1139
  ], 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", [
1140
+ _ts_decorate5([
1141
+ (0, import_common5.Get)("disks/:disk/object"),
1142
+ _ts_param5(0, (0, import_common5.Param)("disk")),
1143
+ _ts_param5(1, (0, import_common5.Query)("key")),
1144
+ _ts_metadata5("design:type", Function),
1145
+ _ts_metadata5("design:paramtypes", [
634
1146
  String,
635
1147
  String
636
1148
  ]),
637
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1149
+ _ts_metadata5("design:returntype", typeof Promise === "undefined" ? Object : Promise)
638
1150
  ], 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", [
1151
+ _ts_decorate5([
1152
+ (0, import_common5.Get)("disks/:disk/object/raw"),
1153
+ _ts_param5(0, (0, import_common5.Param)("disk")),
1154
+ _ts_param5(1, (0, import_common5.Query)("key")),
1155
+ _ts_metadata5("design:type", Function),
1156
+ _ts_metadata5("design:paramtypes", [
645
1157
  String,
646
1158
  String
647
1159
  ]),
648
- _ts_metadata3("design:returntype", Promise)
1160
+ _ts_metadata5("design:returntype", Promise)
649
1161
  ], 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", [
1162
+ _ts_decorate5([
1163
+ (0, import_common5.Get)("uploads"),
1164
+ _ts_param5(0, (0, import_common5.Query)("disk")),
1165
+ _ts_param5(1, (0, import_common5.Query)("prefix")),
1166
+ _ts_metadata5("design:type", Function),
1167
+ _ts_metadata5("design:paramtypes", [
656
1168
  String,
657
1169
  String
658
1170
  ]),
659
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1171
+ _ts_metadata5("design:returntype", typeof Promise === "undefined" ? Object : Promise)
660
1172
  ], 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", [
1173
+ _ts_decorate5([
1174
+ (0, import_common5.Get)("uploads/:id"),
1175
+ _ts_param5(0, (0, import_common5.Param)("id")),
1176
+ _ts_metadata5("design:type", Function),
1177
+ _ts_metadata5("design:paramtypes", [
666
1178
  String
667
1179
  ]),
668
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1180
+ _ts_metadata5("design:returntype", typeof Promise === "undefined" ? Object : Promise)
669
1181
  ], 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)
1182
+ _ts_decorate5([
1183
+ (0, import_common5.Get)("library/collections"),
1184
+ _ts_metadata5("design:type", Function),
1185
+ _ts_metadata5("design:paramtypes", []),
1186
+ _ts_metadata5("design:returntype", typeof Promise === "undefined" ? Object : Promise)
675
1187
  ], 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", [
1188
+ _ts_decorate5([
1189
+ (0, import_common5.Get)("library"),
1190
+ _ts_param5(0, (0, import_common5.Query)("collection")),
1191
+ _ts_param5(1, (0, import_common5.Query)("disk")),
1192
+ _ts_param5(2, (0, import_common5.Query)("cursor")),
1193
+ _ts_param5(3, (0, import_common5.Query)("limit")),
1194
+ _ts_metadata5("design:type", Function),
1195
+ _ts_metadata5("design:paramtypes", [
684
1196
  String,
685
1197
  String,
686
1198
  String,
687
1199
  String
688
1200
  ]),
689
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1201
+ _ts_metadata5("design:returntype", typeof Promise === "undefined" ? Object : Promise)
690
1202
  ], 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", [
1203
+ _ts_decorate5([
1204
+ (0, import_common5.Get)("library/:id"),
1205
+ _ts_param5(0, (0, import_common5.Param)("id")),
1206
+ _ts_metadata5("design:type", Function),
1207
+ _ts_metadata5("design:paramtypes", [
696
1208
  String
697
1209
  ]),
698
- _ts_metadata3("design:returntype", typeof Promise === "undefined" ? Object : Promise)
1210
+ _ts_metadata5("design:returntype", typeof Promise === "undefined" ? Object : Promise)
699
1211
  ], 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)
1212
+ _ts_decorate5([
1213
+ (0, import_common5.Get)("topology"),
1214
+ _ts_metadata5("design:type", Function),
1215
+ _ts_metadata5("design:paramtypes", []),
1216
+ _ts_metadata5("design:returntype", typeof Topology === "undefined" ? Object : Topology)
705
1217
  ], 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", [
1218
+ MediaConsoleReadController = _ts_decorate5([
1219
+ (0, import_common5.UseGuards)(MediaConsoleGuard),
1220
+ (0, import_common5.Controller)(),
1221
+ _ts_param5(0, (0, import_common5.Inject)(MediaConsoleService)),
1222
+ _ts_metadata5("design:type", Function),
1223
+ _ts_metadata5("design:paramtypes", [
711
1224
  typeof MediaConsoleService === "undefined" ? Object : MediaConsoleService
712
1225
  ])
713
1226
  ], MediaConsoleReadController);
714
1227
 
715
1228
  // src/server/media-console-api.module.ts
716
- function _ts_decorate4(decorators, target, key, desc) {
1229
+ function _ts_decorate6(decorators, target, key, desc) {
717
1230
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
718
1231
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
719
1232
  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
1233
  return c > 3 && r && Object.defineProperty(target, key, r), r;
721
1234
  }
722
- __name(_ts_decorate4, "_ts_decorate");
1235
+ __name(_ts_decorate6, "_ts_decorate");
723
1236
  var MediaConsoleApiModule = class _MediaConsoleApiModule {
724
1237
  static {
725
1238
  __name(this, "MediaConsoleApiModule");
726
1239
  }
727
- static register(actions) {
1240
+ static register(options) {
728
1241
  return {
729
1242
  module: _MediaConsoleApiModule,
730
- controllers: actions ? [
1243
+ imports: options.imports ?? [],
1244
+ controllers: [
731
1245
  MediaConsoleReadController,
732
- MediaConsoleActionsController
733
- ] : [
734
- MediaConsoleReadController
1246
+ MediaConsoleAuthController,
1247
+ ...options.actions ? [
1248
+ MediaConsoleActionsController
1249
+ ] : []
735
1250
  ],
736
1251
  providers: [
737
1252
  MediaConsoleService,
1253
+ MediaConsoleGuard,
738
1254
  {
739
1255
  provide: MEDIA_DASHBOARD_ACTIONS,
740
- useValue: actions
741
- }
1256
+ useValue: options.actions
1257
+ },
1258
+ {
1259
+ provide: MEDIA_CONSOLE_COOKIE_PATH,
1260
+ useValue: options.cookiePath
1261
+ },
1262
+ options.authProvider
742
1263
  ],
743
1264
  exports: [
744
1265
  MediaConsoleService
@@ -746,32 +1267,32 @@ var MediaConsoleApiModule = class _MediaConsoleApiModule {
746
1267
  };
747
1268
  }
748
1269
  };
749
- MediaConsoleApiModule = _ts_decorate4([
750
- (0, import_common4.Module)({})
1270
+ MediaConsoleApiModule = _ts_decorate6([
1271
+ (0, import_common6.Module)({})
751
1272
  ], MediaConsoleApiModule);
752
1273
 
753
1274
  // src/server/media-dashboard-ui.controller.ts
754
1275
  var import_node_fs = require("fs");
755
1276
  var import_node_path = require("path");
756
1277
  var import_node_url = require("url");
757
- var import_common5 = require("@nestjs/common");
758
- function _ts_decorate5(decorators, target, key, desc) {
1278
+ var import_common7 = require("@nestjs/common");
1279
+ function _ts_decorate7(decorators, target, key, desc) {
759
1280
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
760
1281
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
761
1282
  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
1283
  return c > 3 && r && Object.defineProperty(target, key, r), r;
763
1284
  }
764
- __name(_ts_decorate5, "_ts_decorate");
765
- function _ts_metadata4(k, v) {
1285
+ __name(_ts_decorate7, "_ts_decorate");
1286
+ function _ts_metadata6(k, v) {
766
1287
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
767
1288
  }
768
- __name(_ts_metadata4, "_ts_metadata");
769
- function _ts_param4(paramIndex, decorator) {
1289
+ __name(_ts_metadata6, "_ts_metadata");
1290
+ function _ts_param6(paramIndex, decorator) {
770
1291
  return function(target, key) {
771
1292
  decorator(target, key, paramIndex);
772
1293
  };
773
1294
  }
774
- __name(_ts_param4, "_ts_param");
1295
+ __name(_ts_param6, "_ts_param");
775
1296
  var BUILD_BASE = "/media";
776
1297
  function spaDir() {
777
1298
  return (0, import_node_url.fileURLToPath)(new URL("../spa", importMetaUrl));
@@ -802,7 +1323,7 @@ var MediaDashboardUiController = class {
802
1323
  index() {
803
1324
  const indexPath = (0, import_node_path.join)(this.dir, "index.html");
804
1325
  if (!(0, import_node_fs.existsSync)(indexPath)) {
805
- throw new import_common5.NotFoundException("Console SPA is not built. Run the package build.");
1326
+ throw new import_common7.NotFoundException("Console SPA is not built. Run the package build.");
806
1327
  }
807
1328
  const html = (0, import_node_fs.readFileSync)(indexPath, "utf8").replaceAll(`="${BUILD_BASE}/`, `="${this.basePath}/`);
808
1329
  const inject = `<script>window.__MEDIA_BASE__='${this.basePath}';window.__MEDIA_API__='${this.apiBasePath}';</script>`;
@@ -810,55 +1331,55 @@ var MediaDashboardUiController = class {
810
1331
  }
811
1332
  asset(file) {
812
1333
  const safe = (0, import_node_path.basename)(file);
813
- if (safe !== file) throw new import_common5.NotFoundException();
1334
+ if (safe !== file) throw new import_common7.NotFoundException();
814
1335
  const root = (0, import_node_path.resolve)(this.dir, "assets");
815
1336
  const assetPath = (0, import_node_path.resolve)(root, safe);
816
1337
  if (!assetPath.startsWith(root + import_node_path.sep) || !(0, import_node_fs.existsSync)(assetPath)) {
817
- throw new import_common5.NotFoundException();
1338
+ throw new import_common7.NotFoundException();
818
1339
  }
819
1340
  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), {
1341
+ return new import_common7.StreamableFile((0, import_node_fs.readFileSync)(assetPath), {
821
1342
  type
822
1343
  });
823
1344
  }
824
1345
  };
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)
1346
+ _ts_decorate7([
1347
+ (0, import_common7.Get)(),
1348
+ (0, import_common7.Header)("Content-Type", "text/html; charset=utf-8"),
1349
+ (0, import_common7.Header)("Cache-Control", "no-store, must-revalidate"),
1350
+ _ts_metadata6("design:type", Function),
1351
+ _ts_metadata6("design:paramtypes", []),
1352
+ _ts_metadata6("design:returntype", String)
832
1353
  ], 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", [
1354
+ _ts_decorate7([
1355
+ (0, import_common7.Get)("assets/:file"),
1356
+ (0, import_common7.Header)("Cache-Control", "public, max-age=31536000, immutable"),
1357
+ _ts_param6(0, (0, import_common7.Param)("file")),
1358
+ _ts_metadata6("design:type", Function),
1359
+ _ts_metadata6("design:paramtypes", [
839
1360
  String
840
1361
  ]),
841
- _ts_metadata4("design:returntype", typeof import_common5.StreamableFile === "undefined" ? Object : import_common5.StreamableFile)
1362
+ _ts_metadata6("design:returntype", typeof import_common7.StreamableFile === "undefined" ? Object : import_common7.StreamableFile)
842
1363
  ], 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", [
1364
+ MediaDashboardUiController = _ts_decorate7([
1365
+ (0, import_common7.Controller)(),
1366
+ _ts_param6(0, (0, import_common7.Inject)(MEDIA_DASHBOARD_BASE_PATH)),
1367
+ _ts_param6(1, (0, import_common7.Inject)(MEDIA_DASHBOARD_API_PATH)),
1368
+ _ts_metadata6("design:type", Function),
1369
+ _ts_metadata6("design:paramtypes", [
849
1370
  String,
850
1371
  String
851
1372
  ])
852
1373
  ], MediaDashboardUiController);
853
1374
 
854
1375
  // src/server/media-dashboard.module.ts
855
- function _ts_decorate6(decorators, target, key, desc) {
1376
+ function _ts_decorate8(decorators, target, key, desc) {
856
1377
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
857
1378
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
858
1379
  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
1380
  return c > 3 && r && Object.defineProperty(target, key, r), r;
860
1381
  }
861
- __name(_ts_decorate6, "_ts_decorate");
1382
+ __name(_ts_decorate8, "_ts_decorate");
862
1383
  function normalize(path) {
863
1384
  return `/${path.replace(/^\/+|\/+$/g, "")}`;
864
1385
  }
@@ -868,13 +1389,34 @@ var MediaDashboardModule = class _MediaDashboardModule {
868
1389
  __name(this, "MediaDashboardModule");
869
1390
  }
870
1391
  static forRoot(options = {}) {
1392
+ const apiBasePath = normalize(options.apiBasePath ?? `${normalize(options.basePath ?? "/media")}/api`);
1393
+ return _MediaDashboardModule.build(options, apiBasePath, {
1394
+ provide: MEDIA_CONSOLE_AUTH,
1395
+ useValue: resolveConsoleAuth(options.auth)
1396
+ });
1397
+ }
1398
+ static forRootAsync(options) {
1399
+ const apiBasePath = normalize(options.apiBasePath ?? `${normalize(options.basePath ?? "/media")}/api`);
1400
+ const authProvider = {
1401
+ provide: MEDIA_CONSOLE_AUTH,
1402
+ inject: options.inject ?? [],
1403
+ useFactory: /* @__PURE__ */ __name(async (...deps) => resolveConsoleAuth(await options.useAuth(...deps)), "useFactory")
1404
+ };
1405
+ return _MediaDashboardModule.build(options, apiBasePath, authProvider, options.imports);
1406
+ }
1407
+ /** Shared wiring: static routing + the API module, with `auth` supplied by the given provider. */
1408
+ static build(options, apiBasePath, authProvider, imports) {
871
1409
  const basePath = normalize(options.basePath ?? "/media");
872
- const apiBasePath = normalize(options.apiBasePath ?? `${basePath}/api`);
873
1410
  const actions = options.actions === true;
874
1411
  return {
875
1412
  module: _MediaDashboardModule,
876
1413
  imports: [
877
- MediaConsoleApiModule.register(actions),
1414
+ MediaConsoleApiModule.register({
1415
+ actions,
1416
+ cookiePath: apiBasePath,
1417
+ authProvider,
1418
+ imports
1419
+ }),
878
1420
  import_core.RouterModule.register([
879
1421
  {
880
1422
  path: basePath,
@@ -906,8 +1448,8 @@ var MediaDashboardModule = class _MediaDashboardModule {
906
1448
  };
907
1449
  }
908
1450
  };
909
- MediaDashboardModule = _ts_decorate6([
910
- (0, import_common6.Module)({})
1451
+ MediaDashboardModule = _ts_decorate8([
1452
+ (0, import_common8.Module)({})
911
1453
  ], MediaDashboardModule);
912
1454
  // Annotate the CommonJS export names for ESM import in node:
913
1455
  0 && (module.exports = {