From 431c77f9707f077e21878930881abd971045e0fb Mon Sep 17 00:00:00 2001 From: Bilal Dieumegard Date: Wed, 27 Nov 2024 18:09:42 +0100 Subject: [PATCH 1/7] Ajouts des models et de l'api avec gestion du cache --- package.json | 3 + src/lib/prismaClient.ts | 4 + src/lib/redisClient.ts | 11 ++ src/routes/api/canal/[id]/+server.js.ts | 123 +++++++++++++++ src/routes/api/canal/[id]/messages/+server.ts | 149 ++++++++++++++++++ src/routes/api/canals/+server.ts | 47 ++++++ src/routes/api/user/[id]/+server.ts | 108 +++++++++++++ src/routes/api/users/+server.ts | 27 ++++ 8 files changed, 472 insertions(+) create mode 100644 src/lib/prismaClient.ts create mode 100644 src/lib/redisClient.ts create mode 100644 src/routes/api/canal/[id]/+server.js.ts create mode 100644 src/routes/api/canal/[id]/messages/+server.ts create mode 100644 src/routes/api/canals/+server.ts create mode 100644 src/routes/api/user/[id]/+server.ts create mode 100644 src/routes/api/users/+server.ts diff --git a/package.json b/package.json index fb08de5..b8e0281 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,9 @@ "vite": "^5.0.3" }, "dependencies": { + "@prisma/client": "^5.22.0", + "prisma": "^5.22.0", + "redis": "^4.7.0", "svelte-radix": "^2.0.1" } } diff --git a/src/lib/prismaClient.ts b/src/lib/prismaClient.ts new file mode 100644 index 0000000..031acc8 --- /dev/null +++ b/src/lib/prismaClient.ts @@ -0,0 +1,4 @@ +import { PrismaClient } from '@prisma/client'; + +const prisma = new PrismaClient(); +export default prisma; \ No newline at end of file diff --git a/src/lib/redisClient.ts b/src/lib/redisClient.ts new file mode 100644 index 0000000..739c27b --- /dev/null +++ b/src/lib/redisClient.ts @@ -0,0 +1,11 @@ +import redis from 'redis'; + +const client = redis.createClient({ + url: process.env.REDIS_URL || 'redis://localhost:6379', +}); + +client.on('error', (err) => console.error('Redis Error:', err)); + +await client.connect(); + +export default client; diff --git a/src/routes/api/canal/[id]/+server.js.ts b/src/routes/api/canal/[id]/+server.js.ts new file mode 100644 index 0000000..cfdb6f3 --- /dev/null +++ b/src/routes/api/canal/[id]/+server.js.ts @@ -0,0 +1,123 @@ +import { json } from '@sveltejs/kit'; +import prisma from '$lib/prismaClient'; +import redisClient from '$lib/redisClient'; // Assurez-vous d'importer le client Redis + +// Récupérer les informations du canal et le dernier message (avec cache Redis) +export async function GET({ params }) { + const canalId = parseInt(params.id); + + // Clé cache pour les informations du canal et le dernier message + const canalCacheKey = `canal:${canalId}:info`; + + try { + // Vérifier si les informations du canal et le dernier message sont dans le cache Redis + const cachedCanalData = await redisClient.get(canalCacheKey); + if (cachedCanalData) { + console.log('✅ Cache hit pour les informations du canal et le dernier message'); + return json(JSON.parse(cachedCanalData)); + } + + console.log('❌ Cache miss'); + // Si non, récupérer les informations du canal et le dernier message depuis Prisma + const canal = await prisma.canal.findUnique({ + where: { id: canalId }, + include: { + users: true, // Inclut les utilisateurs associés au canal + }, + }); + + if (!canal) { + return json({ error: 'Canal non trouvé' }, { status: 404 }); + } + + // Récupérer le dernier message + const lastMessage = await prisma.message.findFirst({ + where: { canalId }, + include: { + user: { select: { id: true, pseudo: true } }, + }, + orderBy: { createdAt: 'desc' }, // Trie par date décroissante, donc le dernier message est récupéré en premier + }); + + // Créer un objet combiné pour le canal et le dernier message + const canalData = { + canal, + lastMessage, // Inclure uniquement le dernier message + }; + + // Mettre en cache les informations du canal et le dernier message pendant 5 minutes + await redisClient.set(canalCacheKey, JSON.stringify(canalData), 'EX', 300); // Cache pendant 5 minutes + + console.log('❌ Cache miss - Mise en cache des résultats'); + return json(canalData); + } catch (err) { + console.error(err); + return json({ error: 'Erreur lors de la récupération du canal ou du dernier message' }, { status: 500 }); + } +} + +// Supprimer un canal et invalider le cache associé +export async function DELETE({ params }) { + const canalId = parseInt(params.id); + + try { + // Supprimer le canal de la base de données + await prisma.canal.delete({ + where: { id: canalId }, + }); + + // Invalider le cache + await redisClient.del(`canal:${canalId}:info`); + + return json({ message: 'Canal supprimé avec succès' }); + } catch (err) { + console.error(err); + return json({ error: 'Erreur lors de la suppression du canal' }, { status: 500 }); + } +} + +// Modifier un canal +export async function PUT({ params, request }) { + const canalId = parseInt(params.id); + const { nom, domaine } = await request.json(); // On suppose que ce sont les champs à mettre à jour + + // Clé cache pour les informations du canal et le dernier message + const canalCacheKey = `canal:${canalId}:info`; + + try { + // Mettre à jour les informations du canal dans la base de données + const updatedCanal = await prisma.canal.update({ + where: { id: canalId }, + data: { + nom, // Nom du canal + domaine, // Domaine du canal + }, + include: { + users: true, // Inclut les utilisateurs associés au canal + }, + }); + + // Récupérer le dernier message associé au canal après mise à jour + const lastMessage = await prisma.message.findFirst({ + where: { canalId }, + include: { + user: { select: { id: true, pseudo: true } }, + }, + orderBy: { createdAt: 'desc' }, + }); + + // Créer un objet combiné pour les nouvelles informations du canal et le dernier message + const canalData = { + canal: updatedCanal, + lastMessage, // Inclure uniquement le dernier message + }; + + // Mettre en cache les nouvelles informations pendant 5 minutes + await redisClient.set(canalCacheKey, JSON.stringify(canalData), 'EX', 60 * 5); // Cache pendant 5 minutes + + return json(canalData); + } catch (err) { + console.error(err); + return json({ error: 'Erreur lors de la mise à jour du canal' }, { status: 500 }); + } +} diff --git a/src/routes/api/canal/[id]/messages/+server.ts b/src/routes/api/canal/[id]/messages/+server.ts new file mode 100644 index 0000000..9fd337b --- /dev/null +++ b/src/routes/api/canal/[id]/messages/+server.ts @@ -0,0 +1,149 @@ +import { json } from '@sveltejs/kit'; +import prisma from '$lib/prismaClient'; +import redisClient from '$lib/redisClient'; // Assure-toi d'importer ton client Redis + +export async function GET({ params, url }) { + const canalId = parseInt(params.id); + + // Gestion de la pagination avec des paramètres optionnels `page` et `limit` + const page = parseInt(url.searchParams.get('page')) || 1; + const limit = parseInt(url.searchParams.get('limit')) || 10; + const offset = (page - 1) * limit; + + // Générer une clé cache Redis unique en fonction du canal et des paramètres de pagination + const cacheKey = `canal:${canalId}:messages:page:${page}:limit:${limit}`; + + try { + // 1. Vérifier si les messages sont déjà dans le cache Redis + const cachedMessages = await redisClient.get(cacheKey); + if (cachedMessages) { + console.log('✅ Cache hit'); + return json(JSON.parse(cachedMessages)); // Si les données sont en cache, les retourner + } + + // 2. Si les messages ne sont pas en cache, récupérer depuis la base de données + const messages = await prisma.message.findMany({ + where: { canalId }, + include: { + user: { + select: { id: true, pseudo: true }, // Inclut uniquement l’ID et le pseudo de l’utilisateur + }, + }, + orderBy: { + createdAt: 'asc', // Trie par date croissante + }, + skip: offset, + take: limit, + }); + + // 3. Compter le nombre total de messages pour la pagination + const totalMessages = await prisma.message.count({ + where: { canalId }, + }); + + const response = { + messages, + pagination: { + page, + limit, + totalMessages, + totalPages: Math.ceil(totalMessages / limit), + }, + }; + + // 4. Mettre en cache les messages avec une expiration (par exemple 5 minutes) + await redisClient.set(cacheKey, JSON.stringify(response), 'EX', 60 * 5); // Cache pendant 5 minutes + + console.log('❌ Cache miss - Mise en cache des résultats'); + return json(response); // Retourner les données récupérées + } catch (err) { + console.error(err); + return json({ error: 'Erreur lors de la récupération des messages' }, { status: 500 }); + } +} + +export async function POST({ params, request }) { + const canalId = parseInt(params.id); + const { userId, text } = await request.json(); + + try { + // Créer un nouveau message dans la base de données + const newMessage = await prisma.message.create({ + data: { + userId, + canalId, + text, + }, + include: { user: { select: { id: true, pseudo: true } } }, + }); + + updateCaches(); // Mettre à jour les caches après la création d’un nouveau message + + return json(newMessage, { status: 201 }); + } catch (err) { + console.error(err); + return json({ error: 'Erreur lors de la création du message' }, { status: 500 }); + } +} + +export async function DELETE({ params }) { + const messageId = parseInt(params.id); + + try { + // Supprimer le message de la base de données + await prisma.message.delete({ + where: { id: messageId }, + }); + + updateCaches(); // Mettre à jour les caches après la suppression d’un message + + return json({ message: 'Message supprimé avec succès' }); + } catch (err) { + console.error(err); + return json({ error: 'Erreur lors de la suppression du message' }, { status: 500 }); + } +} + +// Fonction pour mettre à jour tous les caches des messages +function updateCaches(canalId) { + // Mettre à jour tous les caches + // Mettre à jour toutes les pages dans le cache + let page : number = 1; + let limit : number = 10; + let offset : number = (page - 1) * limit; + while (true) { + const cacheKey = `canal:${canalId}:messages:page:${page}:limit:${limit}`; + const cachedMessages = await redisClient.get(cacheKey); + if (!cachedMessages) { + break; + } + const totalMessages = await prisma.message.count({ + where: { canalId }, + }); + const messages = await prisma.message.findMany({ + where: { canalId }, + include: { + user: { + select: { id: true, pseudo: true }, + }, + }, + orderBy: { + createdAt: 'asc', + }, + skip: offset, + take: limit, + }); + const response = { + messages, + pagination: { + page, + limit, + totalMessages, + totalPages: Math.ceil(totalMessages / limit), + }, + }; + await redisClient.set(cacheKey, JSON.stringify(response), 'EX', 60 * 5); + page++; + offset = (page - 1) * limit; + } +} diff --git a/src/routes/api/canals/+server.ts b/src/routes/api/canals/+server.ts new file mode 100644 index 0000000..b154366 --- /dev/null +++ b/src/routes/api/canals/+server.ts @@ -0,0 +1,47 @@ +import { json } from '@sveltejs/kit'; +import prisma from '$lib/prismaClient'; +import redisClient from '$lib/redisClient'; + +// GET: Liste tous les canaux +export async function GET() { + try { + const cachedCanaux = await redisClient.get('canaux'); + if (cachedCanaux) { + console.log('✅ Cache hit'); + return json(JSON.parse(cachedCanaux)); + } + + console.log('❌ Cache miss'); + const canaux = await prisma.canal.findMany({ + include: { users: true, messages: true }, // Inclut les relations + }); + + await redisClient.set('canaux', JSON.stringify(canaux), { EX: 600 }); // Met en cache + return json(canaux); + } catch (err) { + console.error(err); + return json({ error: 'Erreur serveur' }, { status: 500 }); + } +} + +export async function POST({ request }) { + const { nom, domaine, userIds } = await request.json(); + + try { + const canal = await prisma.canal.create({ + data: { + nom, + domaine, + users: { + connect: userIds.map((id) => ({ id })), // Associe des utilisateurs au canal + }, + }, + }); + + return json(canal, { status: 201 }); + } catch (err) { + console.error(err); + return json({ error: 'Erreur lors de la création du canal' }, { status: 500 }); + } +} + diff --git a/src/routes/api/user/[id]/+server.ts b/src/routes/api/user/[id]/+server.ts new file mode 100644 index 0000000..fed07c3 --- /dev/null +++ b/src/routes/api/user/[id]/+server.ts @@ -0,0 +1,108 @@ +import { json } from '@sveltejs/kit'; +import redisClient from '$lib/redisClient'; +import prisma from '$lib/prismaClient'; + +export async function GET({ params }) { + const userId = params.id; + + try { + // Vérifier si l'utilisateur est dans le cache Redis + const cachedUser = await redisClient.get(`user:${userId}`); + if (cachedUser) { + console.log('✅ Cache hit'); + return json(JSON.parse(cachedUser)); + } + + console.log('❌ Cache miss'); + // Si non, récupérer depuis MongoDB via Prisma + const user = await prisma.user.findUnique({ + where: { id: parseInt(userId) }, + }); + + if (!user) { + return json({ error: 'Utilisateur non trouvé' }, { status: 404 }); + } + + // Mettre l'utilisateur en cache + await redisClient.set(`user:${userId}`, JSON.stringify(user), { EX: 3600 }); + + return json(user); + } catch (err) { + console.error(err); + return json({ error: 'Erreur serveur' }, { status: 500 }); + } +} + +export async function POST({ request }) { + const { pseudo, nom, prenom, email, password } = await request.json(); + + try { + const user = await prisma.user.create({ + data: { + pseudo, + nom, + prenom, + email, + password, + }, + }); + + // Mettre le nouvel utilisateur dans le cache + await redisClient.set(`user:${user.id}`, JSON.stringify(user), { EX: 3600 }); + + return json(user, { status: 201 }); + } catch (err) { + console.error(err); + return json({ error: 'Erreur lors de la création de l’utilisateur' }, { status: 500 }); + } +} + +// Mettre à jour un utilisateur avec PUT +export async function PUT({ params, request }) { + const userId = parseInt(params.id); + const { pseudo, nom, prenom, email, password } = await request.json(); // Assurez-vous d'envoyer tous les champs nécessaires dans le body + + try { + // Mettre à jour l'utilisateur dans la base de données + const updatedUser = await prisma.user.update({ + where: { id: userId }, + data: { + pseudo, + nom, + prenom, + email, + password, // Attention à ne pas oublier de sécuriser le mot de passe avec bcrypt ou une autre méthode + }, + }); + + // Mettre à jour l'utilisateur dans le cache Redis + await redisClient.set(`user:${userId}`, JSON.stringify(updatedUser), 'EX', 3600); // Cache pendant 1 heure (3600 secondes) + + return json(updatedUser); + } catch (err) { + console.error(err); + return json({ error: 'Erreur lors de la mise à jour de l’utilisateur' }, { status: 500 }); + } +} + + +export async function DELETE({ params }) { + const userId = parseInt(params.id); + + try { + await prisma.user.delete({ + where: { id: userId }, + }); + + // Supprimer l'utilisateur du cache Redis + await redisClient.del(`user:${userId}`); + + return json({ message: 'Utilisateur supprimé avec succès' }); + } catch (err) { + console.error(err); + return json({ error: 'Erreur lors de la suppression de l’utilisateur' }, { status: 500 }); + } +} + + + diff --git a/src/routes/api/users/+server.ts b/src/routes/api/users/+server.ts new file mode 100644 index 0000000..0d7b259 --- /dev/null +++ b/src/routes/api/users/+server.ts @@ -0,0 +1,27 @@ +// src/routes/api/users/+server.js +import { json } from '@sveltejs/kit'; +import redisClient from '$lib/redisClient'; +import prisma from '$lib/prismaClient'; + +export async function GET() { + try { + // Vérifier si les utilisateurs sont dans le cache Redis + const cachedUsers = await redisClient.get('users'); + if (cachedUsers) { + console.log('✅ Cache hit'); + return json(JSON.parse(cachedUsers)); + } + + console.log('❌ Cache miss'); + // Sinon, récupérer les utilisateurs depuis MongoDB + const users = await prisma.user.findMany(); + + // Mettre les utilisateurs en cache + await redisClient.set('users', JSON.stringify(users), { EX: 600 }); + + return json(users); + } catch (err) { + console.error(err); + return json({ error: 'Erreur serveur' }, { status: 500 }); + } +} From 1f5342998b8fce7c5c365eb65b29da86bec0524d Mon Sep 17 00:00:00 2001 From: Bilal Dieumegard Date: Wed, 27 Nov 2024 18:10:49 +0100 Subject: [PATCH 2/7] Ajouts des models avec schema.prisma --- prisma/schema.prisma | 49 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 prisma/schema.prisma diff --git a/prisma/schema.prisma b/prisma/schema.prisma new file mode 100644 index 0000000..e3ef7ec --- /dev/null +++ b/prisma/schema.prisma @@ -0,0 +1,49 @@ +// This is your Prisma schema file, +// learn more about it in the docs: https://pris.ly/d/prisma-schema + +// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions? +// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init + +generator client { + provider = "prisma-client-js" +} + +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +model User { + id Int @id @default(autoincrement()) + pseudo String @unique + nom String + prenom String + email String @unique + password String + canaux Canal[] @relation("UserCanaux") + messages Message[] + + @@map("users") // Table name in DB +} + +model Canal { + id Int @id @default(autoincrement()) + nom String + domaine String + users User[] @relation("UserCanaux") + messages Message[] + + @@map("canaux") // Table name in DB +} + +model Message { + id Int @id @default(autoincrement()) + user User @relation(fields: [userId], references: [id]) + userId Int + canal Canal @relation(fields: [canalId], references: [id]) + canalId Int + text String + createdAt DateTime @default(now()) + + @@map("messages") // Table name in DB +} From 22b54827c00126e62248927034fceeb02791cff7 Mon Sep 17 00:00:00 2001 From: Nabil Ould Hamou Date: Sat, 30 Nov 2024 15:21:52 +0100 Subject: [PATCH 3/7] fix: issues in server.ts fix: added @types/node to fix errors due to types missing. fix: prisma.schema to deal with some mongodb specific issues. --- docker-compose.yml | 39 ++++ package.json | 1 + pnpm-lock.yaml | 207 ++++++++++++++++-- prisma/schema.prisma | 42 ++-- src/lib/redisClient.ts | 6 +- .../canal/[id]/{+server.js.ts => +server.ts} | 7 +- 6 files changed, 257 insertions(+), 45 deletions(-) create mode 100644 docker-compose.yml rename src/routes/api/canal/[id]/{+server.js.ts => +server.ts} (95%) diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..4ac470d --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,39 @@ +services: + mongodb: + image: mongo:latest + hostname: mongodb + restart: always + env_file: + - .env + environment: + - MONGO_INITDB_ROOT_USERNAME=temp-root-username + - MONGO_INITDB_ROOT_PASSWORD=temp-password + - MONGO_INITDB_DATABASE=chat_projetweb + ports: + - "27017:27017" + volumes: + - mongo-data:/data/db/ + - mongo-logs:/var/log/mongodb/ + networks: + - mongodb_network + + redis: + image: redis:latest + hostname: redis + restart: always + ports: + - "6379:6379" + command: redis-server --save 20 1 --loglevel warning + volumes: + - redis-data:/data + networks: + - redis_network + +networks: + mongodb_network: + redis_network: + +volumes: + mongo-data: + mongo-logs: + redis-data: \ No newline at end of file diff --git a/package.json b/package.json index b8e0281..036ee8d 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ }, "dependencies": { "@prisma/client": "^5.22.0", + "@types/node": "^22.10.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 80bcfdc..f8244bc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,19 +8,31 @@ importers: .: dependencies: + '@prisma/client': + specifier: ^5.22.0 + version: 5.22.0(prisma@5.22.0) + '@types/node': + specifier: ^22.10.1 + version: 22.10.1 + prisma: + specifier: ^5.22.0 + version: 5.22.0 + redis: + specifier: ^4.7.0 + version: 4.7.0 svelte-radix: specifier: ^2.0.1 version: 2.0.1(svelte@5.2.7) devDependencies: '@sveltejs/adapter-auto': specifier: ^3.0.0 - version: 3.3.1(@sveltejs/kit@2.8.3(@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11))(svelte@5.2.7)(vite@5.4.11)) + version: 3.3.1(@sveltejs/kit@2.8.3(@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11(@types/node@22.10.1)))(svelte@5.2.7)(vite@5.4.11(@types/node@22.10.1))) '@sveltejs/kit': specifier: ^2.0.0 - version: 2.8.3(@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11))(svelte@5.2.7)(vite@5.4.11) + version: 2.8.3(@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11(@types/node@22.10.1)))(svelte@5.2.7)(vite@5.4.11(@types/node@22.10.1)) '@sveltejs/vite-plugin-svelte': specifier: ^4.0.0 - version: 4.0.2(svelte@5.2.7)(vite@5.4.11) + version: 4.0.2(svelte@5.2.7)(vite@5.4.11(@types/node@22.10.1)) autoprefixer: specifier: ^10.4.20 version: 10.4.20(postcss@8.4.49) @@ -77,7 +89,7 @@ importers: version: 8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.7.2) vite: specifier: ^5.0.3 - version: 5.4.11 + version: 5.4.11(@types/node@22.10.1) packages: @@ -339,6 +351,59 @@ packages: '@polka/url@1.0.0-next.28': resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==} + '@prisma/client@5.22.0': + resolution: {integrity: sha512-M0SVXfyHnQREBKxCgyo7sffrKttwE6R8PMq330MIUF0pTwjUhLbW84pFDlf06B27XyCR++VtjugEnIHdr07SVA==} + engines: {node: '>=16.13'} + peerDependencies: + prisma: '*' + peerDependenciesMeta: + prisma: + optional: true + + '@prisma/debug@5.22.0': + resolution: {integrity: sha512-AUt44v3YJeggO2ZU5BkXI7M4hu9BF2zzH2iF2V5pyXT/lRTyWiElZ7It+bRH1EshoMRxHgpYg4VB6rCM+mG5jQ==} + + '@prisma/engines-version@5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2': + resolution: {integrity: sha512-2PTmxFR2yHW/eB3uqWtcgRcgAbG1rwG9ZriSvQw+nnb7c4uCr3RAcGMb6/zfE88SKlC1Nj2ziUvc96Z379mHgQ==} + + '@prisma/engines@5.22.0': + resolution: {integrity: sha512-UNjfslWhAt06kVL3CjkuYpHAWSO6L4kDCVPegV6itt7nD1kSJavd3vhgAEhjglLJJKEdJ7oIqDJ+yHk6qO8gPA==} + + '@prisma/fetch-engine@5.22.0': + resolution: {integrity: sha512-bkrD/Mc2fSvkQBV5EpoFcZ87AvOgDxbG99488a5cexp5Ccny+UM6MAe/UFkUC0wLYD9+9befNOqGiIJhhq+HbA==} + + '@prisma/get-platform@5.22.0': + resolution: {integrity: sha512-pHhpQdr1UPFpt+zFfnPazhulaZYCUqeIcPpJViYoq9R+D/yw4fjE+CtnsnKzPYm0ddUbeXUzjGVGIRVgPDCk4Q==} + + '@redis/bloom@1.2.0': + resolution: {integrity: sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==} + peerDependencies: + '@redis/client': ^1.0.0 + + '@redis/client@1.6.0': + resolution: {integrity: sha512-aR0uffYI700OEEH4gYnitAnv3vzVGXCFvYfdpu/CJKvk4pHfLPEy/JSZyrpQ+15WhXe1yJRXLtfQ84s4mEXnPg==} + engines: {node: '>=14'} + + '@redis/graph@1.1.1': + resolution: {integrity: sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==} + peerDependencies: + '@redis/client': ^1.0.0 + + '@redis/json@1.0.7': + resolution: {integrity: sha512-6UyXfjVaTBTJtKNG4/9Z8PSpKE6XgSyEb8iwaqDcy+uKrd/DGYHTWkUdnQDyzm727V7p21WUMhsqz5oy65kPcQ==} + peerDependencies: + '@redis/client': ^1.0.0 + + '@redis/search@1.2.0': + resolution: {integrity: sha512-tYoDBbtqOVigEDMAcTGsRlMycIIjwMCgD8eR2t0NANeQmgK/lvxNAvYyb6bZDD4frHRhIHkJu2TBRvB0ERkOmw==} + peerDependencies: + '@redis/client': ^1.0.0 + + '@redis/time-series@1.1.0': + resolution: {integrity: sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g==} + peerDependencies: + '@redis/client': ^1.0.0 + '@rollup/rollup-android-arm-eabi@4.27.4': resolution: {integrity: sha512-2Y3JT6f5MrQkICUyRVCw4oa0sutfAsgaSsb0Lmmy1Wi2y7X5vT9Euqw4gOsCyy0YfKURBg35nhUKZS4mDcfULw==} cpu: [arm] @@ -470,6 +535,9 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/node@22.10.1': + resolution: {integrity: sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==} + '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -651,6 +719,10 @@ packages: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} + cluster-key-slot@1.1.2: + resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} + engines: {node: '>=0.10.0'} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -871,6 +943,10 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + generic-pool@3.9.0: + resolution: {integrity: sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==} + engines: {node: '>= 4'} + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -1271,6 +1347,11 @@ packages: prism-svelte@0.4.7: resolution: {integrity: sha512-yABh19CYbM24V7aS7TuPYRNMqthxwbvx6FF/Rw920YbyBWO3tnyPIqRMgHuSVsLmuHkkBS1Akyof463FVdkeDQ==} + prisma@5.22.0: + resolution: {integrity: sha512-vtpjW3XuYCSnMsNVBjLMNkTj6OZbudcPPTPYHqX0CJfpcdWciI1dM8uHETwmDxxiqEwCIE6WvXucWUetJgfu/A==} + engines: {node: '>=16.13'} + hasBin: true + prismjs@1.29.0: resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} engines: {node: '>=6'} @@ -1293,6 +1374,9 @@ packages: resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==} engines: {node: '>= 14.16.0'} + redis@4.7.0: + resolution: {integrity: sha512-zvmkHEAdGMn+hMRXuMBtu4Vo5P6rHQjLoHftu+lBqq8ZTA3RCVC/WzD790bkKKiNFp7d5/9PcSD19fJyyRvOdQ==} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -1471,6 +1555,9 @@ packages: engines: {node: '>=14.17'} hasBin: true + undici-types@6.20.0: + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + unist-util-stringify-position@2.0.3: resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==} @@ -1545,6 +1632,9 @@ packages: resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} engines: {node: '>=12'} + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + yaml@1.10.2: resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} engines: {node: '>= 6'} @@ -1759,6 +1849,57 @@ snapshots: '@polka/url@1.0.0-next.28': {} + '@prisma/client@5.22.0(prisma@5.22.0)': + optionalDependencies: + prisma: 5.22.0 + + '@prisma/debug@5.22.0': {} + + '@prisma/engines-version@5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2': {} + + '@prisma/engines@5.22.0': + dependencies: + '@prisma/debug': 5.22.0 + '@prisma/engines-version': 5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2 + '@prisma/fetch-engine': 5.22.0 + '@prisma/get-platform': 5.22.0 + + '@prisma/fetch-engine@5.22.0': + dependencies: + '@prisma/debug': 5.22.0 + '@prisma/engines-version': 5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2 + '@prisma/get-platform': 5.22.0 + + '@prisma/get-platform@5.22.0': + dependencies: + '@prisma/debug': 5.22.0 + + '@redis/bloom@1.2.0(@redis/client@1.6.0)': + dependencies: + '@redis/client': 1.6.0 + + '@redis/client@1.6.0': + dependencies: + cluster-key-slot: 1.1.2 + generic-pool: 3.9.0 + yallist: 4.0.0 + + '@redis/graph@1.1.1(@redis/client@1.6.0)': + dependencies: + '@redis/client': 1.6.0 + + '@redis/json@1.0.7(@redis/client@1.6.0)': + dependencies: + '@redis/client': 1.6.0 + + '@redis/search@1.2.0(@redis/client@1.6.0)': + dependencies: + '@redis/client': 1.6.0 + + '@redis/time-series@1.1.0(@redis/client@1.6.0)': + dependencies: + '@redis/client': 1.6.0 + '@rollup/rollup-android-arm-eabi@4.27.4': optional: true @@ -1813,14 +1954,14 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.27.4': optional: true - '@sveltejs/adapter-auto@3.3.1(@sveltejs/kit@2.8.3(@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11))(svelte@5.2.7)(vite@5.4.11))': + '@sveltejs/adapter-auto@3.3.1(@sveltejs/kit@2.8.3(@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11(@types/node@22.10.1)))(svelte@5.2.7)(vite@5.4.11(@types/node@22.10.1)))': dependencies: - '@sveltejs/kit': 2.8.3(@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11))(svelte@5.2.7)(vite@5.4.11) + '@sveltejs/kit': 2.8.3(@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11(@types/node@22.10.1)))(svelte@5.2.7)(vite@5.4.11(@types/node@22.10.1)) import-meta-resolve: 4.1.0 - '@sveltejs/kit@2.8.3(@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11))(svelte@5.2.7)(vite@5.4.11)': + '@sveltejs/kit@2.8.3(@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11(@types/node@22.10.1)))(svelte@5.2.7)(vite@5.4.11(@types/node@22.10.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 4.0.2(svelte@5.2.7)(vite@5.4.11) + '@sveltejs/vite-plugin-svelte': 4.0.2(svelte@5.2.7)(vite@5.4.11(@types/node@22.10.1)) '@types/cookie': 0.6.0 cookie: 0.6.0 devalue: 5.1.1 @@ -1834,27 +1975,27 @@ snapshots: sirv: 3.0.0 svelte: 5.2.7 tiny-glob: 0.2.9 - vite: 5.4.11 + vite: 5.4.11(@types/node@22.10.1) - '@sveltejs/vite-plugin-svelte-inspector@3.0.1(@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11))(svelte@5.2.7)(vite@5.4.11)': + '@sveltejs/vite-plugin-svelte-inspector@3.0.1(@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11(@types/node@22.10.1)))(svelte@5.2.7)(vite@5.4.11(@types/node@22.10.1))': dependencies: - '@sveltejs/vite-plugin-svelte': 4.0.2(svelte@5.2.7)(vite@5.4.11) + '@sveltejs/vite-plugin-svelte': 4.0.2(svelte@5.2.7)(vite@5.4.11(@types/node@22.10.1)) debug: 4.3.7 svelte: 5.2.7 - vite: 5.4.11 + vite: 5.4.11(@types/node@22.10.1) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11)': + '@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11(@types/node@22.10.1))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 3.0.1(@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11))(svelte@5.2.7)(vite@5.4.11) + '@sveltejs/vite-plugin-svelte-inspector': 3.0.1(@sveltejs/vite-plugin-svelte@4.0.2(svelte@5.2.7)(vite@5.4.11(@types/node@22.10.1)))(svelte@5.2.7)(vite@5.4.11(@types/node@22.10.1)) debug: 4.3.7 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.13 svelte: 5.2.7 - vite: 5.4.11 - vitefu: 1.0.3(vite@5.4.11) + vite: 5.4.11(@types/node@22.10.1) + vitefu: 1.0.3(vite@5.4.11(@types/node@22.10.1)) transitivePeerDependencies: - supports-color @@ -1868,6 +2009,10 @@ snapshots: '@types/json-schema@7.0.15': {} + '@types/node@22.10.1': + dependencies: + undici-types: 6.20.0 + '@types/unist@2.0.11': {} '@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.7.2))(eslint@9.15.0(jiti@1.21.6))(typescript@5.7.2)': @@ -2064,6 +2209,8 @@ snapshots: clsx@2.1.1: {} + cluster-key-slot@1.1.2: {} + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -2308,6 +2455,8 @@ snapshots: function-bind@1.1.2: {} + generic-pool@3.9.0: {} + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -2591,6 +2740,12 @@ snapshots: prism-svelte@0.4.7: {} + prisma@5.22.0: + dependencies: + '@prisma/engines': 5.22.0 + optionalDependencies: + fsevents: 2.3.3 + prismjs@1.29.0: {} punycode@2.3.1: {} @@ -2607,6 +2762,15 @@ snapshots: readdirp@4.0.2: {} + redis@4.7.0: + dependencies: + '@redis/bloom': 1.2.0(@redis/client@1.6.0) + '@redis/client': 1.6.0 + '@redis/graph': 1.1.1(@redis/client@1.6.0) + '@redis/json': 1.0.7(@redis/client@1.6.0) + '@redis/search': 1.2.0(@redis/client@1.6.0) + '@redis/time-series': 1.1.0(@redis/client@1.6.0) + resolve-from@4.0.0: {} resolve@1.22.8: @@ -2829,6 +2993,8 @@ snapshots: typescript@5.7.2: {} + undici-types@6.20.0: {} + unist-util-stringify-position@2.0.3: dependencies: '@types/unist': 2.0.11 @@ -2850,17 +3016,18 @@ snapshots: '@types/unist': 2.0.11 unist-util-stringify-position: 2.0.3 - vite@5.4.11: + vite@5.4.11(@types/node@22.10.1): dependencies: esbuild: 0.21.5 postcss: 8.4.49 rollup: 4.27.4 optionalDependencies: + '@types/node': 22.10.1 fsevents: 2.3.3 - vitefu@1.0.3(vite@5.4.11): + vitefu@1.0.3(vite@5.4.11(@types/node@22.10.1)): optionalDependencies: - vite: 5.4.11 + vite: 5.4.11(@types/node@22.10.1) which@2.0.2: dependencies: @@ -2880,6 +3047,8 @@ snapshots: string-width: 5.1.2 strip-ansi: 7.1.0 + yallist@4.0.0: {} + yaml@1.10.2: {} yaml@2.6.1: {} diff --git a/prisma/schema.prisma b/prisma/schema.prisma index e3ef7ec..71b0476 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -9,39 +9,41 @@ generator client { } datasource db { - provider = "postgresql" + provider = "mongodb" url = env("DATABASE_URL") } model User { - id Int @id @default(autoincrement()) - pseudo String @unique - nom String - prenom String - email String @unique - password String - canaux Canal[] @relation("UserCanaux") - messages Message[] + id String @id @default(cuid()) @map("_id") @db.ObjectId + username String @unique + surname String + name String + email String @unique + password String + channels Channel[] @relation(fields: [channelIDs], references: [id]) + channelIDs String[] @db.ObjectId + messages Message[] @@map("users") // Table name in DB } -model Canal { - id Int @id @default(autoincrement()) - nom String - domaine String - users User[] @relation("UserCanaux") - messages Message[] +model Channel { + id String @id @default(cuid()) @map("_id") @db.ObjectId + name String + topic String + users User[] @relation(fields: [userIDs], references: [id]) + userIDs String[] @db.ObjectId + messages Message[] - @@map("canaux") // Table name in DB + @@map("channels") // Table name in DB } model Message { - id Int @id @default(autoincrement()) + id String @id @default(cuid()) @map("_id") @db.ObjectId user User @relation(fields: [userId], references: [id]) - userId Int - canal Canal @relation(fields: [canalId], references: [id]) - canalId Int + userId String @db.ObjectId + channel Channel @relation(fields: [channelId], references: [id]) + channelId String @db.ObjectId text String createdAt DateTime @default(now()) diff --git a/src/lib/redisClient.ts b/src/lib/redisClient.ts index 739c27b..28b31bf 100644 --- a/src/lib/redisClient.ts +++ b/src/lib/redisClient.ts @@ -1,7 +1,7 @@ -import redis from 'redis'; +import { createClient } from 'redis'; -const client = redis.createClient({ - url: process.env.REDIS_URL || 'redis://localhost:6379', +const client = await createClient({ + url: process.env.REDIS_URL || 'redis://localhost:6379' }); client.on('error', (err) => console.error('Redis Error:', err)); diff --git a/src/routes/api/canal/[id]/+server.js.ts b/src/routes/api/canal/[id]/+server.ts similarity index 95% rename from src/routes/api/canal/[id]/+server.js.ts rename to src/routes/api/canal/[id]/+server.ts index cfdb6f3..96cfcaf 100644 --- a/src/routes/api/canal/[id]/+server.js.ts +++ b/src/routes/api/canal/[id]/+server.ts @@ -1,6 +1,6 @@ import { json } from '@sveltejs/kit'; import prisma from '$lib/prismaClient'; -import redisClient from '$lib/redisClient'; // Assurez-vous d'importer le client Redis +import redisClient from '$lib/redisClient'; // Récupérer les informations du canal et le dernier message (avec cache Redis) export async function GET({ params }) { @@ -46,7 +46,8 @@ export async function GET({ params }) { }; // Mettre en cache les informations du canal et le dernier message pendant 5 minutes - await redisClient.set(canalCacheKey, JSON.stringify(canalData), 'EX', 300); // Cache pendant 5 minutes + await redisClient.set(canalCacheKey, JSON.stringify(canalData), {EX: 300, NX: true}); // Cache pendant 5 minutes + console.log('❌ Cache miss - Mise en cache des résultats'); return json(canalData); @@ -113,7 +114,7 @@ export async function PUT({ params, request }) { }; // Mettre en cache les nouvelles informations pendant 5 minutes - await redisClient.set(canalCacheKey, JSON.stringify(canalData), 'EX', 60 * 5); // Cache pendant 5 minutes + await redisClient.set(canalCacheKey, JSON.stringify(canalData), { EX: 300, NX: true }); return json(canalData); } catch (err) { From aab022686196ca69efc60a8c0467911eb9e55dea Mon Sep 17 00:00:00 2001 From: Nabil Ould Hamou Date: Sat, 30 Nov 2024 15:38:32 +0100 Subject: [PATCH 4/7] feat: added environment variables to the redis server in docker-compose.yml --- docker-compose.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 4ac470d..53fe995 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,8 +24,10 @@ services: ports: - "6379:6379" command: redis-server --save 20 1 --loglevel warning + environment: + - REDIS_PASSWORD=temp-redis-password volumes: - - redis-data:/data + - redis-data:/root/redis networks: - redis_network From 44370a1b003855be4d22f9ab31bacf85ffec02b3 Mon Sep 17 00:00:00 2001 From: Nabil Ould Hamou Date: Sun, 1 Dec 2024 13:47:18 +0100 Subject: [PATCH 5/7] =?UTF-8?q?R=C3=A9paration=20du=20docker-compose=20de?= =?UTF-8?q?=20la=20base=20de=20donn=C3=A9es=20Mongo=20et=20d=C3=A9but=20de?= =?UTF-8?q?=20l'authentification?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yml | 6 +++--- mongodb_rs/Dockerfile | 11 +++++++++++ prisma/schema.prisma | 6 +++--- src/routes/+page.server.ts | 21 +++++++++++++++++++++ src/routes/+page.svelte | 31 ++++++++++++++++++------------- 5 files changed, 56 insertions(+), 19 deletions(-) create mode 100644 mongodb_rs/Dockerfile create mode 100644 src/routes/+page.server.ts diff --git a/docker-compose.yml b/docker-compose.yml index 53fe995..0e5d47c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,14 +1,14 @@ services: mongodb: - image: mongo:latest + build: ./mongodb_rs hostname: mongodb restart: always - env_file: - - .env environment: - MONGO_INITDB_ROOT_USERNAME=temp-root-username - MONGO_INITDB_ROOT_PASSWORD=temp-password - MONGO_INITDB_DATABASE=chat_projetweb + - MONGO_REPLICA_HOST=localhost + - MONGO_REPLICA_PORT=27017 ports: - "27017:27017" volumes: diff --git a/mongodb_rs/Dockerfile b/mongodb_rs/Dockerfile new file mode 100644 index 0000000..9bbc3d1 --- /dev/null +++ b/mongodb_rs/Dockerfile @@ -0,0 +1,11 @@ +FROM mongo:5 + +# we take over the default & start mongo in replica set mode in a background task +ENTRYPOINT mongod --port $MONGO_REPLICA_PORT --replSet rs0 --bind_ip 0.0.0.0 & MONGOD_PID=$!; \ +# we prepare the replica set with a single node and prepare the root user config +INIT_REPL_CMD="rs.initiate({ _id: 'rs0', members: [{ _id: 0, host: '$MONGO_REPLICA_HOST:$MONGO_REPLICA_PORT' }] })"; \ +INIT_USER_CMD="db.getUser('$MONGO_INITDB_ROOT_USERNAME') || db.createUser({ user: '$MONGO_INITDB_ROOT_USERNAME', pwd: '$MONGO_INITDB_ROOT_PASSWORD', roles: ['root'] })"; \ +# we wait for the replica set to be ready and then submit the command just above +until (mongo admin --port $MONGO_REPLICA_PORT --eval "$INIT_REPL_CMD && $INIT_USER_CMD"); do sleep 1; done; \ +# we are done but we keep the container by waiting on signals from the mongo task +echo "REPLICA SET ONLINE"; wait $MONGOD_PID; \ No newline at end of file diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 71b0476..f8fda22 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -14,7 +14,7 @@ datasource db { } model User { - id String @id @default(cuid()) @map("_id") @db.ObjectId + id String @id @default(auto()) @map("_id") @db.ObjectId username String @unique surname String name String @@ -28,7 +28,7 @@ model User { } model Channel { - id String @id @default(cuid()) @map("_id") @db.ObjectId + id String @id @default(auto()) @map("_id") @db.ObjectId name String topic String users User[] @relation(fields: [userIDs], references: [id]) @@ -39,7 +39,7 @@ model Channel { } model Message { - id String @id @default(cuid()) @map("_id") @db.ObjectId + id String @id @default(auto()) @map("_id") @db.ObjectId user User @relation(fields: [userId], references: [id]) userId String @db.ObjectId channel Channel @relation(fields: [channelId], references: [id]) diff --git a/src/routes/+page.server.ts b/src/routes/+page.server.ts new file mode 100644 index 0000000..d16c5d4 --- /dev/null +++ b/src/routes/+page.server.ts @@ -0,0 +1,21 @@ +import type { Actions } from '@sveltejs/kit'; +import prismaClient from '$lib/prismaClient'; + +export const actions: Actions = { + login: async ({request}) => { + const formData = await request.formData(); + + console.log(formData.get("username")); + + await prismaClient.user.create({ + data: { + email: "fdp", + username: "test", + surname: "azeza", + name: "aiudhza", + password: "feur" + } + }); + + } +} \ No newline at end of file diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 1645fab..cd1246a 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -3,6 +3,9 @@ import { Button } from "$lib/components/ui/button"; import { Input } from "$lib/components/ui/input"; import * as Card from "$lib/components/ui/card"; + import { enhance } from '$app/forms'; + +
@@ -11,18 +14,20 @@ 🌳 Un chat collaboratif - -
- - -
-
- - -
-
- - - +
+ +
+ + +
+
+ + +
+
+ + + +
\ No newline at end of file From 081acb3a4130fddabb54b486b978f9e42d586ddd Mon Sep 17 00:00:00 2001 From: Nabil Ould Hamou Date: Sun, 1 Dec 2024 15:37:31 +0100 Subject: [PATCH 6/7] =?UTF-8?q?Page=20de=20login=20"termin=C3=A9e"=20Syst?= =?UTF-8?q?=C3=A8me=20presque=20fini=20manque=20juste=20les=20cookies=20et?= =?UTF-8?q?=20check=20de=20la=20connexion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + pnpm-lock.yaml | 31 ++++++++ src/lib/components/ui/tabs/index.ts | 18 +++++ .../components/ui/tabs/tabs-content.svelte | 21 +++++ src/lib/components/ui/tabs/tabs-list.svelte | 19 +++++ .../components/ui/tabs/tabs-trigger.svelte | 23 ++++++ src/routes/+page.server.ts | 77 ++++++++++++++++--- src/routes/+page.svelte | 73 ++++++++++++++---- 8 files changed, 237 insertions(+), 26 deletions(-) create mode 100644 src/lib/components/ui/tabs/index.ts create mode 100644 src/lib/components/ui/tabs/tabs-content.svelte create mode 100644 src/lib/components/ui/tabs/tabs-list.svelte create mode 100644 src/lib/components/ui/tabs/tabs-trigger.svelte diff --git a/package.json b/package.json index 036ee8d..8bc3d67 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "dependencies": { "@prisma/client": "^5.22.0", "@types/node": "^22.10.1", + "argon2": "^0.41.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 f8244bc..5cf6b15 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: '@types/node': specifier: ^22.10.1 version: 22.10.1 + argon2: + specifier: ^0.41.1 + version: 0.41.1 prisma: specifier: ^5.22.0 version: 5.22.0 @@ -344,6 +347,10 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@phc/format@1.0.0': + resolution: {integrity: sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==} + engines: {node: '>=10'} + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -647,6 +654,10 @@ packages: arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + argon2@0.41.1: + resolution: {integrity: sha512-dqCW8kJXke8Ik+McUcMDltrbuAWETPyU6iq+4AhxqKphWi7pChB/Zgd/Tp/o8xRLbg8ksMj46F/vph9wnxpTzQ==} + engines: {node: '>=16.17.0'} + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -1141,6 +1152,14 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + node-addon-api@8.3.0: + resolution: {integrity: sha512-8VOpLHFrOQlAH+qA0ZzuGRlALRA6/LVh8QJldbrC4DY0hXoMP0l4Acq8TzFC018HztWiRqyCEj2aTWY2UvnJUg==} + engines: {node: ^18 || ^20 || >= 21} + + node-gyp-build@4.8.4: + resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} + hasBin: true + node-releases@2.0.18: resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} @@ -1844,6 +1863,8 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 + '@phc/format@1.0.0': {} + '@pkgjs/parseargs@0.11.0': optional: true @@ -2133,6 +2154,12 @@ snapshots: arg@5.0.2: {} + argon2@0.41.1: + dependencies: + '@phc/format': 1.0.0 + node-addon-api: 8.3.0 + node-gyp-build: 4.8.4 + argparse@2.0.1: {} aria-query@5.3.2: {} @@ -2619,6 +2646,10 @@ snapshots: natural-compare@1.4.0: {} + node-addon-api@8.3.0: {} + + node-gyp-build@4.8.4: {} + node-releases@2.0.18: {} normalize-path@3.0.0: {} diff --git a/src/lib/components/ui/tabs/index.ts b/src/lib/components/ui/tabs/index.ts new file mode 100644 index 0000000..f1ab372 --- /dev/null +++ b/src/lib/components/ui/tabs/index.ts @@ -0,0 +1,18 @@ +import { Tabs as TabsPrimitive } from "bits-ui"; +import Content from "./tabs-content.svelte"; +import List from "./tabs-list.svelte"; +import Trigger from "./tabs-trigger.svelte"; + +const Root = TabsPrimitive.Root; + +export { + Root, + Content, + List, + Trigger, + // + Root as Tabs, + Content as TabsContent, + List as TabsList, + Trigger as TabsTrigger, +}; diff --git a/src/lib/components/ui/tabs/tabs-content.svelte b/src/lib/components/ui/tabs/tabs-content.svelte new file mode 100644 index 0000000..b611559 --- /dev/null +++ b/src/lib/components/ui/tabs/tabs-content.svelte @@ -0,0 +1,21 @@ + + + + + diff --git a/src/lib/components/ui/tabs/tabs-list.svelte b/src/lib/components/ui/tabs/tabs-list.svelte new file mode 100644 index 0000000..773c754 --- /dev/null +++ b/src/lib/components/ui/tabs/tabs-list.svelte @@ -0,0 +1,19 @@ + + + + + diff --git a/src/lib/components/ui/tabs/tabs-trigger.svelte b/src/lib/components/ui/tabs/tabs-trigger.svelte new file mode 100644 index 0000000..b99358d --- /dev/null +++ b/src/lib/components/ui/tabs/tabs-trigger.svelte @@ -0,0 +1,23 @@ + + + + + diff --git a/src/routes/+page.server.ts b/src/routes/+page.server.ts index d16c5d4..7ac4113 100644 --- a/src/routes/+page.server.ts +++ b/src/routes/+page.server.ts @@ -1,21 +1,80 @@ -import type { Actions } from '@sveltejs/kit'; +import { type Actions, json } from '@sveltejs/kit'; import prismaClient from '$lib/prismaClient'; +import * as argon2 from 'argon2'; +import { redirect, error } from '@sveltejs/kit'; export const actions: Actions = { login: async ({request}) => { const formData = await request.formData(); - console.log(formData.get("username")); + // @ts-ignore Can't be empty + const username = formData.get('username').toString(); - await prismaClient.user.create({ - data: { - email: "fdp", - username: "test", - surname: "azeza", - name: "aiudhza", - password: "feur" + // @ts-ignore Can't be empty + const password = formData.get('password').toString(); + + const user = await prismaClient.user.findFirst({ + where: { + username: username, } }); + if (user == null) { + return error(400, {message: "Nom d'utilisateur ou mot de passe invalide."}); + } + + try { + // @ts-ignore Already checked for null + if (await argon2.verify(user.password, password)) { + console.log("login succesful") + } 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."}) + } + }, + + register: async ({request}) => { + 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 + } + ] + } + }); + + if (user != null) { + return error(400, { message: "Un compte avec cette email ou nom d'utilisateur éxiste déjà." }); + } + + 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 cd1246a..0e07cbf 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,33 +1,72 @@
- + + + + Se connecter + S'inscrire + + + + - 🌳 - Un chat collaboratif + 🌳 - Arbres + Connectez vous pour chatter!
-
- - -
-
- - -
+
+ + +
+
+ + +
+
+ + + + + 🌳 - Arbres + Inscrivez-vous pour chatter! + +
+ +
+ + +
+
+ + +
+
+ + +
+
+ + + +
+
+
+ +
\ No newline at end of file From 069de640cbddbb7b00fa9d3c4c21d463cce60ad6 Mon Sep 17 00:00:00 2001 From: Nabil Ould Hamou Date: Sun, 1 Dec 2024 16:09:44 +0100 Subject: [PATCH 7/7] Added a logger to the project --- .gitignore | 2 + package.json | 3 +- pnpm-lock.yaml | 199 +++++++++++++++++++++++++++++++++++++ src/lib/logger.ts | 21 ++++ src/routes/+page.server.ts | 6 +- 5 files changed, 228 insertions(+), 3 deletions(-) create mode 100644 src/lib/logger.ts diff --git a/.gitignore b/.gitignore index 79518f7..c92aacb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ node_modules + +/logs # Output .output .vercel diff --git a/package.json b/package.json index 8bc3d67..51366ad 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "argon2": "^0.41.1", "prisma": "^5.22.0", "redis": "^4.7.0", - "svelte-radix": "^2.0.1" + "svelte-radix": "^2.0.1", + "winston": "^3.17.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5cf6b15..86b24dc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,6 +26,9 @@ importers: svelte-radix: specifier: ^2.0.1 version: 2.0.1(svelte@5.2.7) + winston: + specifier: ^3.17.0 + version: 3.17.0 devDependencies: '@sveltejs/adapter-auto': specifier: ^3.0.0 @@ -104,6 +107,13 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} + '@colors/colors@1.6.0': + resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} + engines: {node: '>=0.1.90'} + + '@dabh/diagnostics@2.0.3': + resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==} + '@esbuild/aix-ppc64@0.21.5': resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} engines: {node: '>=12'} @@ -545,6 +555,9 @@ packages: '@types/node@22.10.1': resolution: {integrity: sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==} + '@types/triple-beam@1.3.5': + resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} + '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -665,6 +678,9 @@ packages: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + autoprefixer@10.4.20: resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} engines: {node: ^10 || ^12 || >=14} @@ -734,13 +750,28 @@ packages: resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} engines: {node: '>=0.10.0'} + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@3.2.1: + resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} + + colorspace@1.1.4: + resolution: {integrity: sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==} + commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} @@ -802,6 +833,9 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + enabled@2.0.0: + resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} + esbuild@0.21.5: resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} engines: {node: '>=12'} @@ -917,6 +951,9 @@ packages: picomatch: optional: true + fecha@4.2.3: + resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} + file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} @@ -936,6 +973,9 @@ packages: flatted@3.3.2: resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} + fn.name@1.1.0: + resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} + focus-trap@7.6.2: resolution: {integrity: sha512-9FhUxK1hVju2+AiQIDJ5Dd//9R2n2RAfJ0qfhF4IHGHgcoEUTMpbTeG/zbEuwaiYXfuAH6XE0/aCyxDdRM+W5w==} @@ -1010,6 +1050,12 @@ packages: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} @@ -1037,6 +1083,10 @@ packages: is-reference@3.0.3: resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -1070,6 +1120,9 @@ packages: known-css-properties@0.35.0: resolution: {integrity: sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A==} + kuler@2.0.0: + resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -1095,6 +1148,10 @@ packages: lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + logform@2.7.0: + resolution: {integrity: sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==} + engines: {node: '>= 12.0.0'} + lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} @@ -1179,6 +1236,9 @@ packages: resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} + one-time@1.0.0: + resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -1385,6 +1445,10 @@ packages: read-cache@1.0.0: resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -1420,6 +1484,13 @@ packages: resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} engines: {node: '>=6'} + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + semver@7.6.3: resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} engines: {node: '>=10'} @@ -1440,6 +1511,9 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + sirv@3.0.0: resolution: {integrity: sha512-BPwJGUeDaDCHihkORDchNyyTvWFhcusy1XMmhEVTQTwGeybFbp8YEmB+njbPnth1FibULBSBVwCQni25XlCUDg==} engines: {node: '>=18'} @@ -1448,6 +1522,9 @@ 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==} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -1456,6 +1533,9 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -1525,6 +1605,9 @@ packages: engines: {node: '>=14.0.0'} hasBin: true + text-hex@1.0.0: + resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} + thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -1543,6 +1626,10 @@ packages: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} + triple-beam@1.4.1: + resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} + engines: {node: '>= 14.0.0'} + ts-api-utils@1.4.1: resolution: {integrity: sha512-5RU2/lxTA3YUZxju61HO2U6EoZLvBLtmV2mbTvqyu4a/7s7RmJPT+1YekhMVsQhznRWk/czIwDUg+V8Q9ZuG4w==} engines: {node: '>=16'} @@ -1639,6 +1726,14 @@ packages: engines: {node: '>= 8'} hasBin: true + winston-transport@4.9.0: + resolution: {integrity: sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==} + engines: {node: '>= 12.0.0'} + + winston@3.17.0: + resolution: {integrity: sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==} + engines: {node: '>= 12.0.0'} + word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -1679,6 +1774,14 @@ snapshots: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 + '@colors/colors@1.6.0': {} + + '@dabh/diagnostics@2.0.3': + dependencies: + colorspace: 1.1.4 + enabled: 2.0.0 + kuler: 2.0.0 + '@esbuild/aix-ppc64@0.21.5': optional: true @@ -2034,6 +2137,8 @@ snapshots: dependencies: undici-types: 6.20.0 + '@types/triple-beam@1.3.5': {} + '@types/unist@2.0.11': {} '@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0(jiti@1.21.6))(typescript@5.7.2))(eslint@9.15.0(jiti@1.21.6))(typescript@5.7.2)': @@ -2164,6 +2269,8 @@ snapshots: aria-query@5.3.2: {} + async@3.2.6: {} + autoprefixer@10.4.20(postcss@8.4.49): dependencies: browserslist: 4.24.2 @@ -2238,12 +2345,33 @@ snapshots: cluster-key-slot@1.1.2: {} + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + color-convert@2.0.1: dependencies: color-name: 1.1.4 + color-name@1.1.3: {} + color-name@1.1.4: {} + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + + color@3.2.1: + dependencies: + color-convert: 1.9.3 + color-string: 1.9.1 + + colorspace@1.1.4: + dependencies: + color: 3.2.1 + text-hex: 1.0.0 + commander@4.1.1: {} concat-map@0.0.1: {} @@ -2282,6 +2410,8 @@ snapshots: emoji-regex@9.2.2: {} + enabled@2.0.0: {} + esbuild@0.21.5: optionalDependencies: '@esbuild/aix-ppc64': 0.21.5 @@ -2446,6 +2576,8 @@ snapshots: fdir@6.4.2: {} + fecha@4.2.3: {} + file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 @@ -2466,6 +2598,8 @@ snapshots: flatted@3.3.2: {} + fn.name@1.1.0: {} + focus-trap@7.6.2: dependencies: tabbable: 6.2.0 @@ -2528,6 +2662,10 @@ snapshots: imurmurhash@0.1.4: {} + inherits@2.0.4: {} + + is-arrayish@0.3.2: {} + is-binary-path@2.1.0: dependencies: binary-extensions: 2.3.0 @@ -2550,6 +2688,8 @@ snapshots: dependencies: '@types/estree': 1.0.6 + is-stream@2.0.1: {} + isexe@2.0.0: {} jackspeak@3.4.3: @@ -2578,6 +2718,8 @@ snapshots: known-css-properties@0.35.0: {} + kuler@2.0.0: {} + levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -2597,6 +2739,15 @@ snapshots: lodash.merge@4.6.2: {} + logform@2.7.0: + dependencies: + '@colors/colors': 1.6.0 + '@types/triple-beam': 1.3.5 + fecha: 4.2.3 + ms: 2.1.3 + safe-stable-stringify: 2.5.0 + triple-beam: 1.4.1 + lru-cache@10.4.3: {} magic-string@0.30.13: @@ -2660,6 +2811,10 @@ snapshots: object-hash@3.0.0: {} + one-time@1.0.0: + dependencies: + fn.name: 1.1.0 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -2787,6 +2942,12 @@ snapshots: dependencies: pify: 2.3.0 + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + readdirp@3.6.0: dependencies: picomatch: 2.3.1 @@ -2844,6 +3005,10 @@ snapshots: dependencies: mri: 1.2.0 + safe-buffer@5.2.1: {} + + safe-stable-stringify@2.5.0: {} + semver@7.6.3: {} set-cookie-parser@2.7.1: {} @@ -2856,6 +3021,10 @@ snapshots: signal-exit@4.1.0: {} + simple-swizzle@0.2.2: + dependencies: + is-arrayish: 0.3.2 + sirv@3.0.0: dependencies: '@polka/url': 1.0.0-next.28 @@ -2864,6 +3033,8 @@ snapshots: source-map-js@1.2.1: {} + stack-trace@0.0.10: {} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -2876,6 +3047,10 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.1.0 + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -2980,6 +3155,8 @@ snapshots: transitivePeerDependencies: - ts-node + text-hex@1.0.0: {} + thenify-all@1.6.0: dependencies: thenify: 3.3.1 @@ -2999,6 +3176,8 @@ snapshots: totalist@3.0.1: {} + triple-beam@1.4.1: {} + ts-api-utils@1.4.1(typescript@5.7.2): dependencies: typescript: 5.7.2 @@ -3064,6 +3243,26 @@ snapshots: dependencies: isexe: 2.0.0 + winston-transport@4.9.0: + dependencies: + logform: 2.7.0 + readable-stream: 3.6.2 + triple-beam: 1.4.1 + + winston@3.17.0: + dependencies: + '@colors/colors': 1.6.0 + '@dabh/diagnostics': 2.0.3 + async: 3.2.6 + is-stream: 2.0.1 + logform: 2.7.0 + one-time: 1.0.0 + readable-stream: 3.6.2 + safe-stable-stringify: 2.5.0 + stack-trace: 0.0.10 + triple-beam: 1.4.1 + winston-transport: 4.9.0 + word-wrap@1.2.5: {} wrap-ansi@7.0.0: diff --git a/src/lib/logger.ts b/src/lib/logger.ts new file mode 100644 index 0000000..9521549 --- /dev/null +++ b/src/lib/logger.ts @@ -0,0 +1,21 @@ +import winston from 'winston'; + +const { combine, timestamp, json, errors } = winston.format; + +const logger = winston.createLogger({ + levels: winston.config.syslog.levels, + format: combine( + errors({ stack: true }), + timestamp(), + json(), + ), + transports: [ + new winston.transports.Console({level: "debug"}), + new winston.transports.File({ + filename: 'logs/app.log', + level: 'debug' + }) + ] +}); + +export default logger; \ No newline at end of file diff --git a/src/routes/+page.server.ts b/src/routes/+page.server.ts index 7ac4113..fcf0a3f 100644 --- a/src/routes/+page.server.ts +++ b/src/routes/+page.server.ts @@ -1,7 +1,8 @@ -import { type Actions, json } from '@sveltejs/kit'; +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 const actions: Actions = { login: async ({request}) => { @@ -26,7 +27,8 @@ export const actions: Actions = { try { // @ts-ignore Already checked for null if (await argon2.verify(user.password, password)) { - console.log("login succesful") + logger.log("info", "saijdazji") + logger.log("debug", "saijdazji") } else { return error(400, {message: "Nom d'utilisateur ou mot de passe invalide."}); }