diff --git a/package.json b/package.json index 1b0a8e5..b5f3bf0 100644 --- a/package.json +++ b/package.json @@ -36,12 +36,13 @@ "vite": "^5.0.3" }, "dependencies": { - "lucide-svelte": "^0.462.0", - "multer": "^1.4.5-lts.1", - "svelte-radix": "^2.0.1" "@prisma/client": "^5.22.0", + "@types/jsonwebtoken": "^9.0.7", "@types/node": "^22.10.1", "argon2": "^0.41.1", + "jsonwebtoken": "^9.0.2", + "lucide-svelte": "^0.462.0", + "multer": "^1.4.5-lts.1", "prisma": "^5.22.0", "redis": "^4.7.0", "svelte-radix": "^2.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8cc1f9b..7bf2de0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,21 +8,27 @@ importers: .: dependencies: - lucide-svelte: - specifier: ^0.462.0 - version: 0.462.0(svelte@5.2.7) - multer: - specifier: ^1.4.5-lts.1 - version: 1.4.5-lts.1 '@prisma/client': specifier: ^5.22.0 version: 5.22.0(prisma@5.22.0) + '@types/jsonwebtoken': + specifier: ^9.0.7 + version: 9.0.7 '@types/node': specifier: ^22.10.1 version: 22.10.1 argon2: specifier: ^0.41.1 version: 0.41.1 + jsonwebtoken: + specifier: ^9.0.2 + version: 9.0.2 + lucide-svelte: + specifier: ^0.462.0 + version: 0.462.0(svelte@5.2.7) + multer: + specifier: ^1.4.5-lts.1 + version: 1.4.5-lts.1 prisma: specifier: ^5.22.0 version: 5.22.0 @@ -558,6 +564,9 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/jsonwebtoken@9.0.7': + resolution: {integrity: sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg==} + '@types/node@22.10.1': resolution: {integrity: sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==} @@ -728,6 +737,9 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -847,6 +859,9 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + electron-to-chromium@1.5.64: resolution: {integrity: sha512-IXEuxU+5ClW2IGEYFC2T7szbyVgehupCWQe5GNh+H065CD6U6IFN0s4KeAMFGNmQolRU4IV7zGBWSYMmZ8uuqQ==} @@ -1076,7 +1091,6 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - is-arrayish@0.3.2: resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} @@ -1107,13 +1121,13 @@ packages: is-reference@3.0.3: resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} - - isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -1137,6 +1151,16 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + jsonwebtoken@9.0.2: + resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} + engines: {node: '>=12', npm: '>=6'} + + jwa@1.4.1: + resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} + + jws@3.2.2: + resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -1172,9 +1196,30 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} + lodash.includes@4.3.0: + resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} + + lodash.isboolean@3.0.3: + resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} + + lodash.isinteger@4.0.4: + resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} + + lodash.isnumber@3.0.3: + resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.isstring@4.0.1: + resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + lodash.once@4.1.1: + resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + logform@2.7.0: resolution: {integrity: sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==} engines: {node: '>= 12.0.0'} @@ -1505,6 +1550,7 @@ packages: readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} @@ -1546,6 +1592,7 @@ packages: safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -1584,11 +1631,12 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} + stack-trace@0.0.10: + resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} + streamsearch@1.1.0: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} engines: {node: '>=10.0.0'} - stack-trace@0.0.10: - resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} @@ -1600,6 +1648,7 @@ packages: string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} @@ -1823,6 +1872,7 @@ packages: xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} + yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} @@ -2210,6 +2260,10 @@ snapshots: '@types/json-schema@7.0.15': {} + '@types/jsonwebtoken@9.0.7': + dependencies: + '@types/node': 22.10.1 + '@types/node@22.10.1': dependencies: undici-types: 6.20.0 @@ -2393,6 +2447,8 @@ snapshots: node-releases: 2.0.18 update-browserslist-db: 1.1.1(browserslist@4.24.2) + buffer-equal-constant-time@1.0.1: {} + buffer-from@1.1.2: {} busboy@1.6.0: @@ -2498,6 +2554,10 @@ snapshots: eastasianwidth@0.2.0: {} + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 + electron-to-chromium@1.5.64: {} emoji-regex@8.0.0: {} @@ -2782,9 +2842,10 @@ snapshots: dependencies: '@types/estree': 1.0.6 - isarray@1.0.0: {} is-stream@2.0.1: {} + isarray@1.0.0: {} + isexe@2.0.0: {} jackspeak@3.4.3: @@ -2805,6 +2866,30 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} + jsonwebtoken@9.0.2: + 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.1.1 + ms: 2.1.3 + semver: 7.6.3 + + jwa@1.4.1: + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + + jws@3.2.2: + dependencies: + jwa: 1.4.1 + safe-buffer: 5.2.1 + keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -2832,8 +2917,22 @@ snapshots: dependencies: p-locate: 5.0.0 + 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.merge@4.6.2: {} + lodash.once@4.1.1: {} + logform@2.7.0: dependencies: '@colors/colors': 1.6.0 @@ -3075,9 +3174,12 @@ snapshots: process-nextick-args: 2.0.1 safe-buffer: 5.1.2 string_decoder: 1.1.1 + util-deprecate: 1.0.2 + readable-stream@3.6.2: dependencies: inherits: 2.0.4 + string_decoder: 1.3.0 util-deprecate: 1.0.2 readdirp@3.6.0: @@ -3138,6 +3240,7 @@ snapshots: mri: 1.2.0 safe-buffer@5.1.2: {} + safe-buffer@5.2.1: {} safe-stable-stringify@2.5.0: {} @@ -3166,9 +3269,10 @@ snapshots: source-map-js@1.2.1: {} - streamsearch@1.1.0: {} stack-trace@0.0.10: {} + streamsearch@1.1.0: {} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -3184,6 +3288,7 @@ snapshots: string_decoder@1.1.1: dependencies: safe-buffer: 5.1.2 + string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 @@ -3422,6 +3527,7 @@ snapshots: strip-ansi: 7.1.0 xtend@4.0.2: {} + yallist@4.0.0: {} yaml@1.10.2: {} diff --git a/src/app.d.ts b/src/app.d.ts index da08e6d..5076ab9 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -3,7 +3,10 @@ declare global { namespace App { // interface Error {} - // interface Locals {} + interface Locals { + token?: string; + userId?: string; + } // interface PageData {} // interface PageState {} // interface Platform {} diff --git a/src/hooks.server.ts b/src/hooks.server.ts new file mode 100644 index 0000000..38762b9 --- /dev/null +++ b/src/hooks.server.ts @@ -0,0 +1,7 @@ +import type { Handle } from '@sveltejs/kit'; + +export const handle: Handle = async ({ event, resolve }) => { + event.locals.token = await event.cookies.get('token'); + + return await resolve(event); +}; \ No newline at end of file diff --git a/src/routes/+layout.server.ts b/src/routes/+layout.server.ts new file mode 100644 index 0000000..3ce69be --- /dev/null +++ b/src/routes/+layout.server.ts @@ -0,0 +1,11 @@ +import { redirect } from '@sveltejs/kit'; + +export async function load({ locals, url }) { + const token = locals.token; + + if (token == undefined && url.pathname !== "/") { + redirect(301, "/"); + } + + return { token } +} \ No newline at end of file diff --git a/src/routes/+page.server.ts b/src/routes/+page.server.ts index fcf0a3f..5f0c7a7 100644 --- a/src/routes/+page.server.ts +++ b/src/routes/+page.server.ts @@ -1,82 +1,65 @@ import { type Actions } from '@sveltejs/kit'; -import prismaClient from '$lib/prismaClient'; -import * as argon2 from 'argon2'; import { redirect, error } from '@sveltejs/kit'; import logger from '$lib/logger'; +export async function load({locals}) { + if (locals.token != undefined) { + redirect(302, "/chats") + } +} + export const actions: Actions = { - login: async ({request}) => { + login: async ({request, fetch, cookies}) => { const formData = await request.formData(); - // @ts-ignore Can't be empty - const username = formData.get('username').toString(); - - // @ts-ignore Can't be empty - const password = formData.get('password').toString(); - - const user = await prismaClient.user.findFirst({ - where: { - username: username, - } + const response = await fetch('/api/auth/login', { + method: "POST", + body: formData }); - if (user == null) { - return error(400, {message: "Nom d'utilisateur ou mot de passe invalide."}); - } + const data = await response.json(); - try { - // @ts-ignore Already checked for null - if (await argon2.verify(user.password, password)) { - logger.log("info", "saijdazji") - logger.log("debug", "saijdazji") - } else { - return error(400, {message: "Nom d'utilisateur ou mot de passe invalide."}); - } - // eslint-disable-next-line @typescript-eslint/no-unused-vars - } catch (e) { - return error(500, {message: "Erreur interne."}) + if (response.ok) { + cookies.set('token', data.token, { + path: '/', + httpOnly: true, + sameSite: 'strict', + maxAge: (60 * 60) * 30, + }); + + logger.debug("Successfully created a cookie for the user and proceeded with the login.") + + return redirect(302, "/chats"); + } else { + + return error(400, data.message); } }, - register: async ({request}) => { + register: async ({request, fetch, cookies}) => { const formData = await request.formData(); - // @ts-ignore Can't be empty - const username = formData.get('username').toString(); - // @ts-ignore Can't be empty - const email = formData.get('email').toString(); - // @ts-ignore Can't be empty - const password = formData.get('password').toString(); - - const user = await prismaClient.user.findFirst({ - where: { - OR: [ - { - email: email - }, - { - username: username - } - ] - } + const response = await fetch('/api/auth/register', { + method: "POST", + body: formData }); - if (user != null) { - return error(400, { message: "Un compte avec cette email ou nom d'utilisateur éxiste déjà." }); + const data = await response.json(); + + if (response.ok) { + cookies.set('token', data.token, { + path: '/', + httpOnly: true, + sameSite: 'strict', + maxAge: (60 * 60) * 30, + }); + + logger.debug("Successfully created a cookie for the user and proceeded with the register.") + + return redirect(302, "/chats"); + } else { + + return error(400, data.message); } - - const hash = await argon2.hash(password); - - await prismaClient.user.create({ - data: { - email: email, - username: username, - name: "", - surname: "", - password: hash, - } - }); - - return redirect(302, "/chat"); } } \ No newline at end of file diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 0e07cbf..1c48e5d 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -25,8 +25,8 @@