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/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/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/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 new file mode 100644 index 0000000..7ac4113 --- /dev/null +++ b/src/routes/+page.server.ts @@ -0,0 +1,80 @@ +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(); + + // @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, + } + }); + + 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 1645fab..0e07cbf 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,28 +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