Merge pull request #3427 from dpalou/MOBILE-4168
MOBILE-4168 core: Send to reconnect page in auth guardmain
commit
5153d7f020
|
@ -10,94 +10,103 @@
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
<ion-content class="ion-padding" (keydown)="keyDown($event)" (keyup)="keyUp($event)">
|
<ion-content class="ion-padding" (keydown)="keyDown($event)" (keyup)="keyUp($event)">
|
||||||
<div class="list-item-limited-width">
|
<core-loading [hideUntil]="!showLoading">
|
||||||
<div class="ion-text-wrap ion-text-center ion-margin-bottom" [ngClass]="{'item-avatar-center': showSiteAvatar}">
|
<div class="list-item-limited-width">
|
||||||
<!-- Show user avatar. -->
|
<div class="ion-text-wrap ion-text-center ion-margin-bottom" [ngClass]="{'item-avatar-center': showSiteAvatar}">
|
||||||
<img *ngIf="showSiteAvatar" [src]="userAvatar" class="large-avatar" core-external-content [siteId]="siteId"
|
<!-- Show user avatar. -->
|
||||||
alt="{{ 'core.pictureof' | translate:{$a: userFullName} }}" onError="this.src='assets/img/user-avatar.png'">
|
<img *ngIf="showSiteAvatar" [src]="userAvatar" class="large-avatar" core-external-content [siteId]="siteId"
|
||||||
|
alt="{{ 'core.pictureof' | translate:{$a: userFullName} }}" onError="this.src='assets/img/user-avatar.png'">
|
||||||
|
|
||||||
<div class="core-login-site-logo" *ngIf="!showSiteAvatar">
|
<div class="core-login-site-logo" *ngIf="!showSiteAvatar">
|
||||||
<!-- Show site logo or a default image. -->
|
<!-- Show site logo or a default image. -->
|
||||||
<img *ngIf="logoUrl" [src]="logoUrl" role="presentation" onError="this.src='assets/img/login_logo.png'" alt="">
|
<img *ngIf="logoUrl" [src]="logoUrl" role="presentation" onError="this.src='assets/img/login_logo.png'" alt="">
|
||||||
<img *ngIf="!logoUrl" src="assets/img/login_logo.png" role="presentation" alt="">
|
<img *ngIf="!logoUrl" src="assets/img/login_logo.png" role="presentation" alt="">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p *ngIf="siteName" class="ion-padding core-sitename">
|
||||||
|
<core-format-text [text]="siteName" [filter]="false"></core-format-text>
|
||||||
|
</p>
|
||||||
|
<p class="core-siteurl">{{siteUrl}}</p>
|
||||||
|
|
||||||
|
<ion-card *ngIf="!isLoggedOut" class="core-danger-card core-login-reconnect-warning">
|
||||||
|
<ion-item>
|
||||||
|
<ion-icon name="fas-exclamation-circle" slot="start" aria-hidden="true"></ion-icon>
|
||||||
|
<ion-label>
|
||||||
|
<p>{{ 'core.lostconnection' | translate }}</p>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ion-card>
|
||||||
</div>
|
</div>
|
||||||
|
<form *ngIf="!isOAuth" [formGroup]="credForm" (ngSubmit)="login($event)" class="core-login-form" #reconnectForm>
|
||||||
<p *ngIf="siteName" class="ion-padding core-sitename">
|
<ion-item class="ion-text-wrap core-username item-interactive">
|
||||||
<core-format-text [text]="siteName" [filter]="false"></core-format-text>
|
|
||||||
</p>
|
|
||||||
<p class="core-siteurl">{{siteUrl}}</p>
|
|
||||||
|
|
||||||
<ion-card *ngIf="!isLoggedOut" class="core-danger-card core-login-reconnect-warning">
|
|
||||||
<ion-item>
|
|
||||||
<ion-icon name="fas-exclamation-circle" slot="start" aria-hidden="true"></ion-icon>
|
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p>{{ 'core.lostconnection' | translate }}</p>
|
<p>{{username}}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ion-card>
|
<ion-item class="ion-margin-bottom" *ngIf="!isBrowserSSO">
|
||||||
</div>
|
<ion-label class="sr-only">{{ 'core.login.password' | translate }}</ion-label>
|
||||||
<form *ngIf="!isOAuth" [formGroup]="credForm" (ngSubmit)="login($event)" class="core-login-form" #reconnectForm>
|
<core-show-password name="password">
|
||||||
<ion-item class="ion-text-wrap core-username item-interactive">
|
<ion-input class="core-ioninput-password" name="password" type="password"
|
||||||
<ion-label>
|
placeholder="{{ 'core.login.password' | translate }}" formControlName="password" [clearOnEdit]="false"
|
||||||
<p>{{username}}</p>
|
autocomplete="current-password" enterkeyhint="go" required="true">
|
||||||
</ion-label>
|
</ion-input>
|
||||||
</ion-item>
|
</core-show-password>
|
||||||
<ion-item class="ion-margin-bottom">
|
</ion-item>
|
||||||
<ion-label class="sr-only">{{ 'core.login.password' | translate }}</ion-label>
|
<div class="adaptable-buttons-row">
|
||||||
<core-show-password name="password">
|
<ion-button expand="block" fill="outline" (click)="cancel($event)" class="ion-margin ion-text-wrap">
|
||||||
<ion-input class="core-ioninput-password" name="password" type="password"
|
{{ 'core.login.cancel' | translate }}
|
||||||
placeholder="{{ 'core.login.password' | translate }}" formControlName="password" [clearOnEdit]="false"
|
</ion-button>
|
||||||
autocomplete="current-password" enterkeyhint="go" required="true">
|
<ion-button *ngIf="!isBrowserSSO" type="submit" expand="block" [disabled]="!credForm.valid"
|
||||||
</ion-input>
|
class="ion-margin core-login-login-button ion-text-wrap">
|
||||||
</core-show-password>
|
{{ 'core.login.loginbutton' | translate }}
|
||||||
</ion-item>
|
</ion-button>
|
||||||
<div class="adaptable-buttons-row">
|
</div>
|
||||||
<ion-button expand="block" fill="outline" (click)="cancel($event)" class="ion-margin ion-text-wrap">
|
|
||||||
{{ 'core.login.cancel' | translate }}
|
<ion-button expand="block" *ngIf="isBrowserSSO" (click)="openBrowserSSO()"
|
||||||
</ion-button>
|
|
||||||
<ion-button type="submit" expand="block" [disabled]="!credForm.valid"
|
|
||||||
class="ion-margin core-login-login-button ion-text-wrap">
|
class="ion-margin core-login-login-button ion-text-wrap">
|
||||||
{{ 'core.login.loginbutton' | translate }}
|
{{ 'core.login.loginbutton' | translate }}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</div>
|
|
||||||
|
|
||||||
<ng-container *ngIf="showScanQR">
|
<ng-container *ngIf="showScanQR && !isBrowserSSO">
|
||||||
<div class="ion-text-center ion-padding core-login-site-qrcode-separator">{{ 'core.login.or' | translate }}</div>
|
<div class="ion-text-center ion-padding core-login-site-qrcode-separator">{{ 'core.login.or' | translate }}</div>
|
||||||
<ion-button expand="block" fill="outline" class="ion-margin core-login-site-qrcode" (click)="showInstructionsAndScanQR()">
|
<ion-button expand="block" fill="outline" class="ion-margin core-login-site-qrcode"
|
||||||
<ion-icon slot="start" name="fas-qrcode" aria-hidden="true"></ion-icon>
|
(click)="showInstructionsAndScanQR()">
|
||||||
{{ 'core.scanqr' | translate }}
|
<ion-icon slot="start" name="fas-qrcode" aria-hidden="true"></ion-icon>
|
||||||
|
{{ 'core.scanqr' | translate }}
|
||||||
|
</ion-button>
|
||||||
|
</ng-container>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<!-- Forgotten password option. -->
|
||||||
|
<ion-button *ngIf="showForgottenPassword && !isOAuth" expand="block" fill="clear"
|
||||||
|
class="core-login-forgotten-password core-button-as-link ion-text-wrap" (click)="forgottenPassword()">
|
||||||
|
{{ 'core.login.forgotten' | translate }}
|
||||||
|
</ion-button>
|
||||||
|
|
||||||
|
<!-- Login methods -->
|
||||||
|
<core-login-methods></core-login-methods>
|
||||||
|
|
||||||
|
<!-- Identity providers. -->
|
||||||
|
<ion-list *ngIf="identityProviders?.length" class="ion-padding-top core-login-identity-providers">
|
||||||
|
<ion-item class="ion-text-wrap">
|
||||||
|
<ion-label>
|
||||||
|
<h3 class="item-heading">{{ 'core.login.potentialidps' | translate }}</h3>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
<ion-button [fill]="'outline'" *ngFor="let provider of identityProviders"
|
||||||
|
class="ion-text-wrap ion-margin core-oauth-provider" (click)="oauthClicked(provider)" [attr.aria-label]="provider.name"
|
||||||
|
expand="block">
|
||||||
|
<img [src]="provider.iconurl" alt="" width="32" height="32" slot="start">
|
||||||
|
<ion-label>{{ provider.name }}</ion-label>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ng-container>
|
</ion-list>
|
||||||
</form>
|
|
||||||
|
|
||||||
<!-- Forgotten password option. -->
|
<!-- If OAuth, display cancel button since the form isn't displayed. -->
|
||||||
<ion-button *ngIf="showForgottenPassword && !isOAuth" expand="block" fill="clear"
|
<ion-list *ngIf="isOAuth">
|
||||||
class="core-login-forgotten-password core-button-as-link ion-text-wrap" (click)="forgottenPassword()">
|
<ion-button expand="block" class="ion-margin" fill="outline" (click)="cancel($event)">
|
||||||
{{ 'core.login.forgotten' | translate }}
|
{{ 'core.login.cancel' | translate }}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
</ion-list>
|
||||||
<!-- Login methods -->
|
</div>
|
||||||
<core-login-methods></core-login-methods>
|
</core-loading>
|
||||||
|
|
||||||
<!-- Identity providers. -->
|
|
||||||
<ion-list *ngIf="identityProviders?.length" class="ion-padding-top core-login-identity-providers">
|
|
||||||
<ion-item class="ion-text-wrap">
|
|
||||||
<ion-label>
|
|
||||||
<h3 class="item-heading">{{ 'core.login.potentialidps' | translate }}</h3>
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
<ion-button [fill]="'outline'" *ngFor="let provider of identityProviders" class="ion-text-wrap ion-margin core-oauth-provider"
|
|
||||||
(click)="oauthClicked(provider)" [attr.aria-label]="provider.name" expand="block">
|
|
||||||
<img [src]="provider.iconurl" alt="" width="32" height="32" slot="start">
|
|
||||||
<ion-label>{{ provider.name }}</ion-label>
|
|
||||||
</ion-button>
|
|
||||||
</ion-list>
|
|
||||||
|
|
||||||
<!-- If OAuth, display cancel button since the form isn't displayed. -->
|
|
||||||
<ion-list *ngIf="isOAuth">
|
|
||||||
<ion-button expand="block" class="ion-margin" fill="outline" (click)="cancel($event)">
|
|
||||||
{{ 'core.login.cancel' | translate }}
|
|
||||||
</ion-button>
|
|
||||||
</ion-list>
|
|
||||||
</div>
|
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|
|
@ -49,10 +49,12 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy {
|
||||||
identityProviders?: CoreSiteIdentityProvider[];
|
identityProviders?: CoreSiteIdentityProvider[];
|
||||||
showForgottenPassword = true;
|
showForgottenPassword = true;
|
||||||
showSiteAvatar = false;
|
showSiteAvatar = false;
|
||||||
|
isBrowserSSO = false;
|
||||||
isOAuth = false;
|
isOAuth = false;
|
||||||
isLoggedOut: boolean;
|
isLoggedOut: boolean;
|
||||||
siteId!: string;
|
siteId!: string;
|
||||||
showScanQR = false;
|
showScanQR = false;
|
||||||
|
showLoading = true;
|
||||||
|
|
||||||
protected siteConfig?: CoreSitePublicConfigResponse;
|
protected siteConfig?: CoreSitePublicConfigResponse;
|
||||||
protected viewLeft = false;
|
protected viewLeft = false;
|
||||||
|
@ -107,6 +109,8 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy {
|
||||||
this.showSiteAvatar = !!this.userAvatar && !CoreLoginHelper.getFixedSites();
|
this.showSiteAvatar = !!this.userAvatar && !CoreLoginHelper.getFixedSites();
|
||||||
|
|
||||||
this.checkSiteConfig(site);
|
this.checkSiteConfig(site);
|
||||||
|
|
||||||
|
this.showLoading = false;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
CoreDomUtils.showErrorModal(error);
|
CoreDomUtils.showErrorModal(error);
|
||||||
|
|
||||||
|
@ -151,6 +155,7 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy {
|
||||||
CoreEvents.trigger(CoreEvents.LOGIN_SITE_CHECKED, { config: this.siteConfig });
|
CoreEvents.trigger(CoreEvents.LOGIN_SITE_CHECKED, { config: this.siteConfig });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.isBrowserSSO = !this.isOAuth && CoreLoginHelper.isSSOLoginNeeded(this.siteConfig.typeoflogin);
|
||||||
this.showScanQR = CoreLoginHelper.displayQRInSiteScreen() ||
|
this.showScanQR = CoreLoginHelper.displayQRInSiteScreen() ||
|
||||||
CoreLoginHelper.displayQRInCredentialsScreen(this.siteConfig.tool_mobile_qrcodetype);
|
CoreLoginHelper.displayQRInCredentialsScreen(this.siteConfig.tool_mobile_qrcodetype);
|
||||||
|
|
||||||
|
@ -251,6 +256,23 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy {
|
||||||
CoreLoginHelper.forgottenPasswordClicked(this.siteUrl, this.username, this.siteConfig);
|
CoreLoginHelper.forgottenPasswordClicked(this.siteUrl, this.username, this.siteConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open browser for SSO login.
|
||||||
|
*/
|
||||||
|
openBrowserSSO(): void {
|
||||||
|
if (!this.siteConfig) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CoreLoginHelper.confirmAndOpenBrowserForSSOLogin(
|
||||||
|
this.siteUrl,
|
||||||
|
this.siteConfig.typeoflogin,
|
||||||
|
undefined,
|
||||||
|
this.siteConfig.launchurl,
|
||||||
|
this.redirectData,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An OAuth button was clicked.
|
* An OAuth button was clicked.
|
||||||
*
|
*
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { CanLoad, CanActivate, UrlTree } from '@angular/router';
|
import { CanLoad, CanActivate, UrlTree } from '@angular/router';
|
||||||
import { CoreLoginHelper } from '@features/login/services/login-helper';
|
import { CoreLoginHelper } from '@features/login/services/login-helper';
|
||||||
|
import { CoreApp } from '@services/app';
|
||||||
|
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { Router } from '@singletons';
|
import { Router } from '@singletons';
|
||||||
|
@ -45,9 +46,22 @@ export class CoreMainMenuAuthGuard implements CanLoad, CanActivate {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CoreLoginHelper.isSiteLoggedOut()) {
|
if (CoreLoginHelper.isSiteLoggedOut()) {
|
||||||
await CoreSites.logout();
|
// Send the user to reconnect page.
|
||||||
|
const newRoute = Router.parseUrl('/login/reconnect');
|
||||||
|
const siteId = CoreSites.getCurrentSiteId();
|
||||||
|
|
||||||
return Router.parseUrl('/login');
|
// Pass redirect data (if any and belongs to same site).
|
||||||
|
let redirect = CoreApp.consumeMemoryRedirect();
|
||||||
|
if (!redirect?.timemodified || Date.now() - redirect.timemodified > 20000 || redirect.siteId !== siteId) {
|
||||||
|
redirect = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
newRoute.queryParams = {
|
||||||
|
siteId,
|
||||||
|
...redirect,
|
||||||
|
};
|
||||||
|
|
||||||
|
return newRoute;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in New Issue