@lenne.tech/nest-server 3.1.2 → 3.3.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.
- package/dist/core/common/args/filter.args.d.ts +5 -0
- package/dist/core/common/args/filter.args.js +10 -0
- package/dist/core/common/args/filter.args.js.map +1 -1
- package/dist/core/common/args/pagination.args.d.ts +8 -1
- package/dist/core/common/args/pagination.args.js +24 -6
- package/dist/core/common/args/pagination.args.js.map +1 -1
- package/dist/core/common/decorators/restricted.decorator.d.ts +3 -0
- package/dist/core/common/decorators/restricted.decorator.js +16 -5
- package/dist/core/common/decorators/restricted.decorator.js.map +1 -1
- package/dist/core/common/helpers/context.helper.js +15 -5
- package/dist/core/common/helpers/context.helper.js.map +1 -1
- package/dist/core/common/helpers/filter.helper.d.ts +3 -3
- package/dist/core/common/helpers/filter.helper.js.map +1 -1
- package/dist/core/common/helpers/input.helper.js +13 -7
- package/dist/core/common/helpers/input.helper.js.map +1 -1
- package/dist/core/common/helpers/service.helper.d.ts +6 -8
- package/dist/core/common/helpers/service.helper.js +34 -12
- package/dist/core/common/helpers/service.helper.js.map +1 -1
- package/dist/core/common/inputs/combined-filter.input.d.ts +8 -2
- package/dist/core/common/inputs/combined-filter.input.js +16 -5
- package/dist/core/common/inputs/combined-filter.input.js.map +1 -1
- package/dist/core/common/inputs/core-input.input.d.ts +8 -0
- package/dist/core/common/inputs/core-input.input.js +15 -0
- package/dist/core/common/inputs/core-input.input.js.map +1 -0
- package/dist/core/common/inputs/filter.input.d.ts +7 -1
- package/dist/core/common/inputs/filter.input.js +14 -1
- package/dist/core/common/inputs/filter.input.js.map +1 -1
- package/dist/core/common/inputs/single-filter.input.d.ts +2 -1
- package/dist/core/common/inputs/single-filter.input.js +10 -1
- package/dist/core/common/inputs/single-filter.input.js.map +1 -1
- package/dist/core/common/inputs/sort.input.d.ts +2 -1
- package/dist/core/common/inputs/sort.input.js +7 -1
- package/dist/core/common/inputs/sort.input.js.map +1 -1
- package/dist/core/common/interceptors/check-response.interceptor.js +1 -1
- package/dist/core/common/interceptors/check-response.interceptor.js.map +1 -1
- package/dist/core/common/models/core-model.model.d.ts +6 -0
- package/dist/core/common/models/core-model.model.js +10 -3
- package/dist/core/common/models/core-model.model.js.map +1 -1
- package/dist/core/common/models/core-persistence.model.d.ts +5 -29
- package/dist/core/common/models/core-persistence.model.js +19 -41
- package/dist/core/common/models/core-persistence.model.js.map +1 -1
- package/dist/core/common/pipes/check-input.pipe.d.ts +2 -3
- package/dist/core/common/pipes/check-input.pipe.js +5 -20
- package/dist/core/common/pipes/check-input.pipe.js.map +1 -1
- package/dist/core/common/pipes/map-and-validate.pipe.d.ts +4 -0
- package/dist/core/common/pipes/map-and-validate.pipe.js +40 -0
- package/dist/core/common/pipes/map-and-validate.pipe.js.map +1 -0
- package/dist/core/common/types/plain-input.type.d.ts +3 -0
- package/dist/core/common/types/plain-input.type.js +3 -0
- package/dist/core/common/types/plain-input.type.js.map +1 -0
- package/dist/core/modules/auth/core-auth.model.d.ts +3 -1
- package/dist/core/modules/auth/core-auth.model.js +7 -1
- package/dist/core/modules/auth/core-auth.model.js.map +1 -1
- package/dist/core/modules/auth/core-auth.resolver.d.ts +1 -1
- package/dist/core/modules/user/core-user.model.d.ts +3 -0
- package/dist/core/modules/user/core-user.model.js +10 -4
- package/dist/core/modules/user/core-user.model.js.map +1 -1
- package/dist/core/modules/user/core-user.service.d.ts +9 -13
- package/dist/core/modules/user/core-user.service.js +38 -67
- package/dist/core/modules/user/core-user.service.js.map +1 -1
- package/dist/core/modules/user/inputs/core-user-create.input.js +4 -0
- package/dist/core/modules/user/inputs/core-user-create.input.js.map +1 -1
- package/dist/core/modules/user/inputs/core-user.input.d.ts +2 -1
- package/dist/core/modules/user/inputs/core-user.input.js +12 -2
- package/dist/core/modules/user/inputs/core-user.input.js.map +1 -1
- package/dist/core.module.js +2 -3
- package/dist/core.module.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/server/common/models/persistence.model.d.ts +1 -0
- package/dist/server/common/models/persistence.model.js +4 -0
- package/dist/server/common/models/persistence.model.js.map +1 -1
- package/dist/server/modules/auth/auth.model.d.ts +1 -0
- package/dist/server/modules/auth/auth.model.js +4 -0
- package/dist/server/modules/auth/auth.model.js.map +1 -1
- package/dist/server/modules/user/inputs/user-create.input.js.map +1 -1
- package/dist/server/modules/user/inputs/user.input.js.map +1 -1
- package/dist/server/modules/user/user.model.d.ts +3 -2
- package/dist/server/modules/user/user.model.js +9 -5
- package/dist/server/modules/user/user.model.js.map +1 -1
- package/dist/server/modules/user/user.resolver.d.ts +2 -2
- package/dist/server/modules/user/user.resolver.js +10 -12
- package/dist/server/modules/user/user.resolver.js.map +1 -1
- package/dist/server/modules/user/user.service.d.ts +7 -9
- package/dist/server/modules/user/user.service.js +12 -4
- package/dist/server/modules/user/user.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/core/common/args/filter.args.ts +22 -1
- package/src/core/common/args/pagination.args.ts +42 -7
- package/src/core/common/decorators/restricted.decorator.ts +24 -5
- package/src/core/common/helpers/context.helper.ts +14 -3
- package/src/core/common/helpers/filter.helper.ts +3 -3
- package/src/core/common/helpers/input.helper.ts +17 -11
- package/src/core/common/helpers/service.helper.ts +42 -19
- package/src/core/common/inputs/combined-filter.input.ts +30 -9
- package/src/core/common/inputs/core-input.input.ts +36 -0
- package/src/core/common/inputs/filter.input.ts +27 -3
- package/src/core/common/inputs/single-filter.input.ts +7 -6
- package/src/core/common/inputs/sort.input.ts +4 -3
- package/src/core/common/interceptors/check-response.interceptor.ts +2 -2
- package/src/core/common/models/core-model.model.ts +30 -1
- package/src/core/common/models/core-persistence.model.ts +33 -120
- package/src/core/common/pipes/check-input.pipe.ts +13 -33
- package/src/core/common/pipes/map-and-validate.pipe.ts +32 -0
- package/src/core/common/types/plain-input.type.ts +6 -0
- package/src/core/modules/auth/core-auth.model.ts +15 -1
- package/src/core/modules/auth/core-auth.resolver.ts +1 -1
- package/src/core/modules/user/core-user.model.ts +17 -4
- package/src/core/modules/user/core-user.service.ts +59 -115
- package/src/core/modules/user/inputs/core-user-create.input.ts +5 -1
- package/src/core/modules/user/inputs/core-user.input.ts +13 -8
- package/src/core.module.ts +11 -5
- package/src/index.ts +6 -2
- package/src/server/common/models/persistence.model.ts +13 -0
- package/src/server/modules/auth/auth.model.ts +13 -0
- package/src/server/modules/user/inputs/user-create.input.ts +4 -0
- package/src/server/modules/user/inputs/user.input.ts +4 -0
- package/src/server/modules/user/user.model.ts +18 -5
- package/src/server/modules/user/user.resolver.ts +15 -19
- package/src/server/modules/user/user.service.ts +22 -7
|
@@ -2,8 +2,23 @@ import { ModelHelper } from '../helpers/model.helper';
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Core Model
|
|
5
|
+
*
|
|
6
|
+
* HINT: All properties (in this class and all classes that extend this class) must be initialized with a default
|
|
7
|
+
* value or undefined otherwise the property will not be recognized via Object.keys (this is necessary for mapping).
|
|
8
|
+
* If the property is initialized with a default value (e.g. an empty array or boolean), there is a risk that the
|
|
9
|
+
* current value will be overwritten during mapping without this being intentional, so all values should be initialized
|
|
10
|
+
* with undefined if possible. If necessary and useful, the init method can then be used deliberately:
|
|
11
|
+
* const coreModel = item ? CoreModel.map(item).init() : CoreModel.init();
|
|
5
12
|
*/
|
|
6
13
|
export abstract class CoreModel {
|
|
14
|
+
/**
|
|
15
|
+
* Static init method
|
|
16
|
+
*/
|
|
17
|
+
public static init<T extends CoreModel>(this: new (...args: any[]) => T, ...args: any[]): T {
|
|
18
|
+
const item = new this();
|
|
19
|
+
return item.init(args);
|
|
20
|
+
}
|
|
21
|
+
|
|
7
22
|
/**
|
|
8
23
|
* Static map method
|
|
9
24
|
*/
|
|
@@ -13,6 +28,7 @@ export abstract class CoreModel {
|
|
|
13
28
|
options: {
|
|
14
29
|
cloneDeep?: boolean;
|
|
15
30
|
funcAllowed?: boolean;
|
|
31
|
+
init?: boolean;
|
|
16
32
|
item?: T;
|
|
17
33
|
mapId?: boolean;
|
|
18
34
|
} = {}
|
|
@@ -36,6 +52,7 @@ export abstract class CoreModel {
|
|
|
36
52
|
options: {
|
|
37
53
|
cloneDeep?: boolean;
|
|
38
54
|
funcAllowed?: boolean;
|
|
55
|
+
init?: boolean;
|
|
39
56
|
item?: T;
|
|
40
57
|
mapId?: boolean;
|
|
41
58
|
} = {}
|
|
@@ -45,6 +62,14 @@ export abstract class CoreModel {
|
|
|
45
62
|
return item.mapDeep(data, options);
|
|
46
63
|
}
|
|
47
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Initialize instance with default values instead of undefined
|
|
67
|
+
* Should be overwritten in child class to organize the defaults
|
|
68
|
+
*/
|
|
69
|
+
public init<T extends CoreModel>(...args: any[]): this {
|
|
70
|
+
return this;
|
|
71
|
+
}
|
|
72
|
+
|
|
48
73
|
/**
|
|
49
74
|
* Map method
|
|
50
75
|
*/
|
|
@@ -53,16 +78,18 @@ export abstract class CoreModel {
|
|
|
53
78
|
options: {
|
|
54
79
|
cloneDeep?: boolean;
|
|
55
80
|
funcAllowed?: boolean;
|
|
81
|
+
init?: any;
|
|
56
82
|
mapId?: boolean;
|
|
57
83
|
} = {}
|
|
58
84
|
): this {
|
|
59
85
|
const config = {
|
|
60
86
|
cloneDeep: false,
|
|
61
87
|
funcAllowed: false,
|
|
88
|
+
init: undefined,
|
|
62
89
|
mapId: false,
|
|
63
90
|
...options,
|
|
64
91
|
};
|
|
65
|
-
return ModelHelper.map(data, this, config);
|
|
92
|
+
return config.init ? ModelHelper.map(data, this, config).init(config.init) : ModelHelper.map(data, this, config);
|
|
66
93
|
}
|
|
67
94
|
|
|
68
95
|
/**
|
|
@@ -78,12 +105,14 @@ export abstract class CoreModel {
|
|
|
78
105
|
options: {
|
|
79
106
|
cloneDeep?: boolean;
|
|
80
107
|
funcAllowed?: boolean;
|
|
108
|
+
init?: boolean;
|
|
81
109
|
mapId?: boolean;
|
|
82
110
|
} = {}
|
|
83
111
|
): this {
|
|
84
112
|
const config = {
|
|
85
113
|
cloneDeep: true,
|
|
86
114
|
funcAllowed: false,
|
|
115
|
+
init: false,
|
|
87
116
|
mapId: false,
|
|
88
117
|
...options,
|
|
89
118
|
};
|
|
@@ -1,32 +1,38 @@
|
|
|
1
1
|
import { Field, ID, ObjectType } from '@nestjs/graphql';
|
|
2
|
-
import * as _ from 'lodash';
|
|
3
|
-
import { ModelHelper } from '../helpers/model.helper';
|
|
4
2
|
import { Prop, Schema } from '@nestjs/mongoose';
|
|
5
|
-
import
|
|
3
|
+
import { Types } from 'mongoose';
|
|
4
|
+
import { CoreModel } from './core-model.model';
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* Metadata for persistent objects
|
|
9
8
|
*
|
|
10
9
|
* The models are a combination of Mongoose Entities and TypeGraphQL Types
|
|
10
|
+
*
|
|
11
|
+
* HINT: All properties (in this class and all classes that extend this class) must be initialized with a default
|
|
12
|
+
* value or undefined otherwise the property will not be recognized via Object.keys (this is necessary for mapping).
|
|
13
|
+
* If the property is initialized with a default value (e.g. an empty array or boolean), there is a risk that the
|
|
14
|
+
* current value will be overwritten during mapping without this being intentional, so all values should be initialized
|
|
15
|
+
* with undefined if possible. If necessary and useful, the init method can then be used deliberately:
|
|
16
|
+
* const corePersistenceModel = item ? CorePersistenceModel.map(item).init() : CorePersistenceModel.init();
|
|
11
17
|
*/
|
|
12
18
|
@ObjectType({
|
|
13
19
|
description: 'Persistence model which will be saved in DB',
|
|
14
20
|
isAbstract: true,
|
|
15
21
|
})
|
|
16
|
-
@Schema()
|
|
17
|
-
export abstract class CorePersistenceModel {
|
|
22
|
+
@Schema({ timestamps: true })
|
|
23
|
+
export abstract class CorePersistenceModel extends CoreModel {
|
|
18
24
|
// ===========================================================================
|
|
19
25
|
// Getter
|
|
20
26
|
// ===========================================================================
|
|
27
|
+
|
|
21
28
|
get _id() {
|
|
22
|
-
return new
|
|
29
|
+
return new Types.ObjectId(this.id);
|
|
23
30
|
}
|
|
24
31
|
|
|
25
32
|
// ===========================================================================
|
|
26
33
|
// Properties
|
|
27
|
-
//
|
|
28
|
-
// TestFields: https://typegraphql.ml/docs/types-and-fields.html
|
|
29
34
|
// ===========================================================================
|
|
35
|
+
|
|
30
36
|
/**
|
|
31
37
|
* ID of the persistence object as string
|
|
32
38
|
*/
|
|
@@ -37,11 +43,11 @@ export abstract class CorePersistenceModel {
|
|
|
37
43
|
id: string = undefined;
|
|
38
44
|
|
|
39
45
|
/**
|
|
40
|
-
* Created date
|
|
46
|
+
* Created date, is set automatically by mongoose
|
|
41
47
|
*/
|
|
42
48
|
@Field({ description: 'Created date', nullable: true })
|
|
43
|
-
@Prop()
|
|
44
|
-
createdAt: Date =
|
|
49
|
+
@Prop({ onCreate: () => new Date() })
|
|
50
|
+
createdAt: Date = undefined;
|
|
45
51
|
|
|
46
52
|
/**
|
|
47
53
|
* Labels of the object
|
|
@@ -51,7 +57,7 @@ export abstract class CorePersistenceModel {
|
|
|
51
57
|
nullable: true,
|
|
52
58
|
})
|
|
53
59
|
@Prop([String])
|
|
54
|
-
labels: string[] =
|
|
60
|
+
labels: string[] = undefined;
|
|
55
61
|
|
|
56
62
|
/**
|
|
57
63
|
* IDs of the Owners
|
|
@@ -61,7 +67,7 @@ export abstract class CorePersistenceModel {
|
|
|
61
67
|
nullable: true,
|
|
62
68
|
})
|
|
63
69
|
@Prop([String])
|
|
64
|
-
ownerIds: string[] =
|
|
70
|
+
ownerIds: string[] = undefined;
|
|
65
71
|
|
|
66
72
|
/**
|
|
67
73
|
* Tags for the object
|
|
@@ -71,122 +77,29 @@ export abstract class CorePersistenceModel {
|
|
|
71
77
|
nullable: true,
|
|
72
78
|
})
|
|
73
79
|
@Prop([String])
|
|
74
|
-
tags: string[] =
|
|
80
|
+
tags: string[] = undefined;
|
|
75
81
|
|
|
76
82
|
/**
|
|
77
|
-
* Updated date
|
|
83
|
+
* Updated date is set automatically by mongoose
|
|
78
84
|
*/
|
|
79
85
|
@Field({ description: 'Updated date', nullable: true })
|
|
80
86
|
@Prop({ onUpdate: () => new Date() })
|
|
81
|
-
updatedAt: Date =
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Static map method
|
|
85
|
-
*/
|
|
86
|
-
public static map<T extends CorePersistenceModel>(
|
|
87
|
-
this: new (...args: any[]) => T,
|
|
88
|
-
data: Partial<T> | Record<string, any>,
|
|
89
|
-
options: {
|
|
90
|
-
cloneDeep?: boolean;
|
|
91
|
-
funcAllowed?: boolean;
|
|
92
|
-
item?: T;
|
|
93
|
-
mapId?: boolean;
|
|
94
|
-
merge?: boolean;
|
|
95
|
-
} = {}
|
|
96
|
-
): T {
|
|
97
|
-
const item = options.item || new this();
|
|
98
|
-
delete options.item;
|
|
99
|
-
return item.map(data, options);
|
|
100
|
-
}
|
|
87
|
+
updatedAt: Date = undefined;
|
|
101
88
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
* Alias for map with cloneDeep = true
|
|
106
|
-
*
|
|
107
|
-
* MapDeep prevents side effects, because objects will be cloned
|
|
108
|
-
* (cloneDeep = true), but it will be slower than a simple map
|
|
109
|
-
*/
|
|
110
|
-
public static mapDeep<T extends CorePersistenceModel>(
|
|
111
|
-
this: new (...args: any[]) => T,
|
|
112
|
-
data: Partial<T> | Record<string, any>,
|
|
113
|
-
options: {
|
|
114
|
-
cloneDeep?: boolean;
|
|
115
|
-
funcAllowed?: boolean;
|
|
116
|
-
item?: T;
|
|
117
|
-
mapId?: boolean;
|
|
118
|
-
merge?: boolean;
|
|
119
|
-
} = {}
|
|
120
|
-
): T {
|
|
121
|
-
const item = options.item || new this();
|
|
122
|
-
delete options.item;
|
|
123
|
-
return item.mapDeep(data, options);
|
|
124
|
-
}
|
|
89
|
+
// ===========================================================================
|
|
90
|
+
// Properties
|
|
91
|
+
// ===========================================================================
|
|
125
92
|
|
|
126
93
|
/**
|
|
127
|
-
*
|
|
94
|
+
* Initialize instance with default values instead of undefined
|
|
128
95
|
*/
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
} = {}
|
|
137
|
-
): this {
|
|
138
|
-
const config = {
|
|
139
|
-
cloneDeep: false,
|
|
140
|
-
funcAllowed: false,
|
|
141
|
-
mapId: false,
|
|
142
|
-
merge: false,
|
|
143
|
-
...options,
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
// Prepare data
|
|
147
|
-
let preparedData = data;
|
|
148
|
-
preparedData = ModelHelper.prepareMap(preparedData, this, config);
|
|
149
|
-
if (config.cloneDeep) {
|
|
150
|
-
preparedData = _.cloneDeep(preparedData);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Assign
|
|
154
|
-
if (this['assign'] !== 'function') {
|
|
155
|
-
if (!config.merge) {
|
|
156
|
-
Object.assign(this, preparedData);
|
|
157
|
-
}
|
|
158
|
-
} else {
|
|
159
|
-
this['assign'](preparedData, { mergeObjects: config.merge });
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Return
|
|
96
|
+
init() {
|
|
97
|
+
super.init();
|
|
98
|
+
this.createdAt = this.createdAt === undefined ? new Date() : this.createdAt;
|
|
99
|
+
this.labels = this.labels === undefined ? [] : this.labels;
|
|
100
|
+
this.ownerIds = this.ownerIds === undefined ? [] : this.ownerIds;
|
|
101
|
+
this.tags = this.tags === undefined ? [] : this.tags;
|
|
102
|
+
this.updatedAt = this.tags === undefined ? this.createdAt : this.updatedAt;
|
|
163
103
|
return this;
|
|
164
104
|
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Map deep method
|
|
168
|
-
*
|
|
169
|
-
* Alias for map with cloneDeep = true
|
|
170
|
-
*
|
|
171
|
-
* MapDeep prevents side effects, because objects will be cloned
|
|
172
|
-
* (cloneDeep = true), but it will be slower than a simple map
|
|
173
|
-
*/
|
|
174
|
-
public mapDeep(
|
|
175
|
-
data: Partial<this> | Record<string, any>,
|
|
176
|
-
options: {
|
|
177
|
-
cloneDeep?: boolean;
|
|
178
|
-
funcAllowed?: boolean;
|
|
179
|
-
mapId?: boolean;
|
|
180
|
-
merge?: boolean;
|
|
181
|
-
} = {}
|
|
182
|
-
): this {
|
|
183
|
-
const config = {
|
|
184
|
-
cloneDeep: true,
|
|
185
|
-
funcAllowed: false,
|
|
186
|
-
mapId: false,
|
|
187
|
-
merge: false,
|
|
188
|
-
...options,
|
|
189
|
-
};
|
|
190
|
-
return this.map(data, config);
|
|
191
|
-
}
|
|
192
105
|
}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import { ArgumentMetadata,
|
|
1
|
+
import { ArgumentMetadata, Inject, Injectable, PipeTransform } from '@nestjs/common';
|
|
2
2
|
import { CONTEXT } from '@nestjs/graphql';
|
|
3
|
-
import { plainToClass } from 'class-transformer';
|
|
4
|
-
import { validate, ValidationError } from 'class-validator';
|
|
5
|
-
import { checkRestricted } from '../decorators/restricted.decorator';
|
|
6
3
|
import { Context } from '../helpers/context.helper';
|
|
4
|
+
import { InputHelper } from '../helpers/input.helper';
|
|
7
5
|
|
|
8
6
|
/**
|
|
9
7
|
* The CheckInputPipe checks the permissibility of individual properties of inputs for the resolvers
|
|
10
8
|
* in relation to the current user
|
|
9
|
+
*
|
|
10
|
+
* ATTENTION: Pipe does not work yet, because context is missing: https://github.com/nestjs/graphql/issues/325
|
|
11
|
+
* Once this works MapAndValidate can be replaced in the CoreModule with this pipe.
|
|
11
12
|
*/
|
|
12
|
-
@Injectable(
|
|
13
|
-
export class CheckInputPipe implements PipeTransform
|
|
13
|
+
@Injectable()
|
|
14
|
+
export class CheckInputPipe implements PipeTransform {
|
|
14
15
|
/**
|
|
15
16
|
* Constructor to inject context
|
|
16
17
|
*/
|
|
@@ -19,35 +20,14 @@ export class CheckInputPipe implements PipeTransform<any> {
|
|
|
19
20
|
/**
|
|
20
21
|
* Check input
|
|
21
22
|
*/
|
|
22
|
-
async transform(value: any,
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
return value;
|
|
26
|
-
}
|
|
23
|
+
async transform(value: any, metadata: ArgumentMetadata) {
|
|
24
|
+
// Get meta type
|
|
25
|
+
const metatype = metadata?.metatype;
|
|
27
26
|
|
|
28
|
-
//
|
|
27
|
+
// Get user
|
|
29
28
|
const { user }: any = Context.getData(this.context);
|
|
30
|
-
value = checkRestricted(value, user);
|
|
31
29
|
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
const object = plainToClass(metatype, plainValue);
|
|
35
|
-
const errors: ValidationError[] = await validate(object);
|
|
36
|
-
|
|
37
|
-
// Check errors
|
|
38
|
-
if (errors.length > 0) {
|
|
39
|
-
throw new BadRequestException('Validation failed');
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Everything is ok
|
|
43
|
-
return value;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Checks if it is a basic type
|
|
48
|
-
*/
|
|
49
|
-
protected isBasicType(metatype: any): boolean {
|
|
50
|
-
const types = [String, Boolean, Number, Array, Object, Buffer, ArrayBuffer];
|
|
51
|
-
return types.includes(metatype);
|
|
30
|
+
// Check and return
|
|
31
|
+
return InputHelper.check(value, user, metatype);
|
|
52
32
|
}
|
|
53
33
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException } from '@nestjs/common';
|
|
2
|
+
import { plainToInstance } from 'class-transformer';
|
|
3
|
+
import { validate } from 'class-validator';
|
|
4
|
+
import { InputHelper } from '../helpers/input.helper';
|
|
5
|
+
|
|
6
|
+
@Injectable()
|
|
7
|
+
export class MapAndValidatePipe implements PipeTransform {
|
|
8
|
+
async transform(value: any, metadata: ArgumentMetadata) {
|
|
9
|
+
const { metatype } = metadata;
|
|
10
|
+
|
|
11
|
+
if (typeof value !== 'object' || !metatype || InputHelper.isBasicType(metatype)) {
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Convert to metatype
|
|
16
|
+
if (!(value instanceof metatype)) {
|
|
17
|
+
if ((metatype as any)?.map) {
|
|
18
|
+
value = (metatype as any)?.map(value);
|
|
19
|
+
} else {
|
|
20
|
+
value = plainToInstance(metatype, value);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Validate
|
|
25
|
+
const errors = await validate(value);
|
|
26
|
+
if (errors.length > 0) {
|
|
27
|
+
throw new BadRequestException('Input validation failed');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { Field, ObjectType } from '@nestjs/graphql';
|
|
2
|
+
import { CoreModel } from '../../common/models/core-model.model';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* CoreAuth model for the response after the sign in
|
|
5
6
|
*/
|
|
6
7
|
@ObjectType({ description: 'CoreAuth', isAbstract: true })
|
|
7
|
-
export class CoreAuthModel {
|
|
8
|
+
export class CoreAuthModel extends CoreModel {
|
|
8
9
|
// ===================================================================================================================
|
|
9
10
|
// Properties
|
|
10
11
|
// ===================================================================================================================
|
|
@@ -14,4 +15,17 @@ export class CoreAuthModel {
|
|
|
14
15
|
*/
|
|
15
16
|
@Field({ description: 'JavaScript Web Token (JWT)' })
|
|
16
17
|
token: string = undefined;
|
|
18
|
+
|
|
19
|
+
// ===================================================================================================================
|
|
20
|
+
// Properties
|
|
21
|
+
// ===================================================================================================================
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Initialize instance with default values instead of undefined
|
|
25
|
+
*/
|
|
26
|
+
init() {
|
|
27
|
+
super.init();
|
|
28
|
+
// Nothing more to initialize yet
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
17
31
|
}
|
|
@@ -20,7 +20,7 @@ export class CoreAuthResolver {
|
|
|
20
20
|
* Get user via ID
|
|
21
21
|
*/
|
|
22
22
|
@Query((returns) => CoreAuthModel, { description: 'Get JWT token' })
|
|
23
|
-
async signIn(@Args('email') email: string, @Args('password') password: string): Promise<CoreAuthModel
|
|
23
|
+
async signIn(@Args('email') email: string, @Args('password') password: string): Promise<Partial<CoreAuthModel>> {
|
|
24
24
|
return await this.authService.signIn(email, password);
|
|
25
25
|
}
|
|
26
26
|
}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { Field, ObjectType } from '@nestjs/graphql';
|
|
2
2
|
import { IsEmail, IsOptional } from 'class-validator';
|
|
3
|
+
import { Document } from 'mongoose';
|
|
3
4
|
import { CorePersistenceModel } from '../../common/models/core-persistence.model';
|
|
4
|
-
import { Prop, Schema } from '@nestjs/mongoose';
|
|
5
|
+
import { Prop, Schema as MongooseSchema } from '@nestjs/mongoose';
|
|
6
|
+
|
|
7
|
+
export type CoreUserModelDocument = CoreUserModel & Document;
|
|
5
8
|
|
|
6
9
|
/**
|
|
7
10
|
* User model
|
|
8
11
|
*/
|
|
9
12
|
@ObjectType({ description: 'User', isAbstract: true })
|
|
10
|
-
@
|
|
13
|
+
@MongooseSchema({ timestamps: true })
|
|
11
14
|
export abstract class CoreUserModel extends CorePersistenceModel {
|
|
12
15
|
// ===================================================================================================================
|
|
13
16
|
// Properties
|
|
@@ -49,7 +52,7 @@ export abstract class CoreUserModel extends CorePersistenceModel {
|
|
|
49
52
|
@Field((type) => [String], { description: 'Roles of the user', nullable: true })
|
|
50
53
|
@IsOptional()
|
|
51
54
|
@Prop()
|
|
52
|
-
roles: string[] =
|
|
55
|
+
roles: string[] = undefined;
|
|
53
56
|
|
|
54
57
|
/**
|
|
55
58
|
* Username of the user
|
|
@@ -76,8 +79,9 @@ export abstract class CoreUserModel extends CorePersistenceModel {
|
|
|
76
79
|
/**
|
|
77
80
|
* Verification of the user
|
|
78
81
|
*/
|
|
82
|
+
@Field((type) => Boolean, { description: 'Verification state of the user', nullable: true })
|
|
79
83
|
@Prop({ type: Boolean })
|
|
80
|
-
verified =
|
|
84
|
+
verified: boolean = undefined;
|
|
81
85
|
|
|
82
86
|
// ===================================================================================================================
|
|
83
87
|
// Methods
|
|
@@ -108,4 +112,13 @@ export abstract class CoreUserModel extends CorePersistenceModel {
|
|
|
108
112
|
}
|
|
109
113
|
return !roles ? true : roles.every((role) => this.roles.includes(role));
|
|
110
114
|
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Initialize instance with default values instead of undefined
|
|
118
|
+
*/
|
|
119
|
+
public init() {
|
|
120
|
+
super.init();
|
|
121
|
+
this.roles = this.roles === undefined ? [] : this.roles;
|
|
122
|
+
return this;
|
|
123
|
+
}
|
|
111
124
|
}
|