@lenne.tech/nest-server 8.1.0 → 8.2.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 (46) hide show
  1. package/dist/config.env.js +3 -2
  2. package/dist/config.env.js.map +1 -1
  3. package/dist/core/common/decorators/restricted.decorator.d.ts +2 -0
  4. package/dist/core/common/decorators/restricted.decorator.js +10 -7
  5. package/dist/core/common/decorators/restricted.decorator.js.map +1 -1
  6. package/dist/core/common/helpers/input.helper.d.ts +12 -2
  7. package/dist/core/common/helpers/input.helper.js +50 -11
  8. package/dist/core/common/helpers/input.helper.js.map +1 -1
  9. package/dist/core/common/interfaces/service-options.interface.d.ts +6 -0
  10. package/dist/core/common/models/core-model.model.d.ts +1 -1
  11. package/dist/core/common/models/core-model.model.js.map +1 -1
  12. package/dist/core/common/pipes/check-input.pipe.js +1 -1
  13. package/dist/core/common/pipes/check-input.pipe.js.map +1 -1
  14. package/dist/core/common/services/crud.service.js +17 -19
  15. package/dist/core/common/services/crud.service.js.map +1 -1
  16. package/dist/core/common/services/module.service.d.ts +13 -1
  17. package/dist/core/common/services/module.service.js +39 -4
  18. package/dist/core/common/services/module.service.js.map +1 -1
  19. package/dist/core/common/types/ids.type.d.ts +8 -0
  20. package/dist/core/common/types/ids.type.js +3 -0
  21. package/dist/core/common/types/ids.type.js.map +1 -0
  22. package/dist/core/modules/auth/guards/roles.guard.js.map +1 -1
  23. package/dist/core/modules/user/core-user.service.js +38 -35
  24. package/dist/core/modules/user/core-user.service.js.map +1 -1
  25. package/dist/index.d.ts +1 -0
  26. package/dist/index.js +1 -0
  27. package/dist/index.js.map +1 -1
  28. package/dist/server/modules/user/user.model.d.ts +1 -1
  29. package/dist/server/modules/user/user.resolver.d.ts +2 -2
  30. package/dist/server/modules/user/user.resolver.js +30 -14
  31. package/dist/server/modules/user/user.resolver.js.map +1 -1
  32. package/dist/tsconfig.build.tsbuildinfo +1 -1
  33. package/package.json +37 -37
  34. package/src/config.env.ts +3 -2
  35. package/src/core/common/decorators/restricted.decorator.ts +16 -10
  36. package/src/core/common/helpers/input.helper.ts +63 -14
  37. package/src/core/common/interfaces/service-options.interface.ts +19 -1
  38. package/src/core/common/models/core-model.model.ts +1 -1
  39. package/src/core/common/pipes/check-input.pipe.ts +1 -1
  40. package/src/core/common/services/crud.service.ts +17 -22
  41. package/src/core/common/services/module.service.ts +75 -9
  42. package/src/core/common/types/ids.type.ts +7 -0
  43. package/src/core/modules/auth/guards/roles.guard.ts +1 -1
  44. package/src/core/modules/user/core-user.service.ts +42 -44
  45. package/src/index.ts +1 -0
  46. package/src/server/modules/user/user.resolver.ts +26 -20
@@ -47,6 +47,11 @@ export abstract class CoreUserService<
47
47
  // Distinguish between different error messages when saving
