MOBILE-3819 core: Remove local_mobile support

main
Dani Palou 2021-09-03 13:33:03 +02:00
parent 68e57c0f17
commit 705f7ce92d
12 changed files with 87 additions and 287 deletions

View File

@ -62,7 +62,6 @@
"zh-tw": "正體中文"
},
"wsservice": "moodle_mobile_app",
"wsextservice": "local_mobile",
"demo_sites": {
"student": {
"url": "https:\/\/school.moodledemo.net",

View File

@ -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",

View File

@ -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<T = unknown>(method: string, data: any, preSets: CoreSiteWSPreSets, retrying?: boolean): Promise<T> {
@ -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<LocalMobileResponse> {
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<LocalMobileResponse> {
// 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<void> {
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 = {
/**

View File

@ -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.

View File

@ -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",

View File

@ -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;

View File

@ -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).

View File

@ -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(

View File

@ -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) {

View File

@ -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<void> {
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.
*/

View File

@ -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<CoreSiteCheckResponse> {
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;

View File

@ -32,7 +32,6 @@ export interface EnvironmentConfig {
default_lang: string;
languages: Record<string, string>;
wsservice: string;
wsextservice: string;
demo_sites: Record<string, CoreSitesDemoSiteData>;
zoomlevels: Record<CoreZoomLevel, number>;
customurlscheme: string;