# Task — Issue #1050: honor `user_self_signup` for the sign-up link on the modern login screen The modern Dashio login screen (`gui/templates/auth/login.html`) received the `user_self_signup` setting from its own BFF (`api/auth/index.php:142,175` → `config.selfSignup`) and then **threw it away**: `#tl_sign_up` was rendered unconditionally and the registration row was force-shown with ```js // The registration footer (with the Sign Up link) is always shown so the // path to registration stays visible regardless of the self-signup config. $('.registration, #registrationRow').show(); ``` With `user_self_signup = FALSE` the login card therefore advertised a registration entry point that leads to a dead end: following it opens `/gui/templates/auth/firstLogin.html`, which renders the refusal *"New user — self-registration is disabled on this site. Please contact your site administrator."* (i18n key `auth.signUpDisabled`) Legacy never offered that entry point. ## Legacy reference (the behavior that was dropped) - `login.php:234` — `$gui->user_self_signup = config_get('user_self_signup');` - `config.inc.php:2125` — `$g_tpl['login'] = 'login/login-model-marcobiedermann.tpl';` (this is the login template that is actually selected) - `gui/templates/dashio/login/login-model-marcobiedermann.tpl:76-79` ```smarty {if $gui->user_self_signup} {$labels.new_user_q}     {/if} {* the configured authentication method don't allow users to reset his/her password *} {if $gui->external_password_mgmt eq 0 && $tlCfg->demoMode eq 0} {$labels.lost_password_q} {/if} ``` Two independent gates in the template that is in use: | Element | Legacy gate | Modern before this task | |---|---|---| | `#tl_sign_up` | `user_self_signup` (line 76) | **always rendered** (gap) | | `#tl_lost_password` | `external_password_mgmt eq 0 && demoMode eq 0` (line 82) | already correct | | separator between them | implicit (` ` inside each link, never a dangling `\|`) | shown whenever the row was shown | | registration row | rendered, but empty when both links are off | always force-shown | > Note on the second legacy template: `login-dashio.tpl:85-98` nests the > lost-password link **inside** the `user_self_signup` block. It is *not* the > configured template, and there the lost-password link is deliberately > independent. The port therefore implements the configured template's > semantics — gating lost password on self-signup too would have created a new > gap. ## The implementation Single file, front-end only — the flag is already delivered by the BFF and no new user-facing string was introduced, so **no i18n bundle changed**. `gui/templates/auth/login.html`, inside the `GET /api/auth/config` callback: ```js // Sign-up link: rendered ONLY when self-registration is enabled, exactly as // legacy gated it (login-model-marcobiedermann.tpl:76 …). Refs #1050. var showSignUp = !!c.selfSignup; if (showSignUp) { $('#tl_sign_up').attr('href', '/gui/templates/auth/firstLogin.html'); // #1338 } else { $('#tl_sign_up').hide(); } // Lost-password link: independent of self-signup (marcobiedermann.tpl:82) var showLost = (!c.externalPasswordMgmt && !c.demoMode); if (showLost) { $('#tl_lost_password').attr('href', '/gui/templates/auth/lostPassword.html'); } else { $('#tl_lost_password').hide(); } // Separator only when BOTH links are on screen. if (showSignUp && showLost) { $('#lostSep').show(); } else { $('#lostSep').hide(); } // The row ships hidden; reveal it only when there is something to show. if (showSignUp || showLost) { $('.registration, #registrationRow').show(); } ``` ## Visibility matrix (measured in Chrome against the running app) | # | `selfSignup` | `demoMode` | `externalPasswordMgmt` | `#tl_sign_up` | `#tl_lost_password` | `#lostSep` | `#registrationRow` | |---|---|---|---|---|---|---|---| | A | false | false | false | hidden | visible | hidden | visible | | B | true | false | false | visible | visible | visible | visible | | C | true | true | false | visible | hidden | hidden | visible | | D | false | true | false | hidden | hidden | hidden | hidden | | E | false | false | true | hidden | hidden | hidden | hidden | ![Login card with self-registration disabled — only the "Lost password?" link is offered, exactly as legacy `login-model-marcobiedermann.tpl:76-84` renders it](issue-1050-signup-disabled.png) Row B (the shipped default) is unchanged from before the fix, including the absolute href required by #1338. Rows A/E reproduce the dead-end screenshot: with self-registration disabled the footer shows only `Lost password?`. ## Authorization is unaffected The change is presentation-only. The registration POST was — and still is — refused server-side when self-registration is off: - modern: `api/auth/index.php:368-369` → `{"success":false,"reason":"error_self_signup_disabled"}` - legacy: `firstLogin.php:23-26` → `lang_get('error_self_signup_disabled')` ## Verification - `node --check` on the extracted inline `