48
48
  try {
49
49
  await createdUser.save();
50
+ if (!createdUser.ownerIds) {
51
+ createdUser.ownerIds = [];
52
+ }
53
+ createdUser.ownerIds.push(createdUser.id);
54
+ await createdUser.save();
50
55
  } catch (error) {
51
56
  if (error.code === 11000) {
52
57
  throw new UnprocessableEntityException(
@@ -68,16 +73,11 @@ export abstract class CoreUserService<
68
73
  * Get user via email
69
74
  */
70
75
  async getViaEmail(email: string, serviceOptions?: ServiceOptions): Promise<TUser> {
71
- return this.process(
72
- async () => {
73
- const user = await this.mainDbModel.findOne({ email }).exec();
74
- if (!user) {
75
- throw new NotFoundException(`No user found with email: ${email}`);
76
- }
77
- return user;
78
- },
79
- { serviceOptions }
80
- );
76
+ const dbObject = await this.mainDbModel.findOne({ email }).exec();
77
+ if (!dbObject) {
78
+ throw new NotFoundException(`No user found with email: ${email}`);
79
+ }
80
+ return this.process(async () => dbObject, { dbObject, serviceOptions });
81
81
  }
82
82
 
83
83
  /**
@@ -97,30 +97,29 @@ export abstract class CoreUserService<
97
97
  * Verify user with token
98
98
  */
99
99
  async verify(token: string, serviceOptions?: ServiceOptions): Promise<TUser> {
100
+ // Get user
101
+ const dbObject = await this.mainDbModel.findOne({ verificationToken: token }).exec();
102
+ if (!dbObject) {
103
+ throw new NotFoundException(`No user found with verify token: ${token}`);
104
+ }
105
+ if (!dbObject.verificationToken) {
106
+ throw new Error('User has no token');
107
+ }
108
+ if (dbObject.verified) {
109
+ throw new Error('User already verified');
110
+ }
100
111
  return this.process(
101
112
  async () => {
102
- // Get user
103
- const user = await this.mainDbModel.findOne({ verificationToken: token }).exec();
104
- if (!user) {
105
- throw new NotFoundException(`No user found with verify token: ${token}`);
106
- }
107
- if (!user.verificationToken) {
108
- throw new Error('User has no token');
109
- }
110
- if (user.verified) {
111
- throw new Error('User already verified');
112
- }
113
-
114
113
  // Update user
115
- await Object.assign(user, {
114
+ await Object.assign(dbObject, {
116
115
  verified: true,
117
116
  verificationToken: null,
118
117
  }).save();
119
118
 
120
119
  // Return prepared user
121
- return user;
120
+ return dbObject;
122
121
  },
123
- { serviceOptions }
122
+ { dbObject, serviceOptions }
124
123
  );
125
124
  }
126
125
 
@@ -128,24 +127,24 @@ export abstract class CoreUserService<
128
127
  * Set newpassword for user with token
129
128
  */
130
129
  async resetPassword(token: string, newPassword: string, serviceOptions?: ServiceOptions): Promise<TUser> {
130
+ // Get user
131
+ const dbObject = await this.mainDbModel.findOne({ passwordResetToken: token }).exec();
132
+ if (!dbObject) {
133
+ throw new NotFoundException(`No user found with password reset token: ${token}`);
134
+ }
135
+
131
136
  return this.process(
132
137
  async () => {
133
- // Get user
134
- const user = await this.mainDbModel.findOne({ passwordResetToken: token }).exec();
135
- if (!user) {
136
- throw new NotFoundException(`No user found with password reset token: ${token}`);
137
- }
138
-
139
138
  // Update user
140
- await Object.assign(user, {
139
+ await Object.assign(dbObject, {
141
140
  password: await bcrypt.hash(newPassword, 10),
142
141
  passwordResetToken: null,
143
142
  }).save();
144
143
 
145
144
  // Return user
146
- return user;
145
+ return dbObject;
147
146
  },
148
- { serviceOptions }
147
+ { dbObject, serviceOptions }
149
148
  );
150
149
  }
151
150
 
@@ -153,23 +152,22 @@ export abstract class CoreUserService<
153
152
  * Set password rest token for email
154
153
  */
155
154
  async setPasswordResetTokenForEmail(email: string, serviceOptions?: ServiceOptions): Promise<TUser> {
155
+ // Get user
156
+ const dbObject = await this.mainDbModel.findOne({ email }).exec();
157
+ if (!dbObject) {
158
+ throw new NotFoundException(`No user found with email: ${email}`);
159
+ }
156
160
  return this.process(
157
161
  async () => {
158
- // Get user
159
- const user = await this.mainDbModel.findOne({ email }).exec();
160
- if (!user) {
161
- throw new NotFoundException(`No user found with email: ${email}`);
162
- }
163
-
164
162
  // Set reset token
165
163
  const resetToken = crypto.randomBytes(32).toString('hex');
166
- user.passwordResetToken = resetToken;
167
- await user.save();
164
+ dbObject.passwordResetToken = resetToken;
165
+ await dbObject.save();
168
166
 
169
167
  // Return user
170
- return user;
168
+ return dbObject;
171
169
  },
172
- { serviceOptions }
170
+ { dbObject, serviceOptions }
173
171
  );
174
172
  }
175
173
 
package/src/index.ts CHANGED
@@ -52,6 +52,7 @@ export * from './core/common/services/module.service';
52
52
  export * from './core/common/services/template.service';
53
53
  export * from './core/common/types/core-model-constructor.type';
54
54
  export * from './core/common/types/field-selection.type';
55
+ export * from './core/common/types/ids.type';
55
56
  export * from './core/common/types/plain-input.type';
56
57
  export * from './core/common/types/string-or-object-id.type';
57
58
 
@@ -6,7 +6,6 @@ import { FilterArgs } from '../../../core/common/args/filter.args';
6
6
  import { GraphQLUser } from '../../../core/common/decorators/graphql-user.decorator';
7
7
  import { Roles } from '../../../core/common/decorators/roles.decorator';
8
8
  import { RoleEnum } from '../../../core/common/enums/role.enum';
9
- import { check } from '../../../core/common/helpers/input.helper';
10
9
  import { UserCreateInput } from './inputs/user-create.input';
11
10
  import { UserInput } from './inputs/user.input';
12
11
  import { User } from './user.model';
@@ -32,16 +31,23 @@ export class UserResolver {
32
31
  @Roles(RoleEnum.ADMIN)
33
32
  @Query((returns) => [User], { description: 'Find users (via filter)' })
34
33
  async findUsers(@Info() info: GraphQLResolveInfo, @Args() args?: FilterArgs) {
35
- return await this.userService.find(args, { fieldSelection: { info, select: 'findUsers' } });
34
+ return await this.userService.find(args, {
35
+ fieldSelection: { info, select: 'findUsers' },
36
+ inputType: FilterArgs,
37
+ });
36
38
  }
37
39
 
38
40
  /**
39
41
  * Get user via ID
40
42
  */
41
- @Roles(RoleEnum.OWNER, RoleEnum.ADMIN)
43
+ @Roles(RoleEnum.USER)
42
44
  @Query((returns) => User, { description: 'Get user with specified ID' })
43
- async getUser(@Args('id') id: string, @Info() info: GraphQLResolveInfo): Promise<User> {
44
- return await this.userService.get(id, { fieldSelection: { info, select: 'getUser' } });
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.OWNER, RoleEnum.ADMIN],
50
+ });
45
51
  }
46
52
 
47
53
  /**
@@ -73,21 +79,24 @@ export class UserResolver {
73
79
  @GraphQLUser() user: User,
74
80
  @Info() info: GraphQLResolveInfo
75
81
  ): Promise<User> {
76
- // Check input
77
- // Hint: necessary as long as global CheckInputPipe can't access context for current user
78
- // (see https://github.com/nestjs/graphql/issues/325)
79
- input = await check(input, user, UserCreateInput);
80
-
81
- return await this.userService.create(input, { currentUser: user, fieldSelection: { info, select: 'createUser' } });
82
+ return await this.userService.create(input, {
83
+ currentUser: user,
84
+ fieldSelection: { info, select: 'createUser' },
85
+ inputType: UserCreateInput,
86
+ });
82
87
  }
83
88
 
84
89
  /**
85
90
  * Delete existing user
86
91
  */
87
- @Roles(RoleEnum.ADMIN, RoleEnum.OWNER)
92
+ @Roles(RoleEnum.USER)
88
93
  @Mutation((returns) => User, { description: 'Delete existing user' })
89
- async deleteUser(@Args('id') id: string, @Info() info: GraphQLResolveInfo): Promise<User> {
90
- return await this.userService.delete(id, { fieldSelection: { info, select: 'deleteUser' } });
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.OWNER],
99
+ });
91
100
  }
92
101
 
93
102
  /**
@@ -101,7 +110,7 @@ export class UserResolver {
101
110
  /**
102
111
  * Update existing user
103
112
  */
104
- @Roles(RoleEnum.ADMIN, RoleEnum.OWNER)
113
+ @Roles(RoleEnum.USER)
105
114
  @Mutation((returns) => User, { description: 'Update existing user' })
106
115
  async updateUser(
107
116
  @Args('input') input: UserInput,
@@ -109,15 +118,12 @@ export class UserResolver {
109
118
  @GraphQLUser() user: User,
110
119
  @Info() info: GraphQLResolveInfo
111
120
  ): Promise<User> {
112
- // Check input
113
- // Hint: necessary as long as global CheckInputPipe can't access context for current user
114
- // (see https://github.com/nestjs/graphql/issues/325)
115
- input = await check(input, user, UserInput);
116
-
117
121
  // Update user
118
122
  return await this.userService.update(id, input, {
119
123
  currentUser: user,
120
124
  fieldSelection: { info, select: 'updateUser' },
125
+ inputType: UserInput,
126
+ roles: [RoleEnum.ADMIN, RoleEnum.OWNER],
121
127
  });
122
128
  }
123
129