@lenne.tech/nest-server 8.6.24 → 8.6.25
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 +1 -1
- package/dist/config.env.js.map +1 -1
- package/dist/core/common/decorators/restricted.decorator.d.ts +1 -0
- package/dist/core/common/decorators/restricted.decorator.js +68 -57
- package/dist/core/common/decorators/restricted.decorator.js.map +1 -1
- package/dist/core/common/enums/role.enum.d.ts +2 -0
- package/dist/core/common/enums/role.enum.js +2 -0
- package/dist/core/common/enums/role.enum.js.map +1 -1
- package/dist/core/common/helpers/input.helper.d.ts +1 -0
- package/dist/core/common/helpers/input.helper.js +10 -2
- package/dist/core/common/helpers/input.helper.js.map +1 -1
- package/dist/core/common/helpers/model.helper.d.ts +6 -2
- package/dist/core/common/helpers/model.helper.js +14 -6
- package/dist/core/common/helpers/model.helper.js.map +1 -1
- package/dist/core/common/helpers/service.helper.d.ts +1 -0
- package/dist/core/common/helpers/service.helper.js +34 -9
- package/dist/core/common/helpers/service.helper.js.map +1 -1
- package/dist/core/common/services/core-cron-jobs.service.js +2 -2
- package/dist/core/common/services/core-cron-jobs.service.js.map +1 -1
- package/dist/core/common/services/module.service.js +3 -3
- package/dist/core/common/services/module.service.js.map +1 -1
- package/dist/core/common/types/plain-object.type.d.ts +3 -0
- package/dist/core/common/types/plain-object.type.js +3 -0
- package/dist/core/common/types/plain-object.type.js.map +1 -0
- package/dist/core/modules/auth/guards/roles.guard.js +4 -1
- package/dist/core/modules/auth/guards/roles.guard.js.map +1 -1
- package/dist/core/modules/auth/services/core-auth.service.js +3 -1
- package/dist/core/modules/auth/services/core-auth.service.js.map +1 -1
- package/dist/core/modules/file/core-file-info.model.d.ts +1 -1
- package/dist/core/modules/file/core-file-info.model.js +4 -0
- package/dist/core/modules/file/core-file-info.model.js.map +1 -1
- package/dist/core/modules/user/core-user.service.js +2 -0
- 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/common/services/cron-jobs.service.js +1 -1
- package/dist/server/common/services/cron-jobs.service.js.map +1 -1
- package/dist/server/modules/auth/auth.service.js +21 -4
- package/dist/server/modules/auth/auth.service.js.map +1 -1
- package/dist/server/modules/file/file.controller.js +1 -1
- package/dist/server/modules/file/file.controller.js.map +1 -1
- package/dist/server/modules/file/file.resolver.js +1 -0
- package/dist/server/modules/file/file.resolver.js.map +1 -1
- package/dist/server/modules/user/user.model.d.ts +3 -3
- package/dist/server/modules/user/user.model.js +5 -7
- package/dist/server/modules/user/user.model.js.map +1 -1
- package/dist/server/modules/user/user.module.js +2 -0
- package/dist/server/modules/user/user.module.js.map +1 -1
- package/dist/server/modules/user/user.resolver.js +6 -0
- package/dist/server/modules/user/user.resolver.js.map +1 -1
- package/dist/server/modules/user/user.service.js +1 -1
- package/dist/server/modules/user/user.service.js.map +1 -1
- package/dist/test/test.helper.js +4 -4
- package/dist/test/test.helper.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +3 -2
- package/src/config.env.ts +1 -1
- package/src/core/common/decorators/restricted.decorator.ts +95 -75
- package/src/core/common/enums/role.enum.ts +34 -6
- package/src/core/common/helpers/context.helper.ts +2 -2
- package/src/core/common/helpers/input.helper.ts +17 -0
- package/src/core/common/helpers/model.helper.ts +20 -6
- package/src/core/common/helpers/service.helper.ts +43 -11
- package/src/core/common/services/core-cron-jobs.service.ts +2 -2
- package/src/core/common/services/module.service.ts +5 -5
- package/src/core/common/types/plain-object.type.ts +5 -0
- package/src/core/common/types/remove-methods.type.ts +1 -0
- package/src/core/modules/auth/guards/roles.guard.ts +7 -2
- package/src/core/modules/auth/services/core-auth.service.ts +9 -1
- package/src/core/modules/file/core-file-info.model.ts +11 -1
- package/src/core/modules/user/core-user.service.ts +5 -0
- package/src/index.ts +1 -0
- package/src/server/common/services/cron-jobs.service.ts +1 -1
- package/src/server/modules/auth/auth.service.ts +13 -6
- package/src/server/modules/file/file.controller.ts +1 -1
- package/src/server/modules/file/file.resolver.ts +1 -0
- package/src/server/modules/user/user.model.ts +6 -5
- package/src/server/modules/user/user.module.ts +2 -0
- package/src/server/modules/user/user.resolver.ts +6 -0
- package/src/server/modules/user/user.service.ts +1 -1
- package/src/test/test.helper.ts +6 -6
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
|
2
2
|
import { JwtService } from '@nestjs/jwt';
|
|
3
3
|
import * as bcrypt from 'bcrypt';
|
|
4
|
+
import { sha256 } from 'js-sha256';
|
|
4
5
|
import { merge } from '../../../common/helpers/config.helper';
|
|
5
6
|
import { ServiceOptions } from '../../../common/interfaces/service-options.interface';
|
|
6
7
|
import { ICoreAuthUser } from '../interfaces/core-auth-user.interface';
|
|
@@ -23,10 +24,17 @@ export class CoreAuthService {
|
|
|
23
24
|
serviceOptions?: ServiceOptions
|
|
24
25
|
): Promise<{ token: string; user: ICoreAuthUser }> {
|
|
25
26
|
serviceOptions = merge(serviceOptions || {}, { prepareOutput: null });
|
|
27
|
+
|
|
28
|
+
// Get user
|
|
26
29
|
const user = await this.userService.getViaEmail(email, serviceOptions);
|
|
27
|
-
if (
|
|
30
|
+
if (
|
|
31
|
+
!user ||
|
|
32
|
+
!((await bcrypt.compare(password, user.password)) || (await bcrypt.compare(sha256(password), user.password)))
|
|
33
|
+
) {
|
|
28
34
|
throw new UnauthorizedException();
|
|
29
35
|
}
|
|
36
|
+
|
|
37
|
+
// Return JWT
|
|
30
38
|
const payload: JwtPayload = { email: user.email };
|
|
31
39
|
return {
|
|
32
40
|
token: this.jwtService.sign(payload),
|
|
@@ -8,7 +8,17 @@ import { CoreModel } from '../../common/models/core-model.model';
|
|
|
8
8
|
*/
|
|
9
9
|
@ObjectType({ description: 'Information about file' })
|
|
10
10
|
export class CoreFileInfo extends CoreModel {
|
|
11
|
-
|
|
11
|
+
// ===========================================================================
|
|
12
|
+
// Getter
|
|
13
|
+
// ===========================================================================
|
|
14
|
+
|
|
15
|
+
get _id() {
|
|
16
|
+
return new Types.ObjectId(this.id);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// ===========================================================================
|
|
20
|
+
// Properties
|
|
21
|
+
// ===========================================================================
|
|
12
22
|
|
|
13
23
|
@Field(() => String, { description: 'ID of the file' })
|
|
14
24
|
id: string = undefined;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BadRequestException, NotFoundException, UnprocessableEntityException } from '@nestjs/common';
|
|
2
2
|
import * as bcrypt from 'bcrypt';
|
|
3
3
|
import * as crypto from 'crypto';
|
|
4
|
+
import { sha256 } from 'js-sha256';
|
|
4
5
|
import { Document, Model } from 'mongoose';
|
|
5
6
|
import { merge } from '../../common/helpers/config.helper';
|
|
6
7
|
import { assignPlain } from '../../common/helpers/input.helper';
|
|
@@ -128,6 +129,10 @@ export abstract class CoreUserService<
|
|
|
128
129
|
|
|
129
130
|
return this.process(
|
|
130
131
|
async () => {
|
|
132
|
+
// Check if the password was transmitted encrypted
|
|
133
|
+
// If not, the password is encrypted to enable future encrypted and unencrypted transmissions
|
|
134
|
+
newPassword = /^[a-f0-9]{64}$/i.test(newPassword) ? newPassword : sha256(newPassword);
|
|
135
|
+
|
|
131
136
|
// Update and return user
|
|
132
137
|
return await assignPlain(dbObject, {
|
|
133
138
|
password: await bcrypt.hash(newPassword, 10),
|
package/src/index.ts
CHANGED
|
@@ -62,6 +62,7 @@ export * from './core/common/types/field-selection.type';
|
|
|
62
62
|
export * from './core/common/types/ids.type';
|
|
63
63
|
export * from './core/common/types/maybe-promise.type';
|
|
64
64
|
export * from './core/common/types/plain-input.type';
|
|
65
|
+
export * from './core/common/types/plain-object.type';
|
|
65
66
|
export * from './core/common/types/remove-methods.type';
|
|
66
67
|
export * from './core/common/types/require-only-one.type';
|
|
67
68
|
export * from './core/common/types/required-at-least-one.type';
|
|
@@ -21,7 +21,7 @@ export class CronJobs extends CoreCronJobs {
|
|
|
21
21
|
// ===================================================================================================================
|
|
22
22
|
|
|
23
23
|
protected async sayHello() {
|
|
24
|
-
console.
|
|
24
|
+
console.info('Hello :)');
|
|
25
25
|
await new Promise<void>((resolve) => {
|
|
26
26
|
setTimeout(() => resolve(), 30000);
|
|
27
27
|
});
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
|
2
2
|
import { JwtService } from '@nestjs/jwt';
|
|
3
3
|
import * as bcrypt from 'bcrypt';
|
|
4
|
+
import { sha256 } from 'js-sha256';
|
|
4
5
|
import envConfig from '../../../config.env';
|
|
6
|
+
import { Roles } from '../../../core/common/decorators/roles.decorator';
|
|
7
|
+
import { RoleEnum } from '../../../core/common/enums/role.enum';
|
|
5
8
|
import { prepareServiceOptions } from '../../../core/common/helpers/service.helper';
|
|
6
9
|
import { ServiceOptions } from '../../../core/common/interfaces/service-options.interface';
|
|
7
10
|
import { EmailService } from '../../../core/common/services/email.service';
|
|
@@ -12,6 +15,7 @@ import { AuthSignInInput } from './inputs/auth-sign-in.input';
|
|
|
12
15
|
import { AuthSignUpInput } from './inputs/auth-sign-up.input';
|
|
13
16
|
|
|
14
17
|
@Injectable()
|
|
18
|
+
@Roles(RoleEnum.ADMIN)
|
|
15
19
|
export class AuthService {
|
|
16
20
|
constructor(
|
|
17
21
|
protected readonly jwtService: JwtService,
|
|
@@ -22,6 +26,7 @@ export class AuthService {
|
|
|
22
26
|
/**
|
|
23
27
|
* Sign in for user
|
|
24
28
|
*/
|
|
29
|
+
@Roles(RoleEnum.S_EVERYONE)
|
|
25
30
|
async signIn(input: AuthSignInInput, serviceOptions?: ServiceOptions): Promise<Auth> {
|
|
26
31
|
// Prepare service options
|
|
27
32
|
const serviceOptionsForUserService = prepareServiceOptions(serviceOptions, {
|
|
@@ -34,12 +39,13 @@ export class AuthService {
|
|
|
34
39
|
|
|
35
40
|
// Get and check user
|
|
36
41
|
const user = await this.userService.getViaEmail(input.email, serviceOptionsForUserService);
|
|
37
|
-
if (
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
if (
|
|
43
|
+
!user ||
|
|
44
|
+
!(
|
|
45
|
+
(await bcrypt.compare(input.password, user.password)) ||
|
|
46
|
+
(await bcrypt.compare(sha256(input.password), user.password))
|
|
47
|
+
)
|
|
48
|
+
) {
|
|
43
49
|
throw new UnauthorizedException();
|
|
44
50
|
}
|
|
45
51
|
|
|
@@ -54,6 +60,7 @@ export class AuthService {
|
|
|
54
60
|
/**
|
|
55
61
|
* Register a new user Account
|
|
56
62
|
*/
|
|
63
|
+
@Roles(RoleEnum.S_EVERYONE)
|
|
57
64
|
async signUp(input: AuthSignUpInput, serviceOptions?: ServiceOptions): Promise<Auth> {
|
|
58
65
|
// Prepare service options
|
|
59
66
|
const serviceOptionsForUserService = prepareServiceOptions(serviceOptions, {
|
|
@@ -42,6 +42,6 @@ export class FileController extends CoreFileController {
|
|
|
42
42
|
})
|
|
43
43
|
)
|
|
44
44
|
uploadFiles(@UploadedFiles() files, @Body() fields: any) {
|
|
45
|
-
console.
|
|
45
|
+
console.info('Saved file info', JSON.stringify({ files, fields }, null, 2));
|
|
46
46
|
}
|
|
47
47
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Field, ObjectType } from '@nestjs/graphql';
|
|
2
2
|
import { Prop, Schema as MongooseSchema, SchemaFactory } from '@nestjs/mongoose';
|
|
3
|
-
import { Document, Schema
|
|
4
|
-
import { mapClasses } from '../../../core/common/helpers/model.helper';
|
|
3
|
+
import { Document, Schema } from 'mongoose';
|
|
5
4
|
import { CoreUserModel } from '../../../core/modules/user/core-user.model';
|
|
6
5
|
import { PersistenceModel } from '../../common/models/persistence.model';
|
|
7
6
|
|
|
@@ -34,7 +33,7 @@ export class User extends CoreUserModel implements PersistenceModel {
|
|
|
34
33
|
nullable: true,
|
|
35
34
|
})
|
|
36
35
|
@Prop({ type: Schema.Types.ObjectId, ref: 'User' })
|
|
37
|
-
createdBy:
|
|
36
|
+
createdBy: string = undefined;
|
|
38
37
|
|
|
39
38
|
/**
|
|
40
39
|
* ID of the user who updated the object
|
|
@@ -46,7 +45,7 @@ export class User extends CoreUserModel implements PersistenceModel {
|
|
|
46
45
|
nullable: true,
|
|
47
46
|
})
|
|
48
47
|
@Prop({ type: Schema.Types.ObjectId, ref: 'User' })
|
|
49
|
-
updatedBy:
|
|
48
|
+
updatedBy: string = undefined;
|
|
50
49
|
|
|
51
50
|
// ===================================================================================================================
|
|
52
51
|
// Methods
|
|
@@ -66,7 +65,9 @@ export class User extends CoreUserModel implements PersistenceModel {
|
|
|
66
65
|
*/
|
|
67
66
|
map(input) {
|
|
68
67
|
super.map(input);
|
|
69
|
-
|
|
68
|
+
// There is nothing to map yet. Non-primitive variables should always be mapped.
|
|
69
|
+
// If something comes up, you can use `mapClasses` / `mapClassesAsync` from ModelHelper.
|
|
70
|
+
return this;
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
73
|
|
|
@@ -2,6 +2,7 @@ import { Module } from '@nestjs/common';
|
|
|
2
2
|
import { MongooseModule } from '@nestjs/mongoose';
|
|
3
3
|
import { PubSub } from 'graphql-subscriptions';
|
|
4
4
|
import { JSON } from '../../../core/common/scalars/json.scalar';
|
|
5
|
+
import { ConfigService } from '../../../core/common/services/config.service';
|
|
5
6
|
import { AvatarController } from './avatar.controller';
|
|
6
7
|
import { User, UserSchema } from './user.model';
|
|
7
8
|
import { UserResolver } from './user.resolver';
|
|
@@ -16,6 +17,7 @@ import { UserService } from './user.service';
|
|
|
16
17
|
providers: [
|
|
17
18
|
JSON,
|
|
18
19
|
UserResolver,
|
|
20
|
+
ConfigService,
|
|
19
21
|
UserService,
|
|
20
22
|
{
|
|
21
23
|
provide: 'USER_CLASS',
|
|
@@ -15,6 +15,7 @@ import { UserService } from './user.service';
|
|
|
15
15
|
* Resolver to process with user data
|
|
16
16
|
*/
|
|
17
17
|
@Resolver(() => User)
|
|
18
|
+
@Roles(RoleEnum.ADMIN)
|
|
18
19
|
export class UserResolver {
|
|
19
20
|
/**
|
|
20
21
|
* Import services
|
|
@@ -53,6 +54,7 @@ export class UserResolver {
|
|
|
53
54
|
/**
|
|
54
55
|
* Get verified state of user with token
|
|
55
56
|
*/
|
|
57
|
+
@Roles(RoleEnum.S_USER)
|
|
56
58
|
@Query(() => Boolean, { description: 'Get verified state of user with token' })
|
|
57
59
|
async getVerifiedState(@Args('token') token: string) {
|
|
58
60
|
return await this.userService.getVerifiedState(token);
|
|
@@ -61,6 +63,7 @@ export class UserResolver {
|
|
|
61
63
|
/**
|
|
62
64
|
* Request new password for user with email
|
|
63
65
|
*/
|
|
66
|
+
@Roles(RoleEnum.S_EVERYONE)
|
|
64
67
|
@Query(() => Boolean, { description: 'Request new password for user with email' })
|
|
65
68
|
async requestPasswordResetMail(@Args('email') email: string): Promise<boolean> {
|
|
66
69
|
return !!(await this.userService.sendPasswordResetMail(email));
|
|
@@ -103,6 +106,7 @@ export class UserResolver {
|
|
|
103
106
|
/**
|
|
104
107
|
* Set new password for user with token
|
|
105
108
|
*/
|
|
109
|
+
@Roles(RoleEnum.S_EVERYONE)
|
|
106
110
|
@Mutation(() => Boolean, { description: 'Set new password for user with token' })
|
|
107
111
|
async resetPassword(@Args('token') token: string, @Args('password') password: string): Promise<boolean> {
|
|
108
112
|
return !!(await this.userService.resetPassword(token, password));
|
|
@@ -131,6 +135,7 @@ export class UserResolver {
|
|
|
131
135
|
/**
|
|
132
136
|
* Verify user with email
|
|
133
137
|
*/
|
|
138
|
+
@Roles(RoleEnum.S_EVERYONE)
|
|
134
139
|
@Mutation(() => Boolean, { description: 'Verify user with email' })
|
|
135
140
|
async verifyUser(@Args('token') token: string): Promise<boolean> {
|
|
136
141
|
return !!(await this.userService.verify(token));
|
|
@@ -143,6 +148,7 @@ export class UserResolver {
|
|
|
143
148
|
/**
|
|
144
149
|
* Subscription for created user
|
|
145
150
|
*/
|
|
151
|
+
@Roles(RoleEnum.ADMIN)
|
|
146
152
|
@Subscription(() => User, {
|
|
147
153
|
filter(this: UserResolver, payload, variables, context) {
|
|
148
154
|
return context?.user?.hasRole?.(RoleEnum.ADMIN);
|
|
@@ -98,7 +98,7 @@ export class UserService extends CoreUserService<User, UserInput, UserCreateInpu
|
|
|
98
98
|
if (user.avatar) {
|
|
99
99
|
fs.unlink(envConfig.staticAssets.path + '/avatars/' + user.avatar, (err) => {
|
|
100
100
|
if (err) {
|
|
101
|
-
console.
|
|
101
|
+
console.error(err);
|
|
102
102
|
}
|
|
103
103
|
});
|
|
104
104
|
}
|
package/src/test/test.helper.ts
CHANGED
|
@@ -91,7 +91,7 @@ export interface TestGraphQLOptions {
|
|
|
91
91
|
countOfSubscriptionMessages?: number;
|
|
92
92
|
|
|
93
93
|
/**
|
|
94
|
-
*
|
|
94
|
+
* Output information in the console
|
|
95
95
|
*/
|
|
96
96
|
log?: boolean;
|
|
97
97
|
|
|
@@ -444,7 +444,7 @@ export class TestHelper {
|
|
|
444
444
|
//
|
|
445
445
|
// // Log response
|
|
446
446
|
// if (log) {
|
|
447
|
-
// console.
|
|
447
|
+
// console.info(response);
|
|
448
448
|
// }
|
|
449
449
|
//
|
|
450
450
|
// // Check data
|
|
@@ -468,7 +468,7 @@ export class TestHelper {
|
|
|
468
468
|
|
|
469
469
|
// Response
|
|
470
470
|
if (log) {
|
|
471
|
-
console.
|
|
471
|
+
console.info(requestConfig);
|
|
472
472
|
}
|
|
473
473
|
const response = await (variables ? request : request.send(requestConfig.payload));
|
|
474
474
|
return this.processResponse(response, statusCode, log, logError);
|
|
@@ -528,7 +528,7 @@ export class TestHelper {
|
|
|
528
528
|
processResponse(response, statusCode, log, logError) {
|
|
529
529
|
// Log response
|
|
530
530
|
if (log) {
|
|
531
|
-
console.
|
|
531
|
+
console.info('Response', JSON.stringify(response, null, 2));
|
|
532
532
|
}
|
|
533
533
|
|
|
534
534
|
// Log error
|
|
@@ -565,14 +565,14 @@ export class TestHelper {
|
|
|
565
565
|
|
|
566
566
|
// Init client
|
|
567
567
|
if (options.log) {
|
|
568
|
-
console.
|
|
568
|
+
console.info('Subscription query', JSON.stringify(query, null, 2));
|
|
569
569
|
}
|
|
570
570
|
const client = createClient({ url: this.subscriptionUrl, connectionParams, webSocketImpl: ws });
|
|
571
571
|
const messages: any[] = [];
|
|
572
572
|
let unsubscribe: () => void;
|
|
573
573
|
const onNext = (message) => {
|
|
574
574
|
if (options.log) {
|
|
575
|
-
console.
|
|
575
|
+
console.info('Subscription message', JSON.stringify(message, null, 2));
|
|
576
576
|
}
|
|
577
577
|
messages.push(message?.data?.[graphql.name]);
|
|
578
578
|
if (messages.length <= options.countOfSubscriptionMessages) {
|