MOBILE-3780 core: Don't store offline if 4xx or 5xx http error

main
Dani Palou 2022-02-23 16:14:28 +01:00
parent be0ce93a0f
commit 9ded4b7c5b
11 changed files with 87 additions and 14 deletions

View File

@ -36,6 +36,7 @@ import {
import { AddonModAssignHelper } from '../../services/assign-helper'; import { AddonModAssignHelper } from '../../services/assign-helper';
import { AddonModAssignOffline } from '../../services/assign-offline'; import { AddonModAssignOffline } from '../../services/assign-offline';
import { AddonModAssignSync } from '../../services/assign-sync'; import { AddonModAssignSync } from '../../services/assign-sync';
import { CoreUtils } from '@services/utils/utils';
/** /**
* Page that allows adding or editing an assigment submission. * Page that allows adding or editing an assigment submission.
@ -255,7 +256,7 @@ export class AddonModAssignEditPage implements OnInit, OnDestroy, CanLeave {
this.hasOffline, this.hasOffline,
); );
} catch (error) { } catch (error) {
if (this.allowOffline && !this.saveOffline) { if (this.allowOffline && !this.saveOffline && !CoreUtils.isWebServiceError(error)) {
// Cannot submit in online, prepare for offline usage. // Cannot submit in online, prepare for offline usage.
this.saveOffline = true; this.saveOffline = true;

View File

@ -266,9 +266,10 @@ export class AddonModDataEditPage implements OnInit {
this.offline, this.offline,
); );
} catch (error) { } catch (error) {
if (this.offline) { if (this.offline || CoreUtils.isWebServiceError(error)) {
throw error; throw error;
} }
// Cannot submit in online, prepare for offline usage. // Cannot submit in online, prepare for offline usage.
this.offline = true; this.offline = true;

View File

@ -364,7 +364,7 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy, OnChanges
); );
} catch (error) { } catch (error) {
// Cannot upload them in online, save them in offline. // Cannot upload them in online, save them in offline.
if (!this.forum.id || isEditOnline) { if (!this.forum.id || isEditOnline || CoreUtils.isWebServiceError(error)) {
// Cannot store them in offline. Reject. // Cannot store them in offline. Reject.
throw error; throw error;
} }

View File

@ -106,6 +106,10 @@ export class AddonModForumHelperProvider {
try { try {
await Promise.all(promises); await Promise.all(promises);
} catch (error) { } catch (error) {
if (CoreUtils.isWebServiceError(error)) {
throw error;
}
// Cannot upload them in online, save them in offline. // Cannot upload them in online, save them in offline.
saveOffline = true; saveOffline = true;

View File

@ -25,6 +25,7 @@ import { CoreNavigator } from '@services/navigator';
import { CoreSites } from '@services/sites'; import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom'; import { CoreDomUtils } from '@services/utils/dom';
import { CoreTextUtils } from '@services/utils/text'; import { CoreTextUtils } from '@services/utils/text';
import { CoreUtils } from '@services/utils/utils';
import { Translate } from '@singletons'; import { Translate } from '@singletons';
import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreForms } from '@singletons/form'; import { CoreForms } from '@singletons/form';
@ -392,7 +393,11 @@ export class AddonModGlossaryEditPage implements OnInit, OnDestroy, CanLeave {
saveOffline: false, saveOffline: false,
attachmentsResult, attachmentsResult,
}; };
} catch { } catch (error) {
if (CoreUtils.isWebServiceError(error)) {
throw error;
}
// Cannot upload them in online, save them in offline. // Cannot upload them in online, save them in offline.
const attachmentsResult = await AddonModGlossaryHelper.storeFiles( const attachmentsResult = await AddonModGlossaryHelper.storeFiles(
this.glossary.id, this.glossary.id,

View File

@ -304,7 +304,11 @@ export class AddonModWorkshopAssessmentStrategyComponent implements OnInit, OnDe
files, files,
saveOffline, saveOffline,
); );
} catch { } catch (error) {
if (CoreUtils.isWebServiceError(error)) {
throw error;
}
// Cannot upload them in online, save them in offline. // Cannot upload them in online, save them in offline.
saveOffline = true; saveOffline = true;
allowOffline = true; allowOffline = true;

View File

@ -25,6 +25,7 @@ import { CoreSites } from '@services/sites';
import { CoreSync } from '@services/sync'; import { CoreSync } from '@services/sync';
import { CoreDomUtils } from '@services/utils/dom'; import { CoreDomUtils } from '@services/utils/dom';
import { CoreTextUtils } from '@services/utils/text'; import { CoreTextUtils } from '@services/utils/text';
import { CoreUtils } from '@services/utils/utils';
import { Translate } from '@singletons'; import { Translate } from '@singletons';
import { CoreEvents } from '@singletons/events'; import { CoreEvents } from '@singletons/events';
import { CoreForms } from '@singletons/form'; import { CoreForms } from '@singletons/form';
@ -349,7 +350,11 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy, Ca
inputData.attachmentfiles, inputData.attachmentfiles,
false, false,
); );
} catch { } catch (error) {
if (CoreUtils.isWebServiceError(error)) {
throw error;
}
// Cannot upload them in online, save them in offline. // Cannot upload them in online, save them in offline.
saveOffline = true; saveOffline = true;
allowOffline = true; allowOffline = true;

View File

@ -24,6 +24,7 @@ import { CoreCaptureError } from './captureerror';
import { CoreNetworkError } from './network-error'; import { CoreNetworkError } from './network-error';
import { CoreSiteError } from './siteerror'; import { CoreSiteError } from './siteerror';
import { CoreErrorWithTitle } from './errorwithtitle'; import { CoreErrorWithTitle } from './errorwithtitle';
import { CoreHttpError } from './httperror';
export const CORE_ERRORS_CLASSES: Type<unknown>[] = [ export const CORE_ERRORS_CLASSES: Type<unknown>[] = [
CoreAjaxError, CoreAjaxError,
@ -36,4 +37,5 @@ export const CORE_ERRORS_CLASSES: Type<unknown>[] = [
CoreSiteError, CoreSiteError,
CoreWSError, CoreWSError,
CoreErrorWithTitle, CoreErrorWithTitle,
CoreHttpError,
]; ];

View File

@ -0,0 +1,30 @@
// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { CoreError } from '@classes/errors/error';
/**
* HTTP error.
*/
export class CoreHttpError extends CoreError {
status: number; // HTTP status. 0 if cannot connect or similar errors.
constructor(message: string, status?: number) {
super(message);
this.status = status ?? 0;
}
}

View File

@ -858,12 +858,17 @@ export class CoreUtilsProvider {
*/ */
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
isWebServiceError(error: any): boolean { isWebServiceError(error: any): boolean {
return error && (error.warningcode !== undefined || (error.errorcode !== undefined && return error && (
error.errorcode != 'userdeleted' && error.errorcode != 'upgraderunning' && error.warningcode !== undefined ||
(
error.errorcode !== undefined && error.errorcode != 'userdeleted' && error.errorcode != 'upgraderunning' &&
error.errorcode != 'forcepasswordchangenotice' && error.errorcode != 'usernotfullysetup' && error.errorcode != 'forcepasswordchangenotice' && error.errorcode != 'usernotfullysetup' &&
error.errorcode != 'sitepolicynotagreed' && error.errorcode != 'sitemaintenance' && error.errorcode != 'sitepolicynotagreed' && error.errorcode != 'sitemaintenance' &&
error.errorcode != 'wsaccessusersuspended' && error.errorcode != 'wsaccessuserdeleted' && error.errorcode != 'wsaccessusersuspended' && error.errorcode != 'wsaccessuserdeleted' &&
!this.isExpiredTokenError(error))); !this.isExpiredTokenError(error)
) ||
error.status && error.status >= 400 // CoreHttpError, assume status 400 and above are like WebService errors.
);
} }
/** /**

View File

@ -25,7 +25,7 @@ import { CoreNativeToAngularHttpResponse } from '@classes/native-to-angular-http
import { CoreApp } from '@services/app'; import { CoreApp } from '@services/app';
import { CoreFile, CoreFileFormat } from '@services/file'; import { CoreFile, CoreFileFormat } from '@services/file';
import { CoreMimetypeUtils } from '@services/utils/mimetype'; import { CoreMimetypeUtils } from '@services/utils/mimetype';
import { CoreTextUtils } from '@services/utils/text'; import { CoreTextErrorObject, CoreTextUtils } from '@services/utils/text';
import { CoreUtils, PromiseDefer } from '@services/utils/utils'; import { CoreUtils, PromiseDefer } from '@services/utils/utils';
import { CoreConstants } from '@/core/constants'; import { CoreConstants } from '@/core/constants';
import { CoreError } from '@classes/errors/error'; import { CoreError } from '@classes/errors/error';
@ -38,6 +38,7 @@ import { CoreAjaxError } from '@classes/errors/ajaxerror';
import { CoreAjaxWSError } from '@classes/errors/ajaxwserror'; import { CoreAjaxWSError } from '@classes/errors/ajaxwserror';
import { CoreNetworkError } from '@classes/errors/network-error'; import { CoreNetworkError } from '@classes/errors/network-error';
import { CoreSite } from '@classes/site'; import { CoreSite } from '@classes/site';
import { CoreHttpError } from '@classes/errors/httperror';
/** /**
* This service allows performing WS calls and download/upload files. * This service allows performing WS calls and download/upload files.
@ -693,6 +694,8 @@ export class CoreWSProvider {
return retryPromise; return retryPromise;
} else if (error.status === -2) { } else if (error.status === -2) {
throw new CoreError(this.getCertificateErrorMessage(error.error)); throw new CoreError(this.getCertificateErrorMessage(error.error));
} else if (error.status > 0) {
throw this.createHttpError(error, error.status);
} }
throw new CoreError(Translate.instant('core.serverconnection')); throw new CoreError(Translate.instant('core.serverconnection'));
@ -892,10 +895,7 @@ export class CoreWSProvider {
} catch (error) { } catch (error) {
this.logger.error('Error while uploading file', filePath, error); this.logger.error('Error while uploading file', filePath, error);
throw new CoreError(CoreTextUtils.buildSeveralParagraphsMessage([ throw this.createHttpError(error, error.http_status ?? 0);
Translate.instant('core.cannotconnecttrouble'),
CoreTextUtils.getHTMLBodyContent(CoreTextUtils.getErrorMessageFromError(error) || ''),
]));
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
@ -937,6 +937,22 @@ export class CoreWSProvider {
return data[0]; return data[0];
} }
/**
* Create a CoreHttpError based on a certain error.
*
* @param error Original error.
* @param status Status code (if any).
* @return CoreHttpError.
*/
protected createHttpError(error: CoreTextErrorObject, status: number): CoreHttpError {
const message = CoreTextUtils.buildSeveralParagraphsMessage([
Translate.instant('core.cannotconnecttrouble'),
CoreTextUtils.getHTMLBodyContent(CoreTextUtils.getErrorMessageFromError(error) || ''),
]);
return new CoreHttpError(message, status);
}
/** /**
* Perform an HTTP request requesting for a text response. * Perform an HTTP request requesting for a text response.
* *