@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/dist/config.env.js +24 -3
- package/dist/config.env.js.map +1 -1
- package/dist/core/common/decorators/restricted.decorator.d.ts +1 -0
- package/dist/core/common/decorators/restricted.decorator.js +5 -2
- package/dist/core/common/decorators/restricted.decorator.js.map +1 -1
- package/dist/core/common/interceptors/check-response.interceptor.d.ts +11 -0
- package/dist/core/common/interceptors/check-response.interceptor.js +22 -2
- package/dist/core/common/interceptors/check-response.interceptor.js.map +1 -1
- package/dist/core/common/interfaces/server-options.interface.d.ts +8 -1
- package/dist/core/common/models/core-persistence.model.js +12 -0
- package/dist/core/common/models/core-persistence.model.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/config.env.ts +24 -3
- package/src/core/common/decorators/restricted.decorator.ts +8 -2
- package/src/core/common/interceptors/check-response.interceptor.ts +18 -1
- package/src/core/common/interfaces/server-options.interface.ts +40 -2
- package/src/core/common/models/core-persistence.model.ts +8 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lenne.tech/nest-server",
|
|
3
|
-
"version": "10.2.
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
|
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,
|
|
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?:
|
|
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;
|