@lenne.tech/nest-server 11.6.2 → 11.7.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/config.env.js +19 -12
- package/dist/config.env.js.map +1 -1
- package/dist/core/common/helpers/filter.helper.d.ts +9 -9
- package/dist/core/common/helpers/filter.helper.js +2 -4
- package/dist/core/common/helpers/filter.helper.js.map +1 -1
- package/dist/core/common/helpers/gridfs.helper.js +3 -3
- package/dist/core/common/helpers/gridfs.helper.js.map +1 -1
- package/dist/core/common/interfaces/server-options.interface.d.ts +21 -3
- package/dist/core/common/services/crud.service.d.ts +16 -16
- package/dist/core/common/services/crud.service.js +1 -1
- package/dist/core/common/services/crud.service.js.map +1 -1
- package/dist/core/modules/auth/core-auth.controller.d.ts +1 -0
- package/dist/core/modules/auth/core-auth.controller.js +28 -2
- package/dist/core/modules/auth/core-auth.controller.js.map +1 -1
- package/dist/core/modules/auth/core-auth.module.js +14 -1
- package/dist/core/modules/auth/core-auth.module.js.map +1 -1
- package/dist/core/modules/auth/core-auth.resolver.d.ts +1 -0
- package/dist/core/modules/auth/core-auth.resolver.js +20 -2
- package/dist/core/modules/auth/core-auth.resolver.js.map +1 -1
- package/dist/core/modules/auth/exceptions/legacy-auth-disabled.exception.d.ts +4 -0
- package/dist/core/modules/auth/exceptions/legacy-auth-disabled.exception.js +17 -0
- package/dist/core/modules/auth/exceptions/legacy-auth-disabled.exception.js.map +1 -0
- package/dist/core/modules/auth/guards/legacy-auth-rate-limit.guard.d.ts +9 -0
- package/dist/core/modules/auth/guards/legacy-auth-rate-limit.guard.js +74 -0
- package/dist/core/modules/auth/guards/legacy-auth-rate-limit.guard.js.map +1 -0
- package/dist/core/modules/auth/interfaces/auth-provider.interface.d.ts +7 -0
- package/dist/core/modules/auth/interfaces/auth-provider.interface.js +5 -0
- package/dist/core/modules/auth/interfaces/auth-provider.interface.js.map +1 -0
- package/dist/core/modules/auth/interfaces/core-auth-user.interface.d.ts +1 -0
- package/dist/core/modules/auth/services/core-auth.service.d.ts +10 -1
- package/dist/core/modules/auth/services/core-auth.service.js +141 -9
- package/dist/core/modules/auth/services/core-auth.service.js.map +1 -1
- package/dist/core/modules/auth/services/legacy-auth-rate-limiter.service.d.ts +31 -0
- package/dist/core/modules/auth/services/legacy-auth-rate-limiter.service.js +153 -0
- package/dist/core/modules/auth/services/legacy-auth-rate-limiter.service.js.map +1 -0
- package/dist/core/modules/better-auth/better-auth-migration-status.model.d.ts +10 -0
- package/dist/core/modules/better-auth/better-auth-migration-status.model.js +57 -0
- package/dist/core/modules/better-auth/better-auth-migration-status.model.js.map +1 -0
- package/dist/core/modules/better-auth/better-auth-models.d.ts +0 -1
- package/dist/core/modules/better-auth/better-auth-models.js +0 -4
- package/dist/core/modules/better-auth/better-auth-models.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth-user.mapper.d.ts +33 -0
- package/dist/core/modules/better-auth/better-auth-user.mapper.js +443 -0
- package/dist/core/modules/better-auth/better-auth-user.mapper.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth.config.js +3 -0
- package/dist/core/modules/better-auth/better-auth.config.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth.module.d.ts +10 -2
- package/dist/core/modules/better-auth/better-auth.module.js +40 -52
- package/dist/core/modules/better-auth/better-auth.module.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth.resolver.d.ts +8 -12
- package/dist/core/modules/better-auth/better-auth.resolver.js +33 -351
- package/dist/core/modules/better-auth/better-auth.resolver.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth.service.d.ts +0 -1
- package/dist/core/modules/better-auth/better-auth.service.js +0 -3
- package/dist/core/modules/better-auth/better-auth.service.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth.types.d.ts +9 -8
- package/dist/core/modules/better-auth/better-auth.types.js +14 -3
- package/dist/core/modules/better-auth/better-auth.types.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth.controller.d.ts +67 -0
- package/dist/core/modules/better-auth/core-better-auth.controller.js +504 -0
- package/dist/core/modules/better-auth/core-better-auth.controller.js.map +1 -0
- package/dist/core/modules/better-auth/core-better-auth.resolver.d.ts +61 -0
- package/dist/core/modules/better-auth/core-better-auth.resolver.js +552 -0
- package/dist/core/modules/better-auth/core-better-auth.resolver.js.map +1 -0
- package/dist/core/modules/better-auth/index.d.ts +3 -0
- package/dist/core/modules/better-auth/index.js +3 -0
- package/dist/core/modules/better-auth/index.js.map +1 -1
- package/dist/core/modules/user/core-user.service.d.ts +7 -1
- package/dist/core/modules/user/core-user.service.js +57 -3
- package/dist/core/modules/user/core-user.service.js.map +1 -1
- package/dist/core/modules/user/interfaces/core-user-service-options.interface.d.ts +4 -0
- package/dist/core/modules/user/interfaces/core-user-service-options.interface.js +3 -0
- package/dist/core/modules/user/interfaces/core-user-service-options.interface.js.map +1 -0
- package/dist/core.module.d.ts +3 -0
- package/dist/core.module.js +132 -54
- package/dist/core.module.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/server/modules/auth/auth.resolver.js +2 -0
- package/dist/server/modules/auth/auth.resolver.js.map +1 -1
- package/dist/server/modules/better-auth/better-auth.controller.d.ts +10 -0
- package/dist/server/modules/better-auth/better-auth.controller.js +36 -0
- package/dist/server/modules/better-auth/better-auth.controller.js.map +1 -0
- package/dist/server/modules/better-auth/better-auth.module.d.ts +9 -0
- package/dist/server/modules/better-auth/better-auth.module.js +44 -0
- package/dist/server/modules/better-auth/better-auth.module.js.map +1 -0
- package/dist/server/modules/better-auth/better-auth.resolver.d.ts +47 -0
- package/dist/server/modules/better-auth/better-auth.resolver.js +234 -0
- package/dist/server/modules/better-auth/better-auth.resolver.js.map +1 -0
- package/dist/server/modules/file/file-info.model.d.ts +71 -3
- package/dist/server/modules/user/user.model.d.ts +169 -3
- package/dist/server/modules/user/user.service.d.ts +3 -1
- package/dist/server/modules/user/user.service.js +7 -3
- package/dist/server/modules/user/user.service.js.map +1 -1
- package/dist/server/server.module.js +6 -1
- package/dist/server/server.module.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +20 -29
- package/src/config.env.ts +34 -13
- package/src/core/common/helpers/filter.helper.ts +15 -17
- package/src/core/common/helpers/gridfs.helper.ts +5 -5
- package/src/core/common/interfaces/server-options.interface.ts +222 -14
- package/src/core/common/services/crud.service.ts +22 -22
- package/src/core/modules/auth/core-auth.controller.ts +93 -5
- package/src/core/modules/auth/core-auth.module.ts +15 -1
- package/src/core/modules/auth/core-auth.resolver.ts +70 -2
- package/src/core/modules/auth/exceptions/legacy-auth-disabled.exception.ts +35 -0
- package/src/core/modules/auth/guards/legacy-auth-rate-limit.guard.ts +109 -0
- package/src/core/modules/auth/interfaces/auth-provider.interface.ts +86 -0
- package/src/core/modules/auth/interfaces/core-auth-user.interface.ts +6 -0
- package/src/core/modules/auth/services/core-auth.service.ts +245 -6
- package/src/core/modules/auth/services/legacy-auth-rate-limiter.service.ts +283 -0
- package/src/core/modules/better-auth/INTEGRATION-CHECKLIST.md +254 -0
- package/src/core/modules/better-auth/README.md +698 -54
- package/src/core/modules/better-auth/better-auth-migration-status.model.ts +73 -0
- package/src/core/modules/better-auth/better-auth-models.ts +0 -3
- package/src/core/modules/better-auth/better-auth-user.mapper.ts +805 -0
- package/src/core/modules/better-auth/better-auth.config.ts +5 -0
- package/src/core/modules/better-auth/better-auth.module.ts +107 -66
- package/src/core/modules/better-auth/better-auth.resolver.ts +88 -553
- package/src/core/modules/better-auth/better-auth.service.ts +0 -9
- package/src/core/modules/better-auth/better-auth.types.ts +25 -10
- package/src/core/modules/better-auth/core-better-auth.controller.ts +646 -0
- package/src/core/modules/better-auth/core-better-auth.resolver.ts +730 -0
- package/src/core/modules/better-auth/index.ts +9 -1
- package/src/core/modules/user/core-user.service.ts +131 -4
- package/src/core/modules/user/interfaces/core-user-service-options.interface.ts +15 -0
- package/src/core.module.ts +257 -74
- package/src/index.ts +5 -0
- package/src/server/modules/auth/auth.resolver.ts +8 -0
- package/src/server/modules/better-auth/better-auth.controller.ts +41 -0
- package/src/server/modules/better-auth/better-auth.module.ts +88 -0
- package/src/server/modules/better-auth/better-auth.resolver.ts +210 -0
- package/src/server/modules/user/user.service.ts +4 -2
- package/src/server/server.module.ts +10 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lenne.tech/nest-server",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.7.1",
|
|
4
4
|
"description": "Modern, fast, powerful Node.js web framework in TypeScript based on Nest with a GraphQL API and a connection to MongoDB (or other databases).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"node",
|
|
@@ -77,13 +77,14 @@
|
|
|
77
77
|
"node": ">= 20"
|
|
78
78
|
},
|
|
79
79
|
"dependencies": {
|
|
80
|
-
"@apollo/server": "
|
|
81
|
-
"@
|
|
80
|
+
"@apollo/server": "5.2.0",
|
|
81
|
+
"@as-integrations/express5": "1.1.2",
|
|
82
|
+
"@better-auth/passkey": "1.4.8-beta.4",
|
|
82
83
|
"@getbrevo/brevo": "3.0.1",
|
|
83
|
-
"@nestjs/apollo": "13.
|
|
84
|
+
"@nestjs/apollo": "13.2.3",
|
|
84
85
|
"@nestjs/common": "11.1.9",
|
|
85
86
|
"@nestjs/core": "11.1.9",
|
|
86
|
-
"@nestjs/graphql": "13.2.
|
|
87
|
+
"@nestjs/graphql": "13.2.3",
|
|
87
88
|
"@nestjs/jwt": "11.0.2",
|
|
88
89
|
"@nestjs/mongoose": "11.0.4",
|
|
89
90
|
"@nestjs/passport": "11.0.5",
|
|
@@ -92,16 +93,16 @@
|
|
|
92
93
|
"@nestjs/swagger": "11.2.3",
|
|
93
94
|
"@nestjs/terminus": "11.0.0",
|
|
94
95
|
"@nestjs/websockets": "11.1.9",
|
|
95
|
-
"@thallesp/nestjs-better-auth": "2.2.0",
|
|
96
96
|
"apollo-server-core": "3.13.0",
|
|
97
97
|
"bcrypt": "6.0.0",
|
|
98
|
-
"better-auth": "1.4.
|
|
98
|
+
"better-auth": "1.4.8-beta.4",
|
|
99
99
|
"class-transformer": "0.5.1",
|
|
100
100
|
"class-validator": "0.14.3",
|
|
101
101
|
"compression": "1.8.1",
|
|
102
102
|
"cookie-parser": "1.4.7",
|
|
103
103
|
"dotenv": "17.2.3",
|
|
104
104
|
"ejs": "3.1.10",
|
|
105
|
+
"express": "5.1.0",
|
|
105
106
|
"graphql": "16.12.0",
|
|
106
107
|
"graphql-query-complexity": "1.1.0",
|
|
107
108
|
"graphql-subscriptions": "3.0.0",
|
|
@@ -110,7 +111,7 @@
|
|
|
110
111
|
"json-to-graphql-query": "2.3.0",
|
|
111
112
|
"lodash": "4.17.21",
|
|
112
113
|
"mongodb": "7.0.0",
|
|
113
|
-
"mongoose": "
|
|
114
|
+
"mongoose": "9.0.2",
|
|
114
115
|
"multer": "2.0.2",
|
|
115
116
|
"node-mailjet": "6.0.11",
|
|
116
117
|
"nodemailer": "7.0.11",
|
|
@@ -119,7 +120,6 @@
|
|
|
119
120
|
"reflect-metadata": "0.2.2",
|
|
120
121
|
"rfdc": "1.4.1",
|
|
121
122
|
"rxjs": "7.8.2",
|
|
122
|
-
"ts-jest": "29.4.6",
|
|
123
123
|
"yuml-diagram": "1.2.0"
|
|
124
124
|
},
|
|
125
125
|
"devDependencies": {
|
|
@@ -129,23 +129,23 @@
|
|
|
129
129
|
"@nestjs/schematics": "11.0.9",
|
|
130
130
|
"@nestjs/testing": "11.1.9",
|
|
131
131
|
"@swc/cli": "0.7.9",
|
|
132
|
-
"@swc/core": "1.15.
|
|
132
|
+
"@swc/core": "1.15.7",
|
|
133
133
|
"@types/compression": "1.8.1",
|
|
134
134
|
"@types/cookie-parser": "1.4.10",
|
|
135
135
|
"@types/ejs": "3.1.5",
|
|
136
136
|
"@types/express": "4.17.21",
|
|
137
137
|
"@types/lodash": "4.17.21",
|
|
138
138
|
"@types/multer": "2.0.0",
|
|
139
|
-
"@types/node": "25.0.
|
|
139
|
+
"@types/node": "25.0.3",
|
|
140
140
|
"@types/nodemailer": "7.0.4",
|
|
141
141
|
"@types/passport": "1.0.17",
|
|
142
142
|
"@types/supertest": "6.0.3",
|
|
143
|
-
"@typescript-eslint/eslint-plugin": "8.
|
|
144
|
-
"@typescript-eslint/parser": "8.
|
|
145
|
-
"@vitest/coverage-v8": "4.0.
|
|
146
|
-
"@vitest/ui": "4.0.
|
|
143
|
+
"@typescript-eslint/eslint-plugin": "8.50.0",
|
|
144
|
+
"@typescript-eslint/parser": "8.50.0",
|
|
145
|
+
"@vitest/coverage-v8": "4.0.16",
|
|
146
|
+
"@vitest/ui": "4.0.16",
|
|
147
147
|
"ansi-colors": "4.1.3",
|
|
148
|
-
"eslint": "9.39.
|
|
148
|
+
"eslint": "9.39.2",
|
|
149
149
|
"eslint-config-prettier": "10.1.8",
|
|
150
150
|
"eslint-plugin-unused-imports": "4.3.0",
|
|
151
151
|
"find-file-up": "2.0.1",
|
|
@@ -162,28 +162,19 @@
|
|
|
162
162
|
"pretty-quick": "4.2.2",
|
|
163
163
|
"rimraf": "6.1.2",
|
|
164
164
|
"supertest": "7.1.4",
|
|
165
|
+
"ts-jest": "29.4.6",
|
|
165
166
|
"ts-loader": "9.5.4",
|
|
166
167
|
"ts-morph": "27.0.2",
|
|
167
168
|
"ts-node": "10.9.2",
|
|
168
169
|
"tsconfig-paths": "4.2.0",
|
|
169
170
|
"typescript": "5.9.3",
|
|
170
171
|
"unplugin-swc": "1.5.9",
|
|
171
|
-
"vite": "7.
|
|
172
|
+
"vite": "7.3.0",
|
|
172
173
|
"vite-plugin-node": "7.0.0",
|
|
173
|
-
"vite-tsconfig-paths": "
|
|
174
|
-
"vitest": "4.0.
|
|
174
|
+
"vite-tsconfig-paths": "6.0.3",
|
|
175
|
+
"vitest": "4.0.16",
|
|
175
176
|
"yalc": "1.0.0-pre.53"
|
|
176
177
|
},
|
|
177
|
-
"overrides": {
|
|
178
|
-
"@lykmapipo/common": {
|
|
179
|
-
"flat": "5.0.2",
|
|
180
|
-
"mime": "2.6.0"
|
|
181
|
-
},
|
|
182
|
-
"better-auth": {
|
|
183
|
-
"mongodb": "7.0.0"
|
|
184
|
-
},
|
|
185
|
-
"ts-morph": "27.0.2"
|
|
186
|
-
},
|
|
187
178
|
"jest": {
|
|
188
179
|
"collectCoverage": true,
|
|
189
180
|
"coverageDirectory": "../coverage",
|
package/src/config.env.ts
CHANGED
|
@@ -14,6 +14,16 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
14
14
|
// Development environment
|
|
15
15
|
// ===========================================================================
|
|
16
16
|
development: {
|
|
17
|
+
// Legacy Auth endpoint controls (for migration to BetterAuth)
|
|
18
|
+
// Set to false after all users have migrated to BetterAuth (IAM)
|
|
19
|
+
// See: .claude/rules/module-deprecation.md
|
|
20
|
+
auth: {
|
|
21
|
+
legacyEndpoints: {
|
|
22
|
+
enabled: true, // Set to false to disable legacy auth endpoints (returns HTTP 410)
|
|
23
|
+
// graphql: true, // Optionally disable only GraphQL endpoints
|
|
24
|
+
// rest: true, // Optionally disable only REST endpoints
|
|
25
|
+
},
|
|
26
|
+
},
|
|
17
27
|
automaticObjectIdFiltering: true,
|
|
18
28
|
betterAuth: {
|
|
19
29
|
basePath: '/iam',
|
|
@@ -23,9 +33,6 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
23
33
|
enabled: true,
|
|
24
34
|
expiresIn: '15m',
|
|
25
35
|
},
|
|
26
|
-
legacyPassword: {
|
|
27
|
-
enabled: true,
|
|
28
|
-
},
|
|
29
36
|
passkey: {
|
|
30
37
|
enabled: false,
|
|
31
38
|
origin: 'http://localhost:3000',
|
|
@@ -165,27 +172,34 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
165
172
|
// Local environment
|
|
166
173
|
// ===========================================================================
|
|
167
174
|
local: {
|
|
175
|
+
// Legacy Auth endpoint controls (for migration to BetterAuth)
|
|
176
|
+
// Set to false after all users have migrated to BetterAuth (IAM)
|
|
177
|
+
// See: .claude/rules/module-deprecation.md
|
|
178
|
+
auth: {
|
|
179
|
+
legacyEndpoints: {
|
|
180
|
+
enabled: true, // Set to false to disable legacy auth endpoints (returns HTTP 410)
|
|
181
|
+
// graphql: true, // Optionally disable only GraphQL endpoints
|
|
182
|
+
// rest: true, // Optionally disable only REST endpoints
|
|
183
|
+
},
|
|
184
|
+
},
|
|
168
185
|
automaticObjectIdFiltering: true,
|
|
169
186
|
betterAuth: {
|
|
170
187
|
basePath: '/iam',
|
|
171
188
|
baseUrl: 'http://localhost:3000',
|
|
172
|
-
|
|
189
|
+
enabled: true, // Enable for Scenario 2 (Legacy + IAM) testing
|
|
173
190
|
jwt: {
|
|
174
191
|
enabled: true,
|
|
175
192
|
expiresIn: '15m',
|
|
176
193
|
},
|
|
177
|
-
legacyPassword: {
|
|
178
|
-
enabled: true,
|
|
179
|
-
},
|
|
180
194
|
passkey: {
|
|
181
|
-
enabled:
|
|
195
|
+
enabled: true,
|
|
182
196
|
origin: 'http://localhost:3000',
|
|
183
197
|
rpId: 'localhost',
|
|
184
198
|
rpName: 'Nest Server Local',
|
|
185
199
|
},
|
|
186
200
|
rateLimit: {
|
|
187
201
|
enabled: true,
|
|
188
|
-
max:
|
|
202
|
+
max: 100, // Higher limit for local testing
|
|
189
203
|
message: 'Too many requests, please try again later.',
|
|
190
204
|
skipEndpoints: ['/session', '/callback'],
|
|
191
205
|
strictEndpoints: ['/sign-in', '/sign-up', '/forgot-password', '/reset-password'],
|
|
@@ -211,7 +225,7 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
211
225
|
},
|
|
212
226
|
twoFactor: {
|
|
213
227
|
appName: 'Nest Server Local',
|
|
214
|
-
enabled:
|
|
228
|
+
enabled: true,
|
|
215
229
|
},
|
|
216
230
|
},
|
|
217
231
|
compression: true,
|
|
@@ -327,6 +341,16 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
327
341
|
// Production environment
|
|
328
342
|
// ===========================================================================
|
|
329
343
|
production: {
|
|
344
|
+
// Legacy Auth endpoint controls (for migration to BetterAuth)
|
|
345
|
+
// Set to false after all users have migrated to BetterAuth (IAM)
|
|
346
|
+
// See: .claude/rules/module-deprecation.md
|
|
347
|
+
auth: {
|
|
348
|
+
legacyEndpoints: {
|
|
349
|
+
enabled: process.env.LEGACY_AUTH_ENABLED !== 'false', // Disable via env var
|
|
350
|
+
// graphql: true, // Optionally disable only GraphQL endpoints
|
|
351
|
+
// rest: true, // Optionally disable only REST endpoints
|
|
352
|
+
},
|
|
353
|
+
},
|
|
330
354
|
automaticObjectIdFiltering: true,
|
|
331
355
|
betterAuth: {
|
|
332
356
|
basePath: '/iam',
|
|
@@ -336,9 +360,6 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
336
360
|
enabled: true,
|
|
337
361
|
expiresIn: '15m',
|
|
338
362
|
},
|
|
339
|
-
legacyPassword: {
|
|
340
|
-
enabled: true,
|
|
341
|
-
},
|
|
342
363
|
passkey: {
|
|
343
364
|
enabled: false,
|
|
344
365
|
origin: process.env.BETTER_AUTH_URL || 'https://example.com',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { QueryFilter, QueryOptions } from 'mongoose';
|
|
2
2
|
|
|
3
3
|
import { FilterArgs } from '../args/filter.args';
|
|
4
4
|
import { ComparisonOperatorEnum } from '../enums/comparison-operator.enum';
|
|
@@ -19,14 +19,14 @@ export class Filter {
|
|
|
19
19
|
* Convert filter arguments to a query array
|
|
20
20
|
* @param filterArgs
|
|
21
21
|
*/
|
|
22
|
-
public static convertFilterArgsToQuery<T = any
|
|
23
|
-
return convertFilterArgsToQuery(filterArgs);
|
|
22
|
+
public static convertFilterArgsToQuery<T = Record<string, any>>(filterArgs: Partial<FilterArgs>): [T, QueryOptions] {
|
|
23
|
+
return convertFilterArgsToQuery<T>(filterArgs);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* Generate filter query
|
|
28
28
|
*/
|
|
29
|
-
public static generateFilterQuery<T = any>(filter?: Partial<FilterInput>): any |
|
|
29
|
+
public static generateFilterQuery<T = any>(filter?: Partial<FilterInput>): any | QueryFilter<T> {
|
|
30
30
|
return generateFilterQuery(filter);
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -41,31 +41,29 @@ export class Filter {
|
|
|
41
41
|
/**
|
|
42
42
|
* Convert filter arguments to a query array
|
|
43
43
|
*/
|
|
44
|
-
export function convertFilterArgsToQuery<T = any
|
|
45
|
-
return [generateFilterQuery(filterArgs?.filter), generateFindOptions(filterArgs)];
|
|
44
|
+
export function convertFilterArgsToQuery<T = Record<string, any>>(filterArgs: Partial<FilterArgs>): [T, QueryOptions] {
|
|
45
|
+
return [generateFilterQuery(filterArgs?.filter) as T, generateFindOptions(filterArgs)];
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
49
|
* Merge FilterArgs and FilterQueries
|
|
50
50
|
*/
|
|
51
|
-
export function filterMerge<T =
|
|
51
|
+
export function filterMerge<T = Record<string, any>>(
|
|
52
52
|
filterArgs: Partial<FilterArgs>,
|
|
53
|
-
filterQuery: Partial<
|
|
53
|
+
filterQuery: Partial<T>,
|
|
54
54
|
options?: {
|
|
55
55
|
operator?: '$and' | '$nor' | '$or';
|
|
56
56
|
queryOptions?: Partial<QueryOptions>;
|
|
57
57
|
samples?: number;
|
|
58
58
|
},
|
|
59
|
-
): { filterQuery:
|
|
59
|
+
): { filterQuery: T; queryOptions?: QueryOptions; samples?: number } {
|
|
60
60
|
const config = {
|
|
61
61
|
operator: '$and',
|
|
62
62
|
...options,
|
|
63
63
|
};
|
|
64
64
|
const converted = convertFilterArgsToQuery(filterArgs);
|
|
65
65
|
return {
|
|
66
|
-
filterQuery: (converted[0]
|
|
67
|
-
? { [config.operator]: [converted[0], filterQuery || {}] }
|
|
68
|
-
: filterQuery) as FilterQuery<T>,
|
|
66
|
+
filterQuery: (converted[0] ? { [config.operator]: [converted[0], filterQuery || {}] } : filterQuery) as T,
|
|
69
67
|
queryOptions: converted[1] || config.queryOptions ? { ...converted[1], ...config.queryOptions } : undefined,
|
|
70
68
|
samples: config.samples,
|
|
71
69
|
};
|
|
@@ -76,18 +74,18 @@ export function filterMerge<T = unknown>(
|
|
|
76
74
|
*/
|
|
77
75
|
export function findFilter(options?: {
|
|
78
76
|
conditions?: Record<string, any>[];
|
|
79
|
-
filterOptions?:
|
|
77
|
+
filterOptions?: QueryFilter<any>;
|
|
80
78
|
id?: any;
|
|
81
79
|
ids?: any[];
|
|
82
80
|
type?: '$and' | '$nor' | '$or';
|
|
83
|
-
}):
|
|
81
|
+
}): QueryFilter<any> {
|
|
84
82
|
const config = {
|
|
85
83
|
type: '$and',
|
|
86
84
|
...options,
|
|
87
85
|
};
|
|
88
86
|
|
|
89
87
|
// Init filter Option
|
|
90
|
-
let filterOptions:
|
|
88
|
+
let filterOptions: QueryFilter<any> = config?.filterOptions;
|
|
91
89
|
|
|
92
90
|
// Check where condition
|
|
93
91
|
if (!filterOptions) {
|
|
@@ -120,7 +118,7 @@ export function findFilter(options?: {
|
|
|
120
118
|
}
|
|
121
119
|
|
|
122
120
|
// Filter falsy values
|
|
123
|
-
filterOptions[config.type] = filterOptions[config.type].filter(value => value);
|
|
121
|
+
filterOptions[config.type] = filterOptions[config.type].filter((value) => value);
|
|
124
122
|
|
|
125
123
|
// Optimizations
|
|
126
124
|
if (!filterOptions[config.type].length) {
|
|
@@ -143,7 +141,7 @@ export function findFilter(options?: {
|
|
|
143
141
|
export function generateFilterQuery<T = any>(
|
|
144
142
|
filter?: Partial<FilterInput>,
|
|
145
143
|
options?: { automaticObjectIdFiltering?: boolean },
|
|
146
|
-
): any |
|
|
144
|
+
): any | QueryFilter<T> {
|
|
147
145
|
// Check filter
|
|
148
146
|
if (!filter) {
|
|
149
147
|
return undefined;
|
|
@@ -166,7 +166,7 @@ export class GridFSHelper {
|
|
|
166
166
|
*/
|
|
167
167
|
static async findFiles(bucket: GridFSBucket, filter: any = {}, options: any = {}): Promise<GridFSFileInfo[]> {
|
|
168
168
|
const files = await bucket.find(filter, options).toArray();
|
|
169
|
-
return files.map(file => GridFSHelper.normalizeFileInfo(file));
|
|
169
|
+
return files.map((file) => GridFSHelper.normalizeFileInfo(file));
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
/**
|
|
@@ -200,12 +200,12 @@ export class GridFSHelper {
|
|
|
200
200
|
filename: string,
|
|
201
201
|
options?: { contentType?: string },
|
|
202
202
|
): mongo.GridFSBucketWriteStream {
|
|
203
|
-
// Store contentType in metadata
|
|
203
|
+
// Store contentType in metadata (mongodb 7.x no longer has contentType option)
|
|
204
204
|
if (options?.contentType) {
|
|
205
205
|
const metadata = { contentType: options.contentType };
|
|
206
206
|
return bucket.openUploadStream(filename, { metadata });
|
|
207
207
|
}
|
|
208
|
-
return bucket.openUploadStream(filename
|
|
208
|
+
return bucket.openUploadStream(filename);
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
/**
|
|
@@ -217,11 +217,11 @@ export class GridFSHelper {
|
|
|
217
217
|
filename: string,
|
|
218
218
|
options?: { contentType?: string },
|
|
219
219
|
): mongo.GridFSBucketWriteStream {
|
|
220
|
-
// Store contentType in metadata
|
|
220
|
+
// Store contentType in metadata (mongodb 7.x no longer has contentType option)
|
|
221
221
|
if (options?.contentType) {
|
|
222
222
|
const metadata = { contentType: options.contentType };
|
|
223
223
|
return bucket.openUploadStreamWithId(id, filename, { metadata });
|
|
224
224
|
}
|
|
225
|
-
return bucket.openUploadStreamWithId(id, filename
|
|
225
|
+
return bucket.openUploadStreamWithId(id, filename);
|
|
226
226
|
}
|
|
227
227
|
}
|
|
@@ -22,6 +22,170 @@ import { MailjetOptions } from './mailjet-options.interface';
|
|
|
22
22
|
*/
|
|
23
23
|
export type BetterAuthFieldType = 'boolean' | 'date' | 'json' | 'number' | 'number[]' | 'string' | 'string[]';
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Interface for Auth configuration
|
|
27
|
+
*
|
|
28
|
+
* This configuration controls the authentication system behavior.
|
|
29
|
+
* In v11.x, Legacy Auth (CoreAuthService) is the default.
|
|
30
|
+
* In a future version, BetterAuth (IAM) will become the default.
|
|
31
|
+
*
|
|
32
|
+
* @since 11.7.1
|
|
33
|
+
*
|
|
34
|
+
* ## Migration Roadmap
|
|
35
|
+
*
|
|
36
|
+
* ### v11.x (Current)
|
|
37
|
+
* - Legacy Auth is the default and required for GraphQL Subscriptions
|
|
38
|
+
* - BetterAuth can be used alongside Legacy Auth
|
|
39
|
+
* - Use `legacyEndpoints.enabled: false` after all users migrated to IAM
|
|
40
|
+
*
|
|
41
|
+
* ### Future Version (Planned)
|
|
42
|
+
* - BetterAuth becomes the default
|
|
43
|
+
* - Legacy Auth becomes optional (must be explicitly enabled)
|
|
44
|
+
* - CoreModule.forRoot signature simplifies to `CoreModule.forRoot(options)`
|
|
45
|
+
*
|
|
46
|
+
* @see https://github.com/lenneTech/nest-server/blob/develop/.claude/rules/module-deprecation.md
|
|
47
|
+
*/
|
|
48
|
+
export interface IAuth {
|
|
49
|
+
/**
|
|
50
|
+
* Configuration for legacy auth endpoints
|
|
51
|
+
*
|
|
52
|
+
* Legacy endpoints include:
|
|
53
|
+
* - GraphQL: signIn, signUp, signOut, refreshToken mutations
|
|
54
|
+
* - REST: /api/auth/* endpoints
|
|
55
|
+
*
|
|
56
|
+
* These can be disabled once all users have migrated to BetterAuth (IAM).
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* auth: {
|
|
61
|
+
* legacyEndpoints: {
|
|
62
|
+
* enabled: false // Disable all legacy endpoints after migration
|
|
63
|
+
* }
|
|
64
|
+
* }
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
legacyEndpoints?: IAuthLegacyEndpoints;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Prevent user enumeration via unified error messages
|
|
71
|
+
*
|
|
72
|
+
* When enabled, authentication errors return a generic "Invalid credentials"
|
|
73
|
+
* message instead of specific messages like "Unknown email" or "Wrong password".
|
|
74
|
+
*
|
|
75
|
+
* This prevents attackers from determining whether an email address exists
|
|
76
|
+
* in the system, but reduces UX clarity for legitimate users.
|
|
77
|
+
*
|
|
78
|
+
* @since 11.7.x
|
|
79
|
+
* @default false (backward compatible - specific error messages)
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* auth: {
|
|
84
|
+
* preventUserEnumeration: true // Returns "Invalid credentials" for all auth errors
|
|
85
|
+
* }
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
preventUserEnumeration?: boolean;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Rate limiting configuration for Legacy Auth endpoints
|
|
92
|
+
*
|
|
93
|
+
* Protects against brute-force attacks on signIn, signUp, and other
|
|
94
|
+
* authentication endpoints.
|
|
95
|
+
*
|
|
96
|
+
* Follows the same pattern as `betterAuth.rateLimit`.
|
|
97
|
+
*
|
|
98
|
+
* @since 11.7.x
|
|
99
|
+
* @default { enabled: false }
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* auth: {
|
|
104
|
+
* rateLimit: {
|
|
105
|
+
* enabled: true,
|
|
106
|
+
* max: 10,
|
|
107
|
+
* windowSeconds: 60,
|
|
108
|
+
* message: 'Too many login attempts, please try again later.',
|
|
109
|
+
* }
|
|
110
|
+
* }
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
rateLimit?: IAuthRateLimit;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Interface for Legacy Auth endpoints configuration
|
|
118
|
+
*
|
|
119
|
+
* These endpoints are part of the Legacy Auth system (CoreAuthService).
|
|
120
|
+
* In a future version, BetterAuth (IAM) will become the default and these endpoints
|
|
121
|
+
* can be disabled once all users have migrated.
|
|
122
|
+
*
|
|
123
|
+
* @since 11.7.1
|
|
124
|
+
* @see https://github.com/lenneTech/nest-server/blob/develop/.claude/rules/module-deprecation.md
|
|
125
|
+
*/
|
|
126
|
+
export interface IAuthLegacyEndpoints {
|
|
127
|
+
/**
|
|
128
|
+
* Whether legacy auth endpoints are enabled.
|
|
129
|
+
*
|
|
130
|
+
* Set to false to disable all legacy auth endpoints (GraphQL and REST).
|
|
131
|
+
* Use this after all users have migrated to BetterAuth (IAM).
|
|
132
|
+
*
|
|
133
|
+
* Check migration status via the `betterAuthMigrationStatus` query.
|
|
134
|
+
*
|
|
135
|
+
* @default true
|
|
136
|
+
*/
|
|
137
|
+
enabled?: boolean;
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Whether legacy GraphQL auth endpoints are enabled.
|
|
141
|
+
* Affects: signIn, signUp, signOut, refreshToken mutations
|
|
142
|
+
*
|
|
143
|
+
* @default true (inherits from `enabled`)
|
|
144
|
+
*/
|
|
145
|
+
graphql?: boolean;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Whether legacy REST auth endpoints are enabled.
|
|
149
|
+
* Affects: /api/auth/sign-in, /api/auth/sign-up, etc.
|
|
150
|
+
*
|
|
151
|
+
* @default true (inherits from `enabled`)
|
|
152
|
+
*/
|
|
153
|
+
rest?: boolean;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Interface for Legacy Auth rate limiting configuration
|
|
158
|
+
*
|
|
159
|
+
* Same structure as IBetterAuthRateLimit for consistency.
|
|
160
|
+
*
|
|
161
|
+
* @since 11.7.x
|
|
162
|
+
*/
|
|
163
|
+
export interface IAuthRateLimit {
|
|
164
|
+
/**
|
|
165
|
+
* Whether rate limiting is enabled
|
|
166
|
+
* @default false
|
|
167
|
+
*/
|
|
168
|
+
enabled?: boolean;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Maximum number of requests within the time window
|
|
172
|
+
* @default 10
|
|
173
|
+
*/
|
|
174
|
+
max?: number;
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Custom message when rate limit is exceeded
|
|
178
|
+
* @default 'Too many requests, please try again later.'
|
|
179
|
+
*/
|
|
180
|
+
message?: string;
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Time window in seconds
|
|
184
|
+
* @default 60
|
|
185
|
+
*/
|
|
186
|
+
windowSeconds?: number;
|
|
187
|
+
}
|
|
188
|
+
|
|
25
189
|
/**
|
|
26
190
|
* Interface for better-auth configuration
|
|
27
191
|
*/
|
|
@@ -41,6 +205,40 @@ export interface IBetterAuth {
|
|
|
41
205
|
*/
|
|
42
206
|
additionalUserFields?: Record<string, IBetterAuthUserField>;
|
|
43
207
|
|
|
208
|
+
/**
|
|
209
|
+
* Whether BetterAuthModule should be auto-registered in CoreModule.
|
|
210
|
+
*
|
|
211
|
+
* When false (default), projects integrate BetterAuth via an extended module
|
|
212
|
+
* in their project (e.g., `src/server/modules/better-auth/better-auth.module.ts`).
|
|
213
|
+
* This follows the same pattern as Legacy Auth and allows for custom resolvers,
|
|
214
|
+
* controllers, and project-specific authentication logic.
|
|
215
|
+
*
|
|
216
|
+
* Set to true only for simple projects that don't need customization.
|
|
217
|
+
*
|
|
218
|
+
* @default false
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```typescript
|
|
222
|
+
* // Recommended: Extend BetterAuthModule in your project
|
|
223
|
+
* // src/server/modules/better-auth/better-auth.module.ts
|
|
224
|
+
* import { BetterAuthModule as CoreBetterAuthModule } from '@lenne.tech/nest-server';
|
|
225
|
+
*
|
|
226
|
+
* @Module({})
|
|
227
|
+
* export class BetterAuthModule {
|
|
228
|
+
* static forRoot(options) {
|
|
229
|
+
* return {
|
|
230
|
+
* imports: [CoreBetterAuthModule.forRoot(options)],
|
|
231
|
+
* // Add custom providers, controllers, etc.
|
|
232
|
+
* };
|
|
233
|
+
* }
|
|
234
|
+
* }
|
|
235
|
+
*
|
|
236
|
+
* // Then import in ServerModule
|
|
237
|
+
* import { BetterAuthModule } from './modules/better-auth/better-auth.module';
|
|
238
|
+
* ```
|
|
239
|
+
*/
|
|
240
|
+
autoRegister?: boolean;
|
|
241
|
+
|
|
44
242
|
/**
|
|
45
243
|
* Base path for better-auth endpoints
|
|
46
244
|
* default: '/iam'
|
|
@@ -53,6 +251,19 @@ export interface IBetterAuth {
|
|
|
53
251
|
*/
|
|
54
252
|
baseUrl?: string;
|
|
55
253
|
|
|
254
|
+
/**
|
|
255
|
+
* Email/password authentication configuration.
|
|
256
|
+
* Enabled by default.
|
|
257
|
+
* Set `enabled: false` to explicitly disable email/password auth.
|
|
258
|
+
*/
|
|
259
|
+
emailAndPassword?: {
|
|
260
|
+
/**
|
|
261
|
+
* Whether email/password authentication is enabled.
|
|
262
|
+
* @default true
|
|
263
|
+
*/
|
|
264
|
+
enabled?: boolean;
|
|
265
|
+
};
|
|
266
|
+
|
|
56
267
|
/**
|
|
57
268
|
* Whether better-auth is enabled.
|
|
58
269
|
* BetterAuth is enabled by default (zero-config philosophy).
|
|
@@ -80,20 +291,6 @@ export interface IBetterAuth {
|
|
|
80
291
|
expiresIn?: string;
|
|
81
292
|
};
|
|
82
293
|
|
|
83
|
-
/**
|
|
84
|
-
* Legacy password handling configuration.
|
|
85
|
-
* Used during migration from old auth system.
|
|
86
|
-
* Enabled by default when this config block is present.
|
|
87
|
-
* Set `enabled: false` to explicitly disable.
|
|
88
|
-
*/
|
|
89
|
-
legacyPassword?: {
|
|
90
|
-
/**
|
|
91
|
-
* Whether legacy password handling is enabled.
|
|
92
|
-
* @default true (when legacyPassword config block is present)
|
|
93
|
-
*/
|
|
94
|
-
enabled?: boolean;
|
|
95
|
-
};
|
|
96
|
-
|
|
97
294
|
/**
|
|
98
295
|
* Advanced Better-Auth options passthrough.
|
|
99
296
|
* These options are passed directly to Better-Auth, allowing full customization.
|
|
@@ -380,6 +577,17 @@ export interface IJwt {
|
|
|
380
577
|
* Options for the server
|
|
381
578
|
*/
|
|
382
579
|
export interface IServerOptions {
|
|
580
|
+
/**
|
|
581
|
+
* Authentication system configuration
|
|
582
|
+
*
|
|
583
|
+
* Controls Legacy Auth endpoints and behavior.
|
|
584
|
+
* In a future version, this will also control BetterAuth as the default system.
|
|
585
|
+
*
|
|
586
|
+
* @since 11.7.1
|
|
587
|
+
* @see IAuth
|
|
588
|
+
*/
|
|
589
|
+
auth?: IAuth;
|
|
590
|
+
|
|
383
591
|
/**
|
|
384
592
|
* Automatically detect ObjectIds in string values in FilterQueries
|
|
385
593
|
* and expand them as OR query with string and ObjectId.
|