Add contact management

This commit is contained in:
Ninjdai 2023-12-11 21:50:58 +01:00
parent 1cf5b5a089
commit 8212339da4
14 changed files with 244 additions and 39 deletions

View File

@ -1,22 +0,0 @@
import { permissionBits } from "../../../../utils/permissions.js";
export default {
path: "/api/contacts(/*)?",
requiresLogin: true,
permissions: permissionBits.CALL,
type: "post",
async execute(request, response) {
const phone = request.originalUrl.split("/")[3];
const operation = request.originalUrl.split("/")[4];
switch(operation) {
case 'call':
global.events.submitEvent.emit("contacts/call", request.body);
response.redirect("/calls");
break
case 'add':
global.events.submitEvent.emit("contacts/add", request.body);
//response.redirect("/");
break
}
},
};

View File

@ -0,0 +1,26 @@
import { permissionBits } from "../../../../../utils/permissions.js";
export default {
path: "/api/contacts/:phone",
requiresLogin: true,
permissions: permissionBits.ADMIN,
type: "post",
async execute(request, response) {
const { phone } = request.params;
const { firstName, lastName } = request.body;
if (
await global.database.contacts.findOne({
where: { phone: phone },
})
) return response.status(409).send({ message: "Contact already exists" });
const contactParams = {
phone: phone,
firstName: firstName,
lastName: lastName,
};
console.log(`Creating contact ${phone}`);
console.log(contactParams);
await global.database.contacts.create(contactParams);
response.status(201).send(contactParams);
},
};

View File

