@mastra/nestjs 0.2.30-alpha.0 → 0.2.30-alpha.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.
- package/dist/controllers/mastra.controller.d.ts +6 -2
- package/dist/controllers/mastra.controller.d.ts.map +1 -1
- package/dist/guards/mastra-auth.guard.d.ts +3 -9
- package/dist/guards/mastra-auth.guard.d.ts.map +1 -1
- package/dist/guards/mastra-route.guard.d.ts +1 -3
- package/dist/guards/mastra-route.guard.d.ts.map +1 -1
- package/dist/index.cjs +261 -84
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +256 -85
- package/dist/index.js.map +1 -1
- package/dist/mastra.module.d.ts.map +1 -1
- package/dist/services/auth.service.d.ts +25 -15
- package/dist/services/auth.service.d.ts.map +1 -1
- package/dist/services/custom-route.service.d.ts +30 -0
- package/dist/services/custom-route.service.d.ts.map +1 -0
- package/package.json +8 -7
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { Request, Response } from 'express';
|
|
2
2
|
import type { MastraModuleOptions } from '../mastra.module.js';
|
|
3
|
+
import { AuthService } from '../services/auth.service.js';
|
|
4
|
+
import { CustomRouteService } from '../services/custom-route.service.js';
|
|
3
5
|
import { RequestContextService } from '../services/request-context.service.js';
|
|
4
6
|
import { RouteHandlerService } from '../services/route-handler.service.js';
|
|
5
7
|
/**
|
|
@@ -13,11 +15,13 @@ export declare class MastraController {
|
|
|
13
15
|
private readonly options;
|
|
14
16
|
private readonly routeHandler;
|
|
15
17
|
private readonly requestContext;
|
|
16
|
-
|
|
18
|
+
private readonly customRoutes;
|
|
19
|
+
private readonly authService;
|
|
20
|
+
constructor(options: MastraModuleOptions, routeHandler: RouteHandlerService, requestContext: RequestContextService, customRoutes: CustomRouteService, authService: AuthService);
|
|
17
21
|
/**
|
|
18
22
|
* Catch-all handler that matches incoming requests to Mastra routes.
|
|
19
23
|
*/
|
|
20
|
-
handleRequest(req: Request,
|
|
24
|
+
handleRequest(req: Request, res: Response): Promise<unknown>;
|
|
21
25
|
/**
|
|
22
26
|
* Parse and normalize query parameters.
|
|
23
27
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mastra.controller.d.ts","sourceRoot":"","sources":["../../src/controllers/mastra.controller.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAQjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAKxE;;;;;;GAMG;AACH,qBAIa,gBAAgB;IAED,OAAO,CAAC,QAAQ,CAAC,OAAO;IACnB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc;
|
|
1
|
+
{"version":3,"file":"mastra.controller.d.ts","sourceRoot":"","sources":["../../src/controllers/mastra.controller.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAQjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAKxE;;;;;;GAMG;AACH,qBAIa,gBAAgB;IAED,OAAO,CAAC,QAAQ,CAAC,OAAO;IACnB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAClC,OAAO,CAAC,QAAQ,CAAC,YAAY;IACpC,OAAO,CAAC,QAAQ,CAAC,WAAW;IALnD,YAC2C,OAAO,EAAE,mBAAmB,EACvB,YAAY,EAAE,mBAAmB,EAC/B,cAAc,EAAE,qBAAqB,EACxC,YAAY,EAAE,kBAAkB,EACvC,WAAW,EAAE,WAAW,EAC5D;IAEJ;;OAEG;IAEG,aAAa,CAAQ,GAAG,EAAE,OAAO,EAA8B,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAmDpG;IAED;;;;;;;;;OASG;IACH,OAAO,CAAC,gBAAgB;IAoBxB;;OAEG;YACW,SAAS;CAsBxB"}
|
|
@@ -7,15 +7,9 @@ import { AuthService } from '../services/auth.service.js';
|
|
|
7
7
|
*
|
|
8
8
|
* **IMPORTANT: This guard is for custom user routes, NOT for Mastra API routes.**
|
|
9
9
|
*
|
|
10
|
-
* Mastra routes (agents, workflows, etc.)
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* protect your own NestJS routes with Mastra's auth config.
|
|
14
|
-
*
|
|
15
|
-
* Differences from AuthService (used internally for Mastra routes):
|
|
16
|
-
* - Does NOT check `customRouteAuthConfig`
|
|
17
|
-
* - Does NOT check `isProtectedPath` / `canAccessPublicly` from @mastra/server/auth
|
|
18
|
-
* - Has simpler dev playground detection (just checks header + config)
|
|
10
|
+
* Mastra routes (agents, workflows, etc.) and `server.apiRoutes` are protected by
|
|
11
|
+
* MastraRouteGuard. Use this guard to protect your own NestJS routes with the
|
|
12
|
+
* same Mastra auth pipeline (`server.auth`).
|
|
19
13
|
*
|
|
20
14
|
* @example
|
|
21
15
|
* ```typescript
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mastra-auth.guard.d.ts","sourceRoot":"","sources":["../../src/guards/mastra-auth.guard.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAIzC,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD
|
|
1
|
+
{"version":3,"file":"mastra-auth.guard.d.ts","sourceRoot":"","sources":["../../src/guards/mastra-auth.guard.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAIzC,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBACa,eAAgB,YAAW,WAAW;IAI5B,OAAO,CAAC,QAAQ,CAAC,SAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAJnD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoC;IAE3D,YACsC,SAAS,EAAE,SAAS,EAClB,WAAW,EAAE,WAAW,EAC5D;IAEE,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAqB7D;CACF"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { Mastra } from '@mastra/core/mastra';
|
|
2
1
|
import type { CanActivate, ExecutionContext } from '@nestjs/common';
|
|
3
2
|
import type { MastraModuleOptions } from '../mastra.module.js';
|
|
4
3
|
import { AuthService } from '../services/auth.service.js';
|
|
@@ -11,13 +10,12 @@ import { MastraThrottleGuard } from './mastra-throttle.guard.js';
|
|
|
11
10
|
* then enforces auth + rate limiting for matched Mastra routes.
|
|
12
11
|
*/
|
|
13
12
|
export declare class MastraRouteGuard implements CanActivate {
|
|
14
|
-
private readonly mastra;
|
|
15
13
|
private readonly options;
|
|
16
14
|
private readonly routeHandler;
|
|
17
15
|
private readonly requestContext;
|
|
18
16
|
private readonly authService;
|
|
19
17
|
private readonly throttleGuard;
|
|
20
|
-
constructor(
|
|
18
|
+
constructor(options: MastraModuleOptions, routeHandler: RouteHandlerService, requestContext: RequestContextService, authService: AuthService, throttleGuard: MastraThrottleGuard);
|
|
21
19
|
canActivate(context: ExecutionContext): Promise<boolean>;
|
|
22
20
|
}
|
|
23
21
|
//# sourceMappingURL=mastra-route.guard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mastra-route.guard.d.ts","sourceRoot":"","sources":["../../src/guards/mastra-route.guard.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mastra-route.guard.d.ts","sourceRoot":"","sources":["../../src/guards/mastra-route.guard.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAIpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAExE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE9D;;;;GAIG;AACH,qBACa,gBAAiB,YAAW,WAAW;IAExB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACnB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc;IACzC,OAAO,CAAC,QAAQ,CAAC,WAAW;IACpB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAL7D,YAC2C,OAAO,EAAE,mBAAmB,EACvB,YAAY,EAAE,mBAAmB,EAC/B,cAAc,EAAE,qBAAqB,EAC/C,WAAW,EAAE,WAAW,EAChB,aAAa,EAAE,mBAAmB,EAC9E;IAEE,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CA6B7D;CACF"}
|
package/dist/index.cjs
CHANGED
|
@@ -25,8 +25,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
25
25
|
let _nestjs_common = require("@nestjs/common");
|
|
26
26
|
let _mastra_server_server_adapter = require("@mastra/server/server-adapter");
|
|
27
27
|
let _mastra_server_handlers_error = require("@mastra/server/handlers/error");
|
|
28
|
-
let _mastra_server_auth = require("@mastra/server/auth");
|
|
29
28
|
let _mastra_core_request_context = require("@mastra/core/request-context");
|
|
29
|
+
let _mastra_server_auth = require("@mastra/server/auth");
|
|
30
|
+
let stream = require("stream");
|
|
31
|
+
let hono = require("hono");
|
|
30
32
|
let _nestjs_core = require("@nestjs/core");
|
|
31
33
|
let crypto = require("crypto");
|
|
32
34
|
let module$1 = require("module");
|
|
@@ -473,82 +475,224 @@ function toWebRequest(req) {
|
|
|
473
475
|
});
|
|
474
476
|
}
|
|
475
477
|
//#endregion
|
|
476
|
-
//#region src/services/
|
|
477
|
-
|
|
478
|
-
let
|
|
478
|
+
//#region src/services/custom-route.service.ts
|
|
479
|
+
const NOT_FOUND_HEADER = "x-mastra-custom-route-not-found";
|
|
480
|
+
let CustomRouteService = class CustomRouteService {
|
|
479
481
|
mastra;
|
|
480
|
-
|
|
481
|
-
|
|
482
|
+
routes;
|
|
483
|
+
authConfig;
|
|
484
|
+
fetchPromise;
|
|
482
485
|
constructor(mastra, options) {
|
|
483
486
|
this.mastra = mastra;
|
|
484
|
-
this.
|
|
487
|
+
this.routes = (mastra.getServer()?.apiRoutes ?? []).filter((route) => !("_mastraSchemaRoute" in route && route._mastraSchemaRoute === true));
|
|
488
|
+
this.authConfig = new Map(options.customRouteAuthConfig);
|
|
489
|
+
for (const route of this.routes) {
|
|
490
|
+
const key = `${route.method}:${route.path}`;
|
|
491
|
+
if (!this.authConfig.has(key)) this.authConfig.set(key, route.requiresAuth !== false);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
/** Auth config for custom routes, keyed by `METHOD:path`. */
|
|
495
|
+
get customRouteAuthConfig() {
|
|
496
|
+
return this.authConfig;
|
|
485
497
|
}
|
|
486
498
|
/**
|
|
487
|
-
*
|
|
488
|
-
* Returns
|
|
489
|
-
* Throws UnauthorizedException or ForbiddenException if auth fails.
|
|
499
|
+
* Runs a matched custom route and writes its response.
|
|
500
|
+
* Returns false if no custom route handled the request.
|
|
490
501
|
*
|
|
491
|
-
*
|
|
492
|
-
*
|
|
502
|
+
* `authenticate` runs after Hono's router selects the route, so auth is enforced
|
|
503
|
+
* for exactly the routes Hono dispatches (including regex-constrained params).
|
|
493
504
|
*/
|
|
494
|
-
async authenticate
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
const
|
|
501
|
-
const
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
};
|
|
505
|
-
|
|
506
|
-
if (
|
|
507
|
-
if ((
|
|
508
|
-
|
|
509
|
-
|
|
505
|
+
async handle(req, res, requestContext, authenticate) {
|
|
506
|
+
if (this.routes.length === 0) return false;
|
|
507
|
+
this.fetchPromise ??= this.build().catch((err) => {
|
|
508
|
+
this.fetchPromise = void 0;
|
|
509
|
+
throw err;
|
|
510
|
+
});
|
|
511
|
+
const fetch = await this.fetchPromise;
|
|
512
|
+
const env = {
|
|
513
|
+
requestContext,
|
|
514
|
+
authenticate
|
|
515
|
+
};
|
|
516
|
+
const response = await fetch(this.toFetchRequest(req), env);
|
|
517
|
+
if (env.authError !== void 0) throw env.authError;
|
|
518
|
+
if (response.headers.get(NOT_FOUND_HEADER) === "true") return false;
|
|
519
|
+
res.status(response.status);
|
|
520
|
+
response.headers.forEach((value, key) => {
|
|
521
|
+
if (key.toLowerCase() === "set-cookie") return;
|
|
522
|
+
res.setHeader(key, value);
|
|
523
|
+
});
|
|
524
|
+
for (const cookie of response.headers.getSetCookie()) res.append("set-cookie", cookie);
|
|
525
|
+
if (!response.body) {
|
|
526
|
+
res.end();
|
|
527
|
+
return true;
|
|
528
|
+
}
|
|
529
|
+
const reader = response.body.getReader();
|
|
530
|
+
const onClose = () => void reader.cancel().catch(() => {});
|
|
531
|
+
res.once("close", onClose);
|
|
510
532
|
try {
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
533
|
+
while (!res.destroyed) {
|
|
534
|
+
const { done, value } = await reader.read();
|
|
535
|
+
if (done) break;
|
|
536
|
+
if (!res.write(value)) await new Promise((resolve) => {
|
|
537
|
+
const resume = () => {
|
|
538
|
+
res.off("drain", resume);
|
|
539
|
+
res.off("close", resume);
|
|
540
|
+
resolve();
|
|
541
|
+
};
|
|
542
|
+
res.once("drain", resume);
|
|
543
|
+
res.once("close", resume);
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
} finally {
|
|
547
|
+
res.off("close", onClose);
|
|
548
|
+
res.end();
|
|
522
549
|
}
|
|
550
|
+
return true;
|
|
551
|
+
}
|
|
552
|
+
async build() {
|
|
553
|
+
const mastra = this.mastra;
|
|
554
|
+
const app = new hono.Hono();
|
|
555
|
+
app.use("*", async (c, next) => {
|
|
556
|
+
c.set("mastra", mastra);
|
|
557
|
+
c.set("requestContext", c.env?.requestContext ?? new _mastra_core_request_context.RequestContext());
|
|
558
|
+
await next();
|
|
559
|
+
});
|
|
560
|
+
const serverOnError = mastra.getServer()?.onError;
|
|
561
|
+
app.onError((err, c) => {
|
|
562
|
+
if (serverOnError) return serverOnError(err, c);
|
|
563
|
+
mastra.getLogger()?.error(`Custom route handler failed: ${c.req.method} ${c.req.path}`, { error: err instanceof Error ? err.stack ?? err.message : String(err) });
|
|
564
|
+
return c.json({ error: "Internal Server Error" }, 500);
|
|
565
|
+
});
|
|
566
|
+
for (const route of this.routes) {
|
|
567
|
+
const handler = "handler" in route && route.handler ? route.handler : "createHandler" in route ? await route.createHandler({ mastra }) : void 0;
|
|
568
|
+
if (!handler) continue;
|
|
569
|
+
const middlewares = route.middleware ? Array.isArray(route.middleware) ? route.middleware : [route.middleware] : [];
|
|
570
|
+
const requiresAuth = this.authConfig.get(`${route.method}:${route.path}`) ?? route.requiresAuth !== false;
|
|
571
|
+
const authMiddleware = async (c, next) => {
|
|
572
|
+
try {
|
|
573
|
+
await c.env.authenticate(requiresAuth);
|
|
574
|
+
} catch (err) {
|
|
575
|
+
c.env.authError = err;
|
|
576
|
+
return c.body(null, 401);
|
|
577
|
+
}
|
|
578
|
+
await next();
|
|
579
|
+
};
|
|
580
|
+
const handlers = [
|
|
581
|
+
authMiddleware,
|
|
582
|
+
...middlewares,
|
|
583
|
+
handler
|
|
584
|
+
];
|
|
585
|
+
if (route.method === "ALL") app.all(route.path, handlers[0], ...handlers.slice(1));
|
|
586
|
+
else app.on(route.method, route.path, handlers[0], ...handlers.slice(1));
|
|
587
|
+
}
|
|
588
|
+
app.notFound(() => new Response(null, {
|
|
589
|
+
status: 404,
|
|
590
|
+
headers: { [NOT_FOUND_HEADER]: "true" }
|
|
591
|
+
}));
|
|
592
|
+
return (request, env) => Promise.resolve(app.fetch(request, env));
|
|
593
|
+
}
|
|
594
|
+
toFetchRequest(req) {
|
|
595
|
+
const url = `${req.protocol || "http"}://${req.get("host") || "localhost"}${req.originalUrl || req.url}`;
|
|
596
|
+
const headers = new Headers();
|
|
597
|
+
for (const [key, value] of Object.entries(req.headers)) if (typeof value === "string") headers.set(key, value);
|
|
598
|
+
else if (Array.isArray(value)) value.forEach((v) => headers.append(key, v));
|
|
599
|
+
const init = {
|
|
600
|
+
method: req.method,
|
|
601
|
+
headers
|
|
602
|
+
};
|
|
603
|
+
if (["GET", "HEAD"].includes(req.method)) return new globalThis.Request(url, init);
|
|
604
|
+
const body = req.body;
|
|
605
|
+
if (!(req._body === true) && req.readable && !req.readableEnded) {
|
|
606
|
+
init.body = stream.Readable.toWeb(req);
|
|
607
|
+
init.duplex = "half";
|
|
608
|
+
} else if (typeof body === "string" || body instanceof Uint8Array) init.body = body;
|
|
609
|
+
else if (typeof body === "object" && body !== null) {
|
|
610
|
+
const contentType = headers.get("content-type") ?? "";
|
|
611
|
+
if (contentType.includes("application/x-www-form-urlencoded")) init.body = new URLSearchParams(body).toString();
|
|
612
|
+
else {
|
|
613
|
+
init.body = JSON.stringify(body);
|
|
614
|
+
if (!contentType) headers.set("content-type", "application/json");
|
|
615
|
+
}
|
|
616
|
+
headers.delete("content-length");
|
|
617
|
+
}
|
|
618
|
+
return new globalThis.Request(url, init);
|
|
619
|
+
}
|
|
620
|
+
};
|
|
621
|
+
CustomRouteService = __decorate([
|
|
622
|
+
(0, _nestjs_common.Injectable)(),
|
|
623
|
+
__decorateParam(0, (0, _nestjs_common.Inject)(MASTRA)),
|
|
624
|
+
__decorateParam(1, (0, _nestjs_common.Inject)(MASTRA_OPTIONS)),
|
|
625
|
+
__decorateMetadata("design:paramtypes", [Object, Object])
|
|
626
|
+
], CustomRouteService);
|
|
627
|
+
//#endregion
|
|
628
|
+
//#region src/services/auth.service.ts
|
|
629
|
+
let AuthService = class AuthService {
|
|
630
|
+
mastra;
|
|
631
|
+
options;
|
|
632
|
+
customRoutes;
|
|
633
|
+
constructor(mastra, options, customRoutes) {
|
|
634
|
+
this.mastra = mastra;
|
|
635
|
+
this.options = options;
|
|
636
|
+
this.customRoutes = customRoutes;
|
|
523
637
|
}
|
|
524
638
|
/**
|
|
525
|
-
*
|
|
526
|
-
*
|
|
527
|
-
* export a standalone type for the auth config object.
|
|
639
|
+
* Whether Mastra auth should run: module options enable it, or the Mastra
|
|
640
|
+
* server has auth configured (unless module options explicitly disable it).
|
|
528
641
|
*/
|
|
529
|
-
|
|
530
|
-
if (
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
642
|
+
isEnabled() {
|
|
643
|
+
if (this.options.auth?.enabled === false) return false;
|
|
644
|
+
return Boolean(this.options.auth?.enabled || this.mastra.getServer()?.auth);
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Check authentication for a request.
|
|
648
|
+
* Returns the authenticated user if auth succeeds, undefined if no auth required.
|
|
649
|
+
* Throws UnauthorizedException or ForbiddenException if auth fails.
|
|
650
|
+
*/
|
|
651
|
+
async authenticate(request, options = {}) {
|
|
652
|
+
const authConfig = this.mastra.getServer()?.auth;
|
|
653
|
+
if (!authConfig) return;
|
|
654
|
+
const requestContext = options.requestContext ?? new _mastra_core_request_context.RequestContext();
|
|
655
|
+
const path = request.path;
|
|
656
|
+
const method = request.method;
|
|
657
|
+
let customRouteAuthConfig = this.customRoutes.customRouteAuthConfig;
|
|
658
|
+
if (options.customRoute && options.requiresAuth !== void 0) {
|
|
659
|
+
customRouteAuthConfig = new Map(customRouteAuthConfig);
|
|
660
|
+
customRouteAuthConfig.set(`${method.toUpperCase()}:${path}`, options.requiresAuth);
|
|
661
|
+
}
|
|
662
|
+
const webRequest = toWebRequest(request);
|
|
663
|
+
const result = await (0, _mastra_server_auth.coreAuthMiddleware)({
|
|
664
|
+
path,
|
|
665
|
+
method,
|
|
666
|
+
getHeader: (name) => {
|
|
667
|
+
const value = request.headers[name.toLowerCase()];
|
|
668
|
+
return Array.isArray(value) ? value[0] : value;
|
|
669
|
+
},
|
|
670
|
+
mastra: this.mastra,
|
|
671
|
+
authConfig,
|
|
672
|
+
customRouteAuthConfig,
|
|
673
|
+
requestContext,
|
|
674
|
+
rawRequest: webRequest,
|
|
675
|
+
token: this.extractToken(request) ?? null,
|
|
676
|
+
buildAuthorizeContext: () => ({
|
|
536
677
|
get: (key) => {
|
|
537
678
|
if (key === "mastra") return this.mastra;
|
|
538
|
-
if (key === "customRouteAuthConfig") return
|
|
679
|
+
if (key === "customRouteAuthConfig") return customRouteAuthConfig;
|
|
539
680
|
},
|
|
540
|
-
req:
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
}
|
|
681
|
+
req: webRequest
|
|
682
|
+
}),
|
|
683
|
+
requiresAuth: options.requiresAuth
|
|
684
|
+
});
|
|
685
|
+
if (result.headers && options.response) for (const [key, value] of Object.entries(result.headers)) if (key.toLowerCase() === "set-cookie") options.response.append(key, value);
|
|
686
|
+
else options.response.setHeader(key, value);
|
|
687
|
+
if (result.action === "error") {
|
|
688
|
+
const message = typeof result.body.error === "string" ? result.body.error : "Access denied";
|
|
689
|
+
if (result.status === 401) throw new _nestjs_common.UnauthorizedException(message);
|
|
690
|
+
if (result.status === 403) throw new _nestjs_common.ForbiddenException(message);
|
|
691
|
+
throw new _nestjs_common.HttpException(result.body, result.status);
|
|
692
|
+
}
|
|
693
|
+
const user = requestContext.get(_mastra_server_auth.MASTRA_USER_KEY);
|
|
694
|
+
if (user !== void 0) request.user = user;
|
|
695
|
+
return user;
|
|
552
696
|
}
|
|
553
697
|
/**
|
|
554
698
|
* Extract authentication token from request.
|
|
@@ -567,11 +711,16 @@ let AuthService = _AuthService = class AuthService {
|
|
|
567
711
|
}
|
|
568
712
|
}
|
|
569
713
|
};
|
|
570
|
-
AuthService =
|
|
714
|
+
AuthService = __decorate([
|
|
571
715
|
(0, _nestjs_common.Injectable)(),
|
|
572
716
|
__decorateParam(0, (0, _nestjs_common.Inject)(MASTRA)),
|
|
573
717
|
__decorateParam(1, (0, _nestjs_common.Inject)(MASTRA_OPTIONS)),
|
|
574
|
-
|
|
718
|
+
__decorateParam(2, (0, _nestjs_common.Inject)(CustomRouteService)),
|
|
719
|
+
__decorateMetadata("design:paramtypes", [
|
|
720
|
+
Object,
|
|
721
|
+
Object,
|
|
722
|
+
typeof CustomRouteService === "undefined" ? Object : CustomRouteService
|
|
723
|
+
])
|
|
575
724
|
], AuthService);
|
|
576
725
|
//#endregion
|
|
577
726
|
//#region src/services/request-context.service.ts
|
|
@@ -850,14 +999,12 @@ MastraThrottleGuard = _MastraThrottleGuard = __decorate([
|
|
|
850
999
|
//#endregion
|
|
851
1000
|
//#region src/guards/mastra-route.guard.ts
|
|
852
1001
|
let MastraRouteGuard = class MastraRouteGuard {
|
|
853
|
-
mastra;
|
|
854
1002
|
options;
|
|
855
1003
|
routeHandler;
|
|
856
1004
|
requestContext;
|
|
857
1005
|
authService;
|
|
858
1006
|
throttleGuard;
|
|
859
|
-
constructor(
|
|
860
|
-
this.mastra = mastra;
|
|
1007
|
+
constructor(options, routeHandler, requestContext, authService, throttleGuard) {
|
|
861
1008
|
this.options = options;
|
|
862
1009
|
this.routeHandler = routeHandler;
|
|
863
1010
|
this.requestContext = requestContext;
|
|
@@ -868,29 +1015,29 @@ let MastraRouteGuard = class MastraRouteGuard {
|
|
|
868
1015
|
const request = context.switchToHttp().getRequest();
|
|
869
1016
|
const method = request.method.toUpperCase();
|
|
870
1017
|
const routePath = getMastraRoutePath(request.path, this.options.prefix);
|
|
871
|
-
if (!routePath) return true;
|
|
872
|
-
if (
|
|
873
|
-
|
|
874
|
-
|
|
1018
|
+
if (!(routePath ? this.routeHandler.matchRoute(method, routePath) : void 0)) return true;
|
|
1019
|
+
if (this.authService.isEnabled()) {
|
|
1020
|
+
const user = await this.authService.authenticate(request, {
|
|
1021
|
+
requestContext: this.requestContext.requestContext,
|
|
1022
|
+
response: context.switchToHttp().getResponse()
|
|
1023
|
+
});
|
|
875
1024
|
if (user !== void 0) this.requestContext.setUser(user);
|
|
876
1025
|
}
|
|
877
1026
|
if (this.options.rateLimitOptions?.enabled !== false) {
|
|
878
|
-
const { limit, windowMs } = this.throttleGuard.getRateLimitSettings(request, void 0, routePath);
|
|
879
|
-
await this.throttleGuard.checkLimit(request, limit, windowMs, routePath);
|
|
1027
|
+
const { limit, windowMs } = this.throttleGuard.getRateLimitSettings(request, void 0, routePath ?? void 0);
|
|
1028
|
+
await this.throttleGuard.checkLimit(request, limit, windowMs, routePath ?? void 0);
|
|
880
1029
|
}
|
|
881
1030
|
return true;
|
|
882
1031
|
}
|
|
883
1032
|
};
|
|
884
1033
|
MastraRouteGuard = __decorate([
|
|
885
1034
|
(0, _nestjs_common.Injectable)({ scope: _nestjs_common.Scope.REQUEST }),
|
|
886
|
-
__decorateParam(0, (0, _nestjs_common.Inject)(
|
|
887
|
-
__decorateParam(1, (0, _nestjs_common.Inject)(
|
|
888
|
-
__decorateParam(2, (0, _nestjs_common.Inject)(
|
|
889
|
-
__decorateParam(3, (0, _nestjs_common.Inject)(
|
|
890
|
-
__decorateParam(4, (0, _nestjs_common.Inject)(
|
|
891
|
-
__decorateParam(5, (0, _nestjs_common.Inject)(MastraThrottleGuard)),
|
|
1035
|
+
__decorateParam(0, (0, _nestjs_common.Inject)(MASTRA_OPTIONS)),
|
|
1036
|
+
__decorateParam(1, (0, _nestjs_common.Inject)(RouteHandlerService)),
|
|
1037
|
+
__decorateParam(2, (0, _nestjs_common.Inject)(RequestContextService)),
|
|
1038
|
+
__decorateParam(3, (0, _nestjs_common.Inject)(AuthService)),
|
|
1039
|
+
__decorateParam(4, (0, _nestjs_common.Inject)(MastraThrottleGuard)),
|
|
892
1040
|
__decorateMetadata("design:paramtypes", [
|
|
893
|
-
Object,
|
|
894
1041
|
Object,
|
|
895
1042
|
typeof RouteHandlerService === "undefined" ? Object : RouteHandlerService,
|
|
896
1043
|
typeof RequestContextService === "undefined" ? Object : RequestContextService,
|
|
@@ -10853,18 +11000,36 @@ let MastraController = class MastraController {
|
|
|
10853
11000
|
options;
|
|
10854
11001
|
routeHandler;
|
|
10855
11002
|
requestContext;
|
|
10856
|
-
|
|
11003
|
+
customRoutes;
|
|
11004
|
+
authService;
|
|
11005
|
+
constructor(options, routeHandler, requestContext, customRoutes, authService) {
|
|
10857
11006
|
this.options = options;
|
|
10858
11007
|
this.routeHandler = routeHandler;
|
|
10859
11008
|
this.requestContext = requestContext;
|
|
11009
|
+
this.customRoutes = customRoutes;
|
|
11010
|
+
this.authService = authService;
|
|
10860
11011
|
}
|
|
10861
11012
|
/**
|
|
10862
11013
|
* Catch-all handler that matches incoming requests to Mastra routes.
|
|
10863
11014
|
*/
|
|
10864
|
-
async handleRequest(req,
|
|
11015
|
+
async handleRequest(req, res) {
|
|
10865
11016
|
const path = req.path;
|
|
10866
11017
|
const method = req.method.toUpperCase();
|
|
10867
11018
|
const routePath = getMastraRoutePath(path, this.options.prefix);
|
|
11019
|
+
if (!routePath || !this.routeHandler.matchRoute(method, routePath)) {
|
|
11020
|
+
const requestContext = this.requestContext.requestContext;
|
|
11021
|
+
const authenticate = async (requiresAuth) => {
|
|
11022
|
+
if (!this.authService.isEnabled()) return;
|
|
11023
|
+
const user = await this.authService.authenticate(req, {
|
|
11024
|
+
requestContext,
|
|
11025
|
+
response: res,
|
|
11026
|
+
requiresAuth,
|
|
11027
|
+
customRoute: true
|
|
11028
|
+
});
|
|
11029
|
+
if (user !== void 0) this.requestContext.setUser(user);
|
|
11030
|
+
};
|
|
11031
|
+
if (await this.customRoutes.handle(req, res, requestContext, authenticate)) return;
|
|
11032
|
+
}
|
|
10868
11033
|
if (!routePath) throw new _nestjs_common.NotFoundException(`Route not found: ${method} ${path}`);
|
|
10869
11034
|
if (routePath.includes("//")) throw new _nestjs_common.NotFoundException(`Route not found: ${method} ${path}`);
|
|
10870
11035
|
const matchResult = this.routeHandler.matchRoute(method, routePath);
|
|
@@ -10943,10 +11108,14 @@ MastraController = __decorate([
|
|
|
10943
11108
|
__decorateParam(0, (0, _nestjs_common.Inject)(MASTRA_OPTIONS)),
|
|
10944
11109
|
__decorateParam(1, (0, _nestjs_common.Inject)(RouteHandlerService)),
|
|
10945
11110
|
__decorateParam(2, (0, _nestjs_common.Inject)(RequestContextService)),
|
|
11111
|
+
__decorateParam(3, (0, _nestjs_common.Inject)(CustomRouteService)),
|
|
11112
|
+
__decorateParam(4, (0, _nestjs_common.Inject)(AuthService)),
|
|
10946
11113
|
__decorateMetadata("design:paramtypes", [
|
|
10947
11114
|
Object,
|
|
10948
11115
|
typeof RouteHandlerService === "undefined" ? Object : RouteHandlerService,
|
|
10949
|
-
typeof RequestContextService === "undefined" ? Object : RequestContextService
|
|
11116
|
+
typeof RequestContextService === "undefined" ? Object : RequestContextService,
|
|
11117
|
+
typeof CustomRouteService === "undefined" ? Object : CustomRouteService,
|
|
11118
|
+
typeof AuthService === "undefined" ? Object : AuthService
|
|
10950
11119
|
])
|
|
10951
11120
|
], MastraController);
|
|
10952
11121
|
//#endregion
|
|
@@ -11107,7 +11276,7 @@ let MastraAuthGuard = _MastraAuthGuard = class MastraAuthGuard {
|
|
|
11107
11276
|
if (this.reflector.getAllAndOverride("isPublic", [context.getHandler(), context.getClass()])) return true;
|
|
11108
11277
|
const request = context.switchToHttp().getRequest();
|
|
11109
11278
|
try {
|
|
11110
|
-
await this.authService.authenticate(request);
|
|
11279
|
+
await this.authService.authenticate(request, { response: context.switchToHttp().getResponse() });
|
|
11111
11280
|
return true;
|
|
11112
11281
|
} catch (error) {
|
|
11113
11282
|
this.logger.error(`Authentication error: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -11321,6 +11490,7 @@ let MastraModule = _MastraModule = class MastraModule {
|
|
|
11321
11490
|
RequestContextService,
|
|
11322
11491
|
ShutdownService,
|
|
11323
11492
|
AuthService,
|
|
11493
|
+
CustomRouteService,
|
|
11324
11494
|
BodyLimitMiddleware,
|
|
11325
11495
|
JsonBodyMiddleware,
|
|
11326
11496
|
MastraAuthGuard,
|
|
@@ -11395,6 +11565,7 @@ let MastraModule = _MastraModule = class MastraModule {
|
|
|
11395
11565
|
RequestContextService,
|
|
11396
11566
|
ShutdownService,
|
|
11397
11567
|
AuthService,
|
|
11568
|
+
CustomRouteService,
|
|
11398
11569
|
BodyLimitMiddleware,
|
|
11399
11570
|
JsonBodyMiddleware,
|
|
11400
11571
|
MastraAuthGuard,
|
|
@@ -11433,6 +11604,12 @@ Object.defineProperty(exports, "BodyLimitMiddleware", {
|
|
|
11433
11604
|
return BodyLimitMiddleware;
|
|
11434
11605
|
}
|
|
11435
11606
|
});
|
|
11607
|
+
Object.defineProperty(exports, "CustomRouteService", {
|
|
11608
|
+
enumerable: true,
|
|
11609
|
+
get: function() {
|
|
11610
|
+
return CustomRouteService;
|
|
11611
|
+
}
|
|
11612
|
+
});
|
|
11436
11613
|
Object.defineProperty(exports, "JsonBodyMiddleware", {
|
|
11437
11614
|
enumerable: true,
|
|
11438
11615
|
get: function() {
|