@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.
Files changed (82) hide show
  1. package/dist/config.env.js +1 -1
  2. package/dist/config.env.js.map +1 -1
  3. package/dist/core/common/decorators/restricted.decorator.d.ts +1 -0
  4. package/dist/core/common/decorators/restricted.decorator.js +68 -57
  5. package/dist/core/common/decorators/restricted.decorator.js.map +1 -1
  6. package/dist/core/common/enums/role.enum.d.ts +2 -0
  7. package/dist/core/common/enums/role.enum.js +2 -0
  8. package/dist/core/common/enums/role.enum.js.map +1 -1
  9. package/dist/core/common/helpers/input.helper.d.ts +1 -0
  10. package/dist/core/common/helpers/input.helper.js +10 -2
  11. package/dist/core/common/helpers/input.helper.js.map +1 -1
  12. package/dist/core/common/helpers/model.helper.d.ts +6 -2
  13. package/dist/core/common/helpers/model.helper.js +14 -6
  14. package/dist/core/common/helpers/model.helper.js.map +1 -1
  15. package/dist/core/common/helpers/service.helper.d.ts +1 -0
  16. package/dist/core/common/helpers/service.helper.js +34 -9
  17. package/dist/core/common/helpers/service.helper.js.map +1 -1
  18. package/dist/core/common/services/core-cron-jobs.service.js +2 -2
  19. package/dist/core/common/services/core-cron-jobs.service.js.map +1 -1
  20. package/dist/core/common/services/module.service.js +3 -3
  21. package/dist/core/common/services/module.service.js.map +1 -1
  22. package/dist/core/common/types/plain-object.type.d.ts +3 -0
  23. package/dist/core/common/types/plain-object.type.js +3 -0
  24. package/dist/core/common/types/plain-object.type.js.map +1 -0
  25. package/dist/core/modules/auth/guards/roles.guard.js +4 -1
  26. package/dist/core/modules/auth/guards/roles.guard.js.map +1 -1
  27. package/dist/core/modules/auth/services/core-auth.service.js +3 -1
  28. package/dist/core/modules/auth/services/core-auth.service.js.map +1 -1
  29. package/dist/core/modules/file/core-file-info.model.d.ts +1 -1
  30. package/dist/core/modules/file/core-file-info.model.js +4 -0
  31. package/dist/core/modules/file/core-file-info.model.js.map +1 -1
  32. package/dist/core/modules/user/core-user.service.js +2 -0
  33. package/dist/core/modules/user/core-user.service.js.map +1 -1
  34. package/dist/index.d.ts +1 -0
  35. package/dist/index.js +1 -0
  36. package/dist/index.js.map +1 -1
  37. package/dist/server/common/services/cron-jobs.service.js +1 -1
  38. package/dist/server/common/services/cron-jobs.service.js.map +1 -1
  39. package/dist/server/modules/auth/auth.service.js +21 -4
  40. package/dist/server/modules/auth/auth.service.js.map +1 -1
  41. package/dist/server/modules/file/file.controller.js +1 -1
  42. package/dist/server/modules/file/file.controller.js.map +1 -1
  43. package/dist/server/modules/file/file.resolver.js +1 -0
  44. package/dist/server/modules/file/file.resolver.js.map +1 -1
  45. package/dist/server/modules/user/user.model.d.ts +3 -3
  46. package/dist/server/modules/user/user.model.js +5 -7
  47. package/dist/server/modules/user/user.model.js.map +1 -1
  48. package/dist/server/modules/user/user.module.js +2 -0
  49. package/dist/server/modules/user/user.module.js.map +1 -1
  50. package/dist/server/modules/user/user.resolver.js +6 -0
  51. package/dist/server/modules/user/user.resolver.js.map +1 -1
  52. package/dist/server/modules/user/user.service.js +1 -1
  53. package/dist/server/modules/user/user.service.js.map +1 -1
  54. package/dist/test/test.helper.js +4 -4
  55. package/dist/test/test.helper.js.map +1 -1
  56. package/dist/tsconfig.build.tsbuildinfo +1 -1
  57. package/package.json +3 -2
  58. package/src/config.env.ts +1 -1
  59. package/src/core/common/decorators/restricted.decorator.ts +95 -75
  60. package/src/core/common/enums/role.enum.ts +34 -6
  61. package/src/core/common/helpers/context.helper.ts +2 -2
  62. package/src/core/common/helpers/input.helper.ts +17 -0
  63. package/src/core/common/helpers/model.helper.ts +20 -6
  64. package/src/core/common/helpers/service.helper.ts +43 -11
  65. package/src/core/common/services/core-cron-jobs.service.ts +2 -2
  66. package/src/core/common/services/module.service.ts +5 -5
  67. package/src/core/common/types/plain-object.type.ts +5 -0
  68. package/src/core/common/types/remove-methods.type.ts +1 -0
  69. package/src/core/modules/auth/guards/roles.guard.ts +7 -2
  70. package/src/core/modules/auth/services/core-auth.service.ts +9 -1
  71. package/src/core/modules/file/core-file-info.model.ts +11 -1
  72. package/src/core/modules/user/core-user.service.ts +5 -0
  73. package/src/index.ts +1 -0
  74. package/src/server/common/services/cron-jobs.service.ts +1 -1
  75. package/src/server/modules/auth/auth.service.ts +13 -6
  76. package/src/server/modules/file/file.controller.ts +1 -1
  77. package/src/server/modules/file/file.resolver.ts +1 -0
  78. package/src/server/modules/user/user.model.ts +6 -5
  79. package/src/server/modules/user/user.module.ts +2 -0
  80. package/src/server/modules/user/user.resolver.ts +6 -0
  81. package/src/server/modules/user/user.service.ts +1 -1
  82. 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 (!user || !(await bcrypt.compare(password, user.password))) {
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
- _id: Types.ObjectId;
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.log('Hello :)');
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 (!user) {
38
- throw new UnauthorizedException();
39
- }
40
-
41
- // Check password
42
- if (!(await bcrypt.compare(input.password, user.password))) {
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.log('Saved file info', JSON.stringify({ files, fields }, null, 2));
45
+ console.info('Saved file info', JSON.stringify({ files, fields }, null, 2));
46
46
  }
47
47
  }
@@ -11,6 +11,7 @@ import { FileService } from './file.service';
11
11
  * File resolver
12
12
  */
13
13
  @Resolver()
14
+ @Roles(RoleEnum.ADMIN)
14
15
  export class FileResolver {
15
16
  /**
16
17
  * Integrate services
@@ -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, Types } from 'mongoose';
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: Types.ObjectId | string = undefined;
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: Types.ObjectId | string = undefined;
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
- return mapClasses(input, { createdBy: User, updatedBy: User }, this);
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.log(err);
101
+ console.error(err);
102
102
  }
103
103
  });
104
104
  }
@@ -91,7 +91,7 @@ export interface TestGraphQLOptions {
91
91
  countOfSubscriptionMessages?: number;
92
92
 
93
93
  /**
94
- * Print console logs
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.log(response);
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.log(requestConfig);
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.log('Response', JSON.stringify(response, null, 2));
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.log('Subscription query', JSON.stringify(query, null, 2));
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.log('Subscription message', JSON.stringify(message, null, 2));
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) {