Skip to content

Commit

Permalink
Fix the auth problems with the UI
Browse files Browse the repository at this point in the history
  • Loading branch information
Senyoret1 committed Sep 14, 2022
1 parent 44ebb17 commit 2aada9e
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 11 deletions.
4 changes: 2 additions & 2 deletions static/skywire-manager-src/src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
</div>
<div class="flex-1 content container-fluid">
<div [ngClass]="{'background': inVpnClient}"></div>
<router-outlet *ngIf="hypervisorPkObtained"></router-outlet>
<app-loading-indicator class="h-100" *ngIf="!hypervisorPkObtained"></app-loading-indicator>
<router-outlet *ngIf="hypervisorPkObtained || inLoginPage"></router-outlet>
<app-loading-indicator class="h-100" *ngIf="!hypervisorPkObtained && !inLoginPage"></app-loading-indicator>
</div>
50 changes: 45 additions & 5 deletions static/skywire-manager-src/src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Component } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { MatDialog } from '@angular/material/dialog';
import { of } from 'rxjs';
import { of, Subscription } from 'rxjs';
import { delay, flatMap } from 'rxjs/operators';

import { StorageService } from './services/storage.service';
Expand All @@ -19,12 +19,20 @@ import { processServiceError } from './utils/errors';
styleUrls: ['./app.component.scss']
})
export class AppComponent {
static currentInstance: AppComponent;

// If the app is showing the VPN client.
inVpnClient = false;
// If the app is in the login page. Needed to know if content should be shown even if
// hypervisorPkObtained is false.
inLoginPage = false;

// If the pk of the hypervisor has been obtained.
hypervisorPkObtained = false;
pkErrorShown = false;
pkErrorsFound = 0;

obtainPkSubscription: Subscription;

constructor(
// Imported to call its constructor right after opening the app.
Expand All @@ -35,6 +43,8 @@ export class AppComponent {
private languageService: LanguageService,
private apiService: ApiService,
) {
AppComponent.currentInstance = this;

// Close the snackbar when opening a modal window.
dialog.afterOpened.subscribe(() => snackbarService.closeCurrent());

Expand All @@ -53,9 +63,19 @@ export class AppComponent {
dialog.afterAllClosed.subscribe(() => snackbarService.closeCurrentIfTemporaryError());

// Check if the app is showing the VPN client.
router.events.subscribe(() => {
router.events.subscribe((e: any) => {
this.inVpnClient = router.url.includes('/vpn/') || router.url.includes('vpnlogin');

// Check if the user enters or leaves the login page.
if (e.url) {
const previousInLoginPageValue = this.inLoginPage;
this.inLoginPage = e.url.includes('login');

if (previousInLoginPageValue && !this.inLoginPage && !this.hypervisorPkObtained) {
this.checkHypervisorPk(0);
}
}

// Show the correct document title.
if (router.url.length > 2) {
if (this.inVpnClient) {
Expand All @@ -72,11 +92,26 @@ export class AppComponent {
this.checkHypervisorPk(0);
}

/**
* This should be called a frame before leaving the login page, to avoid race conditions in which the
* automatic event code in the constructor changes the value of inLoginPage to false but Angular still
* loads the content of the new page just before taking that value into account.
*/
processLoginDone() {
this.inLoginPage = false;
if (!this.hypervisorPkObtained) {
this.checkHypervisorPk(0);
}
}

/**
* Gets the pk of the hypervisor. After that, it initializes services and allows the app to start working.
*/
private checkHypervisorPk(delayMs: number) {
of(1).pipe(delay(delayMs), flatMap(() => this.apiService.get('about'))).subscribe(result => {
if (this.obtainPkSubscription) {
this.obtainPkSubscription.unsubscribe();
}
this.obtainPkSubscription = of(1).pipe(delay(delayMs), flatMap(() => this.apiService.get('about'))).subscribe(result => {
if (result.public_key) {
this.finishStartup(result.public_key);
this.hypervisorPkObtained = true;
Expand All @@ -88,12 +123,17 @@ export class AppComponent {
this.checkHypervisorPk(1000);
}
}, err => {
if (!this.pkErrorShown) {
this.pkErrorsFound += 1;

if (this.pkErrorsFound > 4 && !this.pkErrorShown) {
const e = processServiceError(err);
this.snackbarService.showError('start.loading-error', null, true, e);
this.pkErrorShown = true;
}
this.checkHypervisorPk(1000);

if (!this.inLoginPage) {
this.checkHypervisorPk(1000);
}
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { SnackbarService } from '../../../services/snackbar.service';
import { InitialSetupComponent } from './initial-setup/initial-setup.component';
import { OperationError } from '../../../utils/operation-error';
import { processServiceError } from '../../../utils/errors';
import { AppComponent } from 'src/app/app.component';

/**
* Login page.
Expand Down Expand Up @@ -46,8 +47,12 @@ export class LoginComponent implements OnInit, OnDestroy {
// Check if the user is already logged.
this.verificationSubscription = this.authService.checkLogin().subscribe(response => {
if (response !== AuthStates.NotLogged) {
const destination = !this.isForVpn ? ['nodes'] : ['vpn', this.vpnKey, 'status'];
this.router.navigate(destination, { replaceUrl: true });
// Inform about the redirect a frame before it is done, to avoid problems.
AppComponent.currentInstance.processLoginDone();
setTimeout(() => {
const destination = !this.isForVpn ? ['nodes'] : ['vpn', this.vpnKey, 'status'];
this.router.navigate(destination, { replaceUrl: true });
});
}
});
});
Expand Down Expand Up @@ -83,8 +88,12 @@ export class LoginComponent implements OnInit, OnDestroy {
}

private onLoginSuccess() {
const destination = !this.isForVpn ? ['nodes'] : ['vpn', this.vpnKey, 'status'];
this.router.navigate(destination, { replaceUrl: true });
// Inform about the redirect a frame before it is done, to avoid problems.
AppComponent.currentInstance.processLoginDone();
setTimeout(() => {
const destination = !this.isForVpn ? ['nodes'] : ['vpn', this.vpnKey, 'status'];
this.router.navigate(destination, { replaceUrl: true });
});
}

private onLoginError(err: OperationError) {
Expand Down

0 comments on commit 2aada9e

Please sign in to comment.