@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.
- package/dist/config.env.js +3 -2
- package/dist/config.env.js.map +1 -1
- package/dist/core/common/decorators/restricted.decorator.d.ts +2 -0
- package/dist/core/common/decorators/restricted.decorator.js +10 -7
- package/dist/core/common/decorators/restricted.decorator.js.map +1 -1
- package/dist/core/common/helpers/input.helper.d.ts +12 -2
- package/dist/core/common/helpers/input.helper.js +50 -11
- package/dist/core/common/helpers/input.helper.js.map +1 -1
- package/dist/core/common/interfaces/service-options.interface.d.ts +6 -0
- package/dist/core/common/models/core-model.model.d.ts +1 -1
- package/dist/core/common/models/core-model.model.js.map +1 -1
- package/dist/core/common/pipes/check-input.pipe.js +1 -1
- package/dist/core/common/pipes/check-input.pipe.js.map +1 -1
- package/dist/core/common/services/crud.service.js +17 -19
- package/dist/core/common/services/crud.service.js.map +1 -1
- package/dist/core/common/services/module.service.d.ts +13 -1
- package/dist/core/common/services/module.service.js +39 -4
- package/dist/core/common/services/module.service.js.map +1 -1
- package/dist/core/common/types/ids.type.d.ts +8 -0
- package/dist/core/common/types/ids.type.js +3 -0
- package/dist/core/common/types/ids.type.js.map +1 -0
- package/dist/core/modules/auth/guards/roles.guard.js.map +1 -1
- package/dist/core/modules/user/core-user.service.js +38 -35
- package/dist/core/modules/user/core-user.service.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/server/modules/user/user.model.d.ts +1 -1
- package/dist/server/modules/user/user.resolver.d.ts +2 -2
- package/dist/server/modules/user/user.resolver.js +30 -14
- package/dist/server/modules/user/user.resolver.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +37 -37
- package/src/config.env.ts +3 -2
- package/src/core/common/decorators/restricted.decorator.ts +16 -10
- package/src/core/common/helpers/input.helper.ts +63 -14
- package/src/core/common/interfaces/service-options.interface.ts +19 -1
- package/src/core/common/models/core-model.model.ts +1 -1
- package/src/core/common/pipes/check-input.pipe.ts +1 -1
- package/src/core/common/services/crud.service.ts +17 -22
- package/src/core/common/services/module.service.ts +75 -9
- package/src/core/common/types/ids.type.ts +7 -0
- package/src/core/modules/auth/guards/roles.guard.ts +1 -1
- package/src/core/modules/user/core-user.service.ts +42 -44
- package/src/index.ts +1 -0
- 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
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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
|
-
|
|
167
|
-
await
|
|
164
|
+
dbObject.passwordResetToken = resetToken;
|
|
165
|
+
await dbObject.save();
|
|
168
166
|
|
|
169
167
|
// Return user
|
|
170
|
-
return
|
|
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, {
|
|
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.
|
|
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, {
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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.
|
|
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, {
|
|
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.
|
|
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
|
|