-
Notifications
You must be signed in to change notification settings - Fork 198
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
feat: auto accept proofs #367
Merged
TimoGlastra
merged 21 commits into
openwallet-foundation:main
from
berendsliedrecht:feature/auto-accept-proof
Jul 19, 2021
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
9dd797d
feat: propose proof always is auto accept
berendsliedrecht 8632876
fixed for testing
berendsliedrecht 8c0a1c7
fix for testing
berendsliedrecht 73dfdfa
feat: auto accept proof always working
berendsliedrecht 0826f19
improved testing and added contentApproved
berendsliedrecht f7d194e
revert changed from auto accept credential
berendsliedrecht 456fce7
removed autoAcceptCredential
berendsliedrecht 1a9627d
Removed tags
berendsliedrecht 6c73742
Copied from credentialresponsecoordinator
berendsliedrecht 8d383ee
minified tests
berendsliedrecht b46eff5
Consistent logging
berendsliedrecht 5849035
test: more in sync with other tests
berendsliedrecht 2a1fad0
added functionality in the README
berendsliedrecht bc5aa3e
Added better documentation
berendsliedrecht 1596a25
Fix: functions were not async
berendsliedrecht 8e3c139
Merge branch 'main' into feature/auto-accept-proof
berendsliedrecht 659b17c
Merge remote-tracking branch 'origin/main' into feature/auto-accept-p…
berendsliedrecht 44cebf0
merged
berendsliedrecht 938402f
Merge remote-tracking branch 'origin/main' into feature/auto-accept-p…
berendsliedrecht 23f1d86
Fix: feedback from auto-accept-credential
berendsliedrecht 7f39d2a
Merge remote-tracking branch 'origin/main' into feature/auto-accept-p…
berendsliedrecht File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/** | ||
* Typing of the state for auto acceptance | ||
*/ | ||
export enum AutoAcceptProof { | ||
// Always auto accepts the proof no matter if it changed in subsequent steps | ||
Always = 'always', | ||
|
||
// Needs one acceptation and the rest will be automated if nothing changes | ||
ContentApproved = 'contentApproved', | ||
|
||
// DEFAULT: Never auto accept a proof | ||
Never = 'never', | ||
} |
86 changes: 86 additions & 0 deletions
86
packages/core/src/modules/proofs/ProofResponseCoordinator.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import type { ProofRecord } from './repository' | ||
|
||
import { scoped, Lifecycle } from 'tsyringe' | ||
|
||
import { AgentConfig } from '../../agent/AgentConfig' | ||
|
||
import { AutoAcceptProof } from './ProofAutoAcceptType' | ||
|
||
/** | ||
* This class handles all the automation with all the messages in the present proof protocol | ||
* Every function returns `true` if it should automate the flow and `false` if not | ||
*/ | ||
@scoped(Lifecycle.ContainerScoped) | ||
export class ProofResponseCoordinator { | ||
private agentConfig: AgentConfig | ||
|
||
public constructor(agentConfig: AgentConfig) { | ||
this.agentConfig = agentConfig | ||
} | ||
|
||
/** | ||
* Returns the proof auto accept config based on priority: | ||
* - The record config takes first priority | ||
* - Otherwise the agent config | ||
* - Otherwise {@link AutoAcceptProof.Never} is returned | ||
*/ | ||
private static composeAutoAccept( | ||
recordConfig: AutoAcceptProof | undefined, | ||
agentConfig: AutoAcceptProof | undefined | ||
) { | ||
return recordConfig ?? agentConfig ?? AutoAcceptProof.Never | ||
} | ||
|
||
/** | ||
* Checks whether it should automatically respond to a proposal | ||
*/ | ||
public shoudlAutoRespondToProposal(proofRecord: ProofRecord) { | ||
const autoAccept = ProofResponseCoordinator.composeAutoAccept( | ||
proofRecord.autoAcceptProof, | ||
this.agentConfig.autoAcceptProofs | ||
) | ||
|
||
if (autoAccept === AutoAcceptProof.Always) { | ||
return true | ||
} | ||
return false | ||
} | ||
|
||
/** | ||
* Checks whether it should automatically respond to a request | ||
*/ | ||
public shouldAutoRespondToRequest(proofRecord: ProofRecord) { | ||
const autoAccept = ProofResponseCoordinator.composeAutoAccept( | ||
proofRecord.autoAcceptProof, | ||
this.agentConfig.autoAcceptProofs | ||
) | ||
|
||
if ( | ||
autoAccept === AutoAcceptProof.Always || | ||
(autoAccept === AutoAcceptProof.ContentApproved && proofRecord.proposalMessage) | ||
) { | ||
return true | ||
} | ||
|
||
return false | ||
} | ||
|
||
/** | ||
* Checks whether it should automatically respond to a presention of proof | ||
*/ | ||
public shouldAutoRespondToPresentation(proofRecord: ProofRecord) { | ||
const autoAccept = ProofResponseCoordinator.composeAutoAccept( | ||
proofRecord.autoAcceptProof, | ||
this.agentConfig.autoAcceptProofs | ||
) | ||
|
||
if ( | ||
autoAccept === AutoAcceptProof.Always || | ||
(autoAccept === AutoAcceptProof.ContentApproved && proofRecord.requestMessage) | ||
) { | ||
return true | ||
} | ||
|
||
return false | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 33 additions & 2 deletions
35
packages/core/src/modules/proofs/handlers/PresentationHandler.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,48 @@ | ||
import type { AgentConfig } from '../../../agent/AgentConfig' | ||
import type { Handler, HandlerInboundMessage } from '../../../agent/Handler' | ||
import type { ProofResponseCoordinator } from '../ProofResponseCoordinator' | ||
import type { ProofRecord } from '../repository' | ||
import type { ProofService } from '../services' | ||
|
||
import { createOutboundMessage } from '../../../agent/helpers' | ||
import { PresentationMessage } from '../messages' | ||
|
||
export class PresentationHandler implements Handler { | ||
private proofService: ProofService | ||
private agentConfig: AgentConfig | ||
private proofResponseCoordinator: ProofResponseCoordinator | ||
public supportedMessages = [PresentationMessage] | ||
|
||
public constructor(proofService: ProofService) { | ||
public constructor( | ||
proofService: ProofService, | ||
agentConfig: AgentConfig, | ||
proofResponseCoordinator: ProofResponseCoordinator | ||
) { | ||
this.proofService = proofService | ||
this.agentConfig = agentConfig | ||
this.proofResponseCoordinator = proofResponseCoordinator | ||
} | ||
|
||
public async handle(messageContext: HandlerInboundMessage<PresentationHandler>) { | ||
await this.proofService.processPresentation(messageContext) | ||
const proofRecord = await this.proofService.processPresentation(messageContext) | ||
|
||
if (this.proofResponseCoordinator.shouldAutoRespondToPresentation(proofRecord)) { | ||
return await this.createAck(proofRecord, messageContext) | ||
} | ||
} | ||
|
||
private async createAck(proofRecord: ProofRecord, messageContext: HandlerInboundMessage<PresentationHandler>) { | ||
this.agentConfig.logger.info( | ||
`Automatically sending acknowledgement with autoAccept on ${this.agentConfig.autoAcceptProofs}` | ||
) | ||
|
||
if (!messageContext.connection) { | ||
this.agentConfig.logger.error('No connection on the messageContext') | ||
return | ||
} | ||
|
||
const { message } = await this.proofService.createAck(proofRecord) | ||
|
||
return createOutboundMessage(messageContext.connection, message) | ||
} | ||
} |
49 changes: 47 additions & 2 deletions
49
packages/core/src/modules/proofs/handlers/ProposePresentationHandler.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,62 @@ | ||
import type { AgentConfig } from '../../../agent/AgentConfig' | ||
import type { Handler, HandlerInboundMessage } from '../../../agent/Handler' | ||
import type { ProofResponseCoordinator } from '../ProofResponseCoordinator' | ||
import type { ProofRecord } from '../repository' | ||
import type { ProofService } from '../services' | ||
|
||
import { createOutboundMessage } from '../../../agent/helpers' | ||
import { ProposePresentationMessage } from '../messages' | ||
|
||
export class ProposePresentationHandler implements Handler { | ||
private proofService: ProofService | ||
private agentConfig: AgentConfig | ||
private proofResponseCoordinator: ProofResponseCoordinator | ||
public supportedMessages = [ProposePresentationMessage] | ||
|
||
public constructor(proofService: ProofService) { | ||
public constructor( | ||
proofService: ProofService, | ||
agentConfig: AgentConfig, | ||
proofResponseCoordinator: ProofResponseCoordinator | ||
) { | ||
this.proofService = proofService | ||
this.agentConfig = agentConfig | ||
this.proofResponseCoordinator = proofResponseCoordinator | ||
} | ||
|
||
public async handle(messageContext: HandlerInboundMessage<ProposePresentationHandler>) { | ||
await this.proofService.processProposal(messageContext) | ||
const proofRecord = await this.proofService.processProposal(messageContext) | ||
|
||
if (this.proofResponseCoordinator.shoudlAutoRespondToProposal(proofRecord)) { | ||
return await this.createRequest(proofRecord, messageContext) | ||
} | ||
} | ||
|
||
private async createRequest( | ||
proofRecord: ProofRecord, | ||
messageContext: HandlerInboundMessage<ProposePresentationHandler> | ||
) { | ||
this.agentConfig.logger.info( | ||
`Automatically sending request with autoAccept on ${this.agentConfig.autoAcceptProofs}` | ||
) | ||
|
||
if (!messageContext.connection) { | ||
this.agentConfig.logger.error('No connection on the messageContext') | ||
return | ||
} | ||
if (!proofRecord.proposalMessage) { | ||
this.agentConfig.logger.error(`Proof record with id ${proofRecord.id} is missing required credential proposal`) | ||
return | ||
} | ||
const proofRequest = await this.proofService.createProofRequestFromProposal( | ||
proofRecord.proposalMessage.presentationProposal, | ||
{ | ||
name: 'proof-request', | ||
version: '1.0', | ||
} | ||
) | ||
|
||
const { message } = await this.proofService.createRequestAsResponse(proofRecord, proofRequest) | ||
|
||
return createOutboundMessage(messageContext.connection, message) | ||
} | ||
} |
51 changes: 49 additions & 2 deletions
51
packages/core/src/modules/proofs/handlers/RequestPresentationHandler.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,64 @@ | ||
import type { AgentConfig } from '../../../agent/AgentConfig' | ||
import type { Handler, HandlerInboundMessage } from '../../../agent/Handler' | ||
import type { ProofResponseCoordinator } from '../ProofResponseCoordinator' | ||
import type { ProofRecord } from '../repository' | ||
import type { ProofService } from '../services' | ||
|
||
import { createOutboundMessage } from '../../../agent/helpers' | ||
import { RequestPresentationMessage } from '../messages' | ||
|
||
export class RequestPresentationHandler implements Handler { | ||
private proofService: ProofService | ||
private agentConfig: AgentConfig | ||
private proofResponseCoordinator: ProofResponseCoordinator | ||
public supportedMessages = [RequestPresentationMessage] | ||
|
||
public constructor(proofService: ProofService) { | ||
public constructor( | ||
proofService: ProofService, | ||
agentConfig: AgentConfig, | ||
proofResponseCoordinator: ProofResponseCoordinator | ||
) { | ||
this.proofService = proofService | ||
this.agentConfig = agentConfig | ||
this.proofResponseCoordinator = proofResponseCoordinator | ||
} | ||
|
||
public async handle(messageContext: HandlerInboundMessage<RequestPresentationHandler>) { | ||
await this.proofService.processRequest(messageContext) | ||
const proofRecord = await this.proofService.processRequest(messageContext) | ||
|
||
if (this.proofResponseCoordinator.shouldAutoRespondToRequest(proofRecord)) { | ||
return await this.createPresentation(proofRecord, messageContext) | ||
} | ||
} | ||
|
||
private async createPresentation( | ||
proofRecord: ProofRecord, | ||
messageContext: HandlerInboundMessage<RequestPresentationHandler> | ||
) { | ||
const indyProofRequest = proofRecord.requestMessage?.indyProofRequest | ||
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 makes the handler kind of Indy specific. 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. Will fix this when we support multiple credential types. |
||
|
||
this.agentConfig.logger.info( | ||
`Automatically sending presentation with autoAccept on ${this.agentConfig.autoAcceptProofs}` | ||
) | ||
|
||
if (!messageContext.connection) { | ||
this.agentConfig.logger.error('No connection on the messageContext') | ||
return | ||
} | ||
|
||
if (!indyProofRequest) { | ||
return | ||
} | ||
|
||
const retrievedCredentials = await this.proofService.getRequestedCredentialsForProofRequest( | ||
indyProofRequest, | ||
proofRecord.proposalMessage?.presentationProposal | ||
) | ||
|
||
const requestedCredentials = this.proofService.autoSelectCredentialsForProofRequest(retrievedCredentials) | ||
|
||
const { message } = await this.proofService.createPresentation(proofRecord, requestedCredentials) | ||
|
||
return createOutboundMessage(messageContext.connection, message) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Maybe we should have two types, like
AutoAcceptProof
for the holder andAutoAcceptProofRequest
request for the issuer. Similarly with credentials. But that's of course more of a future improvement idea.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.
Any particular reason for this? Maybe it allows for some use cases that I don't know of.
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 see 2 reasons:
The first is expressiveness.
AutoAcceptProof
means auto acceptance proof from the verifier point of view but also auto acceptance of the proof request from the holder's perspective. Even now, I'm not sure if I wrote it correctly.The second is a potential use case when someone uses an agent for more than one role. Let's say I want to accept proofs as a verifier but don't want to accept proof requests as a holder.