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:
254
bao/bin/search-user
Executable file
254
bao/bin/search-user
Executable file
@@ -0,0 +1,254 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Script de recherche d'utilisateurs par chaîne
|
||||
* Recherche dans : username, nom, prénom, secteur
|
||||
* Usage: ./search-user <environment> <search_string>
|
||||
*/
|
||||
|
||||
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> <search_string>");
|
||||
error("Exemple: " . basename($argv[0]) . " dev dupont");
|
||||
error(" " . basename($argv[0]) . " dev secteur_a");
|
||||
error(" " . basename($argv[0]) . " dev j.dupont");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$environment = strtoupper($argv[1]);
|
||||
$searchString = strtolower(trim($argv[2]));
|
||||
|
||||
if (strlen($searchString) < 2) {
|
||||
error("La recherche doit contenir au moins 2 caractères");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
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: '$searchString'");
|
||||
info("Champs: username, nom, prénom, secteur\n");
|
||||
|
||||
// Récupérer les utilisateurs avec sect_name (en clair) et first_name (en clair)
|
||||
// On peut filtrer directement sur ces deux champs
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT
|
||||
u.id,
|
||||
u.encrypted_user_name,
|
||||
u.encrypted_email,
|
||||
u.encrypted_name,
|
||||
u.first_name,
|
||||
u.sect_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
|
||||
WHERE LOWER(u.first_name) LIKE :search1
|
||||
OR LOWER(u.sect_name) LIKE :search2
|
||||
ORDER BY u.id
|
||||
");
|
||||
|
||||
$searchPattern = '%' . $searchString . '%';
|
||||
$stmt->execute([
|
||||
'search1' => $searchPattern,
|
||||
'search2' => $searchPattern
|
||||
]);
|
||||
|
||||
$preFilteredUsers = $stmt->fetchAll();
|
||||
|
||||
// Récupérer TOUS les utilisateurs pour chercher dans les champs chiffrés
|
||||
$stmtAll = $pdo->query("
|
||||
SELECT
|
||||
u.id,
|
||||
u.encrypted_user_name,
|
||||
u.encrypted_email,
|
||||
u.encrypted_name,
|
||||
u.first_name,
|
||||
u.sect_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 = $stmtAll->fetchAll();
|
||||
|
||||
info("Analyse de " . count($allUsers) . " utilisateurs...\n");
|
||||
|
||||
// Déchiffrer et filtrer
|
||||
$config = DatabaseConfig::getInstance();
|
||||
$crypto = new CryptoService($config->getEncryptionKey());
|
||||
|
||||
$matchedUsers = [];
|
||||
$seenIds = [];
|
||||
|
||||
// Ajouter d'abord les résultats pré-filtrés (sect_name, first_name)
|
||||
foreach ($preFilteredUsers as $user) {
|
||||
$username = $crypto->decryptSearchable($user['encrypted_user_name']);
|
||||
$name = $crypto->decryptWithIV($user['encrypted_name']);
|
||||
|
||||
// Vérifier aussi dans les champs chiffrés
|
||||
$matches = false;
|
||||
$matchedFields = [];
|
||||
|
||||
if (stripos($user['first_name'], $searchString) !== false) {
|
||||
$matches = true;
|
||||
$matchedFields[] = 'prénom';
|
||||
}
|
||||
if (stripos($user['sect_name'], $searchString) !== false) {
|
||||
$matches = true;
|
||||
$matchedFields[] = 'secteur';
|
||||
}
|
||||
if ($username && stripos($username, $searchString) !== false) {
|
||||
$matches = true;
|
||||
$matchedFields[] = 'username';
|
||||
}
|
||||
if ($name && stripos($name, $searchString) !== false) {
|
||||
$matches = true;
|
||||
$matchedFields[] = 'nom';
|
||||
}
|
||||
|
||||
if ($matches) {
|
||||
$matchedUsers[] = [
|
||||
'id' => $user['id'],
|
||||
'username' => $username ?? '-',
|
||||
'prenom' => $user['first_name'] ?? '-',
|
||||
'nom' => $name ?? '-',
|
||||
'secteur' => $user['sect_name'] ?? '-',
|
||||
'role' => $user['role_name'] ?? '-',
|
||||
'entite' => $crypto->decryptWithIV($user['entite_encrypted_name']) ?? '-',
|
||||
'matched_in' => implode(', ', $matchedFields),
|
||||
];
|
||||
$seenIds[$user['id']] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Chercher dans les utilisateurs restants (pour username et nom chiffrés)
|
||||
foreach ($allUsers as $user) {
|
||||
if (isset($seenIds[$user['id']])) {
|
||||
continue; // Déjà trouvé
|
||||
}
|
||||
|
||||
$username = $crypto->decryptSearchable($user['encrypted_user_name']);
|
||||
$name = $crypto->decryptWithIV($user['encrypted_name']);
|
||||
|
||||
$matches = false;
|
||||
$matchedFields = [];
|
||||
|
||||
if ($username && stripos($username, $searchString) !== false) {
|
||||
$matches = true;
|
||||
$matchedFields[] = 'username';
|
||||
}
|
||||
if ($name && stripos($name, $searchString) !== false) {
|
||||
$matches = true;
|
||||
$matchedFields[] = 'nom';
|
||||
}
|
||||
|
||||
if ($matches) {
|
||||
$matchedUsers[] = [
|
||||
'id' => $user['id'],
|
||||
'username' => $username ?? '-',
|
||||
'prenom' => $user['first_name'] ?? '-',
|
||||
'nom' => $name ?? '-',
|
||||
'secteur' => $user['sect_name'] ?? '-',
|
||||
'role' => $user['role_name'] ?? '-',
|
||||
'entite' => $crypto->decryptWithIV($user['entite_encrypted_name']) ?? '-',
|
||||
'matched_in' => implode(', ', $matchedFields),
|
||||
];
|
||||
$seenIds[$user['id']] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($matchedUsers)) {
|
||||
warning("\nAucun utilisateur trouvé avec: '$searchString'");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Affichage
|
||||
title("RÉSULTATS DE LA RECHERCHE - " . count($matchedUsers) . " utilisateur(s) trouvé(s)");
|
||||
|
||||
// Préparer les données pour le tableau
|
||||
$tableData = [];
|
||||
foreach ($matchedUsers as $user) {
|
||||
$tableData[] = [
|
||||
'id' => $user['id'],
|
||||
'username' => truncate($user['username'], 20),
|
||||
'prenom' => truncate($user['prenom'], 15),
|
||||
'nom' => truncate($user['nom'], 20),
|
||||
'secteur' => truncate($user['secteur'], 15),
|
||||
'role' => truncate($user['role'], 12),
|
||||
'match' => $user['matched_in'],
|
||||
];
|
||||
}
|
||||
|
||||
table(
|
||||
[
|
||||
'id' => 'ID',
|
||||
'username' => 'Username',
|
||||
'prenom' => 'Prénom',
|
||||
'nom' => 'Nom',
|
||||
'secteur' => 'Secteur',
|
||||
'role' => 'Rôle',
|
||||
'match' => 'Trouvé dans',
|
||||
],
|
||||
$tableData,
|
||||
true
|
||||
);
|
||||
|
||||
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");
|
||||
}
|
||||
} elseif (count($matchedUsers) > 1 && count($matchedUsers) <= 10) {
|
||||
echo "\n";
|
||||
if (confirm("Afficher les détails d'un utilisateur spécifique ?")) {
|
||||
echo color("\nEntrez l'ID de l'utilisateur: ", 'yellow');
|
||||
$handle = fopen('php://stdin', 'r');
|
||||
$userId = trim(fgets($handle));
|
||||
fclose($handle);
|
||||
|
||||
if (is_numeric($userId) && (int)$userId > 0) {
|
||||
echo "\n";
|
||||
$decryptUserScript = __DIR__ . '/decrypt-user';
|
||||
passthru("$decryptUserScript $environment $userId");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
error("Erreur: " . $e->getMessage());
|
||||
exit(1);
|
||||
}
|
||||
Reference in New Issue
Block a user