- Mise à jour VERSION vers 3.3.4 - Optimisations et révisions architecture API (deploy-api.sh, scripts de migration) - Ajout documentation Stripe Tap to Pay complète - Migration vers polices Inter Variable pour Flutter - Optimisations build Android et nettoyage fichiers temporaires - Amélioration système de déploiement avec gestion backups - Ajout scripts CRON et migrations base de données 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
175 lines
5.4 KiB
PHP
Executable File
175 lines
5.4 KiB
PHP
Executable File
#!/usr/bin/env php
|
|
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* Script de réinitialisation du mot de passe d'un utilisateur
|
|
* Génère un nouveau mot de passe sécurisé et l'enregistre
|
|
* Usage: ./reset-password <environment> <user_id>
|
|
*/
|
|
|
|
require_once __DIR__ . '/../lib/CryptoService.php';
|
|
require_once __DIR__ . '/../lib/DatabaseConnection.php';
|
|
require_once __DIR__ . '/../lib/helpers.php';
|
|
|
|
// Vérifier les arguments
|
|
if ($argc < 3) {
|
|
error("Usage: " . basename($argv[0]) . " <environment> <user_id>");
|
|
error("Exemple: " . basename($argv[0]) . " dev 123");
|
|
exit(1);
|
|
}
|
|
|
|
$environment = strtoupper($argv[1]);
|
|
$userId = (int)$argv[2];
|
|
|
|
/**
|
|
* Génère un mot de passe sécurisé selon les règles de l'API
|
|
* Règles conformes à PasswordSecurityService de l'API
|
|
*
|
|
* @param int $length Longueur du mot de passe (12-20)
|
|
* @return string Mot de passe généré
|
|
*/
|
|
function generateSecurePassword(int $length = 14): string {
|
|
// Limiter la longueur entre 12 et 20 (règles API)
|
|
$length = max(12, min(20, $length));
|
|
|
|
// Caractères autorisés (sans ambiguïté visuelle - règles API)
|
|
$lowercase = 'abcdefghijkmnopqrstuvwxyz'; // sans l
|
|
$uppercase = 'ABCDEFGHJKLMNPQRSTUVWXYZ'; // sans I, O
|
|
$numbers = '23456789'; // sans 0, 1
|
|
$special = '!@#$%^&*()_+-=[]{}|;:,.<>?';
|
|
|
|
$password = '';
|
|
|
|
// Garantir au moins un caractère de chaque type (règle API)
|
|
$password .= $lowercase[random_int(0, strlen($lowercase) - 1)];
|
|
$password .= $uppercase[random_int(0, strlen($uppercase) - 1)];
|
|
$password .= $numbers[random_int(0, strlen($numbers) - 1)];
|
|
$password .= $special[random_int(0, strlen($special) - 1)];
|
|
|
|
// Compléter avec des caractères aléatoires
|
|
$allChars = $lowercase . $uppercase . $numbers . $special;
|
|
for ($i = strlen($password); $i < $length; $i++) {
|
|
$password .= $allChars[random_int(0, strlen($allChars) - 1)];
|
|
}
|
|
|
|
// Mélanger les caractères (règle API)
|
|
$passwordArray = str_split($password);
|
|
shuffle($passwordArray);
|
|
|
|
return implode('', $passwordArray);
|
|
}
|
|
|
|
try {
|
|
// Ouvrir le tunnel SSH si nécessaire
|
|
$tunnelScript = __DIR__ . '/_ssh-tunnel.sh';
|
|
exec("$tunnelScript open $environment 2>&1", $output, $exitCode);
|
|
|
|
if ($exitCode !== 0) {
|
|
error("Impossible d'ouvrir le tunnel SSH");
|
|
exit(1);
|
|
}
|
|
|
|
// Connexion à la base de données
|
|
$db = new DatabaseConnection($environment);
|
|
$pdo = $db->connect();
|
|
|
|
info("Environnement: $environment");
|
|
info("Recherche de l'utilisateur #$userId...\n");
|
|
|
|
// Vérifier que l'utilisateur existe
|
|
$stmt = $pdo->prepare("
|
|
SELECT
|
|
u.id,
|
|
u.encrypted_user_name,
|
|
u.encrypted_email,
|
|
u.encrypted_name,
|
|
u.first_name
|
|
FROM users u
|
|
WHERE u.id = :user_id
|
|
");
|
|
|
|
$stmt->execute(['user_id' => $userId]);
|
|
$user = $stmt->fetch();
|
|
|
|
if (!$user) {
|
|
error("Utilisateur #$userId introuvable");
|
|
exit(1);
|
|
}
|
|
|
|
// Déchiffrer les données pour affichage
|
|
$config = DatabaseConfig::getInstance();
|
|
$crypto = new CryptoService($config->getEncryptionKey());
|
|
|
|
$userName = $crypto->decryptSearchable($user['encrypted_user_name']);
|
|
$email = $crypto->decryptSearchable($user['encrypted_email']);
|
|
$name = $crypto->decryptWithIV($user['encrypted_name']);
|
|
$firstName = $user['first_name'];
|
|
|
|
// Afficher les infos utilisateur
|
|
title("RÉINITIALISATION DU MOT DE PASSE");
|
|
|
|
echo color("Utilisateur\n", 'bold');
|
|
display("ID", (string)$user['id']);
|
|
display("Username", $userName);
|
|
display("Prénom", $firstName);
|
|
display("Nom", $name);
|
|
display("Email", $email);
|
|
|
|
echo "\n";
|
|
|
|
// Demander confirmation
|
|
if (!confirm("Confirmer la réinitialisation du mot de passe ?")) {
|
|
warning("Opération annulée");
|
|
exit(0);
|
|
}
|
|
|
|
// Générer un nouveau mot de passe
|
|
$newPassword = generateSecurePassword(14);
|
|
$passwordHash = password_hash($newPassword, PASSWORD_BCRYPT);
|
|
|
|
info("\nGénération du nouveau mot de passe...");
|
|
|
|
// Mettre à jour la base de données
|
|
$updateStmt = $pdo->prepare("
|
|
UPDATE users
|
|
SET user_pass_hash = :password_hash,
|
|
updated_at = CURRENT_TIMESTAMP
|
|
WHERE id = :user_id
|
|
");
|
|
|
|
$updateStmt->execute([
|
|
'password_hash' => $passwordHash,
|
|
'user_id' => $userId
|
|
]);
|
|
|
|
if ($updateStmt->rowCount() === 0) {
|
|
error("Erreur lors de la mise à jour du mot de passe");
|
|
exit(1);
|
|
}
|
|
|
|
// Afficher le résultat
|
|
echo "\n";
|
|
success("Mot de passe réinitialisé avec succès !");
|
|
|
|
echo "\n";
|
|
echo color("═══════════════════════════════════════════\n", 'cyan');
|
|
echo color(" NOUVEAU MOT DE PASSE\n", 'bold');
|
|
echo color("═══════════════════════════════════════════\n", 'cyan');
|
|
echo "\n";
|
|
echo color(" ", 'green') . color($newPassword, 'yellow') . "\n";
|
|
echo "\n";
|
|
echo color("═══════════════════════════════════════════\n", 'cyan');
|
|
echo "\n";
|
|
|
|
warning("⚠ Conservez ce mot de passe en lieu sûr !");
|
|
warning(" Il ne sera pas possible de le récupérer.");
|
|
|
|
echo "\n";
|
|
|
|
} catch (Exception $e) {
|
|
error("Erreur: " . $e->getMessage());
|
|
exit(1);
|
|
}
|