Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/app/core/auth/auth.actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,16 @@ export class AuthenticatedAction implements Action {
public type: string = AuthActionTypes.AUTHENTICATED;
payload: AuthTokenInfo;

constructor(token: AuthTokenInfo) {
/**
* Whether we should consider the given authentication info final.
* If the backend restarted we may have a token that hasn't expired yet, but it will be invalid anyway.
* In this case we'll have to check twice.
*/
checkAgain: boolean;

constructor(token: AuthTokenInfo, checkAgain = false) {
this.payload = token;
this.checkAgain = checkAgain;
}
}

Expand Down
20 changes: 16 additions & 4 deletions src/app/core/auth/auth.effects.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,25 +156,37 @@ describe('AuthEffects', () => {

describe('when token is valid', () => {
it('should return a AUTHENTICATED_SUCCESS action in response to a AUTHENTICATED action', () => {
actions = hot('--a-', { a: { type: AuthActionTypes.AUTHENTICATED, payload: token } });
actions = hot('--a-', { a: new AuthenticatedAction(token) });

const expected = cold('--b-', { b: new AuthenticatedSuccessAction(true, token, EPersonMock._links.self.href) });

expect(authEffects.authenticated$).toBeObservable(expected);
});
});

describe('when token is not valid', () => {
describe('when token is expired', () => {
it('should return a AUTHENTICATED_ERROR action in response to a AUTHENTICATED action', () => {
spyOn((authEffects as any).authService, 'authenticatedUser').and.returnValue(observableThrow(new Error('Message Error test')));

actions = hot('--a-', { a: { type: AuthActionTypes.AUTHENTICATED, payload: token } });
actions = hot('--a-', { a: new AuthenticatedAction(token) });

const expected = cold('--b-', { b: new AuthenticatedErrorAction(new Error('Message Error test')) });

expect(authEffects.authenticated$).toBeObservable(expected);
});
});

describe('when token is not valid but also not expired (~ cookie)', () => {
it('should return a AUTHENTICATED_ERROR action in response to a AUTHENTICATED action', () => {
spyOn((authEffects as any).authService, 'authenticatedUser').and.returnValue(observableThrow(new Error('Message Error test')));

actions = hot('--a-', { a: new AuthenticatedAction(token, true) });

const expected = cold('--b-', { b: new CheckAuthenticationTokenCookieAction() });

expect(authEffects.authenticated$).toBeObservable(expected);
});
});
});

describe('authenticatedSuccess$', () => {
Expand Down Expand Up @@ -210,7 +222,7 @@ describe('AuthEffects', () => {

actions = hot('--a-', { a: { type: AuthActionTypes.CHECK_AUTHENTICATION_TOKEN } });

const expected = cold('--b-', { b: new AuthenticatedAction(token) });
const expected = cold('--b-', { b: new AuthenticatedAction(token, true) });

expect(authEffects.checkToken$).toBeObservable(expected);
});
Expand Down
10 changes: 8 additions & 2 deletions src/app/core/auth/auth.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,13 @@ export class AuthEffects {
switchMap((action: AuthenticatedAction) => {
return this.authService.authenticatedUser(action.payload).pipe(
map((userHref: string) => new AuthenticatedSuccessAction((userHref !== null), action.payload, userHref)),
catchError((error: unknown) => errorToAuthAction$(AuthenticatedErrorAction, error)),
catchError((error: unknown) => {
if (action.checkAgain) {
return of(new CheckAuthenticationTokenCookieAction());
} else {
return errorToAuthAction$(AuthenticatedErrorAction, error);
}
}),
);
}),
));
Expand Down Expand Up @@ -176,7 +182,7 @@ export class AuthEffects {
public checkToken$: Observable<Action> = createEffect(() => this.actions$.pipe(ofType(AuthActionTypes.CHECK_AUTHENTICATION_TOKEN),
switchMap(() => {
return this.authService.hasValidAuthenticationToken().pipe(
map((token: AuthTokenInfo) => new AuthenticatedAction(token)),
map((token: AuthTokenInfo) => new AuthenticatedAction(token, true)),
catchError((error: unknown) => of(new CheckAuthenticationTokenCookieAction())),
);
}),
Expand Down
Loading