api fonctionnelle pour action sur la table user
continuous-integration/drone/push Build is passing Details

pull/2/head
Hugo PRADIER 11 months ago
parent b62e80e538
commit 9fcc8a806c

@ -16,7 +16,8 @@
"@fastify/cors": "^9.0.0", "@fastify/cors": "^9.0.0",
"@fastify/type-provider-typebox": "^4.0.0", "@fastify/type-provider-typebox": "^4.0.0",
"@sinclair/typebox": "^0.32.9", "@sinclair/typebox": "^0.32.9",
"fastify": "^4.25.2", "fastify": "^4.27.0",
"fastify-sqlite-typed": "^0.1.1",
"nanoid": "^5.0.4", "nanoid": "^5.0.4",
"sqlite3": "^5.1.7", "sqlite3": "^5.1.7",
"zeromq": "6.0.0-beta.19" "zeromq": "6.0.0-beta.19"

@ -179,12 +179,19 @@ function selectUserById(db: sqlite3.Database, id: number) {
}); });
} }
/////////////////////////// Exécution des requêtes /////////////////////////// /////////////////////////// Export des fonctions ///////////////////////////
const db = openDatabase(); export {
db.serialize(() => { createDbDirectory,
createDbDirectory(); openDatabase,
createRegisteredUserTable(db); closeDatabase,
insertUser(db, "user1", "password1", 1); createRegisteredUserTable,
selectAllUsers(db); insertUser,
closeDatabase(db); updateUserLogin,
}); updateUserPassword,
updateUserPermissions,
deleteUser,
deleteAllUsers,
selectAllUsers,
selectUserByLogin,
selectUserById,
};

