Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(proofs): await shouldAutoRespond to correctly handle the check #1116

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ import type { JsonLdOptionsRFC0593 } from './JsonLdOptionsRFC0593'
import { injectable } from 'tsyringe'

import { AriesFrameworkError } from '../../../../error'
import { objectEquality } from '../../../../utils'
import { JsonTransformer } from '../../../../utils/JsonTransformer'
import { MessageValidator } from '../../../../utils/MessageValidator'
import { deepEqual } from '../../../../utils/objEqual'
import { findVerificationMethodByKeyType } from '../../../dids/domain/DidDocument'
import { DidResolverService } from '../../../dids/services/DidResolverService'
import { W3cCredentialService } from '../../../vc'
Expand Down Expand Up @@ -344,7 +344,7 @@ export class JsonLdCredentialFormatService extends CredentialFormatService<JsonL
}

private compareCredentialSubject(credential: W3cVerifiableCredential, request: W3cCredential): void {
if (!deepEqual(credential.credentialSubject, request.credentialSubject)) {
if (!objectEquality(credential.credentialSubject, request.credentialSubject)) {
throw new AriesFrameworkError('Received credential subject does not match subject from credential request')
}
}
Expand Down Expand Up @@ -386,7 +386,7 @@ export class JsonLdCredentialFormatService extends CredentialFormatService<JsonL
const obj1 = message1.getDataAsJson()
const obj2 = message2.getDataAsJson()

return deepEqual(obj1, obj2)
return objectEquality(obj1, obj2)
}

