v1.8.2: Pre-flight check sudoers avec instructions de fix dans l'UI
Sur les anciens capteurs sans regle sudoers NOPASSWD pour /var/www/nebuleair_pro_4g/*, l'update echouait avec un message sudo cryptique. Nouveau: - preflight_sudo_check() en PHP teste 'sudo -n -l <script>' avant de lancer l'update (online ou offline) - Si KO: la route retourne error_type=sudoers_missing avec un message clair et la sortie technique de sudo - L'UI affiche une alerte warning structuree avec etapes numerotees, contenu du fichier /etc/sudoers.d/nebuleair pret a coller, et un bouton 'Copier le contenu' (presse-papier) - Echec immediat (<1s) au lieu d'attendre le timeout du script Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -428,9 +428,43 @@ if ($type == "update_firmware") {
|
||||
]);
|
||||
}
|
||||
|
||||
// Pre-flight: check that www-data can sudo the firmware update script without a password.
|
||||
// On older sensors the sudoers rule for /var/www/nebuleair_pro_4g/* may be missing,
|
||||
// in which case sudo would block on a password prompt and the update silently fails.
|
||||
// Returns ['ok' => true] on success, or ['ok' => false, 'message' => ...] with a fix hint.
|
||||
function preflight_sudo_check($scriptPath) {
|
||||
// `sudo -n -l <cmd>` is a non-interactive check: succeeds only if the user is
|
||||
// allowed to run <cmd> via sudo WITHOUT a password. Doesn't actually run anything.
|
||||
exec('sudo -n -l ' . escapeshellarg($scriptPath) . ' 2>&1', $out, $rc);
|
||||
if ($rc === 0) return ['ok' => true];
|
||||
|
||||
$output = implode("\n", $out);
|
||||
$msg = "Configuration sudoers manquante sur ce capteur (www-data n'a pas le droit d'exécuter le script de mise à jour sans mot de passe). "
|
||||
. "Voir l'erreur ci-dessous pour appliquer le fix.";
|
||||
return [
|
||||
'ok' => false,
|
||||
'error_type' => 'sudoers_missing',
|
||||
'message' => $msg,
|
||||
'raw' => $output
|
||||
];
|
||||
}
|
||||
|
||||
// Start firmware update in background, returns immediately so the UI can poll progress.
|
||||
// Output is written to a temp log file. A 'done' marker file is created when finished.
|
||||
if ($type == "update_firmware_start") {
|
||||
// Pre-flight: fail fast with a clear message if sudoers is misconfigured
|
||||
$preflight = preflight_sudo_check('/var/www/nebuleair_pro_4g/update_firmware.sh');
|
||||
if (!$preflight['ok']) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'error_type' => $preflight['error_type'],
|
||||
'message' => $preflight['message'],
|
||||
'raw' => $preflight['raw']
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$logFile = '/tmp/nebuleair_firmware_update.log';
|
||||
$doneFile = '/tmp/nebuleair_firmware_update.done';
|
||||
|
||||
@@ -500,6 +534,19 @@ if ($type == "upload_firmware") {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Pre-flight sudoers check: fail fast before the user uploads the ZIP only
|
||||
// to discover their sensor has no sudo NOPASSWD rule.
|
||||
$preflight = preflight_sudo_check('/var/www/nebuleair_pro_4g/update_firmware_from_file.sh');
|
||||
if (!$preflight['ok']) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'error_type' => $preflight['error_type'],
|
||||
'message' => $preflight['message'],
|
||||
'raw' => $preflight['raw']
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Check file upload
|
||||
if (!isset($_FILES['firmware_file']) || $_FILES['firmware_file']['error'] !== UPLOAD_ERR_OK) {
|
||||
$max_upload = ini_get('upload_max_filesize');
|
||||
|
||||
Reference in New Issue
Block a user