From 1e990719078cfd559d345f8a8387e17f9db85dbd Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 17 Jan 2020 11:51:55 +0100 Subject: [PATCH] Added auth action that allows to retrieve token once check on authentication cooke is successful --- src/app/core/auth/auth.actions.ts | 18 ++++++++++-- src/app/core/auth/auth.effects.spec.ts | 40 +++++++++++++++++++++++--- src/app/core/auth/auth.effects.ts | 16 +++++++++-- 3 files changed, 65 insertions(+), 9 deletions(-) diff --git a/src/app/core/auth/auth.actions.ts b/src/app/core/auth/auth.actions.ts index 7cff3fd1c7..6b2dcc3ff9 100644 --- a/src/app/core/auth/auth.actions.ts +++ b/src/app/core/auth/auth.actions.ts @@ -1,9 +1,7 @@ // import @ngrx import { Action } from '@ngrx/store'; - // import type function import { type } from '../../shared/ngrx/type'; - // import models import { EPerson } from '../eperson/models/eperson.model'; import { AuthTokenInfo } from './models/auth-token-info.model'; @@ -27,6 +25,7 @@ export const AuthActionTypes = { REFRESH_TOKEN: type('dspace/auth/REFRESH_TOKEN'), REFRESH_TOKEN_SUCCESS: type('dspace/auth/REFRESH_TOKEN_SUCCESS'), REFRESH_TOKEN_ERROR: type('dspace/auth/REFRESH_TOKEN_ERROR'), + RETRIEVE_TOKEN: type('dspace/auth/RETRIEVE_TOKEN'), ADD_MESSAGE: type('dspace/auth/ADD_MESSAGE'), RESET_MESSAGES: type('dspace/auth/RESET_MESSAGES'), LOG_OUT: type('dspace/auth/LOG_OUT'), @@ -252,6 +251,15 @@ export class RefreshTokenErrorAction implements Action { public type: string = AuthActionTypes.REFRESH_TOKEN_ERROR; } +/** + * Retrieve authentication token. + * @class RetrieveTokenAction + * @implements {Action} + */ +export class RetrieveTokenAction implements Action { + public type: string = AuthActionTypes.RETRIEVE_TOKEN; +} + /** * Sign up. * @class RegistrationAction @@ -386,7 +394,11 @@ export type AuthActions | RegistrationErrorAction | RegistrationSuccessAction | AddAuthenticationMessageAction + | RefreshTokenAction + | RefreshTokenErrorAction + | RefreshTokenSuccessAction | ResetAuthenticationMessagesAction | RetrieveAuthMethodsAction | RetrieveAuthMethodsSuccessAction - | RetrieveAuthMethodsErrorAction; + | RetrieveAuthMethodsErrorAction + | RetrieveTokenAction; diff --git a/src/app/core/auth/auth.effects.spec.ts b/src/app/core/auth/auth.effects.spec.ts index ba67a95ab1..1f6fdc2bc1 100644 --- a/src/app/core/auth/auth.effects.spec.ts +++ b/src/app/core/auth/auth.effects.spec.ts @@ -17,12 +17,12 @@ import { CheckAuthenticationTokenCookieAction, LogOutErrorAction, LogOutSuccessAction, - RefreshTokenAction, RefreshTokenErrorAction, RefreshTokenSuccessAction, RetrieveAuthMethodsAction, RetrieveAuthMethodsErrorAction, - RetrieveAuthMethodsSuccessAction + RetrieveAuthMethodsSuccessAction, + RetrieveTokenAction } from './auth.actions'; import { authMethodsMock, AuthServiceStub } from '../../shared/testing/auth-service-stub'; import { AuthService } from './auth.service'; @@ -161,7 +161,7 @@ describe('AuthEffects', () => { describe('checkTokenCookie$', () => { describe('when check token succeeded', () => { - it('should return a REFRESH_TOKEN action in response to a CHECK_AUTHENTICATION_TOKEN_COOKIE action when authenticated is true', () => { + it('should return a RETRIEVE_TOKEN action in response to a CHECK_AUTHENTICATION_TOKEN_COOKIE action when authenticated is true', () => { spyOn((authEffects as any).authService, 'checkAuthenticationCookie').and.returnValue( observableOf( { authenticated: true @@ -169,7 +169,7 @@ describe('AuthEffects', () => { ); actions = hot('--a-', {a: {type: AuthActionTypes.CHECK_AUTHENTICATION_TOKEN_COOKIE}}); - const expected = cold('--b-', {b: new RefreshTokenAction(null)}); + const expected = cold('--b-', {b: new RetrieveTokenAction()}); expect(authEffects.checkTokenCookie$).toBeObservable(expected); }); @@ -226,6 +226,38 @@ describe('AuthEffects', () => { }) }); + describe('retrieveToken$', () => { + describe('when user is authenticated', () => { + it('should return a AUTHENTICATE_SUCCESS action in response to a RETRIEVE_TOKEN action', () => { + actions = hot('--a-', { + a: { + type: AuthActionTypes.RETRIEVE_TOKEN + } + }); + + const expected = cold('--b-', {b: new AuthenticationSuccessAction(token)}); + + expect(authEffects.retrieveToken$).toBeObservable(expected); + }); + }); + + describe('when user is not authenticated', () => { + it('should return a AUTHENTICATE_ERROR action in response to a RETRIEVE_TOKEN action', () => { + spyOn((authEffects as any).authService, 'refreshAuthenticationToken').and.returnValue(observableThrow(new Error('Message Error test'))); + + actions = hot('--a-', { + a: { + type: AuthActionTypes.RETRIEVE_TOKEN + } + }); + + const expected = cold('--b-', {b: new AuthenticationErrorAction(new Error('Message Error test'))}); + + expect(authEffects.retrieveToken$).toBeObservable(expected); + }); + }); + }); + describe('logOut$', () => { describe('when refresh token succeeded', () => { diff --git a/src/app/core/auth/auth.effects.ts b/src/app/core/auth/auth.effects.ts index 9e860326c9..bef84971df 100644 --- a/src/app/core/auth/auth.effects.ts +++ b/src/app/core/auth/auth.effects.ts @@ -27,7 +27,7 @@ import { RegistrationSuccessAction, RetrieveAuthMethodsAction, RetrieveAuthMethodsErrorAction, - RetrieveAuthMethodsSuccessAction + RetrieveAuthMethodsSuccessAction, RetrieveTokenAction } from './auth.actions'; import { EPerson } from '../eperson/models/eperson.model'; import { AuthStatus } from './models/auth-status.model'; @@ -97,7 +97,7 @@ export class AuthEffects { return this.authService.checkAuthenticationCookie().pipe( map((response: AuthStatus) => { if (response.authenticated) { - return new RefreshTokenAction(null); + return new RetrieveTokenAction(); } else { return new RetrieveAuthMethodsAction(response); } @@ -119,6 +119,18 @@ export class AuthEffects { }) ); + @Effect() + public retrieveToken$: Observable = this.actions$.pipe( + ofType(AuthActionTypes.RETRIEVE_TOKEN), + switchMap((action: AuthenticateAction) => { + return this.authService.refreshAuthenticationToken(null).pipe( + take(1), + map((token: AuthTokenInfo) => new AuthenticationSuccessAction(token)), + catchError((error) => observableOf(new AuthenticationErrorAction(error))) + ); + }) + ); + @Effect() public refreshToken$: Observable = this.actions$.pipe(ofType(AuthActionTypes.REFRESH_TOKEN), switchMap((action: RefreshTokenAction) => {