Trần Viết Sơn commited on
Commit
fac3fcb
2 Parent(s): c8b1da2 5ec5d67

Merge pull request #15 from PBL6-team-CATS/fix/config-env

Browse files
backend/.gitignore CHANGED
@@ -54,3 +54,4 @@ pids
54
 
55
  # Diagnostic reports (https://nodejs.org/api/report.html)
56
  report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
 
 
54
 
55
  # Diagnostic reports (https://nodejs.org/api/report.html)
56
  report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
57
+ src/modules/authentication/constants.ts
backend/package-lock.json CHANGED
@@ -3993,6 +3993,7 @@
3993
  "version": "16.4.5",
3994
  "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
3995
  "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
 
3996
  "engines": {
3997
  "node": ">=12"
3998
  },
 
3993
  "version": "16.4.5",
3994
  "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
3995
  "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
3996
+ "license": "BSD-2-Clause",
3997
  "engines": {
3998
  "node": ">=12"
3999
  },
backend/src/entities/user.entity.ts CHANGED
@@ -10,12 +10,14 @@ import {
10
  } from 'typeorm';
11
  import { BranchEntity } from './branch.entity.js';
12
  import { RoleEntity } from './role.entity.js';
 
13
 
14
  @Entity('users')
15
  export class UserEntity extends BaseEntity {
16
  @PrimaryGeneratedColumn('uuid')
17
  id: string;
18
 
 
19
  @Column({ nullable: true })
20
  avatar: string;
21
 
@@ -31,21 +33,26 @@ export class UserEntity extends BaseEntity {
31
  @Column({ nullable: true })
32
  email: string;
33
 
 
34
  @Column({ nullable: true })
35
  role_id: number;
36
-
37
  @Column({ nullable: true })
38
  hash_password: string;
39
 
 
40
  @Column({ default: true })
41
  is_valid: boolean;
42
 
 
43
  @Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' })
44
  create_at: Date;
45
 
 
46
  @OneToMany(() => BranchEntity, (branch) => branch.owner)
47
  branches: Relation<BranchEntity>[];
48
 
 
49
  @ManyToOne(() => RoleEntity)
50
  @JoinColumn({ name: 'role_id'})
51
  role: RoleEntity;
 
10
  } from 'typeorm';
11
  import { BranchEntity } from './branch.entity.js';
12
  import { RoleEntity } from './role.entity.js';
13
+ import { IsOptional } from 'class-validator';
14
 
15
  @Entity('users')
16
  export class UserEntity extends BaseEntity {
17
  @PrimaryGeneratedColumn('uuid')
18
  id: string;
19
 
20
+ @IsOptional()
21
  @Column({ nullable: true })
22
  avatar: string;
23
 
 
33
  @Column({ nullable: true })
34
  email: string;
35
 
36
+ @IsOptional()
37
  @Column({ nullable: true })
38
  role_id: number;
39
+
40
  @Column({ nullable: true })
41
  hash_password: string;
42
 
43
+ @IsOptional()
44
  @Column({ default: true })
45
  is_valid: boolean;
46
 
47
+ @IsOptional()
48
  @Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' })
49
  create_at: Date;
50
 
51
+ @IsOptional()
52
  @OneToMany(() => BranchEntity, (branch) => branch.owner)
53
  branches: Relation<BranchEntity>[];
54
 
55
+ @IsOptional()
56
  @ManyToOne(() => RoleEntity)
57
  @JoinColumn({ name: 'role_id'})
58
  role: RoleEntity;
backend/src/modules/authentication/README.md ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Set up
2
+ Hiện tại cái **JWT_KEY** trong file **.env** vì lý do gì đó mà lúc đọc vào thì có lúc undefine, lúc ok nên t để cái JWT_KEY trong file constants.ts (ni t ignore cái file nớ rou)
3
+ * Vào src/modules/authentication tạo file **constants.ts** với nội dung sau:
4
+ ```javascript
5
+ export const jwtConstants = {
6
+ secret: '',
7
+ };
8
+ ```
9
+ Trong đó **secret** là một cái JWT key t sẽ cung cấp sau.
10
+
11
+ ## Signup
12
+ **Url:** *http://localhost:3000/authentication/signup* <br>
13
+ **Method:** POST <br>
14
+ **Input:**
15
+ * full_name: Tên của người dùng
16
+ * Email: Tài khoản email, hiện đang để optional do chưa xử lý cái unique
17
+ * Số điện thoại: Số điện thoại đang để check mã vùng ở Việt Nam
18
+ * password: Độ dài ít nhất 8 ký tự <br>
19
+ **Output:**
20
+ * access_token
21
+
22
+ ## Login
23
+ **Url:** *http://localhost:3000/authentication/login* <br>
24
+ **Method:** POST <br>
25
+ **Input:**
26
+ * username: hiện đang để là full_name, sau ni sẽ sửa lại database với code để email và số điện thoại là unique
27
+ * password: Độ dài ít nhất 8 ký tự
28
+ **Output:** <br>
29
+ * access_token
30
+
31
+
32
+
33
+
backend/src/modules/authentication/authentication.controller.ts CHANGED
@@ -11,7 +11,7 @@ import { AuthenticationGuard } from './authentication.guard.js';
11
  import { AuthenticationService } from './authentication.service.js';
12
  import { Public } from './authentication.decorator.js';
13
  import { SignInDto } from './dto/sign-in.dto.js';
14
-
15
  @Controller('authentication')
16
  export class AuthenticationController {
17
  constructor(private AuthenticationService: AuthenticationService) {}
@@ -23,6 +23,13 @@ export class AuthenticationController {
23
  return this.AuthenticationService.signIn(signInDto.username, signInDto.password);
24
  }
25
 
 
 
 
 
 
 
 
26
  // @UseGuards(AuthenticationGuard)
27
  @Get('profile')
28
  getProfile(@Request() req) {
 
11
  import { AuthenticationService } from './authentication.service.js';
12
  import { Public } from './authentication.decorator.js';
13
  import { SignInDto } from './dto/sign-in.dto.js';
14
+ import { SignUpDto } from './dto/sign-up.dto.js';
15
  @Controller('authentication')
16
  export class AuthenticationController {
17
  constructor(private AuthenticationService: AuthenticationService) {}
 
23
  return this.AuthenticationService.signIn(signInDto.username, signInDto.password);
24
  }
25
 
26
+ @Public()
27
+ @HttpCode(HttpStatus.OK)
28
+ @Post('signup')
29
+ signUp(@Body() signUpDto: SignUpDto) {
30
+ return this.AuthenticationService.signUp(signUpDto);
31
+ }
32
+
33
  // @UseGuards(AuthenticationGuard)
34
  @Get('profile')
35
  getProfile(@Request() req) {
backend/src/modules/authentication/authentication.guard.ts CHANGED
@@ -5,15 +5,17 @@ import {
5
  UnauthorizedException,
6
  } from '@nestjs/common';
7
  import { JwtService } from '@nestjs/jwt';
8
- import { jwtConstants } from './constants.js';
9
  import { Request } from 'express';
10
  import { Reflector } from '@nestjs/core';
11
  import { IS_PUBLIC_KEY } from './authentication.decorator.js';
 
 
12
  @Injectable()
13
  export class AuthenticationGuard implements CanActivate {
14
  constructor(
15
  private jwtService: JwtService,
16
  private reflector: Reflector,
 
17
  ) {}
18
 
19
  async canActivate(context: ExecutionContext): Promise<boolean> {
@@ -33,7 +35,7 @@ export class AuthenticationGuard implements CanActivate {
33
  }
34
  try {
35
  const payload = await this.jwtService.verifyAsync(token, {
36
- secret: jwtConstants.secret,
37
  });
38
  // 💡 We're assigning the payload to the request object here
39
  // so that we can access it in our route handlers
 
5
  UnauthorizedException,
6
  } from '@nestjs/common';
7
  import { JwtService } from '@nestjs/jwt';
 
8
  import { Request } from 'express';
9
  import { Reflector } from '@nestjs/core';
10
  import { IS_PUBLIC_KEY } from './authentication.decorator.js';
11
+ import { ConfigService } from '@nestjs/config';
12
+ import { buffer } from 'stream/consumers';
13
  @Injectable()
14
  export class AuthenticationGuard implements CanActivate {
15
  constructor(
16
  private jwtService: JwtService,
17
  private reflector: Reflector,
18
+ private configService: ConfigService
19
  ) {}
20
 
21
  async canActivate(context: ExecutionContext): Promise<boolean> {
 
35
  }
36
  try {
37
  const payload = await this.jwtService.verifyAsync(token, {
38
+ secret: this.configService.get<String>('JWT_KEY') as string,
39
  });
40
  // 💡 We're assigning the payload to the request object here
41
  // so that we can access it in our route handlers
backend/src/modules/authentication/authentication.module.ts CHANGED
@@ -3,16 +3,19 @@ import { AuthenticationService } from './authentication.service.js';
3
  import { UserModule } from '../user/user.module.js';
4
  import { JwtModule } from '@nestjs/jwt';
5
  import { AuthenticationController } from './authentication.controller.js';
6
- import { jwtConstants } from './constants.js';
7
  import { AuthenticationGuard } from './authentication.guard.js';
8
  import { APP_GUARD } from '@nestjs/core';
 
9
  @Module({
10
  imports: [
11
  UserModule,
12
- JwtModule.register({
13
- global: true,
14
- secret: jwtConstants.secret,
15
- signOptions: { expiresIn: '90s' },
 
 
 
16
  }),
17
  ],
18
  providers: [
 
3
  import { UserModule } from '../user/user.module.js';
4
  import { JwtModule } from '@nestjs/jwt';
5
  import { AuthenticationController } from './authentication.controller.js';
 
6
  import { AuthenticationGuard } from './authentication.guard.js';
7
  import { APP_GUARD } from '@nestjs/core';
8
+ import { ConfigModule, ConfigService } from '@nestjs/config';
9
  @Module({
10
  imports: [
11
  UserModule,
12
+ JwtModule.registerAsync({
13
+ imports: [ConfigModule], // Nhập ConfigModule để sử dụng ConfigService
14
+ useFactory: async (configService: ConfigService) => ({
15
+ secret: configService.get<string>('JWT_KEY'), // Lấy giá trị từ biến môi trường
16
+ signOptions: { expiresIn: '60s' }, // Thời gian hết hạn token
17
+ }),
18
+ inject: [ConfigService], // Inject ConfigService vào factory
19
  }),
20
  ],
21
  providers: [
backend/src/modules/authentication/authentication.service.ts CHANGED
@@ -2,6 +2,8 @@ import { Injectable, UnauthorizedException } from '@nestjs/common';
2
  import { UserService } from '../user/user.service.js';
3
  import * as bcrypt from 'bcrypt';
4
  import { JwtService } from '@nestjs/jwt';
 
 
5
  @Injectable()
6
  export class AuthenticationService {
7
  constructor(
@@ -22,4 +24,33 @@ export class AuthenticationService {
22
  access_token: await this.jwtService.signAsync(payload),
23
  };
24
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  }
 
2
  import { UserService } from '../user/user.service.js';
3
  import * as bcrypt from 'bcrypt';
4
  import { JwtService } from '@nestjs/jwt';
5
+ import { SignUpDto } from './dto/sign-up.dto.js';
6
+ import { UserEntity } from 'src/entities/user.entity.js';
7
  @Injectable()
8
  export class AuthenticationService {
9
  constructor(
 
24
  access_token: await this.jwtService.signAsync(payload),
25
  };
26
  }
27
+
28
+ async signUp(
29
+ signUpDto: SignUpDto,
30
+ ): Promise<{ access_token: string }> {
31
+ const {
32
+ full_name,
33
+ phone_number,
34
+ email,
35
+ password
36
+ } = signUpDto
37
+ const hash_password = await bcrypt.hash(password, 10)
38
+
39
+ const user = await this.usersService.create({
40
+ full_name: full_name,
41
+ phone_number: phone_number,
42
+ email: email,
43
+ password: hash_password
44
+ })
45
+ console.log(user)
46
+ await this.usersService.save(user);
47
+
48
+ const payload = { sub: user.id, username: user.id };
49
+ console.log("payload: ", payload);
50
+ const token = await this.jwtService.signAsync(payload)
51
+ console.log("token: ", token);
52
+ return {
53
+ access_token: token
54
+ };
55
+ }
56
  }
backend/src/modules/authentication/constants.ts DELETED
@@ -1,5 +0,0 @@
1
-
2
- export const jwtConstants = {
3
- secret: process.env.JWT_SECRET,
4
- };
5
-
 
 
 
 
 
 
backend/src/modules/authentication/dto/sign-in.dto.ts CHANGED
@@ -1,9 +1,10 @@
1
- import { IsString } from 'class-validator';
2
 
3
  export class SignInDto {
4
  @IsString()
5
  username: string;
6
 
7
  @IsString()
 
8
  password: string;
9
  }
 
1
+ import { IsString, MinLength } from 'class-validator';
2
 
3
  export class SignInDto {
4
  @IsString()
5
  username: string;
6
 
7
  @IsString()
8
+ @MinLength(8)
9
  password: string;
10
  }
backend/src/modules/authentication/dto/sign-up.dto.ts ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import {
2
+ IsString,
3
+ IsEmail,
4
+ IsMobilePhone,
5
+ IsOptional,
6
+ IsNumber,
7
+ MinLength
8
+ } from "class-validator";
9
+
10
+ export class SignUpDto{
11
+ @IsString()
12
+ full_name: string;
13
+
14
+ @IsMobilePhone('vi-VN')
15
+ phone_number: string;
16
+
17
+ @IsOptional()
18
+ @IsEmail()
19
+ email?: string;
20
+
21
+ @IsString()
22
+ @MinLength(8)
23
+ password: string;
24
+ }
backend/src/modules/user/user.service.ts CHANGED
@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
2
  import { InjectRepository } from '@nestjs/typeorm';
3
  import { Repository } from 'typeorm';
4
  import { UserEntity } from '../../entities/user.entity.js';
 
5
 
6
  export type User = any;
7
 
@@ -10,6 +11,19 @@ export class UserService {
10
  constructor() {}
11
 
12
  async findOne(username: string): Promise<UserEntity | undefined> {
13
- return UserEntity.findOne({ where: { id: username } });
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  }
15
  }
 
2
  import { InjectRepository } from '@nestjs/typeorm';
3
  import { Repository } from 'typeorm';
4
  import { UserEntity } from '../../entities/user.entity.js';
5
+ import { SignUpDto } from '../authentication/dto/sign-up.dto.js';
6
 
7
  export type User = any;
8
 
 
11
  constructor() {}
12
 
13
  async findOne(username: string): Promise<UserEntity | undefined> {
14
+ return UserEntity.findOne({ where: { full_name: username } });
15
+ }
16
+
17
+ async create(signUpDto: SignUpDto): Promise<UserEntity | undefined>{
18
+ return UserEntity.create({
19
+ full_name: signUpDto.full_name,
20
+ phone_number: signUpDto.phone_number,
21
+ email: signUpDto.email,
22
+ hash_password: signUpDto.password
23
+ })
24
+ }
25
+
26
+ async save(userEntity: UserEntity): Promise<UserEntity | undefined>{
27
+ return UserEntity.save(userEntity);
28
  }
29
  }