UX: if no login options are configured, show a message (#24777)

Admins will be instructed to login via /u/admin-login to change their
site settings.
This commit is contained in:
Neil Lalonde 2023-12-08 10:49:54 -05:00 committed by GitHub
parent 28956a5415
commit 27144f188c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 111 additions and 63 deletions

View File

@ -9,78 +9,97 @@
<:body>
<PluginOutlet @name="login-before-modal-body" @connectorTagName="div" />
{{#if this.site.mobileView}}
<Modal::Login::WelcomeHeader
@wavingHandURL={{this.wavingHandURL}}
@createAccount={{this.createAccount}}
/>
{{#if this.showLoginButtons}}
<LoginButtons
@externalLogin={{this.externalLoginAction}}
@passkeyLogin={{this.passkeyLogin}}
@context="login"
/>
{{/if}}
{{/if}}
{{#if this.canLoginLocal}}
{{#if this.hasNoLoginOptions}}
<div class={{if this.site.desktopView "login-left-side"}}>
{{#if this.site.desktopView}}
<Modal::Login::WelcomeHeader
@wavingHandURL={{this.wavingHandURL}}
@createAccount={{this.createAccount}}
/>
{{/if}}
<Modal::Login::LocalLoginForm
@loginName={{this.loginName}}
@loginNameChanged={{this.loginNameChanged}}
@canLoginLocalWithEmail={{this.canLoginLocalWithEmail}}
@canUsePasskeys={{this.canUsePasskeys}}
@passkeyLogin={{this.passkeyLogin}}
@loginPassword={{this.loginPassword}}
@secondFactorMethod={{this.secondFactorMethod}}
@secondFactorToken={{this.secondFactorToken}}
@backupEnabled={{this.backupEnabled}}
@securityKeyAllowedCredentialIds={{this.securityKeyAllowedCredentialIds}}
@securityKeyChallenge={{this.securityKeyChallenge}}
@showSecurityKey={{this.showSecurityKey}}
@otherMethodAllowed={{this.otherMethodAllowed}}
@showSecondFactor={{this.showSecondFactor}}
@handleForgotPassword={{this.handleForgotPassword}}
@login={{this.triggerLogin}}
@flashChanged={{this.flashChanged}}
@flashTypeChanged={{this.flashTypeChanged}}
@securityKeyCredentialChanged={{this.securityKeyCredentialChanged}}
/>
<Modal::Login::Footer
@canLoginLocal={{this.canLoginLocal}}
@showSecurityKey={{this.showSecurityKey}}
@login={{this.triggerLogin}}
@loginButtonLabel={{this.loginButtonLabel}}
@loginDisabled={{this.loginDisabled}}
@showSignupLink={{this.showSignupLink}}
@createAccount={{this.createAccount}}
@loggingIn={{this.loggingIn}}
@showSecondFactor={{this.showSecondFactor}}
/>
</div>
{{/if}}
{{#if (and this.showLoginButtons this.site.desktopView)}}
{{#unless this.canLoginLocal}}
<div class="login-left-side">
<Modal::Login::WelcomeHeader @wavingHandURL={{this.wavingHandURL}} />
<div class="login-welcome-header no-login-methods-configured">
<h1 class="login-title">{{i18n "login.no_login_methods.title"}}</h1>
<img />
<p class="login-subheader">
{{html-safe
(i18n
"login.no_login_methods.description"
(hash adminLoginPath=this.adminLoginPath)
)
}}
</p>
</div>
{{/unless}}
{{#if this.hasAtLeastOneLoginButton}}
<div class="login-right-side">
</div>
{{else}}
{{#if this.site.mobileView}}
<Modal::Login::WelcomeHeader
@wavingHandURL={{this.wavingHandURL}}
@createAccount={{this.createAccount}}
/>
{{#if this.showLoginButtons}}
<LoginButtons
@externalLogin={{this.externalLoginAction}}
@passkeyLogin={{this.passkeyLogin}}
@context="login"
/>
{{/if}}
{{/if}}
{{#if this.canLoginLocal}}
<div class={{if this.site.desktopView "login-left-side"}}>
{{#if this.site.desktopView}}
<Modal::Login::WelcomeHeader
@wavingHandURL={{this.wavingHandURL}}
@createAccount={{this.createAccount}}
/>
{{/if}}
<Modal::Login::LocalLoginForm
@loginName={{this.loginName}}
@loginNameChanged={{this.loginNameChanged}}
@canLoginLocalWithEmail={{this.canLoginLocalWithEmail}}
@canUsePasskeys={{this.canUsePasskeys}}
@passkeyLogin={{this.passkeyLogin}}
@loginPassword={{this.loginPassword}}
@secondFactorMethod={{this.secondFactorMethod}}
@secondFactorToken={{this.secondFactorToken}}
@backupEnabled={{this.backupEnabled}}
@securityKeyAllowedCredentialIds={{this.securityKeyAllowedCredentialIds}}
@securityKeyChallenge={{this.securityKeyChallenge}}
@showSecurityKey={{this.showSecurityKey}}
@otherMethodAllowed={{this.otherMethodAllowed}}
@showSecondFactor={{this.showSecondFactor}}
@handleForgotPassword={{this.handleForgotPassword}}
@login={{this.triggerLogin}}
@flashChanged={{this.flashChanged}}
@flashTypeChanged={{this.flashTypeChanged}}
@securityKeyCredentialChanged={{this.securityKeyCredentialChanged}}
/>
<Modal::Login::Footer
@canLoginLocal={{this.canLoginLocal}}
@showSecurityKey={{this.showSecurityKey}}
@login={{this.triggerLogin}}
@loginButtonLabel={{this.loginButtonLabel}}
@loginDisabled={{this.loginDisabled}}
@showSignupLink={{this.showSignupLink}}
@createAccount={{this.createAccount}}
@loggingIn={{this.loggingIn}}
@showSecondFactor={{this.showSecondFactor}}
/>
</div>
{{/if}}
{{#if (and this.showLoginButtons this.site.desktopView)}}
{{#unless this.canLoginLocal}}
<div class="login-left-side">
<Modal::Login::WelcomeHeader
@wavingHandURL={{this.wavingHandURL}}
/>
</div>
{{/unless}}
{{#if this.hasAtLeastOneLoginButton}}
<div class="login-right-side">
<LoginButtons
@externalLogin={{this.externalLoginAction}}
@passkeyLogin={{this.passkeyLogin}}
@context="login"
/>
</div>
{{/if}}
{{/if}}
{{/if}}
</:body>
</DModal>

View File

@ -16,6 +16,7 @@ import {
import { findAll } from "discourse/models/login-method";
import { SECOND_FACTOR_METHODS } from "discourse/models/user";
import escape from "discourse-common/lib/escape";
import getURL from "discourse-common/lib/get-url";
import I18n from "discourse-i18n";
export default class Login extends Component {
@ -96,6 +97,10 @@ export default class Login extends Component {
return findAll().length > 0 || this.canUsePasskeys;
}
get hasNoLoginOptions() {
return !this.hasAtLeastOneLoginButton && !this.canLoginLocal;
}
get loginButtonLabel() {
return this.loggingIn ? "login.logging_in" : "login.title";
}
@ -106,6 +111,10 @@ export default class Login extends Component {
);
}
get adminLoginPath() {
return getURL("/u/admin-login");
}
@action
async passkeyLogin(mediation = "optional") {
try {

View File

@ -117,3 +117,20 @@ acceptance("Modal - Login - Passkeys on mobile", function (needs) {
assert.dom(".dialog-body").exists();
});
});
acceptance("Modal - Login - With no way to login", function (needs) {
needs.settings({
enable_local_logins: false,
enable_facebook_logins: false,
});
needs.site({ auth_providers: [] });
test("Displays a helpful message", async function (assert) {
await visit("/");
await click("header .login-button");
assert.dom("#login-account-name").doesNotExist();
assert.dom("#login-button").doesNotExist();
assert.dom(".no-login-methods-configured").exists();
});
});

View File

@ -2270,6 +2270,9 @@ en:
totp: "Use an authenticator app instead"
backup_code: "Use a backup code instead"
security_key: "Use a security key instead"
no_login_methods:
title: "No login methods"
description: "No login methods are configured. Administrators can visit <a href='%{adminLoginPath}' target='_blank'>%{adminLoginPath}</a> to reconfigure the site."
invites:
accept_title: "Invitation"
welcome_to: "Welcome to %{site_name}!"