public shouldAutoRespondToProposal(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -963,7 +963,7 @@ export class V1CredentialService extends CredentialService<[IndyCredentialFormat
credentialRecord: CredentialExchangeRecord
proposalMessage: V1ProposeCredentialMessage
}
): Promise<boolean> {
) {
const { credentialRecord, proposalMessage } = options
const autoAccept = composeAutoAccept(
credentialRecord.autoAcceptCredential,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export class ProofResponseCoordinator {
/**
* Checks whether it should automatically respond to a proposal
*/
public shouldAutoRespondToProposal(agentContext: AgentContext, proofRecord: ProofExchangeRecord) {
public async shouldAutoRespondToProposal(agentContext: AgentContext, proofRecord: ProofExchangeRecord) {
const autoAccept = ProofResponseCoordinator.composeAutoAccept(
proofRecord.autoAcceptProof,
agentContext.config.autoAcceptProofs
Expand All @@ -54,7 +54,7 @@ export class ProofResponseCoordinator {
/**
* Checks whether it should automatically respond to a request
*/
public shouldAutoRespondToRequest(agentContext: AgentContext, proofRecord: ProofExchangeRecord) {
public async shouldAutoRespondToRequest(agentContext: AgentContext, proofRecord: ProofExchangeRecord) {
const autoAccept = ProofResponseCoordinator.composeAutoAccept(
proofRecord.autoAcceptProof,
agentContext.config.autoAcceptProofs
Expand All @@ -74,7 +74,7 @@ export class ProofResponseCoordinator {
/**
* Checks whether it should automatically respond to a presentation of proof
*/
public shouldAutoRespondToPresentation(agentContext: AgentContext, proofRecord: ProofExchangeRecord) {
public async shouldAutoRespondToPresentation(agentContext: AgentContext, proofRecord: ProofExchangeRecord) {
const autoAccept = ProofResponseCoordinator.composeAutoAccept(
proofRecord.autoAcceptProof,
agentContext.config.autoAcceptProofs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,10 @@ import { Attachment, AttachmentData } from '../../../../decorators/attachment/At
import { AriesFrameworkError } from '../../../../error/AriesFrameworkError'
import { ConsoleLogger, LogLevel } from '../../../../logger'
import { DidCommMessageRepository } from '../../../../storage/didcomm/DidCommMessageRepository'
import { checkProofRequestForDuplicates } from '../../../../utils'
import { checkProofRequestForDuplicates, deepEquality } from '../../../../utils'
import { JsonEncoder } from '../../../../utils/JsonEncoder'
import { JsonTransformer } from '../../../../utils/JsonTransformer'
import { MessageValidator } from '../../../../utils/MessageValidator'
import { objectEquals } from '../../../../utils/objectCheck'
import { uuid } from '../../../../utils/uuid'
import { IndyWallet } from '../../../../wallet/IndyWallet'
import { IndyCredential, IndyCredentialInfo } from '../../../credentials'
Expand Down Expand Up @@ -121,7 +120,7 @@ export class IndyProofFormatService extends ProofFormatService {
})

const request = new ProofRequest(options.proofProposalOptions)
await MessageValidator.validateSync(request)
MessageValidator.validateSync(request)

const attachment = new Attachment({
id: options.id,
Expand Down Expand Up @@ -157,7 +156,7 @@ export class IndyProofFormatService extends ProofFormatService {

const proposalMessage = JsonTransformer.fromJSON(proofProposalJson, ProofRequest)

await MessageValidator.validateSync(proposalMessage)
MessageValidator.validateSync(proposalMessage)
}

public async createRequestAsResponse(
Expand Down Expand Up @@ -213,7 +212,7 @@ export class IndyProofFormatService extends ProofFormatService {
`Missing required base64 or json encoded attachment data for presentation request with thread id ${options.record?.threadId}`
)
}
await MessageValidator.validateSync(proofRequest)
MessageValidator.validateSync(proofRequest)

// Assert attribute and predicate (group) names do not match
checkProofRequestForDuplicates(proofRequest)
Expand Down Expand Up @@ -356,8 +355,8 @@ export class IndyProofFormatService extends ProofFormatService {
const requestAttachmentData = JsonTransformer.fromJSON(requestAttachmentJson, ProofRequest)

if (
objectEquals(proposalAttachmentData.requestedAttributes, requestAttachmentData.requestedAttributes) &&
objectEquals(proposalAttachmentData.requestedPredicates, requestAttachmentData.requestedPredicates)
deepEquality(proposalAttachmentData.requestedAttributes, requestAttachmentData.requestedAttributes) &&
deepEquality(proposalAttachmentData.requestedPredicates, requestAttachmentData.requestedPredicates)
) {
return true
}
Expand Down Expand Up @@ -606,7 +605,7 @@ export class IndyProofFormatService extends ProofFormatService {
if (!proofRequest) {
throw new AriesFrameworkError(`Missing required base64 or json encoded attachment data for presentation request.`)
}
await MessageValidator.validateSync(proofRequest)
MessageValidator.validateSync(proofRequest)

// Assert attribute and predicate (group) names do not match
checkProofRequestForDuplicates(proofRequest)
Expand Down
10 changes: 3 additions & 7 deletions packages/core/src/modules/proofs/protocol/v1/V1ProofService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -764,20 +764,16 @@ export class V1ProofService extends ProofService<[IndyProofFormat]> {
messageClass: V1ProposePresentationMessage,
})

if (!proposal) {
return false
}
await MessageValidator.validateSync(proposal)
if (!proposal) return false
MessageValidator.validateSync(proposal)

// check the proposal against a possible previous request
const request = await this.didCommMessageRepository.findAgentMessage(agentContext, {
associatedRecordId: proofRecord.id,
messageClass: V1RequestPresentationMessage,
})

if (!request) {
return false
}
if (!request) return false

const proofRequest = request.indyProofRequest

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ export class V1PresentationHandler implements Handler {
public async handle(messageContext: HandlerInboundMessage<V1PresentationHandler>) {
const proofRecord = await this.proofService.processPresentation(messageContext)

if (this.proofResponseCoordinator.shouldAutoRespondToPresentation(messageContext.agentContext, proofRecord)) {
const shouldAutoRespond = await this.proofResponseCoordinator.shouldAutoRespondToPresentation(
messageContext.agentContext,
proofRecord
)

if (shouldAutoRespond) {
return await this.createAck(proofRecord, messageContext)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,13 @@ export class V1ProposePresentationHandler implements Handler {

public async handle(messageContext: HandlerInboundMessage<V1ProposePresentationHandler>) {
const proofRecord = await this.proofService.processProposal(messageContext)
if (this.proofResponseCoordinator.shouldAutoRespondToProposal(messageContext.agentContext, proofRecord)) {

const shouldAutoRespond = await this.proofResponseCoordinator.shouldAutoRespondToProposal(
messageContext.agentContext,
proofRecord
)

if (shouldAutoRespond) {
return await this.createRequest(proofRecord, messageContext)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,13 @@ export class V1RequestPresentationHandler implements Handler {

public async handle(messageContext: HandlerInboundMessage<V1RequestPresentationHandler>) {
const proofRecord = await this.proofService.processRequest(messageContext)
if (this.proofResponseCoordinator.shouldAutoRespondToRequest(messageContext.agentContext, proofRecord)) {

const shouldAutoRespond = await this.proofResponseCoordinator.shouldAutoRespondToRequest(
messageContext.agentContext,
proofRecord
)

if (shouldAutoRespond) {
return await this.createPresentation(proofRecord, messageContext)
}
}
Expand Down
17 changes: 8 additions & 9 deletions packages/core/src/modules/proofs/protocol/v2/V2ProofService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -545,15 +545,15 @@ export class V2ProofService<PFs extends ProofFormat[] = ProofFormat[]> extends P
)
}

const msg = new V2PresentationAckMessage({
const message = new V2PresentationAckMessage({
threadId: options.proofRecord.threadId,
status: AckStatus.OK,
})

await this.updateState(agentContext, options.proofRecord, ProofState.Done)

return {
message: msg,
message,
proofRecord: options.proofRecord,
}
}
Expand Down Expand Up @@ -681,17 +681,16 @@ export class V2ProofService<PFs extends ProofFormat[] = ProofFormat[]> extends P
messageClass: V2ProposalPresentationMessage,
})

if (!proposal) {
return false
}
if (!proposal) return false

const request = await this.didCommMessageRepository.findAgentMessage(agentContext, {
associatedRecordId: proofRecord.id,
messageClass: V2RequestPresentationMessage,
})
if (!request) {
return true
}
await MessageValidator.validateSync(proposal)

if (!request) return false

MessageValidator.validateSync(proposal)

const proposalAttachments = proposal.getAttachmentFormats()
const requestAttachments = request.getAttachmentFormats()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ export class V2PresentationHandler implements Handler {
public async handle(messageContext: HandlerInboundMessage<V2PresentationHandler>) {
const proofRecord = await this.proofService.processPresentation(messageContext)

if (this.proofResponseCoordinator.shouldAutoRespondToPresentation(messageContext.agentContext, proofRecord)) {
const shouldAutoRespond = await this.proofResponseCoordinator.shouldAutoRespondToPresentation(
messageContext.agentContext,
proofRecord
)

if (shouldAutoRespond) {
return await this.createAck(proofRecord, messageContext)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ export class V2ProposePresentationHandler<PFs extends ProofFormat[] = ProofForma
public async handle(messageContext: HandlerInboundMessage<V2ProposePresentationHandler>) {
const proofRecord = await this.proofService.processProposal(messageContext)

if (this.proofResponseCoordinator.shouldAutoRespondToProposal(messageContext.agentContext, proofRecord)) {
const shouldAutoRespond = await this.proofResponseCoordinator.shouldAutoRespondToProposal(
messageContext.agentContext,
proofRecord
)

if (shouldAutoRespond) {
return this.createRequest(proofRecord, messageContext)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,13 @@ export class V2RequestPresentationHandler<PFs extends ProofFormat[] = ProofForma

public async handle(messageContext: HandlerInboundMessage<V2RequestPresentationHandler>) {
const proofRecord = await this.proofService.processRequest(messageContext)
if (this.proofResponseCoordinator.shouldAutoRespondToRequest(messageContext.agentContext, proofRecord)) {

const shouldAutoRespond = await this.proofResponseCoordinator.shouldAutoRespondToRequest(
messageContext.agentContext,
proofRecord
)

if (shouldAutoRespond) {
return await this.createPresentation(proofRecord, messageContext)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@ describe('UpdateAssistant | Backup', () => {
backupPath = `${fileSystem.basePath}/afj/migration/backup/${backupIdentifier}`

// If tests fail it's possible the cleanup has been skipped. So remove before running tests
if (await fileSystem.exists(backupPath)) {
const doesFileSystemExist = await fileSystem.exists(backupPath)
if (doesFileSystemExist) {
unlinkSync(backupPath)
}
if (await fileSystem.exists(`${backupPath}-error`)) {
const doesbackupFileSystemExist = await fileSystem.exists(`${backupPath}-error`)
if (doesbackupFileSystemExist) {
unlinkSync(`${backupPath}-error`)
}

Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/utils/MessageValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ export class MessageValidator {
/**
*
* @param classInstance the class instance to validate
* @returns nothing
* @returns void
* @throws array of validation errors {@link ValidationError}
*/
// eslint-disable-next-line @typescript-eslint/ban-types
public static validateSync<T extends object>(classInstance: T & {}) {
// NOTE: validateSync (strangely) return an Array of errors so we
// have to transform that into an error of choice and throw that.
// NOTE: validateSync returns an Array of errors.
// We have to transform that into an error of choice and throw that.
const errors = validateSync(classInstance)
if (isValidationErrorArray(errors)) {
throw new ClassValidationError('Failed to validate class.', {
Expand Down
82 changes: 82 additions & 0 deletions packages/core/src/utils/__tests__/deepEquality.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { Metadata } from '../../storage/Metadata'
import { deepEquality } from '../deepEquality'

describe('deepEquality', () => {
test('evaluates to true with equal maps', () => {
const a = new Map([
['foo', 1],
['bar', 2],
['baz', 3],
])
const b = new Map([
['foo', 1],
['bar', 2],
['baz', 3],
])
expect(deepEquality(a, b)).toBe(true)
})
test('evaluates to false with unequal maps', () => {
const c = new Map([
['foo', 1],
['baz', 3],
['bar', 2],
])

const d = new Map([
['foo', 1],
['bar', 2],
['qux', 3],
])
expect(deepEquality(c, d)).toBe(false)
})

test('evaluates to true with equal maps with different order', () => {
const a = new Map([
['baz', 3],
['bar', 2],
['foo', 1],
])
const b = new Map([
['foo', 1],
['bar', 2],
['baz', 3],
])
expect(deepEquality(a, b)).toBe(true)
})
test('evaluates to true with equal primitives', () => {
expect(deepEquality(1, 1)).toBe(true)
expect(deepEquality(true, true)).toBe(true)
expect(deepEquality('a', 'a')).toBe(true)
})

test('evaluates to false with unequal primitives', () => {
expect(deepEquality(1, 2)).toBe(false)
expect(deepEquality(true, false)).toBe(false)
expect(deepEquality('a', 'b')).toBe(false)
})

test('evaluates to true with equal complex types', () => {
const fn = () => 'hello World!'
expect(deepEquality(fn, fn)).toBe(true)
expect(deepEquality({}, {})).toBe(true)
expect(deepEquality({ foo: 'bar' }, { foo: 'bar' })).toBe(true)
expect(deepEquality({ foo: 'baz', bar: 'bar' }, { bar: 'bar', foo: 'baz' })).toBe(true)
expect(deepEquality(Metadata, Metadata)).toBe(true)
expect(deepEquality(new Metadata({}), new Metadata({}))).toBe(true)
})

test('evaluates to false with unequal complex types', () => {
const fn = () => 'hello World!'
const fnTwo = () => 'Goodbye World!'
class Bar {
public constructor() {
'yes'
}
}
expect(deepEquality(fn, fnTwo)).toBe(false)
expect(deepEquality({ bar: 'foo' }, { a: 'b' })).toBe(false)
expect(deepEquality({ b: 'a' }, { b: 'a', c: 'd' })).toBe(false)
expect(deepEquality(Metadata, Bar)).toBe(false)
expect(deepEquality(new Metadata({}), new Bar())).toBe(false)
})
})
Loading