import { Injectable , NgZone } from '@angular/core' ; import { Router } from '@angular/router' ; import { Action , Selector , State , StateContext } from '@ngxs/store' ; import { OAuthService } from 'angular-oauth2-oidc' ; import { map } from 'rxjs/operators' ; import { AuthMode , AuthModeChanged , ChangeAuthMode , Login , LoginCanceled , LoginSuccess , Logout , LogoutSuccess , } from './auth.actions' ; import { AuthService } from './auth.service' ; import { authConfigCodeFlow , authConfigHybridFlow , authConfigImplicit , authConfigPassword } from './oauth.config' ; export interface AuthStateModel { isLoggedIn : boolean ; profile : any ; authMode : AuthMode ; } @ State < AuthStateModel > ( { name : 'auth' , defaults : { isLoggedIn : false , profile : { } , authMode : AuthMode . ImplicitFLow , } , } ) @ Injectable ( { providedIn : 'root' , } ) export class AuthState { constructor ( private authService , private oauthService , private router , private zone ) { } @ Selector ( ) static isLoggedIn ( state ) { return state . isLoggedIn ; } @ Selector ( ) static profile ( state ) { return state . profile ; } @ Selector ( ) static authMode ( state ) { return state ? state . authMode : AuthMode . ImplicitFLow ; } @ Action ( LoginSuccess ) loginSuccess ( { getState , patchState } , { payload } ) { patchState ( { isLoggedIn : true , profile : payload , } ) ; this . authService . startAutoRefreshToken ( ) ; if ( getState ( ) . authMode === AuthMode . PasswordFlow ) { this . zone . run ( ( ) => this . router . navigate ( [ '/dashboard' ] ) ) ; } } @ Action ( [ LogoutSuccess , LoginCanceled ] ) logoutSuccess ( { getState , setState } ) { setState ( { isLoggedIn : false , profile : { } , authMode : getState ( ) . authMode , } ) ; this . authService . stopAutoRefreshToken ( ) ; this . zone . run ( ( ) => this . router . navigate ( [ '/home' ] ) ) ; } @ Action ( AuthModeChanged ) authModeChanged ( { getState , patchState } , { payload } ) { patchState ( { authMode : payload , } ) ; } @ Action ( ChangeAuthMode ) async changeAuthMode ( { getState , dispatch } , { payload } ) { if ( getState ( ) . authMode !== payload ) { switch ( payload ) { case AuthMode . PasswordFlow : this . oauthService . configure ( authConfigPassword ) ; break ; case AuthMode . CodeFLow : this . oauthService . configure ( authConfigCodeFlow ) ; break ; case AuthMode . HybridFlow : this . oauthService . configure ( authConfigHybridFlow ) ; break ; default : this . oauthService . configure ( authConfigImplicit ) ; break ; } await this . oauthService . loadDiscoveryDocument ( ) ; dispatch ( new AuthModeChanged ( payload ) ) ; } } @ Action ( Logout ) logout ( { getState } ) { return this . authService . logout ( ) ; } @ Action ( Login ) login ( { getState , dispatch } , { payload } ) { return this . zone . run ( ( ) => this . authService . login ( payload ) . pipe ( map ( ( profile ) => { if ( profile === false ) { dispatch ( new LoginCanceled ( ) ) ; } else { dispatch ( new LoginSuccess ( profile ) ) ; } } ) ) ) ; } }