@lenne.tech/nest-server 8.0.2 → 8.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 (166) hide show
  1. package/dist/config.env.js +3 -2
  2. package/dist/config.env.js.map +1 -1
  3. package/dist/core/common/args/pagination.args.js +1 -1
  4. package/dist/core/common/args/pagination.args.js.map +1 -1
  5. package/dist/core/common/decorators/restricted.decorator.d.ts +3 -0
  6. package/dist/core/common/decorators/restricted.decorator.js +14 -8
  7. package/dist/core/common/decorators/restricted.decorator.js.map +1 -1
  8. package/dist/core/common/enums/role.enum.d.ts +3 -2
  9. package/dist/core/common/enums/role.enum.js +3 -2
  10. package/dist/core/common/enums/role.enum.js.map +1 -1
  11. package/dist/core/common/helpers/config.helper.d.ts +2 -1
  12. package/dist/core/common/helpers/config.helper.js +11 -7
  13. package/dist/core/common/helpers/config.helper.js.map +1 -1
  14. package/dist/core/common/helpers/context.helper.d.ts +7 -1
  15. package/dist/core/common/helpers/context.helper.js +33 -29
  16. package/dist/core/common/helpers/context.helper.js.map +1 -1
  17. package/dist/core/common/helpers/db.helper.d.ts +37 -0
  18. package/dist/core/common/helpers/db.helper.js +356 -0
  19. package/dist/core/common/helpers/db.helper.js.map +1 -0
  20. package/dist/core/common/helpers/file.helper.d.ts +8 -1
  21. package/dist/core/common/helpers/file.helper.js +43 -31
  22. package/dist/core/common/helpers/file.helper.js.map +1 -1
  23. package/dist/core/common/helpers/filter.helper.d.ts +3 -0
  24. package/dist/core/common/helpers/filter.helper.js +93 -81
  25. package/dist/core/common/helpers/filter.helper.js.map +1 -1
  26. package/dist/core/common/helpers/graphql.helper.d.ts +24 -1
  27. package/dist/core/common/helpers/graphql.helper.js +144 -96
  28. package/dist/core/common/helpers/graphql.helper.js.map +1 -1
  29. package/dist/core/common/helpers/input.helper.d.ts +42 -4
  30. package/dist/core/common/helpers/input.helper.js +256 -97
  31. package/dist/core/common/helpers/input.helper.js.map +1 -1
  32. package/dist/core/common/helpers/model.helper.d.ts +11 -0
  33. package/dist/core/common/helpers/model.helper.js +41 -29
  34. package/dist/core/common/helpers/model.helper.js.map +1 -1
  35. package/dist/core/common/helpers/service.helper.d.ts +21 -1
  36. package/dist/core/common/helpers/service.helper.js +80 -72
  37. package/dist/core/common/helpers/service.helper.js.map +1 -1
  38. package/dist/core/common/inputs/combined-filter.input.js +1 -1
  39. package/dist/core/common/inputs/combined-filter.input.js.map +1 -1
  40. package/dist/core/common/inputs/core-input.input.js +1 -1
  41. package/dist/core/common/inputs/core-input.input.js.map +1 -1
  42. package/dist/core/common/interceptors/check-response.interceptor.js +1 -1
  43. package/dist/core/common/interceptors/check-response.interceptor.js.map +1 -1
  44. package/dist/core/common/interfaces/resolve-selector.interface.d.ts +5 -0
  45. package/dist/core/common/interfaces/resolve-selector.interface.js +3 -0
  46. package/dist/core/common/interfaces/resolve-selector.interface.js.map +1 -0
  47. package/dist/core/common/interfaces/service-options.interface.d.ts +36 -0
  48. package/dist/core/common/interfaces/service-options.interface.js +3 -0
  49. package/dist/core/common/interfaces/service-options.interface.js.map +1 -0
  50. package/dist/core/common/models/core-model.model.d.ts +5 -1
  51. package/dist/core/common/models/core-model.model.js +1 -1
  52. package/dist/core/common/models/core-model.model.js.map +1 -1
  53. package/dist/core/common/pipes/check-input.pipe.js +2 -2
  54. package/dist/core/common/pipes/check-input.pipe.js.map +1 -1
  55. package/dist/core/common/pipes/map-and-validate.pipe.js +1 -1
  56. package/dist/core/common/pipes/map-and-validate.pipe.js.map +1 -1
  57. package/dist/core/common/services/crud.service.d.ts +13 -0
  58. package/dist/core/common/services/crud.service.js +57 -0
  59. package/dist/core/common/services/crud.service.js.map +1 -0
  60. package/dist/core/common/services/email.service.js +8 -8
  61. package/dist/core/common/services/email.service.js.map +1 -1
  62. package/dist/core/common/services/module.service.d.ts +40 -0
  63. package/dist/core/common/services/module.service.js +80 -0
  64. package/dist/core/common/services/module.service.js.map +1 -0
  65. package/dist/core/common/types/core-model-constructor.type.d.ts +21 -0
  66. package/dist/core/common/types/core-model-constructor.type.js +3 -0
  67. package/dist/core/common/types/core-model-constructor.type.js.map +1 -0
  68. package/dist/core/common/types/field-selection.type.d.ts +4 -0
  69. package/dist/core/common/types/field-selection.type.js +3 -0
  70. package/dist/core/common/types/field-selection.type.js.map +1 -0
  71. package/dist/core/common/types/ids.type.d.ts +8 -0
  72. package/dist/core/common/types/ids.type.js +3 -0
  73. package/dist/core/common/types/ids.type.js.map +1 -0
  74. package/dist/core/common/types/string-or-object-id.type.d.ts +2 -0
  75. package/dist/core/common/types/string-or-object-id.type.js +3 -0
  76. package/dist/core/common/types/string-or-object-id.type.js.map +1 -0
  77. package/dist/core/modules/auth/core-auth.resolver.d.ts +2 -1
  78. package/dist/core/modules/auth/core-auth.resolver.js +4 -3
  79. package/dist/core/modules/auth/core-auth.resolver.js.map +1 -1
  80. package/dist/core/modules/auth/guards/roles.guard.js +1 -2
  81. package/dist/core/modules/auth/guards/roles.guard.js.map +1 -1
  82. package/dist/core/modules/auth/services/core-auth-user.service.d.ts +3 -1
  83. package/dist/core/modules/auth/services/core-auth-user.service.js.map +1 -1
  84. package/dist/core/modules/auth/services/core-auth.service.d.ts +2 -1
  85. package/dist/core/modules/auth/services/core-auth.service.js +6 -4
  86. package/dist/core/modules/auth/services/core-auth.service.js.map +1 -1
  87. package/dist/core/modules/user/core-user.model.js +1 -1
  88. package/dist/core/modules/user/core-user.model.js.map +1 -1
  89. package/dist/core/modules/user/core-user.service.d.ts +16 -25
  90. package/dist/core/modules/user/core-user.service.js +69 -90
  91. package/dist/core/modules/user/core-user.service.js.map +1 -1
  92. package/dist/core.module.js +1 -1
  93. package/dist/core.module.js.map +1 -1
  94. package/dist/index.d.ts +9 -1
  95. package/dist/index.js +9 -1
  96. package/dist/index.js.map +1 -1
  97. package/dist/server/modules/auth/auth.resolver.d.ts +2 -1
  98. package/dist/server/modules/auth/auth.resolver.js +4 -3
  99. package/dist/server/modules/auth/auth.resolver.js.map +1 -1
  100. package/dist/server/modules/file/file.controller.js +1 -1
  101. package/dist/server/modules/file/file.controller.js.map +1 -1
  102. package/dist/server/modules/user/avatar.controller.js +2 -2
  103. package/dist/server/modules/user/avatar.controller.js.map +1 -1
  104. package/dist/server/modules/user/user.model.d.ts +2 -1
  105. package/dist/server/modules/user/user.module.js +7 -3
  106. package/dist/server/modules/user/user.module.js.map +1 -1
  107. package/dist/server/modules/user/user.resolver.d.ts +8 -7
  108. package/dist/server/modules/user/user.resolver.js +85 -49
  109. package/dist/server/modules/user/user.resolver.js.map +1 -1
  110. package/dist/server/modules/user/user.service.d.ts +9 -18
  111. package/dist/server/modules/user/user.service.js +23 -30
  112. package/dist/server/modules/user/user.service.js.map +1 -1
  113. package/dist/test/test.helper.d.ts +1 -2
  114. package/dist/test/test.helper.js +1 -16
  115. package/dist/test/test.helper.js.map +1 -1
  116. package/dist/tsconfig.build.tsbuildinfo +1 -1
  117. package/package.json +58 -59
  118. package/src/config.env.ts +3 -2
  119. package/src/core/common/args/pagination.args.ts +2 -2
  120. package/src/core/common/decorators/restricted.decorator.ts +24 -12
  121. package/src/core/common/enums/role.enum.ts +23 -5
  122. package/src/core/common/helpers/config.helper.ts +26 -6
  123. package/src/core/common/helpers/context.helper.ts +42 -33
  124. package/src/core/common/helpers/db.helper.ts +595 -0
  125. package/src/core/common/helpers/file.helper.ts +76 -49
  126. package/src/core/common/helpers/filter.helper.ts +119 -96
  127. package/src/core/common/helpers/graphql.helper.ts +219 -117
  128. package/src/core/common/helpers/input.helper.ts +349 -108
  129. package/src/core/common/helpers/model.helper.ts +102 -57
  130. package/src/core/common/helpers/service.helper.ts +149 -117
  131. package/src/core/common/inputs/combined-filter.input.ts +2 -2
  132. package/src/core/common/inputs/core-input.input.ts +2 -2
  133. package/src/core/common/interceptors/check-response.interceptor.ts +2 -2
  134. package/src/core/common/interfaces/resolve-selector.interface.ts +9 -0
  135. package/src/core/common/interfaces/service-options.interface.ts +71 -0
  136. package/src/core/common/models/core-model.model.ts +7 -3
  137. package/src/core/common/pipes/check-input.pipe.ts +4 -4
  138. package/src/core/common/pipes/map-and-validate.pipe.ts +2 -2
  139. package/src/core/common/services/crud.service.ts +100 -0
  140. package/src/core/common/services/email.service.ts +9 -9
  141. package/src/core/common/services/module.service.ts +188 -0
  142. package/src/core/common/types/core-model-constructor.type.ts +30 -0
  143. package/src/core/common/types/field-selection.type.ts +8 -0
  144. package/src/core/common/types/ids.type.ts +7 -0
  145. package/src/core/common/types/string-or-object-id.type.ts +3 -0
  146. package/src/core/modules/auth/core-auth.module.ts +1 -1
  147. package/src/core/modules/auth/core-auth.resolver.ts +8 -3
  148. package/src/core/modules/auth/guards/roles.guard.ts +5 -7
  149. package/src/core/modules/auth/services/core-auth-user.service.ts +7 -1
  150. package/src/core/modules/auth/services/core-auth.service.ts +14 -4
  151. package/src/core/modules/user/core-user.model.ts +2 -1
  152. package/src/core/modules/user/core-user.service.ts +115 -185
  153. package/src/core.module.ts +2 -2
  154. package/src/index.ts +9 -1
  155. package/src/main.ts +1 -1
  156. package/src/server/modules/auth/auth.resolver.ts +8 -3
  157. package/src/server/modules/file/file.controller.ts +2 -2
  158. package/src/server/modules/user/avatar.controller.ts +3 -3
  159. package/src/server/modules/user/user.module.ts +7 -3
  160. package/src/server/modules/user/user.resolver.ts +74 -43
  161. package/src/server/modules/user/user.service.ts +30 -53
  162. package/src/test/test.helper.ts +31 -30
  163. package/dist/core/modules/user/core-basic-user.service.d.ts +0 -17
  164. package/dist/core/modules/user/core-basic-user.service.js +0 -73
  165. package/dist/core/modules/user/core-basic-user.service.js.map +0 -1
  166. package/src/core/modules/user/core-basic-user.service.ts +0 -138
