MOBILE-3780 core: Don't store offline if 4xx or 5xx http error
This commit is contained in:
		
							parent
							
								
									be0ce93a0f
								
							
						
					
					
						commit
						9ded4b7c5b
					
				| @ -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; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -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; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -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; | ||||||
|                     } |                     } | ||||||
|  | |||||||
| @ -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; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -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, | ||||||
|  | |||||||
| @ -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; | ||||||
|  | |||||||
| @ -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; | ||||||
|  | |||||||
| @ -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, | ||||||
| ]; | ]; | ||||||
|  | |||||||
							
								
								
									
										30
									
								
								src/core/classes/errors/httperror.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/core/classes/errors/httperror.ts
									
									
									
									
									
										Normal 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; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -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.
 | ||||||
|  |         ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | |||||||
| @ -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. | ||||||
|      * |      * | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user