MOBILE-4469 login: Support isFeatureDisabled in all site classes

main
Dani Palou 2023-11-13 08:19:23 +01:00
parent a724a946d2
commit a3898d7515
19 changed files with 263 additions and 134 deletions

View File

@ -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<CoreSitePublicConfigResponse> {
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.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(<CoreSitePublicConfigResponse> response);
response = <CoreSitePublicConfigResponse> response;
this.setPublicConfig(response);
subject.next(response);
subject.complete();
return;
@ -1581,6 +1596,14 @@ export function chainRequests<T, O extends ObservableInput<any>>(
);
}
/**
* Optional data to create a candidate site.
*/
export type CoreCandidateSiteOptionalData = {
privateToken?: string;
publicConfig?: CoreSitePublicConfigResponse;
};
/**
* PreSets accepted by the WS call.
*/

View File

@ -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.
*/

View File

@ -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<CoreSitePublicConfigResponse> {
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;
}
}
/**

View File

@ -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);
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);
if (!this.isBrowserSSO) {
this.identityProviders = await CoreLoginHelper.getValidIdentityProvidersForSite(
CoreSitesFactory.makeUnauthenticatedSite(this.siteUrl, this.siteConfig),
);
}
if (this.reconnect) {

View File

@ -20,7 +20,7 @@
</ion-header>
<ion-content class="ion-padding limited-width">
<core-loading [hideUntil]="pageLoaded">
<ng-container *ngIf="!siteCheckError && site">
<ng-container *ngIf="!siteCheckError && site && credForm">
<div class="ion-text-wrap ion-text-center core-login-info-box">
<div class="core-login-site">
<div class="core-login-site-logo" *ngIf="logoUrl">

View File

@ -21,7 +21,7 @@ import { CoreApp } from '@services/app';
import { CoreNetwork } from '@services/network';
import { CoreSiteCheckResponse, CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreLoginHelper } from '@features/login/services/login-helper';
import { CoreLoginHelper, CoreLoginHelperProvider } from '@features/login/services/login-helper';
import { Translate } from '@singletons';
import { CoreSitePublicConfigResponse, CoreUnauthenticatedSite } from '@classes/sites/unauthenticated-site';
import { CoreEvents } from '@singletons/events';
@ -86,12 +86,12 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy {
this.siteConfig = this.siteCheck.config;
}
this.site = CoreSitesFactory.makeUnauthenticatedSite(siteUrl);
this.site = CoreSitesFactory.makeUnauthenticatedSite(siteUrl, this.siteConfig);
this.logoUrl = this.site.getLogoUrl(this.siteConfig);
this.urlToOpen = CoreNavigator.getRouteParam('urlToOpen');
this.supportConfig = this.siteConfig && new CoreUserGuestSupportConfig(this.siteConfig);
this.supportConfig = this.siteConfig && new CoreUserGuestSupportConfig(this.site, this.siteConfig);
this.displaySiteUrl = this.site.shouldDisplayInformativeLinks();
this.siteName = (await this.site.getSiteName()) || CoreNavigator.getRouteParam('siteName');
this.siteName = await this.site.getSiteName();
} catch (error) {
CoreDomUtils.showErrorModal(error);
@ -158,11 +158,12 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy {
try {
if (!this.siteCheck) {
this.siteCheck = await CoreSites.checkSite(this.site.siteUrl, protocol);
this.siteCheck.config && this.site.setPublicConfig(this.siteCheck.config);
}
this.site.setURL(this.siteCheck.siteUrl);
this.siteConfig = this.siteCheck.config;
this.supportConfig = this.siteConfig && new CoreUserGuestSupportConfig(this.siteConfig);
this.supportConfig = this.siteConfig && new CoreUserGuestSupportConfig(this.site, this.siteConfig);
await this.treatSiteConfig();
@ -198,10 +199,9 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy {
this.showScanQR = await CoreLoginHelper.displayQRInCredentialsScreen(this.siteConfig.tool_mobile_qrcodetype);
}
const disabledFeatures = CoreLoginHelper.getDisabledFeatures(this.siteConfig);
this.canSignup = this.siteConfig.registerauth == 'email' &&
!CoreLoginHelper.isEmailSignupDisabled(this.siteConfig, disabledFeatures);
this.showForgottenPassword = !CoreLoginHelper.isForgottenPasswordDisabled(this.siteConfig, disabledFeatures);
!this.site.isFeatureDisabled(CoreLoginHelperProvider.EMAIL_SIGNUP_FEATURE_NAME);
this.showForgottenPassword = !this.site.isFeatureDisabled(CoreLoginHelperProvider.FORGOTTEN_PASSWORD_FEATURE_NAME);
this.exceededAttemptsHTML = CoreLoginHelper.buildExceededAttemptsHTML(
!!this.supportConfig?.canContactSupport(),
this.showForgottenPassword,

View File

@ -77,7 +77,7 @@
</form>
<!-- Signup form. -->
<form *ngIf="!ageDigitalConsentVerification" [formGroup]="signupForm" (ngSubmit)="create($event)" #signupFormEl>
<form *ngIf="!ageDigitalConsentVerification && site" [formGroup]="signupForm" (ngSubmit)="create($event)" #signupFormEl>
<ion-item class="ion-text-wrap ion-text-center">
<ion-label>

View File

@ -15,7 +15,6 @@
import { Component, ViewChild, ElementRef, OnInit, ChangeDetectorRef } from '@angular/core';
import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreTextUtils } from '@services/utils/text';
import { CoreCountry, CoreUtils } from '@services/utils/utils';
@ -28,6 +27,7 @@ import {
AuthEmailSignupProfileFieldsCategory,
AuthEmailSignupSettings,
CoreLoginHelper,
CoreLoginHelperProvider,
} from '@features/login/services/login-helper';
import { CoreNavigator } from '@services/navigator';
import { CoreForms } from '@singletons/form';
@ -163,7 +163,7 @@ export class CoreLoginEmailSignupPage implements OnInit {
protected async fetchData(): Promise<void> {
try {
// Get site config.
this.siteConfig = await CoreSites.getSitePublicConfig(this.site.getURL());
this.siteConfig = await this.site.getPublicConfig();
this.signupUrl = CorePath.concatenatePaths(this.siteConfig.httpswwwroot, 'login/signup.php');
const configValid = await this.treatSiteConfig();
@ -238,7 +238,10 @@ export class CoreLoginEmailSignupPage implements OnInit {
* @returns True if success.
*/
protected async treatSiteConfig(): Promise<boolean> {
if (this.siteConfig?.registerauth == 'email' && !CoreLoginHelper.isEmailSignupDisabled(this.siteConfig)) {
if (
this.siteConfig?.registerauth == 'email' &&
!this.site.isFeatureDisabled(CoreLoginHelperProvider.EMAIL_SIGNUP_FEATURE_NAME)
) {
this.siteName = await this.site.getSiteName();
this.authInstructions = this.siteConfig.authinstructions;

View File

@ -21,9 +21,10 @@ import { Translate } from '@singletons';
import { CoreNavigator } from '@services/navigator';
import { CoreForms } from '@singletons/form';
import { CorePlatform } from '@services/platform';
import { CoreSitePublicConfigResponse } from '@classes/sites/unauthenticated-site';
import { CoreSitePublicConfigResponse, CoreUnauthenticatedSite } from '@classes/sites/unauthenticated-site';
import { CoreUserSupportConfig } from '@features/user/classes/support/support-config';
import { CoreUserGuestSupportConfig } from '@features/user/classes/support/guest-support-config';
import { CoreSitesFactory } from '@services/sites-factory';
/**
* Page to recover a forgotten password.
@ -37,7 +38,7 @@ export class CoreLoginForgottenPasswordPage implements OnInit {
@ViewChild('resetPasswordForm') formElement?: ElementRef;
myForm!: FormGroup;
siteUrl!: string;
site!: CoreUnauthenticatedSite;
autoFocus!: boolean;
supportConfig?: CoreUserSupportConfig;
canContactSupport?: boolean;
@ -59,14 +60,14 @@ export class CoreLoginForgottenPasswordPage implements OnInit {
const siteConfig = CoreNavigator.getRouteParam<CoreSitePublicConfigResponse>('siteConfig');
this.siteUrl = siteUrl;
this.site = CoreSitesFactory.makeUnauthenticatedSite(siteUrl, siteConfig);
this.autoFocus = CorePlatform.is('tablet');
this.myForm = this.formBuilder.group({
field: ['username', Validators.required],
value: [CoreNavigator.getRouteParam<string>('username') || '', Validators.required],
});
this.supportConfig = siteConfig && new CoreUserGuestSupportConfig(siteConfig);
this.supportConfig = siteConfig && new CoreUserGuestSupportConfig(this.site, siteConfig);
this.canContactSupport = this.supportConfig?.canContactSupport();
this.wasPasswordResetRequestedRecently = await CoreLoginHelper.wasPasswordResetRequestedRecently(siteUrl);
}
@ -94,7 +95,7 @@ export class CoreLoginForgottenPasswordPage implements OnInit {
try {
const response = await CoreLoginHelper.requestPasswordReset(
this.siteUrl,
this.site.getURL(),
isMail ? '' : value,
isMail ? value : '',
);
@ -115,7 +116,7 @@ export class CoreLoginForgottenPasswordPage implements OnInit {
await CoreDomUtils.showAlert(Translate.instant('core.success'), response.notice);
await CoreNavigator.back();
await CoreLoginHelper.passwordResetRequested(this.siteUrl);
await CoreLoginHelper.passwordResetRequested(this.site.getURL());
}
} catch (error) {
CoreDomUtils.showErrorModal(error);

View File

@ -20,7 +20,7 @@ import { CoreNetwork } from '@services/network';
import { CoreSiteBasicInfo, CoreSites, CoreSitesReadingStrategy } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { CoreLoginHelper } from '@features/login/services/login-helper';
import { CoreLoginHelper, CoreLoginHelperProvider } from '@features/login/services/login-helper';
import { CoreSite } from '@classes/sites/site';
import { CoreEvents } from '@singletons/events';
import { CoreError } from '@classes/errors/error';
@ -171,7 +171,7 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy {
return;
}
this.showForgottenPassword = !CoreLoginHelper.isForgottenPasswordDisabled(this.siteConfig);
this.showForgottenPassword = !this.site.isFeatureDisabled(CoreLoginHelperProvider.FORGOTTEN_PASSWORD_FEATURE_NAME);
this.exceededAttemptsHTML = CoreLoginHelper.buildExceededAttemptsHTML(
!!this.supportConfig?.canContactSupport(),
this.showForgottenPassword,

View File

@ -120,7 +120,7 @@
<!-- Template site selector. -->
<ng-template #sitelisting let-site="site">
<ion-item button (click)="connect(site.url, $event, site)" [ngClass]="site.className" [attr.aria-label]="site.name" [detail]="true">
<ion-item button (click)="connect(site.url, $event)" [ngClass]="site.className" [attr.aria-label]="site.name" [detail]="true">
<ion-thumbnail *ngIf="siteFinderSettings.displayimage" slot="start">
<img [src]="site.imageurl" *ngIf="site.imageurl" onError="this.src='assets/icon/icon.png'" alt="" role="presentation">
<img src="assets/icon/icon.png" *ngIf="!site.imageurl" class="core-login-default-icon" alt="" role="presentation">

View File

@ -278,10 +278,9 @@ export class CoreLoginSitePage implements OnInit {
*
* @param url The URL to connect to.
* @param e Event (if any).
* @param foundSite The site clicked, if any, from the found sites list.
* @returns Promise resolved when done.
*/
async connect(url: string, e?: Event, foundSite?: CoreLoginSiteInfoExtended): Promise<void> {
async connect(url: string, e?: Event): Promise<void> {
e?.preventDefault();
e?.stopPropagation();
@ -341,7 +340,7 @@ export class CoreLoginSitePage implements OnInit {
}
}
await this.login(checkResult, foundSite);
await this.login(checkResult);
modal.dismiss();
}
@ -381,23 +380,17 @@ export class CoreLoginSitePage implements OnInit {
* Process login to a site.
*
* @param siteCheck Response obtained from the site check request.
* @param foundSite The site clicked, if any, from the found sites list.
*
* @returns Promise resolved after logging in.
*/
protected async login(siteCheck: CoreSiteCheckResponse, foundSite?: CoreLoginSiteInfoExtended): Promise<void> {
protected async login(siteCheck: CoreSiteCheckResponse): Promise<void> {
try {
await CoreSites.checkApplication(siteCheck.config);
CoreForms.triggerFormSubmittedEvent(this.formElement, true);
const pageParams = { siteCheck };
if (foundSite && !this.fixedSites) {
pageParams['siteName'] = foundSite.name;
}
CoreNavigator.navigate('/login/credentials', {
params: pageParams,
params: { siteCheck },
});
} catch {
// Ignore errors.

View File

@ -45,6 +45,7 @@ import {
CoreSiteIdentityProvider,
CoreSitePublicConfigResponse,
CoreSiteQRCodeType,
CoreUnauthenticatedSite,
TypeOfLogin,
} from '@classes/sites/unauthenticated-site';
@ -62,6 +63,10 @@ export class CoreLoginHelperProvider {
static readonly FAQ_QRCODE_INFO_DONE = 'qrcode_info_done';
static readonly FAQ_URL_IMAGE_HTML = '<img src="assets/img/login/faq_url.png" role="presentation" alt="">';
static readonly FAQ_QRCODE_IMAGE_HTML = '<img src="assets/img/login/faq_qrcode.png" role="presentation" alt="">';
static readonly EMAIL_SIGNUP_FEATURE_NAME = 'CoreLoginEmailSignup';
static readonly FORGOTTEN_PASSWORD_FEATURE_NAME = 'NoDelegate_ForgottenPassword';
static readonly IDENTITY_PROVIDERS_FEATURE_NAME = 'NoDelegate_IdentityProviders';
static readonly IDENTITY_PROVIDER_FEATURE_NAME_PREFIX = 'NoDelegate_IdentityProvider_';
protected logger: CoreLogger;
protected sessionExpiredCheckingSite: Record<string, boolean> = {};
@ -238,6 +243,7 @@ export class CoreLoginHelperProvider {
*
* @param config Site public config.
* @returns Disabled features.
* @deprecated since 4.4. No longer needed.
*/
getDisabledFeatures(config?: CoreSitePublicConfigResponse): string {
const disabledFeatures = config?.tool_mobile_disabledfeatures;
@ -307,7 +313,7 @@ export class CoreLoginHelperProvider {
*
* @param config Site public config.
* @returns Logo URL.
* @deprecated since 4.2. Please use getLogoUrl in a site instance.
* @deprecated since 4.4. Please use getLogoUrl in a site instance.
*/
getLogoUrl(config: CoreSitePublicConfigResponse): string | undefined {
return !CoreConstants.CONFIG.forceLoginLogo && config ? (config.logourl || config.compactlogourl) : undefined;
@ -404,14 +410,56 @@ export class CoreLoginHelperProvider {
* Get the valid identity providers from a site config.
*
* @param siteConfig Site's public config.
* @param disabledFeatures List of disabled features already treated. If not provided it will be calculated.
* @returns Valid identity providers.
* @deprecated since 4.4. Please use getValidIdentityProvidersForSite instead.
*/
getValidIdentityProviders(siteConfig?: CoreSitePublicConfigResponse, disabledFeatures?: string): CoreSiteIdentityProvider[] {
getValidIdentityProviders(siteConfig?: CoreSitePublicConfigResponse): CoreSiteIdentityProvider[] {
if (!siteConfig) {
return [];
}
if (this.isFeatureDisabled('NoDelegate_IdentityProviders', siteConfig, disabledFeatures)) {
// eslint-disable-next-line deprecation/deprecation
if (this.isFeatureDisabled(CoreLoginHelperProvider.IDENTITY_PROVIDERS_FEATURE_NAME, siteConfig)) {
// Identity providers are disabled, return an empty list.
return [];
}
const validProviders: CoreSiteIdentityProvider[] = [];
const httpUrl = CorePath.concatenatePaths(siteConfig.wwwroot, 'auth/oauth2/');
const httpsUrl = CorePath.concatenatePaths(siteConfig.httpswwwroot, 'auth/oauth2/');
if (siteConfig.identityproviders && siteConfig.identityproviders.length) {
siteConfig.identityproviders.forEach((provider) => {
const urlParams = CoreUrlUtils.extractUrlParams(provider.url);
if (
provider.url &&
(provider.url.indexOf(httpsUrl) != -1 || provider.url.indexOf(httpUrl) != -1) &&
!this.isFeatureDisabled( // eslint-disable-line deprecation/deprecation
CoreLoginHelperProvider.IDENTITY_PROVIDER_FEATURE_NAME_PREFIX + urlParams.id,
siteConfig,
)
) {
validProviders.push(provider);
}
});
}
return validProviders;
}
/**
* Get the valid identity providers from a site config.
*
* @param site Site instance.
* @returns Valid identity providers.
*/
async getValidIdentityProvidersForSite(site: CoreUnauthenticatedSite): Promise<CoreSiteIdentityProvider[]> {
const siteConfig = await CoreUtils.ignoreErrors(site.getPublicConfig());
if (!siteConfig) {
return [];
}
if (site.isFeatureDisabled(CoreLoginHelperProvider.IDENTITY_PROVIDERS_FEATURE_NAME)) {
// Identity providers are disabled, return an empty list.
return [];
}
@ -425,7 +473,7 @@ export class CoreLoginHelperProvider {
const urlParams = CoreUrlUtils.extractUrlParams(provider.url);
if (provider.url && (provider.url.indexOf(httpsUrl) != -1 || provider.url.indexOf(httpUrl) != -1) &&
!this.isFeatureDisabled('NoDelegate_IdentityProvider_' + urlParams.id, siteConfig, disabledFeatures)) {
!site.isFeatureDisabled(CoreLoginHelperProvider.IDENTITY_PROVIDER_FEATURE_NAME_PREFIX + urlParams.id)) {
validProviders.push(provider);
}
});
@ -518,11 +566,12 @@ export class CoreLoginHelperProvider {
* Given a site public config, check if email signup is disabled.
*
* @param config Site public config.
* @param disabledFeatures List of disabled features already treated. If not provided it will be calculated.
* @returns Whether email signup is disabled.
* @deprecated since 4.4. Please use isFeatureDisabled in a site instance.
*/
isEmailSignupDisabled(config?: CoreSitePublicConfigResponse, disabledFeatures?: string): boolean {
return this.isFeatureDisabled('CoreLoginEmailSignup', config, disabledFeatures);
isEmailSignupDisabled(config?: CoreSitePublicConfigResponse): boolean {
// eslint-disable-next-line deprecation/deprecation
return this.isFeatureDisabled(CoreLoginHelperProvider.EMAIL_SIGNUP_FEATURE_NAME, config);
}
/**
@ -530,17 +579,12 @@ export class CoreLoginHelperProvider {
*
* @param feature Feature to check.
* @param config Site public config.
* @param disabledFeatures List of disabled features already treated. If not provided it will be calculated.
* @returns Whether email signup is disabled.
* @deprecated since 4.4. Please use isFeatureDisabled in a site instance.
*/
isFeatureDisabled(feature: string, config?: CoreSitePublicConfigResponse, disabledFeatures?: string): boolean {
if (disabledFeatures === undefined) {
disabledFeatures = this.getDisabledFeatures(config);
}
const regEx = new RegExp('(,|^)' + feature + '(,|$)', 'g');
return !!disabledFeatures.match(regEx);
isFeatureDisabled(feature: string, config?: CoreSitePublicConfigResponse): boolean {
// eslint-disable-next-line deprecation/deprecation
return this.isFeatureDisabled(feature, config);
}
/**
@ -568,11 +612,12 @@ export class CoreLoginHelperProvider {
* Given a site public config, check if forgotten password is disabled.
*
* @param config Site public config.
* @param disabledFeatures List of disabled features already treated. If not provided it will be calculated.
* @returns Whether it's disabled.
* @deprecated since 4.4. Please use isFeatureDisabled in a site instance.
*/
isForgottenPasswordDisabled(config?: CoreSitePublicConfigResponse, disabledFeatures?: string): boolean {
return this.isFeatureDisabled('NoDelegate_ForgottenPassword', config, disabledFeatures);
isForgottenPasswordDisabled(config?: CoreSitePublicConfigResponse): boolean {
// eslint-disable-next-line deprecation/deprecation
return this.isFeatureDisabled(CoreLoginHelperProvider.FORGOTTEN_PASSWORD_FEATURE_NAME, config);
}
/**

View File

@ -842,7 +842,7 @@ export class CorePushNotificationsProvider {
result.siteid,
result.siteurl,
result.token,
CoreTextUtils.parseJSON<CoreSiteInfo | null>(result.info, null) || undefined,
{ info: CoreTextUtils.parseJSON<CoreSiteInfo | null>(result.info, null) || undefined },
);
await this.unregisterDeviceOnMoodle(tmpSite);

View File

@ -16,6 +16,7 @@ import { CoreSite } from '@classes/sites/site';
import { CoreSites } from '@services/sites';
import { CoreUserSupportConfig } from './support-config';
import { CoreSiteConfigSupportAvailability } from '@classes/sites/unauthenticated-site';
import { CoreCandidateSite } from '@classes/sites/candidate-site';
/**
* Support config for an authenticated user.
@ -31,9 +32,9 @@ export class CoreUserAuthenticatedSupportConfig extends CoreUserSupportConfig {
return new CoreUserAuthenticatedSupportConfig(CoreSites.getRequiredCurrentSite());
}
private site: CoreSite;
private site: CoreSite | CoreCandidateSite;
constructor(site: CoreSite) {
constructor(site: CoreSite | CoreCandidateSite) {
super();
this.site = site;
@ -48,7 +49,7 @@ export class CoreUserAuthenticatedSupportConfig extends CoreUserSupportConfig {
}
if (this.site.isVersionGreaterEqualThan('4.1')) {
if (!this.site.config || !('supportavailability' in this.site.config)) {
if (!('config' in this.site) || !this.site.config || !('supportavailability' in this.site.config)) {
return false;
}
@ -78,8 +79,10 @@ export class CoreUserAuthenticatedSupportConfig extends CoreUserSupportConfig {
* @inheritdoc
*/
protected buildSupportPageUrl(): string {
return this.site.config?.supportpage?.trim()
|| `${this.site.config?.httpswwwroot ?? this.site.config?.wwwroot ?? this.site.siteUrl}/user/contactsitesupport.php`;
const config = 'config' in this.site ? this.site.config : undefined;
return config?.supportpage?.trim()
|| `${config?.httpswwwroot ?? config?.wwwroot ?? this.site.siteUrl}/user/contactsitesupport.php`;
}
}

View File

@ -12,12 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { CoreSiteConfigSupportAvailability, CoreSitePublicConfigResponse } from '@classes/sites/unauthenticated-site';
import { CoreLoginHelper } from '@features/login/services/login-helper';
import {
CoreSiteConfigSupportAvailability,
CoreSitePublicConfigResponse,
CoreUnauthenticatedSite,
} from '@classes/sites/unauthenticated-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';
import { CoreSitesFactory } from '@services/sites-factory';
/**
* Support config for a guest user.
@ -37,14 +41,16 @@ export class CoreUserGuestSupportConfig extends CoreUserSupportConfig {
return new CoreUserNullSupportConfig();
}
return new CoreUserGuestSupportConfig(siteConfig);
return new CoreUserGuestSupportConfig(CoreSitesFactory.makeUnauthenticatedSite(siteUrl, siteConfig), siteConfig);
}
private site: CoreUnauthenticatedSite;
private config: CoreSitePublicConfigResponse;
constructor(config: CoreSitePublicConfigResponse) {
constructor(site: CoreUnauthenticatedSite, config: CoreSitePublicConfigResponse) {
super();
this.site = site;
this.config = config;
}
@ -52,7 +58,7 @@ export class CoreUserGuestSupportConfig extends CoreUserSupportConfig {
* @inheritdoc
*/
canContactSupport(): boolean {
if (CoreLoginHelper.isFeatureDisabled('NoDelegate_CoreUserSupport', this.config)) {
if (this.site.isFeatureDisabled('NoDelegate_CoreUserSupport')) {
return false;
}

View File

@ -13,10 +13,10 @@
// limitations under the License.
import { Injectable } from '@angular/core';
import { CoreCandidateSite } from '@classes/sites/candidate-site';
import { CoreCandidateSite, CoreCandidateSiteOptionalData } from '@classes/sites/candidate-site';
import { CoreSite, CoreSiteConfig } from '@classes/sites/site';
import { CoreUnauthenticatedSite, CoreSiteInfo } from '@classes/sites/unauthenticated-site';
import { CoreSite, CoreSiteOptionalData } from '@classes/sites/site';
import { CoreUnauthenticatedSite, CoreSitePublicConfigResponse } from '@classes/sites/unauthenticated-site';
import { makeSingleton } from '@singletons';
/*
@ -31,22 +31,16 @@ export class CoreSitesFactoryService {
* @param id Site ID.
* @param siteUrl Site URL.
* @param token Site's WS token.
* @param info Site info.
* @param privateToken Private token.
* @param config Site public config.
* @param loggedOut Whether user is logged out.
* @param otherData Other data.
* @returns Site instance.
*/
makeSite(
id: string,
siteUrl: string,
token: string,
info?: CoreSiteInfo,
privateToken?: string,
config?: CoreSiteConfig,
loggedOut?: boolean,
otherData: CoreSiteOptionalData = {},
): CoreSite {
return new CoreSite(id, siteUrl, token, info, privateToken, config, loggedOut);
return new CoreSite(id, siteUrl, token, otherData);
}
/**
@ -54,21 +48,22 @@ export class CoreSitesFactoryService {
*
* @param siteUrl Site URL.
* @param token Site's WS token.
* @param privateToken Private token.
* @param options Other options.
* @returns Candidate site instance.
*/
makeCandidateSite(siteUrl: string, token: string, privateToken?: string): CoreCandidateSite {
return new CoreCandidateSite(siteUrl, token, privateToken);
makeCandidateSite(siteUrl: string, token: string, options: CoreCandidateSiteOptionalData = {}): CoreCandidateSite {
return new CoreCandidateSite(siteUrl, token, options);
}
/**
* Create an unauthenticated site instance.
*
* @param siteUrl Site URL.
* @param publicConfig Site public config.
* @returns Unauthenticated site instance.
*/
makeUnauthenticatedSite(siteUrl: string): CoreUnauthenticatedSite {
return new CoreUnauthenticatedSite(siteUrl);
makeUnauthenticatedSite(siteUrl: string, publicConfig?: CoreSitePublicConfigResponse): CoreUnauthenticatedSite {
return new CoreUnauthenticatedSite(siteUrl, publicConfig);
}
}

View File

@ -305,7 +305,7 @@ export class CoreSitesProvider {
// Check that the user can authenticate.
if (!config.enablewebservices) {
throw this.createCannotConnectLoginError(config.httpswwwroot || config.wwwroot, {
supportConfig: new CoreUserGuestSupportConfig(config),
supportConfig: new CoreUserGuestSupportConfig(temporarySite, config),
errorcode: 'webservicesnotenabled',
errorDetails: Translate.instant('core.login.webservicesnotenabled'),
critical: true,
@ -314,7 +314,7 @@ export class CoreSitesProvider {
if (!config.enablemobilewebservice) {
throw this.createCannotConnectLoginError(config.httpswwwroot || config.wwwroot, {
supportConfig: new CoreUserGuestSupportConfig(config),
supportConfig: new CoreUserGuestSupportConfig(temporarySite, config),
errorcode: 'mobileservicesnotenabled',
errorDetails: Translate.instant('core.login.mobileservicesnotenabled'),
critical: true,
@ -515,7 +515,7 @@ export class CoreSitesProvider {
}
// Create a "candidate" site to fetch the site info.
const candidateSite = CoreSitesFactory.makeCandidateSite(siteUrl, token, privateToken);
const candidateSite = CoreSitesFactory.makeCandidateSite(siteUrl, token, { privateToken });
let isNewSite = true;
try {
@ -544,7 +544,7 @@ export class CoreSitesProvider {
} else {
// New site, set site ID and info.
isNewSite = true;
site = CoreSitesFactory.makeSite(siteId, siteUrl, token, info, privateToken);
site = CoreSitesFactory.makeSite(siteId, siteUrl, token, { info, privateToken });
site.setOAuthId(oauthId);
// Create database tables before login and before any WS call.
@ -1172,10 +1172,12 @@ export class CoreSitesProvider {
entry.id,
entry.siteUrl,
entry.token,
{
info,
entry.privateToken,
privateToken: entry.privateToken,
config,
entry.loggedOut == 1,
loggedOut: entry.loggedOut == 1,
},
);
site.setOAuthId(entry.oauthId || undefined);
@ -1246,8 +1248,10 @@ export class CoreSitesProvider {
await Promise.all(sites.map(async (site) => {
if (!ids || ids.indexOf(site.id) > -1) {
const siteName = await CoreSitesFactory.makeUnauthenticatedSite(site.siteUrl).getSiteName();
const siteInfo = site.info ? <CoreSiteInfo> CoreTextUtils.parseJSON(site.info) : undefined;
const siteInstance = CoreSitesFactory.makeSite(site.id, site.siteUrl, site.token, { info: siteInfo });
const siteName = await siteInstance.getSiteName();
const basicInfo: CoreSiteBasicInfo = {
id: site.id,

View File

@ -27,7 +27,7 @@ export class CoreSiteStub extends CoreSite {
protected wsStubs: Record<string, unknown> = {};
constructor (fixture: CoreSiteFixture) {
super(fixture.id, fixture.info.siteurl, '', fixture.info);
super(fixture.id, fixture.info.siteurl, '', { info: fixture.info });
this.stubWSResponse<CoreSiteConfigResponse>('tool_mobile_get_config', {
settings: [],