From 2f24abbe725f90c19167da98261966f3281de4e4 Mon Sep 17 00:00:00 2001 From: lucaslinyker Date: Wed, 18 Jun 2025 11:10:11 -0300 Subject: [PATCH 01/22] =?UTF-8?q?feat:=20Criar=20service=20de=20autentica?= =?UTF-8?q?=C3=A7=C3=A3o=20e=20erro?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit criar um service de autenticação e criar também o erro de credenciais --- .../errors/invalid-credentials-error.ts | 5 ++++ src/services/users/authenticate.ts | 28 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/services/errors/invalid-credentials-error.ts create mode 100644 src/services/users/authenticate.ts diff --git a/src/services/errors/invalid-credentials-error.ts b/src/services/errors/invalid-credentials-error.ts new file mode 100644 index 0000000..8cff53d --- /dev/null +++ b/src/services/errors/invalid-credentials-error.ts @@ -0,0 +1,5 @@ +export class InvalidCredentialsError extends Error { + constructor() { + super('Invalid credentials.') + } +} diff --git a/src/services/users/authenticate.ts b/src/services/users/authenticate.ts new file mode 100644 index 0000000..f9e0ded --- /dev/null +++ b/src/services/users/authenticate.ts @@ -0,0 +1,28 @@ +import type { UsersRepository } from '@/repositories/users-repository' +import { compare } from 'bcryptjs' +import { InvalidCredentialsError } from '../errors/invalid-credentials-error' + +interface AuthenticateServiceRequest { + email: string + password: string +} + +export class AuthenticateService { + constructor(private usersRepository: UsersRepository) {} + + async execute({ email, password }: AuthenticateServiceRequest) { + const user = await this.usersRepository.findByEmail(email) + + if (!user) { + throw new InvalidCredentialsError() + } + + const doesPasswordMatches = await compare(password, user.password) + + if (!doesPasswordMatches) { + throw new InvalidCredentialsError() + } + + return { user } + } +} From a7eaef8378c2e4ab65c82032b30bd1a94ca99112 Mon Sep 17 00:00:00 2001 From: lucaslinyker Date: Tue, 24 Jun 2025 14:30:59 -0300 Subject: [PATCH 02/22] build: Adicionar @fastify/cookie e @fastify/jwt --- package-lock.json | 180 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 2 + 2 files changed, 179 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2f951ee..cb690ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,8 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "@fastify/cookie": "^11.0.2", + "@fastify/jwt": "^9.1.0", "@prisma/client": "^6.4.1", "bcryptjs": "^3.0.2", "dotenv": "^16.5.0", @@ -829,6 +831,26 @@ "fast-uri": "^3.0.0" } }, + "node_modules/@fastify/cookie": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/@fastify/cookie/-/cookie-11.0.2.tgz", + "integrity": "sha512-GWdwdGlgJxyvNv+QcKiGNevSspMQXncjMZ1J8IvuDQk0jvkzgWWZFNC2En3s+nHndZBGV8IbLwOI/sxCZw/mzA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "cookie": "^1.0.0", + "fastify-plugin": "^5.0.0" + } + }, "node_modules/@fastify/error": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@fastify/error/-/error-4.0.0.tgz", @@ -860,6 +882,29 @@ "integrity": "sha512-kJExsp4JCms7ipzg7SJ3y8DwmePaELHxKYtg+tZow+k0znUTf3cb+npgyqm8+ATZOdmfgfydIebPDWM172wfyA==", "license": "MIT" }, + "node_modules/@fastify/jwt": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@fastify/jwt/-/jwt-9.1.0.tgz", + "integrity": "sha512-CiGHCnS5cPMdb004c70sUWhQTfzrJHAeTywt7nVw6dAiI0z1o4WRvU94xfijhkaId4bIxTCOjFgn4sU+Gvk43w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "@fastify/error": "^4.0.0", + "@lukeed/ms": "^2.0.2", + "fast-jwt": "^5.0.0", + "fastify-plugin": "^5.0.0", + "steed": "^1.1.3" + } + }, "node_modules/@fastify/merge-json-schemas": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@fastify/merge-json-schemas/-/merge-json-schemas-0.2.1.tgz", @@ -970,6 +1015,15 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@lukeed/ms": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@lukeed/ms/-/ms-2.0.2.tgz", + "integrity": "sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -1459,6 +1513,18 @@ "dev": true, "license": "MIT" }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, "node_modules/atomic-sleep": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", @@ -1527,6 +1593,12 @@ "readable-stream": "^3.4.0" } }, + "node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "license": "MIT" + }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -1895,6 +1967,15 @@ "dev": true, "license": "MIT" }, + "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/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -2027,6 +2108,21 @@ "rfdc": "^1.2.0" } }, + "node_modules/fast-jwt": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/fast-jwt/-/fast-jwt-5.0.6.tgz", + "integrity": "sha512-LPE7OCGUl11q3ZgW681cEU2d0d2JZ37hhJAmetCgNyW8waVaJVZXhyFF6U2so1Iim58Yc7pfxJe2P7MNetQH2g==", + "license": "Apache-2.0", + "dependencies": { + "@lukeed/ms": "^2.0.2", + "asn1.js": "^5.4.1", + "ecdsa-sig-formatter": "^1.0.11", + "mnemonist": "^0.40.0" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/fast-querystring": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/fast-querystring/-/fast-querystring-1.1.2.tgz", @@ -2061,6 +2157,18 @@ ], "license": "BSD-3-Clause" }, + "node_modules/fastfall": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/fastfall/-/fastfall-1.5.1.tgz", + "integrity": "sha512-KH6p+Z8AKPXnmA7+Iz2Lh8ARCMr+8WNPVludm1LGkZoD2MjY6LVnRMtTKhkdzI+jr0RzQWXKzKyBJm1zoHEL4Q==", + "license": "MIT", + "dependencies": { + "reusify": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/fastify": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/fastify/-/fastify-5.3.2.tgz", @@ -2094,6 +2202,12 @@ "toad-cache": "^3.7.0" } }, + "node_modules/fastify-plugin": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-5.0.1.tgz", + "integrity": "sha512-HCxs+YnRaWzCl+cWRYFnHmeRFyR5GVnJTAaCJQiYzQSDwK9MgJdyAsuL3nh0EWRCYMgQ5MeziymvmAhUHYHDUQ==", + "license": "MIT" + }, "node_modules/fastify/node_modules/process-warning": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", @@ -2110,6 +2224,16 @@ ], "license": "MIT" }, + "node_modules/fastparallel": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/fastparallel/-/fastparallel-2.4.1.tgz", + "integrity": "sha512-qUmhxPgNHmvRjZKBFUNI0oZuuH9OlSIOXmJ98lhKPxMZZ7zS/Fi0wRHOihDSz0R1YiIOjxzOY4bq65YTcdBi2Q==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4", + "xtend": "^4.0.2" + } + }, "node_modules/fastq": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", @@ -2119,6 +2243,16 @@ "reusify": "^1.0.4" } }, + "node_modules/fastseries": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/fastseries/-/fastseries-1.7.2.tgz", + "integrity": "sha512-dTPFrPGS8SNSzAt7u/CbMKCJ3s01N04s4JFbORHcmyvVfVKmbhMD1VtRbh5enGHxkaQDqWyLefiKOGGmohGDDQ==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.0", + "xtend": "^4.0.0" + } + }, "node_modules/fdir": { "version": "6.4.3", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", @@ -2316,7 +2450,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, "license": "ISC" }, "node_modules/ini": { @@ -2771,6 +2904,12 @@ "node": ">=6" } }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "license": "ISC" + }, "node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -2797,6 +2936,15 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/mnemonist": { + "version": "0.40.3", + "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.40.3.tgz", + "integrity": "sha512-Vjyr90sJ23CKKH/qPAgUKicw/v6pRoamxIEDFOF8uSgFME7DqPRpHgRTejWVjkdGg5dXj0/NyxZHZ9bcjH+2uQ==", + "license": "MIT", + "dependencies": { + "obliterator": "^2.0.4" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -2836,6 +2984,12 @@ "node": ">=0.10.0" } }, + "node_modules/obliterator": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.5.tgz", + "integrity": "sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==", + "license": "MIT" + }, "node_modules/on-exit-leak-free": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", @@ -3364,7 +3518,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -3413,7 +3566,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, "license": "MIT" }, "node_modules/secure-json-parse": { @@ -3517,6 +3669,19 @@ "node": ">= 10.x" } }, + "node_modules/steed": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/steed/-/steed-1.1.3.tgz", + "integrity": "sha512-EUkci0FAUiE4IvGTSKcDJIQ/eRUP2JJb56+fvZ4sdnguLTqIdKjSxUe138poW8mkvKWXW2sFPrgTsxqoISnmoA==", + "license": "MIT", + "dependencies": { + "fastfall": "^1.5.0", + "fastparallel": "^2.2.0", + "fastq": "^1.3.0", + "fastseries": "^1.7.0", + "reusify": "^1.0.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -4035,6 +4200,15 @@ "node": ">=8" } }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, "node_modules/yoctocolors-cjs": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", diff --git a/package.json b/package.json index bf261e4..6f8ab0d 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,8 @@ "typescript": "^5.8.2" }, "dependencies": { + "@fastify/cookie": "^11.0.2", + "@fastify/jwt": "^9.1.0", "@prisma/client": "^6.4.1", "fastify": "^5.3.2", "bcryptjs": "^3.0.2", From df746fb253447d7d2c7c2386d74a568760e2b9e7 Mon Sep 17 00:00:00 2001 From: lucaslinyker Date: Tue, 24 Jun 2025 14:42:46 -0300 Subject: [PATCH 03/22] =?UTF-8?q?chore(env):=20Adicionar=20verifica=C3=A7?= =?UTF-8?q?=C3=A3o=20do=20secret=20JWT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/env/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/env/index.ts b/src/env/index.ts index 4af392b..3762a7a 100644 --- a/src/env/index.ts +++ b/src/env/index.ts @@ -4,6 +4,7 @@ import { z } from 'zod' const envSchema = z.object({ PORT: z.coerce.number().min(1000).max(9999).default(3333), NODE_ENV: z.enum(['dev', 'test', 'prod']).default('dev'), + JWT_SECRET: z.string(), }) const _env = envSchema.safeParse(process.env) From bae9298bc7b6228f97fa2488706e99a2ec7e539b Mon Sep 17 00:00:00 2001 From: lucaslinyker Date: Tue, 24 Jun 2025 14:53:08 -0300 Subject: [PATCH 04/22] chore(types): Adicionar interface user para o @fastify/jwt --- src/@types/fastify-jwt.d.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/@types/fastify-jwt.d.ts diff --git a/src/@types/fastify-jwt.d.ts b/src/@types/fastify-jwt.d.ts new file mode 100644 index 0000000..e2e946d --- /dev/null +++ b/src/@types/fastify-jwt.d.ts @@ -0,0 +1,10 @@ +import '@fastify/jwt' + +declare module '@fastify/jwt' { + export interface FastifyJWT { + user: { + sub: string + role: 'CUSTOMER' | 'EMPLOYEE' | 'ADMIN' + } + } +} From d28cc6b4724f6a1aca321ab4e2402b86dfa024ab Mon Sep 17 00:00:00 2001 From: lucaslinyker Date: Tue, 24 Jun 2025 14:56:42 -0300 Subject: [PATCH 05/22] feat: Configurar fastifyJwt e cookie no fastify --- src/app.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/app.ts b/src/app.ts index c5ac111..3479d02 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,3 +1,5 @@ +import fastifyCookie from '@fastify/cookie' +import fastifyJwt from '@fastify/jwt' import fastify, { type FastifyReply } from 'fastify' import { ZodError } from 'zod' import { env } from './env' @@ -12,6 +14,19 @@ app.get('/', (_, reply: FastifyReply) => { }) }) +app.register(fastifyJwt, { + secret: env.JWT_SECRET, + cookie: { + cookieName: 'refreshToken', + signed: false, + }, + sign: { + expiresIn: '10m', + }, +}) + +app.register(fastifyCookie) + app.register(appRoutes, { prefix: '/api' }) app.setErrorHandler((error, _, reply) => { From b9a2bf61a2c0ad6f61966920e7591038923a4d52 Mon Sep 17 00:00:00 2001 From: lucaslinyker Date: Tue, 24 Jun 2025 14:58:01 -0300 Subject: [PATCH 06/22] =?UTF-8?q?feat:=20Criar=20factory=20de=20autentica?= =?UTF-8?q?=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/services/factories/make-authenticate-service.ts | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/services/factories/make-authenticate-service.ts diff --git a/src/services/factories/make-authenticate-service.ts b/src/services/factories/make-authenticate-service.ts new file mode 100644 index 0000000..39e288e --- /dev/null +++ b/src/services/factories/make-authenticate-service.ts @@ -0,0 +1,9 @@ +import { PrismaUsersRepository } from '@/repositories/prisma/prisma-users-repository' +import { AuthenticateService } from '../users/authenticate' + +export function makeAuthenticateService() { + const usersRepository = new PrismaUsersRepository() + const authenticateService = new AuthenticateService(usersRepository) + + return authenticateService +} From 5c3b31e3116325665ec5a8adbbdde9495eda8bcd Mon Sep 17 00:00:00 2001 From: lucaslinyker Date: Tue, 24 Jun 2025 15:03:32 -0300 Subject: [PATCH 07/22] =?UTF-8?q?feat:=20Criar=20controller=20de=20autenti?= =?UTF-8?q?ca=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fazer a criação dos token JWT quando autenticado --- src/http/controllers/users/authenticate.ts | 62 ++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/http/controllers/users/authenticate.ts diff --git a/src/http/controllers/users/authenticate.ts b/src/http/controllers/users/authenticate.ts new file mode 100644 index 0000000..38c57e6 --- /dev/null +++ b/src/http/controllers/users/authenticate.ts @@ -0,0 +1,62 @@ +import type { FastifyReply, FastifyRequest } from 'fastify' +import { z } from 'zod' + +import { InvalidCredentialsError } from '@/services/errors/invalid-credentials-error' +import { makeAuthenticateService } from '@/services/factories/make-authenticate-service' + +export async function authenticate( + request: FastifyRequest, + reply: FastifyReply, +) { + const authenticateBodySchema = z.object({ + email: z.string().email(), + password: z.string().min(6), + }) + + const { email, password } = authenticateBodySchema.parse(request.body) + + try { + const authenticateService = makeAuthenticateService() + + const { user } = await authenticateService.execute({ email, password }) + + const token = await reply.jwtSign( + { + role: user.role, + }, + { + sign: { + sub: user.id, + }, + }, + ) + + const refreshToken = await reply.jwtSign( + { + role: user.role, + }, + { + sign: { + sub: user.id, + expiresIn: '7d', + }, + }, + ) + + return reply + .setCookie('refreshToken', refreshToken, { + path: '/', + secure: true, + sameSite: true, + httpOnly: true, + }) + .status(200) + .send({ token }) + } catch (err) { + if (err instanceof InvalidCredentialsError) { + return reply.status(400).send({ message: err.message }) + } + + throw err + } +} From 1e8052cbd4779c26560f154c6760a972c10508a3 Mon Sep 17 00:00:00 2001 From: lucaslinyker Date: Tue, 24 Jun 2025 15:09:52 -0300 Subject: [PATCH 08/22] feat: Criar controller de refresh token --- src/http/controllers/users/refresh.ts | 36 +++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/http/controllers/users/refresh.ts diff --git a/src/http/controllers/users/refresh.ts b/src/http/controllers/users/refresh.ts new file mode 100644 index 0000000..4784efd --- /dev/null +++ b/src/http/controllers/users/refresh.ts @@ -0,0 +1,36 @@ +import type { FastifyReply, FastifyRequest } from 'fastify' + +export async function refresh(request: FastifyRequest, reply: FastifyReply) { + await request.jwtVerify({ onlyCookie: true }) + + const { role } = request.user + + const token = await reply.jwtSign( + { role }, + { + sign: { + sub: request.user.sub, + }, + }, + ) + + const refreshToken = await reply.jwtSign( + { role }, + { + sign: { + sub: request.user.sub, + expiresIn: '7d', + }, + }, + ) + + return reply + .setCookie('refreshToken', refreshToken, { + path: '/', + secure: true, + sameSite: true, + httpOnly: true, + }) + .status(200) + .send({ token }) +} From f5f0b939babc658cdfe71d3dcef909efc0ce0117 Mon Sep 17 00:00:00 2001 From: lucaslinyker Date: Tue, 24 Jun 2025 15:11:37 -0300 Subject: [PATCH 09/22] feat: Criar controller de logout --- src/http/controllers/users/logout.ts | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/http/controllers/users/logout.ts diff --git a/src/http/controllers/users/logout.ts b/src/http/controllers/users/logout.ts new file mode 100644 index 0000000..68073fd --- /dev/null +++ b/src/http/controllers/users/logout.ts @@ -0,0 +1,7 @@ +import type { FastifyReply, FastifyRequest } from 'fastify' + +export async function logout(_: FastifyRequest, reply: FastifyReply) { + reply.clearCookie('refreshToken', { path: '/' }) + + return reply.status(200).send() +} From 3f053c890825b9ff5eaffb5b14a630f452652249 Mon Sep 17 00:00:00 2001 From: lucaslinyker Date: Tue, 24 Jun 2025 15:47:50 -0300 Subject: [PATCH 10/22] =?UTF-8?q?feat:=20Adicionar=20rotas=20para=20os=20c?= =?UTF-8?q?ontrollers=20de=20autentica=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/http/controllers/users/routes.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/http/controllers/users/routes.ts b/src/http/controllers/users/routes.ts index 6ecb433..326551d 100644 --- a/src/http/controllers/users/routes.ts +++ b/src/http/controllers/users/routes.ts @@ -1,7 +1,10 @@ import type { FastifyInstance } from 'fastify' +import { authenticate } from './authenticate' import { getUser } from './getUser' import { list } from './list' +import { logout } from './logout' +import { refresh } from './refresh' import { register } from './register' import { remove } from './remove' import { update } from './update' @@ -12,4 +15,8 @@ export async function usersRoutes(app: FastifyInstance) { app.post('/users', register) app.patch('/user/:id', update) app.delete('/user/:id', remove) + + app.post('/auth/login', authenticate) + app.patch('/auth/refresh', refresh) + app.delete('/auth/logout', logout) } From c43649e3cd1fb1d3d3054fe78d2dcf1db9c279d5 Mon Sep 17 00:00:00 2001 From: lucaslinyker Date: Tue, 24 Jun 2025 15:51:46 -0300 Subject: [PATCH 11/22] feat: Criar middleware para verificar jwt --- src/http/middlewares/verify-jwt.ts | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/http/middlewares/verify-jwt.ts diff --git a/src/http/middlewares/verify-jwt.ts b/src/http/middlewares/verify-jwt.ts new file mode 100644 index 0000000..5a3df95 --- /dev/null +++ b/src/http/middlewares/verify-jwt.ts @@ -0,0 +1,9 @@ +import type { FastifyReply, FastifyRequest } from 'fastify' + +export async function verifyJWT(request: FastifyRequest, reply: FastifyReply) { + try { + await request.jwtVerify() + } catch (err) { + return reply.status(401).send({ message: 'Unauthorized.' }) + } +} From 21f12ae02eb9747199740ba262f6e8cf5e526df6 Mon Sep 17 00:00:00 2001 From: lucaslinyker Date: Tue, 24 Jun 2025 15:54:55 -0300 Subject: [PATCH 12/22] feat: Criar middleware para verificar role do user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit criar um middleware que verificará o acesso do usuário a determinadas rotas com base na role (cargo) dele --- src/http/middlewares/verify-user-role.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/http/middlewares/verify-user-role.ts diff --git a/src/http/middlewares/verify-user-role.ts b/src/http/middlewares/verify-user-role.ts new file mode 100644 index 0000000..b7276d1 --- /dev/null +++ b/src/http/middlewares/verify-user-role.ts @@ -0,0 +1,22 @@ +import type { FastifyReply, FastifyRequest } from 'fastify' + +type Role = 'CUSTOMER' | 'EMPLOYEE' | 'ADMIN' + +const roleHierarchy: Record = { + ADMIN: ['ADMIN', 'EMPLOYEE', 'CUSTOMER'], + EMPLOYEE: ['EMPLOYEE', 'CUSTOMER'], + CUSTOMER: ['CUSTOMER'], +} + +export function verifyUserRole(roleToVerify: Role) { + return async (request: FastifyRequest, reply: FastifyReply) => { + await request.jwtVerify() + const { role } = request.user + + const allowedRoles = roleHierarchy[role] + + if (!allowedRoles.includes(roleToVerify)) { + return reply.status(401).send({ message: 'Unauthorized.' }) + } + } +} From ad83d518807463f0a4ef983bb44c5762b9b93094 Mon Sep 17 00:00:00 2001 From: lucaslinyker Date: Tue, 24 Jun 2025 16:08:20 -0300 Subject: [PATCH 13/22] feat: Adicionar middlewares para algumas rotas MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit adicionar middlwares para algumas rotas que precisam verificar se o usuário está logado ou se pode acessar a rota com base na role (cargo) dele --- src/http/controllers/users/routes.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/http/controllers/users/routes.ts b/src/http/controllers/users/routes.ts index 326551d..afa2344 100644 --- a/src/http/controllers/users/routes.ts +++ b/src/http/controllers/users/routes.ts @@ -1,5 +1,8 @@ import type { FastifyInstance } from 'fastify' +import { verifyJWT } from '@/http/middlewares/verify-jwt' +import { verifyUserRole } from '@/http/middlewares/verify-user-role' + import { authenticate } from './authenticate' import { getUser } from './getUser' import { list } from './list' @@ -10,13 +13,15 @@ import { remove } from './remove' import { update } from './update' export async function usersRoutes(app: FastifyInstance) { - app.get('/user/:email', getUser) - app.get('/users', list) app.post('/users', register) - app.patch('/user/:id', update) - app.delete('/user/:id', remove) + app.get('/user/:email', { onRequest: [verifyJWT] }, getUser) + // TODO: separate the route of update into more + app.patch('/user/:id', { onRequest: [verifyJWT] }, update) + app.delete('/user/:id', { onRequest: [verifyJWT] }, remove) app.post('/auth/login', authenticate) app.patch('/auth/refresh', refresh) - app.delete('/auth/logout', logout) + app.delete('/auth/logout', { onRequest: [verifyJWT] }, logout) + + app.get('/users', { onRequest: [verifyUserRole('ADMIN')] }, list) } From a43c76c5a5189f6d74a7ad042b5e6a6e5411d68a Mon Sep 17 00:00:00 2001 From: lucaslinyker Date: Tue, 24 Jun 2025 18:45:17 -0300 Subject: [PATCH 14/22] refact: Remover a necessidade de passar o email para buscar o profile --- src/http/controllers/users/getUser.ts | 30 +++++++++------------------ src/http/controllers/users/routes.ts | 2 +- src/services/users/get-user.ts | 12 +++-------- 3 files changed, 14 insertions(+), 30 deletions(-) diff --git a/src/http/controllers/users/getUser.ts b/src/http/controllers/users/getUser.ts index 9c5f303..e8008ef 100644 --- a/src/http/controllers/users/getUser.ts +++ b/src/http/controllers/users/getUser.ts @@ -1,28 +1,18 @@ import type { FastifyReply, FastifyRequest } from 'fastify' -import { z } from 'zod' -import { UserNotExistsError } from '@/services/errors/user-not-exists-error' import { makeGetUserService } from '@/services/factories/make-get-user-service' export async function getUser(request: FastifyRequest, reply: FastifyReply) { - const getUserParamsSchema = z.object({ - email: z.string().email(), - }) - - const { email } = getUserParamsSchema.parse(request.params) - - let user = null - try { - const getUserService = makeGetUserService() + const getUser = makeGetUserService() - user = await getUserService.execute({ email }) - } catch (err) { - if (err instanceof UserNotExistsError) { - return reply.status(404).send({ message: err.message }) - } - - throw err - } + const { user } = await getUser.execute({ + userId: request.user.sub, + }) - return reply.status(200).send(user) + return reply.status(200).send({ + user: { + ...user, + password: undefined, + }, + }) } diff --git a/src/http/controllers/users/routes.ts b/src/http/controllers/users/routes.ts index afa2344..c127e88 100644 --- a/src/http/controllers/users/routes.ts +++ b/src/http/controllers/users/routes.ts @@ -14,7 +14,7 @@ import { update } from './update' export async function usersRoutes(app: FastifyInstance) { app.post('/users', register) - app.get('/user/:email', { onRequest: [verifyJWT] }, getUser) + app.get('/user', { onRequest: [verifyJWT] }, getUser) // TODO: separate the route of update into more app.patch('/user/:id', { onRequest: [verifyJWT] }, update) app.delete('/user/:id', { onRequest: [verifyJWT] }, remove) diff --git a/src/services/users/get-user.ts b/src/services/users/get-user.ts index 16fe8bb..7b790c2 100644 --- a/src/services/users/get-user.ts +++ b/src/services/users/get-user.ts @@ -1,19 +1,13 @@ import type { UsersRepository } from '@/repositories/users-repository' -import { UserNotExistsError } from '../errors/user-not-exists-error' - interface GetUserServiceRequest { - email: string + userId: string } export class GetUserService { constructor(private usersRepository: UsersRepository) {} - async execute({ email }: GetUserServiceRequest) { - const user = await this.usersRepository.findByEmail(email) - - if (!user) { - throw new UserNotExistsError() - } + async execute({ userId }: GetUserServiceRequest) { + const user = await this.usersRepository.findById(userId) return { user } } From 709b4fe6d2f35abb144be1854ea7501a231d5a7e Mon Sep 17 00:00:00 2001 From: lucaslinyker Date: Wed, 25 Jun 2025 14:39:38 -0300 Subject: [PATCH 15/22] =?UTF-8?q?refact:=20Passar=20o=20id=20do=20usu?= =?UTF-8?q?=C3=A1rio=20pelo=20token=20jwt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/http/controllers/users/routes.ts | 2 +- src/http/controllers/users/update.ts | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/http/controllers/users/routes.ts b/src/http/controllers/users/routes.ts index c127e88..5737b03 100644 --- a/src/http/controllers/users/routes.ts +++ b/src/http/controllers/users/routes.ts @@ -16,7 +16,7 @@ export async function usersRoutes(app: FastifyInstance) { app.post('/users', register) app.get('/user', { onRequest: [verifyJWT] }, getUser) // TODO: separate the route of update into more - app.patch('/user/:id', { onRequest: [verifyJWT] }, update) + app.patch('/user', { onRequest: [verifyJWT] }, update) app.delete('/user/:id', { onRequest: [verifyJWT] }, remove) app.post('/auth/login', authenticate) diff --git a/src/http/controllers/users/update.ts b/src/http/controllers/users/update.ts index 155ebc9..1dd9e91 100644 --- a/src/http/controllers/users/update.ts +++ b/src/http/controllers/users/update.ts @@ -5,10 +5,6 @@ import { UserNotExistsError } from '@/services/errors/user-not-exists-error' import { makeUpdateService } from '@/services/factories/make-update-service' export async function update(request: FastifyRequest, reply: FastifyReply) { - const updateParamsSchema = z.object({ - id: z.string().cuid(), - }) - const updateBodySchema = z .object({ name: z.string().min(2), @@ -21,7 +17,7 @@ export async function update(request: FastifyRequest, reply: FastifyReply) { message: 'At least one field must be provided for update', }) - const { id } = updateParamsSchema.parse(request.params) + const id = request.user.sub const data = updateBodySchema.parse(request.body) let user = null @@ -37,5 +33,10 @@ export async function update(request: FastifyRequest, reply: FastifyReply) { throw err } - return reply.status(200).send(user) + return reply.status(200).send({ + user: { + ...user, + password: undefined, + }, + }) } From 8873b2b3f85082bc36ab2ac8cbb94770968a963f Mon Sep 17 00:00:00 2001 From: lucaslinyker Date: Wed, 25 Jun 2025 14:46:26 -0300 Subject: [PATCH 16/22] refact: Passar o id pelo jwt --- src/http/controllers/users/remove.ts | 7 +------ src/http/controllers/users/routes.ts | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/http/controllers/users/remove.ts b/src/http/controllers/users/remove.ts index 24bde42..093d291 100644 --- a/src/http/controllers/users/remove.ts +++ b/src/http/controllers/users/remove.ts @@ -1,15 +1,10 @@ import type { FastifyReply, FastifyRequest } from 'fastify' -import { z } from 'zod' import { UserNotExistsError } from '@/services/errors/user-not-exists-error' import { makeRemoveService } from '@/services/factories/make-remove-service' export async function remove(request: FastifyRequest, reply: FastifyReply) { - const removeParamsSchema = z.object({ - id: z.string().cuid(), - }) - - const { id } = removeParamsSchema.parse(request.params) + const id = request.user.sub try { const removeService = makeRemoveService() diff --git a/src/http/controllers/users/routes.ts b/src/http/controllers/users/routes.ts index 5737b03..c3a8892 100644 --- a/src/http/controllers/users/routes.ts +++ b/src/http/controllers/users/routes.ts @@ -17,7 +17,7 @@ export async function usersRoutes(app: FastifyInstance) { app.get('/user', { onRequest: [verifyJWT] }, getUser) // TODO: separate the route of update into more app.patch('/user', { onRequest: [verifyJWT] }, update) - app.delete('/user/:id', { onRequest: [verifyJWT] }, remove) + app.delete('/user', { onRequest: [verifyJWT] }, remove) app.post('/auth/login', authenticate) app.patch('/auth/refresh', refresh) From 94e366ac1c9b69285b29a9f10f60b44edfdb0d86 Mon Sep 17 00:00:00 2001 From: lucaslinyker Date: Thu, 26 Jun 2025 15:25:10 -0300 Subject: [PATCH 17/22] refact: Adicionar logout ao deletar a conta --- src/http/controllers/users/remove.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/http/controllers/users/remove.ts b/src/http/controllers/users/remove.ts index 093d291..b774e3c 100644 --- a/src/http/controllers/users/remove.ts +++ b/src/http/controllers/users/remove.ts @@ -3,6 +3,8 @@ import type { FastifyReply, FastifyRequest } from 'fastify' import { UserNotExistsError } from '@/services/errors/user-not-exists-error' import { makeRemoveService } from '@/services/factories/make-remove-service' +import { logout } from './logout' + export async function remove(request: FastifyRequest, reply: FastifyReply) { const id = request.user.sub @@ -10,6 +12,8 @@ export async function remove(request: FastifyRequest, reply: FastifyReply) { const removeService = makeRemoveService() await removeService.execute({ id }) + + await logout(request, reply) } catch (err) { if (err instanceof UserNotExistsError) { return reply.status(404).send({ message: err.message }) From 387754737230772b48ab986ebb8aa266d9b0a7ac Mon Sep 17 00:00:00 2001 From: lucaslinyker Date: Thu, 26 Jun 2025 16:32:52 -0300 Subject: [PATCH 18/22] =?UTF-8?q?refact:=20Adicionar=20verifica=C3=A7?= =?UTF-8?q?=C3=A3o=20para=20o=20token=20existir?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/http/controllers/users/refresh.ts | 6 +++++- src/http/middlewares/verify-user-role.ts | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/http/controllers/users/refresh.ts b/src/http/controllers/users/refresh.ts index 4784efd..b3bbcbb 100644 --- a/src/http/controllers/users/refresh.ts +++ b/src/http/controllers/users/refresh.ts @@ -1,7 +1,11 @@ import type { FastifyReply, FastifyRequest } from 'fastify' export async function refresh(request: FastifyRequest, reply: FastifyReply) { - await request.jwtVerify({ onlyCookie: true }) + try { + await request.jwtVerify({ onlyCookie: true }) + } catch (err) { + return reply.status(401).send({ message: 'Unauthorized.' }) + } const { role } = request.user diff --git a/src/http/middlewares/verify-user-role.ts b/src/http/middlewares/verify-user-role.ts index b7276d1..d57d605 100644 --- a/src/http/middlewares/verify-user-role.ts +++ b/src/http/middlewares/verify-user-role.ts @@ -10,7 +10,11 @@ const roleHierarchy: Record = { export function verifyUserRole(roleToVerify: Role) { return async (request: FastifyRequest, reply: FastifyReply) => { - await request.jwtVerify() + try { + await request.jwtVerify() + } catch (err) { + return reply.status(401).send({ message: 'Unauthorized.' }) + } const { role } = request.user const allowedRoles = roleHierarchy[role] From 5096e2b73305954b2aae00f1005cedf4260d75a5 Mon Sep 17 00:00:00 2001 From: lucaslinyker Date: Sat, 28 Jun 2025 15:25:07 -0300 Subject: [PATCH 19/22] feat: Habilitar CORS --- package-lock.json | 21 +++++++++++++++++++++ package.json | 3 ++- src/app.ts | 21 +++++++++++++++++++-- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index cb690ce..00f0733 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "@fastify/cookie": "^11.0.2", + "@fastify/cors": "^11.0.1", "@fastify/jwt": "^9.1.0", "@prisma/client": "^6.4.1", "bcryptjs": "^3.0.2", @@ -851,6 +852,26 @@ "fastify-plugin": "^5.0.0" } }, + "node_modules/@fastify/cors": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@fastify/cors/-/cors-11.0.1.tgz", + "integrity": "sha512-dmZaE7M1f4SM8ZZuk5RhSsDJ+ezTgI7v3HHRj8Ow9CneczsPLZV6+2j2uwdaSLn8zhTv6QV0F4ZRcqdalGx1pQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT", + "dependencies": { + "fastify-plugin": "^5.0.0", + "toad-cache": "^3.7.0" + } + }, "node_modules/@fastify/error": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@fastify/error/-/error-4.0.0.tgz", diff --git a/package.json b/package.json index 6f8ab0d..bd8d37e 100644 --- a/package.json +++ b/package.json @@ -35,11 +35,12 @@ }, "dependencies": { "@fastify/cookie": "^11.0.2", + "@fastify/cors": "^11.0.1", "@fastify/jwt": "^9.1.0", "@prisma/client": "^6.4.1", - "fastify": "^5.3.2", "bcryptjs": "^3.0.2", "dotenv": "^16.5.0", + "fastify": "^5.3.2", "zod": "^3.24.2" } } diff --git a/src/app.ts b/src/app.ts index 3479d02..48cbf3d 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,5 +1,6 @@ -import fastifyCookie from '@fastify/cookie' -import fastifyJwt from '@fastify/jwt' +import { fastifyCookie } from '@fastify/cookie' +import { fastifyCors } from '@fastify/cors' +import { fastifyJwt } from '@fastify/jwt' import fastify, { type FastifyReply } from 'fastify' import { ZodError } from 'zod' import { env } from './env' @@ -8,6 +9,22 @@ import { appRoutes } from './http/controllers/routes' export const app = fastify() +app.register(fastifyCors, { + origin: (origin, cb) => { + const allowedOrigins = [ + 'http://localhost:5500', + 'https://mlkp1.github.io/Front2/', + ] + if (!origin || allowedOrigins.includes(origin)) { + cb(null, true) + return + } + cb(new Error('Not allowed'), false) + }, + credentials: true, + methods: '*', +}) + app.get('/', (_, reply: FastifyReply) => { return reply.status(200).send({ message: 'Hello, World!', From 05be1dc2fd820d3d2bf7de5529c5e052cbcbb4d2 Mon Sep 17 00:00:00 2001 From: lucaslinyker Date: Sun, 29 Jun 2025 23:33:11 -0300 Subject: [PATCH 20/22] fix: Adicionar hash a senhas no seed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit como as senhas não eram armazenas em hash no banco quando criadas no seed, não era possível autenticar com nenhuma conta que foi gerada pelo seed --- prisma/seed.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/prisma/seed.ts b/prisma/seed.ts index 71da612..33f110b 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -1,4 +1,5 @@ import { fakerPT_BR as faker } from '@faker-js/faker' +import { hash } from 'bcryptjs' import { prisma } from '../src/lib/prisma' console.time('time') @@ -16,7 +17,7 @@ async function seed() { data: { email: 'admin@gmail.com', name: 'Admin', - password: 'dnx42697', + password: await hash('dnx42697', 10), role: 'ADMIN', }, }) @@ -29,7 +30,7 @@ async function seed() { data: { name: faker.person.fullName(), email: faker.internet.email(), - password: faker.internet.password(), + password: await hash(faker.internet.password(), 10), createdAt: faker.date.recent({ days: 40 }), updatedAt: faker.date.recent({ days: 30 }), }, From a2bf7cc9c310ef513ea29e6e26c5f150c43cad9b Mon Sep 17 00:00:00 2001 From: lucaslinyker Date: Mon, 30 Jun 2025 00:01:23 -0300 Subject: [PATCH 21/22] =?UTF-8?q?fix:=20Melhorar=20mensagem=20de=20erro=20?= =?UTF-8?q?para=20origem=20n=C3=A3o=20permitida=20no=20CORS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app.ts b/src/app.ts index 48cbf3d..69d6e12 100644 --- a/src/app.ts +++ b/src/app.ts @@ -19,7 +19,7 @@ app.register(fastifyCors, { cb(null, true) return } - cb(new Error('Not allowed'), false) + cb(new Error(`Not allowed from origin ${origin}`), false) }, credentials: true, methods: '*', From 711569fdd6c7e0c95605ef2935d3e5de962fa178 Mon Sep 17 00:00:00 2001 From: lucaslinyker Date: Mon, 30 Jun 2025 00:10:46 -0300 Subject: [PATCH 22/22] fix: Remover barra extra de origem permitida no CORS --- src/app.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/app.ts b/src/app.ts index 69d6e12..1da3e56 100644 --- a/src/app.ts +++ b/src/app.ts @@ -11,10 +11,7 @@ export const app = fastify() app.register(fastifyCors, { origin: (origin, cb) => { - const allowedOrigins = [ - 'http://localhost:5500', - 'https://mlkp1.github.io/Front2/', - ] + const allowedOrigins = ['http://localhost:5500', 'https://mlkp1.github.io'] if (!origin || allowedOrigins.includes(origin)) { cb(null, true) return