Ajout du dossier api avec la géolocalisation automatique des casernes de pompiers

This commit is contained in:
d6soft
2025-05-16 21:03:04 +02:00
parent 69dcff42f8
commit f4f7882963
143 changed files with 24329 additions and 1 deletions

View File

@@ -0,0 +1,605 @@
<?php
declare(strict_types=1);
namespace App\Controllers;
require_once __DIR__ . '/../Services/LogService.php';
require_once __DIR__ . '/../Services/ApiService.php';
use PDO;
use PDOException;
use Database;
use AppConfig;
use Request;
use Response;
use Session;
use LogService;
use ApiService;
class UserController {
private PDO $db;
private AppConfig $appConfig;
public function __construct() {
$this->db = Database::getInstance();
$this->appConfig = AppConfig::getInstance();
}
public function getUsers(): void {
Session::requireAuth();
// Vérification des droits d'accès (rôle administrateur)
// Récupérer le rôle de l'utilisateur depuis la base de données
$userId = Session::getUserId();
$stmt = $this->db->prepare('SELECT fk_role FROM users WHERE id = ?');
$stmt->execute([$userId]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$userRole = $result ? $result['fk_role'] : null;
if ($userRole != '1' && $userRole != '2') { // Supposons que 1 et 2 sont des rôles admin
Response::json([
'status' => 'error',
'message' => 'Accès non autorisé'
], 403);
return;
}
try {
$stmt = $this->db->prepare('
SELECT
u.id,
u.encrypt_email,
u.encrypted_name,
u.first_name,
u.fk_role as role,
u.fk_entite,
u.chk_active,
u.created_at,
u.updated_at,
e.encrypted_name as entite_name
FROM users u
LEFT JOIN entites e ON u.fk_entite = e.id
ORDER BY u.created_at DESC
');
$stmt->execute();
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Déchiffrement des données sensibles pour chaque utilisateur
foreach ($users as &$user) {
$user['email'] = ApiService::decryptSearchableData($user['encrypt_email']);
$user['name'] = ApiService::decryptData($user['encrypted_name']);
if (!empty($user['entite_name'])) {
$user['entite_name'] = ApiService::decryptData($user['entite_name']);
}
// Suppression des champs chiffrés
unset($user['encrypt_email']);
unset($user['encrypted_name']);
}
Response::json([
'status' => 'success',
'users' => $users
]);
} catch (PDOException $e) {
LogService::log('Erreur lors de la récupération des utilisateurs GeoSector', [
'level' => 'error',
'error' => $e->getMessage()
]);
Response::json([
'status' => 'error',
'message' => 'Erreur serveur'
], 500);
}
}
public function getUserById(string $id): void {
Session::requireAuth();
// Vérification des droits d'accès (rôle administrateur ou utilisateur lui-même)
$currentUserId = Session::getUserId();
// Récupérer le rôle de l'utilisateur depuis la base de données
$stmt = $this->db->prepare('SELECT fk_role FROM users WHERE id = ?');
$stmt->execute([$currentUserId]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$userRole = $result ? $result['fk_role'] : null;
if ($userRole != '1' && $userRole != '2' && $currentUserId != $id) {
Response::json([
'status' => 'error',
'message' => 'Accès non autorisé'
], 403);
return;
}
try {
$stmt = $this->db->prepare('
SELECT
u.id,
u.encrypt_email,
u.encrypted_name,
u.first_name,
u.sect_name,
u.encrypt_phone,
u.encrypt_mobile,
u.fk_role as role,
u.fk_entite,
u.infos,
u.chk_alert_email,
u.chk_suivi,
u.date_naissance,
u.date_embauche,
u.matricule,
u.chk_active,
u.created_at,
u.updated_at,
e.encrypted_name as entite_name,
e.adresse1,
e.adresse2,
e.cp,
e.ville,
e.fk_region
FROM users u
LEFT JOIN entites e ON u.fk_entite = e.id
WHERE u.id = ?
');
$stmt->execute([$id]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$user) {
Response::json([
'status' => 'error',
'message' => 'Utilisateur non trouvé'
], 404);
return;
}
// Déchiffrement des données sensibles
$user['email'] = ApiService::decryptSearchableData($user['encrypt_email']);
$user['name'] = ApiService::decryptData($user['encrypted_name']);
$user['phone'] = ApiService::decryptData($user['encrypt_phone'] ?? '');
$user['mobile'] = ApiService::decryptData($user['encrypt_mobile'] ?? '');
if (!empty($user['entite_name'])) {
$user['entite_name'] = ApiService::decryptData($user['entite_name']);
}
// Suppression des champs chiffrés
unset($user['encrypt_email']);
unset($user['encrypted_name']);
unset($user['encrypt_phone']);
unset($user['encrypt_mobile']);
Response::json([
'status' => 'success',
'user' => $user
]);
} catch (PDOException $e) {
LogService::log('Erreur lors de la récupération de l\'utilisateur GeoSector', [
'level' => 'error',
'error' => $e->getMessage(),
'userId' => $id
]);
Response::json([
'status' => 'error',
'message' => 'Erreur serveur'
], 500);
}
}
public function createUser(): void {
Session::requireAuth();
// Vérification des droits d'accès (rôle administrateur)
$currentUserId = Session::getUserId();
// Récupérer le rôle de l'utilisateur depuis la base de données
$stmt = $this->db->prepare('SELECT fk_role FROM users WHERE id = ?');
$stmt->execute([$currentUserId]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$userRole = $result ? $result['fk_role'] : null;
if ($userRole != '1' && $userRole != '2') {
Response::json([
'status' => 'error',
'message' => 'Accès non autorisé'
], 403);
return;
}
try {
$data = Request::getJson();
$currentUserId = Session::getUserId();
// Validation des données requises
if (!isset($data['email'], $data['name'])) {
Response::json([
'status' => 'error',
'message' => 'Email et nom requis'
], 400);
return;
}
$email = trim(strtolower($data['email']));
$name = trim($data['name']);
$firstName = isset($data['first_name']) ? trim($data['first_name']) : '';
$role = isset($data['role']) ? trim($data['role']) : '1';
$entiteId = isset($data['fk_entite']) ? (int)$data['fk_entite'] : 1;
// Vérification des longueurs d'entrée
if (strlen($email) > 255 || strlen($name) > 255) {
Response::json([
'status' => 'error',
'message' => 'Email ou nom trop long'
], 400);
return;
}
// Validation de l'email
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
Response::json([
'status' => 'error',
'message' => 'Format d\'email invalide'
], 400);
return;
}
// Chiffrement des données sensibles
$encryptedEmail = ApiService::encryptSearchableData($email);
$encryptedName = ApiService::encryptData($name);
// Vérification de l'existence de l'email
$checkStmt = $this->db->prepare('SELECT id FROM users WHERE encrypt_email = ?');
$checkStmt->execute([$encryptedEmail]);
if ($checkStmt->fetch()) {
Response::json([
'status' => 'error',
'message' => 'Cet email est déjà utilisé'
], 409);
return;
}
// Génération du mot de passe
$password = ApiService::generateSecurePassword();
$passwordHash = password_hash($password, PASSWORD_DEFAULT);
// Préparation des champs optionnels
$phone = isset($data['phone']) ? ApiService::encryptData(trim($data['phone'])) : null;
$mobile = isset($data['mobile']) ? ApiService::encryptData(trim($data['mobile'])) : null;
$sectName = isset($data['sect_name']) ? trim($data['sect_name']) : '';
$infos = isset($data['infos']) ? trim($data['infos']) : '';
$alertEmail = isset($data['chk_alert_email']) ? (int)$data['chk_alert_email'] : 1;
$suivi = isset($data['chk_suivi']) ? (int)$data['chk_suivi'] : 0;
$dateNaissance = isset($data['date_naissance']) ? $data['date_naissance'] : null;
$dateEmbauche = isset($data['date_embauche']) ? $data['date_embauche'] : null;
$matricule = isset($data['matricule']) ? trim($data['matricule']) : '';
// Insertion en base de données
$stmt = $this->db->prepare('
INSERT INTO users (
encrypt_email, user_pswd, encrypted_name, first_name,
sect_name, encrypt_phone, encrypt_mobile, fk_role,
fk_entite, infos, chk_alert_email, chk_suivi,
date_naissance, date_embauche, matricule,
created_at, fk_user_creat, chk_active
) VALUES (
?, ?, ?, ?,
?, ?, ?, ?,
?, ?, ?, ?,
?, ?, ?,
NOW(), ?, 1
)
');
$stmt->execute([
$encryptedEmail,
$passwordHash,
$encryptedName,
$firstName,
$sectName,
$phone,
$mobile,
$role,
$entiteId,
$infos,
$alertEmail,
$suivi,
$dateNaissance,
$dateEmbauche,
$matricule,
$currentUserId
]);
$userId = $this->db->lastInsertId();
// Envoi de l'email avec les identifiants
ApiService::sendEmail($email, $name, 'welcome', ['password' => $password]);
LogService::log('Utilisateur GeoSector créé', [
'level' => 'info',
'createdBy' => $currentUserId,
'newUserId' => $userId,
'email' => $email
]);
Response::json([
'status' => 'success',
'message' => 'Utilisateur créé avec succès',
'id' => $userId
], 201);
} catch (PDOException $e) {
LogService::log('Erreur lors de la création d\'un utilisateur GeoSector', [
'level' => 'error',
'error' => $e->getMessage(),
'code' => $e->getCode()
]);
Response::json([
'status' => 'error',
'message' => 'Erreur serveur'
], 500);
}
}
public function updateUser(string $id): void {
Session::requireAuth();
// Vérification des droits d'accès (rôle administrateur ou utilisateur lui-même)
$currentUserId = Session::getUserId();
// Récupérer le rôle de l'utilisateur depuis la base de données
$stmt = $this->db->prepare('SELECT fk_role FROM users WHERE id = ?');
$stmt->execute([$currentUserId]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$userRole = $result ? $result['fk_role'] : null;
if ($userRole != '1' && $userRole != '2' && $currentUserId != $id) {
Response::json([
'status' => 'error',
'message' => 'Accès non autorisé'
], 403);
return;
}
try {
$data = Request::getJson();
// Vérification qu'il y a des données à mettre à jour
if (empty($data)) {
Response::json([
'status' => 'error',
'message' => 'Aucune donnée à mettre à jour'
], 400);
return;
}
// Construction de la requête UPDATE dynamique
$updateFields = [];
$params = ['id' => $id];
// Traitement des champs à chiffrer
if (isset($data['email'])) {
// Vérification que l'email n'est pas déjà utilisé par un autre utilisateur
$email = trim(strtolower($data['email']));
$encryptedEmail = ApiService::encryptSearchableData($email);
$checkStmt = $this->db->prepare('SELECT id FROM users WHERE encrypt_email = ? AND id != ?');
$checkStmt->execute([$encryptedEmail, $id]);
if ($checkStmt->fetch()) {
Response::json([
'status' => 'error',
'message' => 'Cet email est déjà utilisé par un autre utilisateur'
], 409);
return;
}
$updateFields[] = "encrypt_email = :encrypt_email";
$params['encrypt_email'] = $encryptedEmail;
}
if (isset($data['name'])) {
$updateFields[] = "encrypted_name = :encrypted_name";
$params['encrypted_name'] = ApiService::encryptData(trim($data['name']));
}
if (isset($data['phone'])) {
$updateFields[] = "encrypt_phone = :encrypt_phone";
$params['encrypt_phone'] = ApiService::encryptData(trim($data['phone']));
}
if (isset($data['mobile'])) {
$updateFields[] = "encrypt_mobile = :encrypt_mobile";
$params['encrypt_mobile'] = ApiService::encryptData(trim($data['mobile']));
}
// Traitement des champs non chiffrés
$nonEncryptedFields = [
'first_name',
'sect_name',
'fk_role',
'fk_entite',
'infos',
'chk_alert_email',
'chk_suivi',
'date_naissance',
'date_embauche',
'matricule',
'chk_active'
];
foreach ($nonEncryptedFields as $field) {
if (isset($data[$field])) {
$updateFields[] = "$field = :$field";
$params[$field] = is_string($data[$field]) ? trim($data[$field]) : $data[$field];
}
}
// Mise à jour du mot de passe si fourni
if (isset($data['password']) && !empty($data['password'])) {
if (strlen($data['password']) < 8) {
Response::json([
'status' => 'error',
'message' => 'Le mot de passe doit contenir au moins 8 caractères'
], 400);
return;
}
$updateFields[] = "user_pswd = :password";
$params['password'] = password_hash($data['password'], PASSWORD_DEFAULT);
}
// Ajout des champs de mise à jour
$updateFields[] = "updated_at = NOW()";
$updateFields[] = "fk_user_modif = :modifier_id";
$params['modifier_id'] = $currentUserId;
if (!empty($updateFields)) {
$sql = 'UPDATE users SET ' . implode(', ', $updateFields) . ' WHERE id = :id';
$stmt = $this->db->prepare($sql);
$stmt->execute($params);
if ($stmt->rowCount() === 0) {
Response::json([
'status' => 'warning',
'message' => 'Aucune modification effectuée'
]);
return;
}
LogService::log('Utilisateur GeoSector mis à jour', [
'level' => 'info',
'modifiedBy' => $currentUserId,
'userId' => $id,
'fields' => array_keys($data)
]);
Response::json([
'status' => 'success',
'message' => 'Utilisateur mis à jour avec succès'
]);
} else {
Response::json([
'status' => 'warning',
'message' => 'Aucune donnée valide à mettre à jour'
]);
}
} catch (PDOException $e) {
LogService::log('Erreur lors de la mise à jour d\'un utilisateur GeoSector', [
'level' => 'error',
'error' => $e->getMessage(),
'userId' => $id
]);
Response::json([
'status' => 'error',
'message' => 'Erreur serveur'
], 500);
}
}
public function deleteUser(string $id): void {
Session::requireAuth();
// Vérification des droits d'accès (rôle administrateur)
$currentUserId = Session::getUserId();
// Récupérer le rôle de l'utilisateur depuis la base de données
$stmt = $this->db->prepare('SELECT fk_role FROM users WHERE id = ?');
$stmt->execute([$currentUserId]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$userRole = $result ? $result['fk_role'] : null;
if ($userRole != '1' && $userRole != '2') {
Response::json([
'status' => 'error',
'message' => 'Accès non autorisé'
], 403);
return;
}
$currentUserId = Session::getUserId();
// Empêcher la suppression de son propre compte
if ($currentUserId == $id) {
Response::json([
'status' => 'error',
'message' => 'Vous ne pouvez pas supprimer votre propre compte'
], 400);
return;
}
try {
// Désactivation de l'utilisateur plutôt que suppression
$stmt = $this->db->prepare('
UPDATE users
SET chk_active = 0,
updated_at = NOW(),
fk_user_modif = ?
WHERE id = ?
');
$stmt->execute([$currentUserId, $id]);
if ($stmt->rowCount() === 0) {
Response::json([
'status' => 'error',
'message' => 'Utilisateur non trouvé'
], 404);
return;
}
LogService::log('Utilisateur GeoSector désactivé', [
'level' => 'info',
'deactivatedBy' => $currentUserId,
'userId' => $id
]);
Response::json([
'status' => 'success',
'message' => 'Utilisateur désactivé avec succès'
]);
} catch (PDOException $e) {
LogService::log('Erreur lors de la désactivation d\'un utilisateur GeoSector', [
'level' => 'error',
'error' => $e->getMessage(),
'userId' => $id
]);
Response::json([
'status' => 'error',
'message' => 'Erreur serveur'
], 500);
}
}
// Méthodes auxiliaires
private function validateUpdateData(array $data): ?string {
// Validation de l'email
if (isset($data['email'])) {
if (!filter_var(trim($data['email']), FILTER_VALIDATE_EMAIL)) {
return 'Format d\'email invalide';
}
}
// Validation du nom
if (isset($data['name']) && strlen(trim($data['name'])) < 2) {
return 'Le nom doit contenir au moins 2 caractères';
}
// Validation du téléphone
if (isset($data['phone']) && !empty($data['phone'])) {
if (!preg_match('/^[0-9+\s()-]{6,20}$/', trim($data['phone']))) {
return 'Format de téléphone invalide';
}
}
// Validation du mobile
if (isset($data['mobile']) && !empty($data['mobile'])) {
if (!preg_match('/^[0-9+\s()-]{6,20}$/', trim($data['mobile']))) {
return 'Format de mobile invalide';
}
}
return null;
}
}