ajout envoi smtp (paramètres, test envois, envoi à 1 participant). protège vue mot de passe

- ajout filtre page statistiques
This commit is contained in:
Yannick Le Duc
2025-08-25 18:28:14 +02:00
parent caed358661
commit b0a945f07b
21 changed files with 3523 additions and 30 deletions

73
src/lib/encryption.ts Normal file
View File

@@ -0,0 +1,73 @@
import { createCipheriv, createDecipheriv, randomBytes, pbkdf2Sync } from 'crypto';
// Clé de chiffrement dérivée de la clé Supabase
const deriveKey = (): Buffer => {
const salt = process.env.SUPABASE_ANON_KEY || 'default-salt';
return pbkdf2Sync(salt, 'mes-budgets-participatifs', 100000, 32, 'sha256');
};
export const encryptionService = {
/**
* Chiffre une valeur avec AES-256-GCM
*/
encrypt(value: string): string {
if (!value) return '';
const key = deriveKey();
const iv = randomBytes(16);
const cipher = createCipheriv('aes-256-gcm', key, iv);
let encrypted = cipher.update(value, 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag();
// Format: iv:authTag:encryptedData
return `${iv.toString('hex')}:${authTag.toString('hex')}:${encrypted}`;
},
/**
* Déchiffre une valeur chiffrée avec AES-256-GCM
*/
decrypt(encryptedValue: string): string {
if (!encryptedValue) return '';
try {
const parts = encryptedValue.split(':');
if (parts.length !== 3) {
throw new Error('Format de chiffrement invalide');
}
const [ivHex, authTagHex, encryptedData] = parts;
const key = deriveKey();
const iv = Buffer.from(ivHex, 'hex');
const authTag = Buffer.from(authTagHex, 'hex');
const decipher = createDecipheriv('aes-256-gcm', key, iv);
decipher.setAuthTag(authTag);
let decrypted = decipher.update(encryptedData, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
} catch (error) {
console.error('Erreur lors du déchiffrement:', error);
return '';
}
},
/**
* Vérifie si une valeur est chiffrée
*/
isEncrypted(value: string): boolean {
return value && value.includes(':') && value.split(':').length === 3;
},
/**
* Masque une valeur pour l'affichage
*/
mask(value: string, maskChar: string = '•'): string {
if (!value) return '';
return maskChar.repeat(Math.min(value.length, 8));
}
};