import { Injectable } from '@angular/core' ; import { HttpEvent , HttpHandler , HttpInterceptor , HttpRequest , HttpResponse , HttpErrorResponse , HttpEventType , } from '@angular/common/http' ; import { from , Observable , combineLatest , throwError , race } from 'rxjs' ; import { catchError , finalize , first , map , switchMap , tap , } from 'rxjs/operators' ; import { MultiFactorLazyService } from './multi-factor-auth-lazy.service' ; import { MultiFactorAuthService , MultiFactorRootPanel , } from './multi-factor-auth-service' ; import { FormToastService } from '../../../../common/services/form-toast.service' ; @ Injectable ( ) export class MultiFactorHttpInterceptorService implements HttpInterceptor { constructor ( private multiFactorModalService , private multiFactorAuthService , private toastService ) { } /**
     * Add our two factor headers
     */ addHeaders ( request , payload ) { let headers = request . headers ; if ( payload . code ) { headers = headers . set ( 'X-MINDS-2FA-CODE' , payload . code ) ; } if ( payload . smsSecretKey ) { headers = headers . set ( 'X-MINDS-SMS-2FA-KEY' , payload . smsSecretKey ) ; } if ( payload . emailSecretKey ) { headers = headers . set ( 'X-MINDS-EMAIL-2FA-KEY' , payload . emailSecretKey ) ; } return request . clone ( { headers } ) ; } /**
     * This function will detect if TwoFactor is required, open the two factor
     * modal, apply headers to request and retry
     */ handleResponseError ( err , req , next ) { if ( [ 'Minds::Core::Security::TwoFactor::TwoFactorRequiredException' , 'Minds::Core::Security::TwoFactor::TwoFactorInvalidCodeException' , ] . indexOf ( err ?. error ?. errorId ) > - 1 ) { if ( err ?. error . errorId === 'Minds::Core::Security::TwoFactor::TwoFactorRequiredException' ) { const smsKey = err . headers . get ( 'X-MINDS-SMS-2FA-KEY' ) ; const emailKey = err . headers . get ( 'X-MINDS-EMAIL-2FA-KEY' ) ; let mfaType = 'email' ; if ( smsKey ) { mfaType = 'sms' ; } else if ( emailKey ) { } else { mfaType = 'totp' ; } this . multiFactorAuthService . originalRequest$ . next ( req ) ; this . multiFactorAuthService . mfaType$ . next ( mfaType ) ; this . multiFactorAuthService . mfaSecretKey$ . next ( smsKey || emailKey ) ; } return race ( [ this . multiFactorAuthService . mfaPayload$ , from ( this . multiFactorModalService . open ( { authType : this . multiFactorAuthService . mfaType$ . getValue ( ) , } ) ) , ] ) . pipe ( first ( ) , switchMap ( payload => { if ( ! payload ) { throw 'Front::TwoFactorAborted' ; } req = this . addHeaders ( req , payload ) ; return next . handle ( req ) . pipe ( catchError ( err => { if ( err !== 'Front::TwoFactorAborted' ) this . toastService . error ( err ?. error ?. message ?? `An unknown error has occurred` ) ; return this . handleResponseError ( err , req , next ) ; } ) , finalize ( ( ) => { this . multiFactorModalService . dismiss ( { success : true } ) ; } ) ) ; } ) ) ; } return throwError ( err ) ; } /**
     * This intercepts the http requests across the app
     * We use it to catch any errors and pass to handleResponseError above
     */ intercept ( req , next ) { return next . handle ( req ) . pipe ( catchError ( err => { return this . handleResponseError ( err , req , next ) ; } ) ) ; } }