@lenne.tech/nest-server 10.5.0 → 10.7.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.
Files changed (86) hide show
  1. package/dist/core/common/decorators/restricted.decorator.d.ts +5 -1
  2. package/dist/core/common/decorators/restricted.decorator.js +20 -3
  3. package/dist/core/common/decorators/restricted.decorator.js.map +1 -1
  4. package/dist/core/common/helpers/common.helper.js +2 -3
  5. package/dist/core/common/helpers/common.helper.js.map +1 -1
  6. package/dist/core/common/helpers/config.helper.js +1 -2
  7. package/dist/core/common/helpers/config.helper.js.map +1 -1
  8. package/dist/core/common/helpers/context.helper.d.ts +0 -1
  9. package/dist/core/common/helpers/context.helper.js +1 -2
  10. package/dist/core/common/helpers/context.helper.js.map +1 -1
  11. package/dist/core/common/helpers/db.helper.d.ts +0 -24
  12. package/dist/core/common/helpers/db.helper.js +20 -18
  13. package/dist/core/common/helpers/db.helper.js.map +1 -1
  14. package/dist/core/common/helpers/decorator.helper.d.ts +0 -24
  15. package/dist/core/common/helpers/decorator.helper.js +2 -3
  16. package/dist/core/common/helpers/decorator.helper.js.map +1 -1
  17. package/dist/core/common/helpers/file.helper.js +3 -4
  18. package/dist/core/common/helpers/file.helper.js.map +1 -1
  19. package/dist/core/common/helpers/filter.helper.d.ts +0 -24
  20. package/dist/core/common/helpers/filter.helper.js +6 -6
  21. package/dist/core/common/helpers/filter.helper.js.map +1 -1
  22. package/dist/core/common/helpers/graphql.helper.d.ts +2 -2
  23. package/dist/core/common/helpers/graphql.helper.js +12 -13
  24. package/dist/core/common/helpers/graphql.helper.js.map +1 -1
  25. package/dist/core/common/helpers/input.helper.d.ts +2 -0
  26. package/dist/core/common/helpers/input.helper.js +45 -38
  27. package/dist/core/common/helpers/input.helper.js.map +1 -1
  28. package/dist/core/common/helpers/model.helper.js +8 -8
  29. package/dist/core/common/helpers/model.helper.js.map +1 -1
  30. package/dist/core/common/helpers/service.helper.js +3 -4
  31. package/dist/core/common/helpers/service.helper.js.map +1 -1
  32. package/dist/core/common/helpers/table.helper.js +1 -2
  33. package/dist/core/common/helpers/table.helper.js.map +1 -1
  34. package/dist/core/common/interceptors/check-response.interceptor.d.ts +1 -0
  35. package/dist/core/common/interceptors/check-response.interceptor.js +8 -1
  36. package/dist/core/common/interceptors/check-response.interceptor.js.map +1 -1
  37. package/dist/core/common/interceptors/check-security.interceptor.d.ts +7 -0
  38. package/dist/core/common/interceptors/check-security.interceptor.js +30 -2
  39. package/dist/core/common/interceptors/check-security.interceptor.js.map +1 -1
  40. package/dist/core/common/interfaces/server-options.interface.d.ts +6 -2
  41. package/dist/core/common/interfaces/service-options.interface.d.ts +0 -24
  42. package/dist/core/common/models/core-persistence.model.d.ts +0 -26
  43. package/dist/core/common/models/core-persistence.model.js +1 -23
  44. package/dist/core/common/models/core-persistence.model.js.map +1 -1
  45. package/dist/core/common/plugins/mongoose-id.plugin.js +1 -2
  46. package/dist/core/common/plugins/mongoose-id.plugin.js.map +1 -1
  47. package/dist/core/common/services/crud.service.d.ts +0 -24
  48. package/dist/core/common/services/model-doc.service.d.ts +0 -24
  49. package/dist/core/common/services/module.service.d.ts +0 -24
  50. package/dist/core/common/types/field-selection.type.d.ts +0 -24
  51. package/dist/core/common/types/ids.type.d.ts +0 -24
  52. package/dist/core/common/types/populate-config.type.d.ts +0 -24
  53. package/dist/core/common/types/string-or-object-id.type.d.ts +0 -24
  54. package/dist/core/modules/auth/strategies/jwt-refresh.strategy.d.ts +0 -1
  55. package/dist/core/modules/file/core-file-info.model.d.ts +0 -24
  56. package/dist/core/modules/file/core-file.service.d.ts +0 -26
  57. package/dist/core/modules/file/interfaces/file-upload.interface.d.ts +0 -1
  58. package/dist/core/modules/user/core-user.model.d.ts +0 -24
  59. package/dist/core/modules/user/core-user.model.js +1 -2
  60. package/dist/core/modules/user/core-user.model.js.map +1 -1
  61. package/dist/core/modules/user/core-user.service.d.ts +0 -24
  62. package/dist/server/common/models/persistence.model.d.ts +0 -24
  63. package/dist/server/modules/file/file-info.model.d.ts +0 -25
  64. package/dist/server/modules/file/file.controller.d.ts +0 -1
  65. package/dist/server/modules/file/file.service.d.ts +0 -24
  66. package/dist/server/modules/user/avatar.controller.d.ts +0 -1
  67. package/dist/server/modules/user/user.model.d.ts +1 -24
  68. package/dist/server/modules/user/user.model.js +8 -2
  69. package/dist/server/modules/user/user.model.js.map +1 -1
  70. package/dist/server/modules/user/user.resolver.d.ts +1 -1
  71. package/dist/server/modules/user/user.resolver.js +1 -1
  72. package/dist/server/modules/user/user.resolver.js.map +1 -1
  73. package/dist/server/modules/user/user.service.d.ts +0 -25
  74. package/dist/test/test.helper.d.ts +0 -2
  75. package/dist/tsconfig.build.tsbuildinfo +1 -1
  76. package/package.json +28 -28
  77. package/src/core/common/decorators/restricted.decorator.ts +32 -6
  78. package/src/core/common/helpers/db.helper.ts +5 -1
  79. package/src/core/common/helpers/input.helper.ts +16 -4
  80. package/src/core/common/interceptors/check-response.interceptor.ts +13 -1
  81. package/src/core/common/interceptors/check-security.interceptor.ts +37 -2
  82. package/src/core/common/interfaces/server-options.interface.ts +26 -3
  83. package/src/core/common/models/core-persistence.model.ts +1 -25
  84. package/src/core/modules/user/core-user.model.ts +2 -3
  85. package/src/server/modules/user/user.model.ts +10 -3
  86. package/src/server/modules/user/user.resolver.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/nest-server",
