-
Notifications
You must be signed in to change notification settings - Fork 207
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: issue where attributes and predicates match #640
Changes from 2 commits
3b0794a
8174b1f
0a57b2e
028f70c
daf2053
0237061
f610203
4255975
e50b32e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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()}`) | ||
} |
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 attributesToArray(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 predicatesToArray(proofRequest: ProofRequest) { | ||
return Array.from(proofRequest.requestedPredicates.values()).map((a) => a.name) | ||
} | ||
|
||
export function checkProofRequestForDuplicates(proofRequest: ProofRequest) { | ||
const attributes = attributesToArray(proofRequest) | ||
const predicates = predicatesToArray(proofRequest) | ||
assertNoDuplicatesInArray(attributes.concat(predicates)) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -664,3 +664,29 @@ export async function setupProofsTest(faberName: string, aliceName: string, auto | |
aliceReplay, | ||
} | ||
} | ||
|
||
export async function setupSecondCredential( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this still being used somewhere? |
||
faberAgent: Agent, | ||
aliceAgent: Agent, | ||
faberConnection: ConnectionRecord | ||
): Promise<string> { | ||
const { definition } = await prepareForIssuance(faberAgent, ['name', 'age']) | ||
|
||
const credentialPreview = CredentialPreview.fromRecord({ | ||
name: 'John', | ||
age: '99', | ||
}) | ||
|
||
await issueCredential({ | ||
issuerAgent: faberAgent, | ||
issuerConnectionId: faberConnection.id, | ||
holderAgent: aliceAgent, | ||
credentialTemplate: { | ||
credentialDefinitionId: definition.id, | ||
comment: 'some comment about credential', | ||
preview: credentialPreview, | ||
}, | ||
}) | ||
|
||
return definition.id | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,15 +12,19 @@ import { | |
ProofState, | ||
ProposePresentationMessage, | ||
RequestPresentationMessage, | ||
ProofRequest, | ||
AriesFrameworkError, | ||
} from '../src' | ||
import { checkProofRequestForDuplicates } from '../src/utils' | ||
|
||
import { setupProofsTest, waitForProofRecord } from './helpers' | ||
import { setupProofsTest, setupSecondCredential, waitForProofRecord } from './helpers' | ||
import testLogger from './logger' | ||
|
||
describe('Present Proof', () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This only tests the createRequest method. I think the e2e test were useful to check where indy throws error, but it might be easier to create unit tests for the specific service methods like you did with the credential service. |
||
let faberAgent: Agent | ||
let aliceAgent: Agent | ||
let credDefId: CredDefId | ||
let secCredDefId: string | ||
let faberConnection: ConnectionRecord | ||
let aliceConnection: ConnectionRecord | ||
let presentationPreview: PresentationPreview | ||
|
@@ -29,6 +33,8 @@ 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') | ||
secCredDefId = await setupSecondCredential(faberAgent, aliceAgent, faberConnection) | ||
}) | ||
|
||
afterAll(async () => { | ||
|
@@ -365,8 +371,162 @@ 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`) | ||
}) | ||
|
||
test('attribute names match, same cred def filter', async () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These tests are great! I think it would be good to move them to a util test in the utils tests directory. Then add tests to this file that makes sure the method is called where it should be (createRequest, etc...) |
||
const attributes = { | ||
name: new ProofAttributeInfo({ | ||
name: 'age', | ||
restrictions: [ | ||
new AttributeFilter({ | ||
credentialDefinitionId: credDefId, | ||
}), | ||
], | ||
}), | ||
age: new ProofAttributeInfo({ | ||
name: 'age', | ||
restrictions: [ | ||
new AttributeFilter({ | ||
credentialDefinitionId: credDefId, | ||
}), | ||
], | ||
}), | ||
} | ||
|
||
const proofRequestOptions = { | ||
name: 'test-proof-request', | ||
requestedAttributes: attributes, | ||
} | ||
|
||
const nonce = 'testtesttest12345' | ||
|
||
const proofRequest = new ProofRequest({ | ||
name: 'proof-request', | ||
version: '1.0', | ||
nonce, | ||
requestedAttributes: proofRequestOptions.requestedAttributes, | ||
}) | ||
|
||
expect(() => checkProofRequestForDuplicates(proofRequest)).toThrowError(AriesFrameworkError) | ||
}) | ||
|
||
test('attribute names match with predicates name, same cred def filter', async () => { | ||
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) | ||
}) | ||
|
||
test('attribute names match, different cred def filter', async () => { | ||
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: secCredDefId, | ||
}), | ||
], | ||
}), | ||
} | ||
|
||
const proofRequestOptions = { | ||
name: 'test-proof-request', | ||
requestedAttributes: attributes, | ||
predicates: predicates, | ||
} | ||
|
||
const nonce = 'testtesttest12345' | ||
|
||
const proofRequest = new ProofRequest({ | ||
name: 'proof-request', | ||
version: '1.0', | ||
nonce, | ||
requestedAttributes: proofRequestOptions.requestedAttributes, | ||
}) | ||
|
||
expect(() => checkProofRequestForDuplicates(proofRequest)).resolves | ||
}) | ||
|
||
test('attribute name matches with predicate name, different cred def filter', async () => { | ||
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: secCredDefId, | ||
}), | ||
], | ||
}), | ||
} | ||
|
||
const nonce = 'testtesttest12345' | ||
|
||
const proofRequest = new ProofRequest({ | ||
name: 'proof-request', | ||
version: '1.0', | ||
nonce, | ||
requestedAttributes: attributes, | ||
requestedPredicates: predicates, | ||
}) | ||
|
||
expect(() => checkProofRequestForDuplicates(proofRequest)).resolves | ||
}) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think
predicateNamesToArray
, and same for attributes, Is a better name.