Added auth action that allows to retrieve token once check on authentication cooke is successful

This commit is contained in:
Giuseppe Digilio
2020-01-17 11:51:55 +01:00
parent 0eac9c6369
commit 1e99071907
3 changed files with 65 additions and 9 deletions

View File

@@ -1,9 +1,7 @@
// import @ngrx // import @ngrx
import { Action } from '@ngrx/store'; import { Action } from '@ngrx/store';
// import type function // import type function
import { type } from '../../shared/ngrx/type'; import { type } from '../../shared/ngrx/type';
// 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'; import { AuthTokenInfo } from './models/auth-token-info.model';
@@ -27,6 +25,7 @@ export const AuthActionTypes = {
REFRESH_TOKEN: type('dspace/auth/REFRESH_TOKEN'), REFRESH_TOKEN: type('dspace/auth/REFRESH_TOKEN'),
REFRESH_TOKEN_SUCCESS: type('dspace/auth/REFRESH_TOKEN_SUCCESS'), REFRESH_TOKEN_SUCCESS: type('dspace/auth/REFRESH_TOKEN_SUCCESS'),
REFRESH_TOKEN_ERROR: type('dspace/auth/REFRESH_TOKEN_ERROR'), REFRESH_TOKEN_ERROR: type('dspace/auth/REFRESH_TOKEN_ERROR'),
RETRIEVE_TOKEN: type('dspace/auth/RETRIEVE_TOKEN'),
ADD_MESSAGE: type('dspace/auth/ADD_MESSAGE'), ADD_MESSAGE: type('dspace/auth/ADD_MESSAGE'),
RESET_MESSAGES: type('dspace/auth/RESET_MESSAGES'), RESET_MESSAGES: type('dspace/auth/RESET_MESSAGES'),
LOG_OUT: type('dspace/auth/LOG_OUT'), LOG_OUT: type('dspace/auth/LOG_OUT'),
@@ -252,6 +251,15 @@ export class RefreshTokenErrorAction implements Action {
public type: string = AuthActionTypes.REFRESH_TOKEN_ERROR; 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. * Sign up.
* @class RegistrationAction * @class RegistrationAction
@@ -386,7 +394,11 @@ export type AuthActions
| RegistrationErrorAction | RegistrationErrorAction
| RegistrationSuccessAction | RegistrationSuccessAction
| AddAuthenticationMessageAction | AddAuthenticationMessageAction
| RefreshTokenAction
| RefreshTokenErrorAction
| RefreshTokenSuccessAction
| ResetAuthenticationMessagesAction | ResetAuthenticationMessagesAction
| RetrieveAuthMethodsAction | RetrieveAuthMethodsAction
| RetrieveAuthMethodsSuccessAction | RetrieveAuthMethodsSuccessAction
| RetrieveAuthMethodsErrorAction; | RetrieveAuthMethodsErrorAction
| RetrieveTokenAction;

View File

@@ -17,12 +17,12 @@ import {
CheckAuthenticationTokenCookieAction, CheckAuthenticationTokenCookieAction,
LogOutErrorAction, LogOutErrorAction,
LogOutSuccessAction, LogOutSuccessAction,
RefreshTokenAction,
RefreshTokenErrorAction, RefreshTokenErrorAction,
RefreshTokenSuccessAction, RefreshTokenSuccessAction,
RetrieveAuthMethodsAction, RetrieveAuthMethodsAction,
RetrieveAuthMethodsErrorAction, RetrieveAuthMethodsErrorAction,
RetrieveAuthMethodsSuccessAction RetrieveAuthMethodsSuccessAction,
RetrieveTokenAction
} from './auth.actions'; } from './auth.actions';
import { authMethodsMock, AuthServiceStub } from '../../shared/testing/auth-service-stub'; import { authMethodsMock, AuthServiceStub } from '../../shared/testing/auth-service-stub';
import { AuthService } from './auth.service'; import { AuthService } from './auth.service';
@@ -161,7 +161,7 @@ describe('AuthEffects', () => {
describe('checkTokenCookie$', () => { describe('checkTokenCookie$', () => {
describe('when check token succeeded', () => { 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( spyOn((authEffects as any).authService, 'checkAuthenticationCookie').and.returnValue(
observableOf( observableOf(
{ authenticated: true { authenticated: true
@@ -169,7 +169,7 @@ describe('AuthEffects', () => {
); );
actions = hot('--a-', {a: {type: AuthActionTypes.CHECK_AUTHENTICATION_TOKEN_COOKIE}}); 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); 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('logOut$', () => {
describe('when refresh token succeeded', () => { describe('when refresh token succeeded', () => {

View File

@@ -27,7 +27,7 @@ import {
RegistrationSuccessAction, RegistrationSuccessAction,
RetrieveAuthMethodsAction, RetrieveAuthMethodsAction,
RetrieveAuthMethodsErrorAction, RetrieveAuthMethodsErrorAction,
RetrieveAuthMethodsSuccessAction RetrieveAuthMethodsSuccessAction, RetrieveTokenAction
} 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';
@@ -97,7 +97,7 @@ export class AuthEffects {
return this.authService.checkAuthenticationCookie().pipe( return this.authService.checkAuthenticationCookie().pipe(
map((response: AuthStatus) => { map((response: AuthStatus) => {
if (response.authenticated) { if (response.authenticated) {
return new RefreshTokenAction(null); return new RetrieveTokenAction();
} else { } else {
return new RetrieveAuthMethodsAction(response); return new RetrieveAuthMethodsAction(response);
} }
@@ -119,6 +119,18 @@ export class AuthEffects {
}) })
); );
@Effect()
public retrieveToken$: Observable<Action> = 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() @Effect()
public refreshToken$: Observable<Action> = this.actions$.pipe(ofType(AuthActionTypes.REFRESH_TOKEN), public refreshToken$: Observable<Action> = this.actions$.pipe(ofType(AuthActionTypes.REFRESH_TOKEN),
switchMap((action: RefreshTokenAction) => { switchMap((action: RefreshTokenAction) => {