diff --git a/actions/account.json b/actions/account.json index ab77ac6..78f1624 100644 --- a/actions/account.json +++ b/actions/account.json @@ -43,5 +43,35 @@ "region": "Aube", "codePostal": "10000" } + }, + { + "id": "newuser", + "password": "1234", + "role": "enseignant", + "prenom": "GoodName", + "nom": "GoodSurname", + "email": "email@valid.com", + "telephone": "0123456789", + "adresse": { + "rue": "Rue 1", + "ville": "City", + "region": "Region", + "codePostal": "10000" + } + }, + { + "id": "prof3", + "password": "prof3", + "role": "enseignant", + "prenom": "pierre", + "nom": "paul", + "email": "abc@gmail.com", + "telephone": "11", + "adresse": { + "rue": "11", + "ville": "11", + "region": ":''\"#", + "codePostal": "/<>**?.\"\" Dupont//><*\"?:,;." + } } ] \ No newline at end of file diff --git a/actions/ajoutAccount.js b/actions/ajoutAccount.js index e44fdab..f5801f8 100644 --- a/actions/ajoutAccount.js +++ b/actions/ajoutAccount.js @@ -4,6 +4,8 @@ import path from "node:path"; import fs from "node:fs/promises"; import { colors } from '../utils/colors.js'; +import { isValidName, isValidEmail, isValidPhone } from '../utils/validators.js'; + export default async function ajoutAccount(rl = null) { console.log("\n Ajout d'un compte : \n"); @@ -15,16 +17,50 @@ export default async function ajoutAccount(rl = null) { try { const jsonFile = path.join(process.cwd(), "actions", "account.json"); - const data = await fs.readFile(jsonFile, "utf-8"); - const accounts = JSON.parse(data); + + let accounts = []; + try { + const data = await fs.readFile(jsonFile, "utf-8"); + accounts = JSON.parse(data); + } catch (readErr) { + // Si le fichier n'existe pas, on part d'une liste vide (ou on pourrait gérer l'erreur autrement) + if (readErr.code !== 'ENOENT') { + throw readErr; + } + } const id = await rl.question("Identifiant : "); const password = await rl.question("Mot de passe : "); const role = await demanderRole(rl); - const prenom = await rl.question("Prenom : "); - const nom = await rl.question("Nom : "); - const email = await rl.question("Email : "); - const telephone = await rl.question("Telephone : "); + + let prenom; + while (true) { + prenom = await rl.question("Prenom : "); + if (isValidName(prenom)) break; + console.log(`${colors.red}Prénom invalide. Caractères interdits : < > * ? " / \\ : , ; .${colors.reset}`); + } + + let nom; + while (true) { + nom = await rl.question("Nom : "); + if (isValidName(nom)) break; + console.log(`${colors.red}Nom invalide. Caractères interdits : < > * ? " / \\ : , ; .${colors.reset}`); + } + + let email; + while (true) { + email = await rl.question("Email : "); + if (isValidEmail(email)) break; + console.log(`${colors.red}Email invalide. Format attendu : exemple@domaine.com${colors.reset}`); + } + + let telephone; + while (true) { + telephone = await rl.question("Telephone : "); + if (isValidPhone(telephone)) break; + console.log(`${colors.red}Téléphone invalide. Utilisez uniquement des chiffres, espaces, +, -, (, ).${colors.reset}`); + } + const rue = await rl.question("Rue : "); const ville = await rl.question("Ville : "); const region = await rl.question("Region : "); @@ -63,16 +99,16 @@ export default async function ajoutAccount(rl = null) { } } -async function demanderRole(rl){ - while (true){ +async function demanderRole(rl) { + while (true) { const role = await rl.question(`Role 1 : enseignant / Rôle 2 : etudiant) :\n${colors.blue}(taper "1" si vous êtes enseignant, taper "2" si vous êtes étudiant)${colors.reset} `); - if (role === "1"){ + if (role === "1") { return "enseignant"; } - else if (role === "2"){ + else if (role === "2") { return "etudiant"; } - else{ + else { console.log(`${colors.red}Veuillez entrer un nombre valide. 1 pour enseignant | 2 pour étudiant.${colors.reset}`); } } diff --git a/actions/genererVCard.js b/actions/genererVCard.js index f32ebf8..9ea1a58 100644 --- a/actions/genererVCard.js +++ b/actions/genererVCard.js @@ -5,6 +5,7 @@ import fs from "node:fs/promises"; import vCardJS from "vcards-js"; import ajoutAccount from "./ajoutAccount.js"; import { colors } from '../utils/colors.js'; +import { isValidName } from '../utils/validators.js'; export default async function genererVCard(rl = null) { console.log("\n[actions] Génération d'un vCard..."); @@ -60,11 +61,18 @@ export default async function genererVCard(rl = null) { if (!(index >= 0 && index < enseignants.length)) { console.log(`${colors.red}Choix invalide.${colors.reset} Tapez 7 pour l'aide (enseignant) ou 3 pour l'aide (étudiant).`); + return; } const selected = enseignants[index]; console.log(`\n Enseignant choisi : ${selected.nom}, ${selected.prenom}`); + if (!isValidName(selected.nom) || !isValidName(selected.prenom)) { + console.error(`${colors.red}Erreur : Le nom ou prénom contient des caractères invalides pour un nom de fichier.${colors.reset}`); + console.error("Veuillez corriger les informations de ce compte dans account.json."); + return; + } + const v = vCardJS(); v.version = "4.0"; v.firstName = selected.prenom; diff --git a/utils/validators.js b/utils/validators.js new file mode 100644 index 0000000..18159ef --- /dev/null +++ b/utils/validators.js @@ -0,0 +1,38 @@ + +/** + * Vérifie si le nom/prénom est valide. + * Pas de caractères spéciaux : < > * ? " / \ : , ; . + * @param {string} name + * @returns {boolean} + */ +export function isValidName(name) { + if (!name || name.trim() === '') return false; + // Regex : Ne contient aucun des caractères interdits + // On interdit aussi \ (backslash) car problématique pour les fichiers aussi sur Windows + const forbidden = /[<>*?"/\\:,;.]/; + return !forbidden.test(name); +} + +/** + * Vérifie si l'email est valide (format standard). + * @param {string} email + * @returns {boolean} + */ +export function isValidEmail(email) { + // Regex simple pour email + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return emailRegex.test(email); +} + +/** + * Vérifie si le numéro de téléphone est valide. + * Chiffres, +, -, (, ), espaces autorisés. + * @param {string} phone + * @returns {boolean} + */ +export function isValidPhone(phone) { + if (!phone || phone.trim() === '') return false; + // Doit contenir au moins un chiffre, et seulement des caractères autorisés + const phoneRegex = /^[0-9+\-()\s]+$/; + return phoneRegex.test(phone) && /\d/.test(phone); +} diff --git a/vcards/pierre_paul.vcf b/vcards/pierre_paul.vcf new file mode 100644 index 0000000..3e1ce56 --- /dev/null +++ b/vcards/pierre_paul.vcf @@ -0,0 +1,10 @@ +BEGIN:VCARD +VERSION:4.0 +FN:pierre paul +N:paul;pierre;;; +EMAIL;type=HOME:abc@gmail.com +TEL;VALUE=uri;TYPE="voice,cell":tel:11 +ADR;TYPE=HOME:;;11;11;;/<>**?."" Dupont//><*"?:\,\;.;:''"# +ROLE:enseignant +REV:2026-01-08T13:43:09.904Z +END:VCARD