3
- "version": "10.5.0",
3
+ "version": "10.7.0",
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",
@@ -66,14 +66,14 @@
66
66
  "@getbrevo/brevo": "1.0.1",
67
67
  "@lenne.tech/mongoose-gridfs": "1.4.2",
68
68
  "@lenne.tech/multer-gridfs-storage": "5.0.6",
69
- "@nestjs/apollo": "12.2.1",
70
- "@nestjs/common": "10.4.6",
71
- "@nestjs/core": "10.4.6",
72
- "@nestjs/graphql": "12.2.1",
69
+ "@nestjs/apollo": "12.2.2",
70
+ "@nestjs/common": "10.4.13",
71
+ "@nestjs/core": "10.4.13",
72
+ "@nestjs/graphql": "12.2.2",
73
73
  "@nestjs/jwt": "10.2.0",
74
74
  "@nestjs/mongoose": "10.1.0",
75
75
  "@nestjs/passport": "10.0.3",
76
- "@nestjs/platform-express": "10.4.6",
76
+ "@nestjs/platform-express": "10.4.13",
77
77
  "@nestjs/schedule": "4.1.1",
78
78
  "@nestjs/terminus": "10.2.3",
79
79
  "apollo-server-core": "3.13.0",
@@ -81,22 +81,22 @@
81
81
  "bcrypt": "5.1.1",
