diff --git a/moodle.config.json b/moodle.config.json index af5ee4d0d..99348b609 100644 --- a/moodle.config.json +++ b/moodle.config.json @@ -62,7 +62,6 @@ "zh-tw": "正體中文" }, "wsservice": "moodle_mobile_app", - "wsextservice": "local_mobile", "demo_sites": { "student": { "url": "https:\/\/school.moodledemo.net", diff --git a/scripts/langindex.json b/scripts/langindex.json index 80e114b51..3c46978e7 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -1851,7 +1851,6 @@ "core.login.invalidurl": "scorm", "core.login.invalidvaluemax": "local_moodlemobileapp", "core.login.invalidvaluemin": "local_moodlemobileapp", - "core.login.localmobileunexpectedresponse": "local_moodlemobileapp", "core.login.loggedoutssodescription": "local_moodlemobileapp", "core.login.login": "moodle", "core.login.loginbutton": "local_moodlemobileapp", diff --git a/src/core/classes/site.ts b/src/core/classes/site.ts index c5a3260f2..c3593943a 100644 --- a/src/core/classes/site.ts +++ b/src/core/classes/site.ts @@ -485,9 +485,6 @@ export class CoreSite { * * Caching is also implemented, when enabled this method will returned a cached version of the request if the * data hasn't expired. - * - * This method is smart which means that it will try to map the method to a compatibility one if need be, usually this - * means that it will fallback on the 'local_mobile_' prefixed function if it is available and the non-prefixed is not. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any async request(method: string, data: any, preSets: CoreSiteWSPreSets, retrying?: boolean): Promise { @@ -505,18 +502,12 @@ export class CoreSite { throw new CoreError(Translate.instant('core.errorofflinedisabled')); } - // Check if the method is available, use a prefixed version if possible. + // Check if the method is available. // We ignore this check when we do not have the site info, as the list of functions is not loaded yet. - if (this.getInfo() && !this.wsAvailable(method, false)) { - const compatibilityMethod = CoreConstants.WS_PREFIX + method; - if (this.wsAvailable(compatibilityMethod, false)) { - this.logger.info(`Using compatibility WS method '${compatibilityMethod}'`); - method = compatibilityMethod; - } else { - this.logger.error(`WS function '${method}' is not available, even in compatibility mode.`); + if (this.getInfo() && !this.wsAvailable(method)) { + this.logger.error(`WS function '${method}' is not available.`); - throw new CoreError(Translate.instant('core.wsfunctionnotavailable')); - } + throw new CoreError(Translate.instant('core.wsfunctionnotavailable')); } const wsPreSets: CoreWSPreSets = { @@ -860,24 +851,10 @@ export class CoreSite { * Check if a WS is available in this site. * * @param method WS name. - * @param checkPrefix When true also checks with the compatibility prefix. * @return Whether the WS is available. */ - wsAvailable(method: string, checkPrefix: boolean = true): boolean { - if (typeof this.infos == 'undefined') { - return false; - } - - if (this.infos?.functionsByName?.[method]) { - return true; - } - - // Let's try again with the compatibility prefix. - if (checkPrefix) { - return this.wsAvailable(CoreConstants.WS_PREFIX + method, false); - } - - return false; + wsAvailable(method: string): boolean { + return !!this.infos?.functionsByName?.[method]; } /** @@ -1301,112 +1278,32 @@ export class CoreSite { /** * Check if the local_mobile plugin is installed in the Moodle site. * - * @param retrying True if we're retrying the check. * @return Promise resolved when the check is done. + * @deprecated since app 4.0 */ - async checkLocalMobilePlugin(retrying?: boolean): Promise { - const checkUrl = this.siteUrl + '/local/mobile/check.php'; - const service = CoreConstants.CONFIG.wsextservice; - - if (!service) { - // External service not defined. - return { code: 0 }; - } - - let data; - - try { - const response = await CoreWS.sendHTTPRequest(checkUrl, { - method: 'post', - data: { service }, - }); - - data = response.body; - } catch (ex) { - return { code: 0 }; - } - - if (data === null) { - // This probably means that the server was configured to return null for non-existing URLs. Not installed. - return { code: 0 }; - } - - if (typeof data != 'undefined' && data.errorcode === 'requirecorrectaccess') { - if (!retrying) { - this.siteUrl = CoreUrlUtils.addOrRemoveWWW(this.siteUrl); - - return this.checkLocalMobilePlugin(true); - } else { - throw new CoreWSError(data); - } - } else if (typeof data == 'undefined' || typeof data.code == 'undefined') { - // The local_mobile returned something we didn't expect. Let's assume it's not installed. - return { code: 0, warning: 'core.login.localmobileunexpectedresponse' }; - } - - const code = parseInt(data.code, 10); - if (data.error) { - switch (code) { - case 1: - // Site in maintenance mode. - throw new CoreError(Translate.instant('core.login.siteinmaintenance')); - case 2: - // Web services not enabled. - throw new CoreError(Translate.instant('core.login.webservicesnotenabled')); - case 3: - // Extended service not enabled, but the official is enabled. - return { code: 0 }; - case 4: - // Neither extended or official services enabled. - throw new CoreError(Translate.instant('core.login.mobileservicesnotenabled')); - default: - throw new CoreError(Translate.instant('core.unexpectederror')); - } - } else { - return { code, service, coreSupported: !!data.coresupported }; - } + async checkLocalMobilePlugin(): Promise { + // Not used anymore. + return { code: 0, coreSupported: true }; } /** * Check if local_mobile has been installed in Moodle. * * @return Whether the App is able to use local_mobile plugin for this site. + * @deprecated since app 4.0 */ checkIfAppUsesLocalMobile(): boolean { - let appUsesLocalMobile = false; - - if (!this.infos || !this.infos.functions) { - return appUsesLocalMobile; - } - - this.infos.functions.forEach((func) => { - if (func.name.indexOf(CoreConstants.WS_PREFIX) != -1) { - appUsesLocalMobile = true; - } - }); - - return appUsesLocalMobile; + return false; } /** * Check if local_mobile has been installed in Moodle but the app is not using it. * * @return Promise resolved it local_mobile was added, rejected otherwise. + * @deprecated since app 4.0 */ async checkIfLocalMobileInstalledAndNotUsed(): Promise { - const appUsesLocalMobile = this.checkIfAppUsesLocalMobile(); - - if (appUsesLocalMobile) { - // App already uses local_mobile, it wasn't added. - throw new CoreError('Already used.'); - } - - const data = await this.checkLocalMobilePlugin(); - - if (typeof data.service == 'undefined') { - // The local_mobile NOT installed. Reject. - throw new CoreError('Not installed.'); - } + throw new CoreError('Deprecated.'); } /** @@ -2078,6 +1975,8 @@ export type CoreSiteWSPreSets = { /** * Response of checking local_mobile status. + * + * @deprecated since app 4.0 */ export type LocalMobileResponse = { /** diff --git a/src/core/constants.ts b/src/core/constants.ts index bbba1fdbd..255be2450 100644 --- a/src/core/constants.ts +++ b/src/core/constants.ts @@ -68,7 +68,7 @@ export class CoreConstants { // WS constants. static readonly WS_TIMEOUT = 30000; // Timeout when not in WiFi. static readonly WS_TIMEOUT_WIFI = 30000; // Timeout when in WiFi. - static readonly WS_PREFIX = 'local_mobile_'; + static readonly WS_PREFIX = 'local_mobile_'; // @deprecated since app 4.0. // Login constants. static readonly LOGIN_SSO_CODE = 2; // SSO in browser window is required. diff --git a/src/core/features/login/lang.json b/src/core/features/login/lang.json index 74ae914e8..8ebeb7fa5 100644 --- a/src/core/features/login/lang.json +++ b/src/core/features/login/lang.json @@ -56,7 +56,6 @@ "invalidurl": "Invalid URL specified", "invalidvaluemax": "The maximum value is {{$a}}", "invalidvaluemin": "The minimum value is {{$a}}", - "localmobileunexpectedresponse": "Moodle Mobile Additional Features check returned an unexpected response. You will be authenticated using the standard mobile service.", "loggedoutssodescription": "You have to authenticate again. You need to log in to the site in a browser window.", "login": "Log in", "loginbutton": "Log in", diff --git a/src/core/features/login/pages/credentials/credentials.ts b/src/core/features/login/pages/credentials/credentials.ts index 714b06934..7f478d243 100644 --- a/src/core/features/login/pages/credentials/credentials.ts +++ b/src/core/features/login/pages/credentials/credentials.ts @@ -124,7 +124,7 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy { } /** - * Check if a site uses local_mobile, requires SSO login, etc. + * Get site config and check if it requires SSO login. * This should be used only if a fixed URL is set, otherwise this check is already performed in CoreLoginSitePage. * * @param siteUrl Site URL to check. @@ -145,10 +145,6 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy { this.siteConfig = result.config; this.treatSiteConfig(); - if (result && result.warning) { - CoreDomUtils.showErrorModal(result.warning, true, 4000); - } - if (CoreLoginHelper.isSSOLoginNeeded(result.code)) { // SSO. User needs to authenticate in a browser. this.isBrowserSSO = true; diff --git a/src/core/features/login/pages/email-signup/email-signup.ts b/src/core/features/login/pages/email-signup/email-signup.ts index 7e2462f6d..6e3c673ce 100644 --- a/src/core/features/login/pages/email-signup/email-signup.ts +++ b/src/core/features/login/pages/email-signup/email-signup.ts @@ -310,8 +310,7 @@ export class CoreLoginEmailSignupPage implements OnInit { }; if (this.siteConfig?.launchurl) { - const service = CoreSites.determineService(this.siteUrl); - params.redirect = CoreLoginHelper.prepareForSSOLogin(this.siteUrl, service, this.siteConfig.launchurl); + params.redirect = CoreLoginHelper.prepareForSSOLogin(this.siteUrl, undefined, this.siteConfig.launchurl); } // Get the recaptcha response (if needed). diff --git a/src/core/features/login/pages/site/site.ts b/src/core/features/login/pages/site/site.ts index ea3f85f98..1f567ebad 100644 --- a/src/core/features/login/pages/site/site.ts +++ b/src/core/features/login/pages/site/site.ts @@ -339,10 +339,6 @@ export class CoreLoginSitePage implements OnInit { CoreForms.triggerFormSubmittedEvent(this.formElement, true); - if (response.warning) { - CoreDomUtils.showErrorModal(response.warning, true, 4000); - } - if (CoreLoginHelper.isSSOLoginNeeded(response.code)) { // SSO. User needs to authenticate in a browser. CoreLoginHelper.confirmAndOpenBrowserForSSOLogin( diff --git a/src/core/features/login/services/login-helper.ts b/src/core/features/login/services/login-helper.ts index 91d95ff1f..75c316eb2 100644 --- a/src/core/features/login/services/login-helper.ts +++ b/src/core/features/login/services/login-helper.ts @@ -128,8 +128,8 @@ export class CoreLoginHelperProvider { * * @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 service The service to use. If not defined, external service will be used. - * @param launchUrl The URL to open for SSO. If not defined, local_mobile launch URL will be used. + * @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. * @return Promise resolved when done or if user cancelled. */ async confirmAndOpenBrowserForSSOLogin( @@ -655,8 +655,7 @@ export class CoreLoginHelperProvider { return false; } - const service = CoreSites.determineService(siteUrl); - const loginUrl = this.prepareForSSOLogin(siteUrl, service, launchUrl, pageName, pageOptions, { + const loginUrl = this.prepareForSSOLogin(siteUrl, undefined, launchUrl, pageName, pageOptions, { oauthsso: params.id, }); @@ -672,8 +671,8 @@ export class CoreLoginHelperProvider { * * @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 service The service to use. If not defined, external service will be used. - * @param launchUrl The URL to open for SSO. If not defined, local_mobile launch URL will be used. + * @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 pageName Name of the page to go once authenticated. If not defined, site initial page. * @param pageOptions Options of the state to go once authenticated. */ @@ -790,8 +789,8 @@ export class CoreLoginHelperProvider { * Prepare the app to perform SSO login. * * @param siteUrl URL of the site where the SSO login will be performed. - * @param service The service to use. If not defined, external service will be used. - * @param launchUrl The URL to open for SSO. If not defined, local_mobile launch URL will be used. + * @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 pageName Name of the page to go once authenticated. If not defined, site initial page. * @param pageOptions Options of the page to go once authenticated. * @param urlParams Other params to add to the URL. @@ -806,8 +805,8 @@ export class CoreLoginHelperProvider { urlParams?: CoreUrlParams, ): string { - service = service || CoreConstants.CONFIG.wsextservice; - launchUrl = launchUrl || siteUrl + '/local/mobile/launch.php'; + service = service || CoreConstants.CONFIG.wsservice; + launchUrl = launchUrl || siteUrl + '/admin/tool/mobile/launch.php'; const passport = Math.random() * 1000; let loginUrl = launchUrl + '?service=' + service; @@ -896,10 +895,6 @@ export class CoreLoginHelperProvider { // Check authentication method. const result = await CoreSites.checkSite(siteUrl); - if (result.warning) { - CoreDomUtils.showErrorModal(result.warning, true, 4000); - } - if (this.isSSOLoginNeeded(result.code)) { // SSO. User needs to authenticate in a browser. Check if we need to display a message. if (!CoreApp.isSSOAuthenticationOngoing() && !this.waitingForBrowser) { diff --git a/src/core/features/settings/services/settings-helper.ts b/src/core/features/settings/services/settings-helper.ts index 2d68d2330..ee07046d5 100644 --- a/src/core/features/settings/services/settings-helper.ts +++ b/src/core/features/settings/services/settings-helper.ts @@ -267,7 +267,6 @@ export class CoreSettingsHelperProvider { CoreUtils.ignoreErrors(CoreFilepool.invalidateAllFiles(siteId)), // Invalidate and synchronize site data. site.invalidateWsCache(), - this.checkSiteLocalMobile(site), CoreSites.updateSiteInfo(site.getId()), CoreCronDelegate.forceSyncExecution(site.getId()), // eslint-disable-next-line arrow-body-style @@ -284,27 +283,6 @@ export class CoreSettingsHelperProvider { } } - /** - * Check if local_mobile was added to the site. - * - * @param site Site to check. - * @return Promise resolved if no action needed. - */ - protected async checkSiteLocalMobile(site: CoreSite): Promise { - try { - // Check if local_mobile was installed in Moodle. - await site.checkIfLocalMobileInstalledAndNotUsed(); - } catch { - // Not added, nothing to do. - return; - } - - // Local mobile was added. Throw invalid session to force reconnect and create a new token. - CoreEvents.trigger(CoreEvents.SESSION_EXPIRED, {}, site.getId()); - - throw new CoreError(Translate.instant('core.lostconnection')); - } - /** * Upgrades from Font size to new zoom level. */ diff --git a/src/core/services/sites.ts b/src/core/services/sites.ts index ee1b5c434..85de9ea31 100644 --- a/src/core/services/sites.ts +++ b/src/core/services/sites.ts @@ -27,7 +27,6 @@ import { CoreConstants } from '@/core/constants'; import { CoreSite, CoreSiteWSPreSets, - LocalMobileResponse, CoreSiteInfo, CoreSiteConfig, CoreSitePublicConfigResponse, @@ -73,7 +72,6 @@ export class CoreSitesProvider { protected static readonly INVALID_VERSION = -1; protected logger: CoreLogger; - protected services = {}; protected sessionRestored = false; protected currentSite?: CoreSite; protected sites: { [s: string]: CoreSite } = {}; @@ -182,8 +180,6 @@ export class CoreSitesProvider { * @return A promise resolved when the site is checked. */ async checkSiteWithProtocol(siteUrl: string, protocol: string): Promise { - let publicConfig: CoreSitePublicConfigResponse | undefined; - // Now, replace the siteUrl with the protocol. siteUrl = siteUrl.replace(/^https?:\/\//i, protocol); @@ -222,82 +218,59 @@ export class CoreSitesProvider { } } - // Site exists. Create a temporary site to check if local_mobile is installed. + // Site exists. Create a temporary site to fetch its info. const temporarySite = CoreSitesFactory.makeSite(undefined, siteUrl); - let data: LocalMobileResponse; + let config: CoreSitePublicConfigResponse | undefined; try { - data = await temporarySite.checkLocalMobilePlugin(); + config = await temporarySite.getPublicConfig(); + + // Check that the user can authenticate. + if (!config.enablewebservices) { + throw new CoreSiteError({ + message: Translate.instant('core.login.webservicesnotenabled'), + }); + } else if (!config.enablemobilewebservice) { + throw new CoreSiteError({ + message: Translate.instant('core.login.mobileservicesnotenabled'), + }); + } else if (config.maintenanceenabled) { + let message = Translate.instant('core.sitemaintenance'); + if (config.maintenancemessage) { + message += config.maintenancemessage; + } + + throw new CoreSiteError({ + message, + }); + } } catch (error) { - // Local mobile check returned an error. This only happens if the plugin is installed and it returns an error. - throw new CoreSiteError({ - message: error.message, - critical: true, - }); - } + // Error, check if not supported. + if (error.available === 1) { + // Service supported but an error happened. Return error. + if (error.errorcode == 'codingerror') { + // This could be caused by a redirect. Check if it's the case. + const redirect = await CoreUtils.checkRedirect(siteUrl); - data.service = data.service || CoreConstants.CONFIG.wsservice; - this.services[siteUrl] = data.service; // No need to store it in DB. - - if (data.coreSupported || (data.code != CoreConstants.LOGIN_SSO_CODE && data.code != CoreConstants.LOGIN_SSO_INAPP_CODE)) { - // SSO using local_mobile not needed, try to get the site public config. - try { - const config = await temporarySite.getPublicConfig(); - - publicConfig = config; - - // Check that the user can authenticate. - if (!config.enablewebservices) { - throw new CoreSiteError({ - message: Translate.instant('core.login.webservicesnotenabled'), - }); - } else if (!config.enablemobilewebservice) { - throw new CoreSiteError({ - message: Translate.instant('core.login.mobileservicesnotenabled'), - }); - } else if (config.maintenanceenabled) { - let message = Translate.instant('core.sitemaintenance'); - if (config.maintenancemessage) { - message += config.maintenancemessage; + if (redirect) { + error.error = Translate.instant('core.login.sitehasredirect'); + } else { + // We can't be sure if there is a redirect or not. Display cannot connect error. + error.error = Translate.instant('core.cannotconnecttrouble'); } - - throw new CoreSiteError({ - message, - }); } - // Everything ok. - if (data.code === 0) { - data.code = config.typeoflogin; - } - } catch (error) { - // Error, check if not supported. - if (error.available === 1) { - // Service supported but an error happened. Return error. - if (error.errorcode == 'codingerror') { - // This could be caused by a redirect. Check if it's the case. - const redirect = await CoreUtils.checkRedirect(siteUrl); - - if (redirect) { - error.error = Translate.instant('core.login.sitehasredirect'); - } else { - // We can't be sure if there is a redirect or not. Display cannot connect error. - error.error = Translate.instant('core.cannotconnecttrouble'); - } - } - - throw new CoreSiteError({ - message: error.error, - errorcode: error.errorcode, - critical: true, - }); - } + throw new CoreSiteError({ + message: error.error, + errorcode: error.errorcode, + critical: true, + }); } } siteUrl = temporarySite.getURL(); - return { siteUrl, code: data.code, warning: data.warning, service: data.service, config: publicConfig }; + return { siteUrl, code: config?.typeoflogin || 0, service: CoreConstants.CONFIG.wsservice, config }; } /** @@ -367,10 +340,7 @@ export class CoreSitesProvider { throw new CoreNetworkError(); } - if (!service) { - service = this.determineService(siteUrl); - } - + service = service || CoreConstants.CONFIG.wsservice; const params = { username, password, @@ -573,25 +543,10 @@ export class CoreSitesProvider { /** * Function for determine which service we should use (default or extended plugin). * - * @param siteUrl The site URL. * @return The service shortname. + * @deprecated since app 4.0 */ - determineService(siteUrl: string): string { - // We need to try siteUrl in both https or http (due to loginhttps setting). - - // First http:// - siteUrl = siteUrl.replace('https://', 'http://'); - if (this.services[siteUrl]) { - return this.services[siteUrl]; - } - - // Now https:// - siteUrl = siteUrl.replace('http://', 'https://'); - if (this.services[siteUrl]) { - return this.services[siteUrl]; - } - - // Return default service. + determineService(): string { return CoreConstants.CONFIG.wsservice; } @@ -839,37 +794,24 @@ export class CoreSitesProvider { return false; } - // Check if local_mobile was installed to Moodle. + let config: CoreSitePublicConfigResponse | undefined; + try { - await site.checkIfLocalMobileInstalledAndNotUsed(); - - // Local mobile was added. Throw invalid session to force reconnect and create a new token. - CoreEvents.trigger(CoreEvents.SESSION_EXPIRED, { - pageName, - options: pageOptions, - }, siteId); - - return false; + config = await site.getPublicConfig(); } catch (error) { - let config: CoreSitePublicConfigResponse | undefined; + // Error getting config, maybe the user is offline. + } - try { - config = await site.getPublicConfig(); - } catch (error) { - // Error getting config, probably the site doesn't have the WS - } + try { + await this.checkApplication(config); - try { - await this.checkApplication(config); + this.login(siteId); + // Update site info. We don't block the UI. + this.updateSiteInfo(siteId); - this.login(siteId); - // Update site info. We don't block the UI. - this.updateSiteInfo(siteId); - - return true; - } catch (error) { - return false; - } + return true; + } catch (error) { + return false; } } @@ -1499,13 +1441,12 @@ export class CoreSitesProvider { * Check if a WS is available in the current site, if any. * * @param method WS name. - * @param checkPrefix When true also checks with the compatibility prefix. * @return Whether the WS is available. */ - wsAvailableInCurrentSite(method: string, checkPrefix: boolean = true): boolean { + wsAvailableInCurrentSite(method: string): boolean { const site = this.getCurrentSite(); - return site ? site.wsAvailable(method, checkPrefix) : false; + return site ? site.wsAvailable(method) : false; } /** @@ -1744,7 +1685,7 @@ export type CoreSiteCheckResponse = { service: string; /** - * Code of the warning message to show to the user. + * Code of the warning message to show to the user. @deprecated since app 4.0 */ warning?: string; diff --git a/src/types/config.d.ts b/src/types/config.d.ts index 25d7151f8..7f3fcc65c 100644 --- a/src/types/config.d.ts +++ b/src/types/config.d.ts @@ -32,7 +32,6 @@ export interface EnvironmentConfig { default_lang: string; languages: Record; wsservice: string; - wsextservice: string; demo_sites: Record; zoomlevels: Record; customurlscheme: string;