mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 18:14:17 +00:00
fixed auth module
This commit is contained in:
@@ -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'])
|
||||||
|
@@ -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) =>
|
||||||
|
@@ -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);
|
||||||
|
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -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;
|
||||||
|
@@ -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>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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)});
|
||||||
|
@@ -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:
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
5
src/app/core/cache/response-cache.service.ts
vendored
5
src/app/core/cache/response-cache.service.ts
vendored
@@ -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
|
||||||
*
|
*
|
||||||
|
@@ -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,
|
||||||
|
@@ -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';
|
||||||
|
@@ -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(
|
||||||
|
Reference in New Issue
Block a user