diff --git a/src/core/classes/site.ts b/src/core/classes/site.ts index c3593943a..5105c2b2e 100644 --- a/src/core/classes/site.ts +++ b/src/core/classes/site.ts @@ -41,6 +41,15 @@ import { CoreLogger } from '@singletons/logger'; import { Translate } from '@singletons'; import { CoreIonLoadingElement } from './ion-loading'; +/** + * QR Code type enumeration. + */ +export enum CoreSiteQRCodeType { + QR_CODE_DISABLED = 0, // QR code disabled value + QR_CODE_URL = 1, // QR code type URL value + QR_CODE_LOGIN = 2, // QR code type login value +} + /** * Class that represents a site (combination of site + user). * It will have all the site data and provide utility functions regarding a site. @@ -2122,6 +2131,7 @@ export type CoreSitePublicConfigResponse = { tool_mobile_androidappid?: string; // Android app's unique identifier. // eslint-disable-next-line @typescript-eslint/naming-convention tool_mobile_setuplink?: string; // App download page. + tool_mobile_qrcodetype?: CoreSiteQRCodeType; // eslint-disable-line @typescript-eslint/naming-convention warnings?: CoreWSExternalWarning[]; }; diff --git a/src/core/features/login/pages/credentials/credentials.ts b/src/core/features/login/pages/credentials/credentials.ts index 7f478d243..ad4e804ce 100644 --- a/src/core/features/login/pages/credentials/credentials.ts +++ b/src/core/features/login/pages/credentials/credentials.ts @@ -68,32 +68,32 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy { /** * Initialize the component. */ - ngOnInit(): void { - const siteUrl = CoreNavigator.getRouteParam('siteUrl'); - if (!siteUrl) { - CoreDomUtils.showErrorModal('Site URL not supplied.'); - CoreNavigator.back(); + async ngOnInit(): Promise { + try { + this.siteUrl = CoreNavigator.getRequiredRouteParam('siteUrl'); - return; + this.siteName = CoreNavigator.getRouteParam('siteName'); + this.logoUrl = !CoreConstants.CONFIG.forceLoginLogo && CoreNavigator.getRouteParam('logoUrl') || undefined; + this.siteConfig = CoreNavigator.getRouteParam('siteConfig'); + this.urlToOpen = CoreNavigator.getRouteParam('urlToOpen'); + } catch (error) { + CoreDomUtils.showErrorModal(error); + + return CoreNavigator.back(); } - this.siteUrl = siteUrl; - this.siteName = CoreNavigator.getRouteParam('siteName'); - this.logoUrl = !CoreConstants.CONFIG.forceLoginLogo && CoreNavigator.getRouteParam('logoUrl') || undefined; - this.siteConfig = CoreNavigator.getRouteParam('siteConfig'); - this.urlToOpen = CoreNavigator.getRouteParam('urlToOpen'); - this.showScanQR = CoreLoginHelper.displayQRInCredentialsScreen(); - this.credForm = this.fb.group({ username: [CoreNavigator.getRouteParam('username') || '', Validators.required], password: ['', Validators.required], }); - this.treatSiteConfig(); + if (this.siteConfig) { + this.treatSiteConfig(); + } this.isFixedUrlSet = CoreLoginHelper.isFixedUrlSet(); - if (this.isFixedUrlSet) { - // Fixed URL, we need to check if it uses browser SSO login. + if (this.isFixedUrlSet || !this.siteConfig) { + // Fixed URL or not siteConfig retrieved from params, we need to check if it uses browser SSO login. this.checkSite(this.siteUrl); } else { this.siteChecked = true; @@ -177,6 +177,7 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy { this.siteName = CoreConstants.CONFIG.sitename ? CoreConstants.CONFIG.sitename : this.siteConfig.sitename; this.logoUrl = CoreLoginHelper.getLogoUrl(this.siteConfig); this.authInstructions = this.siteConfig.authinstructions || Translate.instant('core.login.loginsteps'); + this.showScanQR = CoreLoginHelper.displayQRInCredentialsScreen(this.siteConfig.tool_mobile_qrcodetype); const disabledFeatures = CoreLoginHelper.getDisabledFeatures(this.siteConfig); this.identityProviders = CoreLoginHelper.getValidIdentityProviders(this.siteConfig, disabledFeatures); diff --git a/src/core/features/login/pages/reconnect/reconnect.ts b/src/core/features/login/pages/reconnect/reconnect.ts index f48433217..b34720cdd 100644 --- a/src/core/features/login/pages/reconnect/reconnect.ts +++ b/src/core/features/login/pages/reconnect/reconnect.ts @@ -20,7 +20,7 @@ import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUtils } from '@services/utils/utils'; import { CoreLoginHelper } from '@features/login/services/login-helper'; -import { CoreSiteIdentityProvider, CoreSitePublicConfigResponse } from '@classes/site'; +import { CoreSite, CoreSiteIdentityProvider, CoreSitePublicConfigResponse } from '@classes/site'; import { CoreEvents } from '@singletons/events'; import { CoreError } from '@classes/errors/error'; import { CoreNavigationOptions, CoreNavigator } from '@services/navigator'; @@ -64,7 +64,7 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy { ) { const currentSite = CoreSites.getCurrentSite(); - this.isLoggedOut = !!currentSite?.isLoggedOut(); + this.isLoggedOut = !currentSite || currentSite.isLoggedOut(); this.credForm = fb.group({ password: ['', Validators.required], }); @@ -74,17 +74,12 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy { * Initialize the component. */ async ngOnInit(): Promise { - const siteId = CoreNavigator.getRouteParam('siteId'); - if (!siteId) { - return this.cancel(); - } - - this.siteId = siteId; - this.page = CoreNavigator.getRouteParam('pageName'); - this.pageOptions = CoreNavigator.getRouteParam('pageOptions'); - this.showScanQR = CoreLoginHelper.displayQRInSiteScreen() || CoreLoginHelper.displayQRInCredentialsScreen(); - try { + this.siteId = CoreNavigator.getRequiredRouteParam('siteId'); + + this.page = CoreNavigator.getRouteParam('pageName'); + this.pageOptions = CoreNavigator.getRouteParam('pageOptions'); + const site = await CoreSites.getSite(this.siteId); if (!site.infos) { @@ -103,26 +98,11 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy { // Show logo instead of avatar if it's a fixed site. this.showSiteAvatar = !!this.userAvatar && !CoreLoginHelper.getFixedSites(); - const config = await CoreUtils.ignoreErrors(site.getPublicConfig()); - - if (!config) { - return; - } - - this.siteConfig = config; - - await CoreSites.checkApplication(config); - - // Check logoURL if user avatar is not set. - if (this.userAvatar.startsWith(this.siteUrl + '/theme/image.php')) { - this.showSiteAvatar = false; - } - this.logoUrl = CoreLoginHelper.getLogoUrl(config); - - this.getDataFromConfig(this.siteConfig); + this.checkSiteConfig(site); } catch (error) { - // Just leave the view. - this.cancel(); + CoreDomUtils.showErrorModal(error); + + return this.cancel(); } } @@ -136,19 +116,34 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy { /** * Get some data (like identity providers) from the site config. - * - * @param config Config to use. */ - protected getDataFromConfig(config: CoreSitePublicConfigResponse): void { - const disabledFeatures = CoreLoginHelper.getDisabledFeatures(config); + protected async checkSiteConfig(site: CoreSite): Promise { + this.siteConfig = await CoreUtils.ignoreErrors(site.getPublicConfig()); - this.identityProviders = CoreLoginHelper.getValidIdentityProviders(config, disabledFeatures); - this.showForgottenPassword = !CoreLoginHelper.isForgottenPasswordDisabled(config); + if (!this.siteConfig) { + return; + } + + const disabledFeatures = CoreLoginHelper.getDisabledFeatures(this.siteConfig); + + this.identityProviders = CoreLoginHelper.getValidIdentityProviders(this.siteConfig, disabledFeatures); + this.showForgottenPassword = !CoreLoginHelper.isForgottenPasswordDisabled(this.siteConfig); if (!this.eventThrown && !this.viewLeft) { this.eventThrown = true; - CoreEvents.trigger(CoreEvents.LOGIN_SITE_CHECKED, { config: config }); + CoreEvents.trigger(CoreEvents.LOGIN_SITE_CHECKED, { config: this.siteConfig }); } + + this.showScanQR = CoreLoginHelper.displayQRInSiteScreen() || + CoreLoginHelper.displayQRInCredentialsScreen(this.siteConfig.tool_mobile_qrcodetype); + + await CoreSites.checkApplication(this.siteConfig); + + // Check logoURL if user avatar is not set. + if (this.userAvatar?.startsWith(this.siteUrl + '/theme/image.php')) { + this.showSiteAvatar = false; + } + this.logoUrl = CoreLoginHelper.getLogoUrl(this.siteConfig); } /** @@ -162,6 +157,11 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy { e.stopPropagation(); } + if (this.isLoggedOut) { + // Go to sites page when user is logged out. + CoreNavigator.navigate('/login/sites', { reset: true }); + } + CoreSites.logout(); } diff --git a/src/core/features/login/services/login-helper.ts b/src/core/features/login/services/login-helper.ts index 75c316eb2..8f9780fc3 100644 --- a/src/core/features/login/services/login-helper.ts +++ b/src/core/features/login/services/login-helper.ts @@ -26,7 +26,7 @@ import { CoreTextUtils } from '@services/utils/text'; import { CoreUrlParams, CoreUrlUtils } from '@services/utils/url'; import { CoreUtils } from '@services/utils/utils'; import { CoreConstants } from '@/core/constants'; -import { CoreSite, CoreSiteIdentityProvider, CoreSitePublicConfigResponse } from '@classes/site'; +import { CoreSite, CoreSiteIdentityProvider, CoreSitePublicConfigResponse, CoreSiteQRCodeType } from '@classes/site'; import { CoreError } from '@classes/errors/error'; import { CoreWSError } from '@classes/errors/wserror'; import { makeSingleton, Translate } from '@singletons'; @@ -1237,15 +1237,22 @@ export class CoreLoginHelperProvider { /** * Check whether the QR reader should be displayed in credentials screen. * + * @param qrCodeType QR Code type from public config, assuming enabled if undefined. * @return Whether the QR reader should be displayed in credentials screen. */ - displayQRInCredentialsScreen(): boolean { + displayQRInCredentialsScreen(qrCodeType = CoreSiteQRCodeType.QR_CODE_LOGIN): boolean { if (!CoreUtils.canScanQR()) { return false; } - return (CoreConstants.CONFIG.displayqroncredentialscreen === undefined && this.isFixedUrlSet()) || - (CoreConstants.CONFIG.displayqroncredentialscreen !== undefined && !!CoreConstants.CONFIG.displayqroncredentialscreen); + if ((CoreConstants.CONFIG.displayqroncredentialscreen === undefined && this.isFixedUrlSet()) || + (CoreConstants.CONFIG.displayqroncredentialscreen !== undefined && + !!CoreConstants.CONFIG.displayqroncredentialscreen)) { + + return qrCodeType == CoreSiteQRCodeType.QR_CODE_LOGIN; + } + + return false; } /** diff --git a/src/core/services/sites.ts b/src/core/services/sites.ts index 38a35cd28..26e8901b5 100644 --- a/src/core/services/sites.ts +++ b/src/core/services/sites.ts @@ -948,9 +948,13 @@ export class CoreSitesProvider { } else { // Retrieve and create the site. const db = await this.appDB; - const data = await db.getRecord(SITES_TABLE_NAME, { id: siteId }); + try { + const data = await db.getRecord(SITES_TABLE_NAME, { id: siteId }); - return this.makeSiteFromSiteListEntry(data); + return this.makeSiteFromSiteListEntry(data); + } catch { + throw new CoreError('SiteId not found'); + } } }