import { Process , Processor , InjectQueue , OnQueueCompleted } from '@nestjs/bull' ; import { Logger , BadRequestException } from '@nestjs/common' ; import { Job , Queue } from 'bull' ; import { LibDidSiopService , SIOPRequestCall , SIOP_KEY_ALGO , SIOPResponseMode , DID_SIOP_ERRORS } from '@lib/did-siop' ; import { WalletService , WALLET } from '@lib/wallet' ; import { SiopUriRequest , SiopResponse , SiopAckRequest , QRResponse } from './dtos/SIOP' ; import { doPostCall , getUserDid , getJwtNonce } from 'src/util/Util' ; import { BASE_URL } from 'src/Config' ; import QRCode from 'qrcode' ; import io from 'socket.io-client' ; import Redis from 'ioredis' ; @ Processor ( 'siop' ) export class SiopProcessor { constructor ( @ InjectQueue ( 'siopError' ) private readonly siopErrorQueue ) { } private readonly logger = new Logger ( SiopProcessor . name ) ; private readonly jwtRedis = new Redis ( { keyPrefix : "jwt:" } ) ; private readonly nonceRedis = new Redis ( { keyPrefix : "nonce:" } ) ; private readonly socket = io ( BASE_URL ) ; @ Process ( 'userRequest' ) handleSiopRequest ( job ) { this . logger . debug ( 'SIOP Request received.' ) ; this . logger . debug ( `Processing job ${ job . id } of type ${ job . name }` ) ; if ( ! job || ! job . data || ! job . data . clientId || ! job . data . sessionId ) { throw new BadRequestException ( DID_SIOP_ERRORS . INVALID_PARAMS ) ; } const wallet = WalletService . Instance . wallet ; const siopRequestCall = { iss : wallet . did , client_id : job . data . clientId , key : wallet . key , alg : [ SIOP_KEY_ALGO . ES256K , SIOP_KEY_ALGO . EdDSA , SIOP_KEY_ALGO . RS256 ] , did_doc : wallet . didDoc , response_mode : SIOPResponseMode . FORM_POST , request_uri : `http://localhost:9003/siop/jwts/${ job . data . sessionId }` } ; const siopRequestJwt = LibDidSiopService . createSIOPRequest ( siopRequestCall ) ; this . logger . debug ( `SIOP Request JWT: ${ siopRequestJwt }` ) ; this . jwtRedis . set ( job . data . sessionId , siopRequestJwt ) ; const siopUri = LibDidSiopService . createUriRequest ( siopRequestCall ) ; this . logger . debug ( `SIOP Request URI: ${ siopUri }` ) ; this . nonceRedis . set ( job . data . sessionId , getJwtNonce ( siopRequestJwt ) ) ; this . logger . debug ( 'SIOP Request completed.' ) ; return { siopUri } ; } @ OnQueueCompleted ( ) async onCompleted ( job , result ) { this . logger . debug ( 'SIOP Request event completed.' ) ; this . logger . debug ( `Processing result` ) ; this . logger . debug ( 'Result: ' + JSON . stringify ( result ) ) ; if ( ! job || ! job . data || ! result || ! result . siopUri ) { throw new BadRequestException ( DID_SIOP_ERRORS . INVALID_PARAMS ) ; } if ( ! job . data . clientUriRedirect ) { const imageQr = await QRCode . toDataURL ( result . siopUri ) ; const qrResponse = { imageQr , siopUri : result . siopUri } ; this . socket . emit ( 'sendSIOPRequestJwtToFrontend' , qrResponse ) ; } if ( job . data . clientUriRedirect ) { const response = await doPostCall ( result , job . data . clientUriRedirect ) ; this . logger . debug ( 'Response: ' + JSON . stringify ( response ) ) ; if ( ! response || ! response . validationRequest ) { this . logger . debug ( 'Error on SIOP Request Validation.' ) ; await this . siopErrorQueue . add ( 'errorSiopRequestValidation' ) ; } } } }