AnhLedger commited on
Commit
85b81c4
1 Parent(s): ddd07cb

feat: Add role

Browse files
backend/package-lock.json CHANGED
@@ -14,6 +14,7 @@
14
  "@nestjs/core": "^10.0.0",
15
  "@nestjs/jwt": "^10.2.0",
16
  "@nestjs/mapped-types": "*",
 
17
  "@nestjs/platform-express": "^10.0.0",
18
  "@nestjs/typeorm": "^10.0.2",
19
  "bcrypt": "^5.1.1",
@@ -23,6 +24,9 @@
23
  "mysql2": "^3.11.3",
24
  "nest-access-control": "^3.1.0",
25
  "nestjs-paginate": "^9.3.0",
 
 
 
26
  "pg": "^8.13.0",
27
  "reflect-metadata": "^0.2.0",
28
  "rxjs": "^7.8.1",
@@ -1820,6 +1824,16 @@
1820
  }
1821
  }
1822
  },
 
 
 
 
 
 
 
 
 
 
1823
  "node_modules/@nestjs/platform-express": {
1824
  "version": "10.4.3",
1825
  "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.3.tgz",
@@ -7555,6 +7569,53 @@
7555
  "node": ">= 0.8"
7556
  }
7557
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7558
  "node_modules/path-exists": {
7559
  "version": "4.0.0",
7560
  "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -7620,6 +7681,11 @@
7620
  "node": ">=8"
7621
  }
7622
  },
 
 
 
 
 
7623
  "node_modules/pg": {
7624
  "version": "8.13.0",
7625
  "resolved": "https://registry.npmjs.org/pg/-/pg-8.13.0.tgz",
 
14
  "@nestjs/core": "^10.0.0",
15
  "@nestjs/jwt": "^10.2.0",
16
  "@nestjs/mapped-types": "*",
17
+ "@nestjs/passport": "^10.0.3",
18
  "@nestjs/platform-express": "^10.0.0",
19
  "@nestjs/typeorm": "^10.0.2",
20
  "bcrypt": "^5.1.1",
 
24
  "mysql2": "^3.11.3",
25
  "nest-access-control": "^3.1.0",
26
  "nestjs-paginate": "^9.3.0",
27
+ "passport": "^0.7.0",
28
+ "passport-jwt": "^4.0.1",
29
+ "passport-local": "^1.0.0",
30
  "pg": "^8.13.0",
31
  "reflect-metadata": "^0.2.0",
32
  "rxjs": "^7.8.1",
 
1824
  }
1825
  }
1826
  },
1827
+ "node_modules/@nestjs/passport": {
1828
+ "version": "10.0.3",
1829
+ "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-10.0.3.tgz",
1830
+ "integrity": "sha512-znJ9Y4S8ZDVY+j4doWAJ8EuuVO7SkQN3yOBmzxbGaXbvcSwFDAdGJ+OMCg52NdzIO4tQoN4pYKx8W6M0ArfFRQ==",
1831
+ "license": "MIT",
1832
+ "peerDependencies": {
1833
+ "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0",
1834
+ "passport": "^0.4.0 || ^0.5.0 || ^0.6.0 || ^0.7.0"
1835
+ }
1836
+ },
1837
  "node_modules/@nestjs/platform-express": {
1838
  "version": "10.4.3",
1839
  "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.3.tgz",
 
7569
  "node": ">= 0.8"
7570
  }
7571
  },
7572
+ "node_modules/passport": {
7573
+ "version": "0.7.0",
7574
+ "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz",
7575
+ "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==",
7576
+ "license": "MIT",
7577
+ "dependencies": {
7578
+ "passport-strategy": "1.x.x",
7579
+ "pause": "0.0.1",
7580
+ "utils-merge": "^1.0.1"
7581
+ },
7582
+ "engines": {
7583
+ "node": ">= 0.4.0"
7584
+ },
7585
+ "funding": {
7586
+ "type": "github",
7587
+ "url": "https://github.com/sponsors/jaredhanson"
7588
+ }
7589
+ },
7590
+ "node_modules/passport-jwt": {
7591
+ "version": "4.0.1",
7592
+ "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz",
7593
+ "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==",
7594
+ "license": "MIT",
7595
+ "dependencies": {
7596
+ "jsonwebtoken": "^9.0.0",
7597
+ "passport-strategy": "^1.0.0"
7598
+ }
7599
+ },
7600
+ "node_modules/passport-local": {
7601
+ "version": "1.0.0",
7602
+ "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz",
7603
+ "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==",
7604
+ "dependencies": {
7605
+ "passport-strategy": "1.x.x"
7606
+ },
7607
+ "engines": {
7608
+ "node": ">= 0.4.0"
7609
+ }
7610
+ },
7611
+ "node_modules/passport-strategy": {
7612
+ "version": "1.0.0",
7613
+ "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
7614
+ "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==",
7615
+ "engines": {
7616
+ "node": ">= 0.4.0"
7617
+ }
7618
+ },
7619
  "node_modules/path-exists": {
7620
  "version": "4.0.0",
7621
  "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
 
7681
  "node": ">=8"
7682
  }
