Add user deletion and subdomain handling

This commit is contained in:
Ninjdai 2023-12-12 13:43:47 +01:00
parent 3c9d92a497
commit 7caff58cdf
10 changed files with 122 additions and 23 deletions

View File

@ -16,6 +16,7 @@
"express-session": "^1.17.3", "express-session": "^1.17.3",
"sequelize": "^6.35.1", "sequelize": "^6.35.1",
"serve-favicon": "^2.5.0", "serve-favicon": "^2.5.0",
"sqlite3": "^5.1.6" "sqlite3": "^5.1.6",
"vhost": "^3.0.2"
} }
} }

View File

@ -0,0 +1,19 @@
import { permissionBits } from "../../../../../utils/permissions.js";
export default {
path: "/api/contacts/:phone",
requiresLogin: true,
permissions: permissionBits.ADMIN,
type: "delete",
async execute(request, response) {
const { phone } = request.params;
const contact = await global.database.contacts.findOne({
where: { phone: phone },
});
if (!contact) return response.status(404).send({ message: "Contact does not exist" });
await contact.destroy();
response.status(200).send({});
},
};

View File

@ -0,0 +1,19 @@
import { permissionBits } from "../../../../../utils/permissions.js";
export default {
path: "/api/users/:username",
requiresLogin: true,
permissions: permissionBits.ADMIN,
type: "delete",
async execute(request, response) {
const { username } = request.params;
const user = await global.database.users.findOne({
where: { username: username },
});
if (!user) return response.status(404).send({ message: "User does not exist" });
await user.destroy();
response.status(200).send({});
},
};

View File

@ -36,7 +36,7 @@ function genUserTable(users) {
<tr> <tr>
<td><a href='./${user.username}'>${user.username}</a></td> <td><a href='./${user.username}'>${user.username}</a></td>
<td>${userPerms.join(", ")}</td> <td>${userPerms.join(", ")}</td>
<!--<td><button>Supprimer</button></td>--> <td><button onclick="deleteUser('${user.username}');">Supprimer</button></td>
</tr>`; </tr>`;
} }
res += `</table>`; res += `</table>`;

View File

@ -1,6 +1,9 @@
import { permissionBits, checkPermissions } from '../../../../../utils/permissions.js'; import {
import { readFile } from 'fs/promises'; permissionBits,
import { navbar } from '../../../../../utils/navbar.js'; checkPermissions,
} from "../../../../../utils/permissions.js";
import { readFile } from "fs/promises";
import { navbar } from "../../../../../utils/navbar.js";
export default { export default {
path: "/dashboard/users/:username", path: "/dashboard/users/:username",
@ -9,22 +12,28 @@ export default {
type: "get", type: "get",
async execute(request, response) { async execute(request, response) {
const { username } = request.params; const { username } = request.params;
const user = await global.database.users.findOne({ where: { username: username } }); const user = await global.database.users.findOne({
if(!user) return response.redirect('/dashboard/users'); where: { username: username },
const html = await readFile(`${process.env.WWW}/dashboard/users/info.html`); });
response.send(html.toString() if (!user) return response.redirect("/dashboard/users");
.replace('<NAVBAR>', navbar(request.session)) const html = await readFile(
.replace('<USERINFO>', getUserHTML(user)) `${process.env.WWW}/dashboard/users/info.html`,
);
response.send(
html
.toString()
.replace("<NAVBAR>", navbar(request.session))
.replace("<USERINFO>", getUserHTML(user)),
); );
}, },
} };
function getUserHTML(user) { function getUserHTML(user) {
const userPermDict = checkPermissions(user.permissions); const userPermDict = checkPermissions(user.permissions);
let userPerms = []; let userPerms = [];
for (const [key, value] of Object.entries(userPermDict)) { for (const [key, value] of Object.entries(userPermDict)) {
if(value && key != "default") userPerms.push(key); if (value && key != "default") userPerms.push(key);
}; }
let res = ` let res = `
<table> <table>
<tr> <tr>
@ -35,7 +44,7 @@ function getUserHTML(user) {
<tr> <tr>
<td>${user.username}</td> <td>${user.username}</td>
<td>${userPerms.join(", ")}</td> <td>${userPerms.join(", ")}</td>
<td><button>Supprimer</button></td> <td><button onclick="deleteUser('${user.username}');">Supprimer</button></td>
</tr> </tr>
</table>`; </table>`;
return res; return res;

View File

@ -80,6 +80,25 @@ async function deployHandler(app) {
); );
}); });
} }
for(const endpoint of handler.delete) {
app.delete(endpoint.path, async (request, response) => {
console.log("DELETE: " + 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) { function parseURL(URL) {

9
web.js
View File

@ -2,9 +2,11 @@ import express from "express";
import session from "express-session"; import session from "express-session";
import { deployHandler } from "./utils/handler.js"; import { deployHandler } from "./utils/handler.js";
import favicon from "serve-favicon"; import favicon from "serve-favicon";
import vhost from "vhost";
async function launchWeb() { async function launchWeb() {
const app = express(); const app = express();
const routerApp = express();
app.use(express.json()); // Used to parse JSON bodies app.use(express.json()); // Used to parse JSON bodies
app.use(express.urlencoded({ extended: false })); //Parse URL-encoded bodies app.use(express.urlencoded({ extended: false })); //Parse URL-encoded bodies
@ -15,6 +17,7 @@ async function launchWeb() {
saveUninitialized: true, saveUninitialized: true,
}), }),
); );
routerApp.use(vhost(`${process.env.SERVER_URL}`, app));
app.use("/assets", express.static(`${process.env.WWW}/assets`)); app.use("/assets", express.static(`${process.env.WWW}/assets`));
app.use(favicon(`${process.env.WWW}/assets/images/favicon.ico`)); app.use(favicon(`${process.env.WWW}/assets/images/favicon.ico`));
@ -22,8 +25,10 @@ async function launchWeb() {
await deployHandler(app); await deployHandler(app);
const PORT = process.env.PORT || 3000; const PORT = process.env.PORT || 3000;
app.listen(PORT, () => { routerApp.listen(PORT, () => {
console.log(`App available at http://localhost:${PORT}`); console.log(
`App available at http://${process.env.SERVER_URL}:${PORT}`,
);
}); });
} }

View File

@ -1,3 +1,4 @@
<!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">

View File

@ -11,8 +11,21 @@
</style> </style>
</head> </head>
<body> <body>
<NAVBAR> <script>
<USERINFO> function deleteUser(username) {
<a href='./'><p>Retour</p></a> fetch(`/api/users/${username}`, {
method: "DELETE",
})
.then(async (response) => {
const res = await response.json();
console.log(res);
if(!response.ok) return alert(res.message);
location.reload();
});
}
</script>
<NAVBAR>
<USERINFO>
<a href='./'><p>Retour</p></a>
</body> </body>
</html> </html>

View File

@ -11,8 +11,21 @@
</style> </style>
</head> </head>
<body> <body>
<NAVBAR> <script>
<USERTABLE> function deleteUser(username) {
<a href='./'><p>Retour</p></a> fetch(`/api/users/${username}`, {
method: "DELETE",
})
.then(async (response) => {
const res = await response.json();
console.log(res);
if(!response.ok) return alert(res.message);
location.reload();
});
}
</script>
<NAVBAR>
<USERTABLE>
<a href='./'><p>Retour</p></a>
</body> </body>
</html> </html>