@nest-boot/auth 7.1.0 → 7.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.
- package/dist/auth.interceptor.d.ts +19 -0
- package/dist/auth.interceptor.js +97 -0
- package/dist/auth.interceptor.js.map +1 -0
- package/dist/auth.module.js +5 -2
- package/dist/auth.module.js.map +1 -1
- package/dist/auth.transaction-context.d.ts +11 -0
- package/dist/auth.transaction-context.js +28 -0
- package/dist/auth.transaction-context.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +3 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { EntityManager } from "@mikro-orm/core";
|
|
2
|
+
import { type CallHandler, type ExecutionContext, type NestInterceptor } from "@nestjs/common";
|
|
3
|
+
import { Request, Response } from "express";
|
|
4
|
+
import { Observable } from "rxjs";
|
|
5
|
+
import { AuthTransactionContext } from "./auth.transaction-context";
|
|
6
|
+
export declare class AuthInterceptor implements NestInterceptor {
|
|
7
|
+
protected readonly em: EntityManager;
|
|
8
|
+
constructor(em: EntityManager);
|
|
9
|
+
getRequest(context: ExecutionContext): Promise<Request>;
|
|
10
|
+
getResponse(context: ExecutionContext): Promise<Response>;
|
|
11
|
+
/**
|
|
12
|
+
* 扩展事务上下文
|
|
13
|
+
* 子类可以重写此方法来添加自定义的上下文信息
|
|
14
|
+
*/
|
|
15
|
+
extendTransactionContext(transactionContext: AuthTransactionContext, executionContext: ExecutionContext): void | Promise<void>;
|
|
16
|
+
private setTransactionAuthContext;
|
|
17
|
+
private interceptAsync;
|
|
18
|
+
intercept<T>(executionContext: ExecutionContext, next: CallHandler<T>): Observable<T>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
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;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.AuthInterceptor = void 0;
|
|
13
|
+
const core_1 = require("@mikro-orm/core");
|
|
14
|
+
const common_1 = require("@nestjs/common");
|
|
15
|
+
const rxjs_1 = require("rxjs");
|
|
16
|
+
const auth_transaction_context_1 = require("./auth.transaction-context");
|
|
17
|
+
let AuthInterceptor = class AuthInterceptor {
|
|
18
|
+
constructor(em) {
|
|
19
|
+
this.em = em;
|
|
20
|
+
}
|
|
21
|
+
async getRequest(context) {
|
|
22
|
+
if (context.getType() === "graphql") {
|
|
23
|
+
return context.getArgByIndex(2).req;
|
|
24
|
+
}
|
|
25
|
+
return await context.switchToHttp().getRequest();
|
|
26
|
+
}
|
|
27
|
+
async getResponse(context) {
|
|
28
|
+
if (context.getType() === "graphql") {
|
|
29
|
+
return context.getArgByIndex(2).req.res;
|
|
30
|
+
}
|
|
31
|
+
return await context.switchToHttp().getResponse();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 扩展事务上下文
|
|
35
|
+
* 子类可以重写此方法来添加自定义的上下文信息
|
|
36
|
+
*/
|
|
37
|
+
extendTransactionContext(
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
39
|
+
transactionContext,
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
41
|
+
executionContext) {
|
|
42
|
+
//
|
|
43
|
+
}
|
|
44
|
+
async setTransactionAuthContext(executionContext, knex) {
|
|
45
|
+
if (!knex) {
|
|
46
|
+
throw new Error("Knex is not found in transaction context");
|
|
47
|
+
}
|
|
48
|
+
const res = await this.getResponse(executionContext);
|
|
49
|
+
const user = res.locals.user;
|
|
50
|
+
const session = res.locals.session;
|
|
51
|
+
if (user && session) {
|
|
52
|
+
const transactionContext = new auth_transaction_context_1.AuthTransactionContext()
|
|
53
|
+
.set("user_id", user.id)
|
|
54
|
+
.set("user_name", user.name)
|
|
55
|
+
.set("user_email", user.email)
|
|
56
|
+
.set("session_id", session.id)
|
|
57
|
+
.set("session_token", session.token)
|
|
58
|
+
.set("session_expires_at", session.expiresAt.toISOString())
|
|
59
|
+
.set("session_ip_address", session.ipAddress ?? "")
|
|
60
|
+
.set("session_user_agent", session.userAgent ?? "");
|
|
61
|
+
await this.extendTransactionContext(transactionContext, executionContext);
|
|
62
|
+
await knex.raw([
|
|
63
|
+
/* SQL */ `SET LOCAL ROLE authenticated;`,
|
|
64
|
+
transactionContext.toSQL(),
|
|
65
|
+
].join("\n"));
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
await knex.raw(/* SQL */ `SET LOCAL ROLE anonymous;`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async interceptAsync(executionContext) {
|
|
72
|
+
// 检查是否已在事务中
|
|
73
|
+
const knex = this.em.getTransactionContext();
|
|
74
|
+
if (knex) {
|
|
75
|
+
// 已在事务中,直接设置认证上下文
|
|
76
|
+
await this.setTransactionAuthContext(executionContext, knex);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
// 不在事务中,启动一个新事务
|
|
80
|
+
await this.em.transactional(async (em) => {
|
|
81
|
+
await this.setTransactionAuthContext(executionContext, em.getTransactionContext());
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
intercept(executionContext, next) {
|
|
86
|
+
if (["http", "graphql"].includes(executionContext.getType())) {
|
|
87
|
+
return (0, rxjs_1.from)(this.interceptAsync(executionContext)).pipe((0, rxjs_1.concatMap)(() => next.handle()));
|
|
88
|
+
}
|
|
89
|
+
return next.handle();
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
exports.AuthInterceptor = AuthInterceptor;
|
|
93
|
+
exports.AuthInterceptor = AuthInterceptor = __decorate([
|
|
94
|
+
(0, common_1.Injectable)(),
|
|
95
|
+
__metadata("design:paramtypes", [core_1.EntityManager])
|
|
96
|
+
], AuthInterceptor);
|
|
97
|
+
//# sourceMappingURL=auth.interceptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.interceptor.js","sourceRoot":"","sources":["../src/auth.interceptor.ts"],"names":[],"mappings":"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"}
|
package/dist/auth.module.js
CHANGED
|
@@ -49,8 +49,11 @@ let AuthModule = class AuthModule extends auth_module_definition_1.ConfigurableM
|
|
|
49
49
|
proxy.forRoutes(...(this.options.middleware?.includeRoutes ?? ["*"]));
|
|
50
50
|
}
|
|
51
51
|
onModuleInit() {
|
|
52
|
-
const
|
|
53
|
-
|
|
52
|
+
const httpAdapter = this.adapterHost.httpAdapter;
|
|
53
|
+
if (httpAdapter) {
|
|
54
|
+
const app = httpAdapter.getInstance();
|
|
55
|
+
app.all(this.options.basePath ?? "/api/auth/{*any}", (0, node_1.toNodeHandler)(this.auth));
|
|
56
|
+
}
|
|
54
57
|
}
|
|
55
58
|
};
|
|
56
59
|
exports.AuthModule = AuthModule;
|
package/dist/auth.module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.module.js","sourceRoot":"","sources":["../src/auth.module.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,0CAA2C;AAC3C,2CAOwB;AACxB,uCAA+C;AAC/C,6CAA+C;AAC/C,2CAAiD;AAGjD,oEAA+D;AAC/D,qDAA8C;AAC9C,uDAAmD;AACnD,qEAGkC;AAClC,iDAA6C;AAG7C,MAAM,YAAY,GAAa;IAC7B,OAAO,EAAE,2BAAU;IACnB,MAAM,EAAE,CAAC,6CAAoB,EAAE,eAAQ,CAAC;IACxC,UAAU,EAAE,CAAC,OAA0B,EAAE,GAAa,EAAE,EAAE,CACxD,IAAA,wBAAU,EAAC;QACT,GAAG,OAAO;QACV,QAAQ,EAAE,IAAA,mCAAe,EAAC;YACxB,GAAG;YACH,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC3B,CAAC;KACH,CAAC;CACL,CAAC;AAMK,IAAM,UAAU,GAAhB,MAAM,UACX,SAAQ,gDAAuB;IAG/B,YACmB,WAA4B,EAE5B,IAAU,EAEV,OAA0B;QAE3C,KAAK,EAAE,CAAC;QANS,gBAAW,GAAX,WAAW,CAAiB;QAE5B,SAAI,GAAJ,IAAI,CAAM;QAEV,YAAO,GAAP,OAAO,CAAmB;IAG7C,CAAC;IAED,SAAS,CAAC,QAA4B;QACpC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,gCAAc,CAAC,CAAC;QAE7C,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,aAAa,EAAE,CAAC;YAC3C,KAAK,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;QAC1D,CAAC;QAED,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,aAAa,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,YAAY;QACV,MAAM,
|
|
1
|
+
{"version":3,"file":"auth.module.js","sourceRoot":"","sources":["../src/auth.module.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,0CAA2C;AAC3C,2CAOwB;AACxB,uCAA+C;AAC/C,6CAA+C;AAC/C,2CAAiD;AAGjD,oEAA+D;AAC/D,qDAA8C;AAC9C,uDAAmD;AACnD,qEAGkC;AAClC,iDAA6C;AAG7C,MAAM,YAAY,GAAa;IAC7B,OAAO,EAAE,2BAAU;IACnB,MAAM,EAAE,CAAC,6CAAoB,EAAE,eAAQ,CAAC;IACxC,UAAU,EAAE,CAAC,OAA0B,EAAE,GAAa,EAAE,EAAE,CACxD,IAAA,wBAAU,EAAC;QACT,GAAG,OAAO;QACV,QAAQ,EAAE,IAAA,mCAAe,EAAC;YACxB,GAAG;YACH,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC3B,CAAC;KACH,CAAC;CACL,CAAC;AAMK,IAAM,UAAU,GAAhB,MAAM,UACX,SAAQ,gDAAuB;IAG/B,YACmB,WAA4B,EAE5B,IAAU,EAEV,OAA0B;QAE3C,KAAK,EAAE,CAAC;QANS,gBAAW,GAAX,WAAW,CAAiB;QAE5B,SAAI,GAAJ,IAAI,CAAM;QAEV,YAAO,GAAP,OAAO,CAAmB;IAG7C,CAAC;IAED,SAAS,CAAC,QAA4B;QACpC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,gCAAc,CAAC,CAAC;QAE7C,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,aAAa,EAAE,CAAC;YAC3C,KAAK,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;QAC1D,CAAC;QAED,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,aAAa,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,YAAY;QACV,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC;QAEjD,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,GAAG,GAAG,WAAW,CAAC,WAAW,EAAW,CAAC;YAE/C,GAAG,CAAC,GAAG,CACL,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,kBAAkB,EAC3C,IAAA,oBAAa,EAAC,IAAI,CAAC,IAAI,CAAC,CACzB,CAAC;QACJ,CAAC;IACH,CAAC;CACF,CAAA;AApCY,gCAAU;qBAAV,UAAU;IAJtB,IAAA,eAAM,EAAC;QACN,SAAS,EAAE,CAAC,YAAY,EAAE,0BAAW,CAAC;QACtC,OAAO,EAAE,CAAC,0BAAW,CAAC;KACvB,CAAC;IAOG,WAAA,IAAA,eAAM,EAAC,2BAAU,CAAC,CAAA;IAElB,WAAA,IAAA,eAAM,EAAC,6CAAoB,CAAC,CAAA;qCAHC,sBAAe;GALpC,UAAU,CAoCtB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type LowercaseLetter = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z";
|
|
2
|
+
type ValidChar = LowercaseLetter | "_";
|
|
3
|
+
type IsValidSnakeCase<S extends string> = S extends `${infer First}${infer Rest}` ? First extends ValidChar ? IsValidSnakeCase<Rest> : false : true;
|
|
4
|
+
type SnakeCase<S extends string> = S extends "" ? never : S extends `_${string}` | `${string}_` ? never : S extends `${string}__${string}` ? never : IsValidSnakeCase<S> extends true ? S : never;
|
|
5
|
+
export declare class AuthTransactionContext {
|
|
6
|
+
private readonly ctx;
|
|
7
|
+
set<S extends string>(key: SnakeCase<S>, value: string): this;
|
|
8
|
+
entries(): [string, string][];
|
|
9
|
+
toSQL(): string;
|
|
10
|
+
}
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AuthTransactionContext = void 0;
|
|
4
|
+
class AuthTransactionContext {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.ctx = new Map();
|
|
7
|
+
}
|
|
8
|
+
set(key, value) {
|
|
9
|
+
if (!/^[a-z]+(_[a-z]+)*$/.test(key)) {
|
|
10
|
+
throw new Error(`Key must only contain lowercase letters and underscores, cannot start/end with underscore, and cannot have consecutive underscores: ${key}`);
|
|
11
|
+
}
|
|
12
|
+
this.ctx.set(key, value);
|
|
13
|
+
return this;
|
|
14
|
+
}
|
|
15
|
+
entries() {
|
|
16
|
+
return Array.from(this.ctx.entries());
|
|
17
|
+
}
|
|
18
|
+
toSQL() {
|
|
19
|
+
return /* SQL */ `SELECT ${Array.from(this.ctx.entries())
|
|
20
|
+
.map(([key, value]) => {
|
|
21
|
+
const escapedValue = value.replace(/'/g, "''");
|
|
22
|
+
return /* SQL */ `set_config('auth.${key}', '${escapedValue}', true)`;
|
|
23
|
+
})
|
|
24
|
+
.join(",")};`;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.AuthTransactionContext = AuthTransactionContext;
|
|
28
|
+
//# sourceMappingURL=auth.transaction-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.transaction-context.js","sourceRoot":"","sources":["../src/auth.transaction-context.ts"],"names":[],"mappings":";;;AA+CA,MAAa,sBAAsB;IAAnC;QACmB,QAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;IAwBnD,CAAC;IAtBC,GAAG,CAAmB,GAAiB,EAAE,KAAa;QACpD,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CACb,uIAAuI,GAAG,EAAE,CAC7I,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,KAAK;QACH,OAAO,SAAS,CAAC,UAAU,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;aACtD,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;YACpB,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAC/C,OAAO,SAAS,CAAC,oBAAoB,GAAG,OAAO,YAAY,UAAU,CAAC;QACxE,CAAC,CAAC;aACD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IAClB,CAAC;CACF;AAzBD,wDAyBC"}
|