fixed auth module

This commit is contained in:
Giuseppe Digilio
2018-02-10 13:01:58 +01:00
parent 64ad40b676
commit b7cff01dab
14 changed files with 147 additions and 109 deletions

View File

@@ -17,6 +17,9 @@ import { MetadataService } from './core/metadata/metadata.service';
import { HostWindowResizeAction } from './shared/host-window.actions'; import { HostWindowResizeAction } from './shared/host-window.actions';
import { HostWindowState } from './shared/host-window.reducer'; import { HostWindowState } from './shared/host-window.reducer';
import { NativeWindowRef, NativeWindowService } from './shared/services/window.service'; import { NativeWindowRef, NativeWindowService } from './shared/services/window.service';
import { CheckAuthenticationTokenAction } from './core/auth/auth.actions';
import { isAuthenticated } from './core/auth/selectors';
import { PlatformService } from './shared/services/platform.service';
@Component({ @Component({
selector: 'ds-app', selector: 'ds-app',
@@ -32,7 +35,8 @@ export class AppComponent implements OnInit {
@Inject(NativeWindowService) private _window: NativeWindowRef, @Inject(NativeWindowService) private _window: NativeWindowRef,
private translate: TranslateService, private translate: TranslateService,
private store: Store<HostWindowState>, private store: Store<HostWindowState>,
private metadata: MetadataService private metadata: MetadataService,
private platformService: PlatformService
) { ) {
// this language will be used as a fallback when a translation isn't found in the current language // this language will be used as a fallback when a translation isn't found in the current language
translate.setDefaultLang('en'); translate.setDefaultLang('en');
@@ -51,6 +55,12 @@ export class AppComponent implements OnInit {
const color: string = this.config.production ? 'red' : 'green'; const color: string = this.config.production ? 'red' : 'green';
console.info(`Environment: %c${env}`, `color: ${color}; font-weight: bold;`); console.info(`Environment: %c${env}`, `color: ${color}; font-weight: bold;`);
this.dispatchWindowSize(this._window.nativeWindow.innerWidth, this._window.nativeWindow.innerHeight); this.dispatchWindowSize(this._window.nativeWindow.innerWidth, this._window.nativeWindow.innerHeight);
if (this.platformService.isServer) {
this.store.select(isAuthenticated)
.take(1)
.filter((authenticated) => !authenticated)
.subscribe((authenticated) => this.store.dispatch(new CheckAuthenticationTokenAction()));
}
} }
@HostListener('window:resize', ['$event']) @HostListener('window:resize', ['$event'])

View File

@@ -31,6 +31,7 @@ export class AuthRequestService extends HALEndpointService {
protected fetchRequest(request: RestRequest): Observable<any> { protected fetchRequest(request: RestRequest): Observable<any> {
const [successResponse, errorResponse] = this.responseCache.get(request.href) const [successResponse, errorResponse] = this.responseCache.get(request.href)
.map((entry: ResponseCacheEntry) => entry.response) .map((entry: ResponseCacheEntry) => entry.response)
.do(() => this.responseCache.remove(request.href))
.partition((response: RestResponse) => response.isSuccessful); .partition((response: RestResponse) => response.isSuccessful);
return Observable.merge( return Observable.merge(
errorResponse.flatMap((response: ErrorResponse) => errorResponse.flatMap((response: ErrorResponse) =>

View File

@@ -36,10 +36,10 @@ export class AuthResponseParsingService extends BaseResponseParsingService imple
} }
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links) && data.statusCode === '200') { if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links) && (data.statusCode === '200' || data.statusCode === 'OK')) {
const response = this.process<AuthStatus,AuthType>(data.payload, request.href); const response = this.process<AuthStatus,AuthType>(data.payload, request.href);
return new AuthStatusResponse(response[Object.keys(response)[0]][0], data.statusCode); return new AuthStatusResponse(response[Object.keys(response)[0]][0], data.statusCode);
} else if (isEmpty(data.payload) && isNotEmpty(data.headers.get('authorization')) && data.statusCode === '200') { } else if (isEmpty(data.payload) && isNotEmpty(data.headers.get('authorization')) && (data.statusCode === '200' || data.statusCode === 'OK')) {
return new AuthSuccessResponse(new AuthTokenInfo(data.headers.get('authorization')), data.statusCode); return new AuthSuccessResponse(new AuthTokenInfo(data.headers.get('authorization')), data.statusCode);
} else { } else {
return new AuthStatusResponse(data.payload as AuthStatus, data.statusCode); return new AuthStatusResponse(data.payload as AuthStatus, data.statusCode);

View File

@@ -1,34 +0,0 @@
import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
/**
* The auth service.
*/
@Injectable()
export class AuthStorageService {
constructor(@Inject(PLATFORM_ID) private platformId: string) {}
public get(key: string): any {
let item = null;
if (isPlatformBrowser(this.platformId)) {
item = JSON.parse(localStorage.getItem(key));
}
return item;
}
public store(key: string, item: any) {
if (isPlatformBrowser(this.platformId)) {
localStorage.setItem(key, JSON.stringify(item));
}
return true;
}
public remove(key: string) {
if (isPlatformBrowser(this.platformId)) {
localStorage.removeItem(key);
}
return true;
}
}

View File

@@ -15,6 +15,8 @@ export const AuthActionTypes = {
AUTHENTICATED: type('dspace/auth/AUTHENTICATED'), AUTHENTICATED: type('dspace/auth/AUTHENTICATED'),
AUTHENTICATED_ERROR: type('dspace/auth/AUTHENTICATED_ERROR'), AUTHENTICATED_ERROR: type('dspace/auth/AUTHENTICATED_ERROR'),
AUTHENTICATED_SUCCESS: type('dspace/auth/AUTHENTICATED_SUCCESS'), AUTHENTICATED_SUCCESS: type('dspace/auth/AUTHENTICATED_SUCCESS'),
CHECK_AUTHENTICATION_TOKEN: type('dspace/auth/CHECK_AUTHENTICATION_TOKEN'),
CHECK_AUTHENTICATION_TOKEN_ERROR: type('dspace/auth/CHECK_AUTHENTICATION_TOKEN_ERROR'),
RESET_ERROR: type('dspace/auth/RESET_ERROR'), RESET_ERROR: type('dspace/auth/RESET_ERROR'),
LOG_OUT: type('dspace/auth/LOG_OUT'), LOG_OUT: type('dspace/auth/LOG_OUT'),
LOG_OUT_ERROR: type('dspace/auth/LOG_OUT_ERROR'), LOG_OUT_ERROR: type('dspace/auth/LOG_OUT_ERROR'),
@@ -116,6 +118,24 @@ export class AuthenticationSuccessAction implements Action {
} }
} }
/**
* Check if token is already present upon initial load.
* @class CheckAuthenticationTokenAction
* @implements {Action}
*/
export class CheckAuthenticationTokenAction implements Action {
public type: string = AuthActionTypes.CHECK_AUTHENTICATION_TOKEN;
}
/**
* Check Authentication Token Error.
* @class CheckAuthenticationTokenErrorAction
* @implements {Action}
*/
export class CheckAuthenticationTokenErrorAction implements Action {
public type: string = AuthActionTypes.CHECK_AUTHENTICATION_TOKEN_ERROR;
}
/** /**
* Reset error. * Reset error.
* @class ResetAuthenticationErrorAction * @class ResetAuthenticationErrorAction
@@ -215,6 +235,8 @@ export type AuthActions
| AuthenticatedSuccessAction | AuthenticatedSuccessAction
| AuthenticationErrorAction | AuthenticationErrorAction
| AuthenticationSuccessAction | AuthenticationSuccessAction
| CheckAuthenticationTokenAction
| CheckAuthenticationTokenErrorAction
| RegistrationAction | RegistrationAction
| RegistrationErrorAction | RegistrationErrorAction
| RegistrationSuccessAction; | RegistrationSuccessAction;

View File

@@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
// import @ngrx // import @ngrx
import { Effect, Actions } from '@ngrx/effects'; import { Effect, Actions } from '@ngrx/effects';
import { Action } from '@ngrx/store'; import { Action, Store } from '@ngrx/store';
// import rxjs // import rxjs
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
@@ -16,7 +16,7 @@ import {
AuthenticatedErrorAction, AuthenticatedErrorAction,
AuthenticatedSuccessAction, AuthenticatedSuccessAction,
AuthenticationErrorAction, AuthenticationErrorAction,
AuthenticationSuccessAction, LogOutAction, AuthenticationSuccessAction, CheckAuthenticationTokenAction, CheckAuthenticationTokenErrorAction, LogOutAction,
LogOutErrorAction, LogOutErrorAction,
LogOutSuccessAction, RegistrationAction, LogOutSuccessAction, RegistrationAction,
RegistrationErrorAction, RegistrationErrorAction,
@@ -24,6 +24,10 @@ import {
} from './auth.actions'; } from './auth.actions';
import { Eperson } from '../eperson/models/eperson.model'; import { Eperson } from '../eperson/models/eperson.model';
import { AuthStatus } from './models/auth-status.model'; import { AuthStatus } from './models/auth-status.model';
import { AuthTokenInfo } from './models/auth-token-info.model';
import { AppState } from '../../app.reducer';
import { isAuthenticated } from './selectors';
import { StoreActionTypes } from '../../store.actions';
@Injectable() @Injectable()
export class AuthEffects { export class AuthEffects {
@@ -46,12 +50,7 @@ export class AuthEffects {
public authenticateSuccess: Observable<Action> = this.actions$ public authenticateSuccess: Observable<Action> = this.actions$
.ofType(AuthActionTypes.AUTHENTICATE_SUCCESS) .ofType(AuthActionTypes.AUTHENTICATE_SUCCESS)
.do((action: AuthenticationSuccessAction) => this.authService.storeToken(action.payload)) .do((action: AuthenticationSuccessAction) => this.authService.storeToken(action.payload))
.map((action: AuthenticationSuccessAction) => new AuthenticatedAction(action.payload)) .map((action: AuthenticationSuccessAction) => new AuthenticatedAction(action.payload));
@Effect({dispatch: false})
public logOutSuccess: Observable<Action> = this.actions$
.ofType(AuthActionTypes.LOG_OUT_SUCCESS)
.do((action: LogOutSuccessAction) => this.authService.removeToken());
@Effect() @Effect()
public authenticated: Observable<Action> = this.actions$ public authenticated: Observable<Action> = this.actions$
@@ -62,6 +61,20 @@ export class AuthEffects {
.catch((error) => Observable.of(new AuthenticatedErrorAction(error))); .catch((error) => Observable.of(new AuthenticatedErrorAction(error)));
}); });
@Effect({dispatch: false})
public authenticatedError: Observable<Action> = this.actions$
.ofType(AuthActionTypes.AUTHENTICATED_ERROR)
.do((action: LogOutSuccessAction) => this.authService.removeToken());
@Effect()
public checkToken: Observable<Action> = this.actions$
.ofType(AuthActionTypes.CHECK_AUTHENTICATION_TOKEN)
.switchMap(() => {
return this.authService.checkAuthenticationToken()
.map((token: AuthTokenInfo) => new AuthenticatedAction(token))
.catch((error) => Observable.of(new CheckAuthenticationTokenErrorAction()));
});
@Effect() @Effect()
public createUser: Observable<Action> = this.actions$ public createUser: Observable<Action> = this.actions$
.ofType(AuthActionTypes.REGISTRATION) .ofType(AuthActionTypes.REGISTRATION)
@@ -72,21 +85,41 @@ export class AuthEffects {
.catch((error) => Observable.of(new RegistrationErrorAction(error))); .catch((error) => Observable.of(new RegistrationErrorAction(error)));
}); });
/**
* When the store is rehydrated in the browser,
* clear a possible invalid token
*/
@Effect({dispatch: false})
public clearInvalidTokenOnRehydrate = this.actions$
.ofType(StoreActionTypes.REHYDRATE)
.switchMap(() => {
return this.store.select(isAuthenticated)
.take(1)
.filter((authenticated) => !authenticated)
.do(() => this.authService.removeToken());
});
@Effect() @Effect()
public signOut: Observable<Action> = this.actions$ public logOut: Observable<Action> = this.actions$
.ofType(AuthActionTypes.LOG_OUT) .ofType(AuthActionTypes.LOG_OUT)
.switchMap((action: LogOutAction) => { .switchMap(() => {
return this.authService.signout() return this.authService.logout()
.map((value) => new LogOutSuccessAction()) .map((value) => new LogOutSuccessAction())
.catch((error) => Observable.of(new LogOutErrorAction(error))); .catch((error) => Observable.of(new LogOutErrorAction(error)));
}); });
@Effect({dispatch: false})
public logOutSuccess: Observable<Action> = this.actions$
.ofType(AuthActionTypes.LOG_OUT_SUCCESS)
.do((action: LogOutSuccessAction) => this.authService.removeToken());
/** /**
* @constructor * @constructor
* @param {Actions} actions$ * @param {Actions} actions$
* @param {AuthService} authService * @param {AuthService} authService
*/ */
constructor(private actions$: Actions, constructor(private actions$: Actions,
private authService: AuthService) { private authService: AuthService,
private store: Store<AppState>) {
} }
} }

View File

@@ -23,6 +23,10 @@ export class AuthInterceptor implements HttpInterceptor {
return status === 401 || status === 403; return status === 401 || status === 403;
} }
private isAuthRequest(url: string): boolean {
return url.endsWith('/authn/login') || url.endsWith('/authn/logout') || url.endsWith('/authn/status');
}
private isLoginResponse(url: string): boolean { private isLoginResponse(url: string): boolean {
return url.endsWith('/authn/login'); return url.endsWith('/authn/login');
} }
@@ -40,7 +44,7 @@ export class AuthInterceptor implements HttpInterceptor {
authStatus.token = new AuthTokenInfo(accessToken); authStatus.token = new AuthTokenInfo(accessToken);
} else { } else {
authStatus.authenticated = false; authStatus.authenticated = false;
authStatus.error = JSON.parse(error); authStatus.error = isNotEmpty(error) ? JSON.parse(error) : null;
} }
return authStatus; return authStatus;
} }
@@ -53,11 +57,11 @@ export class AuthInterceptor implements HttpInterceptor {
const Authorization = authService.getAuthHeader(); const Authorization = authService.getAuthHeader();
let authReq; let authReq;
if (isNotEmpty(Authorization)) { if (!this.isAuthRequest(req.url) && isNotEmpty(Authorization)) {
// Clone the request to add the new header. // Clone the request to add the new header.
authReq = req.clone({headers: req.headers.set('authorization', Authorization)}); authReq = req.clone({headers: req.headers.set('authorization', Authorization)});
} else { } else {
authReq = req.clone(); authReq = req;
} }
// Pass on the cloned request instead of the original request. // Pass on the cloned request instead of the original request.
@@ -67,6 +71,7 @@ export class AuthInterceptor implements HttpInterceptor {
let authRes: HttpResponse<any>; let authRes: HttpResponse<any>;
if (this.isLoginResponse(response.url)) { if (this.isLoginResponse(response.url)) {
const token = response.headers.get('authorization'); const token = response.headers.get('authorization');
const expires = response.headers.get('expires');
authRes = response.clone({body: this.makeAuthStatusObject(true, token)}); authRes = response.clone({body: this.makeAuthStatusObject(true, token)});
} else { } else {
authRes = response.clone({body: this.makeAuthStatusObject(false)}); authRes = response.clone({body: this.makeAuthStatusObject(false)});

View File

@@ -6,7 +6,6 @@ import {
// import models // import models
import { Eperson } from '../eperson/models/eperson.model'; import { Eperson } from '../eperson/models/eperson.model';
import { AuthTokenInfo } from './models/auth-token-info.model';
/** /**
* The auth state. * The auth state.
@@ -26,9 +25,6 @@ export interface AuthState {
// true when loading // true when loading
loading: boolean; loading: boolean;
// access token
token?: AuthTokenInfo;
// the authenticated user // the authenticated user
user?: Eperson; user?: Eperson;
} }
@@ -61,7 +57,8 @@ export function authReducer(state: any = initialState, action: AuthActions): Aut
return Object.assign({}, state, { return Object.assign({}, state, {
authenticated: false, authenticated: false,
error: (action as AuthenticationErrorAction).payload.message, error: (action as AuthenticationErrorAction).payload.message,
loaded: true loaded: true,
loading: false
}); });
case AuthActionTypes.AUTHENTICATED_SUCCESS: case AuthActionTypes.AUTHENTICATED_SUCCESS:
@@ -82,15 +79,16 @@ export function authReducer(state: any = initialState, action: AuthActions): Aut
}); });
case AuthActionTypes.AUTHENTICATE_SUCCESS: case AuthActionTypes.AUTHENTICATE_SUCCESS:
const token: AuthTokenInfo = (action as AuthenticationSuccessAction).payload;
// verify token is not null
if (token === null) {
return state; return state;
}
case AuthActionTypes.CHECK_AUTHENTICATION_TOKEN:
return Object.assign({}, state, { return Object.assign({}, state, {
token: token loading: true
});
case AuthActionTypes.CHECK_AUTHENTICATION_TOKEN_ERROR:
return Object.assign({}, state, {
loading: false
}); });
case AuthActionTypes.REGISTRATION_SUCCESS: case AuthActionTypes.REGISTRATION_SUCCESS:
@@ -117,8 +115,7 @@ export function authReducer(state: any = initialState, action: AuthActions): Aut
error: undefined, error: undefined,
loaded: false, loaded: false,
loading: false, loading: false,
user: undefined, user: undefined
token: undefined
}); });
case AuthActionTypes.REGISTRATION: case AuthActionTypes.REGISTRATION:

View File

@@ -7,34 +7,9 @@ import { AuthRequestService } from './auth-request.service';
import { HttpHeaders } from '@angular/common/http'; import { HttpHeaders } from '@angular/common/http';
import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service';
import { AuthStatus } from './models/auth-status.model'; import { AuthStatus } from './models/auth-status.model';
import { AuthTokenInfo } from './models/auth-token-info.model'; import { AuthTokenInfo, TOKENITEM } from './models/auth-token-info.model';
import { isNotEmpty, isNotNull } from '../../shared/empty.util'; import { isNotEmpty, isNotNull } from '../../shared/empty.util';
import { AuthStorageService } from './auth-storage.service'; import { CookieService } from '../../shared/services/cookie.service';
export const MOCK_USER = new Eperson();
MOCK_USER.id = '92a59227-ccf7-46da-9776-86c3fc64147f';
MOCK_USER.uuid = '92a59227-ccf7-46da-9776-86c3fc64147f';
MOCK_USER.name = 'andrea.bollini@4science.it';
MOCK_USER.email = 'andrea.bollini@4science.it';
MOCK_USER.metadata = [
{
key: 'eperson.firstname',
value: 'Andrea',
language: null
},
{
key: 'eperson.lastname',
value: 'Bollini',
language: null
},
{
key: 'eperson.language',
value: 'en',
language: null
}
];
export const TOKENITEM = 'dsAuthInfo';
/** /**
* The auth service. * The auth service.
@@ -54,7 +29,7 @@ export class AuthService {
*/ */
private _redirectUrl: string; private _redirectUrl: string;
constructor(private authRequestService: AuthRequestService, private storage: AuthStorageService) { constructor(private authRequestService: AuthRequestService, private storage: CookieService) {
} }
/** /**
@@ -76,7 +51,7 @@ export class AuthService {
let headers = new HttpHeaders(); let headers = new HttpHeaders();
headers = headers.append('Content-Type', 'application/x-www-form-urlencoded'); headers = headers.append('Content-Type', 'application/x-www-form-urlencoded');
options.headers = headers; options.headers = headers;
options.responseType = 'text'; // options.responseType = 'text';
return this.authRequestService.postToEndpoint('login', body, options) return this.authRequestService.postToEndpoint('login', body, options)
.map((status: AuthStatus) => { .map((status: AuthStatus) => {
if (status.authenticated) { if (status.authenticated) {
@@ -101,9 +76,7 @@ export class AuthService {
* @returns {User} * @returns {User}
*/ */
public authenticatedUser(token: AuthTokenInfo): Observable<Eperson> { public authenticatedUser(token: AuthTokenInfo): Observable<Eperson> {
// Normally you would do an HTTP request to determine if // Determine if the user has an existing auth session on the server
// the user has an existing auth session on the server
// but, let's just return the mock user for this example.
const options: HttpOptions = Object.create({}); const options: HttpOptions = Object.create({});
let headers = new HttpHeaders(); let headers = new HttpHeaders();
headers = headers.append('Accept', 'application/json'); headers = headers.append('Accept', 'application/json');
@@ -121,6 +94,14 @@ export class AuthService {
}); });
} }
/**
* Checks if token is present into storage
*/
public checkAuthenticationToken(): Observable<AuthTokenInfo> {
const token = this.getToken();
return isNotEmpty(token) ? Observable.of(token) : Observable.throw(false);
}
/** /**
* Create a new user * Create a new user
* @returns {User} * @returns {User}
@@ -137,7 +118,7 @@ export class AuthService {
* End session * End session
* @returns {Observable<boolean>} * @returns {Observable<boolean>}
*/ */
public signout(): Observable<boolean> { public logout(): Observable<boolean> {
// Normally you would do an HTTP request sign end the session // Normally you would do an HTTP request sign end the session
// but, let's just return an observable of true. // but, let's just return an observable of true.
let headers = new HttpHeaders(); let headers = new HttpHeaders();
@@ -168,11 +149,12 @@ export class AuthService {
public storeToken(token: AuthTokenInfo) { public storeToken(token: AuthTokenInfo) {
// Save authentication token info // Save authentication token info
return this.storage.store(TOKENITEM, JSON.stringify(token)); return this.storage.set(TOKENITEM, token);
} }
public removeToken() { public removeToken() {
// Remove authentication token info // Remove authentication token info
console.log('REMOVE!!!!');
return this.storage.remove(TOKENITEM); return this.storage.remove(TOKENITEM);
} }

View File

@@ -1,3 +1,5 @@
export const TOKENITEM = 'dsAuthInfo';
export class AuthTokenInfo { export class AuthTokenInfo {
public accessToken: string; public accessToken: string;
public expires?: number; public expires?: number;

View File

@@ -65,6 +65,11 @@ export class ResponseCacheService {
return result; return result;
} }
remove(key: string): void {
if (this.has(key)) {
this.store.dispatch(new ResponseCacheRemoveAction(key));
}
}
/** /**
* Check whether a ResponseCacheEntry should still be cached * Check whether a ResponseCacheEntry should still be cached
* *

View File

@@ -44,7 +44,8 @@ import { AuthRequestService } from './auth/auth-request.service';
import { AuthResponseParsingService } from './auth/auth-response-parsing.service'; import { AuthResponseParsingService } from './auth/auth-response-parsing.service';
import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { AuthInterceptor } from './auth/auth.interceptor'; import { AuthInterceptor } from './auth/auth.interceptor';
import { AuthStorageService } from './auth/auth-storage.service'; import { CookieService } from '../shared/services/cookie.service';
import { PlatformService } from '../shared/services/platform.service';
const IMPORTS = [ const IMPORTS = [
CommonModule, CommonModule,
@@ -66,9 +67,9 @@ const PROVIDERS = [
AuthRequestService, AuthRequestService,
AuthResponseParsingService, AuthResponseParsingService,
AuthService, AuthService,
AuthStorageService,
CommunityDataService, CommunityDataService,
CollectionDataService, CollectionDataService,
CookieService,
DSOResponseParsingService, DSOResponseParsingService,
DSpaceRESTv2Service, DSpaceRESTv2Service,
HostWindowService, HostWindowService,
@@ -76,6 +77,7 @@ const PROVIDERS = [
MetadataService, MetadataService,
ObjectCacheService, ObjectCacheService,
PaginationComponentOptions, PaginationComponentOptions,
PlatformService,
RemoteDataBuildService, RemoteDataBuildService,
RequestService, RequestService,
ResponseCacheService, ResponseCacheService,
@@ -90,7 +92,7 @@ const PROVIDERS = [
SubmissionSectionsConfigService, SubmissionSectionsConfigService,
UUIDService, UUIDService,
{ provide: NativeWindowService, useFactory: NativeWindowFactory }, { provide: NativeWindowService, useFactory: NativeWindowFactory },
// register TokenInterceptor as HttpInterceptor // register AuthInterceptor as HttpInterceptor
{ {
provide: HTTP_INTERCEPTORS, provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor, useClass: AuthInterceptor,

View File

@@ -35,18 +35,17 @@ export class AuthNavMenuComponent implements OnDestroy, OnInit {
protected subs: Subscription[] = []; protected subs: Subscription[] = [];
constructor( constructor(
private appStore: Store<AppState>, private store: Store<AppState>,
private coreStore: Store<CoreState>,
public windowService: HostWindowService) { public windowService: HostWindowService) {
} }
ngOnInit(): void { ngOnInit(): void {
// set loading // set loading
this.isAuthenticated = this.coreStore.select(isAuthenticated); this.isAuthenticated = this.store.select(isAuthenticated);
this.user = this.appStore.select(getAuthenticatedUser); this.user = this.store.select(getAuthenticatedUser);
this.subs.push(this.appStore.select(routerStateSelector) this.subs.push(this.store.select(routerStateSelector)
.filter((router: RouterReducerState) => isNotUndefined(router)) .filter((router: RouterReducerState) => isNotUndefined(router))
.subscribe((router: RouterReducerState) => { .subscribe((router: RouterReducerState) => {
this.showAuth = router.state.url !== '/login'; this.showAuth = router.state.url !== '/login';

View File

@@ -1,8 +1,9 @@
import { HttpClient, HttpClientModule } from '@angular/common/http'; import { HttpClient, HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule, makeStateKey, TransferState } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { REQUEST } from '@nguniversal/express-engine/tokens';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader'; import { TranslateHttpLoader } from '@ngx-translate/http-loader';
@@ -15,10 +16,16 @@ import { AppModule } from '../../app/app.module';
import { DSpaceBrowserTransferStateModule } from '../transfer-state/dspace-browser-transfer-state.module'; import { DSpaceBrowserTransferStateModule } from '../transfer-state/dspace-browser-transfer-state.module';
import { DSpaceTransferState } from '../transfer-state/dspace-transfer-state.service'; import { DSpaceTransferState } from '../transfer-state/dspace-transfer-state.service';
export const REQ_KEY = makeStateKey<string>('req');
export function createTranslateLoader(http: HttpClient) { export function createTranslateLoader(http: HttpClient) {
return new TranslateHttpLoader(http, 'assets/i18n/', '.json'); return new TranslateHttpLoader(http, 'assets/i18n/', '.json');
} }
export function getRequest(transferState: TransferState): any {
return transferState.get<any>(REQ_KEY, {})
}
@NgModule({ @NgModule({
bootstrap: [AppComponent], bootstrap: [AppComponent],
imports: [ imports: [
@@ -45,6 +52,13 @@ export function createTranslateLoader(http: HttpClient) {
}), }),
AppModule AppModule
], ],
providers: [
{
provide: REQUEST,
useFactory: getRequest,
deps: [TransferState]
}
]
}) })
export class BrowserAppModule { export class BrowserAppModule {
constructor( constructor(