@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.
Files changed (122) hide show
  1. package/dist/core/common/args/filter.args.d.ts +5 -0
  2. package/dist/core/common/args/filter.args.js +10 -0
  3. package/dist/core/common/args/filter.args.js.map +1 -1
  4. package/dist/core/common/args/pagination.args.d.ts +8 -1
  5. package/dist/core/common/args/pagination.args.js +24 -6
  6. package/dist/core/common/args/pagination.args.js.map +1 -1
  7. package/dist/core/common/decorators/restricted.decorator.d.ts +3 -0
  8. package/dist/core/common/decorators/restricted.decorator.js +16 -5
  9. package/dist/core/common/decorators/restricted.decorator.js.map +1 -1
  10. package/dist/core/common/helpers/context.helper.js +15 -5
  11. package/dist/core/common/helpers/context.helper.js.map +1 -1
  12. package/dist/core/common/helpers/filter.helper.d.ts +3 -3
  13. package/dist/core/common/helpers/filter.helper.js.map +1 -1
  14. package/dist/core/common/helpers/input.helper.js +13 -7
  15. package/dist/core/common/helpers/input.helper.js.map +1 -1
  16. package/dist/core/common/helpers/service.helper.d.ts +6 -8
  17. package/dist/core/common/helpers/service.helper.js +34 -12
  18. package/dist/core/common/helpers/service.helper.js.map +1 -1
  19. package/dist/core/common/inputs/combined-filter.input.d.ts +8 -2
  20. package/dist/core/common/inputs/combined-filter.input.js +16 -5
  21. package/dist/core/common/inputs/combined-filter.input.js.map +1 -1
  22. package/dist/core/common/inputs/core-input.input.d.ts +8 -0
  23. package/dist/core/common/inputs/core-input.input.js +15 -0
  24. package/dist/core/common/inputs/core-input.input.js.map +1 -0
  25. package/dist/core/common/inputs/filter.input.d.ts +7 -1
  26. package/dist/core/common/inputs/filter.input.js +14 -1
  27. package/dist/core/common/inputs/filter.input.js.map +1 -1
  28. package/dist/core/common/inputs/single-filter.input.d.ts +2 -1
  29. package/dist/core/common/inputs/single-filter.input.js +10 -1
  30. package/dist/core/common/inputs/single-filter.input.js.map +1 -1
  31. package/dist/core/common/inputs/sort.input.d.ts +2 -1
  32. package/dist/core/common/inputs/sort.input.js +7 -1
  33. package/dist/core/common/inputs/sort.input.js.map +1 -1
  34. package/dist/core/common/interceptors/check-response.interceptor.js +1 -1
  35. package/dist/core/common/interceptors/check-response.interceptor.js.map +1 -1
  36. package/dist/core/common/models/core-model.model.d.ts +6 -0
  37. package/dist/core/common/models/core-model.model.js +10 -3
  38. package/dist/core/common/models/core-model.model.js.map +1 -1
  39. package/dist/core/common/models/core-persistence.model.d.ts +5 -29
  40. package/dist/core/common/models/core-persistence.model.js +19 -41
  41. package/dist/core/common/models/core-persistence.model.js.map +1 -1
  42. package/dist/core/common/pipes/check-input.pipe.d.ts +2 -3
  43. package/dist/core/common/pipes/check-input.pipe.js +5 -20
  44. package/dist/core/common/pipes/check-input.pipe.js.map +1 -1
  45. package/dist/core/common/pipes/map-and-validate.pipe.d.ts +4 -0
  46. package/dist/core/common/pipes/map-and-validate.pipe.js +40 -0
  47. package/dist/core/common/pipes/map-and-validate.pipe.js.map +1 -0
  48. package/dist/core/common/types/plain-input.type.d.ts +3 -0
  49. package/dist/core/common/types/plain-input.type.js +3 -0
  50. package/dist/core/common/types/plain-input.type.js.map +1 -0
  51. package/dist/core/modules/auth/core-auth.model.d.ts +3 -1
  52. package/dist/core/modules/auth/core-auth.model.js +7 -1
  53. package/dist/core/modules/auth/core-auth.model.js.map +1 -1
  54. package/dist/core/modules/auth/core-auth.resolver.d.ts +1 -1
  55. package/dist/core/modules/user/core-user.model.d.ts +3 -0
  56. package/dist/core/modules/user/core-user.model.js +10 -4
  57. package/dist/core/modules/user/core-user.model.js.map +1 -1
  58. package/dist/core/modules/user/core-user.service.d.ts +9 -13
  59. package/dist/core/modules/user/core-user.service.js +38 -67
  60. package/dist/core/modules/user/core-user.service.js.map +1 -1
  61. package/dist/core/modules/user/inputs/core-user-create.input.js +4 -0
  62. package/dist/core/modules/user/inputs/core-user-create.input.js.map +1 -1
  63. package/dist/core/modules/user/inputs/core-user.input.d.ts +2 -1
  64. package/dist/core/modules/user/inputs/core-user.input.js +12 -2
  65. package/dist/core/modules/user/inputs/core-user.input.js.map +1 -1
  66. package/dist/core.module.js +2 -3
  67. package/dist/core.module.js.map +1 -1
  68. package/dist/index.d.ts +6 -2
  69. package/dist/index.js +6 -2
  70. package/dist/index.js.map +1 -1
  71. package/dist/server/common/models/persistence.model.d.ts +1 -0
  72. package/dist/server/common/models/persistence.model.js +4 -0
  73. package/dist/server/common/models/persistence.model.js.map +1 -1
  74. package/dist/server/modules/auth/auth.model.d.ts +1 -0
  75. package/dist/server/modules/auth/auth.model.js +4 -0
  76. package/dist/server/modules/auth/auth.model.js.map +1 -1
  77. package/dist/server/modules/user/inputs/user-create.input.js.map +1 -1
  78. package/dist/server/modules/user/inputs/user.input.js.map +1 -1
  79. package/dist/server/modules/user/user.model.d.ts +3 -2
  80. package/dist/server/modules/user/user.model.js +9 -5
  81. package/dist/server/modules/user/user.model.js.map +1 -1
  82. package/dist/server/modules/user/user.resolver.d.ts +2 -2
  83. package/dist/server/modules/user/user.resolver.js +10 -12
  84. package/dist/server/modules/user/user.resolver.js.map +1 -1
  85. package/dist/server/modules/user/user.service.d.ts +7 -9
  86. package/dist/server/modules/user/user.service.js +12 -4
  87. package/dist/server/modules/user/user.service.js.map +1 -1
  88. package/dist/tsconfig.build.tsbuildinfo +1 -1
  89. package/package.json +1 -1
  90. package/src/core/common/args/filter.args.ts +22 -1
  91. package/src/core/common/args/pagination.args.ts +42 -7
  92. package/src/core/common/decorators/restricted.decorator.ts +24 -5
  93. package/src/core/common/helpers/context.helper.ts +14 -3
  94. package/src/core/common/helpers/filter.helper.ts +3 -3
  95. package/src/core/common/helpers/input.helper.ts +17 -11
  96. package/src/core/common/helpers/service.helper.ts +42 -19
  97. package/src/core/common/inputs/combined-filter.input.ts +30 -9
  98. package/src/core/common/inputs/core-input.input.ts +36 -0
  99. package/src/core/common/inputs/filter.input.ts +27 -3
  100. package/src/core/common/inputs/single-filter.input.ts +7 -6
  101. package/src/core/common/inputs/sort.input.ts +4 -3
  102. package/src/core/common/interceptors/check-response.interceptor.ts +2 -2
  103. package/src/core/common/models/core-model.model.ts +30 -1
  104. package/src/core/common/models/core-persistence.model.ts +33 -120
  105. package/src/core/common/pipes/check-input.pipe.ts +13 -33
  106. package/src/core/common/pipes/map-and-validate.pipe.ts +32 -0
  107. package/src/core/common/types/plain-input.type.ts +6 -0
  108. package/src/core/modules/auth/core-auth.model.ts +15 -1
  109. package/src/core/modules/auth/core-auth.resolver.ts +1 -1
  110. package/src/core/modules/user/core-user.model.ts +17 -4
  111. package/src/core/modules/user/core-user.service.ts +59 -115
  112. package/src/core/modules/user/inputs/core-user-create.input.ts +5 -1
  113. package/src/core/modules/user/inputs/core-user.input.ts +13 -8
  114. package/src/core.module.ts +11 -5
  115. package/src/index.ts +6 -2
  116. package/src/server/common/models/persistence.model.ts +13 -0
  117. package/src/server/modules/auth/auth.model.ts +13 -0
  118. package/src/server/modules/user/inputs/user-create.input.ts +4 -0
  119. package/src/server/modules/user/inputs/user.input.ts +4 -0
  120. package/src/server/modules/user/user.model.ts +18 -5
  121. package/src/server/modules/user/user.resolver.ts +15 -19
  122. 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 * as mongoose from 'mongoose';
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 mongoose.Types.ObjectId(this.id);
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 = new 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 = new 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
- * Static map deep method
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
- * Map method
94
+ * Initialize instance with default values instead of undefined
128
95
  */
