From 09d0023e1d628093571f5815992d8ac13cb4ac11 Mon Sep 17 00:00:00 2001 From: Xantass Date: Fri, 18 Oct 2024 23:35:28 -0400 Subject: [PATCH 1/7] feat: add authentification with jwt and protected all route apart route login --- package-lock.json | 188 +++++++++++++++++- package.json | 5 + src/app.module.ts | 4 +- src/modules/details/details.controller.ts | 10 +- src/modules/food/food.controller.ts | 10 +- .../food_category/food_category.controller.ts | 10 +- .../ingredient/ingredient.controller.ts | 11 +- src/modules/login/jwt.strategy.ts | 35 ++++ src/modules/login/login.controller.ts | 16 +- src/modules/login/login.module.ts | 19 +- src/modules/login/login.service.ts | 52 ++++- src/modules/orders/orders.controller.ts | 10 +- .../permission/permission.controller.ts | 9 +- src/modules/pos/pos.controller.ts | 4 +- .../restaurants/restaurants.controller.ts | 9 +- src/modules/users/users.controller.ts | 9 +- src/modules/users/users.service.ts | 18 ++ src/shared/guards/jwt-auth.guard.ts | 80 ++++++++ 18 files changed, 463 insertions(+), 36 deletions(-) create mode 100644 src/modules/login/jwt.strategy.ts create mode 100644 src/shared/guards/jwt-auth.guard.ts diff --git a/package-lock.json b/package-lock.json index 9b8daff..92e5b1f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,10 +12,15 @@ "@nestjs/common": "^10.0.0", "@nestjs/config": "^3.2.3", "@nestjs/core": "^10.0.0", + "@nestjs/jwt": "^10.2.0", "@nestjs/mongoose": "^10.0.10", + "@nestjs/passport": "^10.0.3", "@nestjs/platform-express": "^10.0.0", "bcrypt": "^5.1.1", + "bcryptjs": "^2.4.3", "mongoose": "^8.7.0", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1", "reflect-metadata": "^0.2.0", "rxjs": "^7.8.1" }, @@ -1812,6 +1817,19 @@ } } }, + "node_modules/@nestjs/jwt": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-10.2.0.tgz", + "integrity": "sha512-x8cG90SURkEiLOehNaN2aRlotxT0KZESUliOPKKnjWiyJOcWurkF3w345WOX0P4MgFzUjGoZ1Sy0aZnxeihT0g==", + "license": "MIT", + "dependencies": { + "@types/jsonwebtoken": "9.0.5", + "jsonwebtoken": "9.0.2" + }, + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0" + } + }, "node_modules/@nestjs/mongoose": { "version": "10.0.10", "resolved": "https://registry.npmjs.org/@nestjs/mongoose/-/mongoose-10.0.10.tgz", @@ -1823,6 +1841,16 @@ "rxjs": "^7.0.0" } }, + "node_modules/@nestjs/passport": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-10.0.3.tgz", + "integrity": "sha512-znJ9Y4S8ZDVY+j4doWAJ8EuuVO7SkQN3yOBmzxbGaXbvcSwFDAdGJ+OMCg52NdzIO4tQoN4pYKx8W6M0ArfFRQ==", + "license": "MIT", + "peerDependencies": { + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "passport": "^0.4.0 || ^0.5.0 || ^0.6.0 || ^0.7.0" + } + }, "node_modules/@nestjs/platform-express": { "version": "10.4.4", "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.4.4.tgz", @@ -2166,6 +2194,15 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.5.tgz", + "integrity": "sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/methods": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", @@ -2182,7 +2219,6 @@ "version": "20.16.9", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.9.tgz", "integrity": "sha512-rkvIVJxsOfBejxK7I0FO5sa2WxFmJCzoDwcd88+fq/CUfynNywTo/1/T6hyFz22CyztsnLS9nVlHOnTI36RH5w==", - "dev": true, "dependencies": { "undici-types": "~6.19.2" } @@ -3042,6 +3078,12 @@ "node": ">= 10.0.0" } }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==", + "license": "MIT" + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -3221,6 +3263,12 @@ "ieee754": "^1.1.13" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -3910,6 +3958,15 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -6251,6 +6308,49 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "license": "MIT", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "license": "MIT", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/kareem": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", @@ -6334,6 +6434,42 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -6346,6 +6482,12 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -7060,6 +7202,42 @@ "node": ">= 0.8" } }, + "node_modules/passport": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.7.0.tgz", + "integrity": "sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==", + "license": "MIT", + "dependencies": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-jwt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==", + "license": "MIT", + "dependencies": { + "jsonwebtoken": "^9.0.0", + "passport-strategy": "^1.0.0" + } + }, + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -7128,6 +7306,11 @@ "node": ">=8" } }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, "node_modules/picocolors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", @@ -8706,8 +8889,7 @@ "node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" }, "node_modules/universalify": { "version": "2.0.1", diff --git a/package.json b/package.json index dddb32a..9bad1c1 100644 --- a/package.json +++ b/package.json @@ -23,10 +23,15 @@ "@nestjs/common": "^10.0.0", "@nestjs/config": "^3.2.3", "@nestjs/core": "^10.0.0", + "@nestjs/jwt": "^10.2.0", "@nestjs/mongoose": "^10.0.10", + "@nestjs/passport": "^10.0.3", "@nestjs/platform-express": "^10.0.0", "bcrypt": "^5.1.1", + "bcryptjs": "^2.4.3", "mongoose": "^8.7.0", + "passport": "^0.7.0", + "passport-jwt": "^4.0.1", "reflect-metadata": "^0.2.0", "rxjs": "^7.8.1" }, diff --git a/src/app.module.ts b/src/app.module.ts index 65db7af..90a65da 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -20,9 +20,11 @@ import { PermissionModule } from './modules/permission/permission.module'; import { PosModule } from './modules/pos/pos.module'; import { RestaurantsModule } from './modules/restaurants/restaurants.module'; import { UsersModule } from './modules/users/users.module'; +import { PassportModule } from '@nestjs/passport'; @Module({ imports: [ + PassportModule.register({ defaultStrategy : 'jwt' }), /**< Register new configuration authentification */ ConfigModule.forRoot(), /**< Loads environment configuration */ DetailsModule, /**< Manages restaurant details */ FoodModule, /**< Handles food-related functionality */ @@ -33,7 +35,7 @@ import { UsersModule } from './modules/users/users.module'; PermissionModule, /**< Manages permissions in the system */ PosModule, /**< Handles point-of-sale functionality */ RestaurantsModule, /**< Manages restaurant information */ - UsersModule, /**< Manages users and their information */ + UsersModule, /**< Manages users and their information */ ], controllers: [AppController], /**< Application controller */ providers: [AppService], /**< Core application service */ diff --git a/src/modules/details/details.controller.ts b/src/modules/details/details.controller.ts index 07a656b..900d2d9 100644 --- a/src/modules/details/details.controller.ts +++ b/src/modules/details/details.controller.ts @@ -17,10 +17,11 @@ import { Delete, NotFoundException, BadRequestException, - HttpException, - HttpStatus, + InternalServerErrorException, + UseGuards, } from '@nestjs/common'; import { DetailsService } from './details.service'; +import { JwtAuthGuard } from 'src/shared/guards/jwt-auth.guard'; @Controller('api/:idRestaurant/details') export class DetailsController { @@ -35,6 +36,7 @@ export class DetailsController { * @throws {HttpException} - Throws if there is an error during retrieval. * @async */ + @UseGuards(JwtAuthGuard) @Get() async getAllDetail(@Param('idRestaurant') idRestaurant: number) { try { @@ -61,6 +63,7 @@ export class DetailsController { * @throws {HttpException} - Throws if there is an error during retrieval. * @async */ + @UseGuards(JwtAuthGuard) @Get(':id') async getOneDetail( @Param('idRestaurant') idRestaurant: number, @@ -93,6 +96,7 @@ export class DetailsController { * @throws {HttpException} - Throws if there is an error during creation. * @async */ + @UseGuards(JwtAuthGuard) @Post() async createDetail( @Param('idRestaurant') idRestaurant: number, @@ -130,6 +134,7 @@ export class DetailsController { * @throws {HttpException} - Throws if there is an error during the update. * @async */ + @UseGuards(JwtAuthGuard) @Put(':id') async updateOneDetail( @Param('idRestaurant') idRestaurant: number, @@ -167,6 +172,7 @@ export class DetailsController { * @throws {HttpException} - Throws if there is an error during deletion. * @async */ + @UseGuards(JwtAuthGuard) @Delete(':id') async deleteOneDetail( @Param('idRestaurant') idRestaurant: number, diff --git a/src/modules/food/food.controller.ts b/src/modules/food/food.controller.ts index d153514..45ef234 100644 --- a/src/modules/food/food.controller.ts +++ b/src/modules/food/food.controller.ts @@ -17,10 +17,11 @@ import { Delete, NotFoundException, BadRequestException, - HttpException, - HttpStatus, + InternalServerErrorException, + UseGuards, } from '@nestjs/common'; import { FoodService } from './food.service'; +import { JwtAuthGuard } from 'src/shared/guards/jwt-auth.guard'; @Controller('api/:idRestaurant/food') export class FoodController { @@ -35,6 +36,7 @@ export class FoodController { * @throws {HttpException} if there is an error during the operation. * @async */ + @UseGuards(JwtAuthGuard) @Get() async getAllFood(@Param('idRestaurant') idRestaurant: number): Promise { try { @@ -61,6 +63,7 @@ export class FoodController { * @throws {HttpException} if there is an error during the operation. * @async */ + @UseGuards(JwtAuthGuard) @Get(':id') async getOneFood( @Param('idRestaurant') idRestaurant: number, @@ -93,6 +96,7 @@ export class FoodController { * @throws {HttpException} if there is an error during the operation. * @async */ + @UseGuards(JwtAuthGuard) @Post() async createFood( @Param('idRestaurant') idRestaurant: number, @@ -130,6 +134,7 @@ export class FoodController { * @throws {HttpException} if there is an error during the operation. * @async */ + @UseGuards(JwtAuthGuard) @Put(':id') async updateOneFood( @Param('idRestaurant') idRestaurant: number, @@ -167,6 +172,7 @@ export class FoodController { * @throws {HttpException} if there is an error during the operation. * @async */ + @UseGuards(JwtAuthGuard) @Delete(':id') async deleteOneFood( @Param('idRestaurant') idRestaurant: number, diff --git a/src/modules/food_category/food_category.controller.ts b/src/modules/food_category/food_category.controller.ts index 22b9c81..b3ec1f3 100644 --- a/src/modules/food_category/food_category.controller.ts +++ b/src/modules/food_category/food_category.controller.ts @@ -8,10 +8,11 @@ import { Delete, NotFoundException, BadRequestException, - HttpException, - HttpStatus, + InternalServerErrorException, + UseGuards, } from '@nestjs/common'; import { FoodCategoryService } from './food_category.service'; +import { JwtAuthGuard } from 'src/shared/guards/jwt-auth.guard'; /** * Controller for managing food categories in a restaurant. @@ -32,6 +33,7 @@ export class FoodCategoryController { * @throws {NotFoundException} If no food categories are found. * @throws {HttpException} If there's an error fetching the categories. */ + @UseGuards(JwtAuthGuard) @Get() async getAllFoodCategory(@Param('idRestaurant') idRestaurant: number) { try { @@ -59,6 +61,7 @@ export class FoodCategoryController { * @throws {NotFoundException} If the food category with the specified ID is not found. * @throws {HttpException} If there's an error fetching the category. */ + @UseGuards(JwtAuthGuard) @Get(':id') async getOneFoodCategory( @Param('idRestaurant') idRestaurant: number, @@ -90,6 +93,7 @@ export class FoodCategoryController { * @throws {BadRequestException} If there's an error creating the food category. * @throws {HttpException} If there's an error during the creation process. */ + @UseGuards(JwtAuthGuard) @Post() async createFoodCategory( @Param('idRestaurant') idRestaurant: number, @@ -126,6 +130,7 @@ export class FoodCategoryController { * @throws {BadRequestException} If no changes were made to the food category. * @throws {HttpException} If there's an error updating the category. */ + @UseGuards(JwtAuthGuard) @Put(':id') async updateOneFoodCategory( @Param('idRestaurant') idRestaurant: number, @@ -162,6 +167,7 @@ export class FoodCategoryController { * @throws {NotFoundException} If the food category with the specified ID is not found. * @throws {HttpException} If there's an error deleting the category. */ + @UseGuards(JwtAuthGuard) @Delete(':id') async deleteOneFoodCategory( @Param('idRestaurant') idRestaurant: number, diff --git a/src/modules/ingredient/ingredient.controller.ts b/src/modules/ingredient/ingredient.controller.ts index 9a1cb13..3ff828c 100644 --- a/src/modules/ingredient/ingredient.controller.ts +++ b/src/modules/ingredient/ingredient.controller.ts @@ -9,11 +9,11 @@ import { NotFoundException, BadRequestException, InternalServerErrorException, - HttpException, - HttpStatus, + UseGuards, } from '@nestjs/common'; import { IngredientService } from './ingredient.service'; import { Request } from 'express'; +import { JwtAuthGuard } from 'src/shared/guards/jwt-auth.guard'; /** * Controller for managing ingredients within a restaurant. @@ -23,7 +23,7 @@ import { Request } from 'express'; */ @Controller('api/:idRestaurant/ingredient') export class IngredientController { - constructor(private readonly ingredientService: IngredientService) {} + constructor(private readonly ingredientService: IngredientService) { } /** * Retrieves all ingredients for a specific restaurant. @@ -34,6 +34,7 @@ export class IngredientController { * @throws {HttpException} - Throws if there is an error during retrieval. * @async */ + @UseGuards(JwtAuthGuard) @Get() async getAllIngredient(@Param('idRestaurant') idRestaurant: number) { try { @@ -62,6 +63,7 @@ export class IngredientController { * @throws {HttpException} - Throws if there is an error during retrieval. * @async */ + @UseGuards(JwtAuthGuard) @Get(':id') async getOneIngredient( @Param('idRestaurant') idRestaurant: number, @@ -94,6 +96,7 @@ export class IngredientController { * @throws {HttpException} - Throws if there is an error during creation. * @async */ + @UseGuards(JwtAuthGuard) @Post() async createIngredient( @Param('idRestaurant') idRestaurant: number, @@ -131,6 +134,7 @@ export class IngredientController { * @throws {HttpException} - Throws if there is an error during the update. * @async */ + @UseGuards(JwtAuthGuard) @Put(':id') async updateOneIngredient( @Param('idRestaurant') idRestaurant: number, @@ -168,6 +172,7 @@ export class IngredientController { * @throws {HttpException} - Throws if there is an error during deletion. * @async */ + @UseGuards(JwtAuthGuard) @Delete(':id') async deleteOneIngredient( @Param('idRestaurant') idRestaurant: number, diff --git a/src/modules/login/jwt.strategy.ts b/src/modules/login/jwt.strategy.ts new file mode 100644 index 0000000..88016a5 --- /dev/null +++ b/src/modules/login/jwt.strategy.ts @@ -0,0 +1,35 @@ +import { Injectable } from '@nestjs/common'; +import { PassportStrategy } from '@nestjs/passport'; +import { ExtractJwt, Strategy } from 'passport-jwt'; + +@Injectable() +/** + * @class JwtStrategy + * @brief Strategy class that handles JWT validation for authentication. + * + * This class is used to define the strategy for validating JWT tokens using Passport.js in a NestJS application. + */ +export class JwtStrategy extends PassportStrategy(Strategy) { + + constructor() { + super({ + jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), /**< @brief Extracts the token from the Authorization header */ + ignoreExpiration: false, /**< @brief Expired tokens are not allowed */ + secretOrKey: 'secret', /**< @brief Must match the secret defined in `JwtModule.register` */ + }); + } + + /** + * @brief Validates the JWT payload and returns user information. + * + * @param payload The payload decoded from the JWT token. + * @return An object containing the user ID and username extracted from the payload. + * + * This method is automatically called by Passport to validate the token and attach user information + * to the request object. + */ + async validate(payload: any) { + return { userId: payload.sub, username: payload.username }; /**< @brief Returns the user ID and username from the token payload */ + } +} + diff --git a/src/modules/login/login.controller.ts b/src/modules/login/login.controller.ts index 7eb6768..85b5a5f 100644 --- a/src/modules/login/login.controller.ts +++ b/src/modules/login/login.controller.ts @@ -4,25 +4,31 @@ import { LoginService } from './login.service'; // Controller for handling login requests @Controller('api/login') export class LoginController { - constructor(private readonly loginService: LoginService) {} + constructor(private readonly loginService: LoginService) { + } /** * Authenticates a user based on the provided credentials. * - * @param {LoginDto} loginData - The login credentials containing username and password. + * @param {Request} request - The login credentials containing username, password and idRestaurant. * @returns {Promise} The authentication result. * @throws {UnauthorizedException} If authentication fails. */ @Post() - async checkOneInfoUser(@Req() request: Request) { + async login(@Req() request: Request) { try { // Attempt to authenticate the user using the service - const result = await this.loginService.authenticateUser( + const auth = await this.loginService.authenticateUser( + Number(request.body['idRestaurant']), request.body['username'], request.body['password'], ); - return result; // Return the authentication result + console.log(auth); + const token = await this.loginService.login(auth); + console.log(token) + return token; // Return the authentication result } catch (error) { + console.log(error) // Handle authentication failure throw new UnauthorizedException(error.message); } diff --git a/src/modules/login/login.module.ts b/src/modules/login/login.module.ts index e472410..8cfee79 100644 --- a/src/modules/login/login.module.ts +++ b/src/modules/login/login.module.ts @@ -1,6 +1,9 @@ import { Module } from '@nestjs/common'; import { LoginController } from './login.controller'; import { LoginService } from './login.service'; +import { JwtModule, JwtService } from '@nestjs/jwt'; +import { JwtStrategy } from './jwt.strategy'; +import { PassportModule } from '@nestjs/passport'; /** * Module for managing login items in the restaurant. @@ -12,12 +15,24 @@ import { LoginService } from './login.service'; * @module LoginModule */ @Module({ - imports: [], + imports: [ + PassportModule.register( { defaultStrategy: 'jwt' } ), + JwtModule.register({ + global: true, + signOptions: { expiresIn: '1h' }, // life of the token + secret: "secret" + }), + ], controllers: [ LoginController /**< The controller responsible for handling HTTP requests related to login items */ ], providers: [ - LoginService /**< The service that contains the business logic for managing login items */ + LoginService, /**< The service that contains the business logic for managing login items */ + JwtStrategy ], + exports: [ + JwtModule, + PassportModule + ] }) export class LoginModule {} diff --git a/src/modules/login/login.service.ts b/src/modules/login/login.service.ts index d4eae6e..6beadaa 100644 --- a/src/modules/login/login.service.ts +++ b/src/modules/login/login.service.ts @@ -1,23 +1,44 @@ import { Injectable, UnauthorizedException } from '@nestjs/common'; +import { JwtService } from '@nestjs/jwt'; import { DB } from 'src/db/db'; import * as bcrypt from 'bcrypt'; @Injectable() +/** + * @class LoginService + * @brief Service that handles user authentication and JWT generation. + * + * The LoginService is responsible for verifying user credentials (username and password) + * and generating JWT tokens upon successful authentication. + */ export class LoginService extends DB { + constructor(private jwtService: JwtService) { + super() + } + /** - * Authenticates a user by verifying their username and password. + * @brief Authenticates a user by verifying their username and password. * - * @param {string} username - The username of the user attempting to log in. - * @param {string} password - The password provided by the user. + * @param idRestaurant The restaurant ID where the user is working. + * @param username The username of the user attempting to log in. + * @param password The password provided by the user. * @returns {Promise} A success message if authentication is successful. * @throws {UnauthorizedException} If the user is not found or the password is incorrect. + * + * This method retrieves the user from the database, hashes the provided password, + * and compares it with the stored hashed password. If the credentials match, + * the user is authenticated. */ - async authenticateUser(username: string, password: string): Promise { + async authenticateUser(idRestaurant: number, username: string, password: string): Promise { const db = this.getDbConnection(); // Retrieve the user from the database based on the username - const user = await db.collection('user').findOne({ username }); + const user = await db.collection('restaurant').findOne( + { id: idRestaurant }, + { projection: { _id: 0, users: { $elemMatch: { username: username } } } }, + ); + console.log(user.users[0].password) if (!user) { // Throw an error if the user does not exist throw new UnauthorizedException('USER NOT FOUND'); @@ -27,11 +48,28 @@ export class LoginService extends DB { password = bcrypt.hashSync(password, process.env.SALT_HASH); // Compare the hashed password with the stored password - if (password !== user.password) { + if (password !== user.users[0].password) { // Throw an error if the password does not match throw new UnauthorizedException('WRONG PASSWORD'); } - return 'OK'; // Return success message if authentication is successful + return user.users[0]; // Return the authenticated user if successful + } + + /** + * @brief Logs in a user by generating a JWT token. + * + * @param user The user object containing username and ID. + * @returns {Promise} An object containing the generated access token. + * + * This method generates a JWT token using the user's username and ID and + * returns it as part of the login process. + */ + async login(user: any) { + const payload = { username: user.username, sub: user.id }; + console.log(payload) + return { + access_token: await this.jwtService.signAsync(payload), // Generates the JWT token + }; } } diff --git a/src/modules/orders/orders.controller.ts b/src/modules/orders/orders.controller.ts index 69c3d9b..7024988 100644 --- a/src/modules/orders/orders.controller.ts +++ b/src/modules/orders/orders.controller.ts @@ -10,10 +10,10 @@ import { NotFoundException, BadRequestException, InternalServerErrorException, - HttpException, - HttpStatus, + UseGuards, } from '@nestjs/common'; import { OrdersService } from './orders.service'; +import { JwtAuthGuard } from 'src/shared/guards/jwt-auth.guard'; @Controller('api/:idRestaurant/orders') export class OrdersController { @@ -40,6 +40,7 @@ export class OrdersController { * @returns {Promise} The list of orders. * @throws {InternalServerErrorException} If an error occurs while fetching orders. */ + @UseGuards(JwtAuthGuard) @Get() async getOrders( @Query('status') status: string, @@ -70,6 +71,7 @@ export class OrdersController { * @throws {NotFoundException} If the order is not found. * @throws {InternalServerErrorException} If an error occurs while fetching the order. */ + @UseGuards(JwtAuthGuard) @Get(':id') async getOneOrder(@Query('forKDS') forKDS: string, @Param('id') id: number, @Param('idRestaurant') idRestaurant: number) { try { @@ -134,6 +136,7 @@ export class OrdersController { * @throws {BadRequestException} If the order creation fails. * @throws {InternalServerErrorException} If an error occurs while creating the order. */ + @UseGuards(JwtAuthGuard) @Post() async createOrder(@Req() request: Request, @Param('idRestaurant') idRestaurant: number) { try { @@ -164,6 +167,7 @@ export class OrdersController { * @throws {BadRequestException} If no changes were made to the order. * @throws {InternalServerErrorException} If an error occurs while updating the order. */ + @UseGuards(JwtAuthGuard) @Put(':id') async updateOneOrder(@Param('id') id: number, @Req() request: Request, @Param('idRestaurant') idRestaurant: number) { try { @@ -196,6 +200,7 @@ export class OrdersController { * @throws {NotFoundException} If the order is not found. * @throws {InternalServerErrorException} If an error occurs while deleting the order. */ + @UseGuards(JwtAuthGuard) @Delete(':id') async deleteOneOrder(@Param('id') id: number, @Param('idRestaurant') idRestaurant: number) { try { @@ -221,6 +226,7 @@ export class OrdersController { * @throws {NotFoundException} If the order is not found. * @throws {InternalServerErrorException} If an error occurs while updating the order status. */ + @UseGuards(JwtAuthGuard) @Put('status/:id') async ChangeStatusFoodOrdered(@Param('idRestaurant') idRestaurant: number, @Param('id') id: number) { try { diff --git a/src/modules/permission/permission.controller.ts b/src/modules/permission/permission.controller.ts index 80ecd41..3b3a445 100644 --- a/src/modules/permission/permission.controller.ts +++ b/src/modules/permission/permission.controller.ts @@ -9,10 +9,10 @@ import { NotFoundException, BadRequestException, InternalServerErrorException, - HttpException, - HttpStatus, + UseGuards, } from '@nestjs/common'; import { PermissionService } from './permission.service'; +import { JwtAuthGuard } from 'src/shared/guards/jwt-auth.guard'; /** * Controller for managing permissions. @@ -33,6 +33,7 @@ export class PermissionController { * @throws {HttpException} - Throws if there is an error during retrieval. * @async */ + @UseGuards(JwtAuthGuard) @Get() async getAllPermission(@Param('idRestaurant') idRestaurant: number) { try { @@ -59,6 +60,7 @@ export class PermissionController { * @throws {HttpException} - Throws if there is an error during retrieval. * @async */ + @UseGuards(JwtAuthGuard) @Get(':id') async getOnePermission( @Param('idRestaurant') idRestaurant: number, @@ -91,6 +93,7 @@ export class PermissionController { * @throws {HttpException} - Throws if there is an error during creation. * @async */ + @UseGuards(JwtAuthGuard) @Post() async createPermission( @Param('idRestaurant') idRestaurant: number, @@ -128,6 +131,7 @@ export class PermissionController { * @throws {HttpException} - Throws if there is an error during the update. * @async */ + @UseGuards(JwtAuthGuard) @Put(':id') async updateOnePermission( @Param('idRestaurant') idRestaurant: number, @@ -165,6 +169,7 @@ export class PermissionController { * @throws {HttpException} - Throws if there is an error during deletion. * @async */ + @UseGuards(JwtAuthGuard) @Delete(':id') async deleteOnePermission( @Param('idRestaurant') idRestaurant: number, diff --git a/src/modules/pos/pos.controller.ts b/src/modules/pos/pos.controller.ts index f0d4216..5e1bd9c 100644 --- a/src/modules/pos/pos.controller.ts +++ b/src/modules/pos/pos.controller.ts @@ -1,5 +1,6 @@ -import { Controller, Get, Param, NotFoundException, InternalServerErrorException, HttpException, HttpStatus } from '@nestjs/common'; +import { Controller, Get, Param, NotFoundException, InternalServerErrorException, UseGuards } from '@nestjs/common'; import { PosService } from './pos.service'; +import { JwtAuthGuard } from 'src/shared/guards/jwt-auth.guard'; @Controller('api/pos') export class PosController { @@ -14,6 +15,7 @@ export class PosController { * @throws {HttpException} - Throws if there is an error during deletion. * @async */ + @UseGuards(JwtAuthGuard) @Get(':id') async getAllDataPOS(@Param('id') id: number) { try { diff --git a/src/modules/restaurants/restaurants.controller.ts b/src/modules/restaurants/restaurants.controller.ts index 6487d5b..8108937 100644 --- a/src/modules/restaurants/restaurants.controller.ts +++ b/src/modules/restaurants/restaurants.controller.ts @@ -9,11 +9,11 @@ import { NotFoundException, BadRequestException, InternalServerErrorException, - HttpException, - HttpStatus, + UseGuards, } from '@nestjs/common'; import { RestaurantsService } from './restaurants.service'; import { Request } from 'express'; // Ensure to import Request from express +import { JwtAuthGuard } from 'src/shared/guards/jwt-auth.guard'; @Controller('api/restaurants') export class RestaurantsController { @@ -24,6 +24,7 @@ export class RestaurantsController { * * @returns {Promise} An array of restaurants. */ + @UseGuards(JwtAuthGuard) @Get() async getAllRestaurants() { try { @@ -46,6 +47,7 @@ export class RestaurantsController { * @param {number} id - The ID of the restaurant. * @returns {Promise} The restaurant if found. */ + @UseGuards(JwtAuthGuard) @Get(':id') async getOneRestaurant(@Param('id') id: number) { try { @@ -68,6 +70,7 @@ export class RestaurantsController { * @param {Request} request - The incoming request containing the restaurant data. * @returns {Promise} The created restaurant. */ + @UseGuards(JwtAuthGuard) @Post() async createRestaurant(@Req() request: Request) { try { @@ -93,6 +96,7 @@ export class RestaurantsController { * @param {Request} request - The incoming request containing the updated restaurant data. * @returns {Promise} A success message. */ + @UseGuards(JwtAuthGuard) @Put(':id') async updateOneRestaurant(@Param('id') id: number, @Req() request: Request) { try { @@ -121,6 +125,7 @@ export class RestaurantsController { * @param {number} id - The ID of the restaurant to delete. * @returns {Promise} A success message. */ + @UseGuards(JwtAuthGuard) @Delete(':id') async deleteOneRestaurant(@Param('id') id: number) { try { diff --git a/src/modules/users/users.controller.ts b/src/modules/users/users.controller.ts index ad9f9f9..c43cd9f 100644 --- a/src/modules/users/users.controller.ts +++ b/src/modules/users/users.controller.ts @@ -9,11 +9,11 @@ import { NotFoundException, BadRequestException, InternalServerErrorException, - HttpException, - HttpStatus, + UseGuards, } from '@nestjs/common'; import { UsersService } from './users.service'; import { Request } from 'express'; // Ensure to import Request from express +import { JwtAuthGuard } from 'src/shared/guards/jwt-auth.guard'; @Controller('api/:idRestaurant/users') export class UsersController { @@ -28,6 +28,7 @@ export class UsersController { * @throws {HttpException} - Throws if there is an error during retrieval. * @async */ + @UseGuards(JwtAuthGuard) @Get() async getAllUser(@Param('idRestaurant') idRestaurant: number) { try { @@ -54,6 +55,7 @@ export class UsersController { * @throws {HttpException} - Throws if there is an error during retrieval. * @async */ + @UseGuards(JwtAuthGuard) @Get(':id') async getOneUser(@Param('idRestaurant') idRestaurant: number, @Param('id') id: number) { try { @@ -80,6 +82,7 @@ export class UsersController { * @throws {HttpException} - Throws if there is an error during creation. * @async */ + @UseGuards(JwtAuthGuard) @Post() async createUser(@Param('idRestaurant') idRestaurant: number, @Req() request: Request) { try { @@ -108,6 +111,7 @@ export class UsersController { * @throws {HttpException} - Throws if there is an error during the update. * @async */ + @UseGuards(JwtAuthGuard) @Put(':id') async updateOneUser( @Param('idRestaurant') idRestaurant: number, @@ -145,6 +149,7 @@ export class UsersController { * @throws {HttpException} - Throws if there is an error during deletion. * @async */ + @UseGuards(JwtAuthGuard) @Delete(':id') async deleteOneUser(@Param('idRestaurant') idRestaurant: number, @Param('id') id: number) { try { diff --git a/src/modules/users/users.service.ts b/src/modules/users/users.service.ts index cc49254..4ca43ac 100644 --- a/src/modules/users/users.service.ts +++ b/src/modules/users/users.service.ts @@ -40,6 +40,24 @@ export class UsersService extends DB { return restaurant?.users[0]; // Return the matched user object or undefined } + /** + * Retrieves a single user by their username. + * + * @param {number} idRestaurant - The ID of the restaurant. + * @param {string} username - The username of the user. + * @returns {Promise>} The user object if found. + */ + async findOne(idRestaurant: number, username: string): Promise> { + const db = this.getDbConnection(); + + const restaurant = await db.collection('restaurant').findOne( + { id: idRestaurant }, + { projection: { _id: 0, users: { $elemMatch: { username: username } } } }, + ); + + return restaurant?.users[0]; // Return the matched user object or undefined + } + /** * Creates a new user for a specific restaurant. * diff --git a/src/shared/guards/jwt-auth.guard.ts b/src/shared/guards/jwt-auth.guard.ts new file mode 100644 index 0000000..58e3a7a --- /dev/null +++ b/src/shared/guards/jwt-auth.guard.ts @@ -0,0 +1,80 @@ +import { + CanActivate, + ExecutionContext, + Injectable, + UnauthorizedException, +} from '@nestjs/common'; +import { JwtService } from '@nestjs/jwt'; +import { Request } from 'express'; + +@Injectable() +/** + * @class JwtAuthGuard + * @brief A guard that handles JWT authentication for incoming HTTP requests. + * + * This guard checks if the request contains a valid JWT token in the Authorization header, + * verifies it, and assigns the decoded token (payload) to the request object. + */ +export class JwtAuthGuard implements CanActivate { + + constructor(private jwtService: JwtService) { } + + /** + * @brief Determines whether the request can proceed based on the presence and validity of the JWT token. + * + * @param context ExecutionContext object, which provides details of the current request. + * @return Promise Returns true if the request is allowed to proceed, false otherwise. + * + * @throws UnauthorizedException If no token is found or if the token verification fails. + */ + async canActivate(context: ExecutionContext): Promise { + // Extracting the request object from the execution context + const request = context.switchToHttp().getRequest(); + + // Extracting the token from the authorization header + const token = this.extractTokenFromHeader(request); + + // If no token is found, throw an unauthorized exception + if (!token) { + throw new UnauthorizedException(); + } + + try { + // Verifying the JWT token with the secret key + const payload = await this.jwtService.verifyAsync( + token, + { + secret: "secret" // You should replace "secret" with an actual environment variable for security reasons + } + ); + + /** + * @brief Attaching the decoded token (payload) to the request object. + * This makes the user information available to route handlers. + */ + request['user'] = payload; + } catch { + // If the token verification fails, throw an unauthorized exception + throw new UnauthorizedException(); + } + + // If everything is valid, return true to allow the request to proceed + return true; + } + + /** + * @brief Extracts the JWT token from the 'Authorization' header. + * + * @param request The incoming HTTP request. + * @return string | undefined Returns the token if present and properly formatted, otherwise undefined. + * + * This method expects the 'Authorization' header to follow the format: "Bearer ". + */ + private extractTokenFromHeader(request: Request): string | undefined { + // Splitting the 'Authorization' header by space, expecting "Bearer " + const [type, token] = request.headers.authorization?.split(' ') ?? []; + + // Returning the token if the type is 'Bearer', otherwise undefined + return type === 'Bearer' ? token : undefined; + } +} From c87f477f48790f664ffcbb9e11ee6cebc0acc621 Mon Sep 17 00:00:00 2001 From: Xantass Date: Fri, 18 Oct 2024 23:56:53 -0400 Subject: [PATCH 2/7] fix: import httpException and httpStatus in all controller file --- src/modules/details/details.controller.ts | 3 ++- src/modules/food/food.controller.ts | 4 ++-- src/modules/food_category/food_category.controller.ts | 3 ++- src/modules/ingredient/ingredient.controller.ts | 3 ++- src/modules/orders/orders.controller.ts | 3 ++- src/modules/permission/permission.controller.ts | 3 ++- src/modules/pos/pos.controller.ts | 2 +- src/modules/restaurants/restaurants.controller.ts | 3 ++- src/modules/users/users.controller.ts | 3 ++- 9 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/modules/details/details.controller.ts b/src/modules/details/details.controller.ts index 900d2d9..ab13ae3 100644 --- a/src/modules/details/details.controller.ts +++ b/src/modules/details/details.controller.ts @@ -17,8 +17,9 @@ import { Delete, NotFoundException, BadRequestException, - InternalServerErrorException, UseGuards, + HttpException, + HttpStatus, } from '@nestjs/common'; import { DetailsService } from './details.service'; import { JwtAuthGuard } from 'src/shared/guards/jwt-auth.guard'; diff --git a/src/modules/food/food.controller.ts b/src/modules/food/food.controller.ts index 45ef234..257961d 100644 --- a/src/modules/food/food.controller.ts +++ b/src/modules/food/food.controller.ts @@ -16,8 +16,8 @@ import { Put, Delete, NotFoundException, - BadRequestException, - InternalServerErrorException, + HttpException, + HttpStatus, UseGuards, } from '@nestjs/common'; import { FoodService } from './food.service'; diff --git a/src/modules/food_category/food_category.controller.ts b/src/modules/food_category/food_category.controller.ts index b3ec1f3..9b2f80e 100644 --- a/src/modules/food_category/food_category.controller.ts +++ b/src/modules/food_category/food_category.controller.ts @@ -8,7 +8,8 @@ import { Delete, NotFoundException, BadRequestException, - InternalServerErrorException, + HttpException, + HttpStatus, UseGuards, } from '@nestjs/common'; import { FoodCategoryService } from './food_category.service'; diff --git a/src/modules/ingredient/ingredient.controller.ts b/src/modules/ingredient/ingredient.controller.ts index 3ff828c..d6cdc05 100644 --- a/src/modules/ingredient/ingredient.controller.ts +++ b/src/modules/ingredient/ingredient.controller.ts @@ -8,7 +8,8 @@ import { Delete, NotFoundException, BadRequestException, - InternalServerErrorException, + HttpException, + HttpStatus, UseGuards, } from '@nestjs/common'; import { IngredientService } from './ingredient.service'; diff --git a/src/modules/orders/orders.controller.ts b/src/modules/orders/orders.controller.ts index 7024988..96ca012 100644 --- a/src/modules/orders/orders.controller.ts +++ b/src/modules/orders/orders.controller.ts @@ -9,7 +9,8 @@ import { Delete, NotFoundException, BadRequestException, - InternalServerErrorException, + HttpException, + HttpStatus, UseGuards, } from '@nestjs/common'; import { OrdersService } from './orders.service'; diff --git a/src/modules/permission/permission.controller.ts b/src/modules/permission/permission.controller.ts index 3b3a445..3525ecc 100644 --- a/src/modules/permission/permission.controller.ts +++ b/src/modules/permission/permission.controller.ts @@ -8,7 +8,8 @@ import { Delete, NotFoundException, BadRequestException, - InternalServerErrorException, + HttpException, + HttpStatus, UseGuards, } from '@nestjs/common'; import { PermissionService } from './permission.service'; diff --git a/src/modules/pos/pos.controller.ts b/src/modules/pos/pos.controller.ts index 5e1bd9c..2cc4c43 100644 --- a/src/modules/pos/pos.controller.ts +++ b/src/modules/pos/pos.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Get, Param, NotFoundException, InternalServerErrorException, UseGuards } from '@nestjs/common'; +import { Controller, Get, Param, NotFoundException, HttpException, HttpStatus, UseGuards } from '@nestjs/common'; import { PosService } from './pos.service'; import { JwtAuthGuard } from 'src/shared/guards/jwt-auth.guard'; diff --git a/src/modules/restaurants/restaurants.controller.ts b/src/modules/restaurants/restaurants.controller.ts index 8108937..f62c037 100644 --- a/src/modules/restaurants/restaurants.controller.ts +++ b/src/modules/restaurants/restaurants.controller.ts @@ -8,7 +8,8 @@ import { Delete, NotFoundException, BadRequestException, - InternalServerErrorException, + HttpException, + HttpStatus, UseGuards, } from '@nestjs/common'; import { RestaurantsService } from './restaurants.service'; diff --git a/src/modules/users/users.controller.ts b/src/modules/users/users.controller.ts index c43cd9f..805722a 100644 --- a/src/modules/users/users.controller.ts +++ b/src/modules/users/users.controller.ts @@ -8,7 +8,8 @@ import { Delete, NotFoundException, BadRequestException, - InternalServerErrorException, + HttpException, + HttpStatus, UseGuards, } from '@nestjs/common'; import { UsersService } from './users.service'; From 3270c52ef59a150f4f6e08485d5763480b04b135 Mon Sep 17 00:00:00 2001 From: Xantass Date: Sat, 19 Oct 2024 00:28:24 -0400 Subject: [PATCH 3/7] fix: delete all console debug && change Request HTTP for route 'api/login' from POST to GET --- src/modules/login/login.controller.ts | 7 ++----- src/modules/login/login.service.ts | 2 -- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/modules/login/login.controller.ts b/src/modules/login/login.controller.ts index 85b5a5f..ade2bda 100644 --- a/src/modules/login/login.controller.ts +++ b/src/modules/login/login.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Req, Post, UnauthorizedException, Body } from '@nestjs/common'; +import { Controller, Req, Post, UnauthorizedException, Body, Get } from '@nestjs/common'; import { LoginService } from './login.service'; // Controller for handling login requests @@ -14,7 +14,7 @@ export class LoginController { * @returns {Promise} The authentication result. * @throws {UnauthorizedException} If authentication fails. */ - @Post() + @Get() async login(@Req() request: Request) { try { // Attempt to authenticate the user using the service @@ -23,12 +23,9 @@ export class LoginController { request.body['username'], request.body['password'], ); - console.log(auth); const token = await this.loginService.login(auth); - console.log(token) return token; // Return the authentication result } catch (error) { - console.log(error) // Handle authentication failure throw new UnauthorizedException(error.message); } diff --git a/src/modules/login/login.service.ts b/src/modules/login/login.service.ts index 6beadaa..5c92c37 100644 --- a/src/modules/login/login.service.ts +++ b/src/modules/login/login.service.ts @@ -38,7 +38,6 @@ export class LoginService extends DB { { projection: { _id: 0, users: { $elemMatch: { username: username } } } }, ); - console.log(user.users[0].password) if (!user) { // Throw an error if the user does not exist throw new UnauthorizedException('USER NOT FOUND'); @@ -67,7 +66,6 @@ export class LoginService extends DB { */ async login(user: any) { const payload = { username: user.username, sub: user.id }; - console.log(payload) return { access_token: await this.jwtService.signAsync(payload), // Generates the JWT token }; From 1ead1f614408ccd65ffe12f3af71a1d825e55a2b Mon Sep 17 00:00:00 2001 From: Xantass Date: Sat, 19 Oct 2024 00:43:37 -0400 Subject: [PATCH 4/7] fix: change HTTP error when user enter wrong username or password && delete message with this error --- src/modules/login/login.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/login/login.service.ts b/src/modules/login/login.service.ts index 5c92c37..ff98f01 100644 --- a/src/modules/login/login.service.ts +++ b/src/modules/login/login.service.ts @@ -40,7 +40,7 @@ export class LoginService extends DB { if (!user) { // Throw an error if the user does not exist - throw new UnauthorizedException('USER NOT FOUND'); + throw new UnauthorizedException(); } // Hash the provided password using bcrypt @@ -49,7 +49,7 @@ export class LoginService extends DB { // Compare the hashed password with the stored password if (password !== user.users[0].password) { // Throw an error if the password does not match - throw new UnauthorizedException('WRONG PASSWORD'); + throw new UnauthorizedException(); } return user.users[0]; // Return the authenticated user if successful From 5a42464d49141d4489147d1c1aa6918089fd5b49 Mon Sep 17 00:00:00 2001 From: Xantass Date: Sat, 19 Oct 2024 00:44:07 -0400 Subject: [PATCH 5/7] fix: change HTTP error when user enter wrong username or password && delete message with this error --- src/modules/login/login.controller.ts | 4 ++-- src/modules/login/login.service.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/modules/login/login.controller.ts b/src/modules/login/login.controller.ts index ade2bda..280841f 100644 --- a/src/modules/login/login.controller.ts +++ b/src/modules/login/login.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Req, Post, UnauthorizedException, Body, Get } from '@nestjs/common'; +import { Controller, Req, Get, BadRequestException } from '@nestjs/common'; import { LoginService } from './login.service'; // Controller for handling login requests @@ -27,7 +27,7 @@ export class LoginController { return token; // Return the authentication result } catch (error) { // Handle authentication failure - throw new UnauthorizedException(error.message); + throw new BadRequestException(error); } } } diff --git a/src/modules/login/login.service.ts b/src/modules/login/login.service.ts index ff98f01..21f8582 100644 --- a/src/modules/login/login.service.ts +++ b/src/modules/login/login.service.ts @@ -1,4 +1,4 @@ -import { Injectable, UnauthorizedException } from '@nestjs/common'; +import { Injectable, BadRequestException } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; import { DB } from 'src/db/db'; import * as bcrypt from 'bcrypt'; @@ -40,7 +40,7 @@ export class LoginService extends DB { if (!user) { // Throw an error if the user does not exist - throw new UnauthorizedException(); + throw new BadRequestException(); } // Hash the provided password using bcrypt @@ -49,7 +49,7 @@ export class LoginService extends DB { // Compare the hashed password with the stored password if (password !== user.users[0].password) { // Throw an error if the password does not match - throw new UnauthorizedException(); + throw new BadRequestException(); } return user.users[0]; // Return the authenticated user if successful From c6ec699d8ab7c447b09a47a0c4c96ba8b66ceb44 Mon Sep 17 00:00:00 2001 From: Xantass Date: Sat, 19 Oct 2024 00:49:40 -0400 Subject: [PATCH 6/7] fix: change params request of the route 'api/login' to three query params 'password, username, idRestaurant' --- src/modules/login/login.controller.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/modules/login/login.controller.ts b/src/modules/login/login.controller.ts index 280841f..b15db24 100644 --- a/src/modules/login/login.controller.ts +++ b/src/modules/login/login.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Req, Get, BadRequestException } from '@nestjs/common'; +import { Controller, Req, Get, BadRequestException, Query } from '@nestjs/common'; import { LoginService } from './login.service'; // Controller for handling login requests @@ -10,18 +10,22 @@ export class LoginController { /** * Authenticates a user based on the provided credentials. * - * @param {Request} request - The login credentials containing username, password and idRestaurant. + * @param {string} password - The password of the user. + * @param {string} username - The username of the user. + * @param {number} idRestaurant - The id of the restaurant where containing the user. * @returns {Promise} The authentication result. * @throws {UnauthorizedException} If authentication fails. */ @Get() - async login(@Req() request: Request) { + async login(@Query('password') password: string, + @Query('username') username: string, + @Query('idRestaurant') idRestaurant: number) { try { // Attempt to authenticate the user using the service const auth = await this.loginService.authenticateUser( - Number(request.body['idRestaurant']), - request.body['username'], - request.body['password'], + Number(idRestaurant), + username, + password, ); const token = await this.loginService.login(auth); return token; // Return the authentication result From 00ca6d7b405a00247b8ca4b75515e8f90a13c79c Mon Sep 17 00:00:00 2001 From: Xantass Date: Sat, 19 Oct 2024 00:53:24 -0400 Subject: [PATCH 7/7] fix: remove hashing password receive into query params --- src/modules/login/login.service.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/modules/login/login.service.ts b/src/modules/login/login.service.ts index 21f8582..db8bc4a 100644 --- a/src/modules/login/login.service.ts +++ b/src/modules/login/login.service.ts @@ -43,9 +43,6 @@ export class LoginService extends DB { throw new BadRequestException(); } - // Hash the provided password using bcrypt - password = bcrypt.hashSync(password, process.env.SALT_HASH); - // Compare the hashed password with the stored password if (password !== user.users[0].password) { // Throw an error if the password does not match