diff --git a/src/app/core/auth/auth.service.spec.ts b/src/app/core/auth/auth.service.spec.ts index 66c80b9bf5..e596650cfa 100644 --- a/src/app/core/auth/auth.service.spec.ts +++ b/src/app/core/auth/auth.service.spec.ts @@ -288,7 +288,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', () => { @@ -373,7 +373,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); @@ -593,7 +593,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', () => { @@ -633,7 +633,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 cd773b68cf..0a88ce15d5 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -2,7 +2,6 @@ import { HttpHeaders } from '@angular/common/http'; import { Inject, Injectable, - Optional, } from '@angular/core'; import { Router } from '@angular/router'; import { @@ -24,10 +23,6 @@ import { } from 'rxjs/operators'; import { environment } from '../../../environments/environment'; -import { - REQUEST, - RESPONSE, -} from '../../../express.tokens'; import { AppState } from '../../app.reducer'; import { hasNoValue, @@ -111,18 +106,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 @@ -504,10 +498,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 f51215abad..d287604c24 100644 --- a/src/app/core/auth/server-auth.service.ts +++ b/src/app/core/auth/server-auth.service.ts @@ -1,15 +1,40 @@ import { HttpHeaders } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { + Inject, + Injectable, + Optional, +} from '@angular/core'; +import { Router } from '@angular/router'; +import { Store } from '@ngrx/store'; +import { TranslateService } from '@ngx-translate/core'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; +import { + REQUEST, + RESPONSE, +} from '../../../express.tokens'; +import { AppState } from '../../app.reducer'; import { hasValue, isNotEmpty, } from '../../shared/empty.util'; +import { NotificationsService } from '../../shared/notifications/notifications.service'; import { RemoteData } from '../data/remote-data'; import { HttpOptions } from '../dspace-rest/dspace-rest.service'; -import { AuthService } from './auth.service'; +import { EPersonDataService } from '../eperson/eperson-data.service'; +import { CookieService } from '../services/cookie.service'; +import { HardRedirectService } from '../services/hard-redirect.service'; +import { RouteService } from '../services/route.service'; +import { + NativeWindowRef, + NativeWindowService, +} from '../services/window.service'; +import { + AuthService, + LOGIN_ROUTE, +} from './auth.service'; +import { AuthRequestService } from './auth-request.service'; import { AuthStatus } from './models/auth-status.model'; import { AuthTokenInfo } from './models/auth-token-info.model'; @@ -19,6 +44,34 @@ import { AuthTokenInfo } from './models/auth-token-info.model'; @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} @@ -62,4 +115,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 074cfbf02b..4bf3514373 100644 --- a/src/app/core/services/cookie.service.ts +++ b/src/app/core/services/cookie.service.ts @@ -1,15 +1,10 @@ -import { - Inject, - Injectable, -} from '@angular/core'; +import { Injectable } from '@angular/core'; import { CookieAttributes } from 'js-cookie'; import { Observable, Subject, } from 'rxjs'; -import { REQUEST } from '../../../express.tokens'; - export interface ICookieService { readonly cookies$: Observable<{ readonly [key: string]: any }>; @@ -27,9 +22,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 e0f38d026c..7f0327faf9 100644 --- a/src/app/core/services/server-cookie.service.ts +++ b/src/app/core/services/server-cookie.service.ts @@ -1,6 +1,10 @@ -import { Injectable } from '@angular/core'; +import { + Inject, + Injectable, +} from '@angular/core'; import { CookieAttributes } from 'js-cookie'; +import { REQUEST } from '../../../express.tokens'; import { CookieService, ICookieService, @@ -9,6 +13,10 @@ import { @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; }