Skip to content

Commit

Permalink
fix: get all presentations
Browse files Browse the repository at this point in the history
  • Loading branch information
genaris committed May 7, 2024
1 parent 9a382a1 commit db463e9
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 43 deletions.
33 changes: 31 additions & 2 deletions doc/service-agent-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ Subscriptions are composed by:

## Invitations

Service Agent suppors the creation of invitation codes that are used to start flows with agents where a persistent DIDComm connection is not yet established. For that purpose, three types of invitations are provided:
Service Agent supports the creation of invitation codes that are used to start flows with agents where a persistent DIDComm connection is not yet established. For that purpose, three types of invitations are provided:

- Connection Invitation: invite other agents to create a persistent, general purpose DIDComm connection. Codes created can be re-used by multiple agents that want to connect by processing it
- Presentation Request: invite other agent to start a Presentation Request flow. Codes created can only be used once
Expand All @@ -589,7 +589,7 @@ Response from Service Agent is a JSON object containing an URL-encoded invitatio

Note that the following Service Agent configuration environment variables are used when creating invitations:

- AGENT_INVITATION_BASE_URL: Base URL for for invitations (e.g. https://2060.io/i)
- AGENT_INVITATION_BASE_URL: Base URL for invitations (e.g. https://2060.io/i)
- AGENT_INVITATION_IMAGE_URL: An optional image URL to display along the connection invitation
- AGENT_LABEL: An optional label to show along the connection invitation

Expand Down Expand Up @@ -622,6 +622,14 @@ Response will include the invitation code in both short and long form URL format
}
```

Note that the following Service Agent configuration environment variables are used when creating presentation request invitations:

- AGENT_INVITATION_BASE_URL: Base URL for long-form invitations (e.g. https://2060.io/i)
- AGENT_INVITATION_IMAGE_URL: An optional image URL to display along the connection invitation
- AGENT_LABEL: An optional label to show along the connection invitation
- PUBLIC_API_BASE_URL: Base URL for short URL creation (resulting something like https://myHost.com/s?id=<uuid>)


### Credential Offer

Credential offer invitation codes include a preview of the offered credential, meaning by that its `credentialDefinitionId` and claims.
Expand All @@ -645,6 +653,27 @@ Response will include the invitation code in both short and long form URL format
}
```

Note that the following Service Agent configuration environment variables are used when creating credential offer invitations:

- AGENT_INVITATION_BASE_URL: Base URL for long-form invitations (e.g. https://2060.io/i)
- AGENT_INVITATION_IMAGE_URL: An optional image URL to display along the connection invitation
- AGENT_LABEL: An optional label to show along the connection invitation
- PUBLIC_API_BASE_URL: Base URL for short URL creation (resulting something like https://myHost.com/s?id=<uuid>)

## Presentations

It is possible to query all presentation flows created by Service Agent through the endpoint `/presentations`, which will respond with records using the following format:

- proofExchangeId: flow identifier (the same as the one used in events and other responses)
- state: current state of the presentation flow (e.g. `request-sent` when it was just started, `done` when finished)
- claims: array containing the claims received within the presentation
- verified: boolean stating if the presentation is valid (only meaningful when state is `done`)
- threadId: DIDComm thread id (shared with the other party)
- updatedAt: last time activity was recorded for this flow

It is possible to query for a single presentation by executing a GET to `/presentations/<proofExchangeId>`.


## Verifiable Data Registry Operations

This section specifies the different endpoints provided by the Service Agent to operate with the VDR.
Expand Down
80 changes: 39 additions & 41 deletions src/controllers/presentations/PresentationsController.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ProofExchangeRecord } from '@credo-ts/core'
import {
BadRequestException,
Controller,
Expand All @@ -12,7 +13,7 @@ import { ApiTags } from '@nestjs/swagger'

import { Claim } from '../../model'
import { AgentService } from '../../services/AgentService'
import { CredentialTypeInfo } from '../types'
import { PresentationData } from '../types'

@ApiTags('presentations')
@Controller({
Expand All @@ -30,23 +31,14 @@ export class PresentationsController {
* @returns
*/
@Get('/')
public async getAllCredentialTypes(): Promise<CredentialTypeInfo[]> {
public async getAllPresentations(): Promise<PresentationData[]> {
const agent = await this.agentService.getAgent()

const credentialDefinitions = await agent.modules.anoncreds.getCreatedCredentialDefinitions({})
const records = await agent.proofs.getAll()

return Promise.all(
credentialDefinitions.map(async record => {
const schemaResult = await agent.modules.anoncreds.getSchema(record.credentialDefinition.schemaId)

const schema = schemaResult.schema

return {
id: record.credentialDefinitionId,
name: (record.getTag('name') as string) ?? schema?.name,
version: (record.getTag('version') as string) ?? schema?.version,
attributes: schema?.attrNames || [],
}
records.map(async record => {
return await this.getPresentationData(record)
}),
)
}
Expand Down Expand Up @@ -83,40 +75,46 @@ export class PresentationsController {
}

try {
const formatData = await agent.proofs.getFormatData(record.id)
return await this.getPresentationData(record)
} catch (error) {
throw new InternalServerErrorException(error)
}
}

private async getPresentationData(proofExchange: ProofExchangeRecord): Promise<PresentationData> {
const agent = await this.agentService.getAgent()

const revealedAttributes =
formatData.presentation?.anoncreds?.requested_proof.revealed_attrs ??
formatData.presentation?.indy?.requested_proof.revealed_attrs
const formatData = await agent.proofs.getFormatData(proofExchange.id)

const revealedAttributeGroups =
formatData.presentation?.anoncreds?.requested_proof?.revealed_attr_groups ??
formatData.presentation?.indy?.requested_proof.revealed_attr_groups
const revealedAttributes =
formatData.presentation?.anoncreds?.requested_proof.revealed_attrs ??
formatData.presentation?.indy?.requested_proof.revealed_attrs

const claims: Claim[] = []
if (revealedAttributes) {
for (const [name, value] of Object.entries(revealedAttributes)) {
claims.push(new Claim({ name, value: value.raw }))
}
const revealedAttributeGroups =
formatData.presentation?.anoncreds?.requested_proof?.revealed_attr_groups ??
formatData.presentation?.indy?.requested_proof.revealed_attr_groups

const claims: Claim[] = []
if (revealedAttributes) {
for (const [name, value] of Object.entries(revealedAttributes)) {
claims.push(new Claim({ name, value: value.raw }))
}
}

if (revealedAttributeGroups) {
for (const [, groupAttributes] of Object.entries(revealedAttributeGroups)) {
for (const attrName in groupAttributes.values) {
claims.push(new Claim({ name: attrName, value: groupAttributes.values[attrName].raw }))
}
if (revealedAttributeGroups) {
for (const [, groupAttributes] of Object.entries(revealedAttributeGroups)) {
for (const attrName in groupAttributes.values) {
claims.push(new Claim({ name: attrName, value: groupAttributes.values[attrName].raw }))
}
}
return {
claims,
verified: record.isVerified ?? false,
state: record.state,
proofExchangeId: record.id,
threadId: record.threadId,
updatedAt: record.updatedAt,
}
} catch (error) {
throw new InternalServerErrorException(error)
}
return {
claims,
verified: proofExchange.isVerified ?? false,
state: proofExchange.state,
proofExchangeId: proofExchange.id,
threadId: proofExchange.threadId,
updatedAt: proofExchange.updatedAt,
}
}
}
12 changes: 12 additions & 0 deletions src/controllers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ import type {
HandshakeProtocol,
ReceiveOutOfBandInvitationConfig,
OutOfBandDidCommService,
ProofState,
} from '@credo-ts/core'

import { Claim } from '../model'

export interface AgentInfo {
label: string
endpoints: string[]
Expand Down Expand Up @@ -58,6 +61,15 @@ export interface CreatePresentationRequestResult {
shortUrl: string
}

export interface PresentationData {
claims: Claim[]
verified: boolean
state: ProofState
proofExchangeId: string
threadId: string
updatedAt: Date | undefined
}

export interface ClaimOptions {
name: string
mimeType?: string
Expand Down

0 comments on commit db463e9

Please sign in to comment.