diff --git a/src/database.ts b/src/database.ts index 79f02d4..89249ed 100644 --- a/src/database.ts +++ b/src/database.ts @@ -32,9 +32,10 @@ export function runDB( export function allDB( db: sqlite3.Database, query: string, + params?: any[] ): Promise { return new Promise((resolve, reject) => { - db.all(query, (err, rows) => { + db.all(query, params, (err, rows) => { if (err) { reject(err); } else { @@ -95,7 +96,6 @@ export function closeDatabase(db: sqlite3.Database) { /* Create all the tables in the database */ export function createTables(db: sqlite3.Database) { createRegisteredUserTable(db); - createLanguageTable(db); createWorkTable(db); } @@ -103,6 +103,7 @@ export function createTables(db: sqlite3.Database) { // CREATE TABLE registered_user ( // id_user SERIAL PRIMARY KEY, // login VARCHAR(64) NOT NULL, +// email VARCHAR(64) NOT NULL, // password VARCHAR(72) NOT NULL, // permissions INT NOT NULL, // UNIQUE (login) @@ -110,8 +111,13 @@ export function createTables(db: sqlite3.Database) { /* Créer la table registered_user dans la base de données */ export function createRegisteredUserTable(db: sqlite3.Database): Promise { - const tableRegisteredUser = - `CREATE TABLE IF NOT EXISTS registered_user (id_user INTEGER PRIMARY KEY AUTOINCREMENT, login TEXT NOT NULL, password TEXT NOT NULL, permissions INTEGER NOT NULL, UNIQUE (login))`; + const tableRegisteredUser = `CREATE TABLE IF NOT EXISTS registered_user ( + id_user INTEGER PRIMARY KEY AUTOINCREMENT, + login TEXT NOT NULL, + email TEXT NOT NULL, + password TEXT NOT NULL, + permissions INTEGER NOT NULL, + UNIQUE (login))`; return runDB(db, tableRegisteredUser, []); } @@ -120,13 +126,13 @@ export function createRegisteredUserTable(db: sqlite3.Database): Promise { export async function insertUser( db: sqlite3.Database, login: string, + email: string, password: string, permissions: number, ): Promise { - const insertUserQuery = `INSERT INTO registered_user (login, password, permissions) VALUES (?, ?, ?)`; - + const insertUserQuery = `INSERT INTO registered_user (login, email, password, permissions) VALUES (?, ?, ?, ?)`; try { - await runDB(db, insertUserQuery, [login, password, permissions]); + await runDB(db, insertUserQuery, [login, email, password, permissions]); return true; } catch (e) { const error = e as error; @@ -192,6 +198,15 @@ export function updateUserPermissions( return runDB(db, updateUserPermissionsQuery, [newPermissions, id]); } +export function updateUserEmail( + db: sqlite3.Database, + id: number, + newEmail: string +) { + const updateUserEmailQuery = `UPDATE registered_user SET email = ? WHERE id_user = ?`; + return runDB(db, updateUserEmailQuery, [newEmail, id]); +} + /* Supprimer un utilisateur de la table registered_user par son ID */ export function deleteUserById(db: sqlite3.Database, id: number) { const deleteUserQuery = `DELETE FROM registered_user WHERE id_user = ?`; @@ -234,94 +249,26 @@ export function selectUserById(db: sqlite3.Database, id: number) { return getDB(db, selectUserByIdQuery, [id]); } -/////////////////////////// Gestion des Languages /////////////////////////// -// CREATE TABLE language ( -// id_language SERIAL PRIMARY KEY, -// designation VARCHAR(30) NOT NULL, -// version INT NOT NULL, -// ); - -/* Créer la table language dans la base de données */ -export function createLanguageTable(db: sqlite3.Database): Promise { - const tableLanguage = - `CREATE TABLE IF NOT EXISTS language (id_language INTEGER PRIMARY KEY AUTOINCREMENT, designation TEXT NOT NULL, version INTEGER NOT NULL)`; - return runDB(db, tableLanguage, []); -} - -/* Insérer un language dans la table language */ -export function insertLanguage( - db: sqlite3.Database, - designation: string, - version: number, -) { - const insertLanguageQuery = `INSERT INTO language (designation, version) VALUES (?, ?)`; - - return runDB(db, insertLanguageQuery, [designation, version]); -} - -/* Modifier la designation d'un language dans la table language */ -export function updateLanguageDesignation( - db: sqlite3.Database, - id: number, - newDesignation: string, -) { - const updateLanguageDesignationQuery = `UPDATE language SET designation = ? WHERE id_language = ?`; - - return runDB(db, updateLanguageDesignationQuery, [newDesignation, id]); -} - -/* Modifier la version d'un language dans la table language */ -export function updateLanguageVersion( - db: sqlite3.Database, - id: number, - newVersion: number, -) { - const updateLanguageVersionQuery = `UPDATE language SET version = ? WHERE id_language = ?`; - - return runDB(db, updateLanguageVersionQuery, [newVersion, id]); -} - -/* Supprimer un language de la table language par son ID */ -export function deleteLanguage(db: sqlite3.Database, id: number) { - const deleteLanguageQuery = `DELETE FROM language WHERE id_language = ?`; - - return runDB(db, deleteLanguageQuery, [id]); -} - -/* Supprimer tous les languages de la table language */ -export function deleteAllLanguages(db: sqlite3.Database) { - const deleteAllLanguagesQuery = `DELETE FROM language`; - - return runDB(db, deleteAllLanguagesQuery, []); -} - -/* Sélectionner tous les languages de la table language */ -export function selectAllLanguages(db: sqlite3.Database): Promise { - const selectAllLanguagesQuery = `SELECT * FROM language`; - - return allDB(db, selectAllLanguagesQuery); -} - -/* Sélectionner un language par son ID */ -export function selectLanguageById(db: sqlite3.Database, id: number) { - const selectLanguageByIdQuery = `SELECT * FROM language WHERE id_language = ?`; - - return getDB(db, selectLanguageByIdQuery, [id]); -} - /////////////////////////// Gestion des works /////////////////////////// // CREATE TABLE work ( // id_work SERIAL PRIMARY KEY, // link CHAR(36) NOT NULL, // user_id INT REFERENCES registered_user(id_user), -// language_id INT NOT NULL REFERENCES language(id_language) +// language TEXT NOT NULL, +// title VARCHAR(30) NOT NULL, // content TEXT NOT NULL, +// date TIMESTAMP DEFAULT CURRENT_TIMESTAMP // ); /* Créer la table work dans la base de données */ export function createWorkTable(db: sqlite3.Database): Promise { - const tableWork = - `CREATE TABLE IF NOT EXISTS work (id_work INTEGER PRIMARY KEY AUTOINCREMENT, link CHAR(36) NOT NULL, user_id INTEGER REFERENCES registered_user(id_user), language_id INTEGER NOT NULL REFERENCES language(id_language), content TEXT NOT NULL)`; + const tableWork = `CREATE TABLE IF NOT EXISTS work ( + id_work INTEGER PRIMARY KEY AUTOINCREMENT, + link CHAR(36) NOT NULL, user_id INTEGER REFERENCES registered_user(id_user), + language TEXT NOT NULL, + title TEXT NOT NULL, + content TEXT NOT NULL, + date TIMESTAMP DEFAULT CURRENT_TIMESTAMP)`; return runDB(db, tableWork, []); } @@ -330,12 +277,13 @@ export function insertWork( db: sqlite3.Database, link: string, user_id: number, - language_id: number, + language: string, + title: string, content: string, ) { - const insertWorkQuery = `INSERT INTO work (link, user_id, language_id, content) VALUES (?, ?, ?, ?)`; + const insertWorkQuery = `INSERT INTO work (link, user_id, language, title, content, date) VALUES (?, ?, ?, ?, ?, ?)`; - return runDB(db, insertWorkQuery, [link, user_id, language_id, content]); + return runDB(db, insertWorkQuery, [link, user_id, language, title, content, new Date().toISOString()]); } /* Sélectionner tous les works de la table work */ @@ -345,6 +293,29 @@ export function selectAllWorks(db: sqlite3.Database): Promise { return allDB(db, selectAllWorksQuery); } +/* Sélectionner tous les works de la table work */ +export function selectWorksByUserId(db: sqlite3.Database, user_id: number): Promise { + const selectWorksByUserIdQuery = `SELECT * FROM work WHERE user_id = ?`; + + return allDB(db, selectWorksByUserIdQuery, [user_id]); +} + +/* Sélectionner un work par son ID */ +export function selectWorkByLink(db: sqlite3.Database, link: string) { + const selectWorkByLinkQuery = `SELECT * FROM work WHERE link = ?`; + return getDB(db, selectWorkByLinkQuery, [link]); +} + +/* Sélectionner le dernier work par l'id de l'utilisateur */ +export function selectLastWorkByUserId(db: sqlite3.Database, user_id: number) { + const selectLastWorkByUserIdQuery = `SELECT * FROM work + WHERE user_id = ? + ORDER BY date DESC + LIMIT 1`; + + return getDB(db, selectLastWorkByUserIdQuery, [user_id]); +} + /* Supprimer tous les works de la table work */ export function deleteAllWorks(db: sqlite3.Database) { const deleteAllWorksQuery = `DELETE FROM work`; @@ -359,9 +330,27 @@ export function deleteWork(db: sqlite3.Database, id: number) { return runDB(db, deleteWorkQuery, [id]); } -/* Sélectionner un work par son ID */ -export function selectWorkById(db: sqlite3.Database, id: number) { - const selectWorkByIdQuery = `SELECT * FROM work WHERE id_work = ?`; +/* Update the work title by its ID */ +export function updateWorkTitle( + db: sqlite3.Database, + id: number, + newTitle: string +) { + const updateWorkTitleQuery = `UPDATE work SET title = ? WHERE id_work = ?`; - return getDB(db, selectWorkByIdQuery, [id]); + return runDB(db, updateWorkTitleQuery, [newTitle, id]); } + +/* Update the work content by its ID */ +export function updateWorkContent( + db: sqlite3.Database, + id: number, + newContent: string, + language: string, +) { + const updateWorkContentQuery = `UPDATE work SET content = ?, language = ? WHERE id_work = ?`; + + return runDB(db, updateWorkContentQuery, [newContent, language, id]); +} + + diff --git a/src/server.ts b/src/server.ts index 27635ad..be97bb0 100644 --- a/src/server.ts +++ b/src/server.ts @@ -195,13 +195,14 @@ fastify.post( schema: { body: Type.Object({ login: Type.String(), + email: Type.String(), password: Type.String(), permissions: Type.Number(), }), }, }, async (request, reply) => { - const { login, password, permissions } = request.body; + const { login, email, password, permissions } = request.body; // Hashage du mot de passe const saltRounds = 10; @@ -210,6 +211,7 @@ fastify.post( const success = await db.insertUser( database, login, + email, hashedPassword, permissions ); @@ -325,6 +327,36 @@ fastify.put( } ); +/* Route pour mettre à jour l'email d'un utilisateur */ +fastify.put( + "/users/:id/email", + { + schema: { + params: Type.Object({ + id: Type.Number({ + minimum: 0, + }), + }), + body: Type.Object({ + newEmail: Type.String(), + }), + }, + }, + async (request, reply) => { + const { id } = request.params; + const { newEmail } = request.body; + + // Check if the ID relates to an existing ID. + const user = await db.selectUserById(database, id); + if (!user) { + reply.status(404).send({ error: "User not found" }); + return; + } + await db.updateUserEmail(database, id, newEmail); + reply.send({ success: true }); + } +); + /* Route pour supprimer un utilisateur par son ID */ fastify.delete( "/users/:id", @@ -411,120 +443,6 @@ fastify.get( } ); -/* Route pour créer un language */ -fastify.post( - "/languages", - { - schema: { - body: Type.Object({ - designation: Type.String(), - version: Type.Number(), - }), - }, - }, - async (request, reply) => { - const { designation, version } = request.body; - db.insertLanguage(database, designation, version); - reply.send({ success: true }); - } -); - -/* Route pour mettre à jour la désignation d'un language */ -fastify.put( - "/languages/:id/designation", - { - schema: { - params: Type.Object({ - id: Type.Number({ - minimum: 0, - }), - }), - body: Type.Object({ - newDesignation: Type.String(), - }), - }, - }, - async (request, reply) => { - const { id } = request.params; - const { newDesignation } = request.body; - db.updateLanguageDesignation(database, id, newDesignation); - reply.send({ success: true }); - } -); - -/* Route pour mettre à jour la version d'un language */ -fastify.put( - "/languages/:id/version", - { - schema: { - params: Type.Object({ - id: Type.Number({ - minimum: 0, - }), - }), - body: Type.Object({ - newVersion: Type.Number(), - }), - }, - }, - async (request, reply) => { - const { id } = request.params; - const { newVersion } = request.body; - db.updateLanguageVersion(database, id, newVersion); - reply.send({ success: true }); - } -); - -/* Route pour supprimer un language */ -fastify.delete( - "/languages/:id", - { - schema: { - params: Type.Object({ - id: Type.Number({ - minimum: 0, - }), - }), - }, - }, - async (request, reply) => { - const { id } = request.params; - db.deleteLanguage(database, id); - reply.send({ success: true }); - } -); - -/* Route pour supprimer tous les languages */ -fastify.delete("/languages", async (request, reply) => { - db.deleteAllLanguages(database); - reply.send({ success: true }); -}); - -/* Route pour récupérer un language par son ID */ -fastify.get( - "/languages/:id", - { - schema: { - params: Type.Object({ - id: Type.Number({ - minimum: 0, - }), - }), - }, - }, - async (request, reply) => { - const { id } = request.params; - const language = await db.selectLanguageById(database, id); - reply.send(language); - } -); - -/* Route pour récupérer tous les languages */ -fastify.get("/languages", async (request, reply) => { - const languages = await db.selectAllLanguages(database); - reply.send(languages); -}); - /* Route pour créer un work */ fastify.post( "/works", @@ -533,14 +451,15 @@ fastify.post( body: Type.Object({ id_user: Type.Number(), link: Type.String(), - id_language: Type.Number(), + language: Type.String(), + title: Type.String(), code: Type.String(), }), }, }, async (request, reply) => { - const { id_user, link, id_language, code } = request.body; - db.insertWork(database, link, id_user, id_language, code); + const { id_user, link, language, title, code } = request.body; + await db.insertWork(database, link, id_user, language, title, code); reply.send({ success: true }); } ); @@ -576,23 +495,40 @@ fastify.delete( } ); -/* Route pour récupérer un work par son ID */ +/* Route pour récupérer un work par son Link */ fastify.get( - "/works/:id", + "/works/:link", { schema: { params: Type.Object({ - id: Type.Number({ + link: Type.String(), + }), + }, + }, + async (request, reply) => { + const {link} = request.params; + const work = await db.selectWorkByLink(database, link); + reply.send(work); + }, +); + +/* Route pour récupérer le dernier work par l'id de l'utilisateur */ +fastify.get( + "/works/last-work/:user_id", + { + schema: { + params: Type.Object({ + user_id: Type.Number({ minimum: 0, }), }), }, }, async (request, reply) => { - const { id } = request.params; - const work = await db.selectWorkById(database, id); + const { user_id } = request.params; + const work = await db.selectLastWorkByUserId(database, user_id); reply.send(work); - } + }, ); /* Forward output est une fonction asynchrone qui permet de récupérer les messages envoyés par le container et de les renvoyer au client */