From 42447770bf39e7bb7164b66c498b80827dff04d1 Mon Sep 17 00:00:00 2001 From: Jan Cernik <66427541+jancernik@users.noreply.github.com> Date: Fri, 7 Feb 2025 12:40:45 -0300 Subject: [PATCH] FIX: Automatic auth flow with full page login/signup V3 (#31072) This adds back the fixes from https://github.com/discourse/discourse/pull/30928 that were reverted by https://github.com/discourse/discourse/pull/30960. --- .../discourse/app/controllers/login.js | 8 +- .../discourse/app/routes/application.js | 22 +- .../javascripts/discourse/app/routes/login.js | 30 +- .../discourse/app/routes/signup.js | 23 +- .../discourse/app/services/login.js | 21 +- .../discourse/app/templates/login.hbs | 327 +++++------ .../discourse/app/templates/signup.hbs | 526 +++++++++--------- .../tests/acceptance/login-required-test.js | 36 +- config/site_settings.yml | 1 + spec/system/social_authentication_spec.rb | 137 +++++ 10 files changed, 678 insertions(+), 453 deletions(-) diff --git a/app/assets/javascripts/discourse/app/controllers/login.js b/app/assets/javascripts/discourse/app/controllers/login.js index 323b9f8086b..559ae4370b6 100644 --- a/app/assets/javascripts/discourse/app/controllers/login.js +++ b/app/assets/javascripts/discourse/app/controllers/login.js @@ -119,7 +119,8 @@ export default class LoginPageController extends Controller { get shouldTriggerRouteAction() { return ( !this.siteSettings.full_page_login || - this.siteSettings.enable_discourse_connect + this.siteSettings.enable_discourse_connect || + this.singleExternalLogin ); } @@ -220,7 +221,10 @@ export default class LoginPageController extends Controller { const returnPath = encodeURIComponent(window.location.pathname); window.location = getURL("/session/sso?return_path=" + returnPath); } else { - if (this.isOnlyOneExternalLoginMethod) { + if ( + this.isOnlyOneExternalLoginMethod && + this.siteSettings.auth_immediately + ) { // we will automatically redirect to the external auth service this.login.externalLogin(this.externalLoginMethods[0], { signup: true, diff --git a/app/assets/javascripts/discourse/app/routes/application.js b/app/assets/javascripts/discourse/app/routes/application.js index 34d737afdba..d680a6ac790 100644 --- a/app/assets/javascripts/discourse/app/routes/application.js +++ b/app/assets/javascripts/discourse/app/routes/application.js @@ -17,7 +17,6 @@ import DiscourseURL from "discourse/lib/url"; import { postRNWebviewMessage } from "discourse/lib/utilities"; import Category from "discourse/models/category"; import Composer from "discourse/models/composer"; -import { findAll } from "discourse/models/login-method"; import DiscourseRoute from "discourse/routes/discourse"; import { i18n } from "discourse-i18n"; @@ -44,17 +43,6 @@ export default class ApplicationRoute extends DiscourseRoute { @setting("title") siteTitle; @setting("short_site_description") shortSiteDescription; - get isOnlyOneExternalLoginMethod() { - return ( - !this.siteSettings.enable_local_logins && - this.externalLoginMethods.length === 1 - ); - } - - get externalLoginMethods() { - return findAll(); - } - @action loading(transition) { this.loadingSlider.transitionStarted(); @@ -295,8 +283,8 @@ export default class ApplicationRoute extends DiscourseRoute { : encodeURIComponent(window.location.pathname); window.location = getURL("/session/sso?return_path=" + returnPath); } else { - if (this.isOnlyOneExternalLoginMethod) { - this.login.externalLogin(this.externalLoginMethods[0]); + if (this.login.isOnlyOneExternalLoginMethod) { + this.login.singleExternalLogin(); } else if (this.siteSettings.full_page_login) { this.router.transitionTo("login").then((login) => { login.controller.set("canSignUp", this.controller.canSignUp); @@ -321,11 +309,9 @@ export default class ApplicationRoute extends DiscourseRoute { const returnPath = encodeURIComponent(window.location.pathname); window.location = getURL("/session/sso?return_path=" + returnPath); } else { - if (this.isOnlyOneExternalLoginMethod) { + if (this.login.isOnlyOneExternalLoginMethod) { // we will automatically redirect to the external auth service - this.login.externalLogin(this.externalLoginMethods[0], { - signup: true, - }); + this.login.singleExternalLogin({ signup: true }); } else if (this.siteSettings.full_page_login) { this.router.transitionTo("signup").then((signup) => { Object.keys(createAccountProps || {}).forEach((key) => { diff --git a/app/assets/javascripts/discourse/app/routes/login.js b/app/assets/javascripts/discourse/app/routes/login.js index 05c2ff10ce2..988a3e6024b 100644 --- a/app/assets/javascripts/discourse/app/routes/login.js +++ b/app/assets/javascripts/discourse/app/routes/login.js @@ -7,12 +7,26 @@ import DiscourseRoute from "discourse/routes/discourse"; export default class LoginRoute extends DiscourseRoute { @service siteSettings; @service router; + @service login; beforeModel() { - if ( - !this.siteSettings.login_required && - (!this.siteSettings.full_page_login || - this.siteSettings.enable_discourse_connect) + if (this.siteSettings.login_required) { + if ( + this.login.isOnlyOneExternalLoginMethod && + this.siteSettings.auth_immediately && + !document.getElementById("data-authentication")?.dataset + .authenticationData + ) { + this.login.singleExternalLogin(); + } + } else if ( + this.login.isOnlyOneExternalLoginMethod && + this.siteSettings.full_page_login + ) { + this.login.singleExternalLogin(); + } else if ( + !this.siteSettings.full_page_login || + this.siteSettings.enable_discourse_connect ) { this.router .replaceWith(`/${defaultHomepage()}`) @@ -38,5 +52,13 @@ export default class LoginRoute extends DiscourseRoute { if (this.siteSettings.login_required) { controller.set("showLogin", false); } + + if (this.login.isOnlyOneExternalLoginMethod) { + if (this.siteSettings.auth_immediately) { + controller.set("isRedirectingToExternalAuth", true); + } else { + controller.set("singleExternalLogin", this.login.singleExternalLogin); + } + } } } diff --git a/app/assets/javascripts/discourse/app/routes/signup.js b/app/assets/javascripts/discourse/app/routes/signup.js index e78b79a459f..f32ee482571 100644 --- a/app/assets/javascripts/discourse/app/routes/signup.js +++ b/app/assets/javascripts/discourse/app/routes/signup.js @@ -4,11 +4,30 @@ import { service } from "@ember/service"; import DiscourseRoute from "discourse/routes/discourse"; export default class SignupRoute extends DiscourseRoute { - @service router; @service siteSettings; + @service router; + @service login; + + authComplete = false; beforeModel() { - this.showCreateAccount(); + this.authComplete = document.getElementById( + "data-authentication" + )?.dataset.authenticationData; + + if (this.login.isOnlyOneExternalLoginMethod && !this.authComplete) { + this.login.singleExternalLogin({ signup: true }); + } else { + this.showCreateAccount(); + } + } + + setupController(controller) { + super.setupController(...arguments); + + if (this.login.isOnlyOneExternalLoginMethod && !this.authComplete) { + controller.set("isRedirectingToExternalAuth", true); + } } @action diff --git a/app/assets/javascripts/discourse/app/services/login.js b/app/assets/javascripts/discourse/app/services/login.js index 4c92ea7e460..c6aec234e83 100644 --- a/app/assets/javascripts/discourse/app/services/login.js +++ b/app/assets/javascripts/discourse/app/services/login.js @@ -1,9 +1,12 @@ import { action } from "@ember/object"; -import Service from "@ember/service"; +import Service, { service } from "@ember/service"; import { disableImplicitInjections } from "discourse/lib/implicit-injections"; +import { findAll } from "discourse/models/login-method"; @disableImplicitInjections export default class LoginService extends Service { + @service siteSettings; + @action async externalLogin( loginMethod, @@ -16,4 +19,20 @@ export default class LoginService extends Service { setLoggingIn?.(false); } } + + @action + async singleExternalLogin(opts) { + await this.externalLogin(this.externalLoginMethods[0], opts); + } + + get isOnlyOneExternalLoginMethod() { + return ( + !this.siteSettings.enable_local_logins && + this.externalLoginMethods.length === 1 + ); + } + + get externalLoginMethods() { + return findAll(); + } } diff --git a/app/assets/javascripts/discourse/app/templates/login.hbs b/app/assets/javascripts/discourse/app/templates/login.hbs index 70310b1cc30..2665ed6529e 100644 --- a/app/assets/javascripts/discourse/app/templates/login.hbs +++ b/app/assets/javascripts/discourse/app/templates/login.hbs @@ -1,176 +1,187 @@ -{{#if - (and - this.siteSettings.full_page_login - (or this.showLogin (not this.siteSettings.login_required)) - ) -}} - {{hide-application-header-buttons "search" "login" "signup" "menu"}} - {{hide-application-sidebar}} - {{body-class "login-page"}} -
- {{html-safe - (i18n - "login.no_login_methods.description" - (hash adminLoginPath=this.adminLoginPath) - ) - }} -
-+ {{html-safe + (i18n + "login.no_login_methods.description" + (hash adminLoginPath=this.adminLoginPath) + ) + }} +