Files
geo/api/src/Controllers/PasswordController.php
pierre 2f5946a184 feat: Version 3.5.2 - Configuration Stripe et gestion des immeubles
- Configuration complète Stripe pour les 3 environnements (DEV/REC/PROD)
  * DEV: Clés TEST Pierre (mode test)
  * REC: Clés TEST Client (mode test)
  * PROD: Clés LIVE Client (mode live)
- Ajout de la gestion des bases de données immeubles/bâtiments
  * Configuration buildings_database pour DEV/REC/PROD
  * Service BuildingService pour enrichissement des adresses
- Optimisations pages et améliorations ergonomie
- Mises à jour des dépendances Composer
- Nettoyage des fichiers obsolètes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-09 18:26:27 +01:00

210 lines
7.4 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Controllers;
require_once __DIR__ . '/../Services/PasswordSecurityService.php';
require_once __DIR__ . '/../Services/LogService.php';
use Request;
use Response;
use App\Services\LogService;
use App\Services\PasswordSecurityService;
/**
* Contrôleur pour la gestion de la sécurité des mots de passe
* Fournit des endpoints pour vérifier la force et la compromission des mots de passe
*/
class PasswordController {
/**
* Vérifie la force d'un mot de passe et s'il a été compromis
* Endpoint utilisable sans authentification pour le formulaire d'inscription
*
* POST /api/password/check
*/
public function checkStrength(): void {
try {
$data = Request::getJson();
if (!isset($data['password']) || empty($data['password'])) {
Response::json([
'status' => 'error',
'message' => 'Mot de passe requis'
], 400);
return;
}
$password = $data['password'];
$checkCompromised = $data['check_compromised'] ?? true;
// Validation du mot de passe
$validation = PasswordSecurityService::validatePassword($password, $checkCompromised);
// Estimation de la force
$strength = PasswordSecurityService::estimatePasswordStrength($password);
// Vérification spécifique de compromission si demandée
$compromisedInfo = null;
if ($checkCompromised) {
$compromisedCheck = PasswordSecurityService::checkPasswordCompromised($password);
if ($compromisedCheck['compromised']) {
$compromisedInfo = [
'compromised' => true,
'occurrences' => $compromisedCheck['occurrences'],
'message' => sprintf(
'Ce mot de passe a été trouvé %s fois dans des fuites de données',
number_format($compromisedCheck['occurrences'], 0, ',', ' ')
)
];
}
}
Response::json([
'status' => 'success',
'valid' => $validation['valid'],
'errors' => $validation['errors'],
'warnings' => $validation['warnings'],
'strength' => $strength,
'compromised' => $compromisedInfo
]);
} catch (\Exception $e) {
LogService::log('Erreur lors de la vérification du mot de passe', [
'level' => 'error',
'error' => $e->getMessage()
]);
Response::json([
'status' => 'error',
'message' => 'Erreur lors de la vérification du mot de passe'
], 500);
}
}
/**
* Génère un mot de passe sécurisé aléatoire
* Endpoint nécessitant une authentification
*
* GET /api/password/generate
*/
public function generate(): void {
try {
// Vérifier l'authentification
if (!isset($_SESSION['user_id'])) {
Response::json([
'status' => 'error',
'message' => 'Authentification requise'
], 401);
return;
}
// Récupérer les paramètres optionnels
$length = isset($_GET['length']) ? intval($_GET['length']) : 14;
$length = max(12, min(20, $length)); // Limiter entre 12 et 20
// Générer un mot de passe non compromis
$password = PasswordSecurityService::generateSecurePassword($length);
if ($password === null) {
// En cas d'échec, utiliser la méthode classique
$password = $this->generateFallbackPassword($length);
}
// Calculer la force du mot de passe généré
$strength = PasswordSecurityService::estimatePasswordStrength($password);
Response::json([
'status' => 'success',
'password' => $password,
'length' => strlen($password),
'strength' => $strength
]);
} catch (\Exception $e) {
LogService::log('Erreur lors de la génération du mot de passe', [
'level' => 'error',
'error' => $e->getMessage()
]);
Response::json([
'status' => 'error',
'message' => 'Erreur lors de la génération du mot de passe'
], 500);
}
}
/**
* Vérifie uniquement si un mot de passe est compromis
* Endpoint rapide pour vérification en temps réel
*
* POST /api/password/compromised
*/
public function checkCompromised(): void {
try {
$data = Request::getJson();
if (!isset($data['password']) || empty($data['password'])) {
Response::json([
'status' => 'error',
'message' => 'Mot de passe requis'
], 400);
return;
}
$password = $data['password'];
// Vérification de compromission
$compromisedCheck = PasswordSecurityService::checkPasswordCompromised($password);
$response = [
'status' => 'success',
'compromised' => $compromisedCheck['compromised'],
'occurrences' => $compromisedCheck['occurrences']
];
if ($compromisedCheck['compromised']) {
$response['message'] = sprintf(
'Ce mot de passe a été trouvé %s fois dans des fuites de données',
number_format($compromisedCheck['occurrences'], 0, ',', ' ')
);
$response['recommendation'] = 'Il est fortement recommandé de choisir un autre mot de passe';
}
if ($compromisedCheck['error']) {
$response['warning'] = 'Impossible de vérifier complètement le mot de passe';
}
Response::json($response);
} catch (\Exception $e) {
LogService::log('Erreur lors de la vérification de compromission', [
'level' => 'error',
'error' => $e->getMessage()
]);
Response::json([
'status' => 'error',
'message' => 'Erreur lors de la vérification'
], 500);
}
}
/**
* Génère un mot de passe de secours si le service principal échoue
*
* @param int $length Longueur du mot de passe
* @return string Le mot de passe généré
*/
private function generateFallbackPassword(int $length): string {
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+-=[]{}|;:,.<>?';
$password = '';
for ($i = 0; $i < $length; $i++) {
$password .= $chars[random_int(0, strlen($chars) - 1)];
}
return $password;
}
}