Skip to content

Commit

Permalink
fix: issue where attributes and predicates match (#640)
Browse files Browse the repository at this point in the history
Signed-off-by: annelein <[email protected]>
  • Loading branch information
Annelein authored Mar 3, 2022
1 parent 8386506 commit 15a5e6b
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 10 deletions.
1 change: 0 additions & 1 deletion demo/src/Faber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ export class Faber extends BaseAgent {

public async acceptConnection(invitation_url: string) {
const connectionRecord = await this.receiveConnectionRequest(invitation_url)

this.connectionRecordAliceId = await this.waitForConnection(connectionRecord)
}

Expand Down
13 changes: 7 additions & 6 deletions packages/core/src/modules/proofs/services/ProofService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { EventEmitter } from '../../../agent/EventEmitter'
import { InjectionSymbols } from '../../../constants'
import { Attachment, AttachmentData } from '../../../decorators/attachment/Attachment'
import { AriesFrameworkError } from '../../../error'
import { checkProofRequestForDuplicates } from '../../../utils'
import { JsonEncoder } from '../../../utils/JsonEncoder'
import { JsonTransformer } from '../../../utils/JsonTransformer'
import { uuid } from '../../../utils/uuid'
Expand Down Expand Up @@ -257,8 +258,8 @@ export class ProofService {
comment?: string
}
): Promise<ProofProtocolMsgReturnType<RequestPresentationMessage>> {
// Assert attribute and predicate group names do not match
this.assertAttributePredicateGroupNamesDoNotMatch(proofRequest)
// Assert attribute and predicate (group) names do not match
checkProofRequestForDuplicates(proofRequest)

// Assert
proofRecord.assertState(ProofState.ProposalReceived)
Expand Down Expand Up @@ -305,8 +306,8 @@ export class ProofService {
): Promise<ProofProtocolMsgReturnType<RequestPresentationMessage>> {
this.logger.debug(`Creating proof request`)

// Assert attribute and predicate group names do not match
this.assertAttributePredicateGroupNamesDoNotMatch(proofRequest)
// Assert attribute and predicate (group) names do not match
checkProofRequestForDuplicates(proofRequest)

// Assert
connectionRecord?.assertReady()
Expand Down Expand Up @@ -369,8 +370,8 @@ export class ProofService {
}
await validateOrReject(proofRequest)

// Assert attribute and predicate group names do not match
this.assertAttributePredicateGroupNamesDoNotMatch(proofRequest)
// Assert attribute and predicate (group) names do not match
checkProofRequestForDuplicates(proofRequest)

this.logger.debug('received proof request', proofRequest)

Expand Down
90 changes: 90 additions & 0 deletions packages/core/src/utils/__tests__/indyProofRequest.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { checkProofRequestForDuplicates } from '..'

import {
AriesFrameworkError,
AttributeFilter,
PredicateType,
ProofAttributeInfo,
ProofPredicateInfo,
ProofRequest,
} from '@aries-framework/core'

export const INDY_CREDENTIAL_OFFER_ATTACHMENT_ID = 'libindy-cred-offer-0'

describe('Present Proof', () => {
let credDefId: string

beforeAll(() => {
credDefId = '9vPXgSpQJPkJEALbLXueBp:3:CL:57753:tag1'
})

test('attribute names match, same cred def filter', () => {
const attributes = {
name: new ProofAttributeInfo({
name: 'age',
restrictions: [
new AttributeFilter({
credentialDefinitionId: credDefId,
}),
],
}),
age: new ProofAttributeInfo({
name: 'age',
restrictions: [
new AttributeFilter({
credentialDefinitionId: credDefId,
}),
],
}),
}

const nonce = 'testtesttest12345'

const proofRequest = new ProofRequest({
name: 'proof-request',
version: '1.0',
nonce,
requestedAttributes: attributes,
})

expect(() => checkProofRequestForDuplicates(proofRequest)).toThrowError(AriesFrameworkError)
})

test('attribute names match with predicates name, same cred def filter', () => {
const attributes = {
name: new ProofAttributeInfo({
name: 'age',
restrictions: [
new AttributeFilter({
credentialDefinitionId: credDefId,
}),
],
}),
}

const predicates = {
age: new ProofPredicateInfo({
name: 'age',
predicateType: PredicateType.GreaterThanOrEqualTo,
predicateValue: 50,
restrictions: [
new AttributeFilter({
credentialDefinitionId: credDefId,
}),
],
}),
}

const nonce = 'testtesttest12345'

const proofRequest = new ProofRequest({
name: 'proof-request',
version: '1.0',
nonce,
requestedAttributes: attributes,
requestedPredicates: predicates,
})

expect(() => checkProofRequestForDuplicates(proofRequest)).toThrowError(AriesFrameworkError)
})
})
11 changes: 11 additions & 0 deletions packages/core/src/utils/assertNoDuplicates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { AriesFrameworkError } from '../error/AriesFrameworkError'

export function assertNoDuplicatesInArray(arr: string[]) {
const arrayLength = arr.length
const uniqueArrayLength = new Set(arr).size

if (arrayLength === uniqueArrayLength) return

const duplicates = arr.filter((item, index) => arr.indexOf(item) != index)
throw new AriesFrameworkError(`The proof request contains duplicate items: ${duplicates.toString()}`)
}
1 change: 1 addition & 0 deletions packages/core/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from './MultiBaseEncoder'
export * from './buffer'
export * from './MultiHashEncoder'
export * from './JWE'
export * from './indyProofRequest'
22 changes: 22 additions & 0 deletions packages/core/src/utils/indyProofRequest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { ProofRequest } from '../modules/proofs/models/ProofRequest'

import { assertNoDuplicatesInArray } from './assertNoDuplicates'

export function attributeNamesToArray(proofRequest: ProofRequest) {
// Attributes can contain either a `name` string value or an `names` string array. We reduce it to a single array
// containing all attribute names from the requested attributes.
return Array.from(proofRequest.requestedAttributes.values()).reduce<string[]>(
(names, a) => [...names, ...(a.name ? [a.name] : a.names ? a.names : [])],
[]
)
}

export function predicateNamesToArray(proofRequest: ProofRequest) {
return Array.from(proofRequest.requestedPredicates.values()).map((a) => a.name)
}

export function checkProofRequestForDuplicates(proofRequest: ProofRequest) {
const attributes = attributeNamesToArray(proofRequest)
const predicates = predicateNamesToArray(proofRequest)
assertNoDuplicatesInArray(attributes.concat(predicates))
}
5 changes: 2 additions & 3 deletions packages/core/tests/proofs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ describe('Present Proof', () => {
testLogger.test('Initializing the agents')
;({ faberAgent, aliceAgent, credDefId, faberConnection, aliceConnection, presentationPreview } =
await setupProofsTest('Faber agent', 'Alice agent'))
testLogger.test('Issuing second credential')
})

afterAll(async () => {
Expand Down Expand Up @@ -365,8 +366,6 @@ describe('Present Proof', () => {
requestedAttributes: attributes,
requestedPredicates: predicates,
})
).rejects.toThrowError(
`The proof request contains an attribute group name that matches a predicate group name: age`
)
).rejects.toThrowError(`The proof request contains duplicate items: age`)
})
})

0 comments on commit 15a5e6b

Please sign in to comment.