diff --git a/containers/libreportal/frontend/components/apps/core/js/apps-manager.js b/containers/libreportal/frontend/components/apps/core/js/apps-manager.js index b5a0ca1..dc6d268 100755 --- a/containers/libreportal/frontend/components/apps/core/js/apps-manager.js +++ b/containers/libreportal/frontend/components/apps/core/js/apps-manager.js @@ -977,14 +977,20 @@ class AppsManager { const passKeys = Object.keys(cfg).filter(k => loginKey('PASSWORD').test(k)); const emailVal = emailKeys[0] ? cfg[emailKeys[0]] : ''; const userVal = userKeys[0] ? cfg[userKeys[0]] : ''; - const identifier = emailVal || userVal || 'admin'; - const userLabel = (emailVal || (typeof identifier === 'string' && identifier.includes('@'))) ? 'Email' : 'User'; + // Only claim a username when the app actually declares one. This used to + // fall back to the literal 'admin', which invented a login name for + // password-only apps — speedtest has a single CFG_SPEEDTEST_PASSWORD_1 and + // no user concept at all, yet its card advertised "User: admin". + // eoCredList omits any row whose value is null, so passing undefined for + // either half renders just the half that exists. + const identifier = emailVal || userVal; + const userLabel = (emailVal || identifier.includes('@')) ? 'Email' : 'User'; if (userKeys[0] || emailKeys[0] || passKeys[0]) { creds.push({ title: `${app.name.split(' - ')[0]} Login`, - username: identifier, + username: identifier || undefined, userLabel, - password: cfg[passKeys[0]] || '(not generated)' + password: passKeys[0] ? (cfg[passKeys[0]] || '(not generated)') : undefined }); }