MOBILE-3846 core: Don't allow using sites not present in config

main
Dani Palou 2021-08-27 10:14:49 +02:00
parent 83d5282852
commit e9506a106f
12 changed files with 116 additions and 10 deletions

View File

@ -1902,6 +1902,7 @@
"core.login.sitebadgedescription": "local_moodlemobileapp",
"core.login.sitehasredirect": "local_moodlemobileapp",
"core.login.siteinmaintenance": "local_moodlemobileapp",
"core.login.sitenotallowed": "local_moodlemobileapp",
"core.login.sitepolicynotagreederror": "local_moodlemobileapp",
"core.login.siteurl": "local_moodlemobileapp",
"core.login.siteurlrequired": "local_moodlemobileapp",

View File

@ -23,6 +23,7 @@ import { CoreAjaxWSError } from './ajaxwserror';
import { CoreCaptureError } from './captureerror';
import { CoreNetworkError } from './network-error';
import { CoreSiteError } from './siteerror';
import { CoreErrorWithTitle } from './errorwithtitle';
export const CORE_ERRORS_CLASSES: Type<unknown>[] = [
CoreAjaxError,
@ -34,4 +35,5 @@ export const CORE_ERRORS_CLASSES: Type<unknown>[] = [
CoreSilentError,
CoreSiteError,
CoreWSError,
CoreErrorWithTitle,
];

View File

@ -12,8 +12,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { CoreUpdateManager } from '@services/update-manager';
import { CoreError } from './error';
/**
* Error with an explicit title describing the problem (instead of just "Error" or a generic message).
* This title should be used to communicate the problem with users, and if it's undefined it should be omitted.
*/
export class CoreErrorWithTitle extends CoreError {
title?: string;
constructor(message?: string, title?: string) {
super(message);
this.title = title;
}
export default async function(): Promise<void> {
await CoreUpdateManager.load();
}

View File

@ -108,6 +108,7 @@
"sitebadgedescription": "There are {{count}} unread notifications.",
"sitehasredirect": "Your site contains at least one HTTP redirect. The app cannot follow redirects, this could be the issue that's preventing the app from connecting to your site.",
"siteinmaintenance": "Your site is in maintenance mode",
"sitenotallowed": "This site is no longer available.",
"sitepolicynotagreederror": "Site policy not agreed.",
"siteurl": "Site URL",
"siteurlrequired": "Site URL required i.e <i>http://www.yourmoodlesite.org</i>",

View File

@ -49,6 +49,10 @@ export class CoreLoginSitesPage implements OnInit {
* @return Promise resolved when done.
*/
async ngOnInit(): Promise<void> {
if (CoreNavigator.getRouteBooleanParam('openAddSite')) {
this.add();
}
const sites = await CoreUtils.ignoreErrors(CoreSites.getSortedSites(), [] as CoreSiteBasicInfo[]);
// Remove protocol from the url to show more url text.

View File

@ -573,9 +573,10 @@ export class CoreLoginHelperProvider {
* Check if a site URL is "allowed". In case the app has fixed sites, only those will be allowed to connect to.
*
* @param siteUrl Site URL to check.
* @param checkSiteFinder Whether to check site finder if needed. Defaults to true.
* @return Promise resolved with boolean: whether is one of the fixed sites.
*/
async isSiteUrlAllowed(siteUrl: string): Promise<boolean> {
async isSiteUrlAllowed(siteUrl: string, checkSiteFinder = true): Promise<boolean> {
if (this.isFixedUrlSet()) {
// Only 1 site allowed.
return CoreUrl.sameDomainAndPath(siteUrl, <string> this.getFixedSites());
@ -583,7 +584,8 @@ export class CoreLoginHelperProvider {
const sites = <CoreLoginSiteInfo[]> this.getFixedSites();
return sites.some((site) => CoreUrl.sameDomainAndPath(siteUrl, site.url));
} else if (CoreConstants.CONFIG.multisitesdisplay == 'sitefinder' && CoreConstants.CONFIG.onlyallowlistedsites) {
} else if (CoreConstants.CONFIG.multisitesdisplay == 'sitefinder' && CoreConstants.CONFIG.onlyallowlistedsites &&
checkSiteFinder) {
// Call the sites finder to validate the site.
const result = await CoreSites.findSites(siteUrl.replace(/^https?:\/\/|\.\w{2,3}\/?$/g, ''));

View File

@ -13,7 +13,10 @@
// limitations under the License.
import { CoreApp } from '@services/app';
import { CoreUpdateManager } from '@services/update-manager';
export default async function(): Promise<void> {
await CoreUpdateManager.donePromise;
export default function(): void {
CoreApp.consumeStorageRedirect();
}

View File

@ -15,11 +15,13 @@
import { CoreFilepool } from '@services/filepool';
import { CoreLang } from '@services/lang';
import { CoreLocalNotifications } from '@services/local-notifications';
import { CoreUpdateManager } from '@services/update-manager';
export default async function(): Promise<void> {
await Promise.all([
CoreFilepool.initialize(),
CoreLang.initialize(),
CoreLocalNotifications.initialize(),
CoreUpdateManager.initialize(),
]);
}

View File

@ -13,7 +13,10 @@
// limitations under the License.
import { CoreSites } from '@services/sites';
import { CoreUpdateManager } from '@services/update-manager';
export default async function(): Promise<void> {
await CoreUpdateManager.donePromise;
await CoreSites.restoreSession();
}

View File

@ -53,6 +53,8 @@ import { CoreNetworkError } from '@classes/errors/network-error';
import { CoreNavigationOptions } from './navigator';
import { CoreSitesFactory } from './sites-factory';
import { CoreText } from '@singletons/text';
import { CoreLoginHelper } from '@features/login/services/login-helper';
import { CoreErrorWithTitle } from '@classes/errors/errorwithtitle';
export const CORE_SITE_SCHEMAS = new InjectionToken<CoreSiteSchema[]>('CORE_SITE_SCHEMAS');
@ -823,6 +825,11 @@ export class CoreSitesProvider {
const site = await this.getSite(siteId);
const siteUrlAllowed = await CoreLoginHelper.isSiteUrlAllowed(site.getURL(), false);
if (!siteUrlAllowed) {
throw new CoreErrorWithTitle(Translate.instant('core.login.sitenotallowed'));
}
this.currentSite = site;
if (site.isLoggedOut()) {
@ -1196,8 +1203,6 @@ export class CoreSitesProvider {
return;
}
const db = await this.appDB;
const promises: Promise<unknown>[] = [];
const siteConfig = this.currentSite.getStoredConfig();
const siteId = this.currentSite.getId();
@ -1208,7 +1213,7 @@ export class CoreSitesProvider {
promises.push(this.setSiteLoggedOut(siteId, true));
}
promises.push(db.deleteRecords(CURRENT_SITE_TABLE_NAME, { id: 1 }));
promises.push(this.removeStoredCurrentSite());
await CoreUtils.ignoreErrors(Promise.all(promises));
@ -1449,6 +1454,17 @@ export class CoreSitesProvider {
return currentSite.siteId;
}
/**
* Remove current site stored in DB.
*
* @return Promise resolved when done.
*/
async removeStoredCurrentSite(): Promise<void> {
const db = await this.appDB;
await db.deleteRecords(CURRENT_SITE_TABLE_NAME, { id: 1 });
}
/**
* Get the public config of a certain site.
*

View File

@ -19,6 +19,10 @@ import { CoreConstants } from '@/core/constants';
import { CoreLogger } from '@singletons/logger';
import { makeSingleton } from '@singletons';
import { CoreH5P } from '@features/h5p/services/h5p';
import { CoreLoginHelper } from '@features/login/services/login-helper';
import { CoreSites } from './sites';
import { CoreUtils, PromiseDefer } from './utils/utils';
import { CoreApp } from './app';
const VERSION_APPLIED = 'version_applied';
@ -31,9 +35,20 @@ const VERSION_APPLIED = 'version_applied';
export class CoreUpdateManagerProvider {
protected logger: CoreLogger;
protected doneDeferred: PromiseDefer<void>;
constructor() {
this.logger = CoreLogger.getInstance('CoreUpdateManagerProvider');
this.doneDeferred = CoreUtils.promiseDefer();
}
/**
* Returns a promise resolved when the load function is done.
*
* @return Promise resolved when the load function is done.
*/
get donePromise(): Promise<void> {
return this.doneDeferred.promise;
}
/**
@ -42,12 +57,16 @@ export class CoreUpdateManagerProvider {
*
* @return Promise resolved when the update process finishes.
*/
async load(): Promise<void> {
async initialize(): Promise<void> {
const promises: Promise<unknown>[] = [];
const versionCode = CoreConstants.CONFIG.versioncode;
const versionApplied = await CoreConfig.get<number>(VERSION_APPLIED, 0);
if (versionCode > versionApplied) {
promises.push(this.checkCurrentSiteAllowed());
}
if (versionCode >= 3950 && versionApplied < 3950 && versionApplied > 0) {
promises.push(CoreH5P.h5pPlayer.deleteAllContentIndexes());
}
@ -58,9 +77,47 @@ export class CoreUpdateManagerProvider {
await CoreConfig.set(VERSION_APPLIED, versionCode);
} catch (error) {
this.logger.error(`Error applying update from ${versionApplied} to ${versionCode}`, error);
} finally {
this.doneDeferred.resolve();
}
}
/**
* If there is a current site, check if it's still supported in the new app.
*
* @return Promise resolved when done.
*/
protected async checkCurrentSiteAllowed(): Promise<void> {
if (!CoreLoginHelper.getFixedSites()) {
return;
}
const currentSiteId = await CoreUtils.ignoreErrors(CoreSites.getStoredCurrentSiteId());
if (!currentSiteId) {
return;
}
const site = await CoreUtils.ignoreErrors(CoreSites.getSite(currentSiteId));
if (!site) {
return;
}
const isUrlAllowed = await CoreLoginHelper.isSiteUrlAllowed(site.getURL(), false);
if (isUrlAllowed) {
return;
}
// Site no longer supported, remove it as current site.
await CoreSites.removeStoredCurrentSite();
// Tell the app to open add site so the user can add the new site.
CoreApp.storeRedirect(CoreConstants.NO_SITE_ID, '/login/sites', {
params: {
openAddSite: true,
},
});
}
}
export const CoreUpdateManager = makeSingleton(CoreUpdateManagerProvider);

View File

@ -38,6 +38,7 @@ import { CoreViewerImageComponent } from '@features/viewer/components/image/imag
import { CoreFormFields, CoreForms } from '../../singletons/form';
import { CoreModalLateralTransitionEnter, CoreModalLateralTransitionLeave } from '@classes/modal-lateral-transition';
import { CoreZoomLevel } from '@features/settings/services/settings-helper';
import { CoreErrorWithTitle } from '@classes/errors/errorwithtitle';
/*
* "Utils" service with helper functions for UI, DOM elements and HTML code.
@ -1376,6 +1377,8 @@ export class CoreDomUtilsProvider {
if (this.isNetworkError(message, error)) {
alertOptions.cssClass = 'core-alert-network-error';
} else if (error instanceof CoreErrorWithTitle) {
alertOptions.header = error.title || undefined;
} else {
alertOptions.header = Translate.instant('core.error');
}