82
82
  "class-transformer": "0.5.1",
83
83
  "class-validator": "0.14.1",
84
- "compression": "1.7.4",
84
+ "compression": "1.7.5",
85
85
  "cookie-parser": "1.4.7",
86
86
  "ejs": "3.1.10",
87
87
  "graphql": "16.9.0",
88
88
  "graphql-query-complexity": "1.0.0",
89
- "graphql-subscriptions": "2.0.0",
89
+ "graphql-subscriptions": "3.0.0",
90
90
  "graphql-upload": "15.0.2",
91
91
  "js-sha256": "0.11.0",
92
92
  "json-to-graphql-query": "2.3.0",
93
- "light-my-request": "6.2.0",
93
+ "light-my-request": "6.3.0",
94
94
  "lodash": "4.17.21",
95
- "mongodb": "6.10.0",
96
- "mongoose": "7.8.2",
95
+ "mongodb": "6.11.0",
96
+ "mongoose": "7.8.3",
97
97
  "multer": "1.4.5-lts.1",
98
98
  "node-mailjet": "6.0.6",
99
- "nodemailer": "6.9.15",
99
+ "nodemailer": "6.9.16",
100
100
  "nodemon": "3.1.7",
101
101
  "passport": "0.7.0",
102
102
  "passport-jwt": "4.0.1",
@@ -110,22 +110,22 @@
110
110
  "@babel/plugin-proposal-private-methods": "7.18.6",
111
111
  "@compodoc/compodoc": "1.1.26",
112
112
  "@lenne.tech/eslint-config-ts": "0.0.16",
113
- "@nestjs/cli": "10.4.5",
114
- "@nestjs/schematics": "10.2.2",
115
- "@nestjs/testing": "10.4.6",
116
- "@swc/cli": "0.4.0",
117
- "@swc/core": "1.7.39",
118
- "@swc/jest": "0.2.36",
113
+ "@nestjs/cli": "10.4.8",
114
+ "@nestjs/schematics": "10.2.3",
115
+ "@nestjs/testing": "10.4.13",
116
+ "@swc/cli": "0.5.2",
117
+ "@swc/core": "1.10.0",
118
+ "@swc/jest": "0.2.37",
119
119
  "@types/compression": "1.7.5",
120
- "@types/cookie-parser": "1.4.7",
120
+ "@types/cookie-parser": "1.4.8",
121
121
  "@types/ejs": "3.1.5",
122
122
  "@types/express": "4.17.21",
123
123
  "@types/jest": "29.5.14",
124
- "@types/lodash": "4.17.12",
124
+ "@types/lodash": "4.17.13",
125
125
  "@types/multer": "1.4.12",
126
- "@types/node": "20.17.0",
127
- "@types/nodemailer": "6.4.16",
128
- "@types/passport": "1.0.16",
126
+ "@types/node": "22.10.1",
127
+ "@types/nodemailer": "6.4.17",
128
+ "@types/passport": "1.0.17",
129
129
  "@types/supertest": "6.0.2",
130
130
  "@typescript-eslint/eslint-plugin": "6.21.0",
131
131
  "@typescript-eslint/parser": "6.21.0",
@@ -139,19 +139,19 @@
139
139
  "grunt-contrib-clean": "2.0.1",
140
140
  "grunt-contrib-watch": "1.1.0",
141
141
  "grunt-sync": "0.8.2",
142
- "husky": "9.1.6",
142
+ "husky": "9.1.7",
143
143
  "jest": "29.7.0",
144
144
  "npm-watch": "0.13.0",
145
- "pm2": "5.4.2",
146
- "prettier": "3.3.3",
145
+ "pm2": "5.4.3",
146
+ "prettier": "3.4.2",
147
147
  "pretty-quick": "4.0.0",
