Add timeout to promise, return undefined on error

This commit is contained in:
Yarmo Mackenbach 2020-12-20 22:44:37 +01:00
parent 7daececb99
commit 686f0e2a5e
2 changed files with 104 additions and 90 deletions

View file

@ -117,7 +117,6 @@ const verify = async (input, fingerprint, opts) => {
const res = await verify(user.notations, fingerprintFromKey, opts) const res = await verify(user.notations, fingerprintFromKey, opts)
resolve(res) resolve(res)
} catch (e) { } catch (e) {
console.error(`Claim verification failed: ${user.userData.id}`, e)
reject(e) reject(e)
} }
}) })
@ -136,7 +135,6 @@ const verify = async (input, fingerprint, opts) => {
const res = await verify(uri, fingerprint, opts) const res = await verify(uri, fingerprint, opts)
resolve(res) resolve(res)
} catch (e) { } catch (e) {
console.error(`Claim verification failed: ${uri}`, e)
reject(e) reject(e)
} }
}) })
@ -149,58 +147,75 @@ const verify = async (input, fingerprint, opts) => {
}) })
} }
const uri = input.replace(/^\s+|\s+$/g, '') const promiseClaim = new Promise(async (resolve, reject) => {
let verifErrors = [] let objResult = {
isVerified: null,
errors: [],
serviceproviderData: null,
}
const uri = input.replace(/^\s+|\s+$/g, '')
if (!fingerprint) { if (!fingerprint) {
fingerprint = null fingerprint = null
} }
const defaultOpts = { const defaultOpts = {
returnMatchesOnly: false, returnMatchesOnly: false,
proxyPolicy: 'adaptive', proxyPolicy: 'adaptive',
doipProxyHostname: 'proxy.keyoxide.org', doipProxyHostname: 'proxy.keyoxide.org',
} }
opts = mergeOptions(defaultOpts, opts ? opts : {}) opts = mergeOptions(defaultOpts, opts ? opts : {})
if (!validUrl.isUri(uri)) { if (!validUrl.isUri(uri)) {
throw new Error('Invalid URI') objResult.errors.push('invalid_uri')
} reject(objResult)
}
const spMatches = serviceproviders.match(uri, opts) const spMatches = serviceproviders.match(uri, opts)
if ('returnMatchesOnly' in opts && opts.returnMatchesOnly) { if ('returnMatchesOnly' in opts && opts.returnMatchesOnly) {
return spMatches resolve(spMatches)
} }
let claimVerificationDone = false, let claimVerificationDone = false,
claimVerificationResult, claimVerificationResult,
sp, sp,
iSp = 0, iSp = 0,
res, res,
proofData, proofData,
spData spData
while (!claimVerificationDone && iSp < spMatches.length) { while (!claimVerificationDone && iSp < spMatches.length) {
spData = spMatches[iSp] spData = spMatches[iSp]
spData.claim.fingerprint = fingerprint spData.claim.fingerprint = fingerprint
res = null res = null
if (spData.customRequestHandler instanceof Function) { if (spData.customRequestHandler instanceof Function) {
try { try {
proofData = await spData.customRequestHandler(spData, opts) proofData = await spData.customRequestHandler(spData, opts)
} catch (e) { } catch (e) {
verifErrors.push('custom_request_handler_failed') objResult.errors.push('custom_request_handler_failed')
} }
} else { } else {
switch (opts.proxyPolicy) { switch (opts.proxyPolicy) {
case 'adaptive': case 'adaptive':
if (spData.proof.useProxy) { if (spData.proof.useProxy) {
try { try {
proofData = await serviceproviders.proxyRequestHandler(spData, opts) proofData = await serviceproviders.proxyRequestHandler(spData, opts)
} catch(er) {} } catch(er) {}
} else { } else {
try {
proofData = await serviceproviders.directRequestHandler(spData, opts)
} catch(er) {}
if (!proofData) {
try {
proofData = await serviceproviders.proxyRequestHandler(spData, opts)
} catch(er) {}
}
}
break;
case 'fallback':
try { try {
proofData = await serviceproviders.directRequestHandler(spData, opts) proofData = await serviceproviders.directRequestHandler(spData, opts)
} catch(er) {} } catch(er) {}
@ -209,57 +224,56 @@ const verify = async (input, fingerprint, opts) => {
proofData = await serviceproviders.proxyRequestHandler(spData, opts) proofData = await serviceproviders.proxyRequestHandler(spData, opts)
} catch(er) {} } catch(er) {}
} }
} break;
break; case 'always':
case 'fallback':
try {
proofData = await serviceproviders.directRequestHandler(spData, opts)
} catch(er) {}
if (!proofData) {
try { try {
proofData = await serviceproviders.proxyRequestHandler(spData, opts) proofData = await serviceproviders.proxyRequestHandler(spData, opts)
} catch(er) {} } catch(er) {}
} break;
break; case 'never':
case 'always': try {
try { proofData = await serviceproviders.directRequestHandler(spData, opts)
proofData = await serviceproviders.proxyRequestHandler(spData, opts) } catch(er) {}
} catch(er) {} break;
break; default:
case 'never': objResult.errors.push('invalid_proxy_policy')
try { }
proofData = await serviceproviders.directRequestHandler(spData, opts) }
} catch(er) {}
break; if (proofData) {
default: claimVerificationResult = runVerification(proofData, spData)
verifErrors.push('invalid_proxy_policy')
if (claimVerificationResult.errors.length == 0) {
claimVerificationDone = true
}
} else {
objResult.errors.push('unsuccessful_claim_verification')
}
iSp++
}
if (!claimVerificationResult) {
claimVerificationResult = {
isVerified: false,
} }
} }
if (proofData) { objResult.isVerified = claimVerificationResult.isVerified
claimVerificationResult = runVerification(proofData, spData) objResult.serviceproviderData = spData
resolve(objResult)
})
if (claimVerificationResult.errors.length == 0) { const promiseTimeout = new Promise((res) => {
claimVerificationDone = true const objResult = {
} isVerified: null,
} else { errors: 'verification_timed_out',
verifErrors.push('unsuccessful_claim_verification') serviceproviderData: null,
} }
setTimeout(() => res(objResult), 5000)
})
iSp++ return await Promise.race([promiseClaim, promiseTimeout])
}
if (!claimVerificationResult) {
claimVerificationResult = {
isVerified: false,
}
}
return {
isVerified: claimVerificationResult.isVerified,
errors: verifErrors,
serviceproviderData: spData,
}
} }
exports.verify = verify exports.verify = verify

View file

@ -62,13 +62,13 @@ describe('claims.verify', () => {
expect(doipjs.claims.verify).to.be.a('function') expect(doipjs.claims.verify).to.be.a('function')
expect(doipjs.claims.verify).to.have.length(3) expect(doipjs.claims.verify).to.have.length(3)
}) })
it('should throw an error for non-valid URIs', () => { it('should return undefined for non-valid URIs', () => {
return expect(doipjs.claims.verify('noURI')).to.eventually.be.rejectedWith( return expect(doipjs.claims.verify('noURI')).to.eventually.be.rejectedWith(
'Invalid URI' undefined
) )
return expect( return expect(
doipjs.claims.verify('domain.org') doipjs.claims.verify('domain.org')
).to.eventually.be.rejectedWith('Invalid URI') ).to.eventually.be.rejectedWith(undefined)
}) })
doipjs.serviceproviders.list.forEach((spName, i) => { doipjs.serviceproviders.list.forEach((spName, i) => {