@ -1,4 +1,4 @@
import { permissionBits } from "../../../../utils/permissions.js"; import { permissionBits } from "../../../../../utils/permissions.js";
export default { export default {
path: "/api/users/:username", path: "/api/users/:username",
@ -12,7 +12,7 @@ export default {
await global.database.users.findOne({ await global.database.users.findOne({
where: { username: username }, where: { username: username },
}) })
) return response.status(412).send({ message: "User already exists" }); ) return response.status(409).send({ message: "User already exists" });
if (!(permissions & permissionBits.DEFAULT)) if (!(permissions & permissionBits.DEFAULT))
permissions ^= permissionBits.DEFAULT; permissions ^= permissionBits.DEFAULT;

View File

@ -1,4 +1,4 @@
import { permissionBits } from "../../../../utils/permissions.js"; import { permissionBits } from "../../../../../utils/permissions.js";
export default { export default {
path: "/api/users/:username", path: "/api/users/:username",

View File

@ -0,0 +1,22 @@
import { readFile } from "fs/promises";
import { navbar } from "../../../../../utils/navbar.js";
import { permissionBits } from "../../../../../utils/permissions.js";
export default {
path: "/dashboard/contacts/create",
requiresLogin: true,
permissions: permissionBits.ADMIN,
type: "get",
async execute(request, response, args) {
let res = await readFile(
`${process.env.WWW}/dashboard/contacts/create.html`,
"utf8",
);
if (args?.error)
res += `
<script type="text/javascript">
alert("Erreur: ${args.error.replaceAll("%20", " ")}");
</script>`;
response.send(res.replaceAll("<NAVBAR>", navbar(request.session)));
},
};

View File

@ -0,0 +1,16 @@
import { permissionBits } from '../../../../../utils/permissions.js';
import { readFile } from 'fs/promises';
import { navbar } from '../../../../../utils/navbar.js';
export default {
path: "/dashboard/contacts",
requiresLogin: true,
permissions: permissionBits.ADMIN,
type: "get",
async execute(request, response) {
const html = await readFile(`${process.env.WWW}/dashboard/contacts/index.html`);
return await response.send(html.toString()
.replace('<NAVBAR>', navbar(request.session))
);
},
}

View File

@ -1,6 +1,6 @@
import { readFile } from "fs/promises"; import { readFile } from "fs/promises";
import { navbar } from "../../../../utils/navbar.js"; import { navbar } from "../../../../../utils/navbar.js";
import { permissionBits } from "../../../../utils/permissions.js"; import { permissionBits } from "../../../../../utils/permissions.js";
export default { export default {
path: "/dashboard/users/create", path: "/dashboard/users/create",

View File

@ -1,6 +1,6 @@
import { permissionBits } from '../../../../utils/permissions.js'; import { permissionBits } from '../../../../../utils/permissions.js';
import { readFile } from 'fs/promises'; import { readFile } from 'fs/promises';
import { navbar } from '../../../../utils/navbar.js'; import { navbar } from '../../../../../utils/navbar.js';
export default { export default {
path: "/dashboard/users", path: "/dashboard/users",

View File

@ -1,6 +1,6 @@
import { navbar } from '../../../../utils/navbar.js'; import { navbar } from '../../../../../utils/navbar.js';
import { readFile } from 'fs/promises'; import { readFile } from 'fs/promises';
import { permissionBits, checkPermissions } from '../../../../utils/permissions.js'; import { permissionBits, checkPermissions } from '../../../../../utils/permissions.js';
export default { export default {
path: "/dashboard/users/list", path: "/dashboard/users/list",

View File

@ -1,6 +1,6 @@
import { permissionBits, checkPermissions } from '../../../../utils/permissions.js'; import { permissionBits, checkPermissions } from '../../../../../utils/permissions.js';
import { readFile } from 'fs/promises'; import { readFile } from 'fs/promises';
import { navbar } from '../../../../utils/navbar.js'; import { navbar } from '../../../../../utils/navbar.js';
export default { export default {
path: "/dashboard/users/:username", path: "/dashboard/users/:username",

View File

@ -9,10 +9,20 @@ async function genHandler() {
delete: [], delete: [],
}; };
let numberOfPages = 0; let numberOfPages = 0;
const endpointCategories = fs const endpointFiles = fs
.readdirSync(pagesPath) .readdirSync(pagesPath, { recursive: true })
.filter((file) => !file.includes(".")); .filter((file) => file.endsWith(".js"));
for (const category of endpointCategories) { console.log(endpointFiles)
for (const file of endpointFiles) {
const { default: endpoint } = await import(`.${pagesPath}/${file}`);
handler[endpoint.type].push(endpoint);
console.log(
`\x1b[32mChargement de POST: ${endpoint.path} !\x1b[0m`,
);
numberOfPages++;
console.log(numberOfPages + " endpoints chargés ! ");
}
/*for (const category of endpointCategories) {
const endpointFiles = fs const endpointFiles = fs
.readdirSync(`${pagesPath}${category}`) .readdirSync(`${pagesPath}${category}`)
.filter((file) => file.endsWith(".js")); .filter((file) => file.endsWith(".js"));
@ -25,7 +35,7 @@ async function genHandler() {
numberOfPages++; numberOfPages++;
console.log(numberOfPages + " endpoints chargés ! "); console.log(numberOfPages + " endpoints chargés ! ");
} }
} }*/
return handler; return handler;
} }
@ -86,4 +96,14 @@ function parseURL(URL) {
return [path, args]; return [path, args];
} }
export { deployHandler }; function recursiveFileSearch(directory) {
const files = [];
fs.readdirSync(directory).forEach(File => {
const Absolute = Path.join(directory, File);
if (fs.statSync(Absolute).isDirectory()) return ThroughDirectory(Absolute);
else return files.push(Absolute);
});
return files;
}
export { deployHandler, parseURL };

View File

@ -0,0 +1,127 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Utilisateurs</title>
<style>
body {
font-family: Arial, Helvetica, sans-serif;
background-color: black;
}
* {
box-sizing: border-box;
}
/* Add padding to containers */
.container {
padding: 16px;
background-color: white;
display: block;
position: relative;
padding-left: 35px;
margin-bottom: 12px;
cursor: pointer;
font-size: 22px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
/* Full-width input fields */
input[type=text], input[type=password] {
width: 100%;
padding: 15px;
margin: 5px 0 22px 0;
display: inline-block;
border: none;
background: #f1f1f1;
}
input[type=text]:focus, input[type=password]:focus {
background-color: #ddd;
outline: none;
}
/* Overwrite default styles of hr */
hr {
border: 1px solid #f1f1f1;
margin-bottom: 25px;
}
/* Set a style for the submit button */
.registerbtn {
background-color: #04AA6D;
color: white;
padding: 16px 20px;
margin: 8px 0;
border: none;
cursor: pointer;
width: 100%;
opacity: 0.9;
}
.registerbtn:hover {
opacity: 1;
}
/* Add a blue text color to links */
a {
color: dodgerblue;
}
/* Set a grey background color and center the text of the "sign in" section */
.signin {
background-color: #f1f1f1;
text-align: center;
}
</style>
<script>
function createContactFromForm() {
const form = document.getElementById("contactCreateForm");
fetch(`/api/contacts/${form.phone.value}`, {
method: "POST",
body: JSON.stringify({
phone: form.phone.value,
firstName: form.firstName.value,
lastName: form.lastName.value,
}),
headers: {
"Content-type": "application/json; charset=UTF-8"
}
})
.then(async (response) => {
const res = await response.json();
console.log(res);
if(!response.ok) return alert(res.message);
form.reset();
});
}
</script>
</head>
<body>
<NAVBAR>
<form action="javascript:createContactFromForm()" id="contactCreateForm">
<div class="container">
<h1>Création de compte</h1>
<p>Formulaire d'ajout de contact.</p>
<hr>
<label for="phone"><b>Numéro de téléphone</b></label>
<input type="tel" placeholder="Entrez le numéro de téléphone" name="phone" id="phone" required>
<label for="firstName"><b>Prénom</b></label>
<input type="text" placeholder="Prénom du contact" name="firstName" id="firstName" required>
<label for="lastName"><b>Nom</b></label>
<input type="text" placeholder="Nom du contact" name="lastName" id="lastName" required>
<hr>
<button type="submit" class="registerbtn">Register</button>
</div>
</form>
</body>
</html>

View File

@ -0,0 +1,15 @@
<html>
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
<title>Contacts</title>
</head>
<body>
<NAVBAR>
<h1>Gestion des contacts</h1>
<p><a href='/dashboard/contacts/list'>Liste des contacts</a></p>
<p><a href='/dashboard/contacts/create'>Ajouter un contact</a></p>
<p><a href='/dashboard'>Retour</a></p>
</body>
</html>

View File

@ -10,6 +10,7 @@
<h1>Dashboard</h1> <h1>Dashboard</h1>
<p><a href='/calls'>Phoning</a></p> <p><a href='/calls'>Phoning</a></p>
<p><a href='/dashboard/users'>Gestion des utilisateurs</a></p> <p><a href='/dashboard/users'>Gestion des utilisateurs</a></p>
<p><a href='/dashboard/contacts'>Gestion des contacts</a></p>
<p><a href='/logout'>Déconnexion</a></p> <p><a href='/logout'>Déconnexion</a></p>
</body> </body>
</html> </html>