From dd6d7fc5524a94defc3cafefa42180be9bdd2eb4 Mon Sep 17 00:00:00 2001 From: Ninjdai Date: Thu, 7 Dec 2023 23:50:39 +0100 Subject: [PATCH] Update handler to ease implementation of REST API --- src/html/pages/api/users.js | 39 ------------ src/html/pages/api/users_get.js | 19 ++++++ src/html/pages/api/users_post.js | 32 ++++++++++ src/html/pages/dashboard/users_show.js | 42 +++++++++++++ src/html/pages/root/login_post.js | 4 +- utils/handler.js | 84 ++++++++++++++++++++++---- web.js | 57 +---------------- www/dashboard/users/create.html | 29 +++++++-- www/dashboard/users/info.html | 17 ++++++ 9 files changed, 210 insertions(+), 113 deletions(-) delete mode 100644 src/html/pages/api/users.js create mode 100644 src/html/pages/api/users_get.js create mode 100644 src/html/pages/api/users_post.js create mode 100644 src/html/pages/dashboard/users_show.js create mode 100644 www/dashboard/users/info.html diff --git a/src/html/pages/api/users.js b/src/html/pages/api/users.js deleted file mode 100644 index 45584cf..0000000 --- a/src/html/pages/api/users.js +++ /dev/null @@ -1,39 +0,0 @@ -import { permissionBits } from "../../../../utils/permissions.js"; - -export default { - path: "/api/users(/*)?", - requiresLogin: true, - permissions: permissionBits.ADMIN, - type: "post", - async execute(request, response) { - const username = request.originalUrl.split("/")[3]; - const operation = request.originalUrl.split("/")[4]; - const args = request.body; - switch (operation) { - case "create": - if ( - await global.database.users.findOne({ - where: { username: username }, - }) - ) return response.redirect("/dashboard/users/create?error=User already exists"); - console.log(`Creating user ${username}`); - - let permissions = Number(args.permissions); - if (isNaN(permissions)) { - permissions = 0; - for (const permissionBit of args.permissions) { - permissions += Number(permissionBit); - } - } - if(!(permissions & permissionBits.DEFAULT)) permissions ^= permissionBits.DEFAULT; - await global.database.users.create({ - username: username, - password: args.password, - permissions: permissions, - }); - break; - case "delete": - break; - } - }, -}; diff --git a/src/html/pages/api/users_get.js b/src/html/pages/api/users_get.js new file mode 100644 index 0000000..20ce6bb --- /dev/null +++ b/src/html/pages/api/users_get.js @@ -0,0 +1,19 @@ +import { permissionBits } from "../../../../utils/permissions.js"; + +export default { + path: "/api/users/:username", + requiresLogin: true, + permissions: permissionBits.ADMIN, + type: "get", + async execute(request, response) { + const { username } = request.params; + const user = await global.database.users.findOne({ + where: { username: username }, + }); + if(!user || user == 0) return response.status(404).send({ message: "User does not exist" }); + response.send({ + username: user.username, + permissions: user.permissions, + }); + }, +}; diff --git a/src/html/pages/api/users_post.js b/src/html/pages/api/users_post.js new file mode 100644 index 0000000..7cbf278 --- /dev/null +++ b/src/html/pages/api/users_post.js @@ -0,0 +1,32 @@ +import { permissionBits } from "../../../../utils/permissions.js"; + +export default { + path: "/api/users/:username", + requiresLogin: true, + permissions: permissionBits.ADMIN, + type: "post", + async execute(request, response) { + const { username } = request.params; + let { permissions, password } = request.body; + if ( + await global.database.users.findOne({ + where: { username: username }, + }) + ) return response.status(412).send({ message: "User already exists" }); + + if (!(permissions & permissionBits.DEFAULT)) + permissions ^= permissionBits.DEFAULT; + + const userParams = { + username: username, + password: password, + permissions: permissions, + } + console.log(`Creating user ${username}`); + await global.database.users.create(userParams); + response.status(201).send({ + username: username, + permissions: permissions, + }); + }, +}; diff --git a/src/html/pages/dashboard/users_show.js b/src/html/pages/dashboard/users_show.js new file mode 100644 index 0000000..f38b173 --- /dev/null +++ b/src/html/pages/dashboard/users_show.js @@ -0,0 +1,42 @@ +import { permissionBits, checkPermissions } from '../../../../utils/permissions.js'; +import { readFile } from 'fs/promises'; +import { navbar } from '../../../../utils/navbar.js'; + +export default { + path: "/dashboard/users/:username", + requiresLogin: true, + permissions: permissionBits.ADMIN, + type: "get", + async execute(request, response) { + const { username } = request.params; + const user = await global.database.users.findOne({ where: { username: username } }); + if(!user) return response.redirect('/dashboard/users'); + const html = await readFile(`${process.env.WWW}/dashboard/users/info.html`); + response.send(html.toString() + .replace('', navbar(request.session)) + .replace('', getUserHTML(user)) + ); + }, +} + +function getUserHTML(user) { + const userPermDict = checkPermissions(user.permissions); + let userPerms = []; + for (const [key, value] of Object.entries(userPermDict)) { + if(value && key != "default") userPerms.push(key); + }; + let res = ` + + + + + + + + + + + +
IdentifiantPermissionsAction
${user.username}${userPerms.join(", ")}
`; + return res; +} diff --git a/src/html/pages/root/login_post.js b/src/html/pages/root/login_post.js index c791f87..528cef8 100644 --- a/src/html/pages/root/login_post.js +++ b/src/html/pages/root/login_post.js @@ -4,10 +4,10 @@ export default { async execute(request, response) { const { username, password } = request.body; console.log(request.body); - global.database.users.findOne({ where: { username: username } }).then(function (user) { + global.database.users.findOne({ where: { username: username } }).then(async function (user) { if (!user) { response.redirect('/login'); - } else if (!user.validPassword(password)) { + } else if (!await user.validPassword(password)) { response.redirect('/login'); } else { request.session.user = user.dataValues; diff --git a/utils/handler.js b/utils/handler.js index f3d0423..af25f0a 100644 --- a/utils/handler.js +++ b/utils/handler.js @@ -1,29 +1,89 @@ import fs from 'fs'; const pagesPath = "./src/html/pages/"; -async function deployHandler() { - global.handler = { - get: {}, - post: {}, +async function genHandler() { + const handler = { + get: [], + post: [], + path: [], + delete: [], }; let numberOfPages = 0; - const PagesCategories = fs + const endpointCategories = fs .readdirSync(pagesPath) .filter((file) => !file.includes(".")); - for (const category of PagesCategories) { - const pageFiles = fs + for (const category of endpointCategories) { + const endpointFiles = fs .readdirSync(`${pagesPath}${category}`) .filter((file) => file.endsWith(".js")); - for (const file of pageFiles) { - const { default: page } = await import(`.${pagesPath}${category}/${file}`); - global.handler[page.type][page.path] = page; + for (const file of endpointFiles) { + const { default: endpoint } = await import(`.${pagesPath}${category}/${file}`); + handler[endpoint.type].push(endpoint); console.log( - `\x1b[32mChargement de POST: ${page.path} !\x1b[0m`, + `\x1b[32mChargement de POST: ${endpoint.path} !\x1b[0m`, ); numberOfPages++; - console.log(numberOfPages + " pages chargées ! "); + console.log(numberOfPages + " endpoints chargés ! "); } } + return handler; +} + +async function deployHandler(app) { + const handler = await genHandler(); + + for(const endpoint of handler.get) { + app.get(endpoint.path, async (request, response) => { + const [path, args] = parseURL(request.originalUrl); + console.log("GET: " + path); + + if (endpoint.requiresLogin && !request.session.user) { + return response.redirect("/login"); + } + if (endpoint.permissions) { + if((endpoint.permissions & request.session.user.permissions) == 0) { + return response.status(403).send("Vous n'avez pas la permission d'effectuer cette action !"); + } + } + return await endpoint.execute( + request, + response, + ); + }); + } + + for(const endpoint of handler.post) { + app.post(endpoint.path, async (request, response) => { + console.log("POST: " + request.originalUrl); + + if (endpoint.requiresLogin && !request.session.user) { + return response.redirect("/login"); + } + if (endpoint.permissions) { + if((endpoint.permissions & request.session.user.permissions) == 0) { + return response.status(403).send("Vous n'avez pas la permission d'effectuer cette action !"); + } + } + return await endpoint.execute( + request, + response, + ); + }); + } +} + +function parseURL(URL) { + const spURL = URL.split("?"); + const path = spURL[0]; + if(!spURL[1]) return [path, {}]; + + const args = {}; + for (let i = 0; i < spURL[1].split("=").length; i+=2) { + const key = spURL[1].split("=")[i]; + const val = spURL[1].split("=")[i+1]; + args[key] = val; + } + return [path, args]; } export { deployHandler }; diff --git a/web.js b/web.js index 039d572..b00dd46 100644 --- a/web.js +++ b/web.js @@ -19,48 +19,7 @@ async function launchWeb() { app.use("/assets", express.static(`${process.env.WWW}/assets`)); app.use(favicon(`${process.env.WWW}/assets/images/favicon.ico`)); - await deployHandler(); - - app.post("*", async (request, response) => { - console.log("POST: " + request.originalUrl); - let handled = global.handler.post[request.originalUrl]; - - if(!handled) for(const path of Object.keys(global.handler.post)) { - if(new RegExp(path).test(request.originalUrl)) handled = global.handler.post[path]; - } - - if (!handled) return console.log(request.originalUrl); - if (handled.requiresLogin && !request.session.user) { - return response.redirect("/login"); - } - if (handled.permissions) { - if((handled.permissions & request.session.user.permissions) == 0) return response.status(403).send("Vous n'avez pas la permission d'effectuer cette action !"); - } - return await handled.execute( - request, - response, - ); - }); - - app.get("*", async (request, response) => { - const [path, args] = parseURL(request.originalUrl); - const argNum = Object.keys(args).length; - console.log(`GET: ${path} ${argNum > 0 ? '('+argNum+' args)' : ""}`); - let handled = global.handler.get[path]; - - if(!handled) for(const path of Object.keys(global.handler.get)) { - if(new RegExp(path).test(request.originalUrl)) handled = global.handler.get[path]; - } - - if (!handled) return; - if (handled.requiresLogin && !request.session.user) { - return response.redirect("/login"); - } - if (handled.permissions) { - if((handled.permissions & request.session.user.permissions) == 0) return response.status(403).send("Vous n'avez pas la permission d'accéder cette page !"); - } - return await handled.execute(request, response, args); - }); + await deployHandler(app); const PORT = process.env.PORT || 3000; app.listen(PORT, () => { @@ -68,18 +27,4 @@ async function launchWeb() { }); } -function parseURL(URL) { - const spURL = URL.split("?"); - const path = spURL[0]; - if(!spURL[1]) return [path, {}]; - - const args = {}; - for (let i = 0; i < spURL[1].split("=").length; i+=2) { - const key = spURL[1].split("=")[i]; - const val = spURL[1].split("=")[i+1]; - args[key] = val; - } - return [path, args]; -} - export { launchWeb }; diff --git a/www/dashboard/users/create.html b/www/dashboard/users/create.html index 3f87850..fa308ef 100644 --- a/www/dashboard/users/create.html +++ b/www/dashboard/users/create.html @@ -78,15 +78,36 @@ a { } -
+

Création de compte

Formulaire de création de compte.

diff --git a/www/dashboard/users/info.html b/www/dashboard/users/info.html new file mode 100644 index 0000000..a302101 --- /dev/null +++ b/www/dashboard/users/info.html @@ -0,0 +1,17 @@ + + + + Utilisateurs + + + + + + + + +