@@ -1,3 +1,4 @@
1
+ import { Inject } from '@nestjs/common';
1
2
  import { Args, Info, Mutation, Query, Resolver, Subscription } from '@nestjs/graphql';
2
3
  import { GraphQLResolveInfo } from 'graphql';
3
4
  import { PubSub } from 'graphql-subscriptions';
@@ -5,12 +6,10 @@ import { FilterArgs } from '../../../core/common/args/filter.args';
5
6
  import { GraphQLUser } from '../../../core/common/decorators/graphql-user.decorator';
6
7
  import { Roles } from '../../../core/common/decorators/roles.decorator';
7
8
  import { RoleEnum } from '../../../core/common/enums/role.enum';
8
- import { InputHelper } from '../../../core/common/helpers/input.helper';
9
9
  import { UserCreateInput } from './inputs/user-create.input';
10
10
  import { UserInput } from './inputs/user.input';
11
11
  import { User } from './user.model';
12
12
  import { UserService } from './user.service';
13
- import { Inject } from '@nestjs/common';
14
13
 
15
14
  /**
16
15
  * Resolver to process with user data
@@ -20,27 +19,43 @@ export class UserResolver {
20
19
  /**
21
20
  * Import services
22
21
  */
23
- constructor(protected readonly usersService: UserService, @Inject('PUB_SUB') protected readonly pubSub: PubSub) {}
22
+ constructor(protected readonly userService: UserService, @Inject('PUB_SUB') protected readonly pubSub: PubSub) {}
24
23
 
