fix(lyrion): access URLs point to the real LMS UI + admin button reads them from API

Three bugs found while validating the v1.1.0 admin webui rollout:

1. lyrionctl config_get concatenated inline TOML comments into the
   value. `http_port = 9000  # web admin UI + JSON-RPC` became the
   string "9000  # web admin UI + JSON-RPC", which then served as the
   port in the access URL. The Access card and the "Open Music UI"
   button both ended up pointing at
   http://192.168.1.200:9000#webadminUI+JSON-RPC/ — a fragment that
   silently took the browser nowhere. Now strips the inline comment
   and surrounding whitespace before returning the value.

2. emit_access_json built URLs with the /lyrion/ suffix (which is the
   admin path, NOT the music UI). Both LAN and public access URLs now
   point at the real LMS roots:
     lan    http://<host>:9000/        direct nginx vhost (LAN-only)
     public https://<PUBLIC_HOSTNAME>/ Authelia-gated dedicated vhost
   And PUBLIC_HOSTNAME defaults to lyrion.gk2.secubox.in if the toml
   does not override it.

3. The admin webui hardcoded the "Open Music UI" button's href to
   https://lyrion.gk2.secubox.in/. That had to stay in lock-step with
   the Access card by hand. Now the button reads the public (or LAN
   fallback) URL from the /access response — single source of truth.

Plus a stray `""|""` duplicate pattern in cmd_status's case turned into
`""|list` to match the cmd_components / cmd_access conventions.
This commit is contained in:
CyberMind-FR 2026-05-24 09:48:35 +02:00
parent b171878879
commit d4adc1a3e1
2 changed files with 42 additions and 14 deletions

View File

@ -29,12 +29,27 @@ err() { printf '%b[error]%b %s\n' "$RED" "$NC" "$*" >&2; }
# ── TOML config (best-effort, grep-style — same as giteactl) ─────────────────
config_get() {
local key="$1" default="${2:-}"
# Minimal TOML scalar read: strips inline `# comments`, surrounding
# whitespace, and the optional "..." / '...' quotes. The previous
# version concatenated comment text into the value (eg HTTP_PORT
# became `9000 # web admin UI` which then broke URL construction).
local key="$1" default="${2:-}" raw=""
if [ -f "$CONFIG_FILE" ]; then
grep -E "^[[:space:]]*${key}[[:space:]]*=" "$CONFIG_FILE" 2>/dev/null \
| head -1 | cut -d= -f2- | tr -d ' "' | tr -d "'" || echo "$default"
else
raw=$(grep -E "^[[:space:]]*${key}[[:space:]]*=" "$CONFIG_FILE" 2>/dev/null | head -1)
fi
if [ -z "$raw" ]; then
echo "$default"
return
fi
# value-after-equals, strip inline comment, trim whitespace, drop quotes
local val
val=$(echo "$raw" | cut -d= -f2- | sed 's/[[:space:]]*#.*$//' \
| sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//' \
| tr -d '"' | tr -d "'")
if [ -z "$val" ]; then
echo "$default"
else
echo "$val"
fi
}
@ -42,7 +57,7 @@ LXC_NAME=$(config_get "name" "lyrion")
LXC_IP=$(config_get "ip" "10.100.0.100")
LXC_PATH=$(config_get "path" "/data/lxc")
HTTP_PORT=$(config_get "http_port" "3000")
PUBLIC_HOSTNAME=$(config_get "public_hostname" "")
PUBLIC_HOSTNAME=$(config_get "public_hostname" "lyrion.gk2.secubox.in")
# ── LXC helpers ───────────────────────────────────────────────────────────────
lxc_state() {
@ -130,10 +145,15 @@ EOF
}
emit_access_json() {
# Real LMS Music UI URLs — NOT the /lyrion/ admin subpath. The admin
# webui's "Open Music UI" button reads this; consistency comes from
# one source.
# lan: http://<host>:9000/ (direct nginx vhost, LAN-only)
# public: https://<PUBLIC_HOSTNAME>/ (Authelia-gated dedicated vhost)
local lan_url public_url
lan_url="https://$(hostname -I | awk '{print $1}')/lyrion/"
lan_url="http://$(hostname -I | awk '{print $1}'):${HTTP_PORT}/"
if [ -n "$PUBLIC_HOSTNAME" ]; then
public_url="https://${PUBLIC_HOSTNAME}/lyrion/"
public_url="https://${PUBLIC_HOSTNAME}/"
else
public_url=""
fi
@ -141,9 +161,9 @@ emit_access_json() {
{
"module": "lyrion",
"access": [
{"url": "$lan_url", "auth": "jwt|lyrion-admin", "scope": "lan"}$( [ -n "$public_url" ] && echo ',' )
{"url": "$lan_url", "auth": "lan-only", "scope": "lan"}$( [ -n "$public_url" ] && echo ',' )
$( [ -n "$public_url" ] && cat <<PUB
{"url": "$public_url", "auth": "jwt|lyrion-admin", "scope": "public"}
{"url": "$public_url", "auth": "Authelia SSO", "scope": "public"}
PUB
)
]
@ -163,7 +183,7 @@ cmd_components() {
cmd_status() {
case "${1:-}" in
--json) emit_status_json ;;
""|"") emit_components_text ; echo ; emit_status_json | python3 -c 'import json,sys; d=json.load(sys.stdin); print("overall:", d["overall"])' ;;
""|list) emit_components_text ; echo ; emit_status_json | python3 -c 'import json,sys; d=json.load(sys.stdin); print("overall:", d["overall"])' ;;
*) err "unknown verb for 'status': $1"; exit 1 ;;
esac
}

View File

@ -71,7 +71,7 @@
vhost — serving LMS at the root path is the only way the Material
skin's absolute asset URLs load correctly.
</p>
<a class="open-cta" href="https://lyrion.gk2.secubox.in/" target="_blank" rel="noopener">
<a class="open-cta" id="open-music-ui" href="#" target="_blank" rel="noopener">
▶ Open Lyrion Music UI →
</a>
</header>
@ -179,15 +179,23 @@
async function loadAccess() {
try {
const d = await api("/access");
const items = (d.access || []).map(a => [
const access = d.access || [];
const items = access.map(a => [
escapeHtml(a.scope || "url"),
`<a href="${escapeHtml(a.url)}" target="_blank" rel="noopener">${escapeHtml(a.url)}</a>`
]);
if (!items.length) {
document.getElementById("access-v").innerHTML = `<div class="empty">none</div>`;
return;
} else {
setRows("access-v", items);
}
setRows("access-v", items);
// Single source of truth for the "Open Music UI" button: prefer
// the `public` access entry (https + Authelia), fall back to lan.
const pub = access.find(a => a.scope === "public");
const lan = access.find(a => a.scope === "lan");
const target = (pub && pub.url) || (lan && lan.url) || "#";
const btn = document.getElementById("open-music-ui");
if (btn) btn.href = target;
} catch (e) {
document.getElementById("access-v").innerHTML = `<span class="empty">${escapeHtml(e.message)}</span>`;
}