commit
ba9ccb6566
|
@ -1384,6 +1384,7 @@
|
|||
"core.add": "moodle",
|
||||
"core.agelocationverification": "moodle",
|
||||
"core.ago": "message",
|
||||
"core.ajaxendpointnotfound": "local_moodlemobileapp",
|
||||
"core.all": "moodle",
|
||||
"core.allgroups": "moodle",
|
||||
"core.allparticipants": "moodle",
|
||||
|
@ -1405,6 +1406,7 @@
|
|||
"core.captureimage": "local_moodlemobileapp",
|
||||
"core.capturevideo": "local_moodlemobileapp",
|
||||
"core.category": "moodle",
|
||||
"core.certificaterror": "local_moodlemobileapp",
|
||||
"core.choose": "moodle",
|
||||
"core.choosedots": "moodle",
|
||||
"core.clearsearch": "local_moodlemobileapp",
|
||||
|
|
|
@ -19,12 +19,13 @@ import { CoreError } from '@classes/errors/error';
|
|||
*/
|
||||
export class CoreAjaxError extends CoreError {
|
||||
|
||||
available?: number; // Whether the AJAX call is available. 0 if unknown, 1 if available, -1 if not available.
|
||||
available = 1; // @deprecated since app 4.0. AJAX endpoint should always be available in supported Moodle versions.
|
||||
status?: number;
|
||||
|
||||
constructor(message: string, available?: number) {
|
||||
constructor(message: string, available?: number, status?: number) {
|
||||
super(message);
|
||||
|
||||
this.available = typeof available == 'undefined' ? 0 : available;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1342,38 +1342,38 @@ export class CoreSite {
|
|||
siteUrl: this.siteUrl,
|
||||
};
|
||||
|
||||
let config: CoreSitePublicConfigResponse | undefined;
|
||||
let config: CoreSitePublicConfigResponse;
|
||||
|
||||
try {
|
||||
config = await CoreWS.callAjax('tool_mobile_get_public_config', {}, preSets);
|
||||
config = await CoreWS.callAjax<CoreSitePublicConfigResponse>('tool_mobile_get_public_config', {}, preSets);
|
||||
} catch (error) {
|
||||
if ((!this.getInfo() || this.isVersionGreaterEqualThan('3.8')) && error && error.errorcode == 'codingerror') {
|
||||
// This error probably means that there is a redirect in the site. Try to use a GET request.
|
||||
preSets.noLogin = true;
|
||||
preSets.useGet = true;
|
||||
|
||||
try {
|
||||
config = await CoreWS.callAjax('tool_mobile_get_public_config', {}, preSets);
|
||||
} catch (error2) {
|
||||
if (this.getInfo() && this.isVersionGreaterEqualThan('3.8')) {
|
||||
// GET is supported, return the second error.
|
||||
throw error2;
|
||||
} else {
|
||||
// GET not supported or we don't know if it's supported. Return first error.
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
if (!error || error.errorcode !== 'codingerror' || (this.getInfo() && !this.isVersionGreaterEqualThan('3.8'))) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
throw error;
|
||||
// This error probably means that there is a redirect in the site. Try to use a GET request.
|
||||
preSets.noLogin = true;
|
||||
preSets.useGet = true;
|
||||
|
||||
try {
|
||||
config = await CoreWS.callAjax<CoreSitePublicConfigResponse>('tool_mobile_get_public_config', {}, preSets);
|
||||
} catch (error2) {
|
||||
if (this.getInfo() && this.isVersionGreaterEqualThan('3.8')) {
|
||||
// GET is supported, return the second error.
|
||||
throw error2;
|
||||
} else {
|
||||
// GET not supported or we don't know if it's supported. Return first error.
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use the wwwroot returned by the server.
|
||||
if (config!.httpswwwroot) {
|
||||
this.siteUrl = CoreUrlUtils.removeUrlParams(config!.httpswwwroot); // Make sure the URL doesn't have params.
|
||||
if (config.httpswwwroot) {
|
||||
this.siteUrl = CoreUrlUtils.removeUrlParams(config.httpswwwroot); // Make sure the URL doesn't have params.
|
||||
}
|
||||
|
||||
return config!;
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -498,7 +498,12 @@ export class CoreLoginSitePage implements OnInit {
|
|||
|
||||
if (scheme && scheme != 'http' && scheme != 'https') {
|
||||
CoreDomUtils.showErrorModal(Translate.instant('core.errorurlschemeinvalidscheme', { $a: text }));
|
||||
} else if (CoreLoginHelper.isSiteUrlAllowed(text)) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const allowed = await CoreLoginHelper.isSiteUrlAllowed(text);
|
||||
if (allowed) {
|
||||
// Put the text in the field (if present).
|
||||
this.siteForm.controls.siteUrl.setValue(text);
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
"add": "Add",
|
||||
"agelocationverification": "Age and location verification",
|
||||
"ago": "{{$a}} ago",
|
||||
"ajaxendpointnotfound": "<p>AJAX endpoint not found. This can happen if the Moodle site is too old or it blocks access to this endpoint. The Moodle app only supports Moodle systems {{$a}} onwards. Please contact your site administrator.</p>\n<p>{{whoisadmin}}</p>",
|
||||
"all": "All",
|
||||
"allgroups": "All groups",
|
||||
"allparticipants": "All participants",
|
||||
|
@ -23,6 +24,7 @@
|
|||
"captureimage": "Take picture",
|
||||
"capturevideo": "Record video",
|
||||
"category": "Category",
|
||||
"certificaterror": "<p>The certificate of this site cannot be trusted by your device. Please contact your site administrator.</p>\n<p>{{whoisadmin}}</p>",
|
||||
"choose": "Choose",
|
||||
"choosedots": "Choose...",
|
||||
"clearsearch": "Clear search",
|
||||
|
|
|
@ -54,6 +54,8 @@ import { CoreSitesFactory } from './sites-factory';
|
|||
import { CoreText } from '@singletons/text';
|
||||
import { CoreLoginHelper } from '@features/login/services/login-helper';
|
||||
import { CoreErrorWithTitle } from '@classes/errors/errorwithtitle';
|
||||
import { CoreAjaxError } from '@classes/errors/ajaxerror';
|
||||
import { CoreAjaxWSError } from '@classes/errors/ajaxwserror';
|
||||
|
||||
export const CORE_SITE_SCHEMAS = new InjectionToken<CoreSiteSchema[]>('CORE_SITE_SCHEMAS');
|
||||
|
||||
|
@ -183,33 +185,30 @@ export class CoreSitesProvider {
|
|||
// Now, replace the siteUrl with the protocol.
|
||||
siteUrl = siteUrl.replace(/^https?:\/\//i, protocol);
|
||||
|
||||
try {
|
||||
await this.siteExists(siteUrl);
|
||||
} catch (error) {
|
||||
// Do not continue checking if WS are not enabled.
|
||||
if (error.errorcode == 'enablewsdescription') {
|
||||
error.critical = true;
|
||||
// Create a temporary site to fetch site info.
|
||||
let temporarySite = CoreSitesFactory.makeSite(undefined, siteUrl);
|
||||
let config: CoreSitePublicConfigResponse | undefined;
|
||||
|
||||
throw error;
|
||||
try {
|
||||
config = await temporarySite.getPublicConfig();
|
||||
} catch (error) {
|
||||
const treatedError = await this.treatGetPublicConfigError(temporarySite.getURL(), error);
|
||||
if (treatedError.critical) {
|
||||
throw treatedError; // App received a WS error, stop.
|
||||
}
|
||||
|
||||
// Site doesn't exist. Try to add or remove 'www'.
|
||||
const treatedUrl = CoreUrlUtils.addOrRemoveWWW(siteUrl);
|
||||
// Try to add or remove 'www'.
|
||||
temporarySite = CoreSitesFactory.makeSite(undefined, CoreUrlUtils.addOrRemoveWWW(siteUrl));
|
||||
|
||||
try {
|
||||
await this.siteExists(treatedUrl);
|
||||
|
||||
// Success, use this new URL as site url.
|
||||
siteUrl = treatedUrl;
|
||||
config = await temporarySite.getPublicConfig();
|
||||
} catch (secondError) {
|
||||
// Do not continue checking if WS are not enabled.
|
||||
if (secondError.errorcode == 'enablewsdescription') {
|
||||
secondError.critical = true;
|
||||
|
||||
throw secondError;
|
||||
const treatedSecondError = await this.treatGetPublicConfigError(temporarySite.getURL(), secondError);
|
||||
if (treatedSecondError.critical) {
|
||||
throw treatedSecondError; // App received a WS error, stop.
|
||||
}
|
||||
|
||||
// Return the error.
|
||||
// App didn't receive a WS response, probably cannot connect. Prioritize first error if it's valid.
|
||||
if (CoreTextUtils.getErrorMessageFromError(error)) {
|
||||
throw error;
|
||||
} else {
|
||||
|
@ -218,54 +217,27 @@ export class CoreSitesProvider {
|
|||
}
|
||||
}
|
||||
|
||||
// Site exists. Create a temporary site to fetch its info.
|
||||
const temporarySite = CoreSitesFactory.makeSite(undefined, siteUrl);
|
||||
let config: CoreSitePublicConfigResponse | undefined;
|
||||
|
||||
try {
|
||||
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,
|
||||
});
|
||||
// Check that the user can authenticate.
|
||||
if (!config.enablewebservices) {
|
||||
throw new CoreSiteError({
|
||||
message: Translate.instant('core.login.webservicesnotenabled'),
|
||||
critical: true,
|
||||
});
|
||||
} else if (!config.enablemobilewebservice) {
|
||||
throw new CoreSiteError({
|
||||
message: Translate.instant('core.login.mobileservicesnotenabled'),
|
||||
critical: true,
|
||||
});
|
||||
} else if (config.maintenanceenabled) {
|
||||
let message = Translate.instant('core.sitemaintenance');
|
||||
if (config.maintenancemessage) {
|
||||
message += config.maintenancemessage;
|
||||
}
|
||||
} 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,
|
||||
critical: true,
|
||||
});
|
||||
}
|
||||
|
||||
siteUrl = temporarySite.getURL();
|
||||
|
@ -273,11 +245,48 @@ export class CoreSitesProvider {
|
|||
return { siteUrl, code: config?.typeoflogin || 0, service: CoreConstants.CONFIG.wsservice, config };
|
||||
}
|
||||
|
||||
/**
|
||||
* Treat an error returned by getPublicConfig in checkSiteWithProtocol. Converts the error to a CoreSiteError.
|
||||
*
|
||||
* @param siteUrl Site URL.
|
||||
* @param error Error returned.
|
||||
* @return Promise resolved with the treated error.
|
||||
*/
|
||||
protected async treatGetPublicConfigError(siteUrl: string, error: CoreAjaxError | CoreAjaxWSError): Promise<CoreSiteError> {
|
||||
if (!('errorcode' in error)) {
|
||||
// The WS didn't return data, probably cannot connect.
|
||||
return new CoreSiteError({
|
||||
message: error.message || '',
|
||||
critical: 'status' in error && error.status === -2, // Certificate error.
|
||||
});
|
||||
}
|
||||
|
||||
// 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.message = Translate.instant('core.login.sitehasredirect');
|
||||
} else {
|
||||
// We can't be sure if there is a redirect or not. Display cannot connect error.
|
||||
error.message = Translate.instant('core.cannotconnecttrouble');
|
||||
}
|
||||
}
|
||||
|
||||
return new CoreSiteError({
|
||||
message: error.message,
|
||||
errorcode: error.errorcode,
|
||||
critical: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a site exists.
|
||||
*
|
||||
* @param siteUrl URL of the site to check.
|
||||
* @return A promise to be resolved if the site exists.
|
||||
* @deprecated since app 4.0. Now the app calls uses tool_mobile_get_public_config to check if site exists.
|
||||
*/
|
||||
async siteExists(siteUrl: string): Promise<void> {
|
||||
let data: CoreSitesLoginTokenResponse;
|
||||
|
|
|
@ -37,6 +37,7 @@ import { CoreWSError } from '@classes/errors/wserror';
|
|||
import { CoreAjaxError } from '@classes/errors/ajaxerror';
|
||||
import { CoreAjaxWSError } from '@classes/errors/ajaxwserror';
|
||||
import { CoreNetworkError } from '@classes/errors/network-error';
|
||||
import { CoreSite } from '@classes/site';
|
||||
|
||||
/**
|
||||
* This service allows performing WS calls and download/upload files.
|
||||
|
@ -474,9 +475,23 @@ export class CoreWSProvider {
|
|||
|
||||
return data.data;
|
||||
}, (data) => {
|
||||
const available = data.status == 404 ? -1 : 0;
|
||||
let message = '';
|
||||
|
||||
throw new CoreAjaxError(Translate.instant('core.serverconnection'), available);
|
||||
switch (data.status) {
|
||||
case -2: // Certificate error.
|
||||
message = this.getCertificateErrorMessage(data.error);
|
||||
break;
|
||||
case 404: // AJAX endpoint not found.
|
||||
message = Translate.instant('core.ajaxendpointnotfound', {
|
||||
$a: CoreSite.MINIMUM_MOODLE_VERSION,
|
||||
whoisadmin: Translate.instant('core.whoissiteadmin'),
|
||||
});
|
||||
break;
|
||||
default:
|
||||
message = Translate.instant('core.serverconnection');
|
||||
}
|
||||
|
||||
throw new CoreAjaxError(message, 1, data.status);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -675,12 +690,32 @@ export class CoreWSProvider {
|
|||
}
|
||||
|
||||
return retryPromise;
|
||||
} else if (error.status === -2) {
|
||||
throw new CoreError(this.getCertificateErrorMessage(error.error));
|
||||
}
|
||||
|
||||
throw new CoreError(Translate.instant('core.serverconnection'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get error message about certificate error.
|
||||
*
|
||||
* @param error Exact error message.
|
||||
* @return Certificate error message.
|
||||
*/
|
||||
protected getCertificateErrorMessage(error?: string): string {
|
||||
const message = Translate.instant('core.certificaterror', {
|
||||
whoisadmin: Translate.instant('core.whoissiteadmin'),
|
||||
});
|
||||
|
||||
if (error) {
|
||||
return `${message}\n<p>${error}</p>`;
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retry all requests in the queue.
|
||||
* This function uses recursion in order to add a delay between requests to reduce stress.
|
||||
|
|
Loading…
Reference in New Issue