commit
f519d56ea7
|
@ -6454,7 +6454,7 @@
|
|||
"integrity": "sha512-EYC5eQFVkoYXq39l7tYKE6lEjHJ04mvTmKXxGL7quHLdFPfJMNzru/UYpn92AOfpl3PQaZmou78C7EgmFOwFQQ=="
|
||||
},
|
||||
"cordova-plugin-wkuserscript": {
|
||||
"version": "git+https://github.com/moodlemobile/cordova-plugin-wkuserscript.git#6413f4bb3c2565f353e690b5c1450b69ad9e860e",
|
||||
"version": "git+https://github.com/moodlemobile/cordova-plugin-wkuserscript.git#aa77d0f98a3fb106f2e798e5adf5882f01a2c947",
|
||||
"from": "git+https://github.com/moodlemobile/cordova-plugin-wkuserscript.git"
|
||||
},
|
||||
"cordova-plugin-wkwebview-cookies": {
|
||||
|
|
|
@ -16,7 +16,8 @@ import { Component, OnInit } from '@angular/core';
|
|||
import { NavController } from '@ionic/angular';
|
||||
|
||||
import { CoreLangProvider } from '@services/lang';
|
||||
import { CoreEvents } from '@singletons/events';
|
||||
import { CoreLoginHelperProvider } from '@core/login/services/helper';
|
||||
import { CoreEvents, CoreEventSessionExpiredData } from '@singletons/events';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
|
@ -28,6 +29,7 @@ export class AppComponent implements OnInit {
|
|||
constructor(
|
||||
protected langProvider: CoreLangProvider,
|
||||
protected navCtrl: NavController,
|
||||
protected loginHelper: CoreLoginHelperProvider,
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -46,6 +48,11 @@ export class AppComponent implements OnInit {
|
|||
// @todo
|
||||
// this.removeVersionClass();
|
||||
});
|
||||
|
||||
// Listen for session expired events.
|
||||
CoreEvents.on(CoreEvents.SESSION_EXPIRED, (data: CoreEventSessionExpiredData) => {
|
||||
this.loginHelper.sessionExpired(data);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
<ng-container *ngIf="control && control.dirty && !control.valid">
|
||||
<ng-container *ngFor="let error of errorKeys">
|
||||
<div *ngIf="control.hasError(error)" class="core-input-error">
|
||||
<span *ngIf="errorMessages[error]">{{errorMessages[error]}}</span>
|
||||
<span *ngIf="!errorMessages[error] && error == 'max' && control.errors.max">
|
||||
{{ 'core.login.invalidvaluemax' | translate:{$a: control.errors.max.max} }}
|
||||
<span *ngIf="errorMessages && errorMessages[error]">{{errorMessages[error]}}</span>
|
||||
<span *ngIf="(!errorMessages || !errorMessages[error]) && error == 'max' && control.errors?.max">
|
||||
{{ 'core.login.invalidvaluemax' | translate:{$a: control.errors!.max.max} }}
|
||||
</span>
|
||||
<span *ngIf="!errorMessages[error] && error == 'min' && control.errors.min">
|
||||
{{ 'core.login.invalidvaluemin' | translate:{$a: control.errors.min.min} }}
|
||||
<span *ngIf="(!errorMessages || !errorMessages[error]) && error == 'min' && control.errors?.min">
|
||||
{{ 'core.login.invalidvaluemin' | translate:{$a: control.errors!.min.min} }}
|
||||
</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
|
|
@ -39,21 +39,25 @@ const routes: Routes = [
|
|||
},
|
||||
{
|
||||
path: 'forgottenpassword',
|
||||
loadChildren: () => import('./pages/forgotten-password/forgotten-password.module')
|
||||
loadChildren: () => import('./pages/forgotten-password/forgotten-password.page.module')
|
||||
.then( m => m.CoreLoginForgottenPasswordPageModule),
|
||||
},
|
||||
{
|
||||
path: 'changepassword',
|
||||
loadChildren: () => import('./pages/change-password/change-password.module')
|
||||
loadChildren: () => import('./pages/change-password/change-password.page.module')
|
||||
.then( m => m.CoreLoginChangePasswordPageModule),
|
||||
},
|
||||
{
|
||||
path: 'sitepolicy',
|
||||
loadChildren: () => import('./pages/site-policy/site-policy.module').then( m => m.CoreLoginSitePolicyPageModule),
|
||||
loadChildren: () => import('./pages/site-policy/site-policy.page.module').then( m => m.CoreLoginSitePolicyPageModule),
|
||||
},
|
||||
{
|
||||
path: 'emailsignup',
|
||||
loadChildren: () => import('./pages/email-signup/email-signup.module').then( m => m.CoreLoginEmailSignupPageModule),
|
||||
loadChildren: () => import('./pages/email-signup/email-signup.page.module').then( m => m.CoreLoginEmailSignupPageModule),
|
||||
},
|
||||
{
|
||||
path: 'reconnect',
|
||||
loadChildren: () => import('./pages/reconnect/reconnect.page.module').then( m => m.CoreLoginReconnectPageModule),
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
}
|
||||
|
||||
.core-sitename {
|
||||
font-size: 1.8rem;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.core-login-site-logo {
|
||||
|
|
|
@ -28,7 +28,7 @@ import { CoreSiteIdentityProvider, CoreSitePublicConfigResponse } from '@classes
|
|||
import { CoreEvents } from '@singletons/events';
|
||||
|
||||
/**
|
||||
* Page that displays a "splash screen" while the app is being initialized.
|
||||
* Page to enter the user credentials.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'page-core-login-credentials',
|
||||
|
@ -161,7 +161,7 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy {
|
|||
*/
|
||||
protected treatSiteConfig(): void {
|
||||
if (this.siteConfig) {
|
||||
this.siteName = CoreConstants.CONFIG.sitename ?? this.siteConfig.sitename;
|
||||
this.siteName = CoreConstants.CONFIG.sitename ? CoreConstants.CONFIG.sitename : this.siteConfig.sitename;
|
||||
this.logoUrl = CoreLoginHelper.instance.getLogoUrl(this.siteConfig);
|
||||
this.authInstructions = this.siteConfig.authinstructions || Translate.instance.instant('core.login.loginsteps');
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@
|
|||
<ion-input type="text" name="nameField" placeholder="{{ 'core.user.' + nameField | translate }}"
|
||||
formControlName="{{nameField}}" autocorrect="off">
|
||||
</ion-input>
|
||||
<core-input-errors [control]="signupForm.controls[nameField]" [errorMessages]="namefieldsErrors[nameField]">
|
||||
<core-input-errors [control]="signupForm.controls[nameField]" [errorMessages]="namefieldsErrors![nameField]">
|
||||
</core-input-errors>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap">
|
||||
|
|
|
@ -337,7 +337,7 @@ export class CoreLoginEmailSignupPage implements OnInit {
|
|||
/**
|
||||
* Show authentication instructions.
|
||||
*/
|
||||
protected showAuthInstructions(): void {
|
||||
showAuthInstructions(): void {
|
||||
CoreTextUtils.instance.viewText(Translate.instance.instant('core.login.instructions'), this.authInstructions!);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button></ion-back-button>
|
||||
</ion-buttons>
|
||||
|
||||
<ion-title>{{ 'core.login.reconnect' | translate }}</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<div class="ion-text-wrap ion-text-center ion-margin-bottom" [ngClass]="{'item-avatar-center': showSiteAvatar}">
|
||||
<ng-container *ngIf="showSiteAvatar">
|
||||
<ion-avatar>
|
||||
<!-- Show user avatar. -->
|
||||
<img [src]="userAvatar" class="avatar" core-external-content [siteId]="siteId" role="presentation"
|
||||
alt="{{ 'core.pictureof' | translate:{$a: userFullName} }}" onError="this.src='assets/img/user-avatar.png'">
|
||||
</ion-avatar>
|
||||
</ng-container>
|
||||
|
||||
<div class="core-login-site-logo" *ngIf="!showSiteAvatar">
|
||||
<!-- Show site logo or a default image. -->
|
||||
<img *ngIf="logoUrl" [src]="logoUrl" role="presentation" onError="this.src='assets/img/login_logo.png'">
|
||||
<img *ngIf="!logoUrl" src="assets/img/login_logo.png" role="presentation">
|
||||
</div>
|
||||
|
||||
<h6 *ngIf="siteName" class="ion-padding core-sitename">
|
||||
<core-format-text [text]="siteName" [filter]="false"></core-format-text>
|
||||
</h6>
|
||||
<p class="core-siteurl">{{siteUrl}}</p>
|
||||
|
||||
<ion-item *ngIf="!isLoggedOut" class="ion-text-center core-login-reconnect-warning" lines="none">
|
||||
<ion-label color="danger">
|
||||
<ion-icon name="fas-exclamation-circle" slot="start"></ion-icon>
|
||||
{{ 'core.login.reconnectdescription' | translate }}
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</div>
|
||||
<form ion-list *ngIf="!isOAuth" [formGroup]="credForm" (ngSubmit)="login($event)" class="core-login-form" #reconnectForm>
|
||||
<ion-item class="ion-text-wrap core-username">
|
||||
<ion-label>
|
||||
<p>{{username}}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item class="ion-margin-bottom">
|
||||
<core-show-password [name]="'password'">
|
||||
<ion-input class="core-ioninput-password" name="password" type="password"
|
||||
placeholder="{{ 'core.login.password' | translate }}" formControlName="password" [clearOnEdit]="false">
|
||||
</ion-input>
|
||||
</core-show-password>
|
||||
</ion-item>
|
||||
<ion-grid class="ion-padding">
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<ion-button expand="block" color="light" (click)="cancel($event)">{{ 'core.login.cancel' | translate }}</ion-button>
|
||||
</ion-col>
|
||||
<ion-col>
|
||||
<ion-button type="submit" expand="block" [disabled]="!credForm.valid">{{ 'core.login.loginbutton' | translate }}</ion-button>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
</form>
|
||||
|
||||
<!-- Forgotten password option. -->
|
||||
<ion-list lines="none" *ngIf="showForgottenPassword && !isOAuth" class="core-login-forgotten-password ion-no-padding">
|
||||
<ion-item button class="ion-text-center ion-text-wrap" (click)="forgottenPassword()" detail="false">
|
||||
<ion-label>
|
||||
{{ 'core.login.forgotten' | translate }}
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
<!-- Identity providers. -->
|
||||
<ion-list *ngIf="identityProviders && identityProviders.length" class="ion-padding-top core-login-identity-providers">
|
||||
<ion-item class="ion-text-wrap" lines="none">
|
||||
<ion-label><h3 class="item-heading">{{ 'core.login.potentialidps' | translate }}</h3></ion-label>
|
||||
</ion-item>
|
||||
<ion-item button *ngFor="let provider of identityProviders" class="ion-text-wrap core-oauth-icon"
|
||||
(click)="oauthClicked(provider)" title="{{provider.name}}">
|
||||
<img [src]="provider.iconurl" alt="" width="32" height="32" slot="start">
|
||||
<ion-label>{{provider.name}}</ion-label>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
<!-- If OAuth, display cancel button since the form isn't displayed. -->
|
||||
<ion-list *ngIf="isOAuth">
|
||||
<ion-button expand="block" class="ion-margin" color="light" (click)="cancel($event)">
|
||||
{{ 'core.login.cancel' | translate }}
|
||||
</ion-button>
|
||||
</ion-list>
|
||||
</ion-content>
|
|
@ -0,0 +1,50 @@
|
|||
// (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 { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
|
||||
import { CoreLoginReconnectPage } from './reconnect.page';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: CoreLoginReconnectPage,
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild(routes),
|
||||
CommonModule,
|
||||
IonicModule,
|
||||
TranslateModule.forChild(),
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
CoreComponentsModule,
|
||||
CoreDirectivesModule,
|
||||
],
|
||||
declarations: [
|
||||
CoreLoginReconnectPage,
|
||||
],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class CoreLoginReconnectPageModule {}
|
|
@ -0,0 +1,245 @@
|
|||
// (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 { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core';
|
||||
import { ActivatedRoute, Params } from '@angular/router';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
import { CoreApp } from '@services/app';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreLoginHelper } from '@core/login/services/helper';
|
||||
import { CoreSiteIdentityProvider, CoreSitePublicConfigResponse } from '@classes/site';
|
||||
import { CoreEvents } from '@singletons/events';
|
||||
import { CoreError } from '@classes/errors/error';
|
||||
|
||||
/**
|
||||
* Page to enter the user password to reconnect to a site.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'page-core-login-reconnect',
|
||||
templateUrl: 'reconnect.html',
|
||||
styleUrls: ['../../login.scss'],
|
||||
})
|
||||
export class CoreLoginReconnectPage implements OnInit, OnDestroy {
|
||||
|
||||
@ViewChild('reconnectForm') formElement?: ElementRef;
|
||||
|
||||
credForm: FormGroup;
|
||||
siteUrl!: string;
|
||||
username!: string;
|
||||
userFullName!: string;
|
||||
userAvatar?: string;
|
||||
siteName!: string;
|
||||
logoUrl?: string;
|
||||
identityProviders?: CoreSiteIdentityProvider[];
|
||||
showForgottenPassword = true;
|
||||
showSiteAvatar = false;
|
||||
isOAuth = false;
|
||||
isLoggedOut: boolean;
|
||||
siteId!: string;
|
||||
|
||||
protected page?: string;
|
||||
protected pageParams?: Params;
|
||||
protected siteConfig?: CoreSitePublicConfigResponse;
|
||||
protected viewLeft = false;
|
||||
protected eventThrown = false;
|
||||
|
||||
constructor(
|
||||
protected navCtrl: NavController,
|
||||
protected fb: FormBuilder,
|
||||
protected route: ActivatedRoute,
|
||||
) {
|
||||
|
||||
const currentSite = CoreSites.instance.getCurrentSite();
|
||||
|
||||
this.isLoggedOut = !!currentSite?.isLoggedOut();
|
||||
this.credForm = fb.group({
|
||||
password: ['', Validators.required],
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the component.
|
||||
*/
|
||||
async ngOnInit(): Promise<void> {
|
||||
const params = this.route.snapshot.queryParams;
|
||||
|
||||
this.siteId = params['siteId'];
|
||||
this.page = params['pageName'];
|
||||
this.pageParams = params['pageParams'];
|
||||
|
||||
try {
|
||||
const site = await CoreSites.instance.getSite(this.siteId);
|
||||
|
||||
if (!site.infos) {
|
||||
throw new CoreError('Invalid site');
|
||||
}
|
||||
|
||||
this.username = site.infos.username;
|
||||
this.userFullName = site.infos.fullname;
|
||||
this.userAvatar = site.infos.userpictureurl;
|
||||
this.siteUrl = site.infos.siteurl;
|
||||
this.siteName = site.getSiteName();
|
||||
|
||||
// If login was OAuth we should only reach this page if the OAuth method ID has changed.
|
||||
this.isOAuth = site.isOAuth();
|
||||
|
||||
// Show logo instead of avatar if it's a fixed site.
|
||||
this.showSiteAvatar = !!this.userAvatar && !CoreLoginHelper.instance.getFixedSites();
|
||||
|
||||
const config = await CoreUtils.instance.ignoreErrors(site.getPublicConfig());
|
||||
|
||||
if (!config) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.siteConfig = config;
|
||||
|
||||
await CoreSites.instance.checkRequiredMinimumVersion(config);
|
||||
|
||||
// Check logoURL if user avatar is not set.
|
||||
if (this.userAvatar.startsWith(this.siteUrl + '/theme/image.php')) {
|
||||
this.showSiteAvatar = false;
|
||||
}
|
||||
this.logoUrl = CoreLoginHelper.instance.getLogoUrl(config);
|
||||
|
||||
this.getDataFromConfig(this.siteConfig);
|
||||
} catch (error) {
|
||||
// Just leave the view.
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Component destroyed.
|
||||
*/
|
||||
ngOnDestroy(): void {
|
||||
this.viewLeft = true;
|
||||
CoreEvents.trigger(CoreEvents.LOGIN_SITE_UNCHECKED, { config: this.siteConfig }, this.siteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get some data (like identity providers) from the site config.
|
||||
*
|
||||
* @param config Config to use.
|
||||
*/
|
||||
protected getDataFromConfig(config: CoreSitePublicConfigResponse): void {
|
||||
const disabledFeatures = CoreLoginHelper.instance.getDisabledFeatures(config);
|
||||
|
||||
this.identityProviders = CoreLoginHelper.instance.getValidIdentityProviders(config, disabledFeatures);
|
||||
this.showForgottenPassword = !CoreLoginHelper.instance.isForgottenPasswordDisabled(config);
|
||||
|
||||
if (!this.eventThrown && !this.viewLeft) {
|
||||
this.eventThrown = true;
|
||||
CoreEvents.trigger(CoreEvents.LOGIN_SITE_CHECKED, { config: config });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel reconnect.
|
||||
*
|
||||
* @param e Event.
|
||||
*/
|
||||
cancel(e?: Event): void {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
CoreSites.instance.logout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to authenticate the user.
|
||||
*
|
||||
* @param e Event.
|
||||
*/
|
||||
async login(e: Event): Promise<void> {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
CoreApp.instance.closeKeyboard();
|
||||
|
||||
// Get input data.
|
||||
const password = this.credForm.value.password;
|
||||
|
||||
if (!password) {
|
||||
CoreDomUtils.instance.showErrorModal('core.login.passwordrequired', true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CoreApp.instance.isOnline()) {
|
||||
CoreDomUtils.instance.showErrorModal('core.networkerrormsg', true);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const modal = await CoreDomUtils.instance.showModalLoading();
|
||||
|
||||
try {
|
||||
// Start the authentication process.
|
||||
const data = await CoreSites.instance.getUserToken(this.siteUrl, this.username, password);
|
||||
|
||||
await CoreSites.instance.updateSiteToken(this.siteUrl, this.username, data.token, data.privateToken);
|
||||
|
||||
CoreDomUtils.instance.triggerFormSubmittedEvent(this.formElement, true);
|
||||
|
||||
// Update site info too.
|
||||
await CoreSites.instance.updateSiteInfoByUrl(this.siteUrl, this.username);
|
||||
|
||||
// Reset fields so the data is not in the view anymore.
|
||||
this.credForm.controls['password'].reset();
|
||||
|
||||
// Go to the site initial page.
|
||||
await CoreLoginHelper.instance.goToSiteInitialPage({
|
||||
redirectPage: this.page,
|
||||
redirectParams: this.pageParams,
|
||||
});
|
||||
} catch (error) {
|
||||
CoreLoginHelper.instance.treatUserTokenError(this.siteUrl, error, this.username, password);
|
||||
|
||||
if (error.loggedout) {
|
||||
this.cancel();
|
||||
} else if (error.errorcode == 'forcepasswordchangenotice') {
|
||||
// Reset password field.
|
||||
this.credForm.controls.password.reset();
|
||||
}
|
||||
} finally {
|
||||
modal.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forgotten password button clicked.
|
||||
*/
|
||||
forgottenPassword(): void {
|
||||
CoreLoginHelper.instance.forgottenPasswordClicked(this.siteUrl, this.username, this.siteConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* An OAuth button was clicked.
|
||||
*
|
||||
* @param provider The provider that was clicked.
|
||||
*/
|
||||
oauthClicked(provider: CoreSiteIdentityProvider): void {
|
||||
if (!CoreLoginHelper.instance.openBrowserForOAuthLogin(this.siteUrl, provider, this.siteConfig?.launchurl)) {
|
||||
CoreDomUtils.instance.showErrorModal('Invalid data.');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -35,6 +35,7 @@ import { makeSingleton, Translate } from '@singletons/core.singletons';
|
|||
import { CoreLogger } from '@singletons/logger';
|
||||
import { CoreUrl } from '@singletons/url';
|
||||
import { NavigationOptions } from '@ionic/angular/providers/nav-controller';
|
||||
import { CoreObject } from '@/app/singletons/object';
|
||||
|
||||
/**
|
||||
* Helper provider that provides some common features regarding authentication.
|
||||
|
@ -126,7 +127,7 @@ export class CoreLoginHelperProvider {
|
|||
const currentSite = CoreSites.instance.getCurrentSite();
|
||||
const currentPage = CoreApp.instance.getCurrentPage();
|
||||
|
||||
if (!CoreApp.instance.isSSOAuthenticationOngoing() && currentSite?.isLoggedOut() && currentPage == 'login/reconnect') {
|
||||
if (!CoreApp.instance.isSSOAuthenticationOngoing() && currentSite?.isLoggedOut() && currentPage == '/login/reconnect') {
|
||||
// User must reauthenticate but he closed the InAppBrowser without doing so, logout him.
|
||||
CoreSites.instance.logout();
|
||||
}
|
||||
|
@ -1106,14 +1107,11 @@ export class CoreLoginHelperProvider {
|
|||
this.isOpeningReconnect = true;
|
||||
|
||||
await CoreUtils.instance.ignoreErrors(this.navCtrl.navigateRoot('/login/reconnect', {
|
||||
queryParams: {
|
||||
infoSiteUrl: info.siteurl,
|
||||
siteUrl: result.siteUrl,
|
||||
siteId: siteId,
|
||||
queryParams: CoreObject.removeUndefined({
|
||||
siteId,
|
||||
pageName: data.pageName,
|
||||
pageParams: data.params,
|
||||
siteConfig: result.config,
|
||||
},
|
||||
}),
|
||||
}));
|
||||
|
||||
this.isOpeningReconnect = false;
|
||||
|
|
|
@ -20,6 +20,7 @@ import { TranslateModule } from '@ngx-translate/core';
|
|||
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
import { CorePipesModule } from '@pipes/pipes.module';
|
||||
|
||||
import { CoreSettingsDeviceInfoPage } from './deviceinfo.page';
|
||||
|
||||
|
@ -38,6 +39,7 @@ const routes: Routes = [
|
|||
TranslateModule.forChild(),
|
||||
CoreComponentsModule,
|
||||
CoreDirectivesModule,
|
||||
CorePipesModule,
|
||||
],
|
||||
declarations: [
|
||||
CoreSettingsDeviceInfoPage,
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { NavController } from '@ionic/angular';
|
||||
import { WKUserScriptWindow, WKUserScriptInjectionTime } from 'cordova-plugin-wkuserscript';
|
||||
import { WKUserScriptWindow } from 'cordova-plugin-wkuserscript';
|
||||
import { WKWebViewCookiesWindow } from 'cordova-plugin-wkwebview-cookies';
|
||||
|
||||
import { CoreApp } from '@services/app';
|
||||
|
@ -470,7 +470,7 @@ export class CoreIframeUtilsProvider {
|
|||
userScriptWindow.WKUserScript?.addScript({
|
||||
id: 'CoreIframeUtilsRecaptchaScript',
|
||||
file: recaptchaPath,
|
||||
injectionTime: WKUserScriptInjectionTime.END,
|
||||
injectionTime: userScriptWindow.WKUserScript?.InjectionTime.END,
|
||||
});
|
||||
|
||||
// Handle post messages received by iframes.
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
// (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.
|
||||
|
||||
/**
|
||||
* Singleton with helper functions for objects.
|
||||
*/
|
||||
export class CoreObject {
|
||||
|
||||
/**
|
||||
* Delete all keys from an object whose value are null or undefined.
|
||||
*
|
||||
* @param object Object to modify.
|
||||
*/
|
||||
static removeUndefined<T>(object: T): T {
|
||||
for (const name in object) {
|
||||
if (object[name] === undefined) {
|
||||
delete object[name];
|
||||
}
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue