feat: Version 3.3.4 - Nouvelle architecture pages, optimisations widgets Flutter et API

- 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>
This commit is contained in:
pierre
2025-10-05 20:11:15 +02:00
parent 2786252307
commit 570a1fa1f0
212 changed files with 24275 additions and 11321 deletions

131
bao/bin/search-email Executable file
View File

@@ -0,0 +1,131 @@
#!/usr/bin/env php
<?php
declare(strict_types=1);
/**
* Script de recherche par email (déchiffré)
* Usage: ./search-email <environment> <email>
*/
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> <email>");
error("Exemple: " . basename($argv[0]) . " dev contact@example.com");
exit(1);
}
$environment = strtoupper($argv[1]);
$searchEmail = strtolower(trim($argv[2]));
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'email: $searchEmail\n");
// Récupérer TOUS les utilisateurs (on doit déchiffrer pour chercher)
$stmt = $pdo->query("
SELECT
u.id,
u.encrypted_user_name,
u.encrypted_email,
u.encrypted_name,
u.first_name,
u.fk_role,
u.fk_entite,
r.libelle as role_name,
e.encrypted_name as entite_encrypted_name
FROM users u
LEFT JOIN x_users_roles r ON u.fk_role = r.id
LEFT JOIN entites e ON u.fk_entite = e.id
ORDER BY u.id
");
$allUsers = $stmt->fetchAll();
// Déchiffrer et filtrer
$config = DatabaseConfig::getInstance();
$crypto = new CryptoService($config->getEncryptionKey());
$matchedUsers = [];
info("Analyse de " . count($allUsers) . " utilisateurs...");
foreach ($allUsers as $user) {
$email = $crypto->decryptSearchable($user['encrypted_email']);
if ($email && strtolower($email) === $searchEmail) {
$matchedUsers[] = [
'id' => $user['id'],
'username' => $crypto->decryptSearchable($user['encrypted_user_name']),
'email' => $email,
'prenom' => $user['first_name'],
'nom' => $crypto->decryptWithIV($user['encrypted_name']),
'role' => $user['role_name'],
'entite_id' => $user['fk_entite'],
'entite' => $crypto->decryptWithIV($user['entite_encrypted_name']),
];
}
}
if (empty($matchedUsers)) {
warning("\nAucun utilisateur trouvé avec l'email: $searchEmail");
exit(0);
}
// Affichage
echo "\n";
title("RÉSULTATS DE LA RECHERCHE - " . count($matchedUsers) . " utilisateur(s) trouvé(s)");
if (count($matchedUsers) > 1) {
warning("Attention: Plusieurs comptes utilisent le même email (autorisé par le système)");
echo "\n";
}
foreach ($matchedUsers as $index => $user) {
echo color("═══ Utilisateur #" . $user['id'] . " ═══", 'cyan') . "\n";
display("Username", $user['username']);
display("Prénom", $user['prenom']);
display("Nom", $user['nom']);
display("Email", $user['email']);
display("Rôle", $user['role']);
display("Entité ID", (string)$user['entite_id']);
display("Entité Nom", $user['entite']);
echo "\n";
}
success("Recherche terminée");
// Proposer d'afficher les détails complets
if (count($matchedUsers) === 1) {
echo "\n";
if (confirm("Afficher les détails complets de cet utilisateur ?")) {
echo "\n";
$userId = $matchedUsers[0]['id'];
$decryptUserScript = __DIR__ . '/decrypt-user';
passthru("$decryptUserScript $environment $userId");
}
}
} catch (Exception $e) {
error("Erreur: " . $e->getMessage());
exit(1);
}