@lenne.tech/nest-server 10.2.13 → 10.2.15

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/nest-server",
3
- "version": "10.2.13",
3
+ "version": "10.2.15",
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",
@@ -63,18 +63,18 @@
63
63
  "node": ">= 20"
64
64
  },
65
65
  "dependencies": {
66
- "@apollo/gateway": "2.6.3",
66
+ "@apollo/gateway": "2.7.1",
67
67
  "@getbrevo/brevo": "1.0.1",
68
68
  "@lenne.tech/mongoose-gridfs": "1.4.2",
69
69
  "@lenne.tech/multer-gridfs-storage": "5.0.6",
70
70
  "@nestjs/apollo": "12.0.11",
71
- "@nestjs/common": "10.3.0",
72
- "@nestjs/core": "10.3.0",
71
+ "@nestjs/common": "10.3.1",
72
+ "@nestjs/core": "10.3.1",
73
73
  "@nestjs/graphql": "12.0.11",
74
74
  "@nestjs/jwt": "10.2.0",
75
75
  "@nestjs/mongoose": "10.0.2",
76
76
  "@nestjs/passport": "10.0.3",
77
- "@nestjs/platform-express": "10.3.0",
77
+ "@nestjs/platform-express": "10.3.1",
78
78
  "@nestjs/schedule": "4.0.0",
79
79
  "@nestjs/terminus": "10.2.0",
80
80
  "apollo-server-core": "3.13.0",
@@ -89,7 +89,7 @@
89
89
  "graphql-query-complexity": "0.12.0",
90
90
  "graphql-subscriptions": "2.0.0",
91
91
  "graphql-upload": "15.0.2",
92
- "js-sha256": "0.10.1",
92
+ "js-sha256": "0.11.0",
93
93
  "json-to-graphql-query": "2.2.5",
94
94
  "light-my-request": "5.11.0",
95
95
  "lodash": "4.17.21",
@@ -102,7 +102,7 @@
102
102
  "passport": "0.7.0",
103
103
  "passport-jwt": "4.0.1",
104
104
  "reflect-metadata": "0.1.14",
105
- "rfdc": "1.3.0",
105
+ "rfdc": "1.3.1",
106
106
  "rimraf": "5.0.5",
107
107
  "rxjs": "7.8.1",
108
108
  "yuml-diagram": "1.2.0"
@@ -113,10 +113,10 @@
113
113
  "@lenne.tech/eslint-config-ts": "0.0.16",
114
114
  "@nestjs/cli": "10.3.0",
115
115
  "@nestjs/schematics": "10.1.0",
116
- "@nestjs/testing": "10.3.0",
117
- "@swc/cli": "0.1.63",
118
- "@swc/core": "1.3.104",
119
- "@swc/jest": "0.2.29",
116
+ "@nestjs/testing": "10.3.1",
117
+ "@swc/cli": "0.1.65",
118
+ "@swc/core": "1.3.106",
119
+ "@swc/jest": "0.2.31",
120
120
  "@types/compression": "1.7.5",
121
121
  "@types/cookie-parser": "1.4.6",
122
122
  "@types/ejs": "3.1.5",
@@ -124,12 +124,12 @@
124
124
  "@types/jest": "29.5.11",
125
125
  "@types/lodash": "4.14.202",
126
126
  "@types/multer": "1.4.11",
127
- "@types/node": "20.11.5",
127
+ "@types/node": "20.11.6",
128
128
  "@types/nodemailer": "6.4.14",
129
129
  "@types/passport": "1.0.16",
130
130
  "@types/supertest": "6.0.2",
131
- "@typescript-eslint/eslint-plugin": "6.19.0",
132
- "@typescript-eslint/parser": "6.19.0",
131
+ "@typescript-eslint/eslint-plugin": "6.19.1",
132
+ "@typescript-eslint/parser": "6.19.1",
133
133
  "coffeescript": "2.7.0",
134
134
  "eslint": "8.56.0",
135
135
  "eslint-config-prettier": "9.1.0",
@@ -143,11 +143,11 @@
143
143
  "husky": "8.0.3",
144
144
  "jest": "29.7.0",
145
145
  "npm-watch": "0.11.0",
146
- "pm2": "5.3.0",
146
+ "pm2": "5.3.1",
147
147
  "prettier": "3.2.4",
148
148
  "pretty-quick": "4.0.0",
149
149
  "supertest": "6.3.4",
150
- "ts-jest": "29.1.1",
150
+ "ts-jest": "29.1.2",
151
151
  "ts-loader": "9.5.1",
152
152
  "ts-morph": "20.0.0",
153
153
  "ts-node": "10.9.2",
package/src/config.env.ts CHANGED
@@ -89,7 +89,14 @@ const config: { [env: string]: IServerOptions } = {
89
89
  },
90
90
  port: 3000,
91
91
  security: {
92
- checkResponseInterceptor: true,
92
+ checkResponseInterceptor: {
93
+ checkObjectItself: false,
94
+ debug: false,
95
+ ignoreUndefined: true,
96
+ mergeRoles: true,
97
+ removeUndefinedFromResultArray: true,
98
+ throwError: false,
99
+ },
93
100
  checkSecurityInterceptor: true,
94
101
  mapAndValidatePipe: true,
95
102
  },
@@ -196,7 +203,14 @@ const config: { [env: string]: IServerOptions } = {
196
203
  },
197
204
  port: 3000,
198
205
  security: {
199
- checkResponseInterceptor: true,
206
+ checkResponseInterceptor: {
207
+ checkObjectItself: false,
208
+ debug: false,
209
+ ignoreUndefined: true,
210
+ mergeRoles: true,
211
+ removeUndefinedFromResultArray: true,
212
+ throwError: false,
213
+ },
200
214
  checkSecurityInterceptor: true,
201
215
  mapAndValidatePipe: true,
202
216
  },
@@ -292,7 +306,14 @@ const config: { [env: string]: IServerOptions } = {
292
306
  },
293
307
  port: 3000,
294
308
  security: {
295
- checkResponseInterceptor: true,
309
+ checkResponseInterceptor: {
310
+ checkObjectItself: false,
311
+ debug: false,
312
+ ignoreUndefined: true,
313
+ mergeRoles: true,
314
+ removeUndefinedFromResultArray: true,
315
+ throwError: false,
316
+ },
296
317
  checkSecurityInterceptor: true,
297
318
  mapAndValidatePipe: true,
298
319
  },
@@ -67,15 +67,20 @@ export const checkRestricted = (
67
67
  dbObject?: any;
68
68
  debug?: boolean;
69
69
  ignoreUndefined?: boolean;
70
+ mergeRoles?: boolean;
70
71
  processType?: ProcessType;
71
72
  removeUndefinedFromResultArray?: boolean;
72
73
  throwError?: boolean;
73
74
  } = {},
74
75
  processedObjects: any[] = [],
75
76
  ) => {
77
+ // Act like Roles handling: checkObjectItself = false & mergeRoles = true
78
+ // For Input: throwError = true
79
+ // For Output: throwError = false
76
80
  const config = {
77
- checkObjectItself: true,
81
+ checkObjectItself: false,
78
82
  ignoreUndefined: true,
83
+ mergeRoles: true,
79
84
  removeUndefinedFromResultArray: true,
80
85
  throwError: true,
81
86
  ...options,
@@ -220,7 +225,8 @@ export const checkRestricted = (
220
225
 
221
226
  // Check restricted
222
227
  const restricted = getRestricted(data, propertyKey) || [];
223
- const valid = validateRestricted(restricted);
228
+ const concatenatedRestrictions = config.mergeRoles ? _.uniq(objectRestrictions.concat(restricted)) : restricted;
229
+ const valid = validateRestricted(concatenatedRestrictions);
224
230
 
225
231
  // Check rights
226
232
  if (valid) {
@@ -4,12 +4,29 @@ import { map } from 'rxjs/operators';
4
4
 
5
5
  import { checkRestricted } from '../decorators/restricted.decorator';
6
6
  import { getContextData } from '../helpers/context.helper';
7
+ import { ConfigService } from '../services/config.service';
7
8
 
8
9
  /**
9
10
  * Interceptor to check the response data for current user
10
11
  */
11
12
  @Injectable()
12
13
  export class CheckResponseInterceptor implements NestInterceptor {
14
+ config = {
15
+ checkObjectItself: false,
16
+ debug: false,
17
+ ignoreUndefined: true,
18
+ mergeRoles: true,
19
+ removeUndefinedFromResultArray: true,
20
+ throwError: false,
21
+ };
22
+
23
+ constructor(private readonly configService: ConfigService) {
24
+ const configuration = this.configService.getFastButReadOnly('security.checkResponseInterceptor');
25
+ if (typeof configuration === 'object') {
26
+ this.config = { ...this.config, ...configuration };
27
+ }
28
+ }
29
+
13
30
  /**
14
31
  * Interception
15
32
  */
@@ -21,7 +38,7 @@ export class CheckResponseInterceptor implements NestInterceptor {
21
38
  return next.handle().pipe(
22
39
  map((data) => {
23
40
  // Prepare response data for current user
24
- return checkRestricted(data, currentUser, { throwError: false });
41
+ return checkRestricted(data, currentUser, this.config);
25
42
  }),
26
43
  );
27
44
  }
@@ -410,9 +410,47 @@ export interface IServerOptions {
410
410
  /**
411
411
  * Check restrictions for output (models and output objects)
412
412
  * See @lenne.tech/nest-server/src/core/common/interceptors/check-response.interceptor.ts
413
- * default = true
414
413
  */
415
- checkResponseInterceptor?: boolean;
414
+ checkResponseInterceptor?:
415
+ | {
416
+ /**
417
+ * Check the object itself for restrictions
418
+ * (the class restriction is not only default for properties but object itself)
419
+ * default = false (to act like Roles)
420
+ */
421
+ checkObjectItself?: boolean;
422
+
423
+ /**
424
+ * Whether to log if a restricted field is found
425
+ * default = false
426
+ */
427
+ debug?: boolean;
428
+
429
+ /**
430
+ * Whether to ignore fields with undefined values
431
+ * default = true
432
+ */
433
+ ignoreUndefined?: boolean;
434
+
435
+ /**
436
+ * Merge roles of object and properties
437
+ * default = true (to act like Roles)
438
+ */
439
+ mergeRoles?: boolean;
440
+
441
+ /**
442
+ * Remove undefined values from result array
443
+ * default = true
444
+ */
445
+ removeUndefinedFromResultArray?: boolean;
446
+
447
+ /**
448
+ * Whether to throw an error if a restricted field is found
449
+ * default = false (for output objects)
450
+ */
451
+ throwError?: boolean;
452
+ }
453
+ | boolean;
416
454
 
417
455
  /**
418
456
  * Process securityCheck() methode of Object before response
@@ -2,6 +2,8 @@ import { Field, ID, ObjectType } from '@nestjs/graphql';
2
2
  import { Prop, Schema } from '@nestjs/mongoose';
3
3
  import { Types } from 'mongoose';
4
4
 
5
+ import { Restricted } from '../decorators/restricted.decorator';
6
+ import { RoleEnum } from '../enums/role.enum';
5
7
  import { CoreModel } from './core-model.model';
6
8
 
7
9
  /**
@@ -26,6 +28,7 @@ export abstract class CorePersistenceModel extends CoreModel {
26
28
  // Getter
27
29
  // ===========================================================================
28
30
 
31
+ @Restricted(RoleEnum.S_EVERYONE)
29
32
  get _id() {
30
33
  return new Types.ObjectId(this.id);
31
34
  }
@@ -37,6 +40,7 @@ export abstract class CorePersistenceModel extends CoreModel {
37
40
  /**
38
41
  * ID of the persistence object as string
39
42
  */
43
+ @Restricted(RoleEnum.S_EVERYONE)
40
44
  @Field(type => ID, {
41
45
  description: 'ID of the persistence object',
42
46
  nullable: true,
@@ -46,6 +50,7 @@ export abstract class CorePersistenceModel extends CoreModel {
46
50
  /**
47
51
  * Created date, is set automatically by mongoose
48
52
  */
53
+ @Restricted(RoleEnum.S_EVERYONE)
49
54
  @Field({ description: 'Created date', nullable: true })
50
55
  @Prop({ onCreate: () => new Date() })
51
56
  createdAt: Date = undefined;
@@ -53,6 +58,7 @@ export abstract class CorePersistenceModel extends CoreModel {
53
58
  /**
54
59
  * Labels of the object
55
60
  */
61
+ @Restricted(RoleEnum.S_EVERYONE)
56
62
  @Field(type => [String], {
57
63
  description: 'Labels of the object',
58
64
  nullable: true,
@@ -63,6 +69,7 @@ export abstract class CorePersistenceModel extends CoreModel {
63
69
  /**
64
70
  * Tags for the object
65
71
  */
72
+ @Restricted(RoleEnum.S_EVERYONE)
66
73
  @Field(type => [String], {
67
74
  description: 'Tags for the object',
68
75
  nullable: true,
@@ -73,6 +80,7 @@ export abstract class CorePersistenceModel extends CoreModel {
73
80
  /**
74
81
  * Updated date is set automatically by mongoose
75
82
  */
83
+ @Restricted(RoleEnum.S_EVERYONE)
76
84
  @Field({ description: 'Updated date', nullable: true })
77
85
  @Prop({ onUpdate: () => new Date() })
78
86
  updatedAt: Date = undefined;