forked from EVOgeek/Vmeda.Online
		
	MOBILE-4059 core: Encapsulate support config
This commit is contained in:
		
							parent
							
								
									b933c92f69
								
							
						
					
					
						commit
						c4952133f1
					
				| @ -13,8 +13,7 @@ | |||||||
| // limitations under the License.
 | // limitations under the License.
 | ||||||
| 
 | 
 | ||||||
| import { CoreError } from '@classes/errors/error'; | import { CoreError } from '@classes/errors/error'; | ||||||
| import { CoreSitePublicConfigResponse } from '@classes/site'; | import { CoreUserSupportConfig } from '@features/user/classes/support/support-config'; | ||||||
| import { CoreUserSupport } from '@features/user/services/support'; |  | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Error returned when performing operations regarding a site. |  * Error returned when performing operations regarding a site. | ||||||
| @ -23,42 +22,14 @@ export class CoreSiteError extends CoreError { | |||||||
| 
 | 
 | ||||||
|     errorcode?: string; |     errorcode?: string; | ||||||
|     errorDetails?: string; |     errorDetails?: string; | ||||||
|     contactSupport?: boolean; |     supportConfig?: CoreUserSupportConfig; | ||||||
|     siteConfig?: CoreSitePublicConfigResponse; |  | ||||||
| 
 | 
 | ||||||
|     constructor(options: CoreSiteErrorOptions) { |     constructor(options: CoreSiteErrorOptions) { | ||||||
|         super(getErrorMessage(options)); |         super(getErrorMessage(options)); | ||||||
| 
 | 
 | ||||||
|         this.errorcode = options.errorcode; |         this.errorcode = options.errorcode; | ||||||
|         this.errorDetails = options.errorDetails; |         this.errorDetails = options.errorDetails; | ||||||
|         this.contactSupport = options.contactSupport; |         this.supportConfig = options.supportConfig; | ||||||
|         this.siteConfig = options.siteConfig; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Get a url to contact site support. |  | ||||||
|      * |  | ||||||
|      * @returns Support page url. |  | ||||||
|      */ |  | ||||||
|     getSupportPageUrl(): string { |  | ||||||
|         if (!this.siteConfig) { |  | ||||||
|             throw new CoreError('Can\'t get support page url'); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         return CoreUserSupport.getSupportPageUrl(this.siteConfig); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Check whether the handling of this error allows users to contact support or not. |  | ||||||
|      * |  | ||||||
|      * @returns Whether to contact support or not. |  | ||||||
|      */ |  | ||||||
|     canContactSupport(): boolean { |  | ||||||
|         if (!this.contactSupport || !this.siteConfig) { |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         return CoreUserSupport.canContactSupport(this.siteConfig); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| @ -70,10 +41,7 @@ export class CoreSiteError extends CoreError { | |||||||
|  * @returns Error message. |  * @returns Error message. | ||||||
|  */ |  */ | ||||||
| function getErrorMessage(options: CoreSiteErrorOptions): string { | function getErrorMessage(options: CoreSiteErrorOptions): string { | ||||||
|     if ( |     if ('supportConfig' in options && !options.supportConfig?.canContactSupport()) { | ||||||
|         options.contactSupport && |  | ||||||
|         (!options.siteConfig || !CoreUserSupport.canContactSupport(options.siteConfig)) |  | ||||||
|     ) { |  | ||||||
|         return options.fallbackMessage ?? options.message; |         return options.fallbackMessage ?? options.message; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -85,6 +53,8 @@ export type CoreSiteErrorOptions = { | |||||||
|     fallbackMessage?: string; // Message to use when contacting support is not possible but warranted.
 |     fallbackMessage?: string; // Message to use when contacting support is not possible but warranted.
 | ||||||
|     errorcode?: string; // Technical error code useful for technical assistance.
 |     errorcode?: string; // Technical error code useful for technical assistance.
 | ||||||
|     errorDetails?: string; // Technical error details useful for technical assistance.
 |     errorDetails?: string; // Technical error details useful for technical assistance.
 | ||||||
|     contactSupport?: boolean; // Whether this error warrants contacting site support or not.
 | 
 | ||||||
|     siteConfig?: CoreSitePublicConfigResponse; |     // Configuration to use to contact site support. If this attribute is present, it means
 | ||||||
|  |     // that the error warrants contacting support.
 | ||||||
|  |     supportConfig?: CoreUserSupportConfig; | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -60,8 +60,8 @@ import { | |||||||
| import { Observable, ObservableInput, ObservedValueOf, OperatorFunction, Subject } from 'rxjs'; | import { Observable, ObservableInput, ObservedValueOf, OperatorFunction, Subject } from 'rxjs'; | ||||||
| import { finalize, map, mergeMap } from 'rxjs/operators'; | import { finalize, map, mergeMap } from 'rxjs/operators'; | ||||||
| import { firstValueFrom } from '../utils/rxjs'; | import { firstValueFrom } from '../utils/rxjs'; | ||||||
| import { CoreUserSupport } from '@features/user/services/support'; |  | ||||||
| import { CoreSiteError } from '@classes/errors/siteerror'; | import { CoreSiteError } from '@classes/errors/siteerror'; | ||||||
|  | import { CoreUserAuthenticatedSupportConfig } from '@features/user/classes/support/authenticated-support-config'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * QR Code type enumeration. |  * QR Code type enumeration. | ||||||
| @ -264,19 +264,6 @@ export class CoreSite { | |||||||
|         return this.db; |         return this.db; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |  | ||||||
|      * Get url to contact site support. |  | ||||||
|      * |  | ||||||
|      * @returns Site support page url. |  | ||||||
|      */ |  | ||||||
|     getSupportPageUrl(): string | null { |  | ||||||
|         if (!this.config || !this.canContactSupport()) { |  | ||||||
|             return null; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         return CoreUserSupport.getSupportPageUrl(this.config, this.siteUrl); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |     /** | ||||||
|      * Get site user's ID. |      * Get site user's ID. | ||||||
|      * |      * | ||||||
| @ -436,19 +423,6 @@ export class CoreSite { | |||||||
|         return !!(info && (info.usercanmanageownfiles === undefined || info.usercanmanageownfiles)); |         return !!(info && (info.usercanmanageownfiles === undefined || info.usercanmanageownfiles)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |  | ||||||
|      * Check whether this site has a support url available. |  | ||||||
|      * |  | ||||||
|      * @returns Whether this site has a support url. |  | ||||||
|      */ |  | ||||||
|     canContactSupport(): boolean { |  | ||||||
|         if (this.isFeatureDisabled('NoDelegate_CoreUserSupport')) { |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         return !!this.config && CoreUserSupport.canContactSupport(this.config); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |     /** | ||||||
|      * Can the user download files? |      * Can the user download files? | ||||||
|      * |      * | ||||||
| @ -1158,13 +1132,8 @@ export class CoreSite { | |||||||
|             ); |             ); | ||||||
| 
 | 
 | ||||||
|             if (!data || !data.responses) { |             if (!data || !data.responses) { | ||||||
|                 const siteConfig = await CoreUtils.ignoreErrors( |  | ||||||
|                     this.getPublicConfig({ readingStrategy: CoreSitesReadingStrategy.ONLY_CACHE }), |  | ||||||
|                 ); |  | ||||||
| 
 |  | ||||||
|                 throw new CoreSiteError({ |                 throw new CoreSiteError({ | ||||||
|                     siteConfig, |                     supportConfig: new CoreUserAuthenticatedSupportConfig(this), | ||||||
|                     contactSupport: true, |  | ||||||
|                     message: Translate.instant('core.cannotconnecttrouble'), |                     message: Translate.instant('core.cannotconnecttrouble'), | ||||||
|                     fallbackMessage: Translate.instant('core.cannotconnecttroublewithoutsupport'), |                     fallbackMessage: Translate.instant('core.cannotconnecttroublewithoutsupport'), | ||||||
|                     errorcode: 'invalidresponse', |                     errorcode: 'invalidresponse', | ||||||
|  | |||||||
| @ -13,7 +13,7 @@ | |||||||
| // limitations under the License.
 | // limitations under the License.
 | ||||||
| 
 | 
 | ||||||
| import { Component, Input, OnInit } from '@angular/core'; | import { Component, Input, OnInit } from '@angular/core'; | ||||||
| import { CoreSiteConfig } from '@classes/site'; | import { CoreUserSupportConfig } from '@features/user/classes/support/support-config'; | ||||||
| import { CoreUserSupport } from '@features/user/services/support'; | import { CoreUserSupport } from '@features/user/services/support'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
| @ -23,8 +23,7 @@ import { CoreUserSupport } from '@features/user/services/support'; | |||||||
| }) | }) | ||||||
| export class CoreLoginExceededAttemptsComponent implements OnInit { | export class CoreLoginExceededAttemptsComponent implements OnInit { | ||||||
| 
 | 
 | ||||||
|     @Input() siteUrl!: string; |     @Input() supportConfig!: CoreUserSupportConfig; | ||||||
|     @Input() siteConfig!: CoreSiteConfig; |  | ||||||
|     @Input() supportSubject?: string; |     @Input() supportSubject?: string; | ||||||
| 
 | 
 | ||||||
|     canContactSupport = false; |     canContactSupport = false; | ||||||
| @ -33,19 +32,15 @@ export class CoreLoginExceededAttemptsComponent implements OnInit { | |||||||
|      * @inheritdoc |      * @inheritdoc | ||||||
|      */ |      */ | ||||||
|     ngOnInit(): void { |     ngOnInit(): void { | ||||||
|         this.canContactSupport = CoreUserSupport.canContactSupport(this.siteConfig); |         this.canContactSupport = this.supportConfig.canContactSupport(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Contact site support. |      * Contact site support. | ||||||
|      */ |      */ | ||||||
|     async contactSupport(): Promise<void> { |     async contactSupport(): Promise<void> { | ||||||
|         if (!this.siteConfig) { |  | ||||||
|             throw new Error('Can\'t contact support without config'); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         await CoreUserSupport.contact({ |         await CoreUserSupport.contact({ | ||||||
|             supportPageUrl: CoreUserSupport.getSupportPageUrl(this.siteConfig, this.siteUrl), |             supportConfig: this.supportConfig, | ||||||
|             subject: this.supportSubject, |             subject: this.supportSubject, | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -23,6 +23,7 @@ import { CoreEventObserver, CoreEvents } from '@singletons/events'; | |||||||
| import { CoreUtils } from '@services/utils/utils'; | import { CoreUtils } from '@services/utils/utils'; | ||||||
| import { CoreUserSupport } from '@features/user/services/support'; | import { CoreUserSupport } from '@features/user/services/support'; | ||||||
| import { AlertButton } from '@ionic/angular'; | import { AlertButton } from '@ionic/angular'; | ||||||
|  | import { CoreUserAuthenticatedSupportConfig } from '@features/user/classes/support/authenticated-support-config'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Page that shows instructions to change the password. |  * Page that shows instructions to change the password. | ||||||
| @ -48,14 +49,14 @@ export class CoreLoginChangePasswordPage implements OnDestroy { | |||||||
|      * Show a help modal. |      * Show a help modal. | ||||||
|      */ |      */ | ||||||
|     showHelp(): void { |     showHelp(): void { | ||||||
|         const site = CoreSites.getRequiredCurrentSite(); |         const supportConfig = CoreUserAuthenticatedSupportConfig.forCurrentSite(); | ||||||
|         const buttons: (AlertButton | string)[] = []; |         const buttons: (AlertButton | string)[] = []; | ||||||
| 
 | 
 | ||||||
|         if (site.canContactSupport()) { |         if (supportConfig.canContactSupport()) { | ||||||
|             buttons.push({ |             buttons.push({ | ||||||
|                 text: Translate.instant('core.contactsupport'), |                 text: Translate.instant('core.contactsupport'), | ||||||
|                 handler: () => CoreUserSupport.contact({ |                 handler: () => CoreUserSupport.contact({ | ||||||
|                     supportPageUrl: site.getSupportPageUrl(), |                     supportConfig, | ||||||
|                     subject: Translate.instant('core.login.changepasswordsupportsubject'), |                     subject: Translate.instant('core.login.changepasswordsupportsubject'), | ||||||
|                 }), |                 }), | ||||||
|             }); |             }); | ||||||
|  | |||||||
| @ -33,7 +33,7 @@ | |||||||
|             <p class="core-siteurl">{{siteUrl}}</p> |             <p class="core-siteurl">{{siteUrl}}</p> | ||||||
|         </div> |         </div> | ||||||
| 
 | 
 | ||||||
|         <core-login-exceeded-attempts *ngIf="loginAttempts >= 3" [siteConfig]="siteConfig" [siteUrl]="siteUrl" |         <core-login-exceeded-attempts *ngIf="supportConfig && loginAttempts >= 3" [supportConfig]="supportConfig" | ||||||
|             [supportSubject]="'core.login.exceededloginattemptssupportsubject' | translate"> |             [supportSubject]="'core.login.exceededloginattemptssupportsubject' | translate"> | ||||||
|             {{ 'core.login.exceededloginattempts' | translate }} |             {{ 'core.login.exceededloginattempts' | translate }} | ||||||
|         </core-login-exceeded-attempts> |         </core-login-exceeded-attempts> | ||||||
|  | |||||||
| @ -29,6 +29,8 @@ import { CoreEvents } from '@singletons/events'; | |||||||
| import { CoreNavigator } from '@services/navigator'; | import { CoreNavigator } from '@services/navigator'; | ||||||
| import { CoreForms } from '@singletons/form'; | import { CoreForms } from '@singletons/form'; | ||||||
| import { CoreUserSupport } from '@features/user/services/support'; | import { CoreUserSupport } from '@features/user/services/support'; | ||||||
|  | import { CoreUserSupportConfig } from '@features/user/classes/support/support-config'; | ||||||
|  | import { CoreUserGuestSupportConfig } from '@features/user/classes/support/guest-support-config'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Page to enter the user credentials. |  * Page to enter the user credentials. | ||||||
| @ -56,9 +58,10 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy { | |||||||
|     showForgottenPassword = true; |     showForgottenPassword = true; | ||||||
|     showScanQR = false; |     showScanQR = false; | ||||||
|     loginAttempts = 0; |     loginAttempts = 0; | ||||||
|     siteConfig?: CoreSitePublicConfigResponse; |     supportConfig?: CoreUserSupportConfig; | ||||||
|     canContactSupport?: boolean; |     canContactSupport?: boolean; | ||||||
| 
 | 
 | ||||||
|  |     protected siteConfig?: CoreSitePublicConfigResponse; | ||||||
|     protected eventThrown = false; |     protected eventThrown = false; | ||||||
|     protected viewLeft = false; |     protected viewLeft = false; | ||||||
|     protected siteId?: string; |     protected siteId?: string; | ||||||
| @ -75,12 +78,12 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy { | |||||||
|     async ngOnInit(): Promise<void> { |     async ngOnInit(): Promise<void> { | ||||||
|         try { |         try { | ||||||
|             this.siteUrl = CoreNavigator.getRequiredRouteParam<string>('siteUrl'); |             this.siteUrl = CoreNavigator.getRequiredRouteParam<string>('siteUrl'); | ||||||
| 
 |  | ||||||
|             this.siteName = CoreNavigator.getRouteParam('siteName'); |             this.siteName = CoreNavigator.getRouteParam('siteName'); | ||||||
|             this.logoUrl = !CoreConstants.CONFIG.forceLoginLogo && CoreNavigator.getRouteParam('logoUrl') || undefined; |             this.logoUrl = !CoreConstants.CONFIG.forceLoginLogo && CoreNavigator.getRouteParam('logoUrl') || undefined; | ||||||
|             this.siteConfig = CoreNavigator.getRouteParam('siteConfig'); |             this.siteConfig = CoreNavigator.getRouteParam<CoreSitePublicConfigResponse>('siteConfig'); | ||||||
|             this.urlToOpen = CoreNavigator.getRouteParam('urlToOpen'); |             this.urlToOpen = CoreNavigator.getRouteParam('urlToOpen'); | ||||||
|             this.canContactSupport = this.siteConfig && CoreUserSupport.canContactSupport(this.siteConfig); |             this.supportConfig = this.siteConfig && new CoreUserGuestSupportConfig(this.siteConfig); | ||||||
|  |             this.canContactSupport = this.supportConfig?.canContactSupport(); | ||||||
|         } catch (error) { |         } catch (error) { | ||||||
|             CoreDomUtils.showErrorModal(error); |             CoreDomUtils.showErrorModal(error); | ||||||
| 
 | 
 | ||||||
| @ -132,9 +135,11 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy { | |||||||
|      * Contact site support. |      * Contact site support. | ||||||
|      */ |      */ | ||||||
|     async contactSupport(): Promise<void> { |     async contactSupport(): Promise<void> { | ||||||
|         const supportPageUrl = this.siteConfig && CoreUserSupport.getSupportPageUrl(this.siteConfig); |         if (!this.supportConfig) { | ||||||
|  |             throw new Error('can\'t contact support'); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         await CoreUserSupport.contact({ supportPageUrl }); |         await CoreUserSupport.contact({ supportConfig: this.supportConfig }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | |||||||
| @ -11,7 +11,7 @@ | |||||||
| </ion-header> | </ion-header> | ||||||
| <ion-content> | <ion-content> | ||||||
|     <div class="list-item-limited-width"> |     <div class="list-item-limited-width"> | ||||||
|         <core-login-exceeded-attempts *ngIf="wasPasswordResetRequestedRecently" [siteConfig]="siteConfig" [siteUrl]="siteUrl" |         <core-login-exceeded-attempts *ngIf="supportConfig && wasPasswordResetRequestedRecently" [supportConfig]="supportConfig" | ||||||
|             [supportSubject]="'core.login.exceededpasswordresetattemptssupportsubject' | translate"> |             [supportSubject]="'core.login.exceededpasswordresetattemptssupportsubject' | translate"> | ||||||
|             {{ 'core.login.exceededpasswordresetattempts' | translate }} |             {{ 'core.login.exceededpasswordresetattempts' | translate }} | ||||||
|         </core-login-exceeded-attempts> |         </core-login-exceeded-attempts> | ||||||
|  | |||||||
| @ -23,6 +23,8 @@ import { CoreNavigator } from '@services/navigator'; | |||||||
| import { CoreForms } from '@singletons/form'; | import { CoreForms } from '@singletons/form'; | ||||||
| import { CorePlatform } from '@services/platform'; | import { CorePlatform } from '@services/platform'; | ||||||
| import { CoreSitePublicConfigResponse } from '@classes/site'; | import { CoreSitePublicConfigResponse } from '@classes/site'; | ||||||
|  | import { CoreUserSupportConfig } from '@features/user/classes/support/support-config'; | ||||||
|  | import { CoreUserGuestSupportConfig } from '@features/user/classes/support/guest-support-config'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Page to recover a forgotten password. |  * Page to recover a forgotten password. | ||||||
| @ -37,8 +39,8 @@ export class CoreLoginForgottenPasswordPage implements OnInit { | |||||||
| 
 | 
 | ||||||
|     myForm!: FormGroup; |     myForm!: FormGroup; | ||||||
|     siteUrl!: string; |     siteUrl!: string; | ||||||
|     siteConfig?: CoreSitePublicConfigResponse; |  | ||||||
|     autoFocus!: boolean; |     autoFocus!: boolean; | ||||||
|  |     supportConfig?: CoreUserSupportConfig; | ||||||
|     wasPasswordResetRequestedRecently = false; |     wasPasswordResetRequestedRecently = false; | ||||||
| 
 | 
 | ||||||
|     constructor(protected formBuilder: FormBuilder) {} |     constructor(protected formBuilder: FormBuilder) {} | ||||||
| @ -55,14 +57,16 @@ export class CoreLoginForgottenPasswordPage implements OnInit { | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         const siteConfig = CoreNavigator.getRouteParam<CoreSitePublicConfigResponse>('siteConfig'); | ||||||
|  | 
 | ||||||
|         this.siteUrl = siteUrl; |         this.siteUrl = siteUrl; | ||||||
|         this.siteConfig = CoreNavigator.getRouteParam<CoreSitePublicConfigResponse>('siteConfig'); |  | ||||||
|         this.autoFocus = CorePlatform.is('tablet'); |         this.autoFocus = CorePlatform.is('tablet'); | ||||||
|         this.myForm = this.formBuilder.group({ |         this.myForm = this.formBuilder.group({ | ||||||
|             field: ['username', Validators.required], |             field: ['username', Validators.required], | ||||||
|             value: [CoreNavigator.getRouteParam<string>('username') || '', Validators.required], |             value: [CoreNavigator.getRouteParam<string>('username') || '', Validators.required], | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|  |         this.supportConfig = siteConfig && new CoreUserGuestSupportConfig(siteConfig); | ||||||
|         this.wasPasswordResetRequestedRecently = await CoreLoginHelper.wasPasswordResetRequestedRecently(siteUrl); |         this.wasPasswordResetRequestedRecently = await CoreLoginHelper.wasPasswordResetRequestedRecently(siteUrl); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -43,7 +43,7 @@ | |||||||
|                     </ion-item> |                     </ion-item> | ||||||
|                 </ion-card> |                 </ion-card> | ||||||
| 
 | 
 | ||||||
|                 <core-login-exceeded-attempts *ngIf="reconnectAttempts >= 3" [siteConfig]="siteConfig" [siteUrl]="siteUrl" |                 <core-login-exceeded-attempts *ngIf="supportConfig && reconnectAttempts >= 3" [supportConfig]="supportConfig" | ||||||
|                     [supportSubject]="'core.login.exceededloginattemptssupportsubject' | translate"> |                     [supportSubject]="'core.login.exceededloginattemptssupportsubject' | translate"> | ||||||
|                     {{ 'core.login.exceededloginattempts' | translate }} |                     {{ 'core.login.exceededloginattempts' | translate }} | ||||||
|                 </core-login-exceeded-attempts> |                 </core-login-exceeded-attempts> | ||||||
|  | |||||||
| @ -27,6 +27,8 @@ import { CoreError } from '@classes/errors/error'; | |||||||
| import { CoreNavigator, CoreRedirectPayload } from '@services/navigator'; | import { CoreNavigator, CoreRedirectPayload } from '@services/navigator'; | ||||||
| import { CoreForms } from '@singletons/form'; | import { CoreForms } from '@singletons/form'; | ||||||
| import { CoreUserSupport } from '@features/user/services/support'; | import { CoreUserSupport } from '@features/user/services/support'; | ||||||
|  | import { CoreUserSupportConfig } from '@features/user/classes/support/support-config'; | ||||||
|  | import { CoreUserAuthenticatedSupportConfig } from '@features/user/classes/support/authenticated-support-config'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Page to enter the user password to reconnect to a site. |  * Page to enter the user password to reconnect to a site. | ||||||
| @ -57,9 +59,10 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy { | |||||||
|     showScanQR = false; |     showScanQR = false; | ||||||
|     showLoading = true; |     showLoading = true; | ||||||
|     reconnectAttempts = 0; |     reconnectAttempts = 0; | ||||||
|     siteConfig?: CoreSitePublicConfigResponse; |     supportConfig?: CoreUserSupportConfig; | ||||||
|     canContactSupport?: boolean; |     canContactSupport?: boolean; | ||||||
| 
 | 
 | ||||||
|  |     protected siteConfig?: CoreSitePublicConfigResponse; | ||||||
|     protected viewLeft = false; |     protected viewLeft = false; | ||||||
|     protected eventThrown = false; |     protected eventThrown = false; | ||||||
|     protected redirectData?: CoreRedirectPayload; |     protected redirectData?: CoreRedirectPayload; | ||||||
| @ -104,7 +107,8 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy { | |||||||
|             this.userAvatar = site.infos.userpictureurl; |             this.userAvatar = site.infos.userpictureurl; | ||||||
|             this.siteUrl = site.infos.siteurl; |             this.siteUrl = site.infos.siteurl; | ||||||
|             this.siteName = site.getSiteName(); |             this.siteName = site.getSiteName(); | ||||||
|             this.canContactSupport = site.canContactSupport(); |             this.supportConfig = new CoreUserAuthenticatedSupportConfig(site); | ||||||
|  |             this.canContactSupport = this.supportConfig.canContactSupport(); | ||||||
| 
 | 
 | ||||||
|             // If login was OAuth we should only reach this page if the OAuth method ID has changed.
 |             // If login was OAuth we should only reach this page if the OAuth method ID has changed.
 | ||||||
|             this.isOAuth = site.isOAuth(); |             this.isOAuth = site.isOAuth(); | ||||||
| @ -141,9 +145,7 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy { | |||||||
|      * Contact site support. |      * Contact site support. | ||||||
|      */ |      */ | ||||||
|     async contactSupport(): Promise<void> { |     async contactSupport(): Promise<void> { | ||||||
|         const supportPageUrl = this.siteConfig && CoreUserSupport.getSupportPageUrl(this.siteConfig); |         await CoreUserSupport.contact({ supportConfig: this.supportConfig }); | ||||||
| 
 |  | ||||||
|         await CoreUserSupport.contact({ supportPageUrl }); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | |||||||
| @ -43,6 +43,8 @@ import { AlertButton } from '@ionic/core'; | |||||||
| import { CoreSiteError } from '@classes/errors/siteerror'; | import { CoreSiteError } from '@classes/errors/siteerror'; | ||||||
| import { CoreUserSupport } from '@features/user/services/support'; | import { CoreUserSupport } from '@features/user/services/support'; | ||||||
| import { CoreErrorInfoComponent } from '@components/error-info/error-info'; | import { CoreErrorInfoComponent } from '@components/error-info/error-info'; | ||||||
|  | import { CoreUserSupportConfig } from '@features/user/classes/support/support-config'; | ||||||
|  | import { CoreUserGuestSupportConfig } from '@features/user/classes/support/guest-support-config'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Site (url) chooser when adding a new site. |  * Site (url) chooser when adding a new site. | ||||||
| @ -386,15 +388,15 @@ export class CoreLoginSitePage implements OnInit { | |||||||
|     protected async showLoginIssue(url: string | null, error: CoreError): Promise<void> { |     protected async showLoginIssue(url: string | null, error: CoreError): Promise<void> { | ||||||
|         let errorMessage = CoreDomUtils.getErrorMessage(error); |         let errorMessage = CoreDomUtils.getErrorMessage(error); | ||||||
|         let siteExists = false; |         let siteExists = false; | ||||||
|         let supportPageUrl: string | null = null; |         let supportConfig: CoreUserSupportConfig | undefined = undefined; | ||||||
|         let errorDetails: string | undefined; |         let errorDetails: string | undefined; | ||||||
|         let errorCode: string | undefined; |         let errorCode: string | undefined; | ||||||
| 
 | 
 | ||||||
|         if (error instanceof CoreSiteError) { |         if (error instanceof CoreSiteError) { | ||||||
|             siteExists = !!error.siteConfig; |             supportConfig = error.supportConfig; | ||||||
|             supportPageUrl = error.canContactSupport() ? error.getSupportPageUrl() : null; |  | ||||||
|             errorDetails = error.errorDetails; |             errorDetails = error.errorDetails; | ||||||
|             errorCode = error.errorcode; |             errorCode = error.errorcode; | ||||||
|  |             siteExists = supportConfig instanceof CoreUserGuestSupportConfig; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if ( |         if ( | ||||||
| @ -420,12 +422,13 @@ export class CoreLoginSitePage implements OnInit { | |||||||
|             errorMessage += '<div class="core-error-info-container"></div>'; |             errorMessage += '<div class="core-error-info-container"></div>'; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         const alertSupportConfig = supportConfig; | ||||||
|         const buttons: AlertButton[] = [ |         const buttons: AlertButton[] = [ | ||||||
|             supportPageUrl |             alertSupportConfig | ||||||
|                 ? { |                 ? { | ||||||
|                     text: Translate.instant('core.contactsupport'), |                     text: Translate.instant('core.contactsupport'), | ||||||
|                     handler: () => CoreUserSupport.contact({ |                     handler: () => CoreUserSupport.contact({ | ||||||
|                         supportPageUrl, |                         supportConfig: alertSupportConfig, | ||||||
|                         subject: Translate.instant('core.cannotconnect', { $a: CoreSite.MINIMUM_MOODLE_VERSION }), |                         subject: Translate.instant('core.cannotconnect', { $a: CoreSite.MINIMUM_MOODLE_VERSION }), | ||||||
|                         message: `Error: ${errorCode}\n\n${errorDetails}`, |                         message: `Error: ${errorCode}\n\n${errorDetails}`, | ||||||
|                     }), |                     }), | ||||||
|  | |||||||
| @ -18,6 +18,7 @@ import { CoreSite, CoreSiteInfo } from '@classes/site'; | |||||||
| import { CoreFilter } from '@features/filter/services/filter'; | import { CoreFilter } from '@features/filter/services/filter'; | ||||||
| import { CoreLoginSitesComponent } from '@features/login/components/sites/sites'; | import { CoreLoginSitesComponent } from '@features/login/components/sites/sites'; | ||||||
| import { CoreLoginHelper } from '@features/login/services/login-helper'; | import { CoreLoginHelper } from '@features/login/services/login-helper'; | ||||||
|  | import { CoreUserAuthenticatedSupportConfig } from '@features/user/classes/support/authenticated-support-config'; | ||||||
| import { CoreUserSupport } from '@features/user/services/support'; | import { CoreUserSupport } from '@features/user/services/support'; | ||||||
| import { CoreUser, CoreUserProfile } from '@features/user/services/user'; | import { CoreUser, CoreUserProfile } from '@features/user/services/user'; | ||||||
| import { | import { | ||||||
| @ -67,7 +68,7 @@ export class CoreMainMenuUserMenuComponent implements OnInit, OnDestroy { | |||||||
|         this.siteName = currentSite.getSiteName(); |         this.siteName = currentSite.getSiteName(); | ||||||
|         this.siteUrl = currentSite.getURL(); |         this.siteUrl = currentSite.getURL(); | ||||||
|         this.displaySwitchAccount = !currentSite.isFeatureDisabled('NoDelegate_SwitchAccount'); |         this.displaySwitchAccount = !currentSite.isFeatureDisabled('NoDelegate_SwitchAccount'); | ||||||
|         this.displayContactSupport = currentSite.canContactSupport(); |         this.displayContactSupport = new CoreUserAuthenticatedSupportConfig(currentSite).canContactSupport(); | ||||||
|         this.removeAccountOnLogout = !!CoreConstants.CONFIG.removeaccountonlogout; |         this.removeAccountOnLogout = !!CoreConstants.CONFIG.removeaccountonlogout; | ||||||
| 
 | 
 | ||||||
|         this.loadSiteLogo(currentSite); |         this.loadSiteLogo(currentSite); | ||||||
|  | |||||||
| @ -0,0 +1,57 @@ | |||||||
|  | // (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 { CoreSite } from '@classes/site'; | ||||||
|  | import { CoreSites } from '@services/sites'; | ||||||
|  | import { CoreUserSupportConfig } from './support-config'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Support config for an authenticated user. | ||||||
|  |  */ | ||||||
|  | export class CoreUserAuthenticatedSupportConfig extends CoreUserSupportConfig { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Get config for the current site. | ||||||
|  |      * | ||||||
|  |      * @returns Support config. | ||||||
|  |      */ | ||||||
|  |     static forCurrentSite(): CoreUserAuthenticatedSupportConfig { | ||||||
|  |         return new CoreUserAuthenticatedSupportConfig(CoreSites.getRequiredCurrentSite()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private site: CoreSite; | ||||||
|  | 
 | ||||||
|  |     constructor(site: CoreSite) { | ||||||
|  |         super(); | ||||||
|  | 
 | ||||||
|  |         this.site = site; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @inheritdoc | ||||||
|  |      */ | ||||||
|  |     canContactSupport(): boolean { | ||||||
|  |         return this.site.isVersionGreaterEqualThan('4.0') | ||||||
|  |             && !this.site.isFeatureDisabled('NoDelegate_CoreUserSupport'); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @inheritdoc | ||||||
|  |      */ | ||||||
|  |     protected buildSupportPageUrl(): string { | ||||||
|  |         return this.site.config?.supportpage?.trim() | ||||||
|  |             || `${this.site.config?.httpswwwroot ?? this.site.config?.wwwroot ?? this.site.siteUrl}/user/contactsitesupport.php`; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,65 @@ | |||||||
|  | // (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 { CoreSitePublicConfigResponse } from '@classes/site'; | ||||||
|  | import { CoreUserNullSupportConfig } from '@features/user/classes/support/null-support-config'; | ||||||
|  | import { CoreSites } from '@services/sites'; | ||||||
|  | import { CoreUtils } from '@services/utils/utils'; | ||||||
|  | import { CoreUserSupportConfig } from './support-config'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Support config for a guest user. | ||||||
|  |  */ | ||||||
|  | export class CoreUserGuestSupportConfig extends CoreUserSupportConfig { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Get support config for a site with given url. | ||||||
|  |      * | ||||||
|  |      * @param siteUrl Site url. | ||||||
|  |      * @returns Support config. | ||||||
|  |      */ | ||||||
|  |     static async forSite(siteUrl: string): Promise<CoreUserSupportConfig> { | ||||||
|  |         const siteConfig = await CoreUtils.ignoreErrors(CoreSites.getPublicSiteConfigByUrl(siteUrl)); | ||||||
|  | 
 | ||||||
|  |         if (!siteConfig) { | ||||||
|  |             return new CoreUserNullSupportConfig(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return new CoreUserGuestSupportConfig(siteConfig); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private config: CoreSitePublicConfigResponse; | ||||||
|  | 
 | ||||||
|  |     constructor(config: CoreSitePublicConfigResponse) { | ||||||
|  |         super(); | ||||||
|  | 
 | ||||||
|  |         this.config = config; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @inheritdoc | ||||||
|  |      */ | ||||||
|  |     canContactSupport(): boolean { | ||||||
|  |         return 'supportpage' in this.config; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @inheritdoc | ||||||
|  |      */ | ||||||
|  |     protected buildSupportPageUrl(): string { | ||||||
|  |         return this.config.supportpage?.trim() | ||||||
|  |             || `${this.config.httpswwwroot || this.config.wwwroot}/user/contactsitesupport.php`; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,39 @@ | |||||||
|  | // (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 { CoreUserSupportConfig } from './support-config'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Null representation for a support config object. | ||||||
|  |  * | ||||||
|  |  * This class can be used in place of a functional support config when it's hasn't been possible | ||||||
|  |  * to obtain any site configuration to extract information about support. | ||||||
|  |  */ | ||||||
|  | export class CoreUserNullSupportConfig extends CoreUserSupportConfig { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @inheritdoc | ||||||
|  |      */ | ||||||
|  |     canContactSupport(): boolean { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @inheritdoc | ||||||
|  |      */ | ||||||
|  |     protected buildSupportPageUrl(): string { | ||||||
|  |         throw new Error('Can\'t build a support page url from a null config'); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										47
									
								
								src/core/features/user/classes/support/support-config.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/core/features/user/classes/support/support-config.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | |||||||
|  | // (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.
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Encapsulates the support affordances a user has access to. | ||||||
|  |  */ | ||||||
|  | export abstract class CoreUserSupportConfig { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Check whether the user can contact support or not. | ||||||
|  |      * | ||||||
|  |      * @return Whether the user can contact support. | ||||||
|  |      */ | ||||||
|  |     public abstract canContactSupport(): boolean; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Get url to use for contacting support. | ||||||
|  |      * | ||||||
|  |      * @returns Support page url. | ||||||
|  |      */ | ||||||
|  |     getSupportPageUrl(): string { | ||||||
|  |         if (!this.canContactSupport()) { | ||||||
|  |             throw new Error('Can\'t get support page url'); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return this.buildSupportPageUrl(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Build page url string with the internal information. | ||||||
|  |      * | ||||||
|  |      * @return Support page url. | ||||||
|  |      */ | ||||||
|  |     protected abstract buildSupportPageUrl(): string; | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -23,6 +23,7 @@ import { CoreEventObserver, CoreEvents } from '@singletons/events'; | |||||||
| import { CoreUtils } from '@services/utils/utils'; | import { CoreUtils } from '@services/utils/utils'; | ||||||
| import { AlertButton } from '@ionic/angular'; | import { AlertButton } from '@ionic/angular'; | ||||||
| import { CoreUserSupport } from '@features/user/services/support'; | import { CoreUserSupport } from '@features/user/services/support'; | ||||||
|  | import { CoreUserAuthenticatedSupportConfig } from '@features/user/classes/support/authenticated-support-config'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Page that shows instructions to complete the profile. |  * Page that shows instructions to complete the profile. | ||||||
| @ -47,14 +48,14 @@ export class CoreUserCompleteProfilePage implements OnDestroy { | |||||||
|      * Show a help modal. |      * Show a help modal. | ||||||
|      */ |      */ | ||||||
|     showHelp(): void { |     showHelp(): void { | ||||||
|         const site = CoreSites.getRequiredCurrentSite(); |         const supportConfig = CoreUserAuthenticatedSupportConfig.forCurrentSite(); | ||||||
|         const buttons: (AlertButton | string)[] = []; |         const buttons: (AlertButton | string)[] = []; | ||||||
| 
 | 
 | ||||||
|         if (site.canContactSupport()) { |         if (supportConfig.canContactSupport()) { | ||||||
|             buttons.push({ |             buttons.push({ | ||||||
|                 text: Translate.instant('core.contactsupport'), |                 text: Translate.instant('core.contactsupport'), | ||||||
|                 handler: () => CoreUserSupport.contact({ |                 handler: () => CoreUserSupport.contact({ | ||||||
|                     supportPageUrl: site.getSupportPageUrl(), |                     supportConfig, | ||||||
|                     subject: Translate.instant('core.login.completeprofilesupportsubject'), |                     subject: Translate.instant('core.login.completeprofilesupportsubject'), | ||||||
|                 }), |                 }), | ||||||
|             }); |             }); | ||||||
|  | |||||||
| @ -13,8 +13,8 @@ | |||||||
| // limitations under the License.
 | // limitations under the License.
 | ||||||
| 
 | 
 | ||||||
| import { Injectable } from '@angular/core'; | import { Injectable } from '@angular/core'; | ||||||
| import { CoreError } from '@classes/errors/error'; | import { CoreUserSupportConfig } from '@features/user/classes/support/support-config'; | ||||||
| import { CoreSiteConfig, CoreSitePublicConfigResponse } from '@classes/site'; | import { CoreUserAuthenticatedSupportConfig } from '@features/user/classes/support/authenticated-support-config'; | ||||||
| import { InAppBrowserObject } from '@ionic-native/in-app-browser'; | import { InAppBrowserObject } from '@ionic-native/in-app-browser'; | ||||||
| import { CorePlatform } from '@services/platform'; | import { CorePlatform } from '@services/platform'; | ||||||
| import { CoreSites } from '@services/sites'; | import { CoreSites } from '@services/sites'; | ||||||
| @ -35,12 +35,8 @@ export class CoreUserSupportService { | |||||||
|      * @param options Options to configure the interaction with support. |      * @param options Options to configure the interaction with support. | ||||||
|      */ |      */ | ||||||
|     async contact(options: CoreUserSupportContactOptions = {}): Promise<void> { |     async contact(options: CoreUserSupportContactOptions = {}): Promise<void> { | ||||||
|         const supportPageUrl = options.supportPageUrl ?? CoreSites.getRequiredCurrentSite().getSupportPageUrl(); |         const supportConfig = options.supportConfig ?? CoreUserAuthenticatedSupportConfig.forCurrentSite(); | ||||||
| 
 |         const supportPageUrl = supportConfig.getSupportPageUrl(); | ||||||
|         if (!supportPageUrl) { |  | ||||||
|             throw new CoreError('Could not get support url'); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         const autoLoginUrl = await CoreSites.getCurrentSite()?.getAutoLoginUrl(supportPageUrl, false); |         const autoLoginUrl = await CoreSites.getCurrentSite()?.getAutoLoginUrl(supportPageUrl, false); | ||||||
|         const browser = CoreUtils.openInApp(autoLoginUrl ?? supportPageUrl); |         const browser = CoreUtils.openInApp(autoLoginUrl ?? supportPageUrl); | ||||||
| 
 | 
 | ||||||
| @ -51,29 +47,6 @@ export class CoreUserSupportService { | |||||||
|         await CoreEvents.waitUntil(CoreEvents.IAB_EXIT); |         await CoreEvents.waitUntil(CoreEvents.IAB_EXIT); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |  | ||||||
|      * Get support page url from site config. |  | ||||||
|      * |  | ||||||
|      * @param config Site config. |  | ||||||
|      * @returns Support page url. |  | ||||||
|      */ |  | ||||||
|     getSupportPageUrl(config: CoreSitePublicConfigResponse): string; |  | ||||||
|     getSupportPageUrl(config: CoreSiteConfig, siteUrl: string): string; |  | ||||||
|     getSupportPageUrl(config: CoreSiteConfig | CoreSitePublicConfigResponse, siteUrl?: string): string { |  | ||||||
|         return config.supportpage?.trim() |  | ||||||
|             || `${config.httpswwwroot ?? config.wwwroot ?? siteUrl}/user/contactsitesupport.php`; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Check whether a site config allows contacting support. |  | ||||||
|      * |  | ||||||
|      * @param config Site config. |  | ||||||
|      * @returns Whether site support can be contacted. |  | ||||||
|      */ |  | ||||||
|     canContactSupport(config: CoreSiteConfig | CoreSitePublicConfigResponse): boolean { |  | ||||||
|         return 'supportpage' in config; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |     /** | ||||||
|      * Inject error details into contact support form. |      * Inject error details into contact support form. | ||||||
|      * |      * | ||||||
| @ -106,7 +79,7 @@ export const CoreUserSupport = makeSingleton(CoreUserSupportService); | |||||||
|  * Options to configure interaction with support. |  * Options to configure interaction with support. | ||||||
|  */ |  */ | ||||||
| export interface CoreUserSupportContactOptions { | export interface CoreUserSupportContactOptions { | ||||||
|     supportPageUrl?: string | null; |     supportConfig?: CoreUserSupportConfig | null; | ||||||
|     subject?: string | null; |     subject?: string | null; | ||||||
|     message?: string | null; |     message?: string | null; | ||||||
| } | } | ||||||
|  | |||||||
| @ -14,7 +14,10 @@ | |||||||
| 
 | 
 | ||||||
| import { CoreSiteError } from '@classes/errors/siteerror'; | import { CoreSiteError } from '@classes/errors/siteerror'; | ||||||
| import { CoreLoginHelper } from '@features/login/services/login-helper'; | import { CoreLoginHelper } from '@features/login/services/login-helper'; | ||||||
|  | import { CoreUserAuthenticatedSupportConfig } from '@features/user/classes/support/authenticated-support-config'; | ||||||
|  | import { CoreUserNullSupportConfig } from '@features/user/classes/support/null-support-config'; | ||||||
| import { CoreApp } from '@services/app'; | import { CoreApp } from '@services/app'; | ||||||
|  | import { CoreSites } from '@services/sites'; | ||||||
| import { CoreCustomURLSchemes } from '@services/urlschemes'; | import { CoreCustomURLSchemes } from '@services/urlschemes'; | ||||||
| import { CoreDomUtils } from '@services/utils/dom'; | import { CoreDomUtils } from '@services/utils/dom'; | ||||||
| import { CoreUrlUtils } from '@services/utils/url'; | import { CoreUrlUtils } from '@services/utils/url'; | ||||||
| @ -47,7 +50,9 @@ export default function(): void { | |||||||
|             // It's an SSO token for another app. Close the IAB and show an error.
 |             // It's an SSO token for another app. Close the IAB and show an error.
 | ||||||
|             CoreUtils.closeInAppBrowser(); |             CoreUtils.closeInAppBrowser(); | ||||||
|             CoreDomUtils.showErrorModal(new CoreSiteError({ |             CoreDomUtils.showErrorModal(new CoreSiteError({ | ||||||
|                 contactSupport: true, |                 supportConfig: CoreSites.getCurrentSite() | ||||||
|  |                     ? CoreUserAuthenticatedSupportConfig.forCurrentSite() | ||||||
|  |                     : new CoreUserNullSupportConfig(), | ||||||
|                 message: Translate.instant('core.cannotconnecttrouble'), |                 message: Translate.instant('core.cannotconnecttrouble'), | ||||||
|                 fallbackMessage: Translate.instant('core.cannotconnecttroublewithoutsupport'), |                 fallbackMessage: Translate.instant('core.cannotconnecttroublewithoutsupport'), | ||||||
|                 errorcode: 'invalidurlscheme', |                 errorcode: 'invalidurlscheme', | ||||||
|  | |||||||
| @ -61,6 +61,7 @@ import { CoreDatabaseCachingStrategy, CoreDatabaseTableProxy } from '@classes/da | |||||||
| import { asyncInstance, AsyncInstance } from '../utils/async-instance'; | import { asyncInstance, AsyncInstance } from '../utils/async-instance'; | ||||||
| import { CoreConfig } from './config'; | import { CoreConfig } from './config'; | ||||||
| import { CoreNetwork } from '@services/network'; | import { CoreNetwork } from '@services/network'; | ||||||
|  | import { CoreUserGuestSupportConfig } from '@features/user/classes/support/guest-support-config'; | ||||||
| 
 | 
 | ||||||
| export const CORE_SITE_SCHEMAS = new InjectionToken<CoreSiteSchema[]>('CORE_SITE_SCHEMAS'); | export const CORE_SITE_SCHEMAS = new InjectionToken<CoreSiteSchema[]>('CORE_SITE_SCHEMAS'); | ||||||
| export const CORE_SITE_CURRENT_SITE_ID_CONFIG = 'current_site_id'; | export const CORE_SITE_CURRENT_SITE_ID_CONFIG = 'current_site_id'; | ||||||
| @ -297,16 +298,16 @@ export class CoreSitesProvider { | |||||||
|         // Check that the user can authenticate.
 |         // Check that the user can authenticate.
 | ||||||
|         if (!config.enablewebservices) { |         if (!config.enablewebservices) { | ||||||
|             throw this.createCannotConnectLoginError({ |             throw this.createCannotConnectLoginError({ | ||||||
|  |                 supportConfig: new CoreUserGuestSupportConfig(config), | ||||||
|                 errorcode: 'webservicesnotenabled', |                 errorcode: 'webservicesnotenabled', | ||||||
|                 errorDetails: Translate.instant('core.login.webservicesnotenabled'), |                 errorDetails: Translate.instant('core.login.webservicesnotenabled'), | ||||||
|                 siteConfig: config, |  | ||||||
|                 critical: true, |                 critical: true, | ||||||
|             }); |             }); | ||||||
|         } else if (!config.enablemobilewebservice) { |         } else if (!config.enablemobilewebservice) { | ||||||
|             throw this.createCannotConnectLoginError({ |             throw this.createCannotConnectLoginError({ | ||||||
|  |                 supportConfig: new CoreUserGuestSupportConfig(config), | ||||||
|                 errorcode: 'mobileservicesnotenabled', |                 errorcode: 'mobileservicesnotenabled', | ||||||
|                 errorDetails: Translate.instant('core.login.mobileservicesnotenabled'), |                 errorDetails: Translate.instant('core.login.mobileservicesnotenabled'), | ||||||
|                 siteConfig: config, |  | ||||||
|                 critical: true, |                 critical: true, | ||||||
|             }); |             }); | ||||||
|         } else if (config.maintenanceenabled) { |         } else if (config.maintenanceenabled) { | ||||||
| @ -332,24 +333,12 @@ export class CoreSitesProvider { | |||||||
|      * @param options Error options. |      * @param options Error options. | ||||||
|      * @return Cannot connect error. |      * @return Cannot connect error. | ||||||
|      */ |      */ | ||||||
|     protected createCannotConnectLoginError(options?: Partial<CoreLoginErrorOptions>): CoreLoginError; |     protected createCannotConnectLoginError(options?: Partial<CoreLoginErrorOptions>): CoreLoginError { | ||||||
|     protected createCannotConnectLoginError(siteUrl: string, options?: Partial<CoreLoginErrorOptions>): Promise<CoreLoginError>; |         return new CoreLoginError({ | ||||||
|     protected createCannotConnectLoginError( |  | ||||||
|         siteUrlOrOptions: string | Partial<CoreLoginErrorOptions> = {}, |  | ||||||
|         options: Partial<CoreLoginErrorOptions> = {}, |  | ||||||
|     ): CoreLoginError | Promise<CoreLoginError> { |  | ||||||
|         const createError = (options: Partial<CoreLoginErrorOptions>) =>  new CoreLoginError({ |  | ||||||
|             ...options, |             ...options, | ||||||
|             message: Translate.instant('core.cannotconnecttrouble'), |             message: Translate.instant('core.cannotconnecttrouble'), | ||||||
|             fallbackMessage: Translate.instant('core.cannotconnecttroublewithoutsupport'), |             fallbackMessage: Translate.instant('core.cannotconnecttroublewithoutsupport'), | ||||||
|             contactSupport: true, |  | ||||||
|         }); |         }); | ||||||
| 
 |  | ||||||
|         return typeof siteUrlOrOptions === 'object' |  | ||||||
|             ? createError(siteUrlOrOptions) |  | ||||||
|             : CoreUtils |  | ||||||
|                 .ignoreErrors(this.getPublicSiteConfigByUrl(siteUrlOrOptions)) |  | ||||||
|                 .then(siteConfig => createError({ ...options, siteConfig })); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -376,8 +365,7 @@ export class CoreSitesProvider { | |||||||
|             critical: true, |             critical: true, | ||||||
|             message: error.message, |             message: error.message, | ||||||
|             errorcode: error.errorcode, |             errorcode: error.errorcode, | ||||||
|             contactSupport: error.contactSupport, |             supportConfig: error.supportConfig, | ||||||
|             siteConfig: error.siteConfig, |  | ||||||
|             errorDetails: error.errorDetails, |             errorDetails: error.errorDetails, | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
| @ -425,7 +413,8 @@ export class CoreSitesProvider { | |||||||
|             data = await Http.post(siteUrl + '/login/token.php', { appsitecheck: 1 }).pipe(timeout(CoreWS.getRequestTimeout())) |             data = await Http.post(siteUrl + '/login/token.php', { appsitecheck: 1 }).pipe(timeout(CoreWS.getRequestTimeout())) | ||||||
|                 .toPromise(); |                 .toPromise(); | ||||||
|         } catch (error) { |         } catch (error) { | ||||||
|             throw await this.createCannotConnectLoginError(siteUrl, { |             throw this.createCannotConnectLoginError({ | ||||||
|  |                 supportConfig: await CoreUserGuestSupportConfig.forSite(siteUrl), | ||||||
|                 errorcode: 'sitecheckfailed', |                 errorcode: 'sitecheckfailed', | ||||||
|                 errorDetails: CoreDomUtils.getErrorMessage(error) ?? undefined, |                 errorDetails: CoreDomUtils.getErrorMessage(error) ?? undefined, | ||||||
|             }); |             }); | ||||||
| @ -433,14 +422,16 @@ export class CoreSitesProvider { | |||||||
| 
 | 
 | ||||||
|         if (data === null) { |         if (data === null) { | ||||||
|             // Cannot connect.
 |             // Cannot connect.
 | ||||||
|             throw await this.createCannotConnectLoginError(siteUrl, { |             throw this.createCannotConnectLoginError({ | ||||||
|  |                 supportConfig: await CoreUserGuestSupportConfig.forSite(siteUrl), | ||||||
|                 errorcode: 'appsitecheckfailed', |                 errorcode: 'appsitecheckfailed', | ||||||
|                 errorDetails: 'A request to /login/token.php with appsitecheck=1 returned an empty response', |                 errorDetails: 'A request to /login/token.php with appsitecheck=1 returned an empty response', | ||||||
|             }); |             }); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (data.errorcode && (data.errorcode == 'enablewsdescription' || data.errorcode == 'requirecorrectaccess')) { |         if (data.errorcode && (data.errorcode == 'enablewsdescription' || data.errorcode == 'requirecorrectaccess')) { | ||||||
|             throw await this.createCannotConnectLoginError(siteUrl, { |             throw this.createCannotConnectLoginError({ | ||||||
|  |                 supportConfig: await CoreUserGuestSupportConfig.forSite(siteUrl), | ||||||
|                 critical: data.errorcode == 'enablewsdescription', |                 critical: data.errorcode == 'enablewsdescription', | ||||||
|                 errorcode: data.errorcode, |                 errorcode: data.errorcode, | ||||||
|                 errorDetails: data.error, |                 errorDetails: data.error, | ||||||
| @ -448,7 +439,8 @@ export class CoreSitesProvider { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (data.error && data.error == 'Web services must be enabled in Advanced features.') { |         if (data.error && data.error == 'Web services must be enabled in Advanced features.') { | ||||||
|             throw await this.createCannotConnectLoginError(siteUrl, { |             throw this.createCannotConnectLoginError({ | ||||||
|  |                 supportConfig: await CoreUserGuestSupportConfig.forSite(siteUrl), | ||||||
|                 critical: true, |                 critical: true, | ||||||
|                 errorcode: 'enablewsdescription', |                 errorcode: 'enablewsdescription', | ||||||
|                 errorDetails: data.error, |                 errorDetails: data.error, | ||||||
| @ -511,14 +503,16 @@ export class CoreSitesProvider { | |||||||
|                         const redirect = await CoreUtils.checkRedirect(loginUrl); |                         const redirect = await CoreUtils.checkRedirect(loginUrl); | ||||||
| 
 | 
 | ||||||
|                         if (redirect) { |                         if (redirect) { | ||||||
|                             throw await this.createCannotConnectLoginError(siteUrl, { |                             throw this.createCannotConnectLoginError({ | ||||||
|  |                                 supportConfig: await CoreUserGuestSupportConfig.forSite(siteUrl), | ||||||
|                                 errorcode: 'sitehasredirect', |                                 errorcode: 'sitehasredirect', | ||||||
|                                 errorDetails: Translate.instant('core.login.sitehasredirect'), |                                 errorDetails: Translate.instant('core.login.sitehasredirect'), | ||||||
|                             }); |                             }); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|                     throw await this.createCannotConnectLoginError(siteUrl, { |                     throw this.createCannotConnectLoginError({ | ||||||
|  |                         supportConfig: await CoreUserGuestSupportConfig.forSite(siteUrl), | ||||||
|                         errorcode: data.errorcode, |                         errorcode: data.errorcode, | ||||||
|                         errorDetails: data.error, |                         errorDetails: data.error, | ||||||
|                     }); |                     }); | ||||||
|  | |||||||
| @ -1366,11 +1366,12 @@ export class CoreDomUtilsProvider { | |||||||
|                 alertOptions.message += '<div class="core-error-info-container"></div>'; |                 alertOptions.message += '<div class="core-error-info-container"></div>'; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (error.canContactSupport()) { |             const supportConfig = error.supportConfig; | ||||||
|  |             if (supportConfig?.canContactSupport()) { | ||||||
|                 alertOptions.buttons.push({ |                 alertOptions.buttons.push({ | ||||||
|                     text: Translate.instant('core.contactsupport'), |                     text: Translate.instant('core.contactsupport'), | ||||||
|                     handler: () => CoreUserSupport.contact({ |                     handler: () => CoreUserSupport.contact({ | ||||||
|                         supportPageUrl: error.getSupportPageUrl(), |                         supportConfig, | ||||||
|                         subject: alertOptions.header, |                         subject: alertOptions.header, | ||||||
|                         message: `${error.errorcode}\n\n${error.errorDetails}`, |                         message: `${error.errorcode}\n\n${error.errorDetails}`, | ||||||
|                     }), |                     }), | ||||||
|  | |||||||
| @ -39,9 +39,8 @@ import { CoreSite } from '@classes/site'; | |||||||
| import { CoreHttpError } from '@classes/errors/httperror'; | import { CoreHttpError } from '@classes/errors/httperror'; | ||||||
| import { CorePromisedValue } from '@classes/promised-value'; | import { CorePromisedValue } from '@classes/promised-value'; | ||||||
| import { CorePlatform } from '@services/platform'; | import { CorePlatform } from '@services/platform'; | ||||||
| import { CoreUtils } from '@services/utils/utils'; |  | ||||||
| import { CoreSites } from '@services/sites'; |  | ||||||
| import { CoreSiteError, CoreSiteErrorOptions } from '@classes/errors/siteerror'; | import { CoreSiteError, CoreSiteErrorOptions } from '@classes/errors/siteerror'; | ||||||
|  | import { CoreUserGuestSupportConfig } from '@features/user/classes/support/guest-support-config'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * This service allows performing WS calls and download/upload files. |  * This service allows performing WS calls and download/upload files. | ||||||
| @ -470,11 +469,8 @@ export class CoreWSProvider { | |||||||
| 
 | 
 | ||||||
|             // Check if error. Ajax layer should always return an object (if error) or an array (if success).
 |             // Check if error. Ajax layer should always return an object (if error) or an array (if success).
 | ||||||
|             if (!data || typeof data != 'object') { |             if (!data || typeof data != 'object') { | ||||||
|                 const siteConfig = await CoreUtils.ignoreErrors(CoreSites.getPublicSiteConfigByUrl(preSets.siteUrl)); |  | ||||||
| 
 |  | ||||||
|                 throw new CoreAjaxError({ |                 throw new CoreAjaxError({ | ||||||
|                     siteConfig, |                     supportConfig: await CoreUserGuestSupportConfig.forSite(preSets.siteUrl), | ||||||
|                     contactSupport: true, |  | ||||||
|                     message: Translate.instant('core.cannotconnecttrouble'), |                     message: Translate.instant('core.cannotconnecttrouble'), | ||||||
|                     fallbackMessage: Translate.instant('core.cannotconnecttroublewithoutsupport'), |                     fallbackMessage: Translate.instant('core.cannotconnecttroublewithoutsupport'), | ||||||
|                     errorcode: 'invalidresponse', |                     errorcode: 'invalidresponse', | ||||||
| @ -496,8 +492,7 @@ export class CoreWSProvider { | |||||||
|             return data.data; |             return data.data; | ||||||
|         }, async (data: HttpErrorResponse) => { |         }, async (data: HttpErrorResponse) => { | ||||||
|             const options: CoreSiteErrorOptions = { |             const options: CoreSiteErrorOptions = { | ||||||
|                 contactSupport: true, |                 supportConfig: await CoreUserGuestSupportConfig.forSite(preSets.siteUrl), | ||||||
|                 siteConfig: await CoreUtils.ignoreErrors(CoreSites.getPublicSiteConfigByUrl(preSets.siteUrl)), |  | ||||||
|                 message: Translate.instant('core.cannotconnecttrouble'), |                 message: Translate.instant('core.cannotconnecttrouble'), | ||||||
|                 fallbackMessage: Translate.instant('core.cannotconnecttroublewithoutsupport'), |                 fallbackMessage: Translate.instant('core.cannotconnecttroublewithoutsupport'), | ||||||
|             }; |             }; | ||||||
| @ -1132,14 +1127,11 @@ export class CoreWSProvider { | |||||||
|         siteUrl: string, |         siteUrl: string, | ||||||
|         options?: Partial<CoreSiteErrorOptions>, |         options?: Partial<CoreSiteErrorOptions>, | ||||||
|     ): Promise<CoreSiteError> { |     ): Promise<CoreSiteError> { | ||||||
|         const siteConfig = await CoreUtils.ignoreErrors(CoreSites.getPublicSiteConfigByUrl(siteUrl)); |  | ||||||
| 
 |  | ||||||
|         return new CoreSiteError({ |         return new CoreSiteError({ | ||||||
|             ...options, |             ...options, | ||||||
|             siteConfig, |             supportConfig: await CoreUserGuestSupportConfig.forSite(siteUrl), | ||||||
|             message: Translate.instant('core.cannotconnecttrouble'), |             message: Translate.instant('core.cannotconnecttrouble'), | ||||||
|             fallbackMessage: Translate.instant('core.cannotconnecttroublewithoutsupport'), |             fallbackMessage: Translate.instant('core.cannotconnecttroublewithoutsupport'), | ||||||
|             contactSupport: true, |  | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user