7683
  },
7684
+ "node_modules/pause": {
7685
+ "version": "0.0.1",
7686
+ "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
7687
+ "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg=="
7688
+ },
7689
  "node_modules/pg": {
7690
  "version": "8.13.0",
7691
  "resolved": "https://registry.npmjs.org/pg/-/pg-8.13.0.tgz",
backend/package.json CHANGED
@@ -30,6 +30,7 @@
30
  "@nestjs/core": "^10.0.0",
31
  "@nestjs/jwt": "^10.2.0",
32
  "@nestjs/mapped-types": "*",
 
33
  "@nestjs/platform-express": "^10.0.0",
34
  "@nestjs/typeorm": "^10.0.2",
35
  "bcrypt": "^5.1.1",
@@ -39,6 +40,9 @@
39
  "mysql2": "^3.11.3",
40
  "nest-access-control": "^3.1.0",
41
  "nestjs-paginate": "^9.3.0",
 
 
 
42
  "pg": "^8.13.0",
43
  "reflect-metadata": "^0.2.0",
44
  "rxjs": "^7.8.1",
 
30
  "@nestjs/core": "^10.0.0",
31
  "@nestjs/jwt": "^10.2.0",
32
  "@nestjs/mapped-types": "*",
33
+ "@nestjs/passport": "^10.0.3",
34
  "@nestjs/platform-express": "^10.0.0",
35
  "@nestjs/typeorm": "^10.0.2",
36
  "bcrypt": "^5.1.1",
 
40
  "mysql2": "^3.11.3",
41
  "nest-access-control": "^3.1.0",
42
  "nestjs-paginate": "^9.3.0",
43
+ "passport": "^0.7.0",
44
+ "passport-jwt": "^4.0.1",
45
+ "passport-local": "^1.0.0",
46
  "pg": "^8.13.0",
47
  "reflect-metadata": "^0.2.0",
48
  "rxjs": "^7.8.1",
backend/src/modules/authentication/authentication.controller.ts CHANGED
@@ -7,12 +7,14 @@ import {
7
  Post,
8
  Request,
9
  } from '@nestjs/common';
10
- 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
  import { SignUpDto } from './dto/sign-up.dto.js';
 
 
15
  @Controller('authentication')
 
16
  export class AuthenticationController {
17
  constructor(private AuthenticationService: AuthenticationService) {}
18
 
@@ -30,8 +32,8 @@ export class AuthenticationController {
30
  return this.AuthenticationService.signUp(signUpDto);
31
  }
32
 
33
- // @UseGuards(AuthenticationGuard)
34
  @Get('profile')
 
35
  getProfile(@Request() req) {
36
  const userId = req.user.sub;
37
  return this.AuthenticationService.getProfile(userId);
 
7
  Post,
8
  Request,
9
  } from '@nestjs/common';
 
10
  import { AuthenticationService } from './authentication.service.js';
11
  import { Public } from './authentication.decorator.js';
12
  import { SignInDto } from './dto/sign-in.dto.js';
13
  import { SignUpDto } from './dto/sign-up.dto.js';
14
+ import { Roles } from './authorization/roles.decorator.js';
15
+ import { Role } from './authorization/enums/role.enum.js';
16
  @Controller('authentication')
17
+
18
  export class AuthenticationController {
19
  constructor(private AuthenticationService: AuthenticationService) {}
20
 
 
32
  return this.AuthenticationService.signUp(signUpDto);
33
  }
34
 
 
35
  @Get('profile')
36
+ @Roles(Role.CUSTOMER)
37
  getProfile(@Request() req) {
38
  const userId = req.user.sub;
39
  return this.AuthenticationService.getProfile(userId);
backend/src/modules/authentication/authentication.module.ts CHANGED
@@ -6,6 +6,7 @@ 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,
@@ -23,6 +24,10 @@ import { ConfigModule, ConfigService } from '@nestjs/config';
23
  {
24
  provide: APP_GUARD,
25
  useClass: AuthenticationGuard,
 
 
 
 
26
  }
27
  ],
28
  controllers: [AuthenticationController],
 
6
  import { AuthenticationGuard } from './authentication.guard.js';
7
  import { APP_GUARD } from '@nestjs/core';
8
  import { ConfigModule, ConfigService } from '@nestjs/config';
9
+ import { RolesGuard } from './authorization/roles.guard.js';
10
  @Module({
11
  imports: [
12
  UserModule,
 
24
  {
25
  provide: APP_GUARD,
26
  useClass: AuthenticationGuard,
27
+ },
28
+ {
29
+ provide: APP_GUARD,
30
+ useClass: RolesGuard,
31
  }
32
  ],
33
  controllers: [AuthenticationController],
backend/src/modules/authentication/authentication.service.ts CHANGED
@@ -23,7 +23,7 @@ export class AuthenticationService {
23
  if (!user || (await !bcrypt.compare(pass, user.hash_password))) {
24
  throw new UnauthorizedException();
25
  }
26
- const payload = { sub: user.id, username: user.id };
27
  return {
28
  access_token: await this.jwtService.signAsync(payload),
29
  };
@@ -49,13 +49,10 @@ export class AuthenticationService {
49
  email: email,
50
  password: hash_password
51
  })
52
- console.log(user)
53
  await this.usersService.save(user);
54
 
55
- const payload = { sub: user.id, username: user.id };
56
- console.log("payload: ", payload);
57
  const token = await this.jwtService.signAsync(payload)
58
- console.log("token: ", token);
59
  return {
60
  access_token: token
61
  };
 
23
  if (!user || (await !bcrypt.compare(pass, user.hash_password))) {
24
  throw new UnauthorizedException();
25
  }
26
+ const payload = { sub: user.id, username: user.id, roles: user.role.role_name};
27
  return {
28
  access_token: await this.jwtService.signAsync(payload),
29
  };
 
49
  email: email,
50
  password: hash_password
51
  })
 
52
  await this.usersService.save(user);
53
 
54
+ const payload = { sub: user.id, username: user.id, role: user.role };
 
55
  const token = await this.jwtService.signAsync(payload)
 
56
  return {
57
  access_token: token
58
  };
backend/src/modules/authentication/{enums/index.ts → authorization/enums/role.enum.ts} RENAMED
File without changes
backend/src/modules/authentication/authorization/roles.decorator.ts ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ // src/decorators/roles.decorator.ts
2
+ import { SetMetadata } from '@nestjs/common';
3
+
4
+ export const ROLES_KEY = 'roles';
5
+ export const Roles = (...roles: string[]) => SetMetadata(ROLES_KEY, roles);
backend/src/modules/authentication/authorization/roles.guard.ts ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
3
+ import { Reflector } from '@nestjs/core';
4
+ import { Role } from 'nest-access-control';
5
+ import { ROLES_KEY } from './roles.decorator.js';
6
+
7
+ @Injectable()
8
+ export class RolesGuard implements CanActivate {
9
+ constructor(private reflector: Reflector) {}
10
+
11
+ canActivate(context: ExecutionContext): boolean {
12
+ const requiredRoles = this.reflector.getAllAndOverride<Role[]>(ROLES_KEY, [
13
+ context.getHandler(),
14
+ context.getClass(),
15
+ ]);
16
+ if (!requiredRoles) {
17
+ return true;
18
+ }
19
+ const { user } = context.switchToHttp().getRequest();
20
+ return requiredRoles.some((role) => user.roles.includes(role));
21
+ }
22
+ }
backend/src/modules/user/user.service.ts CHANGED
@@ -26,6 +26,9 @@ export class UserService {
26
  }
27
 
28
  async findOneByField(field: string, value: any): Promise<UserEntity | undefined> {
29
- return UserEntity.findOne({ where: { [field]: value } });
 
 
 
30
  }
31
  }
 
26
  }
27
 
28
  async findOneByField(field: string, value: any): Promise<UserEntity | undefined> {
29
+ return UserEntity.findOne({
30
+ where: { [field]: value },
31
+ relations: ['role']
32
+ });
33
  }
34
  }