129
- public map(
130
- data: Partial<this> | Record<string, any>,
131
- options: {
132
- cloneDeep?: boolean;
133
- funcAllowed?: boolean;
134
- mapId?: boolean;
135
- merge?: boolean;
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, BadRequestException, Inject, Injectable, PipeTransform, Scope } from '@nestjs/common';
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({ scope: Scope.REQUEST })
13
- export class CheckInputPipe implements PipeTransform<any> {
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, { metatype }: ArgumentMetadata) {
23
- // Return value if it is only a basic type
24
- if (!metatype || this.isBasicType(metatype)) {
25
- return value;
26
- }
23
+ async transform(value: any, metadata: ArgumentMetadata) {
24
+ // Get meta type
25
+ const metatype = metadata?.metatype;
27
26
 
28
- // Remove restricted values if roles are missing
27
+ // Get user
29
28
  const { user }: any = Context.getData(this.context);
30
- value = checkRestricted(value, user);
31
29
 
32
- // Validate value
33
- const plainValue = JSON.parse(JSON.stringify(value));
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
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Type for plain Inputs
3
+ */
4
+ export type PlainInput<T> = {
5
+ [P in keyof T]?: Partial<T[P]> | Partial<PlainInput<T[P]>>;
6
+ };
@@ -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
- @Schema()
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 = false;
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
  }