From 4b20b0cb8116a234c22fb48a79200eb0783b57a1 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Tue, 23 Aug 2022 17:50:46 +0200 Subject: [PATCH] force initservices to wait until authentication is no longer blocking --- src/app/core/auth/auth-request.service.ts | 37 ++++++++++++++--------- src/app/core/auth/auth.reducer.ts | 6 ++++ src/modules/app/browser-init.service.ts | 7 +++++ src/modules/app/server-init.service.ts | 12 ++++++-- 4 files changed, 46 insertions(+), 16 deletions(-) diff --git a/src/app/core/auth/auth-request.service.ts b/src/app/core/auth/auth-request.service.ts index 00a94822d3..bcaa5972ac 100644 --- a/src/app/core/auth/auth-request.service.ts +++ b/src/app/core/auth/auth-request.service.ts @@ -1,5 +1,5 @@ import { Observable } from 'rxjs'; -import { distinctUntilChanged, filter, map, mergeMap, switchMap, tap } from 'rxjs/operators'; +import { distinctUntilChanged, filter, map, mergeMap, switchMap, tap, take } from 'rxjs/operators'; import { HALEndpointService } from '../shared/hal-endpoint.service'; import { RequestService } from '../data/request.service'; import { isNotEmpty } from '../../shared/empty.util'; @@ -26,8 +26,8 @@ export abstract class AuthRequestService { ) { } - protected fetchRequest(request: RestRequest): Observable> { - return this.rdbService.buildFromRequestUUID(request.uuid).pipe( + protected fetchRequest(requestId: string): Observable> { + return this.rdbService.buildFromRequestUUID(requestId).pipe( getFirstCompletedRemoteData(), ); } @@ -37,27 +37,36 @@ export abstract class AuthRequestService { } public postToEndpoint(method: string, body?: any, options?: HttpOptions): Observable> { - return this.halService.getEndpoint(this.linkName).pipe( + const requestId = this.requestService.generateRequestId(); + + this.halService.getEndpoint(this.linkName).pipe( filter((href: string) => isNotEmpty(href)), map((endpointURL) => this.getEndpointByMethod(endpointURL, method)), distinctUntilChanged(), - map((endpointURL: string) => new PostRequest(this.requestService.generateRequestId(), endpointURL, body, options)), - tap((request: PostRequest) => this.requestService.send(request)), - mergeMap((request: PostRequest) => this.fetchRequest(request)), - distinctUntilChanged()); + map((endpointURL: string) => new PostRequest(requestId, endpointURL, body, options)), + take(1) + ).subscribe((request: PostRequest) => { + this.requestService.send(request); + }); + + return this.fetchRequest(requestId); } public getRequest(method: string, options?: HttpOptions): Observable> { - return this.halService.getEndpoint(this.linkName).pipe( + const requestId = this.requestService.generateRequestId(); + + this.halService.getEndpoint(this.linkName).pipe( filter((href: string) => isNotEmpty(href)), map((endpointURL) => this.getEndpointByMethod(endpointURL, method)), distinctUntilChanged(), - map((endpointURL: string) => new GetRequest(this.requestService.generateRequestId(), endpointURL, undefined, options)), - tap((request: GetRequest) => this.requestService.send(request)), - mergeMap((request: GetRequest) => this.fetchRequest(request)), - distinctUntilChanged()); - } + map((endpointURL: string) => new GetRequest(requestId, endpointURL, undefined, options)), + take(1) + ).subscribe((request: GetRequest) => { + this.requestService.send(request); + }); + return this.fetchRequest(requestId); + } /** * Factory function to create the request object to send. This needs to be a POST client side and * a GET server side. Due to CSRF validation, the server isn't allowed to send a POST, so we allow diff --git a/src/app/core/auth/auth.reducer.ts b/src/app/core/auth/auth.reducer.ts index 6f47a3c20c..acdb8ef812 100644 --- a/src/app/core/auth/auth.reducer.ts +++ b/src/app/core/auth/auth.reducer.ts @@ -17,6 +17,7 @@ import { import { AuthTokenInfo } from './models/auth-token-info.model'; import { AuthMethod } from './models/auth.method'; import { AuthMethodType } from './models/auth.method-type'; +import { StoreActionTypes } from '../../store.actions'; /** * The auth state. @@ -251,6 +252,11 @@ export function authReducer(state: any = initialState, action: AuthActions): Aut idle: false, }); + case StoreActionTypes.REHYDRATE: + return Object.assign({}, state, { + blocking: true, + }); + default: return state; } diff --git a/src/modules/app/browser-init.service.ts b/src/modules/app/browser-init.service.ts index 3980b8bc28..2d49870d58 100644 --- a/src/modules/app/browser-init.service.ts +++ b/src/modules/app/browser-init.service.ts @@ -91,6 +91,13 @@ export class BrowserInitService extends InitService { this.initKlaro(); + // wait for auth to be ready + await this.store.pipe( + select(isAuthenticationBlocking), + distinctUntilChanged(), + find((b: boolean) => b === false) + ).toPromise(); + return true; }; } diff --git a/src/modules/app/server-init.service.ts b/src/modules/app/server-init.service.ts index 803dc7a75a..fb3539ecfa 100644 --- a/src/modules/app/server-init.service.ts +++ b/src/modules/app/server-init.service.ts @@ -6,7 +6,7 @@ * http://www.dspace.org/license/ */ import { InitService } from '../../app/init.service'; -import { Store } from '@ngrx/store'; +import { Store, select } from '@ngrx/store'; import { AppState } from '../../app/app.reducer'; import { TransferState } from '@angular/platform-browser'; import { CorrelationIdService } from '../../app/correlation-id/correlation-id.service'; @@ -20,7 +20,8 @@ import { MetadataService } from '../../app/core/metadata/metadata.service'; import { BreadcrumbsService } from '../../app/breadcrumbs/breadcrumbs.service'; import { CSSVariableService } from '../../app/shared/sass-helper/sass-helper.service'; import { ThemeService } from '../../app/shared/theme-support/theme.service'; -import { take } from 'rxjs/operators'; +import { take, distinctUntilChanged, find } from 'rxjs/operators'; +import { isAuthenticationBlocking } from '../../app/core/auth/selectors'; /** * Performs server-side initialization. @@ -66,6 +67,13 @@ export class ServerInitService extends InitService { this.initRouteListeners(); this.themeService.listenForThemeChanges(false); + // wait for auth to be ready + await this.store.pipe( + select(isAuthenticationBlocking), + distinctUntilChanged(), + find((b: boolean) => b === false) + ).toPromise(); + return true; }; }