diff --git a/local_moodleappbehat/tests/behat/behat_app.php b/local_moodleappbehat/tests/behat/behat_app.php index ca4f512aa..498b1c111 100644 --- a/local_moodleappbehat/tests/behat/behat_app.php +++ b/local_moodleappbehat/tests/behat/behat_app.php @@ -336,7 +336,7 @@ class behat_app extends behat_app_helper { // Note there are two 'Log in' texts visible (the title and the button) so we have to use // a 'near' value here. - $this->i_press_in_the_app('"Log in" near "Forgotten"'); + $this->i_press_in_the_app('"Log in" "ion-button"'); // Wait until the main page appears. $this->spin( diff --git a/scripts/langindex.json b/scripts/langindex.json index 332b659a6..90906b272 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -2074,7 +2074,7 @@ "core.login.findyoursite": "local_moodlemobileapp", "core.login.firsttime": "moodle", "core.login.forcepasswordchangenotice": "moodle", - "core.login.forgotten": "moodle", + "core.login.forgotaccount": "moodle", "core.login.help": "moodle", "core.login.instructions": "auth", "core.login.invalidaccount": "local_moodlemobileapp", diff --git a/src/core/classes/site.ts b/src/core/classes/site.ts index c39a09f1e..d44db5b03 100644 --- a/src/core/classes/site.ts +++ b/src/core/classes/site.ts @@ -2771,7 +2771,7 @@ export type CoreSitePublicConfigResponse = { maintenancemessage: string; // Maintenance message. logourl?: string; // The site logo URL. compactlogourl?: string; // The site compact logo URL. - typeoflogin: number; // The type of login. 1 for app, 2 for browser, 3 for embedded. + typeoflogin: TypeOfLogin; // The type of login. 1 for app, 2 for browser, 3 for embedded. launchurl?: string; // SSO login launch URL. mobilecssurl?: string; // Mobile custom CSS theme. // eslint-disable-next-line @typescript-eslint/naming-convention @@ -2869,3 +2869,12 @@ enum OngoingRequestType { STANDARD = 0, UPDATE_IN_BACKGROUND = 1, } + +/** + * The type of login. 1 for app, 2 for browser, 3 for embedded. + */ +export enum TypeOfLogin { + APP = 1, + BROWSER = 2, // SSO in browser window is required. + EMBEDDED = 3, // SSO in embedded browser is required. +} diff --git a/src/core/constants.ts b/src/core/constants.ts index 3048b6501..b1eaa1af8 100644 --- a/src/core/constants.ts +++ b/src/core/constants.ts @@ -82,7 +82,13 @@ export class CoreConstants { static readonly WS_PREFIX = 'local_mobile_'; // @deprecated since app 4.0. // Login constants. + /** + * @deprecated since 4.3 Use TypeOfLogin.BROWSER instead. + */ static readonly LOGIN_SSO_CODE = 2; // SSO in browser window is required. + /** + * @deprecated since 4.3 Use TypeOfLogin.EMBEDDED instead. + */ static readonly LOGIN_SSO_INAPP_CODE = 3; // SSO in embedded browser is required. static readonly LOGIN_LAUNCH_DATA = 'CoreLoginLaunchData'; diff --git a/src/core/features/login/components/login-methods/login-methods.ts b/src/core/features/login/components/login-methods/login-methods.ts index 606e2ee13..a934c1bc0 100644 --- a/src/core/features/login/components/login-methods/login-methods.ts +++ b/src/core/features/login/components/login-methods/login-methods.ts @@ -31,6 +31,7 @@ export class CoreLoginMethodsComponent implements OnInit { @Input() siteConfig?: CoreSitePublicConfigResponse; @Input() redirectData?: CoreRedirectPayload; + isBrowserSSO = false; showScanQR = false; loginMethods: CoreLoginMethod[] = []; identityProviders: CoreSiteIdentityProvider[] = []; @@ -50,9 +51,14 @@ export class CoreLoginMethodsComponent implements OnInit { } if (this.siteConfig) { - const disabledFeatures = CoreLoginHelper.getDisabledFeatures(this.siteConfig); + this.isBrowserSSO = CoreLoginHelper.isSSOLoginNeeded(this.siteConfig.typeoflogin); - this.identityProviders = CoreLoginHelper.getValidIdentityProviders(this.siteConfig, disabledFeatures); + if (!this.isBrowserSSO) { + // Identity providers won't be shown if login on browser. + const disabledFeatures = CoreLoginHelper.getDisabledFeatures(this.siteConfig); + + this.identityProviders = CoreLoginHelper.getValidIdentityProviders(this.siteConfig, disabledFeatures); + } if (this.reconnect) { this.showScanQR = CoreLoginHelper.displayQRInSiteScreen(); diff --git a/src/core/features/login/lang.json b/src/core/features/login/lang.json index 28f619fee..c9bad9613 100644 --- a/src/core/features/login/lang.json +++ b/src/core/features/login/lang.json @@ -37,7 +37,7 @@ "exceededpasswordresetattemptssupportsubject": "I can't reset my password", "faqcannotfindmysiteanswer": "If you tried searching by URL address and still can't find your Moodle site, please get in touch with the person who takes care of Moodle in your school or learning organisation.", "faqcannotfindmysitequestion": "I can't find my site by URL address.", - "faqcantloginanswer": "

Once you've connected to your Moodle site, you should be able to log in with your usual username and password.


If you forgot your username or password, select the option Forgotten your username or password?. If you still have trouble logging in or can't see any options for retrieving your username or password, please get in touch with the person who takes care of Moodle in your school or learning organisation.

", + "faqcantloginanswer": "

Once you've connected to your Moodle site, you should be able to log in with your usual username and password.


If you forgot your username or password, select the option Lost password?. If you still have trouble logging in or can't see any options for retrieving your username or password, please get in touch with the person who takes care of Moodle in your school or learning organisation.

", "faqcantloginquestion": "I can't log in.", "faqmore": "Check out our FAQ for more answers.", "faqsetupsiteanswer": "Visit {{$link}} to check out the different options you have to create your own Moodle site.", @@ -52,7 +52,7 @@ "findyoursite": "Find your site", "firsttime": "Is this your first time here?", "forcepasswordchangenotice": "You must change your password to proceed.", - "forgotten": "Forgotten your username or password?", + "forgotaccount": "Lost password?", "help": "Help", "instructions": "Instructions", "invalidaccount": "Please check your login details and try again.", diff --git a/src/core/features/login/pages/credentials/credentials.html b/src/core/features/login/pages/credentials/credentials.html index 451709a7f..be6df4301 100644 --- a/src/core/features/login/pages/credentials/credentials.html +++ b/src/core/features/login/pages/credentials/credentials.html @@ -69,7 +69,7 @@ - {{ 'core.login.forgotten' | translate }} + {{ 'core.login.forgotaccount' | translate }} @@ -86,7 +86,7 @@ -
+

{{ 'core.login.firsttime' | translate }}

- + + {{ 'core.login.startsignup' | translate }} +
- - {{ 'core.login.startsignup' | translate }} - + {{ 'core.tryagain' | translate }} diff --git a/src/core/features/login/pages/credentials/credentials.ts b/src/core/features/login/pages/credentials/credentials.ts index 9f283db30..e6b995c06 100644 --- a/src/core/features/login/pages/credentials/credentials.ts +++ b/src/core/features/login/pages/credentials/credentials.ts @@ -106,6 +106,10 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy { await this.checkSite(); + if (this.isBrowserSSO && CoreLoginHelper.shouldSkipCredentialsScreenOnSSO()) { + this.openBrowserSSO(); + } + if (CorePlatform.isIOS() && !this.isBrowserSSO) { // Make iOS auto-fill work. The field that isn't focused doesn't get updated, do it manually. // Debounce it to prevent triggering this function too often when the user is typing. diff --git a/src/core/features/login/pages/reconnect/reconnect.html b/src/core/features/login/pages/reconnect/reconnect.html index dbda9509a..c5baa2686 100644 --- a/src/core/features/login/pages/reconnect/reconnect.html +++ b/src/core/features/login/pages/reconnect/reconnect.html @@ -76,7 +76,7 @@ diff --git a/src/core/features/login/services/login-helper.ts b/src/core/features/login/services/login-helper.ts index ee194491b..3ae5297f3 100644 --- a/src/core/features/login/services/login-helper.ts +++ b/src/core/features/login/services/login-helper.ts @@ -26,7 +26,7 @@ import { CoreTextUtils } from '@services/utils/text'; import { CoreUrlParams, CoreUrlUtils } from '@services/utils/url'; import { CoreUtils } from '@services/utils/utils'; import { CoreConstants } from '@/core/constants'; -import { CoreSite, CoreSiteIdentityProvider, CoreSitePublicConfigResponse, CoreSiteQRCodeType } from '@classes/site'; +import { CoreSite, CoreSiteIdentityProvider, CoreSitePublicConfigResponse, CoreSiteQRCodeType, TypeOfLogin } from '@classes/site'; import { CoreError } from '@classes/errors/error'; import { CoreWSError } from '@classes/errors/wserror'; import { DomSanitizer, makeSingleton, Translate } from '@singletons'; @@ -139,7 +139,7 @@ export class CoreLoginHelperProvider { * Open a browser to perform SSO login. * * @param siteUrl URL of the site where the SSO login will be performed. - * @param typeOfLogin CoreConstants.LOGIN_SSO_CODE or CoreConstants.LOGIN_SSO_INAPP_CODE. + * @param typeOfLogin TypeOfLogin.BROWSER or TypeOfLogin.EMBEDDED. * @param service The service to use. If not defined, core service will be used. * @param launchUrl The URL to open for SSO. If not defined, default tool mobile launch URL will be used. * @param redirectData Data of the path/url to open once authenticated. If not defined, site initial page. @@ -148,7 +148,7 @@ export class CoreLoginHelperProvider { */ async confirmAndOpenBrowserForSSOLogin( siteUrl: string, - typeOfLogin: number, + typeOfLogin: TypeOfLogin, service?: string, launchUrl?: string, redirectData?: CoreRedirectPayload, @@ -601,8 +601,8 @@ export class CoreLoginHelperProvider { * @param code Code to check. * @returns True if embedded browser, false othwerise. */ - isSSOEmbeddedBrowser(code: number): boolean { - return code == CoreConstants.LOGIN_SSO_INAPP_CODE; + isSSOEmbeddedBrowser(code: TypeOfLogin): boolean { + return code == TypeOfLogin.EMBEDDED; } /** @@ -611,8 +611,8 @@ export class CoreLoginHelperProvider { * @param code Code to check. * @returns True if SSO login is needed, false othwerise. */ - isSSOLoginNeeded(code: number): boolean { - return code == CoreConstants.LOGIN_SSO_CODE || code == CoreConstants.LOGIN_SSO_INAPP_CODE; + isSSOLoginNeeded(code: TypeOfLogin): boolean { + return code == TypeOfLogin.BROWSER || code == TypeOfLogin.EMBEDDED; } /** @@ -656,14 +656,14 @@ export class CoreLoginHelperProvider { * Open a browser to perform SSO login. * * @param siteUrl URL of the site where the SSO login will be performed. - * @param typeOfLogin CoreConstants.LOGIN_SSO_CODE or CoreConstants.LOGIN_SSO_INAPP_CODE. + * @param typeOfLogin TypeOfLogin.BROWSER or TypeOfLogin.EMBEDDED. * @param service The service to use. If not defined, core service will be used. * @param launchUrl The URL to open for SSO. If not defined, default tool mobile launch URL will be used. * @param redirectData Data of the path/url to open once authenticated. If not defined, site initial page. */ openBrowserForSSOLogin( siteUrl: string, - typeOfLogin: number, + typeOfLogin: TypeOfLogin, service?: string, launchUrl?: string, redirectData?: CoreRedirectPayload, @@ -901,13 +901,21 @@ export class CoreLoginHelperProvider { /** * Check if a confirm should be shown to open a SSO authentication. * - * @param typeOfLogin CoreConstants.LOGIN_SSO_CODE or CoreConstants.LOGIN_SSO_INAPP_CODE. + * @param typeOfLogin TypeOfLogin.BROWSER or TypeOfLogin.EMBEDDED. * @returns True if confirm modal should be shown, false otherwise. - * @deprecated since 4.3 Not used anymore. + * @deprecated since 4.3 Not used anymore. See shouldSkipCredentialsScreenOnSSO. */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - shouldShowSSOConfirm(typeOfLogin: number): boolean { - return false; + shouldShowSSOConfirm(typeOfLogin: TypeOfLogin): boolean { + return !this.isSSOEmbeddedBrowser(typeOfLogin) && !this.shouldSkipCredentialsScreenOnSSO(); + } + + /** + * Check if we can skip credentials page. + * + * @returns If true, the browser should be opened without the user prompt. + */ + shouldSkipCredentialsScreenOnSSO(): boolean { + return String(CoreConstants.CONFIG.skipssoconfirmation) === 'true'; } /** diff --git a/src/core/features/login/tests/behat/basic-usage-400.feature b/src/core/features/login/tests/behat/basic-usage-400.feature index 5e6f19148..9bae39ca8 100644 --- a/src/core/features/login/tests/behat/basic-usage-400.feature +++ b/src/core/features/login/tests/behat/basic-usage-400.feature @@ -9,11 +9,11 @@ Feature: Test basic usage of login in app Scenario: Forgot password When I enter the app - And I press "Forgotten your username or password?" in the app + And I press "Lost password?" in the app And I set the field "Enter either username or email address" to "student1" And I press "Search" in the app Then I should find "Success" in the app When I press "OK" in the app - And I press "Forgotten your username or password?" in the app + And I press "Lost password?" in the app Then I should find "Contact support" in the app diff --git a/src/core/features/login/tests/behat/basic_usage-311.feature b/src/core/features/login/tests/behat/basic_usage-311.feature index a08791ffb..dc76f87e5 100644 --- a/src/core/features/login/tests/behat/basic_usage-311.feature +++ b/src/core/features/login/tests/behat/basic_usage-311.feature @@ -9,11 +9,11 @@ Feature: Test basic usage of login in app Scenario: Forgot password When I enter the app - And I press "Forgotten your username or password?" in the app + And I press "Lost password?" in the app And I set the field "Enter either username or email address" to "student1" And I press "Search" in the app Then I should find "Success" in the app When I press "OK" in the app - And I press "Forgotten your username or password?" in the app + And I press "Lost password?" in the app Then I should not find "Contact support" in the app diff --git a/src/core/features/login/tests/behat/basic_usage.feature b/src/core/features/login/tests/behat/basic_usage.feature index c7421a7c1..152edad21 100755 --- a/src/core/features/login/tests/behat/basic_usage.feature +++ b/src/core/features/login/tests/behat/basic_usage.feature @@ -36,7 +36,7 @@ Feature: Test basic usage of login in app When I set the following fields to these values in the app: | Username | student1 | | Password | student1 | - And I press "Log in" near "Forgotten your username or password?" in the app + And I press "Log in" near "Lost password?" in the app Then I should find "Acceptance test site" in the app And the UI should match the snapshot But I should not find "Log in" in the app @@ -143,11 +143,11 @@ Feature: Test basic usage of login in app Given the following config values are set as admin: | supportavailability | 2 | When I enter the app - And I press "Forgotten your username or password?" in the app + And I press "Lost password?" in the app And I set the field "Enter either username or email address" to "student1" And I press "Search" in the app Then I should find "Success" in the app When I press "OK" in the app - And I press "Forgotten your username or password?" in the app + And I press "Lost password?" in the app Then I should find "Contact support" in the app diff --git a/src/core/features/login/tests/behat/signup.feature b/src/core/features/login/tests/behat/signup.feature index 95ecfcb84..6518f3770 100755 --- a/src/core/features/login/tests/behat/signup.feature +++ b/src/core/features/login/tests/behat/signup.feature @@ -62,14 +62,14 @@ Feature: Test signup in app And I set the following fields to these values in the app: | Username | u1 | | Password | pu1 | - And I press "Log in" near "Forgotten your username or password?" in the app + And I press "Log in" near "Lost password?" in the app Then I should find "You need to confirm your account" in the app When I open a browser tab with url "$WWWROOT" And I confirm email for "u1" And I close the browser tab opened by the app And I press "Close" in the app - And I press "Log in" near "Forgotten your username or password?" in the app + And I press "Log in" near "Lost password?" in the app Then I should find "Acceptance test site" in the app But I should not find "You need to confirm your account" in the app @@ -173,7 +173,7 @@ Feature: Test signup in app And I set the following fields to these values in the app: | Username | u1 | | Password | pu1 | - And I press "Log in" near "Forgotten your username or password?" in the app + And I press "Log in" near "Lost password?" in the app And I press the user menu button in the app And I press "User Test" in the app Then I should find "No" near "Are you a developer?" in the app diff --git a/src/core/features/login/tests/behat/snapshots/test-basic-usage-of-login-in-app-add-a-new-account-in-the-app--site-name-in-displayed-when-adding-a-new-account_9.png b/src/core/features/login/tests/behat/snapshots/test-basic-usage-of-login-in-app-add-a-new-account-in-the-app--site-name-in-displayed-when-adding-a-new-account_9.png index 0c3b160a8..727cbb0e1 100644 Binary files a/src/core/features/login/tests/behat/snapshots/test-basic-usage-of-login-in-app-add-a-new-account-in-the-app--site-name-in-displayed-when-adding-a-new-account_9.png and b/src/core/features/login/tests/behat/snapshots/test-basic-usage-of-login-in-app-add-a-new-account-in-the-app--site-name-in-displayed-when-adding-a-new-account_9.png differ diff --git a/src/types/config.d.ts b/src/types/config.d.ts index cb34209a9..49743638d 100644 --- a/src/types/config.d.ts +++ b/src/types/config.d.ts @@ -46,6 +46,7 @@ export interface EnvironmentConfig { multisitesdisplay: CoreLoginSiteSelectorListMethod; sitefindersettings: Partial; onlyallowlistedsites: boolean; + skipssoconfirmation: boolean; forcedefaultlanguage: boolean; privacypolicy: string; notificoncolor: string;