148
148
  "supertest": "7.0.0",
149
149
  "ts-jest": "29.2.5",
150
150
  "ts-loader": "9.5.1",
151
- "ts-morph": "21.0.1",
151
+ "ts-morph": "24.0.0",
152
152
  "ts-node": "10.9.2",
153
153
  "tsconfig-paths": "4.2.0",
154
- "typescript": "5.3.3",
154
+ "typescript": "5.7.2",
155
155
  "yalc": "1.0.0-pre.53"
156
156
  },
157
157
  "overrides": {
@@ -3,7 +3,7 @@ import 'reflect-metadata';
3
3
 
4
4
  import { ProcessType } from '../enums/process-type.enum';
5
5
  import { RoleEnum } from '../enums/role.enum';
6
- import { getIncludedIds } from '../helpers/db.helper';
6
+ import { equalIds, getIncludedIds } from '../helpers/db.helper';
7
7
  import { RequireAtLeastOne } from '../types/required-at-least-one.type';
8
8
 
9
9
  import _ = require('lodash');
@@ -22,6 +22,7 @@ export type RestrictedType = (
22
22
  'memberOf' | 'roles'
23
23
  >
24
24
  | string
25
+ | string[]
25
26
  )[];
26
27
 
27
28
  /**
@@ -63,11 +64,15 @@ export const checkRestricted = (
63
64
  data: any,
64
65
  user: { hasRole: (roles: string[]) => boolean; id: any },
65
66
  options: {
67
+ allowCreatorOfParent?: boolean;
66
68
  checkObjectItself?: boolean;
67
69
  dbObject?: any;
68
70
  debug?: boolean;
71
+ ignoreFunctions?: boolean;
69
72
  ignoreUndefined?: boolean;
73
+ isCreatorOfParent?: boolean;
70
74
  mergeRoles?: boolean;
75
+ noteCheckedObjects?: boolean;
71
76
  processType?: ProcessType;
72
77
  removeUndefinedFromResultArray?: boolean;
73
78
  throwError?: boolean;
@@ -78,16 +83,20 @@ export const checkRestricted = (
78
83
  // For Input: throwError = true
79
84
  // For Output: throwError = false
80
85
  const config = {
86
+ allowCreatorOfParent: true,
81
87
  checkObjectItself: false,
88
+ ignoreFunctions: true,
82
89
  ignoreUndefined: true,
90
+ isCreatorOfParent: false,
83
91
  mergeRoles: true,
92
+ noteCheckedObjects: true,
84
93
  removeUndefinedFromResultArray: true,
85
94
  throwError: true,
86
95
  ...options,
87
96
  };
88
97
 
89
98
  // Primitives
90
- if (!data || typeof data !== 'object') {
99
+ if (!data || typeof data !== 'object' || (config.noteCheckedObjects && data._objectAlreadyCheckedForRestrictions)) {
91
100
  return data;
92
101
  }
93
102
 
@@ -109,6 +118,10 @@ export const checkRestricted = (
109
118
 
110
119
  // Check function
111
120
  const validateRestricted = (restricted) => {
121
+ if (config.noteCheckedObjects && data?._objectAlreadyCheckedForRestrictions) {
122
+ return true;
123
+ }
124
+
112
125
  // Check restrictions
113
126
  if (!restricted?.length) {
114
127
  return true;
@@ -116,7 +129,7 @@ export const checkRestricted = (
116
129
 
117
130
  let valid = false;
118
131
 
119
- // Get roles
132
+ // Get roles restricted element
120
133
  const roles: string[] = [];
121
134
  restricted.forEach((item) => {
122
135
  if (typeof item === 'string') {
@@ -130,6 +143,8 @@ export const checkRestricted = (
130
143
  } else {
131
144
  roles.push(item.roles);
132
145
  }
146
+ } else if (Array.isArray(item)) {
147
+ roles.push(...item);
133
148
  }
134
149
  });
135
150
 
@@ -145,8 +160,10 @@ export const checkRestricted = (
145
160
  roles.includes(RoleEnum.S_EVERYONE)
146
161
  || user?.hasRole?.(roles)
147
162
  || (user?.id && roles.includes(RoleEnum.S_USER))
148
- || (roles.includes(RoleEnum.S_SELF) && getIncludedIds(config.dbObject, user))
149
- || (roles.includes(RoleEnum.S_CREATOR) && getIncludedIds(config.dbObject?.createdBy, user))
163
+ || (roles.includes(RoleEnum.S_SELF) && equalIds(data, user))
164
+ || (roles.includes(RoleEnum.S_CREATOR)
165
+ && (('createdBy' in data && equalIds(data.createdBy, user))
166
+ || (config.allowCreatorOfParent && !('createdBy' in data) && config.isCreatorOfParent)))
150
167
  ) {
151
168
  valid = true;
152
169
  }
@@ -200,7 +217,7 @@ export const checkRestricted = (
200
217
  return valid;
201
218
  };
202
219
 
203
- // Check object
220
+ // Check data object
204
221
  const objectRestrictions = getRestricted(data.constructor) || [];
205
222
  if (config.checkObjectItself) {
206
223
  const objectIsValid = validateRestricted(objectRestrictions);
@@ -218,6 +235,11 @@ export const checkRestricted = (
218
235
 
219
236
  // Check properties of object
220
237
  for (const propertyKey of Object.keys(data)) {
238
+ // Ignore functions
239
+ if (typeof data[propertyKey] === 'function' && config.ignoreFunctions) {
240
+ continue;
241
+ }
242
+
221
243
  // Check undefined
222
244
  if (data[propertyKey] === undefined && config.ignoreUndefined) {
223
245
  continue;
@@ -230,6 +252,10 @@ export const checkRestricted = (
230
252
 
231
253
  // Check rights
232
254
  if (valid) {
255
+ // Check if data is user or user is creator of data (for nested plain objects)
256
+ config.isCreatorOfParent
257
+ = equalIds(data, user) || ('createdBy' in data ? equalIds(data.createdBy, user) : config.isCreatorOfParent);
258
+
233
259
  // Check deep
234
260
  data[propertyKey] = checkRestricted(data[propertyKey], user, config, processedObjects);
235
261
  } else {
@@ -670,5 +670,9 @@ function getStringId(element: any): string {
670
670
  }
671
671
 
672
672
  // Other types
673
- return element.toString();
673
+ if (typeof element.toString === 'function') {
674
+ return element.toString();
675
+ }
676
+
677
+ return undefined;
674
678
  }
@@ -212,7 +212,9 @@ export async function check(
212
212
  value: any,
213
213
  user: { hasRole: (roles: string[]) => boolean; id: any },
214
214
  options?: {
215
+ allowCreatorOfParent?: boolean;
215
216
  dbObject?: any;
217
+ isCreatorOfParent?: boolean;
216
218
  metatype?: any;
217
219
  processType?: ProcessType;
218
220
  roles?: string | string[];
@@ -221,6 +223,8 @@ export async function check(
221
223
  },
222
224
  ): Promise<any> {
223
225
  const config = {
226
+ allowCreatorOfParent: true,
227
+ isCreatorOfParent: false,
224
228
  throwError: true,
225
229
  ...options,
226
230
  validatorOptions: {
@@ -254,7 +258,12 @@ export async function check(
254
258
  // check if the user is herself / himself
255
259
  || (roles.includes(RoleEnum.S_SELF) && equalIds(config.dbObject, user))
256
260
  // check if the user is the creator
257
- || (roles.includes(RoleEnum.S_CREATOR) && equalIds(config.dbObject?.createdBy, user))
261
+ || (roles.includes(RoleEnum.S_CREATOR)
262
+ && ((config.dbObject && 'createdBy' in config.dbObject && equalIds(config.dbObject.createdBy, user))
263
+ || (config.allowCreatorOfParent
264
+ && config.dbObject
265
+ && !('createdBy' in config.dbObject)
266
+ && config.isCreatorOfParent)))
258
267
  ) {
259
268
  valid = true;
260
269
  }
@@ -263,6 +272,9 @@ export async function check(
263
272
  }
264
273
  }
265
274
 
275
+ // Object check is done
276
+ delete config.roles;
277
+
266
278
  // Return value if it is only a basic type
267
279
  if (!value || typeof value !== 'object') {
268
280
  return value;
@@ -278,12 +290,12 @@ export async function check(
278
290
 
279
291
  const metatype = config.metatype;
280
292
  if (metatype) {
281
- // Check metatype
293
+ // If metatype is a basic type, additional checks are not possible
282
294
  if (isBasicType(metatype)) {
283
295
  return value;
284
296
  }
285
297
 
286
- // Convert to metatype
298
+ // Convert to metatype, validate rights
287
299
  if (!(value instanceof metatype)) {
288
300
  if ((metatype as any)?.map) {
289
301
  value = (metatype as any)?.map(value);
@@ -293,7 +305,7 @@ export async function check(
293
305
  }
294
306
  }
295
307
 
296
- // Validate
308
+ // Validate values (like isEmail, isNumber, etc.)
297
309
  const errors = await validate(value, config.validatorOptions);
298
310
  if (errors.length > 0 && config.throwError) {
299
311
  throw new BadRequestException('Validation failed');
@@ -16,6 +16,7 @@ export class CheckResponseInterceptor implements NestInterceptor {
16
16
  debug: false,
17
17
  ignoreUndefined: true,
18
18
  mergeRoles: true,
19
+ noteCheckedObjects: true,
19
20
  removeUndefinedFromResultArray: true,
20
21
  throwError: false,
21
22
  };
@@ -38,7 +39,18 @@ export class CheckResponseInterceptor implements NestInterceptor {
38
39
  return next.handle().pipe(
39
40
  map((data) => {
40
41
  // Prepare response data for current user
41
- return checkRestricted(data, currentUser, this.config);
42
+ const start = Date.now();
43
+ const result = checkRestricted(data, currentUser, this.config);
44
+ if (
45
+ this.config.debug
46
+ && Date.now() - start >= (typeof this.config.debug === 'number' ? this.config.debug : 100)
47
+ ) {
48
+ console.warn(
49
+ `Duration for CheckResponseInterceptor is too long: ${Date.now() - start}ms`,
50
+ Array.isArray(data) ? `${data[0].constructor.name}[]: ${data.length}` : data?.constructor?.name,
51
+ );
52
+ }
53
+ return result;
42
54
  }),
43
55
  );
44
56
  }
@@ -5,13 +5,29 @@ import { map } from 'rxjs/operators';
5
5
  import { getContextData } from '../helpers/context.helper';
6
6
  import { getStringIds } from '../helpers/db.helper';
7
7
  import { processDeep } from '../helpers/input.helper';
8
+ import { ConfigService } from '../services/config.service';
8
9
 
9
10
  /**
10
11
  * Verification of all outgoing data via securityCheck
11
12
  */
12
13
  @Injectable()
13
14
  export class CheckSecurityInterceptor implements NestInterceptor {
15
+ config = {
16
+ debug: false,
17
+ noteCheckedObjects: true,
18
+ };
19
+
20
+ constructor(private readonly configService: ConfigService) {
21
+ const configuration = this.configService.getFastButReadOnly('security.checkSecurityInterceptor');
22
+ if (typeof configuration === 'object') {
23
+ this.config = { ...this.config, ...configuration };
24
+ }
25
+ }
26
+
14
27
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
28
+ // Start time
29
+ const start = Date.now();
30
+
15
31
  // Get current user
16
32
  const user = getContextData(context)?.currentUser || null;
17
33
 
@@ -25,7 +41,17 @@ export class CheckSecurityInterceptor implements NestInterceptor {
25
41
  }
26
42
  }
27
43
 
28
- const check = (data) => {
44
+ // Data from next for check
45
+ let objectData: any;
46
+
47
+ const check = (data: any) => {
48
+ objectData = data;
49
+
50
+ // Check if data already checked
51
+ if (this.config.noteCheckedObjects && data?._objectAlreadyCheckedForRestrictions) {
52
+ return data;
53
+ }
54
+
29
55
  // Check data
30
56
  if (data && typeof data === 'object' && typeof data.securityCheck === 'function') {
31
57
  const dataJson = JSON.stringify(data);
@@ -73,6 +99,15 @@ export class CheckSecurityInterceptor implements NestInterceptor {
73
99
  };
74
100
 
75
101
  // Check response
76
- return next.handle().pipe(map(check));
102
+ const result = next.handle().pipe(map(check));
103
+ if (this.config.debug && Date.now() - start >= (typeof this.config.debug === 'number' ? this.config.debug : 100)) {
104
+ console.warn(
105
+ `Duration for CheckResponseInterceptor is too long: ${Date.now() - start}ms`,
106
+ Array.isArray(objectData)
107
+ ? `${objectData[0].constructor.name}[]: ${objectData.length}`
108
+ : objectData?.constructor?.name,
109
+ );
110
+ }
111
+ return result;
77
112
  }
78
113
  }
@@ -421,10 +421,11 @@ export interface IServerOptions {
421
421
  checkObjectItself?: boolean;
422
422
 
423
423
  /**
424
- * Whether to log if a restricted field is found
424
+ * Whether to log if a restricted field is found or process is slow
425
+ * boolean or number (time in ms)
425
426
  * default = false
426
427
  */
427
- debug?: boolean;
428
+ debug?: boolean | number;
428
429
 
429
430
  /**
430
431
  * Whether to ignore fields with undefined values
@@ -438,6 +439,13 @@ export interface IServerOptions {
438
439
  */
439
440
  mergeRoles?: boolean;
440
441
 
442
+ /**
443
+ * Whether objects that have already been checked should be ignored
444
+ * Objects with truly property `_objectAlreadyCheckedForRestrictions` will be ignored
445
+ * default = true
446
+ */
447
+ noteCheckedObjects?: boolean;
448
+
441
449
  /**
442
450
  * Remove undefined values from result array
443
451
  * default = true
@@ -457,7 +465,22 @@ export interface IServerOptions {
457
465
  * See @lenne.tech/nest-server/src/core/common/interceptors/check-security.interceptor.ts
458
466
  * default = true
459
467
  */
460
- checkSecurityInterceptor?: boolean;
468
+ checkSecurityInterceptor?:
469
+ | {
470
+ /**
471
+ * Whether to log if a process is slow
472
+ * boolean or number (time in ms)
473
+ * default = false
474
+ */
475
+ debug?: boolean | number;
476
+
477
+ /**
478
+ * Whether objects with truly property `_objectAlreadyCheckedForRestrictions` will be ignored
479
+ * default = true
480
+ */
481
+ noteCheckedObjects?: boolean;
482
+ }
483
+ | boolean;
461
484
 
462
485
  /**
463
486
  * Map incoming plain objects to meta-type and validate
@@ -57,28 +57,6 @@ export abstract class CorePersistenceModel extends CoreModel {
57
57
  @Prop({ onCreate: () => new Date() })
58
58
  createdAt: Date = undefined;
59
59
 
60
- /**
61
- * Labels of the object
62
- */
63
- @Restricted(RoleEnum.S_EVERYONE)
64
- @Field(type => [String], {
65
- description: 'Labels of the object',
66
- nullable: true,
67
- })
68
- @Prop([String])
69
- labels: string[] = undefined;
70
-
71
- /**
72
- * Tags for the object
73
- */
74
- @Restricted(RoleEnum.S_EVERYONE)
75
- @Field(type => [String], {
76
- description: 'Tags for the object',
77
- nullable: true,
78
- })
79
- @Prop([String])
80
- tags: string[] = undefined;
81
-
82
60
  /**
83
61
  * Updated date is set automatically by mongoose
84
62
  */
@@ -97,9 +75,7 @@ export abstract class CorePersistenceModel extends CoreModel {
97
75
  override init() {
98
76
  super.init();
99
77
  this.createdAt = this.createdAt === undefined ? new Date() : this.createdAt;
100
- this.labels = this.labels === undefined ? [] : this.labels;
101
- this.tags = this.tags === undefined ? [] : this.tags;
102
- this.updatedAt = this.tags === undefined ? this.createdAt : this.updatedAt;
78
+ this.updatedAt = this.updatedAt === undefined ? this.createdAt : this.updatedAt;
103
79
  return this;
104
80
  }
105
81
 
@@ -1,6 +1,6 @@
1
1
  import { Field, ObjectType } from '@nestjs/graphql';
2
2
  import { Schema as MongooseSchema, Prop, raw } from '@nestjs/mongoose';
3
- import { IsEmail, IsOptional } from 'class-validator';
3
+ import { IsOptional } from 'class-validator';
4
4
  import { Document } from 'mongoose';
5
5
 
6
6
  import { Restricted } from '../../common/decorators/restricted.decorator';
@@ -26,8 +26,7 @@ export abstract class CoreUserModel extends CorePersistenceModel {
26
26
  */
27
27
  @Restricted(RoleEnum.S_EVERYONE)
28
28
  @Field({ description: 'Email of the user', nullable: true })
29
- @IsEmail()
30
- @Prop({ lowercase: true, trim: true, unique: true })
29
+ @Prop({ index: true, lowercase: true, trim: true })
31
30
  email: string = undefined;
32
31
 
33
32
  /**
@@ -1,6 +1,6 @@
1
1
  import { Field, ObjectType } from '@nestjs/graphql';
2
2
  import { Schema as MongooseSchema, Prop, SchemaFactory } from '@nestjs/mongoose';
3
- import { IsOptional } from 'class-validator';
3
+ import { IsEmail, IsOptional } from 'class-validator';
4
4
  import { Document, Schema } from 'mongoose';
5
5
 
6
6
  import { Restricted } from '../../../core/common/decorators/restricted.decorator';
@@ -42,6 +42,15 @@ export class User extends CoreUserModel implements PersistenceModel {
42
42
  @Prop({ ref: 'User', type: Schema.Types.ObjectId })
43
43
  createdBy: string = undefined;
44
44
 
45
+ /**
46
+ * E-Mail address of the user
47
+ */
48
+ @Restricted(RoleEnum.S_EVERYONE)
49
+ @Field({ description: 'Email of the user', nullable: true })
50
+ @IsEmail()
51
+ @Prop({ lowercase: true, trim: true, unique: true })
52
+ override email: string = undefined;
53
+
45
54
  /**
46
55
  * Roles of the user
47
56
  */
@@ -105,8 +114,6 @@ export class User extends CoreUserModel implements PersistenceModel {
105
114
  // PersistenceModel and CorePersistenceModel
106
115
  this.createdAt = null;
107
116
  this.createdBy = null;
108
- this.labels = null;
109
- this.tags = null;
110
117
  this.updatedAt = null;
111
118
  this.updatedBy = null;
112
119
  }
@@ -169,6 +169,6 @@ export class UserResolver {
169
169
  resolve: user => user,
170
170
  })
171
171
  async userCreated() {
172
- return this.pubSub.asyncIterator('userCreated');
172
+ return this.pubSub.asyncIterableIterator('userCreated');
173
173
  }
174
174
  }