diff --git a/src/app/core/auth/auth.service.spec.ts b/src/app/core/auth/auth.service.spec.ts index b38d17aecd..32ceee35d6 100644 --- a/src/app/core/auth/auth.service.spec.ts +++ b/src/app/core/auth/auth.service.spec.ts @@ -260,7 +260,7 @@ describe('AuthService test', () => { (state as any).core = Object.create({}); (state as any).core.auth = authenticatedState; }); - authService = new AuthService({}, window, undefined, authReqService, mockEpersonDataService, router, routeService, cookieService, store, hardRedirectService, notificationsService, translateService); + authService = new AuthService(window, authReqService, mockEpersonDataService, router, routeService, cookieService, store, hardRedirectService, notificationsService, translateService); })); it('should return true when user is logged in', () => { @@ -345,7 +345,7 @@ describe('AuthService test', () => { (state as any).core = Object.create({}); (state as any).core.auth = authenticatedState; }); - authService = new AuthService({}, window, undefined, authReqService, mockEpersonDataService, router, routeService, cookieService, store, hardRedirectService, notificationsService, translateService); + authService = new AuthService(window, authReqService, mockEpersonDataService, router, routeService, cookieService, store, hardRedirectService, notificationsService, translateService); storage = (authService as any).storage; routeServiceMock = TestBed.inject(RouteService); routerStub = TestBed.inject(Router); @@ -565,7 +565,7 @@ describe('AuthService test', () => { (state as any).core = Object.create({}); (state as any).core.auth = unAuthenticatedState; }); - authService = new AuthService({}, window, undefined, authReqService, mockEpersonDataService, router, routeService, cookieService, store, hardRedirectService, notificationsService, translateService); + authService = new AuthService(window, authReqService, mockEpersonDataService, router, routeService, cookieService, store, hardRedirectService, notificationsService, translateService); })); it('should return null for the shortlived token', () => { @@ -605,7 +605,7 @@ describe('AuthService test', () => { (state as any).core = Object.create({}); (state as any).core.auth = idleState; }); - authService = new AuthService({}, window, undefined, authReqService, mockEpersonDataService, router, routeService, cookieService, store, hardRedirectService, notificationsService, translateService); + authService = new AuthService(window, authReqService, mockEpersonDataService, router, routeService, cookieService, store, hardRedirectService, notificationsService, translateService); })); it('isUserIdle should return true when user is not idle', () => { diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index 8b08b4f32d..3a83674b7f 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -1,7 +1,6 @@ -import { Inject, Injectable, Optional } from '@angular/core'; +import { Inject, Injectable } from '@angular/core'; import { Router } from '@angular/router'; import { HttpHeaders } from '@angular/common/http'; -import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens'; import { Observable, of as observableOf } from 'rxjs'; import { filter, map, startWith, switchMap, take } from 'rxjs/operators'; @@ -79,18 +78,17 @@ export class AuthService { */ private tokenRefreshTimer; - constructor(@Inject(REQUEST) protected req: any, - @Inject(NativeWindowService) protected _window: NativeWindowRef, - @Optional() @Inject(RESPONSE) private response: any, - protected authRequestService: AuthRequestService, - protected epersonService: EPersonDataService, - protected router: Router, - protected routeService: RouteService, - protected storage: CookieService, - protected store: Store, - protected hardRedirectService: HardRedirectService, - private notificationService: NotificationsService, - private translateService: TranslateService + constructor( + @Inject(NativeWindowService) protected _window: NativeWindowRef, + protected authRequestService: AuthRequestService, + protected epersonService: EPersonDataService, + protected router: Router, + protected routeService: RouteService, + protected storage: CookieService, + protected store: Store, + protected hardRedirectService: HardRedirectService, + protected notificationService: NotificationsService, + protected translateService: TranslateService ) { this.store.pipe( // when this service is constructed the store is not fully initialized yet @@ -473,10 +471,6 @@ export class AuthService { if (this._window.nativeWindow.location) { // Hard redirect to login page, so that all state is definitely lost this._window.nativeWindow.location.href = redirectUrl; - } else if (this.response) { - if (!this.response._headerSent) { - this.response.redirect(302, redirectUrl); - } } else { this.router.navigateByUrl(redirectUrl); } diff --git a/src/app/core/auth/server-auth.service.ts b/src/app/core/auth/server-auth.service.ts index fc8ab18bfb..e2d5ec8131 100644 --- a/src/app/core/auth/server-auth.service.ts +++ b/src/app/core/auth/server-auth.service.ts @@ -1,15 +1,25 @@ -import { Injectable } from '@angular/core'; +import { Injectable, Inject, Optional } from '@angular/core'; import { HttpHeaders } from '@angular/common/http'; - +import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; - import { hasValue, isNotEmpty } from '../../shared/empty.util'; import { HttpOptions } from '../dspace-rest/dspace-rest.service'; -import { AuthService } from './auth.service'; +import { AuthService, LOGIN_ROUTE } from './auth.service'; import { AuthStatus } from './models/auth-status.model'; import { AuthTokenInfo } from './models/auth-token-info.model'; import { RemoteData } from '../data/remote-data'; +import { NativeWindowService, NativeWindowRef } from '../services/window.service'; +import { AuthRequestService } from './auth-request.service'; +import { EPersonDataService } from '../eperson/eperson-data.service'; +import { Router } from '@angular/router'; +import { RouteService } from '../services/route.service'; +import { CookieService } from '../services/cookie.service'; +import { Store } from '@ngrx/store'; +import { AppState } from '../../app.reducer'; +import { HardRedirectService } from '../services/hard-redirect.service'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { TranslateService } from '@ngx-translate/core'; /** * The auth service. @@ -17,6 +27,34 @@ import { RemoteData } from '../data/remote-data'; @Injectable() export class ServerAuthService extends AuthService { + constructor( + @Inject(REQUEST) protected req: any, + @Optional() @Inject(RESPONSE) private response: any, + @Inject(NativeWindowService) protected _window: NativeWindowRef, + protected authRequestService: AuthRequestService, + protected epersonService: EPersonDataService, + protected router: Router, + protected routeService: RouteService, + protected storage: CookieService, + protected store: Store, + protected hardRedirectService: HardRedirectService, + protected notificationService: NotificationsService, + protected translateService: TranslateService + ) { + super( + _window, + authRequestService, + epersonService, + router, + routeService, + storage, + store, + hardRedirectService, + notificationService, + translateService + ); + } + /** * Returns the authenticated user * @returns {User} @@ -60,4 +98,18 @@ export class ServerAuthService extends AuthService { map((rd: RemoteData) => Object.assign(new AuthStatus(), rd.payload)) ); } + + override redirectToLoginWhenTokenExpired() { + const redirectUrl = LOGIN_ROUTE + '?expired=true'; + if (this._window.nativeWindow.location) { + // Hard redirect to login page, so that all state is definitely lost + this._window.nativeWindow.location.href = redirectUrl; + } else if (this.response) { + if (!this.response._headerSent) { + this.response.redirect(302, redirectUrl); + } + } else { + this.router.navigateByUrl(redirectUrl); + } + } } diff --git a/src/app/core/services/cookie.service.ts b/src/app/core/services/cookie.service.ts index 0098e3ace4..939e19f317 100644 --- a/src/app/core/services/cookie.service.ts +++ b/src/app/core/services/cookie.service.ts @@ -1,7 +1,4 @@ -import { Inject, Injectable } from '@angular/core'; - -import { REQUEST } from '@nguniversal/express-engine/tokens'; - +import { Injectable } from '@angular/core'; import { Subject , Observable } from 'rxjs'; import { CookieAttributes } from 'js-cookie'; @@ -22,9 +19,6 @@ export abstract class CookieService implements ICookieService { protected readonly cookieSource = new Subject<{ readonly [key: string]: any }>(); public readonly cookies$ = this.cookieSource.asObservable(); - constructor(@Inject(REQUEST) protected req: any) { - } - public abstract set(name: string, value: any, options?: CookieAttributes): void; public abstract remove(name: string, options?: CookieAttributes): void; diff --git a/src/app/core/services/server-cookie.service.ts b/src/app/core/services/server-cookie.service.ts index 6ae3525c74..1cc7d4414f 100644 --- a/src/app/core/services/server-cookie.service.ts +++ b/src/app/core/services/server-cookie.service.ts @@ -1,10 +1,15 @@ -import { Injectable } from '@angular/core'; +import { Injectable, Inject } from '@angular/core'; import { CookieAttributes } from 'js-cookie'; import { CookieService, ICookieService } from './cookie.service'; +import { REQUEST } from '@nguniversal/express-engine/tokens'; @Injectable() export class ServerCookieService extends CookieService implements ICookieService { + constructor(@Inject(REQUEST) protected req: any) { + super(); + } + public set(name: string, value: any, options?: CookieAttributes): void { return; }