From 65a62ca0e40c85e5aa6373cd8484d7ef0fb32ca0 Mon Sep 17 00:00:00 2001 From: sorcier Date: Wed, 4 Nov 2026 12:43:32 +0100 Subject: [PATCH] =?UTF-8?q?v1.5.1:=20Sauvegarde/restauration=20int=C3=A9gr?= =?UTF-8?q?ale=20AstDB=20et=20synchronisation=20SIP=20imm=C3=A9diate=20des?= =?UTF-8?q?=20t=C3=A9l=C3=A9phones=20(check-sync)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- install.sh | 8 ++++++++ scripts/fix.sh | 8 ++++++++ src/BackupManager.php | 39 +++++++++++++++++++++++++++++++++++++++ src/ConfigGenerator.php | 14 ++++++++++++++ src/SystemChecker.php | 15 +++++++++++++++ version.json | 10 +++++----- 6 files changed, 89 insertions(+), 5 deletions(-) diff --git a/install.sh b/install.sh index 11aa02e..ddead27 100755 --- a/install.sh +++ b/install.sh @@ -285,6 +285,8 @@ chmod 0640 /etc/asterisk/keys/* 2>/dev/null || true # Inclusions custom dans Asterisk & initialisation des fichiers cibles touch /etc/asterisk/pjsip.conf \ /etc/asterisk/pjsip.custom.conf \ + /etc/asterisk/pjsip_notify.conf \ + /etc/asterisk/pjsip_notify.custom.conf \ /etc/asterisk/extensions.conf \ /etc/asterisk/extensions.custom.conf \ /etc/asterisk/musiconhold.conf \ @@ -308,6 +310,12 @@ fi if ! grep -q 'pjsip.custom.conf' /etc/asterisk/pjsip.conf 2>/dev/null; then printf '\n#tryinclude "pjsip.custom.conf"\n' >> /etc/asterisk/pjsip.conf fi +if ! grep -q 'pjsip_notify.custom.conf' /etc/asterisk/pjsip_notify.conf 2>/dev/null; then + printf '\n#tryinclude "pjsip_notify.custom.conf"\n' >> /etc/asterisk/pjsip_notify.conf +fi +if [ ! -s /etc/asterisk/pjsip_notify.custom.conf ]; then + printf '[check-sync]\nEvent=>check-sync\\;reboot=false\n\n[resync]\nEvent=>check-sync\\;reboot=false\n' > /etc/asterisk/pjsip_notify.custom.conf +fi if ! grep -q 'extensions.custom.conf' /etc/asterisk/extensions.conf 2>/dev/null; then printf '\n#tryinclude "extensions.custom.conf"\n' >> /etc/asterisk/extensions.conf fi diff --git a/scripts/fix.sh b/scripts/fix.sh index 0e1a3dd..6e1a870 100755 --- a/scripts/fix.sh +++ b/scripts/fix.sh @@ -63,6 +63,8 @@ chmod 2775 /var/www/nexus-pbx/storage /var/www/nexus-pbx/storage/backups /var/ww touch /etc/asterisk/pjsip.conf \ /etc/asterisk/pjsip.custom.conf \ + /etc/asterisk/pjsip_notify.conf \ + /etc/asterisk/pjsip_notify.custom.conf \ /etc/asterisk/extensions.conf \ /etc/asterisk/extensions.custom.conf \ /etc/asterisk/musiconhold.conf \ @@ -86,6 +88,12 @@ fi if ! grep -q 'pjsip.custom.conf' /etc/asterisk/pjsip.conf 2>/dev/null; then printf '\n#tryinclude "pjsip.custom.conf"\n' >> /etc/asterisk/pjsip.conf fi +if ! grep -q 'pjsip_notify.custom.conf' /etc/asterisk/pjsip_notify.conf 2>/dev/null; then + printf '\n#tryinclude "pjsip_notify.custom.conf"\n' >> /etc/asterisk/pjsip_notify.conf +fi +if [ ! -s /etc/asterisk/pjsip_notify.custom.conf ]; then + printf '[check-sync]\nEvent=>check-sync\\;reboot=false\n\n[resync]\nEvent=>check-sync\\;reboot=false\n' > /etc/asterisk/pjsip_notify.custom.conf +fi if ! grep -q 'extensions.custom.conf' /etc/asterisk/extensions.conf 2>/dev/null; then printf '\n#tryinclude "extensions.custom.conf"\n' >> /etc/asterisk/extensions.conf fi diff --git a/src/BackupManager.php b/src/BackupManager.php index dce7de4..b34ce72 100644 --- a/src/BackupManager.php +++ b/src/BackupManager.php @@ -257,6 +257,17 @@ class BackupManager } $manifestFiles['asterisk_custom_conf'] = ['count' => count(glob($destConfs . '/*'))]; + // E2. Base interne Asterisk AstDB (contacts enregistrés, renvois, DND) + $astDbPath = '/var/lib/asterisk/astdb.sqlite3'; + if (file_exists($astDbPath)) { + $destAstDb = $stageDir . '/astdb.sqlite3'; + copy($astDbPath, $destAstDb); + $manifestFiles['astdb.sqlite3'] = [ + 'size' => filesize($destAstDb), + 'md5' => md5_file($destAstDb), + ]; + } + // F. Avatars et photos des contacts de l'annuaire (/var/www/nexus-pbx/public/avatars/) $publicAvatars = '/var/www/nexus-pbx/public/avatars'; if (is_dir($publicAvatars)) { @@ -595,6 +606,15 @@ class BackupManager exec("chmod -R 775 " . escapeshellarg($destAvatars)); } + // 9c. Restauration de la base interne AstDB (contacts enregistrés, renvois, DND) + if (file_exists($stageDir . '/astdb.sqlite3')) { + $targetAstDb = '/var/lib/asterisk/astdb.sqlite3'; + copy($stageDir . '/astdb.sqlite3', $targetAstDb); + @chown($targetAstDb, 'asterisk'); + @chgrp($targetAstDb, 'asterisk'); + @chmod($targetAstDb, 0664); + } + // 10. Régénération intégrale des configurations Asterisk avec la nouvelle base restaurée Database::resetConnection(); $dbFresh = Database::getConnection(true); @@ -609,6 +629,25 @@ class BackupManager $reloadRes = ['success' => false, 'error' => $e->getMessage()]; } + // 12. Notification de réenregistrement immédiat des téléphones IP (check-sync) + try { + $extList = $dbFresh->query("SELECT extension FROM extensions WHERE enabled = 1")->fetchAll(\PDO::FETCH_COLUMN); + foreach ($extList as $extItem) { + $ami->runCommand("pjsip send notify snom-check-cfg endpoint {$extItem}"); + } + $astContacts = $ami->runCommand("database show registrar/contact"); + foreach (preg_split('/\r?\n/', $astContacts) ?: [] as $cLine) { + if (preg_match('/^\/registrar\/contact\/([^;]+);@[a-f0-9]+:\s*(\{.*\})/i', $cLine, $cM)) { + $meta = json_decode($cM[2], true); + if (!empty($meta['uri'])) { + $ami->runCommand("pjsip send notify snom-check-cfg uri " . escapeshellarg($meta['uri'])); + } + } + } + } catch (Exception $e) { + // Silencieux si échec d'envoi NOTIFY + } + return [ 'success' => true, 'message' => 'Restauration complète effectuée avec succès ! Base de données réintégrée, fichiers audio, messageries vocales et configurations Asterisk rechargées.', diff --git a/src/ConfigGenerator.php b/src/ConfigGenerator.php index 0de324c..ab95097 100644 --- a/src/ConfigGenerator.php +++ b/src/ConfigGenerator.php @@ -178,6 +178,17 @@ class ConfigGenerator $lines[] = "allow_reload = no"; $lines[] = ""; + $lines[] = "; --- CONFIGURATION GLOBALE & POINT DE SORTIE PAR DÉFAUT (NOTIFY / RESYNC) ---"; + $lines[] = "[global]"; + $lines[] = "type = global"; + $lines[] = "default_outbound_endpoint = default_outbound_endpoint"; + $lines[] = ""; + $lines[] = "[default_outbound_endpoint]"; + $lines[] = "type = endpoint"; + $lines[] = "context = from-internal"; + $lines[] = "transport = transport-udp"; + $lines[] = ""; + // 3. Extensions (Postes téléphoniques hybrides UDP vs TLS+SRTP) $lines[] = "; ==========================================================================="; $lines[] = "; POSTES TÉLÉPHONIQUES (EXTENSIONS)"; @@ -256,6 +267,9 @@ class ConfigGenerator $lines[] = "type = aor"; $lines[] = "max_contacts = {$maxContacts}"; $lines[] = "remove_existing = yes"; + $lines[] = "default_expiration = 120"; + $lines[] = "maximum_expiration = 300"; + $lines[] = "minimum_expiration = 60"; $lines[] = "qualify_frequency = 30"; if ($hasVm) { $lines[] = "mailboxes = {$num}@default"; diff --git a/src/SystemChecker.php b/src/SystemChecker.php index 2f6f2c1..134a2d0 100644 --- a/src/SystemChecker.php +++ b/src/SystemChecker.php @@ -174,6 +174,21 @@ class SystemChecker } } + $notifyConf = '/etc/asterisk/pjsip_notify.conf'; + if (is_file($notifyConf) && is_writable($notifyConf)) { + $content = (string)file_get_contents($notifyConf); + if (!str_contains($content, 'pjsip_notify.custom.conf')) { + file_put_contents($notifyConf, rtrim($content) . "\n\n#tryinclude \"pjsip_notify.custom.conf\"\n"); + } + } + $customNotify = '/etc/asterisk/pjsip_notify.custom.conf'; + if (!file_exists($customNotify)) { + @file_put_contents($customNotify, "[check-sync]\nEvent=>check-sync\\;reboot=false\n\n[resync]\nEvent=>check-sync\\;reboot=false\n"); + @chown($customNotify, 'asterisk'); + @chgrp($customNotify, 'asterisk'); + @chmod($customNotify, 0664); + } + $extConf = '/etc/asterisk/extensions.conf'; if (is_file($extConf) && is_writable($extConf)) { $content = (string)file_get_contents($extConf); diff --git a/version.json b/version.json index 3c1a95a..2fd7f71 100644 --- a/version.json +++ b/version.json @@ -1,12 +1,12 @@ { - "version": "1.5.0", + "version": "1.5.1", "codename": "Helios", "release_date": "2026-11-04", "min_php_version": "8.2", "changelog": [ - "Gestion native et universelle des sons personnalisés par chemin absolu Asterisk (compatible multilingue français, anglais, italien, espagnol sans dépendance aux liens symboliques)", - "Préservation automatique des invites système par langue (fr, en, it, es)", - "Résolution définitive et propre des conflits de préfixes Dialplan sur les SVI/IVR (*801-*899)", - "Restauration instantanée du statut en ligne des postes après restauration de sauvegarde" + "Sauvegarde et restauration intégrale de la base interne Asterisk AstDB (contacts enregistrés, renvois, DND)", + "Notification et synchronisation SIP immédiate des téléphones IP (check-sync) après toute restauration", + "Plafond d'expiration d'enregistrement SIP (maximum_expiration = 300s, default = 120s) empêchant les téléphones de rester déconnectés", + "Support universel PJSIP Notify et point de sortie par défaut pour la réinitialisation à chaud des téléphones" ] }