'use strict' ; import { Router , RequestHandler , Request , Response , NextFunction } from 'express' ; import { setupMetaverseAPI , finishMetaverseAPI } from '@Route-Tools/middleware' ; import { Requests , RequestType } from '@Entities/Requests' ; import { RequestEntity } from '@Entities/RequestEntity' ; import { Accounts } from '@Entities/Accounts' ; import { accountFromAuthToken , usernameFromParams } from '@Route-Tools/middleware' ; import { IsNullOrEmpty , IsNotNullOrEmpty } from '@Tools/Misc' ; import { Logger } from '@Tools/Logging' ; const procPostUserConnectionRequest = async ( req , resp , next ) => { if ( req . vAuthAccount ) { if ( req . body . user_connection_request ) { const thisNode = req . body . user_connection_request . node_id ; const otherNode = req . body . user_connection_request . proposed_node_id ; if ( req . vAuthAccount . locationNodeId ) { if ( req . vAuthAccount . locationNodeId === thisNode ) { Logger . debug ( `procPostUserConnectionRequest: request from ${ req . vAuthAccount . username } and locationNodeid matches main node` ) ; } else { if ( req . vAuthAccount . locationNodeId === otherNode ) { Logger . debug ( `procPostUserConnectionRequest: request from ${ req . vAuthAccount . username } and locationNodeid matches proposed node` ) ; } else { Logger . debug ( `procPostUserConnectionRequest: request from ${ req . vAuthAccount . username } and locationNodeid does not match either node` ) ; } ; } ; } else { Logger . debug ( `procPostUserConnectionRequest: request from ${ req . vAuthAccount . username } and no nodeID info` ) ; } ; let pending = true ; const previousAsk = await Requests . getWithRequestBetween ( thisNode , otherNode , RequestType . HANDSHAKE , 'requesterNodeId' , 'targetNodeId' ) ; if ( IsNotNullOrEmpty ( previousAsk ) ) { Logger . debug ( `procPostUserConnectionRequest: previous ask. by=${ req . vAuthAccount . id }, this=${ thisNode }, other=${ otherNode }` ) ; if ( previousAsk . requesterNodeId === thisNode ) { if ( previousAsk . targetAccepted ) { Logger . debug ( `procPostUserConnectionRequest: was accepted. by=${ req . vAuthAccount . id }, this=${ thisNode }, other=${ otherNode }` ) ; await BuildNewConnection ( previousAsk ) ; await BuildConnectionResponse ( req , previousAsk . targetAccountId ) ; pending = false ; } else { Logger . debug ( `procPostUserConnectionRequest: other hasn't accepted. by=${ req . vAuthAccount . id }, this=${ thisNode }, other=${ otherNode }` ) ; } ; } else { Logger . debug ( `procPostUserConnectionRequest: I accept. by=${ req . vAuthAccount . id }, this=${ thisNode }, other=${ otherNode }` ) ; previousAsk . targetAccepted = true ; previousAsk . targetAccountId = req . vAuthAccount . id ; Requests . update ( previousAsk , { 'targetAccepted' : true , 'targetAccountId' : req . vAuthAccount . id } ) ; const areConnected = await BuildNewConnection ( previousAsk ) ; if ( areConnected ) { await BuildConnectionResponse ( req , previousAsk . requestingAccountId ) ; pending = false ; } else { Logger . error ( `procPostUserConnectionRequest: BuildNewConnection failed. by=${ req . vAuthAccount . id }, this=${ thisNode }, other=${ otherNode }` ) ; req . vRestResp . respondFailure ( 'error making connection' ) ; } ; } ; } else { Logger . debug ( `procPostUserConnectionRequest: new request. by=${ req . vAuthAccount . id }, this=${ thisNode }, other=${ otherNode }` ) ; const newRequest = await Requests . createHandshakeRequest ( thisNode , otherNode ) ; newRequest . requesterAccepted = true ; newRequest . requestingAccountId = req . vAuthAccount . id ; await Requests . add ( newRequest ) ; } ; if ( pending ) { req . vRestResp . Data = { 'connection' : 'pending' } ; } ; } else { req . vRestResp . respondFailure ( 'badly formed request' ) ; } ; } else { req . vRestResp . respondFailure ( req . vAccountError ?? 'Not logged in' ) ; } ; next ( ) ; } ; async function BuildNewConnection ( pRequest ) { let wasConnected = false ; const requestingAccount = await Accounts . getAccountWithId ( pRequest . requestingAccountId ) ; const targetAccount = await Accounts . getAccountWithId ( pRequest . targetAccountId ) ; if ( requestingAccount && targetAccount ) { await Accounts . makeAccountsConnected ( requestingAccount , targetAccount ) ; wasConnected = true ; } else { Logger . error ( `connection_request: acceptance for connection but accounts not found` ) ; Logger . error ( `connection_request:   reqAccId=${ pRequest . requestingAccountId }, tgtAccId=${ pRequest . targetAccountId }` ) ; } ; return wasConnected ; } ; async function BuildConnectionResponse ( req , pOtherAccountId ) { const otherAccount = await Accounts . getAccountWithId ( pOtherAccountId ) ; req . vRestResp . Data = { 'connection' : { 'new_connection' : true , 'username' : otherAccount ? otherAccount . username : 'UNKNOWN' } } ; } ; const procDeleteUserConnectionRequest = async ( req , resp , next ) => { if ( req . vAuthAccount ) { Logger . debug ( `procDeleteUserConnectionRequest: deleting for ${ req . vAuthAccount . id }` ) ; await Requests . removeAllMyRequests ( req . vAuthAccount . id , RequestType . HANDSHAKE ) ; } else { req . vRestResp . respondFailure ( req . vAccountError ?? 'Not logged in' ) ; } ; next ( ) ; } ; export const name = '/api/v1/user/connection_request' ; export const router = Router ( ) ; router . post ( '/api/v1/user/connection_request' , [ setupMetaverseAPI , accountFromAuthToken , procPostUserConnectionRequest , finishMetaverseAPI ] ) ; router . delete ( '/api/v1/user/connection_request' , [ setupMetaverseAPI , accountFromAuthToken , procDeleteUserConnectionRequest , finishMetaverseAPI ] ) ;