From 5e43f8ec79b39ec83a51ca8a37d53a86ba795c4f Mon Sep 17 00:00:00 2001 From: librelad Date: Sat, 30 May 2026 02:55:31 +0100 Subject: [PATCH] feat(webui): wire updater actions through the task router MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add updater_check/apply/apply_all/rollback cases to task-router routeAction and the matching task-actions methods, each running the locked-down 'libreportal updater …' CLI as a task (apply/rollback snapshot-before-update host-side for disaster recovery). Verified: /updater + all tabs render, the new Updates nav button shows globally, and the feature auto-discovers via /api/features/list. Co-Authored-By: Claude Opus 4.8 Signed-off-by: librelad --- .../frontend/shared/task/task-actions.js | 27 +++++++++++++++++++ .../frontend/shared/task/task-router.js | 11 ++++++++ 2 files changed, 38 insertions(+) diff --git a/containers/libreportal/frontend/shared/task/task-actions.js b/containers/libreportal/frontend/shared/task/task-actions.js index e0e67a1..9c23238 100755 --- a/containers/libreportal/frontend/shared/task/task-actions.js +++ b/containers/libreportal/frontend/shared/task/task-actions.js @@ -260,6 +260,33 @@ async configUpdate(changes) { } } + // App Updater actions — each runs the locked-down `libreportal updater` CLI + // as a task. apply/rollback snapshot-before-update on the host side (DR). + async updaterCheck() { + try { + return await this.executeTask('updater_check', 'updater', 'libreportal updater check', 'Check for updates'); + } catch (error) { throw new Error(`Failed to check for updates: ${error.message}`); } + } + async updaterApply(app) { + if (!app) throw new Error('No app specified'); + try { + return await this.executeTask('updater_apply', app, `libreportal updater apply ${app}`, `Update ${app}`); + } catch (error) { throw new Error(`Failed to update ${app}: ${error.message}`); } + } + async updaterApplyAll(apps) { + try { + const list = (apps || '').toString(); + const cmd = list ? `libreportal updater apply-all ${list}` : 'libreportal updater apply-all'; + return await this.executeTask('updater_apply_all', 'updater', cmd, 'Update all apps'); + } catch (error) { throw new Error(`Failed to update apps: ${error.message}`); } + } + async updaterRollback(app) { + if (!app) throw new Error('No app specified'); + try { + return await this.executeTask('updater_rollback', app, `libreportal updater rollback ${app}`, `Roll back ${app}`); + } catch (error) { throw new Error(`Failed to roll back ${app}: ${error.message}`); } + } + /** * Create a task object */ diff --git a/containers/libreportal/frontend/shared/task/task-router.js b/containers/libreportal/frontend/shared/task/task-router.js index 275d741..ebc8595 100755 --- a/containers/libreportal/frontend/shared/task/task-router.js +++ b/containers/libreportal/frontend/shared/task/task-router.js @@ -69,6 +69,17 @@ class TaskRouter { case 'tool': return await this.actions.runTool(params.appName, params.toolName, params.toolArgs, params.toolLabel); + // App Updater (features/updater) — version/CVE refresh + update/rollback, + // each routed to the locked-down `libreportal updater` CLI as a task. + case 'updater_check': + return await this.actions.updaterCheck(); + case 'updater_apply': + return await this.actions.updaterApply(params.app); + case 'updater_apply_all': + return await this.actions.updaterApplyAll(params.apps); + case 'updater_rollback': + return await this.actions.updaterRollback(params.app); + default: throw new Error(`Unknown action: ${action}`); }