update 1.2.2.2 beta

This commit is contained in:
MacRimi
2026-06-11 23:08:56 +02:00
parent a4d1e9fbb9
commit ed924b67fe
8 changed files with 103 additions and 38 deletions

View File

@@ -1 +1 @@
aa53e689c13d7184ebd7cb46cc0f24af9628804fcaa223a833364a5a09e382ed ProxMenux-1.2.2.1-beta.AppImage ad6a863fc2e344e5fc5ffeb66b09de8339bfc6b8d3dfcaa8020b4fe89abb4d2e ProxMenux-1.2.2.2-beta.AppImage

View File

@@ -1,12 +1,12 @@
{ {
"name": "ProxMenux-Monitor", "name": "ProxMenux-Monitor",
"version": "1.2.2", "version": "1.2.2.2-beta",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ProxMenux-Monitor", "name": "ProxMenux-Monitor",
"version": "1.2.2", "version": "1.2.2.2-beta",
"dependencies": { "dependencies": {
"@hookform/resolvers": "^3.10.0", "@hookform/resolvers": "^3.10.0",
"@radix-ui/react-accordion": "1.2.2", "@radix-ui/react-accordion": "1.2.2",

View File

@@ -1,6 +1,6 @@
{ {
"name": "ProxMenux-Monitor", "name": "ProxMenux-Monitor",
"version": "1.2.2.1-beta", "version": "1.2.2.2-beta",
"description": "Proxmox System Monitoring Dashboard", "description": "Proxmox System Monitoring Dashboard",
"private": true, "private": true,
"scripts": { "scripts": {

View File

@@ -1,6 +1,10 @@
{ {
"compilerOptions": { "compilerOptions": {
"lib": ["dom", "dom.iterable", "es6"], "lib": [
"dom",
"dom.iterable",
"es6"
],
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"strict": true, "strict": true,
@@ -19,9 +23,19 @@
], ],
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"@/*": ["./*"] "@/*": [
} "./*"
]
}, },
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], "target": "ES2017"
"exclude": ["node_modules"] },
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts"
],
"exclude": [
"node_modules"
]
} }

View File

@@ -830,7 +830,7 @@ _rs_extract_borg() {
local -a archive_lines=() local -a archive_lines=()
mapfile -t archive_lines < <( mapfile -t archive_lines < <(
"$borg_bin" list "$repo" \ "$borg_bin" list "$repo" \
--format '{start:%Y-%m-%d %H:%M:%S}|{archive}{NL}' 2>/dev/null \ --format '{start:%Y-%m-%d %H:%M:%S}|{archive}{NL}' </dev/null 2>/dev/null \
| sort -r | sort -r
) )
if [[ ${#archive_lines[@]} -eq 0 ]]; then if [[ ${#archive_lines[@]} -eq 0 ]]; then
@@ -1433,9 +1433,11 @@ _rs_show_plan_summary() {
# dialog --colors only fires inside --msgbox / --yesno / --infobox, not # dialog --colors only fires inside --msgbox / --yesno / --infobox, not
# --textbox, so we build the body as a string. Color codes match the # --textbox, so we build the body as a string. Color codes match the
# complete-restore confirm dialog for visual consistency. # complete-restore confirm dialog for visual consistency. Leading blank
# line matches the convention used in info-style dialogs (compat report,
# etc.) — keeps the title from feeling glued to the first text line.
local body local body
body="\Zb═══ $(translate "Restore plan summary") ═══\ZB"$'\n\n' body=$'\n'"\Zb═══ $(translate "Restore plan summary") ═══\ZB"$'\n\n'
if [[ -f "$meta/run_info.env" ]]; then if [[ -f "$meta/run_info.env" ]]; then
body+="\Zb$(translate "Backup origin metadata:")\ZB"$'\n' body+="\Zb$(translate "Backup origin metadata:")\ZB"$'\n'
@@ -2223,17 +2225,12 @@ _rs_run_complete_extras() {
rm -f "$cur_pkgs_file" rm -f "$cur_pkgs_file"
if [[ ${#missing[@]} -gt 0 ]]; then if [[ ${#missing[@]} -gt 0 ]]; then
echo echo
msg_info "$(translate "Installing") ${#missing[@]} $(translate "user-installed packages from backup...")" # Pre-filter to packages apt actually knows about — otherwise a
stop_spinner # single typo or repo-renamed pkg in packages.manual.list (e.g.
apt-get update -qq 2>&1 | sed -e 's/^/ /' | tail -2 # `lifnet-subnet-perl` from a hand-typo'd apt-mark) makes
# `apt-get install` exit with E_UNRESOLVABLE and the entire
# Pre-filter to packages apt actually knows about — # batch is skipped. Do this BEFORE the "installing N packages"
# otherwise a single typo or repo-renamed pkg in # message so the count is honest about what we'll actually try.
# packages.manual.list (e.g. `lifnet-subnet-perl` from
# a hand-typo'd apt-mark) makes `apt-get install` exit
# with E_UNRESOLVABLE and the entire batch is skipped.
# We do this in two passes: first split into installable
# vs unknown, then run install on the installable set.
local -a installable=() unknown=() local -a installable=() unknown=()
local pkg local pkg
for pkg in "${missing[@]}"; do for pkg in "${missing[@]}"; do
@@ -2245,6 +2242,28 @@ _rs_run_complete_extras() {
done done
if (( ${#installable[@]} > 0 )); then if (( ${#installable[@]} > 0 )); then
# Preview so the operator can see (and ^C if surprised by)
# what's about to land. First six is enough — anyone needing
# the full list goes to the apt log we write below.
local _preview="${installable[*]:0:6}"
(( ${#installable[@]} > 6 )) && _preview+=" … (+ $((${#installable[@]} - 6)) more)"
echo -e "${TAB}${BGN}$(translate "Packages from backup to install:")${CL} ${BL}${_preview}${CL}"
echo
local apt_log="/var/log/proxmenux/restore-apt-$(date +%Y%m%d_%H%M%S).log"
mkdir -p "$(dirname "$apt_log")" 2>/dev/null
msg_info "$(translate "Refreshing apt cache...")"
apt-get update -qq >"$apt_log" 2>&1 || true
msg_ok "$(translate "apt cache refreshed.")"
msg_info "$(translate "Installing") ${#installable[@]} $(translate "packages (this may take a few minutes)...")"
# Silent install — full output goes to $apt_log so the
# spinner keeps turning and the operator sees ongoing
# activity. Without this redirect, dpkg's "Setting up..."
# spew would buffer and dump at the very end after a long
# silent stall, looking like a hang followed by a wall of
# text appearing from nowhere.
# DEBIAN_FRONTEND=noninteractive + --force-conf prevents # DEBIAN_FRONTEND=noninteractive + --force-conf prevents
# apt from blocking on `*** log2ram.conf (Y/I/N/O/D/Z) ?` # apt from blocking on `*** log2ram.conf (Y/I/N/O/D/Z) ?`
# type prompts (which would leave the package in # type prompts (which would leave the package in
@@ -2257,15 +2276,12 @@ _rs_run_complete_extras() {
apt-get install -y \ apt-get install -y \
-o Dpkg::Options::="--force-confdef" \ -o Dpkg::Options::="--force-confdef" \
-o Dpkg::Options::="--force-confold" \ -o Dpkg::Options::="--force-confold" \
"${installable[@]}" 2>&1 | sed -e 's/^/ /' | tail -10 "${installable[@]}" >>"$apt_log" 2>&1
# PIPESTATUS[0] is the real exit code from apt-get; local apt_rc=$?
# without this, the pipeline always reports tee's
# 0 and we'd lie about success.
local apt_rc=${PIPESTATUS[0]}
if (( apt_rc == 0 )); then if (( apt_rc == 0 )); then
msg_ok "$(translate "Installed:") ${#installable[@]} $(translate "packages")" msg_ok "$(translate "Installed:") ${#installable[@]} $(translate "packages.")"
else else
msg_warn "$(translate "apt-get exited") ${apt_rc}$(translate "some packages may have failed; see output above")" msg_warn "$(translate "apt-get exited") ${apt_rc}$(translate "see log:") $apt_log"
fi fi
fi fi
if (( ${#unknown[@]} > 0 )); then if (( ${#unknown[@]} > 0 )); then

View File

@@ -1165,11 +1165,17 @@ hb_ensure_borg() {
hb_borg_init_if_needed() { hb_borg_init_if_needed() {
local borg_bin="$1" repo="$2" encrypt_mode="$3" local borg_bin="$1" repo="$2" encrypt_mode="$3"
"$borg_bin" list "$repo" >/dev/null 2>&1 && return 0 # Borg reads passphrase prompts from /dev/tty even when stdout/stderr
if "$borg_bin" help repo-create >/dev/null 2>&1; then # are redirected — so `>/dev/null 2>&1` is not enough to silence it.
"$borg_bin" repo-create -e "$encrypt_mode" "$repo" # Close stdin (`</dev/null`) so any prompt fails fast instead of
# hijacking the operator's input under the active dialog window.
if "$borg_bin" list "$repo" </dev/null >/dev/null 2>&1; then
return 0
fi
if "$borg_bin" help repo-create </dev/null >/dev/null 2>&1; then
"$borg_bin" repo-create -e "$encrypt_mode" "$repo" </dev/null
else else
"$borg_bin" init --encryption="$encrypt_mode" "$repo" "$borg_bin" init --encryption="$encrypt_mode" "$repo" </dev/null
fi fi
} }
@@ -1187,10 +1193,16 @@ hb_prepare_borg_passphrase() {
return 0 return 0
fi fi
# Saved target, no pw yet — ask once and persist next to its config. # Saved target, no pw yet — ask once and persist next to its config.
# The title is explicit about which passphrase: operators were typing
# their SSH/server password here, which silently persisted as the
# repokey passphrase and made every subsequent `borg list` fail with
# "passphrase ... is incorrect", dropping them back to the menu with
# only a one-second red flash for feedback.
local sel_pass local sel_pass
sel_pass=$(dialog --backtitle "ProxMenux" --insecure --passwordbox \ sel_pass=$(dialog --backtitle "ProxMenux" --colors --insecure \
"$(hb_translate "Passphrase for:") $HB_BORG_SELECTED_NAME" \ --title "$(hb_translate "Borg repository passphrase")" \
"$HB_UI_PASS_H" "$HB_UI_PASS_W" "" 3>&1 1>&2 2>&3) || return 1 --passwordbox "\n$(hb_translate "Enter the BORG REPOKEY passphrase for target:") \Zb${HB_BORG_SELECTED_NAME}\ZB" \
10 78 "" 3>&1 1>&2 2>&3) || return 1
mkdir -p "$HB_STATE_DIR" mkdir -p "$HB_STATE_DIR"
printf '%s' "$sel_pass" > "$sel_pass_file" printf '%s' "$sel_pass" > "$sel_pass_file"
chmod 600 "$sel_pass_file" chmod 600 "$sel_pass_file"
@@ -1790,6 +1802,17 @@ hb_select_borg_repo() {
if [[ "$choice" == "$add_idx" ]]; then if [[ "$choice" == "$add_idx" ]]; then
hb_configure_borg_manual _borg_repo_ref || return 1 hb_configure_borg_manual _borg_repo_ref || return 1
# The new target is saved under HB_BORG_LAST_SAVED_NAME. Promote
# it to SELECTED so hb_prepare_borg_passphrase enters the saved-
# target branch (one passphrase prompt, then persist), instead
# of the brand-new branch (the "¿Cifrar?" yes/no flow that also
# races with borg picking up the repokey prompt on the TTY).
if [[ -n "${HB_BORG_LAST_SAVED_NAME:-}" ]]; then
HB_BORG_SELECTED_NAME="$HB_BORG_LAST_SAVED_NAME"
HB_BORG_SELECTED_PASS=""
fi
export BORG_RELOCATED_REPO_ACCESS_IS_OK=yes
export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes
return 0 return 0
fi fi
@@ -1825,6 +1848,13 @@ hb_select_borg_repo() {
else else
unset BORG_RSH unset BORG_RSH
fi fi
# Saved URL may differ from the repo's recorded location by one
# trailing slash (e.g. ssh://host//path vs ssh://host/path). Borg
# prompts y/N to confirm — without a TTY the answer is empty and
# borg aborts with a red one-liner, dropping the user back to the
# menu. Trust the saved target.
export BORG_RELOCATED_REPO_ACCESS_IS_OK=yes
export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes
HB_BORG_SELECTED_NAME="${HB_BORG_NAMES[$sel]}" HB_BORG_SELECTED_NAME="${HB_BORG_NAMES[$sel]}"
HB_BORG_SELECTED_PASS="${HB_BORG_PASSES[$sel]}" HB_BORG_SELECTED_PASS="${HB_BORG_PASSES[$sel]}"
} }
@@ -2567,8 +2597,11 @@ hb_show_compat_report() {
local tmpfile local tmpfile
tmpfile=$(mktemp) tmpfile=$(mktemp)
# Leading blank line before the summary — dialog's --textbox draws the
# title flush to the top border, and stacking the summary directly under
# it looks cramped. One empty line gives the eye a break before the data.
{ {
printf '%s\n' "$summary" printf '\n%s\n' "$summary"
printf '%s\n\n' "────────────────────────────────────────────────────────────" printf '%s\n\n' "────────────────────────────────────────────────────────────"
printf '%s\n' "$report" printf '%s\n' "$report"
} > "$tmpfile" } > "$tmpfile"

View File

@@ -110,6 +110,8 @@ _sb_run_borg() {
# call is also `>/dev/null 2>&1`). # call is also `>/dev/null 2>&1`).
export BORG_PASSPHRASE="$passphrase" export BORG_PASSPHRASE="$passphrase"
[[ -n "${BORG_RSH:-}" ]] && export BORG_RSH [[ -n "${BORG_RSH:-}" ]] && export BORG_RSH
export BORG_RELOCATED_REPO_ACCESS_IS_OK=yes
export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes
if ! hb_borg_init_if_needed "$borg_bin" "$repo" "${BORG_ENCRYPT_MODE:-none}" >/dev/null 2>&1; then if ! hb_borg_init_if_needed "$borg_bin" "$repo" "${BORG_ENCRYPT_MODE:-none}" >/dev/null 2>&1; then
return 1 return 1