25
24
  // ===========================================================================
26
25
  // Queries
27
26
  // ===========================================================================
28
27
 
28
+ /**
29
+ * Get users (via filter)
30
+ */
31
+ @Roles(RoleEnum.ADMIN)
32
+ @Query((returns) => [User], { description: 'Find users (via filter)' })
33
+ async findUsers(@Info() info: GraphQLResolveInfo, @Args() args?: FilterArgs) {
34
+ return await this.userService.find(args, {
35
+ fieldSelection: { info, select: 'findUsers' },
36
+ inputType: FilterArgs,
37
+ });
38
+ }
39
+
29
40
  /**
30
41
  * Get user via ID
31
42
  */
43
+ @Roles(RoleEnum.S_USER)
32
44
  @Query((returns) => User, { description: 'Get user with specified ID' })
33
- async getUser(@Args('id') id: string, @Info() info: GraphQLResolveInfo): Promise<User> {
34
- return await this.usersService.get(id, info);
45
+ async getUser(@Args('id') id: string, @Info() info: GraphQLResolveInfo, @GraphQLUser() user: User): Promise<User> {
46
+ return await this.userService.get(id, {
47
+ currentUser: user,
48
+ fieldSelection: { info, select: 'getUser' },
49
+ roles: [RoleEnum.ADMIN, RoleEnum.S_CREATOR],
50
+ });
35
51
  }
36
52
 
37
53
  /**
38
- * Get users (via filter)
54
+ * Get verified state of user with token
39
55
  */
40
- @Roles(RoleEnum.USER)
41
- @Query((returns) => [User], { description: 'Find users (via filter)' })
42
- async findUsers(@Info() info: GraphQLResolveInfo, @Args() args?: FilterArgs) {
43
- return await this.usersService.find(args, info);
56
+ @Query((returns) => Boolean, { description: 'Get verified state of user with token' })
57
+ async getVerifiedState(@Args('token') token: string) {
58
+ return await this.userService.getVerifiedState(token);
44
59
  }
45
60
 
46
61
  /**
@@ -48,63 +63,76 @@ export class UserResolver {
48
63
  */
49
64
  @Query((returns) => Boolean, { description: 'Request new password for user with email' })
50
65
  async requestPasswordResetMail(@Args('email') email: string): Promise<boolean> {
51
- return !!(await this.usersService.sendPasswordResetMail(email));
66
+ return !!(await this.userService.sendPasswordResetMail(email));
52
67
  }
53
68
 
54
69
  // ===========================================================================
55
70
  // Mutations
56
71
  // ===========================================================================
72
+
57
73
  /**
58
- * Verify user with email
74
+ * Create new user
59
75
  */
60
- @Mutation((returns) => Boolean, { description: 'Verify user with email' })
61
- async verifyUser(@Args('token') token: string): Promise<boolean> {
62
- return !!(await this.usersService.verify(token));
76
+ @Mutation((returns) => User, { description: 'Create a new user' })
77
+ async createUser(
78
+ @Args('input') input: UserCreateInput,
79
+ @GraphQLUser() user: User,
80
+ @Info() info: GraphQLResolveInfo
81
+ ): Promise<User> {
82
+ return await this.userService.create(input, {
83
+ currentUser: user,
84
+ fieldSelection: { info, select: 'createUser' },
85
+ inputType: UserCreateInput,
86
+ });
63
87
  }
64
88
 
65
89
  /**
66
- * Set new password for user with token
90
+ * Delete existing user
67
91
  */
68
- @Mutation((returns) => Boolean, { description: 'Set new password for user with token' })
69
- async resetPassword(@Args('token') token: string, @Args('password') password: string): Promise<boolean> {
70
- return !!(await this.usersService.resetPassword(token, password));
92
+ @Roles(RoleEnum.S_USER)
93
+ @Mutation((returns) => User, { description: 'Delete existing user' })
94
+ async deleteUser(@Args('id') id: string, @Info() info: GraphQLResolveInfo, @GraphQLUser() user: User): Promise<User> {
95
+ return await this.userService.delete(id, {
96
+ currentUser: user,
97
+ fieldSelection: { info, select: 'deleteUser' },
98
+ roles: [RoleEnum.ADMIN, RoleEnum.S_CREATOR],
99
+ });
71
100
  }
72
101
 
73
102
  /**
74
- * Create new user
103
+ * Set new password for user with token
75
104
  */
76
- @Mutation((returns) => User, { description: 'Create a new user' })
77
- async createUser(@Args('input') input: UserCreateInput, @GraphQLUser() user: User): Promise<User> {
78
- // Check input
79
- // Hint: necessary as long as global CheckInputPipe can't access context for current user
80
- // (see https://github.com/nestjs/graphql/issues/325)
81
- input = await InputHelper.check(input, user, UserCreateInput);
82
-
83
- return await this.usersService.create(input, user);
105
+ @Mutation((returns) => Boolean, { description: 'Set new password for user with token' })
106
+ async resetPassword(@Args('token') token: string, @Args('password') password: string): Promise<boolean> {
107
+ return !!(await this.userService.resetPassword(token, password));
84
108
  }
85
109
 
86
110
  /**
87
111
  * Update existing user
88
112
  */
89
- @Roles(RoleEnum.ADMIN, RoleEnum.OWNER)
113
+ @Roles(RoleEnum.S_USER)
90
114
  @Mutation((returns) => User, { description: 'Update existing user' })
91
- async updateUser(@Args('input') input: UserInput, @Args('id') id: string, @GraphQLUser() user: User): Promise<User> {
92
- // Check input
93
- // Hint: necessary as long as global CheckInputPipe can't access context for current user
94
- // (see https://github.com/nestjs/graphql/issues/325)
95
- input = await InputHelper.check(input, user, UserInput);
96
-
115
+ async updateUser(
116
+ @Args('input') input: UserInput,
117
+ @Args('id') id: string,
118
+ @GraphQLUser() user: User,
119
+ @Info() info: GraphQLResolveInfo
120
+ ): Promise<User> {
97
121
  // Update user
98
- return await this.usersService.update(id, input, user);
122
+ return await this.userService.update(id, input, {
123
+ currentUser: user,
124
+ fieldSelection: { info, select: 'updateUser' },
125
+ inputType: UserInput,
126
+ roles: [RoleEnum.ADMIN, RoleEnum.S_CREATOR],
127
+ });
99
128
  }
100
129
 
101
130
  /**
102
- * Delete existing user
131
+ * Verify user with email
103
132
  */
104
- @Roles(RoleEnum.ADMIN, RoleEnum.OWNER)
105
- @Mutation((returns) => User, { description: 'Delete existing user' })
106
- async deleteUser(@Args('id') id: string, @Info() info: GraphQLResolveInfo): Promise<User> {
107
- return await this.usersService.delete(id, info);
133
+ @Mutation((returns) => Boolean, { description: 'Verify user with email' })
134
+ async verifyUser(@Args('token') token: string): Promise<boolean> {
135
+ return !!(await this.userService.verify(token));
108
136
  }
109
137
 
110
138
  // ===========================================================================
@@ -112,10 +140,13 @@ export class UserResolver {
112
140
  // ===========================================================================
113
141
 
114
142
  /**
115
- * Subscritption for create user
143
+ * Subscription for created user
116
144
  */
117
145
  @Subscription((returns) => User, {
118
- resolve: (value) => value,
146
+ filter(this: UserResolver, payload, variables, context) {
147
+ return context.user.roles.include(RoleEnum.ADMIN);
148
+ },
149
+ resolve: (user) => user,
119
150
  })
120
151
  async userCreated() {
121
152
  return this.pubSub.asyncIterator('userCreated');
@@ -1,33 +1,23 @@
1
1
  import { Inject, Injectable, UnauthorizedException, UnprocessableEntityException } from '@nestjs/common';
2
+ import { InjectModel } from '@nestjs/mongoose';
2
3
  import * as fs from 'fs';
4
+ import { PubSub } from 'graphql-subscriptions';
5
+ import { Model } from 'mongoose';
3
6
  import envConfig from '../../../config.env';
4
- import { FilterArgs } from '../../../core/common/args/filter.args';
5
- import { Filter } from '../../../core/common/helpers/filter.helper';
6
- import { ServiceHelper } from '../../../core/common/helpers/service.helper';
7
+ import { ServiceOptions } from '../../../core/common/interfaces/service-options.interface';
7
8
  import { ConfigService } from '../../../core/common/services/config.service';
8
9
  import { EmailService } from '../../../core/common/services/email.service';
10
+ import { CoreModelConstructor } from '../../../core/common/types/core-model-constructor.type';
9
11
  import { CoreUserService } from '../../../core/modules/user/core-user.service';
10
12
  import { UserCreateInput } from './inputs/user-create.input';
11
13
  import { UserInput } from './inputs/user.input';
12
14
  import { User, UserDocument } from './user.model';
13
- import { InjectModel } from '@nestjs/mongoose';
14
- import { Model } from 'mongoose';
15
- import { ICorePersistenceModel } from '../../../core/common/interfaces/core-persistence-model.interface';
16
- import { PubSub } from 'graphql-subscriptions';
17
15
 
18
16
  /**
19
17
  * User service
20
18
  */
21
19
  @Injectable()
22
20
  export class UserService extends CoreUserService<User, UserInput, UserCreateInput> {
23
- // ===================================================================================================================
24
- // Properties
25
- // ===================================================================================================================
26
-
27
- /**
28
- * User model
29
- */
30
- protected readonly model: ICorePersistenceModel;
31
21
  // ===================================================================================================================
32
22
  // Injections
33
23
  // ===================================================================================================================
@@ -38,11 +28,11 @@ export class UserService extends CoreUserService<User, UserInput, UserCreateInpu
38
28
  constructor(
39
29
  protected readonly configService: ConfigService,
40
30
  protected readonly emailService: EmailService,
41
- @InjectModel('User') protected readonly userModel: Model<UserDocument>,
31
+ @Inject('USER_CLASS') protected readonly mainModelConstructor: CoreModelConstructor<User>,
32
+ @InjectModel('User') protected readonly mainDbModel: Model<UserDocument>,
42
33
  @Inject('PUB_SUB') protected readonly pubSub: PubSub
43
34
  ) {
44
- super(userModel, emailService);
45
- this.model = User;
35
+ super(emailService, mainDbModel, mainModelConstructor);
46
36
  }
47
37
 
48
38
  // ===================================================================================================================
@@ -52,43 +42,48 @@ export class UserService extends CoreUserService<User, UserInput, UserCreateInpu
52
42
  /**
53
43
  * Create new user and send welcome email
54
44
  */
55
- async create(input: UserCreateInput, currentUser?: User): Promise<User> {
56
- const user = await super.create(input, currentUser);
57
-
58
- await this.prepareOutput(user);
45
+ async create(input: UserCreateInput, serviceOptions?: ServiceOptions): Promise<User> {
46
+ // Get prepared user
47
+ let user = await super.create(input, serviceOptions);
48
+
49
+ // Add the createdBy information in an additional step if it was not set by the system,
50
+ // because the user created himself and could not exist as currentUser before
51
+ if (!user.createdBy) {
52
+ await this.mainDbModel.findByIdAndUpdate(user.id, { createdBy: user.id });
53
+ user = await this.get(user.id, serviceOptions);
54
+ }
59
55
 
60
- await this.pubSub.publish('userCreated', User.map(user));
56
+ // Publish action
57
+ if (serviceOptions?.pubSub === undefined || serviceOptions.pubSub) {
58
+ await this.pubSub.publish('userCreated', User.map(user));
59
+ }
61
60
 
61
+ // Send email
62
62
  await this.emailService.sendMail(user.email, 'Welcome', {
63
63
  htmlTemplate: 'welcome',
64
64
  templateData: { name: user.username, link: envConfig.email.verificationLink + '/' + user.verificationToken },
65
65
  });
66
66
 
67
+ // Return created user
67
68
  return user;
68
69
  }
69
70
 
70
- /**
71
- * Get users via filter
72
- */
73
- find(filterArgs?: FilterArgs, ...args: any[]): Promise<User[]> {
74
- const filterQuery = Filter.convertFilterArgsToQuery(filterArgs);
75
- // Return found users
76
- return this.userModel.find(filterQuery[0], null, filterQuery[1]).exec();
77
- }
78
-
79
71
  /**
80
72
  * Request password reset mail
81
73
  *
82
74
  * @param email
83
75
  */
84
- async sendPasswordResetMail(email: string): Promise<User> {
85
- const user = await super.setPasswordResetTokenForEmail(email);
76
+ async sendPasswordResetMail(email: string, serviceOptions?: ServiceOptions): Promise<User> {
77
+ // Set password reset token
78
+ const user = await super.setPasswordResetTokenForEmail(email, serviceOptions);
86
79
 
80
+ // Send email
87
81
  await this.emailService.sendMail(user.email, 'Password reset', {
88
82
  htmlTemplate: 'password-reset',
89
83
  templateData: { name: user.username, link: envConfig.email.passwordResetLink + '/' + user.passwordResetToken },
90
84
  });
91
85
 
86
+ // Return user
92
87
  return user;
93
88
  }
94
89
 
@@ -96,7 +91,7 @@ export class UserService extends CoreUserService<User, UserInput, UserCreateInpu
96
91
  * Set avatar image
97
92
  */
98
93
  async setAvatar(file: Express.Multer.File, user: User): Promise<string> {
99
- const dbUser = await this.userModel.findOne({ id: user.id }).exec();
94
+ const dbUser = await this.mainDbModel.findOne({ id: user.id }).exec();
100
95
  // Check user
101
96
  if (!dbUser) {
102
97
  throw new UnauthorizedException();
@@ -124,22 +119,4 @@ export class UserService extends CoreUserService<User, UserInput, UserCreateInpu
124
119
  // Return user
125
120
  return file.filename;
126
121
  }
127
-
128
- // ===================================================================================================================
129
- // Helper methods
130
- // ===================================================================================================================
131
-
132
- /**
133
- * Prepare input before save
134
- */
135
- protected async prepareInput(input: { [key: string]: any }, currentUser: User, options: { create?: boolean } = {}) {
136
- return ServiceHelper.prepareInput(input, currentUser, options);
137
- }
138
-
139
- /**
140
- * Prepare output before return
141
- */
142
- protected async prepareOutput(user: User): Promise<User> {
143
- return ServiceHelper.prepareOutput(user);
144
- }
145
122
  }
@@ -1,5 +1,5 @@
1
1
  import { INestApplication } from '@nestjs/common';
2
- import { FastifyInstance } from 'fastify';
2
+ // import { FastifyInstance } from 'fastify';
3
3
  import { jsonToGraphQLQuery } from 'json-to-graphql-query';
4
4
  import * as LightMyRequest from 'light-my-request';
5
5
  import * as supertest from 'supertest';
@@ -101,7 +101,8 @@ export interface TestRestOptions {
101
101
  * Test helper
102
102
  */
103
103
  export class TestHelper {
104
- app: FastifyInstance | INestApplication;
104
+ // app: FastifyInstance | INestApplication;
105
+ app: INestApplication;
105
106
 
106
107
  /**
107
108
  * Constructor
@@ -202,15 +203,15 @@ export class TestHelper {
202
203
  const response = await this.getResponse(token, requestConfig, statusCode, log, logError);
203
204
 
204
205
  // Response of fastify
205
- if ((this.app as FastifyInstance).inject) {
206
- // Check data
207
- expect(response.headers['content-type']).toBe('application/json');
208
-
209
- // return data
210
- return JSON.parse(response.payload).data
211
- ? JSON.parse(response.payload).data[(graphql as TestGraphQLConfig).name]
212
- : JSON.parse(response.payload);
213
- }
206
+ // if ((this.app as FastifyInstance).inject) {
207
+ // // Check data
208
+ // expect(response.headers['content-type']).toBe('application/json');
209
+ //
210
+ // // return data
211
+ // return JSON.parse(response.payload).data
212
+ // ? JSON.parse(response.payload).data[(graphql as TestGraphQLConfig).name]
213
+ // : JSON.parse(response.payload);
214
+ // }
214
215
 
215
216
  // Check data
216
217
  expect(response.headers['content-type']).toMatch('application/json');
@@ -322,24 +323,24 @@ export class TestHelper {
322
323
  }
323
324
 
324
325
  // Init response
325
- let response: any;
326
-
327
- // Response of fastify
328
- if ((this.app as FastifyInstance).inject) {
329
- // Get response
330
- response = await (this.app as FastifyInstance).inject(requestConfig);
331
-
332
- // Log response
333
- if (log) {
334
- console.log(response);
335
- }
336
-
337
- // Check data
338
- expect(response.statusCode).toBe(statusCode);
339
-
340
- // Return response
341
- return response;
342
- }
326
+ // let response: any;
327
+
328
+ // // Response of fastify
329
+ // if ((this.app as FastifyInstance).inject) {
330
+ // // Get response
331
+ // response = await (this.app as FastifyInstance).inject(requestConfig);
332
+ //
333
+ // // Log response
334
+ // if (log) {
335
+ // console.log(response);
336
+ // }
337
+ //
338
+ // // Check data
339
+ // expect(response.statusCode).toBe(statusCode);
340
+ //
341
+ // // Return response
342
+ // return response;
343
+ // }
343
344
 
344
345
  // Express request
345
346
  const method: string = requestConfig.method.toLowerCase();
@@ -349,7 +350,7 @@ export class TestHelper {
349
350
  }
350
351
 
351
352
  // Response
352
- response = await request.send(requestConfig.payload);
353
+ const response = await request.send(requestConfig.payload);
353
354
 
354
355
  // Log response
355
356
  if (log) {
@@ -1,17 +0,0 @@
1
- import { FilterArgs } from '../../common/args/filter.args';
2
- import { CoreUserModel } from './core-user.model';
3
- import { CoreUserCreateInput } from './inputs/core-user-create.input';
4
- import { CoreUserInput } from './inputs/core-user.input';
5
- import { Model } from 'mongoose';
6
- import { ICorePersistenceModel } from '../../common/interfaces/core-persistence-model.interface';
7
- export declare abstract class CoreBasicUserService<TUser extends CoreUserModel, TUserInput extends CoreUserInput, TUserCreateInput extends CoreUserCreateInput> {
8
- protected readonly userModel: Model<any>;
9
- protected readonly model: ICorePersistenceModel;
10
- constructor(userModel: Model<any>);
11
- create(input: TUserCreateInput, ...args: any[]): Promise<TUser>;
12
- get(id: string, ...args: any[]): Promise<TUser>;
13
- getViaEmail(email: string, ...args: any[]): Promise<TUser>;
14
- find(filterArgs?: FilterArgs, ...args: any[]): Promise<TUser[]>;
15
- update(id: string, input: TUserInput, ...args: any[]): Promise<TUser>;
16
- delete(id: string, ...args: any[]): Promise<TUser>;
17
- }
@@ -1,73 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CoreBasicUserService = void 0;
4
- const common_1 = require("@nestjs/common");
5
- const bcrypt = require("bcrypt");
6
- const graphql_subscriptions_1 = require("graphql-subscriptions");
7
- const filter_helper_1 = require("../../common/helpers/filter.helper");
8
- const pubSub = new graphql_subscriptions_1.PubSub();
9
- class CoreBasicUserService {
10
- constructor(userModel) {
11
- this.userModel = userModel;
12
- }
13
- async create(input, ...args) {
14
- if (input.password) {
15
- input.password = await bcrypt.hash(input.password, 10);
16
- }
17
- const createdUser = new this.userModel(this.model.map(input));
18
- try {
19
- await createdUser.save();
20
- }
21
- catch (error) {
22
- if (error.code === 11000) {
23
- throw new common_1.UnprocessableEntityException(`User with email address "${input.email}" already exists`);
24
- }
25
- else {
26
- throw new common_1.UnprocessableEntityException();
27
- }
28
- }
29
- pubSub.publish('userCreated', { userCreated: createdUser });
30
- return createdUser;
31
- }
32
- async get(id, ...args) {
33
- const user = await this.userModel.findOne({ id: id }).exec();
34
- if (!user) {
35
- throw new common_1.NotFoundException();
36
- }
37
- return user;
38
- }
39
- async getViaEmail(email, ...args) {
40
- let user = await this.userModel.findOne({ email }).exec();
41
- if (!user) {
42
- throw new common_1.NotFoundException();
43
- }
44
- user = this.model.map(user);
45
- return user;
46
- }
47
- find(filterArgs, ...args) {
48
- return this.userModel.find(...filter_helper_1.Filter.convertFilterArgsToQuery(filterArgs)).exec();
49
- }
50
- async update(id, input, ...args) {
51
- let user = await this.userModel.findOne({ id });
52
- if (!user) {
53
- throw new common_1.NotFoundException(`User not found with ID: ${id}`);
54
- }
55
- if (input.password) {
56
- input.password = await bcrypt.hash(input.password, 10);
57
- }
58
- user.set(input);
59
- await user.save();
60
- user = this.model.map(user);
61
- return user;
62
- }
63
- async delete(id, ...args) {
64
- const user = await this.userModel.findOne({ id }).exec();
65
- if (!user) {
66
- throw new common_1.NotFoundException();
67
- }
68
- await this.userModel.deleteOne({ id: user.id });
69
- return user;
70
- }
71
- }
72
- exports.CoreBasicUserService = CoreBasicUserService;
73
- //# sourceMappingURL=core-basic-user.service.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"core-basic-user.service.js","sourceRoot":"","sources":["../../../../src/core/modules/user/core-basic-user.service.ts"],"names":[],"mappings":"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"}
@@ -1,138 +0,0 @@
1
- import { NotFoundException, UnprocessableEntityException } from '@nestjs/common';
2
- import * as bcrypt from 'bcrypt';
3
- import { PubSub } from 'graphql-subscriptions';
4
- import { FilterArgs } from '../../common/args/filter.args';
5
- import { Filter } from '../../common/helpers/filter.helper';
6
- import { CoreUserModel } from './core-user.model';
7
- import { CoreUserCreateInput } from './inputs/core-user-create.input';
8
- import { CoreUserInput } from './inputs/core-user.input';
9
- import { Model } from 'mongoose';
10
- import { ICorePersistenceModel } from '../../common/interfaces/core-persistence-model.interface';
11
-
12
- // Subscription
13
- const pubSub = new PubSub();
14
-
15
- /**
16
- * User service
17
- */
18
- export abstract class CoreBasicUserService<
19
- TUser extends CoreUserModel,
20
- TUserInput extends CoreUserInput,
21
- TUserCreateInput extends CoreUserCreateInput
22
- > {
23
- protected readonly model: ICorePersistenceModel;
24
-
25
- constructor(protected readonly userModel: Model<any>) {}
26
-
27
- /**
28
- * Create user
29
- */
30
- async create(input: TUserCreateInput, ...args: any[]): Promise<TUser> {
31
- // Prepare input
32
- if ((input as any).password) {
33
- (input as any).password = await bcrypt.hash((input as any).password, 10);
34
- }
35
-
36
- // Create new user
37
- const createdUser = new this.userModel(this.model.map(input));
38
-
39
- try {
40
- // Save created user
41
- await createdUser.save();
42
- } catch (error) {
43
- if (error.code === 11000) {
44
- throw new UnprocessableEntityException(`User with email address "${(input as any).email}" already exists`);
45
- } else {
46
- throw new UnprocessableEntityException();
47
- }
48
- }
49
-
50
- // Inform subscriber
51
- pubSub.publish('userCreated', { userCreated: createdUser });
52
-
53
- // Return created user
54
- return createdUser;
55
- }
56
-
57
- /**
58
- * Get user via ID
59
- */
60
- async get(id: string, ...args: any[]): Promise<TUser> {
61
- const user = await this.userModel.findOne({ id: id }).exec();
62
- if (!user) {
63
- throw new NotFoundException();
64
- }
65
- return user;
66
- }
67
-
68
- /**
69
- * Get user via email
70
- */
71
- async getViaEmail(email: string, ...args: any[]): Promise<TUser> {
72
- let user = await this.userModel.findOne({ email }).exec();
73
-
74
- if (!user) {
75
- throw new NotFoundException();
76
- }
77
-
78
- user = this.model.map(user);
79
-
80
- return user;
81
- }
82
-
83
- /**
84
- * Get users via filter
85
- */
86
- find(filterArgs?: FilterArgs, ...args: any[]): Promise<TUser[]> {
87
- // Return found users
88
- return this.userModel.find(...Filter.convertFilterArgsToQuery(filterArgs)).exec();
89
- }
90
-
91
- /**
92
- * Get user via ID
93
- */
94
- async update(id: string, input: TUserInput, ...args: any[]): Promise<TUser> {
95
- // Check if user exists
96
- let user = await this.userModel.findOne({ id });
97
-
98
- if (!user) {
99
- throw new NotFoundException(`User not found with ID: ${id}`);
100
- }
101
-
102
- // Prepare input
103
- if ((input as any).password) {
104
- (input as any).password = await bcrypt.hash((input as any).password, 10);
105
- }
106
-
107
- // Update
108
- user.set(input);
109
-
110
- // Save
111
- await user.save();
112
-
113
- // Map for response
114
- user = this.model.map(user);
115
-
116
- // Return user
117
- return user;
118
- }
119
-
120
- /**
121
- * Delete user via ID
122
- */
123
- async delete(id: string, ...args: any[]): Promise<TUser> {
124
- // Search user
125
- const user = await this.userModel.findOne({ id }).exec();
126
-
127
- // Check user
128
- if (!user) {
129
- throw new NotFoundException();
130
- }
131
-
132
- // Delete user
133
- await this.userModel.deleteOne({ id: user.id });
134
-
135
- // Return deleted user
136
- return user;
137
- }
138
- }