fix(webui): show generated admin passwords again on the app cards

Every app with a generated admin password displayed "(not generated)" in its
Login Details. The credential matcher anchored on
^CFG_<APP>_(ADMIN_)?(PASSWORD)$, which stopped matching when generated keys were
given slot numbers — CFG_MATRIX_ADMIN_PASSWORD_1 and friends no longer hit the
regex, so the lookup fell through to its placeholder.

All ten apps carrying an admin password were affected: adguard, authelia,
bookstack, gitea, invidious, matrix, nextcloud, owncloud, pihole and stalwart.

Allow an optional _<n> tail. The anchor is kept otherwise, so a database or
upstream credential still cannot be mistaken for a login — CFG_<APP>_DB_PASSWORD_1
does not match, which is the case the anchor was added for.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
librelad 2026-08-18 21:09:33 +01:00
parent 4a95b4c41e
commit 296c6ddff1

View File

@ -967,7 +967,11 @@ class AppsManager {
// app's CFG prefix. Without the anchor, loose suffix matches pull in // app's CFG prefix. Without the anchor, loose suffix matches pull in
// notification-channel / upstream creds that aren't logins at all // notification-channel / upstream creds that aren't logins at all
// (e.g. CFG_GLUETUN_OPENVPN_PASSWORD). // (e.g. CFG_GLUETUN_OPENVPN_PASSWORD).
const loginKey = (kind) => new RegExp(`^CFG_${upper}_(ADMIN_)?(${kind})$`); // The optional _<n> tail matches slot-numbered keys. Generated credentials
// carry a slot (CFG_MATRIX_ADMIN_PASSWORD_1) while hand-set ones usually do
// not, and an anchor that allowed neither made every app with a generated
// admin password report "(not generated)" on its own card.
const loginKey = (kind) => new RegExp(`^CFG_${upper}_(ADMIN_)?(${kind})(_\\d+)?$`);
const emailKeys = Object.keys(cfg).filter(k => loginKey('EMAIL').test(k)); const emailKeys = Object.keys(cfg).filter(k => loginKey('EMAIL').test(k));
const userKeys = Object.keys(cfg).filter(k => loginKey('USER(NAME)?').test(k)); const userKeys = Object.keys(cfg).filter(k => loginKey('USER(NAME)?').test(k));
const passKeys = Object.keys(cfg).filter(k => loginKey('PASSWORD').test(k)); const passKeys = Object.keys(cfg).filter(k => loginKey('PASSWORD').test(k));