Skip to content
Snippets Groups Projects
auth.effects.ts 4.2 KiB
Newer Older
Hugo BAYOUD's avatar
Hugo BAYOUD committed
import { Injectable } from "@angular/core";
import { Router } from "@angular/router";
import { Actions, Effect, ofType } from "@ngrx/effects";
import { select, Store } from "@ngrx/store";
import { EMPTY, of, Subscription } from "rxjs";
import { map, catchError, exhaustMap, tap, switchMap, withLatestFrom } from "rxjs/operators";

import { User } from "../../models/user.model";
import { AuthService } from "../../services/auth.service";
import { AuthActionsTypes, SetCurrentUser, SigninError, SigninSuccess, SignupError, SignupSuccess, TryFetchCurrentUser, TrySignin, TrySignup } from "../actions/auth.actions";
import { State } from "../../store";
import { tokenAuthSelector } from "../selectors/auth.selectors";
import { UserService } from "../../services/user.service";
import { HttpErrorResponse } from "@angular/common/http";

@Injectable()
export class AuthEffects {
	private subscription: Subscription = null;
Hugo BAYOUD's avatar
Hugo BAYOUD committed

	constructor(
		private actions$: Actions,
		private authService: AuthService,
		private router: Router,
		private store: Store<State>,
		private userService: UserService
	) {}

	@Effect()
 	trySignUp$ = this.actions$.pipe(
		ofType(AuthActionsTypes.TRY_SIGNUP),
		map(( action: TrySignup ) => action.payload),
		exhaustMap((user: User) => 
			this.authService
				.signup(user)
				.pipe(
					map((user: User) => new SignupSuccess(user)),
					catchError((error: any) => of(new SignupError(error)))
				)
		)
 	);

	@Effect({dispatch: false})
	signupSuccess$ = this.actions$.pipe(
		ofType(AuthActionsTypes.SIGNUP_SUCCESS),
		tap(() => this.router.navigate(['/signin'], {queryParams: { registered: 'true' } }))
	);

	@Effect()
	trySignin$ = this.actions$.pipe(
	 	ofType(AuthActionsTypes.TRY_SIGNIN),
	 	map(( action: TrySignin ) => action.payload),
	 	exhaustMap((credentials: { email: string, password: string}) =>
		 	this.authService.signin(credentials).pipe(
				map((token: string) => {
					return new SigninSuccess(token)
				}),
				catchError((error: HttpErrorResponse) => {
					let message = `Erreur serveur survenue. Réessayer ultérieurement.`;
					if (error.status === 401) {
						message = `Le mot de passe ou l'adresse mail n'existent pas.`;
					}

					if (error.status === 404) {
						message = `Base de données indisponible pour le moment. Réessayer ultérieurement.`;
					}

					return of(new SigninError(message))
				})
			)
		)
	);

	// On active la subscription pour le initTimer uniquement s'il n'existe pas déjà un subscription
	// On veut un seul initTimer(). On l'init quand l'user se connecte
	@Effect({ dispatch: false })
	signinSuccess$ = this.actions$.pipe(
		ofType(AuthActionsTypes.SIGNIN_SUCCESS),
		map((action: SigninSuccess) => action.payload),
		tap((token: string) => {
			localStorage.setItem('jwt', token);
Hugo BAYOUD's avatar
Hugo BAYOUD committed
				this.subscription = this.authService.initRefreshToken().subscribe();
				this.router.navigate(['/profile']);
			}
		}),
	);

	// Si on a pas de token, on ne va pas demandé un refresh_token au back_end.
	// On utilise donc le store dans l'effet pour le vérifier (withLatestFrom)
Hugo BAYOUD's avatar
Hugo BAYOUD committed
	@Effect()
	tryRefreshToken$ = this.actions$.pipe(
		ofType(AuthActionsTypes.TRY_REFRESH_TOKEN),
		withLatestFrom(this.store.pipe(select(tokenAuthSelector))),
		switchMap(([action, token]) => {
			if (token) {
				return this.authService.refreshToken().pipe(
					map((jwtoken: string) => new SigninSuccess(jwtoken)),
					catchError((err: any) => {
						if(this.subscription) {
							this.subscription.unsubscribe();
Hugo BAYOUD's avatar
Hugo BAYOUD committed
						}
						localStorage.removeItem('jwt');
			
						return EMPTY;
					})
				);
			} else {
				return EMPTY;
			}
		})
	);

	@Effect({ dispatch: false })
	logout$ = this.actions$.pipe(
		ofType(AuthActionsTypes.LOGOUT),
		tap((err: any) => {
			if(this.subscription) {
				this.subscription.unsubscribe();
			}
			localStorage.removeItem('jwt');
			this.router.navigate(['/']);
		})
	)

	@Effect()
	tryFetchCurrentUser$ = this.actions$.pipe(
		ofType(AuthActionsTypes.TRY_FETCH_CURRENT_USER),
		switchMap(() => {
			return this.userService.getCurrentUser().pipe(
				map((user: User) => new SetCurrentUser(user)),
				catchError((err: any) => {
					console.warn('error in tryFetchCurrentUser')
					return EMPTY;
				})
			);
		})
	);
}