@lenne.tech/nest-server 10.2.14 → 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.14",
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",
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;