diff --git a/public/assets/app.js b/public/assets/app.js
index ed26f7e..0534a93 100644
--- a/public/assets/app.js
+++ b/public/assets/app.js
@@ -4922,7 +4922,13 @@ function renderBackups() {
? `Local`
: `Distant (SSH)`;
- const versionBadge = `v${escapeHtml(b.version || '1.2.0')}`;
+ const versionBadge = `v${escapeHtml(b.version || '1.6.2')}`;
+ let srcBadge = '';
+ if (b.source === 'pre-update') {
+ srcBadge = `Pré-MàJ`;
+ } else if (b.source === 'scheduled') {
+ srcBadge = `Auto`;
+ }
return `
@@ -4933,6 +4939,7 @@ function renderBackups() {
${escapeHtml(b.filename)}
${versionBadge}
+ ${srcBadge}
| ${escapeHtml(b.date_formatted)} |
diff --git a/scripts/update.sh b/scripts/update.sh
index 519598f..1a48da7 100755
--- a/scripts/update.sh
+++ b/scripts/update.sh
@@ -81,15 +81,18 @@ fi
echo -e "\n${C_YELLOW}-> Mise à jour vers la version v${REMOTE_VER}...${C_RESET}"
-# 1. Sauvegarde préventive automatique
-echo -e "${C_GRAY}[1/6] Création d'une sauvegarde préventive du système...${C_RESET}"
-mkdir -p "$APP_DIR/storage/backups"
-BACKUP_DATE=$(date +%Y%m%d_%H%M%S)
-BACKUP_FILE="$APP_DIR/storage/backups/pre-update-${BACKUP_DATE}.tar.gz"
-tar -czf "$BACKUP_FILE" \
- -C "$APP_DIR/storage" database.sqlite \
- -C /etc/asterisk pjsip.custom.conf extensions.custom.conf 2>/dev/null || true
-echo -e "${C_GREEN} ✓ Sauvegarde de sécurité créée : $(basename "$BACKUP_FILE")${C_RESET}"
+# 1. Sauvegarde préventive automatique (Disaster Recovery complète)
+echo -e "${C_GRAY}[1/6] Création d'une sauvegarde préventive du système (Disaster Recovery)...${C_RESET}"
+php -r '
+require_once "/var/www/nexus-pbx/src/Database.php";
+require_once "/var/www/nexus-pbx/src/BackupManager.php";
+try {
+ $res = App\BackupManager::createBackup("pre-update");
+ echo " ✓ Sauvegarde Disaster Recovery créée : " . $res["filename"] . " (" . $res["size_formatted"] . ")\n";
+} catch (\Throwable $e) {
+ echo " ! Avertissement sauvegarde préventive : " . $e->getMessage() . "\n";
+}
+' || true
# 2. Application des derniers fichiers de code Git
echo -e "${C_GRAY}[2/6] Déploiement des nouveaux fichiers de code...${C_RESET}"
diff --git a/src/BackupManager.php b/src/BackupManager.php
index dce7de4..16125db 100644
--- a/src/BackupManager.php
+++ b/src/BackupManager.php
@@ -11,7 +11,22 @@ use InvalidArgumentException;
class BackupManager
{
public const BACKUP_DIR = '/var/www/nexus-pbx/storage/system_backups';
- public const VERSION = '1.2.0';
+ public const VERSION = '1.6.2';
+
+ /**
+ * Retourne dynamiquement la version courante de NexusPBX lue depuis version.json
+ */
+ public static function getAppVersion(): string
+ {
+ $vFile = dirname(__DIR__) . '/version.json';
+ if (file_exists($vFile)) {
+ $data = json_decode((string)file_get_contents($vFile), true);
+ if (!empty($data['version'])) {
+ return (string)$data['version'];
+ }
+ }
+ return self::VERSION;
+ }
/**
* Initialise le répertoire des sauvegardes.
@@ -182,7 +197,8 @@ class BackupManager
}
$timestamp = date('Ymd_His');
- $filename = "nexus_backup_v" . self::VERSION . "_{$timestamp}.tar.gz";
+ $currentVer = self::getAppVersion();
+ $filename = "nexus_backup_v{$currentVer}_{$timestamp}.tar.gz";
$localArchivePath = self::BACKUP_DIR . '/' . $filename;
// 2. Préparation du dossier de staging
@@ -268,7 +284,7 @@ class BackupManager
// G. Création du Manifeste
$manifest = [
- 'nexus_version' => self::VERSION,
+ 'nexus_version' => $currentVer,
'created_at' => date('c'),
'timestamp' => time(),
'filename' => $filename,
@@ -360,6 +376,14 @@ class BackupManager
// Tenter de lire le manifest depuis l'archive sans l'extraire entièrement
$manifest = self::readManifestFromTar($file);
+ $archiveVer = $manifest['nexus_version'] ?? null;
+ if (!$archiveVer && preg_match('/_v([0-9]+\.[0-9]+(?:\.[0-9]+)?)/', $name, $vm)) {
+ $archiveVer = $vm[1];
+ }
+ if (!$archiveVer) {
+ $archiveVer = self::getAppVersion();
+ }
+
$backups[] = [
'filename' => $name,
'storage_type' => 'local',
@@ -367,7 +391,7 @@ class BackupManager
'size_formatted' => self::formatBytes($size),
'timestamp' => $mtime,
'date_formatted' => date('d/m/Y H:i:s', $mtime),
- 'version' => $manifest['nexus_version'] ?? self::VERSION,
+ 'version' => $archiveVer,
'source' => $manifest['source'] ?? 'local',
'is_local' => true,
];
@@ -807,6 +831,13 @@ class BackupManager
$name = basename($fullPath);
if (str_ends_with($name, '.tar.gz')) {
+ $remoteVer = null;
+ if (preg_match('/_v([0-9]+\.[0-9]+(?:\.[0-9]+)?)/', $name, $vm)) {
+ $remoteVer = $vm[1];
+ }
+ if (!$remoteVer) {
+ $remoteVer = self::getAppVersion();
+ }
$results[] = [
'filename' => $name,
'storage_type' => 'ssh',
@@ -814,7 +845,7 @@ class BackupManager
'size_formatted' => self::formatBytes($size),
'timestamp' => $timestamp > 0 ? $timestamp : time(),
'date_formatted' => date('d/m/Y H:i:s', $timestamp > 0 ? $timestamp : time()),
- 'version' => self::VERSION,
+ 'version' => $remoteVer,
'source' => 'distant (SSH)',
'is_local' => false,
];
diff --git a/version.json b/version.json
index a81ea33..92da145 100644
--- a/version.json
+++ b/version.json
@@ -1,16 +1,15 @@
{
- "version": "1.6.1",
+ "version": "1.6.2",
"codename": "Helios",
"release_date": "2026-11-05",
"min_php_version": "8.2",
"changelog": [
+ "Sauvegarde & Restauration : versionnage dynamique automatique basé sur la version installée (résolution du tag figé v1.2.0)",
+ "Mises à jour système OTA : déclenchement garanti d'une sauvegarde Disaster Recovery complète pré-mise à jour (visible et restaurable dans l'interface)",
+ "Interface Sauvegardes : nouveau badge identifiant la source (Pré-MàJ, Auto, Manuel)",
"Identité visuelle officielle : intégration du nouveau logo NexusPBX 3D haute définition épuré et du favicon",
"Nouveau slogan télécom : « Supervision & Téléphonie IP • Powered by Asterisk »",
- "Amélioration des scripts d'installation et de mise à jour : initialisation automatique des permissions et ACLs du module CDR (Master.csv)",
- "Nouveau module Journal d'Appels & CDR : traçabilité complète des flux entrants, sortants, internes et services avec détection automatique des Trunks SIP et postes associés",
- "Filtres multicritères CDR en temps réel (période, direction, statut décroché/manqué, recherche textuelle) et export CSV Excel",
- "Optimisation TLS SIP PJSIP : négociation universelle TLSv1.2/TLSv1.3 (method=sslv23)",
- "Suppression de CertificateRequest en mode TLS standard pour compatibilité totale avec les téléphones IP Yealink, Fanvil et Grandstream",
- "Plafond d'expiration d'enregistrement SIP standard (maximum_expiration = 300s, default = 120s) garantissant la reconnexion automatique rapide de tous les postes"
+ "Module Journal d'Appels & CDR avec filtres et export CSV",
+ "Support universel TLSv1.2/TLSv1.3 et suppression CertificateRequest pour postes Yealink"
]
}