From 1de591ed7959c4d4416b214c19cc718cee390b74 Mon Sep 17 00:00:00 2001 From: Janderson Souza Matias Date: Wed, 5 Jun 2024 19:47:35 -0300 Subject: [PATCH] Security improvement --- .../migrations/1717627320186-migrations.ts | 15 ++++++++++++ src/modules/auth/entity/otp.entity.ts | 3 +++ src/modules/auth/service/index.ts | 11 +++++++-- src/modules/logs/controller/index.ts | 7 ++++++ src/modules/region/controller/index.ts | 7 ++++++ src/modules/user/controller/index.ts | 23 +++++++++++++++++++ src/server.ts | 5 ++++ 7 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 src/database/migrations/1717627320186-migrations.ts diff --git a/src/database/migrations/1717627320186-migrations.ts b/src/database/migrations/1717627320186-migrations.ts new file mode 100644 index 0000000..f535c7e --- /dev/null +++ b/src/database/migrations/1717627320186-migrations.ts @@ -0,0 +1,15 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class Migrations1717627320186 implements MigrationInterface { + name = "Migrations1717627320186"; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "otp" ADD "used" boolean NOT NULL DEFAULT false` + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "otp" DROP COLUMN "used"`); + } +} diff --git a/src/modules/auth/entity/otp.entity.ts b/src/modules/auth/entity/otp.entity.ts index eba7706..9dbe1d3 100644 --- a/src/modules/auth/entity/otp.entity.ts +++ b/src/modules/auth/entity/otp.entity.ts @@ -19,6 +19,9 @@ export class Otp { @Column() code?: string; + @Column({ default: false }) + used?: boolean; + @Column() email?: string; diff --git a/src/modules/auth/service/index.ts b/src/modules/auth/service/index.ts index b70ebfc..9fb11a6 100644 --- a/src/modules/auth/service/index.ts +++ b/src/modules/auth/service/index.ts @@ -57,7 +57,7 @@ export default class Authentication { public static signUser = (user: User, res: Response): void => { const payload = { email: user.email, sub: user.id }; const newToken = jwt.sign(payload, secret, { - expiresIn: 604800, // expires in 7 days + expiresIn: 60480, // 1 Day }); res.setHeader("token", newToken); res.setHeader("Access-Control-Allow-Headers", "true"); @@ -137,10 +137,17 @@ export default class Authentication { const otpRepository = await dataSource.getRepository(Otp); const tenMinutesAgo = new Date().getTime() - 10 * 60 * 1000; - return await otpRepository.findOneBy({ + const otpCode = await otpRepository.findOneBy({ email, code, + used: false, created_at: MoreThan(tenMinutesAgo), }); + + if (otpCode?.id) { + await otpRepository.update(otpCode?.id, { used: true }); + } + + return otpCode; }; } diff --git a/src/modules/logs/controller/index.ts b/src/modules/logs/controller/index.ts index 557b38a..c02b07d 100644 --- a/src/modules/logs/controller/index.ts +++ b/src/modules/logs/controller/index.ts @@ -1,6 +1,7 @@ import { Request, Response } from "express"; import { constants } from "http2"; import { LogsService } from "../service"; +import { User } from "../../user/entity"; const { HTTP_STATUS_OK, HTTP_STATUS_INTERNAL_SERVER_ERROR } = constants; export default class LogsController { @@ -9,6 +10,12 @@ export default class LogsController { res: Response ): Promise => { try { + const currentUser: User = res.locals.authUser; + + if (currentUser.role !== "admin") { + throw new Error("You can not do that."); + } + const list = await LogsService.findAll(); return res.status(HTTP_STATUS_OK).send(list); } catch (error) { diff --git a/src/modules/region/controller/index.ts b/src/modules/region/controller/index.ts index 9fe05aa..67caefc 100644 --- a/src/modules/region/controller/index.ts +++ b/src/modules/region/controller/index.ts @@ -1,6 +1,7 @@ import { Request, Response } from "express"; import { constants } from "http2"; import { RegionService } from "../service"; +import { User } from "../../user/entity"; const { HTTP_STATUS_OK, @@ -38,6 +39,12 @@ export default class SchoolController { public static delete = async (req: Request, res: Response): Promise => { try { + const currentUser: User = res.locals.authUser; + + if (currentUser.role !== "admin") { + throw new Error("You can not do that."); + } + const deletedItem = await RegionService.delete(req.params.id); return res.status(HTTP_STATUS_CREATED).send(deletedItem); } catch (error) { diff --git a/src/modules/user/controller/index.ts b/src/modules/user/controller/index.ts index 2d22ae1..872d595 100644 --- a/src/modules/user/controller/index.ts +++ b/src/modules/user/controller/index.ts @@ -1,6 +1,7 @@ import { Request, Response } from "express"; import { UserService } from "../service"; import { constants } from "http2"; +import { User } from "../entity"; const { HTTP_STATUS_OK, @@ -29,6 +30,12 @@ export default class UserController { res: Response ): Promise => { try { + const currentUser: User = res.locals.authUser; + + if (currentUser.role !== "admin") { + throw new Error("You can not do that."); + } + const list = await UserService.findAllAdmins(); return res.status(HTTP_STATUS_OK).send(list); } catch (error) { @@ -50,6 +57,16 @@ export default class UserController { throw new Error("Identifier of user not found."); } + const currentUser: User = res.locals.authUser; + + if (user_id !== currentUser.id && currentUser.role !== "admin") { + throw new Error("You can not do that."); + } + + if (newUser.role && currentUser.role !== "admin") { + throw new Error("You can not do that."); + } + await UserService.updateAdmin(user_id, newUser); return res.status(HTTP_STATUS_OK).send({}); @@ -66,6 +83,12 @@ export default class UserController { res: Response ): Promise => { try { + const currentUser: User = res.locals.authUser; + + if (currentUser.role !== "admin") { + throw new Error("You can not do that."); + } + const newUser = _req.body; return res diff --git a/src/server.ts b/src/server.ts index 17bb49b..742773e 100644 --- a/src/server.ts +++ b/src/server.ts @@ -32,6 +32,11 @@ const CoachServer = { }, }) ); + + app.use((err: any, _req: any, res: any, _next: any) => { + console.error(err.stack); + res.status(500).send("Something broke!"); + }); }, close: (server: Server): void => {