From a3898d751512df268967685535173a101566734a Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Mon, 13 Nov 2023 08:19:23 +0100 Subject: [PATCH] MOBILE-4469 login: Support isFeatureDisabled in all site classes --- src/core/classes/sites/candidate-site.ts | 43 +++++++--- src/core/classes/sites/site.ts | 45 +++++----- .../classes/sites/unauthenticated-site.ts | 68 ++++++++++++++- .../components/login-methods/login-methods.ts | 9 +- .../login/pages/credentials/credentials.html | 2 +- .../login/pages/credentials/credentials.ts | 16 ++-- .../pages/email-signup/email-signup.html | 2 +- .../login/pages/email-signup/email-signup.ts | 9 +- .../forgotten-password/forgotten-password.ts | 13 +-- .../login/pages/reconnect/reconnect.ts | 4 +- src/core/features/login/pages/site/site.html | 2 +- src/core/features/login/pages/site/site.ts | 15 +--- .../features/login/services/login-helper.ts | 85 ++++++++++++++----- .../services/pushnotifications.ts | 2 +- .../support/authenticated-support-config.ts | 13 +-- .../classes/support/guest-support-config.ts | 16 ++-- src/core/services/sites-factory.ts | 29 +++---- src/core/services/sites.ts | 22 +++-- src/storybook/stubs/classes/site.ts | 2 +- 19 files changed, 263 insertions(+), 134 deletions(-) diff --git a/src/core/classes/sites/candidate-site.ts b/src/core/classes/sites/candidate-site.ts index d8da5ba01..c7f3eee3d 100644 --- a/src/core/classes/sites/candidate-site.ts +++ b/src/core/classes/sites/candidate-site.ts @@ -108,14 +108,18 @@ export class CoreCandidateSite extends CoreUnauthenticatedSite { * * @param siteUrl Site URL. * @param token Site's WS token. - * @param privateToken Private token. + * @param otherData Other data. */ - constructor(siteUrl: string, token: string, privateToken?: string) { - super(siteUrl); + constructor( + siteUrl: string, + token: string, + otherData: CoreCandidateSiteOptionalData = {}, + ) { + super(siteUrl, otherData.publicConfig); - this.token = token; - this.privateToken = privateToken; this.logger = CoreLogger.getInstance('CoreCandidateSite'); + this.token = token; + this.privateToken = otherData.privateToken; } /** @@ -700,7 +704,7 @@ export class CoreCandidateSite extends CoreUnauthenticatedSite { this.saveToCache(method, data, error, preSets); throw new CoreWSError(error); - } else if (preSets.emergencyCache !== undefined && !preSets.emergencyCache) { + } else if (preSets.emergencyCache === false) { this.logger.debug(`WS call '${method}' failed. Emergency cache is forbidden, rejecting.`); throw new CoreWSError(error); @@ -1273,6 +1277,11 @@ export class CoreCandidateSite extends CoreUnauthenticatedSite { * @inheritdoc */ async getPublicConfig(options: { readingStrategy?: CoreSitesReadingStrategy } = {}): Promise { + const ignoreCache = CoreSitesReadingStrategy.ONLY_NETWORK || CoreSitesReadingStrategy.PREFER_NETWORK; + if (!ignoreCache && this.publicConfig) { + return this.publicConfig; + }; + const method = 'tool_mobile_get_public_config'; const cacheId = this.getCacheId(method, {}); const cachePreSets: CoreSiteWSPreSets = { @@ -1321,12 +1330,15 @@ export class CoreCandidateSite extends CoreUnauthenticatedSite { try { const config = await this.requestPublicConfig(); - if (cachePreSets.saveToCache) { - this.saveToCache(method, {}, config, cachePreSets); - } + this.saveToCache(method, {}, config, cachePreSets); + this.setPublicConfig(config); return config; } catch (error) { + if (cachePreSets.emergencyCache === false) { + throw error; + } + cachePreSets.omitExpires = true; cachePreSets.getFromCache = true; @@ -1340,7 +1352,10 @@ export class CoreCandidateSite extends CoreUnauthenticatedSite { } }).then((response) => { // The app doesn't store exceptions for this call, it's safe to assume type CoreSitePublicConfigResponse. - subject.next( response); + response = response; + + this.setPublicConfig(response); + subject.next(response); subject.complete(); return; @@ -1581,6 +1596,14 @@ export function chainRequests>( ); } +/** + * Optional data to create a candidate site. + */ +export type CoreCandidateSiteOptionalData = { + privateToken?: string; + publicConfig?: CoreSitePublicConfigResponse; +}; + /** * PreSets accepted by the WS call. */ diff --git a/src/core/classes/sites/site.ts b/src/core/classes/sites/site.ts index 90f9ff452..1e2c74d08 100644 --- a/src/core/classes/sites/site.ts +++ b/src/core/classes/sites/site.ts @@ -51,7 +51,7 @@ import { map } from 'rxjs/operators'; import { firstValueFrom } from '../../utils/rxjs'; import { CoreFilepool } from '@services/filepool'; import { CoreSiteInfo } from './unauthenticated-site'; -import { CoreCandidateSite, CoreSiteWSPreSets, WSObservable } from './candidate-site'; +import { CoreCandidateSite, CoreCandidateSiteOptionalData, CoreSiteWSPreSets, WSObservable } from './candidate-site'; /** * Class that represents a site (combination of site + user). @@ -78,25 +78,19 @@ export class CoreSite extends CoreCandidateSite { * @param id Site ID. * @param siteUrl Site URL. * @param token Site's WS token. - * @param infos Site info. - * @param privateToken Private token. - * @param config Site public config. - * @param loggedOut Whether user is logged out. + * @param otherData Other data. */ constructor( id: string, siteUrl: string, token: string, - infos?: CoreSiteInfo, - privateToken?: string, - config?: CoreSiteConfig, - loggedOut?: boolean, + otherData: CoreSiteOptionalData = {}, ) { - super(siteUrl, token, privateToken); + super(siteUrl, token, otherData); this.id = id; - this.config = config; - this.loggedOut = loggedOut; + this.config = otherData.config; + this.loggedOut = otherData.loggedOut; this.logger = CoreLogger.getInstance('CoreSite'); this.cacheTable = asyncInstance(() => CoreSites.getSiteTable(WS_CACHE_TABLE, { @@ -118,7 +112,7 @@ export class CoreSite extends CoreCandidateSite { config: { cachingStrategy: CoreDatabaseCachingStrategy.Eager }, primaryKeyColumns: ['component', 'id'], })); - this.setInfo(infos); + this.setInfo(otherData.info); this.calculateOfflineDisabled(); this.db = CoreDB.getDB('Site-' + this.id); @@ -678,20 +672,10 @@ export class CoreSite extends CoreCandidateSite { } /** - * Check if a certain feature is disabled in the site. - * - * @param name Name of the feature to check. - * @returns Whether it's disabled. + * @inheritdoc */ - isFeatureDisabled(name: string): boolean { - const disabledFeatures = this.getStoredConfig('tool_mobile_disabledfeatures'); - if (!disabledFeatures) { - return false; - } - - const regEx = new RegExp('(,|^)' + CoreTextUtils.escapeForRegex(name) + '(,|$)', 'g'); - - return !!disabledFeatures.match(regEx); + protected getDisabledFeatures(): string | undefined { + return this.config ? this.getStoredConfig('tool_mobile_disabledfeatures') : super.getDisabledFeatures(); } /** @@ -923,6 +907,15 @@ export class CoreSite extends CoreCandidateSite { } +/** + * Optional data to create a site. + */ +export type CoreSiteOptionalData = CoreCandidateSiteOptionalData & { + info?: CoreSiteInfo; + config?: CoreSiteConfig; + loggedOut?: boolean; +}; + /** * Result of WS tool_mobile_get_config. */ diff --git a/src/core/classes/sites/unauthenticated-site.ts b/src/core/classes/sites/unauthenticated-site.ts index 0cc013524..7263086b8 100644 --- a/src/core/classes/sites/unauthenticated-site.ts +++ b/src/core/classes/sites/unauthenticated-site.ts @@ -28,13 +28,19 @@ export class CoreUnauthenticatedSite { siteUrl: string; + protected publicConfig?: CoreSitePublicConfigResponse; + /** * Create a site. * * @param siteUrl Site URL. + * @param publicConfig Site public config. */ - constructor(siteUrl: string) { + constructor(siteUrl: string, publicConfig?: CoreSitePublicConfigResponse) { this.siteUrl = CoreUrlUtils.removeUrlParams(siteUrl); // Make sure the URL doesn't have params. + if (publicConfig) { + this.setPublicConfig(publicConfig); + } } /** @@ -75,7 +81,7 @@ export class CoreUnauthenticatedSite { return CoreConstants.CONFIG.appname; } - const siteName = this.getInfo()?.sitename; + const siteName = this.getInfo()?.sitename || this.publicConfig?.sitename; if (siteName) { return siteName; } @@ -108,6 +114,7 @@ export class CoreUnauthenticatedSite { * @returns Logo URL. */ getLogoUrl(config?: CoreSitePublicConfigResponse): string | undefined { + config = config ?? this.publicConfig; if (!config || this.forcesLocalLogo()) { return 'assets/img/login_logo.png'; } @@ -151,11 +158,40 @@ export class CoreUnauthenticatedSite { * @returns Promise resolved with public config. Rejected with an object if error, see CoreWSProvider.callAjax. */ async getPublicConfig(options: { readingStrategy?: CoreSitesReadingStrategy } = {}): Promise { + const ignoreCache = options.readingStrategy === CoreSitesReadingStrategy.ONLY_NETWORK || + options.readingStrategy === CoreSitesReadingStrategy.PREFER_NETWORK; + if (!ignoreCache && this.publicConfig) { + return this.publicConfig; + }; + if (options.readingStrategy === CoreSitesReadingStrategy.ONLY_CACHE) { throw new CoreError('Cache not available to read public config'); } - return this.requestPublicConfig(); + try { + const config = await this.requestPublicConfig(); + + this.setPublicConfig(config); + + return config; + } catch (error) { + if (options.readingStrategy === CoreSitesReadingStrategy.ONLY_NETWORK || !this.publicConfig) { + throw error; + } + + return this.publicConfig; + } + } + + /** + * Set public config. + * + * @param publicConfig Public config. + */ + setPublicConfig(publicConfig: CoreSitePublicConfigResponse): void { + publicConfig.tool_mobile_disabledfeatures = + CoreTextUtils.treatDisabledFeatures(publicConfig.tool_mobile_disabledfeatures ?? ''); + this.publicConfig = publicConfig; } /** @@ -262,6 +298,32 @@ export class CoreUnauthenticatedSite { return !CoreConstants.CONFIG.hideInformativeLinks && !this.isDemoModeSite(); } + /** + * Check if a certain feature is disabled in the site. + * + * @param name Name of the feature to check. + * @returns Whether it's disabled. + */ + isFeatureDisabled(name: string): boolean { + const disabledFeatures = this.getDisabledFeatures(); + if (!disabledFeatures) { + return false; + } + + const regEx = new RegExp('(,|^)' + CoreTextUtils.escapeForRegex(name) + '(,|$)', 'g'); + + return !!disabledFeatures.match(regEx); + } + + /** + * Get disabled features string. + * + * @returns Disabled features. + */ + protected getDisabledFeatures(): string | undefined { + return this.publicConfig?.tool_mobile_disabledfeatures; + } + } /** diff --git a/src/core/features/login/components/login-methods/login-methods.ts b/src/core/features/login/components/login-methods/login-methods.ts index f3366b296..ce0df2c19 100644 --- a/src/core/features/login/components/login-methods/login-methods.ts +++ b/src/core/features/login/components/login-methods/login-methods.ts @@ -17,6 +17,7 @@ import { CoreSiteIdentityProvider, CoreSitePublicConfigResponse } from '@classes import { CoreLoginHelper, CoreLoginMethod } from '@features/login/services/login-helper'; import { CoreRedirectPayload } from '@services/navigator'; import { CoreSites } from '@services/sites'; +import { CoreSitesFactory } from '@services/sites-factory'; import { CoreDomUtils } from '@services/utils/dom'; @Component({ @@ -53,11 +54,11 @@ export class CoreLoginMethodsComponent implements OnInit { if (this.siteConfig) { this.isBrowserSSO = CoreLoginHelper.isSSOLoginNeeded(this.siteConfig.typeoflogin); + // Identity providers won't be shown if login on browser. if (!this.isBrowserSSO) { - // Identity providers won't be shown if login on browser. - const disabledFeatures = CoreLoginHelper.getDisabledFeatures(this.siteConfig); - - this.identityProviders = CoreLoginHelper.getValidIdentityProviders(this.siteConfig, disabledFeatures); + this.identityProviders = await CoreLoginHelper.getValidIdentityProvidersForSite( + CoreSitesFactory.makeUnauthenticatedSite(this.siteUrl, this.siteConfig), + ); } if (this.reconnect) { diff --git a/src/core/features/login/pages/credentials/credentials.html b/src/core/features/login/pages/credentials/credentials.html index f5f3b5db7..d2cbebcc8 100644 --- a/src/core/features/login/pages/credentials/credentials.html +++ b/src/core/features/login/pages/credentials/credentials.html @@ -20,7 +20,7 @@ - +