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