diff --git a/.env.example b/.env.example index 293bece..0bac647 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,4 @@ NODE_ENV=dev PORT=3333 DATABASE_URL="postgresql://docker:docker@localhost:8080/orange-db?schema=public" +JWT_SECRET= \ No newline at end of file diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index b816b83..a5a7948 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -31,4 +31,5 @@ jobs: env: DATABASE_URL: "postgresql://docker:docker@localhost:8080/orange-db?schema=public" + JWT_SECRET: "oPedroEhFeraMsmCaraEhDiferenciado" \ No newline at end of file diff --git a/package.json b/package.json index aae5a76..9461d83 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,8 @@ "vitest": "^1.2.1" }, "dependencies": { - "@fastify/cors": "^8.5.0", + "@fastify/cors": "^9.0.0", + "@fastify/jwt": "^8.0.0", "@prisma/client": "5.8.1", "@types/bcryptjs": "^2.4.6", "@types/express": "^4.17.21", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6838931..d66a453 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,8 +6,11 @@ settings: dependencies: '@fastify/cors': - specifier: ^8.5.0 - version: 8.5.0 + specifier: ^9.0.0 + version: 9.0.0 + '@fastify/jwt': + specifier: ^8.0.0 + version: 8.0.0 '@prisma/client': specifier: 5.8.1 version: 5.8.1(prisma@5.8.1) @@ -48,13 +51,13 @@ devDependencies: version: 2.1.0(eslint@8.52.0)(typescript@5.3.3) '@types/node': specifier: ^20.11.6 - version: 20.11.6 + version: 20.11.8 '@types/supertest': specifier: ^6.0.2 version: 6.0.2 '@vitest/coverage-v8': specifier: ^1.2.1 - version: 1.2.1(vitest@1.2.1) + version: 1.2.2(vitest@1.2.2) eslint: specifier: 8.52.0 version: 8.52.0 @@ -75,7 +78,7 @@ devDependencies: version: 5.3.3 vitest: specifier: ^1.2.1 - version: 1.2.1(@types/node@20.11.6) + version: 1.2.2(@types/node@20.11.8) packages: @@ -359,8 +362,8 @@ packages: fast-uri: 2.3.0 dev: false - /@fastify/cors@8.5.0: - resolution: {integrity: sha512-/oZ1QSb02XjP0IK1U0IXktEsw/dUBTxJOW7IpIeO8c/tNalw/KjoNSJv1Sf6eqoBPO+TDGkifq6ynFK3v68HFQ==} + /@fastify/cors@9.0.0: + resolution: {integrity: sha512-KVsBFs2jZHbtN4vI/jJFaeRHXr3htB3koquGD5TwQQt/lmspyrS1a2UOBTlMOC/5hawC81vdoCzmiR03HbjdXg==} dependencies: fastify-plugin: 4.5.1 mnemonist: 0.39.6 @@ -380,6 +383,16 @@ packages: fast-json-stringify: 5.10.0 dev: false + /@fastify/jwt@8.0.0: + resolution: {integrity: sha512-pJHjmZaokteZFMbsVVt7pbyJpbDogTnpl/aD7eR3vLOPgfktp4k4gUM6cd7RtjL/Ol1qDwL5mup+vdNlZI3K0Q==} + dependencies: + '@fastify/error': 3.4.1 + '@lukeed/ms': 2.0.2 + fast-jwt: 3.3.2 + fastify-plugin: 4.5.1 + steed: 1.1.3 + dev: false + /@humanwhocodes/config-array@0.11.14: resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} @@ -449,6 +462,13 @@ packages: '@jridgewell/resolve-uri': 3.1.1 '@jridgewell/sourcemap-codec': 1.4.15 + + /@lukeed/ms@2.0.2: + resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==} + engines: {node: '>=8'} + dev: false + + /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -652,13 +672,13 @@ packages: resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} dependencies: '@types/connect': 3.4.38 - '@types/node': 20.11.6 + '@types/node': 20.11.8 dev: false /@types/connect@3.4.38: resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} dependencies: - '@types/node': 20.11.6 + '@types/node': 20.11.8 dev: false /@types/cookiejar@2.1.5: @@ -671,7 +691,7 @@ packages: /@types/express-serve-static-core@4.17.42: resolution: {integrity: sha512-ckM3jm2bf/MfB3+spLPWYPUH573plBFwpOhqQ2WottxYV85j1HQFlxmnTq57X1yHY9awZPig06hL/cLMgNWHIQ==} dependencies: - '@types/node': 20.11.6 + '@types/node': 20.11.8 '@types/qs': 6.9.11 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -714,8 +734,8 @@ packages: resolution: {integrity: sha512-iJt33IQnVRkqeqC7PzBHPTC6fDlRNRW8vjrgqtScAhrmMwe8c4Eo7+fUGTa+XdWrpEgpyKWMYmi2dIwMAYRzPw==} dev: false - /@types/node@20.11.6: - resolution: {integrity: sha512-+EOokTnksGVgip2PbYbr3xnR7kZigh4LbybAfBAw5BpnQ+FqBYUsvCEjYd70IXKlbohQ64mzEYmMtlWUY8q//Q==} + /@types/node@20.11.8: + resolution: {integrity: sha512-i7omyekpPTNdv4Jb/Rgqg0RU8YqLcNsI12quKSDkRXNfx7Wxdm6HhK1awT3xTgEkgxPn3bvnSpiEAc7a7Lpyow==} dependencies: undici-types: 5.26.5 @@ -735,7 +755,7 @@ packages: resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} dependencies: '@types/mime': 1.3.5 - '@types/node': 20.11.6 + '@types/node': 20.11.8 dev: false /@types/serve-static@1.15.5: @@ -743,7 +763,7 @@ packages: dependencies: '@types/http-errors': 2.0.4 '@types/mime': 3.0.4 - '@types/node': 20.11.6 + '@types/node': 20.11.8 dev: false /@types/superagent@8.1.3: @@ -751,7 +771,7 @@ packages: dependencies: '@types/cookiejar': 2.1.5 '@types/methods': 1.1.4 - '@types/node': 20.11.6 + '@types/node': 20.11.8 dev: true /@types/supertest@6.0.2: @@ -895,8 +915,8 @@ packages: resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} dev: true - /@vitest/coverage-v8@1.2.1(vitest@1.2.1): - resolution: {integrity: sha512-fJEhKaDwGMZtJUX7BRcGxooGwg1Hl0qt53mVup/ZJeznhvL5EodteVnb/mcByhEcvVWbK83ZF31c7nPEDi4LOQ==} + /@vitest/coverage-v8@1.2.2(vitest@1.2.2): + resolution: {integrity: sha512-IHyKnDz18SFclIEEAHb9Y4Uxx0sPKC2VO1kdDCs1BF6Ip4S8rQprs971zIsooLUn7Afs71GRxWMWpkCGZpRMhw==} peerDependencies: vitest: ^1.0.0 dependencies: @@ -913,43 +933,43 @@ packages: std-env: 3.7.0 test-exclude: 6.0.0 v8-to-istanbul: 9.2.0 - vitest: 1.2.1(@types/node@20.11.6) + vitest: 1.2.2(@types/node@20.11.8) transitivePeerDependencies: - supports-color dev: true - /@vitest/expect@1.2.1: - resolution: {integrity: sha512-/bqGXcHfyKgFWYwIgFr1QYDaR9e64pRKxgBNWNXPefPFRhgm+K3+a/dS0cUGEreWngets3dlr8w8SBRw2fCfFQ==} + /@vitest/expect@1.2.2: + resolution: {integrity: sha512-3jpcdPAD7LwHUUiT2pZTj2U82I2Tcgg2oVPvKxhn6mDI2On6tfvPQTjAI4628GUGDZrCm4Zna9iQHm5cEexOAg==} dependencies: - '@vitest/spy': 1.2.1 - '@vitest/utils': 1.2.1 + '@vitest/spy': 1.2.2 + '@vitest/utils': 1.2.2 chai: 4.4.1 dev: true - /@vitest/runner@1.2.1: - resolution: {integrity: sha512-zc2dP5LQpzNzbpaBt7OeYAvmIsRS1KpZQw4G3WM/yqSV1cQKNKwLGmnm79GyZZjMhQGlRcSFMImLjZaUQvNVZQ==} + /@vitest/runner@1.2.2: + resolution: {integrity: sha512-JctG7QZ4LSDXr5CsUweFgcpEvrcxOV1Gft7uHrvkQ+fsAVylmWQvnaAr/HDp3LAH1fztGMQZugIheTWjaGzYIg==} dependencies: - '@vitest/utils': 1.2.1 + '@vitest/utils': 1.2.2 p-limit: 5.0.0 pathe: 1.1.2 dev: true - /@vitest/snapshot@1.2.1: - resolution: {integrity: sha512-Tmp/IcYEemKaqAYCS08sh0vORLJkMr0NRV76Gl8sHGxXT5151cITJCET20063wk0Yr/1koQ6dnmP6eEqezmd/Q==} + /@vitest/snapshot@1.2.2: + resolution: {integrity: sha512-SmGY4saEw1+bwE1th6S/cZmPxz/Q4JWsl7LvbQIky2tKE35US4gd0Mjzqfr84/4OD0tikGWaWdMja/nWL5NIPA==} dependencies: magic-string: 0.30.5 pathe: 1.1.2 pretty-format: 29.7.0 dev: true - /@vitest/spy@1.2.1: - resolution: {integrity: sha512-vG3a/b7INKH7L49Lbp0IWrG6sw9j4waWAucwnksPB1r1FTJgV7nkBByd9ufzu6VWya/QTvQW4V9FShZbZIB2UQ==} + /@vitest/spy@1.2.2: + resolution: {integrity: sha512-k9Gcahssw8d7X3pSLq3e3XEu/0L78mUkCjivUqCQeXJm9clfXR/Td8+AP+VC1O6fKPIDLcHDTAmBOINVuv6+7g==} dependencies: tinyspy: 2.2.0 dev: true - /@vitest/utils@1.2.1: - resolution: {integrity: sha512-bsH6WVZYe/J2v3+81M5LDU8kW76xWObKIURpPrOXm2pjBniBu2MERI/XP60GpS4PHU3jyK50LUutOwrx4CyHUg==} + /@vitest/utils@1.2.2: + resolution: {integrity: sha512-WKITBHLsBHlpjnDQahr+XK6RE7MiAsgrIkr0pGhQ9ygoxBfUeG0lUG5iLlzqjmKSlBv3+j5EGsriBzh+C3Tq9g==} dependencies: diff-sequences: 29.6.3 estree-walker: 3.0.3 @@ -1154,6 +1174,15 @@ packages: resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} dev: true + /asn1.js@5.4.1: + resolution: {integrity: sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==} + dependencies: + bn.js: 4.12.0 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + safer-buffer: 2.1.2 + dev: false + /assertion-error@1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} dev: true @@ -1219,6 +1248,12 @@ packages: engines: {node: '>=8'} dev: false + + /bn.js@4.12.0: + resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} + dev: false + + /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: @@ -1511,6 +1546,14 @@ packages: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} dev: false + + /ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} dev: false @@ -2087,6 +2130,16 @@ packages: rfdc: 1.3.1 dev: false + /fast-jwt@3.3.2: + resolution: {integrity: sha512-H+JYxaFy2LepiC1AQWM/2hzKlQOWaWUkEnu/yebhYu4+ameb3qG77WiRZ1Ct6YBk6d/ESsNguBfTT5+q0XMtKg==} + engines: {node: '>=16 <22'} + dependencies: + '@lukeed/ms': 2.0.2 + asn1.js: 5.4.1 + ecdsa-sig-formatter: 1.0.11 + mnemonist: 0.39.7 + dev: false + /fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} dev: true @@ -2110,6 +2163,13 @@ packages: resolution: {integrity: sha512-eel5UKGn369gGEWOqBShmFJWfq/xSJvsgDzgLYC845GneayWvXBf0lJCBn5qTABfewy1ZDPoaR5OZCP+kssfuw==} dev: false + /fastfall@1.5.1: + resolution: {integrity: sha512-KH6p+Z8AKPXnmA7+Iz2Lh8ARCMr+8WNPVludm1LGkZoD2MjY6LVnRMtTKhkdzI+jr0RzQWXKzKyBJm1zoHEL4Q==} + engines: {node: '>=0.10.0'} + dependencies: + reusify: 1.0.4 + dev: false + /fastify-plugin@4.5.1: resolution: {integrity: sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==} dev: false @@ -2137,11 +2197,27 @@ packages: - supports-color dev: false + + /fastparallel@2.4.1: + resolution: {integrity: sha512-qUmhxPgNHmvRjZKBFUNI0oZuuH9OlSIOXmJ98lhKPxMZZ7zS/Fi0wRHOihDSz0R1YiIOjxzOY4bq65YTcdBi2Q==} + dependencies: + reusify: 1.0.4 + xtend: 4.0.2 + dev: false + /fastq@1.17.0: resolution: {integrity: sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==} dependencies: reusify: 1.0.4 + /fastseries@1.7.2: + resolution: {integrity: sha512-dTPFrPGS8SNSzAt7u/CbMKCJ3s01N04s4JFbORHcmyvVfVKmbhMD1VtRbh5enGHxkaQDqWyLefiKOGGmohGDDQ==} + + dependencies: + reusify: 1.0.4 + xtend: 4.0.2 + dev: false + /file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -2464,7 +2540,6 @@ packages: /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true /internal-slot@1.0.6: resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} @@ -2957,6 +3032,10 @@ packages: engines: {node: '>=12'} dev: true + /minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + dev: false + /minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: @@ -2994,6 +3073,12 @@ packages: obliterator: 2.0.4 dev: false + /mnemonist@0.39.7: + resolution: {integrity: sha512-ix3FwHWZgdXUt0dHM8bCrI4r1KMeYx8bCunPCYmvKXq4tn6gbNsqrsb4q0kDbDqbpIOvEaW5Sn+dmDwGydfrwA==} + dependencies: + obliterator: 2.0.4 + dev: false + /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} @@ -3721,6 +3806,10 @@ packages: engines: {node: '>=10'} dev: false + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: false + /secure-json-parse@2.7.0: resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} dev: false @@ -3874,6 +3963,16 @@ packages: resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} dev: true + /steed@1.1.3: + resolution: {integrity: sha512-EUkci0FAUiE4IvGTSKcDJIQ/eRUP2JJb56+fvZ4sdnguLTqIdKjSxUe138poW8mkvKWXW2sFPrgTsxqoISnmoA==} + dependencies: + fastfall: 1.5.1 + fastparallel: 2.4.1 + fastq: 1.17.0 + fastseries: 1.7.2 + reusify: 1.0.4 + dev: false + /string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -4322,8 +4421,8 @@ packages: spdx-expression-parse: 3.0.1 dev: true - /vite-node@1.2.1(@types/node@20.11.6): - resolution: {integrity: sha512-fNzHmQUSOY+y30naohBvSW7pPn/xn3Ib/uqm+5wAJQJiqQsU0NBR78XdRJb04l4bOFKjpTWld0XAfkKlrDbySg==} + /vite-node@1.2.2(@types/node@20.11.8): + resolution: {integrity: sha512-1as4rDTgVWJO3n1uHmUYqq7nsFgINQ9u+mRcXpjeOMJUmviqNKjcZB7UfRZrlM7MjYXMKpuWp5oGkjaFLnjawg==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true dependencies: @@ -4331,7 +4430,7 @@ packages: debug: 4.3.4 pathe: 1.1.2 picocolors: 1.0.0 - vite: 5.0.12(@types/node@20.11.6) + vite: 5.0.12(@types/node@20.11.8) transitivePeerDependencies: - '@types/node' - less @@ -4359,7 +4458,7 @@ packages: - typescript dev: false - /vite@5.0.12(@types/node@20.11.6): + /vite@5.0.12(@types/node@20.11.8): resolution: {integrity: sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true @@ -4387,7 +4486,7 @@ packages: terser: optional: true dependencies: - '@types/node': 20.11.6 + '@types/node': 20.11.8 esbuild: 0.19.12 postcss: 8.4.33 rollup: 4.9.6 @@ -4395,8 +4494,8 @@ packages: fsevents: 2.3.3 dev: true - /vitest@1.2.1(@types/node@20.11.6): - resolution: {integrity: sha512-TRph8N8rnSDa5M2wKWJCMnztCZS9cDcgVTQ6tsTFTG/odHJ4l5yNVqvbeDJYJRZ6is3uxaEpFs8LL6QM+YFSdA==} + /vitest@1.2.2(@types/node@20.11.8): + resolution: {integrity: sha512-d5Ouvrnms3GD9USIK36KG8OZ5bEvKEkITFtnGv56HFaSlbItJuYr7hv2Lkn903+AvRAgSixiamozUVfORUekjw==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -4420,12 +4519,12 @@ packages: jsdom: optional: true dependencies: - '@types/node': 20.11.6 - '@vitest/expect': 1.2.1 - '@vitest/runner': 1.2.1 - '@vitest/snapshot': 1.2.1 - '@vitest/spy': 1.2.1 - '@vitest/utils': 1.2.1 + '@types/node': 20.11.8 + '@vitest/expect': 1.2.2 + '@vitest/runner': 1.2.2 + '@vitest/snapshot': 1.2.2 + '@vitest/spy': 1.2.2 + '@vitest/utils': 1.2.2 acorn-walk: 8.3.2 cac: 6.7.14 chai: 4.4.1 @@ -4439,8 +4538,8 @@ packages: strip-literal: 1.3.0 tinybench: 2.6.0 tinypool: 0.8.2 - vite: 5.0.12(@types/node@20.11.6) - vite-node: 1.2.1(@types/node@20.11.6) + vite: 5.0.12(@types/node@20.11.8) + vite-node: 1.2.2(@types/node@20.11.8) why-is-node-running: 2.2.2 transitivePeerDependencies: - less diff --git a/src/@types/fastify-jwt.d.ts b/src/@types/fastify-jwt.d.ts new file mode 100644 index 0000000..df76cdc --- /dev/null +++ b/src/@types/fastify-jwt.d.ts @@ -0,0 +1,9 @@ +import '@fastify/jwt' + +declare module '@fastify/jwt' { + export interface FastifyJWT { + user: { + sub: string + } + } +} \ No newline at end of file diff --git a/src/app.ts b/src/app.ts index fe7fbc9..8e6e840 100644 --- a/src/app.ts +++ b/src/app.ts @@ -2,6 +2,8 @@ import fastify from 'fastify' import { userRoutes } from './controller/user/routes' import { env } from './env' import { ZodError } from 'zod' +import { authRoutes } from './controller/session/routes' +import fastifyJwt from '@fastify/jwt' import cors from '@fastify/cors' import { logMiddleware } from './controller/middlewares/logMiddleware' @@ -13,6 +15,13 @@ app.register(cors, { app.register(userRoutes) app.addHook('preHandler', logMiddleware) +app.register(authRoutes) + +app.register(fastifyJwt, { + secret: env.JWT_SECRET, +}) + + app.setErrorHandler((error, _, response) => { if (env.NODE_ENV !== 'production') { console.error(error) diff --git a/src/controller/middlewares/verifyJwt.ts b/src/controller/middlewares/verifyJwt.ts new file mode 100644 index 0000000..c709985 --- /dev/null +++ b/src/controller/middlewares/verifyJwt.ts @@ -0,0 +1,12 @@ +import { FastifyReply, FastifyRequest } from 'fastify' + +export async function verifyJWT( + request: FastifyRequest, + response: FastifyReply, +) { + try { + await request.jwtVerify() + } catch (e) { + return response.status(401).send({ message: 'Unauthorized' }) + } +} \ No newline at end of file diff --git a/src/controller/session/authUser.ts b/src/controller/session/authUser.ts new file mode 100644 index 0000000..c96f5fd --- /dev/null +++ b/src/controller/session/authUser.ts @@ -0,0 +1,34 @@ +import { FastifyReply, FastifyRequest } from 'fastify' +import { AuthUserUseCase } from '../../use-cases/authUserUseCase' +import { z } from 'zod' +import { PrismaUsersRepository } from '../../repositories/prisma/prisma-users-repository' + +export async function authUser( + request: FastifyRequest, + response: FastifyReply, +) { + + const userRepository = new PrismaUsersRepository() + const authUserUseCase = new AuthUserUseCase(userRepository) + + const AuthUserUseCaseSchema = z.object({ + email: z.string().email(), + password: z.string() + }) + + const { email, password } = AuthUserUseCaseSchema.parse(request.body) + + const { user } = await authUserUseCase.execute({ email, password }) + + const token = await response.jwtSign( + {}, + { + sign: { + sub: user.id + }, + }, + ) + + + return response.status(200).send({ user, token }) +} \ No newline at end of file diff --git a/src/controller/session/routes.ts b/src/controller/session/routes.ts new file mode 100644 index 0000000..218c9c3 --- /dev/null +++ b/src/controller/session/routes.ts @@ -0,0 +1,7 @@ +import { FastifyInstance } from 'fastify' +import { authUser } from './authUser' + +export async function authRoutes(app: FastifyInstance) { + + app.post('/login', authUser) +} \ No newline at end of file diff --git a/src/controller/user/routes.ts b/src/controller/user/routes.ts index 941a5ed..7f2c96e 100644 --- a/src/controller/user/routes.ts +++ b/src/controller/user/routes.ts @@ -1,6 +1,7 @@ import { FastifyInstance } from 'fastify' import { getUserById } from './getUserById' import { getUserByEmail } from './getUserByEmail' +import { verifyJWT } from '../middlewares/verifyJwt' import { registerUser } from './registerUser' export async function userRoutes(app: FastifyInstance) { diff --git a/src/env/index.ts b/src/env/index.ts index 08b0b2c..b3f475d 100644 --- a/src/env/index.ts +++ b/src/env/index.ts @@ -5,6 +5,7 @@ const envSchema = z.object({ NODE_ENV: z.enum(['dev', 'test', 'production']).default('dev'), PORT: z.coerce.number().default(3333), DATABASE_URL: z.string(), + JWT_SECRET: z.string() }) const _env = envSchema.safeParse(process.env)