@ -1,9 +1,25 @@
import cors from '@fastify/cors'; import cors from "@fastify/cors";
import { Type, TypeBoxTypeProvider } from '@fastify/type-provider-typebox'; import { Type, TypeBoxTypeProvider } from "@fastify/type-provider-typebox";
import Fastify, { FastifyReply } from 'fastify'; import Fastify, { FastifyReply, FastifyRequest } from "fastify";
import { nanoid } from 'nanoid'; import { nanoid } from "nanoid";
import { allocateBuffer, IMAGES } from 'runner'; import { allocateBuffer, IMAGES } from "runner";
import { Pull, Push } from 'zeromq'; import { Pull, Push } from "zeromq";
import {
createDbDirectory,
openDatabase,
closeDatabase,
createRegisteredUserTable,
insertUser,
updateUserLogin,
updateUserPassword,
updateUserPermissions,
deleteUser,
deleteAllUsers,
selectAllUsers,
selectUserByLogin,
selectUserById,
} from "./database";
const sender = new Push(); const sender = new Push();
await sender.bind(`tcp://127.0.0.1:5557`); await sender.bind(`tcp://127.0.0.1:5557`);
@ -17,37 +33,143 @@ const fastify = Fastify({
logger: true, logger: true,
}).withTypeProvider<TypeBoxTypeProvider>(); }).withTypeProvider<TypeBoxTypeProvider>();
await fastify.register(cors, { await fastify.register(cors, {
origin: process.env.ALLOW_ORIGIN || '*', origin: process.env.ALLOW_ORIGIN || "*",
}); });
fastify.post('/run', { // Code runner in a container
schema: {
body: Type.Object({ // POST /run : Run code in a container
code: Type.String(),
language: Type.String(), fastify.post(
}), "/run",
{
schema: {
body: Type.Object({
code: Type.String(),
language: Type.String(),
}),
},
}, },
}, (req, reply) => { (req, reply) => {
const { code, language } = req.body; const { code, language } = req.body;
const jobId = generateId(); const jobId = generateId();
const buffer = allocateBuffer(jobId, code, IMAGES.moshell); const buffer = allocateBuffer(jobId, code, IMAGES.moshell);
reply.raw.writeHead(200, { reply.raw.writeHead(200, {
'Content-Type': 'text/event-stream', "Content-Type": "text/event-stream",
Connection: 'keep-alive', Connection: "keep-alive",
'Cache-Control': 'no-cache', "Cache-Control": "no-cache",
'Access-Control-Allow-Origin': process.env.ALLOW_ORIGIN || '*', "Access-Control-Allow-Origin": process.env.ALLOW_ORIGIN || "*",
}); });
reply.raw.on('close', () => { reply.raw.on("close", () => {
delete clients[jobId]; delete clients[jobId];
}); });
sender.send(buffer).then(() => { sender.send(buffer).then(() => {
reply.raw.write('event: connected\n'); reply.raw.write("event: connected\n");
reply.raw.write(`data: ${jobId}\n`); reply.raw.write(`data: ${jobId}\n`);
reply.raw.write('id: 0\n\n'); reply.raw.write("id: 0\n\n");
}); });
clients[jobId] = reply; clients[jobId] = reply;
}
);
// Database
// Création du répertoire de la base de données s'il n'existe pas
createDbDirectory();
// Ouvrir la base de données
const db = openDatabase();
// Créer la table registered_user si elle n'existe pas
createRegisteredUserTable(db);
// Route pour créer un utilisateur
fastify.post<{
Body: {
login: string;
password: string;
permissions: number;
};
}>("/users", async (request, reply) => {
const { login, password, permissions } = request.body;
insertUser(db, login, password, permissions);
reply.send({ success: true });
});
// Route pour mettre à jour le login d'un utilisateur
fastify.put<{
Params: { id: string };
Body: { newLogin: string };
}>("/users/:id/login", async (request, reply) => {
const { id } = request.params;
const { newLogin } = request.body;
updateUserLogin(db, parseInt(id), newLogin);
reply.send({ success: true });
});
// Route pour mettre à jour le mot de passe d'un utilisateur
fastify.put<{
Params: { id: string };
Body: { newPassword: string };
}>("/users/:id/password", async (request, reply) => {
const { id } = request.params;
const { newPassword } = request.body;
updateUserPassword(db, parseInt(id), newPassword);
reply.send({ success: true });
}); });
// Route pour mettre à jour les permissions d'un utilisateur
fastify.put<{
Params: { id: string };
Body: { newPermissions: number };
}>("/users/:id/permissions", async (request, reply) => {
const { id } = request.params;
const { newPermissions } = request.body;
updateUserPermissions(db, parseInt(id), newPermissions);
reply.send({ success: true });
});
// Route pour supprimer un utilisateur
fastify.delete<{
Params: { id: string };
}>("/users/:id", async (request, reply) => {
const { id } = request.params;
deleteUser(db, parseInt(id));
reply.send({ success: true });
});
// Route pour supprimer tous les utilisateurs
fastify.delete("/users", async (request, reply) => {
deleteAllUsers(db);
reply.send({ success: true });
});
// Route pour récupérer tous les utilisateurs
fastify.get("/users", async (request, reply) => {
const users = selectAllUsers(db);
return users;
});
// Route pour récupérer un utilisateur par son ID
fastify.get<{
Params: { id: string };
}>("/users/:id", async (request, reply) => {
const { id } = request.params;
const user = selectUserById(db, parseInt(id));
return user;
});
// Route pour récupérer un utilisateur par son login
fastify.get<{
Params: { login: string };
}>("/users/login/:login", async (request, reply) => {
const { login } = request.params;
const user = selectUserByLogin(db, login);
return user;
});
// Forward output from the runner to the client
async function forwardOutput() { async function forwardOutput() {
for await (const [buff] of receiver) { for await (const [buff] of receiver) {
const messageType = buff.readInt8(); const messageType = buff.readInt8();
@ -62,23 +184,23 @@ async function forwardOutput() {
case 1: case 1:
case 2: case 2:
const text = encodeURIComponent(buff.subarray(33).toString()); const text = encodeURIComponent(buff.subarray(33).toString());
raw.write('event: message\n'); raw.write("event: message\n");
if (messageType === 1) { if (messageType === 1) {
raw.write('id: stdout\n'); raw.write("id: stdout\n");
} else { } else {
raw.write('id: stderr\n'); raw.write("id: stderr\n");
} }
raw.write(`data: ${text}\n\n`); raw.write(`data: ${text}\n\n`);
break; break;
case 3: case 3:
const exitCode = buff.readUint32BE(33); const exitCode = buff.readUint32BE(33);
raw.write('event: message\n'); raw.write("event: message\n");
raw.write('id: exit\n'); raw.write("id: exit\n");
raw.write(`data: ${exitCode}\n\n`); raw.write(`data: ${exitCode}\n\n`);
raw.end(); raw.end();
break; break;
default: default:
console.error('Unknown message type', messageType); console.error("Unknown message type", messageType);
} }
} }
} }

Loading…
Cancel
Save