diff --git a/src/database.ts b/src/database.ts index c8b3d48..6a7c543 100644 --- a/src/database.ts +++ b/src/database.ts @@ -4,6 +4,11 @@ import sqlite3 from "sqlite3"; const dbDirectory = "./src/db"; const dbFilePath = `${dbDirectory}/database.db`; +export type error = { + errno: number; + code: string; +}; + /* Fonction pour exécuter une requête sur la base de données */ /* Fonction pour exécuter une requête de modification de la base de données (INSERT, UPDATE, DELETE) */ @@ -111,15 +116,25 @@ export function createRegisteredUserTable(db: sqlite3.Database): Promise { } /* Insérer un utilisateur dans la table registered_user */ -export function insertUser( +export async function insertUser( db: sqlite3.Database, login: string, password: string, permissions: number -) { +): Promise { const insertUserQuery = `INSERT INTO registered_user (login, password, permissions) VALUES (?, ?, ?)`; - return runDB(db, insertUserQuery, [login, password, permissions]); + try { + await runDB(db, insertUserQuery, [login, password, permissions]); + return true; + } catch (e) { + const error = e as error; + if (error.code === "SQLITE_CONSTRAINT") { + return false; + } else { + throw e; + } + } } /* Modifier le login d'un utilisateur dans la table registered_user */ diff --git a/src/server.ts b/src/server.ts index 8690712..702d825 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,5 +1,5 @@ import cors from "@fastify/cors"; -import websocket, { WebSocket } from '@fastify/websocket'; +import websocket, { WebSocket } from "@fastify/websocket"; import { Type, TypeBoxTypeProvider } from "@fastify/type-provider-typebox"; import Fastify, { FastifyReply } from "fastify"; import { nanoid } from "nanoid"; @@ -18,13 +18,13 @@ const clients: Record = {}; const generateId = () => nanoid(32); let updates: Update[] = []; -let doc = Text.of(['']); +let doc = Text.of([""]); const liveClients: WebSocket[] = []; function send(socket: WebSocket, requestId: number, payload: unknown) { const response = { _request: requestId, - payload + payload, }; socket.send(JSON.stringify(response)); } @@ -33,70 +33,78 @@ const fastify = Fastify({ logger: true, }).withTypeProvider(); await fastify.register(cors, { - origin: process.env.ALLOW_ORIGIN || '*', + origin: process.env.ALLOW_ORIGIN || "*", }); fastify.register(websocket); fastify.get("/live", { websocket: true }, (socket, req) => { liveClients.push(socket); - socket.on("message", message => { + socket.on("message", (message) => { const data = JSON.parse(message.toString()); const requestId = data._request; if (data.type === "pullUpdates") { - send(socket, requestId, updates.slice(data.version)) + send(socket, requestId, updates.slice(data.version)); } else if (data.type === "pushUpdates") { let received = data.updates.map((json: any) => ({ clientID: json.clientID, - changes: ChangeSet.fromJSON(json.changes) - })) + changes: ChangeSet.fromJSON(json.changes), + })); if (data.version != updates.length) { - received = rebaseUpdates(received, updates.slice(data.version)) + received = rebaseUpdates(received, updates.slice(data.version)); } for (let update of received) { - updates.push(update) - doc = update.changes.apply(doc) + updates.push(update); + doc = update.changes.apply(doc); } - send(socket, requestId, received.map((update: any) => ({ - clientID: update.clientID, - changes: update.changes.toJSON() - }))); + send( + socket, + requestId, + received.map((update: any) => ({ + clientID: update.clientID, + changes: update.changes.toJSON(), + })) + ); } else if (data.type == "getDocument") { - send(socket, requestId, {version: updates.length, doc: doc.toString()}) + send(socket, requestId, { version: updates.length, doc: doc.toString() }); } - }) -}) - -fastify.post("/run", { - schema: { - body: Type.Object({ - code: Type.String(), - language: Type.String(), - }), - }, -}, (req, reply) => { - const { code, language } = req.body; - const runner = getRunner(language); - if (runner === null) { - return reply.status(422).send({ error: "Invalid language" }); - } - const jobId = generateId(); - const buffer = allocateBuffer(jobId, code, runner); - reply.raw.writeHead(200, { - "Content-Type": "text/event-stream", - Connection: "keep-alive", - "Cache-Control": "no-cache", - "Access-Control-Allow-Origin": process.env.ALLOW_ORIGIN || "*", - }); - reply.raw.on("close", () => { - delete clients[jobId]; }); - sender.send(buffer).then(() => { - reply.raw.write("event: connected\n"); - reply.raw.write(`data: ${jobId}\n`); - reply.raw.write("id: 0\n\n"); - }); - clients[jobId] = reply; }); +fastify.post( + "/run", + { + schema: { + body: Type.Object({ + code: Type.String(), + language: Type.String(), + }), + }, + }, + (req, reply) => { + const { code, language } = req.body; + const runner = getRunner(language); + if (runner === null) { + return reply.status(422).send({ error: "Invalid language" }); + } + const jobId = generateId(); + const buffer = allocateBuffer(jobId, code, runner); + reply.raw.writeHead(200, { + "Content-Type": "text/event-stream", + Connection: "keep-alive", + "Cache-Control": "no-cache", + "Access-Control-Allow-Origin": process.env.ALLOW_ORIGIN || "*", + }); + reply.raw.on("close", () => { + delete clients[jobId]; + }); + sender.send(buffer).then(() => { + reply.raw.write("event: connected\n"); + reply.raw.write(`data: ${jobId}\n`); + reply.raw.write("id: 0\n\n"); + }); + clients[jobId] = reply; + } +); + /* Création du répertoire de la base de données s'il n'existe pas */ db.createDbDirectory(); @@ -120,8 +128,11 @@ fastify.post( }, async (request, reply) => { const { login, password, permissions } = request.body; - db.insertUser(database, login, password, permissions); - reply.send({ success: true }); + if (!(await db.insertUser(database, login, password, permissions))) { + reply.send({ success: false }); + } else { + reply.send({ success: true }); + } } );