Skip to content

Commit

Permalink
fix: miscellaneous issue credential v2 fixes (#769)
Browse files Browse the repository at this point in the history
Signed-off-by: Mike Richardson <[email protected]>
  • Loading branch information
NB-MikeRichardson authored May 25, 2022
1 parent 5b42e6c commit 537b51e
Show file tree
Hide file tree
Showing 23 changed files with 120 additions and 141 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ export interface ServiceAcceptOfferOptions extends AcceptOfferOptions {
export interface ServiceOfferCredentialOptions extends OfferCredentialOptions {
connectionId?: string
attachId?: string
// offerAttachment?: Attachment
}

export interface ServiceAcceptProposalOptions extends AcceptProposalOptions {
Expand All @@ -71,6 +70,7 @@ export interface ServiceRequestCredentialOptions extends RequestCredentialOption
attachId?: string
offerAttachment?: Attachment
requestAttachment?: Attachment
holderDid?: string
}

export interface ServiceAcceptCredentialOptions {
Expand Down
13 changes: 7 additions & 6 deletions packages/core/src/modules/credentials/CredentialsModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,9 @@ export class CredentialsModule implements CredentialsModule {
const requestOptions: RequestCredentialOptions = {
comment: options.comment,
autoAcceptCredential: options.autoAcceptCredential,
holderDid: connection.did,
}
const { message, credentialRecord } = await service.createRequest(record, requestOptions, connection.did)
const { message, credentialRecord } = await service.createRequest(record, requestOptions)

await this.didCommMessageRepo.saveAgentMessage({
agentMessage: message,
Expand Down Expand Up @@ -272,12 +273,9 @@ export class CredentialsModule implements CredentialsModule {
const requestOptions: RequestCredentialOptions = {
comment: options.comment,
autoAcceptCredential: options.autoAcceptCredential,
holderDid: ourService.recipientKeys[0],
}
const { message, credentialRecord } = await service.createRequest(
record,
requestOptions,
ourService.recipientKeys[0]
)
const { message, credentialRecord } = await service.createRequest(record, requestOptions)

// Set and save ~service decorator to record (to remember our verkey)
message.service = ourService
Expand Down Expand Up @@ -349,6 +347,9 @@ export class CredentialsModule implements CredentialsModule {
if (!options.connectionId) {
throw new AriesFrameworkError('Missing connectionId on offerCredential')
}
if (!options.protocolVersion) {
throw new AriesFrameworkError('Missing protocol version in offerCredential')
}
const connection = await this.connectionService.getById(options.connectionId)

const service = this.getService(options.protocolVersion)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ interface ProposeCredentialOptions extends BaseOptions {
}

interface AcceptProposalOptions extends BaseOptions {
connectionId?: string
protocolVersion: CredentialProtocolVersion
credentialRecordId: string
credentialFormats: FormatServiceAcceptProposeCredentialFormats
}
Expand Down Expand Up @@ -57,6 +55,7 @@ interface NegotiateOfferOptions extends ProposeCredentialOptions {
interface RequestCredentialOptions extends BaseOptions {
connectionId?: string
credentialFormats?: FormatServiceRequestCredentialFormats
holderDid?: string
}

interface AcceptRequestOptions extends BaseOptions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,8 @@ describe('CredentialService', () => {
// mock offer so that the request works

// when
const options: RequestCredentialOptions = {}
await credentialService.createRequest(credentialRecord, options, 'holderDid')
const options: RequestCredentialOptions = { holderDid: 'holderDid' }
await credentialService.createRequest(credentialRecord, options)

// then
expect(repositoryUpdateSpy).toHaveBeenCalledTimes(1)
Expand All @@ -310,14 +310,11 @@ describe('CredentialService', () => {
const options: RequestCredentialOptions = {
connectionId: credentialRecord.connectionId,
comment: 'credential request comment',
holderDid: 'holderDid',
}

// when
const { message: credentialRequest } = await credentialService.createRequest(
credentialRecord,
options,
'holderDid'
)
const { message: credentialRequest } = await credentialService.createRequest(credentialRecord, options)

// then
expect(credentialRequest.toJSON()).toMatchObject({
Expand Down Expand Up @@ -345,7 +342,7 @@ describe('CredentialService', () => {
await Promise.all(
invalidCredentialStates.map(async (state) => {
await expect(
credentialService.createRequest(mockCredentialRecord({ state }), {}, 'holderDid')
credentialService.createRequest(mockCredentialRecord({ state }), { holderDid: 'holderDid' })
).rejects.toThrowError(`Credential record is in invalid state ${state}. Valid states are: ${validState}.`)
})
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,11 +293,12 @@ describe('CredentialService', () => {

const requestOptions: RequestCredentialOptions = {
credentialFormats: v2CredentialRequest,
holderDid: 'holderDid',
}

// when

await credentialService.createRequest(credentialRecord, requestOptions, 'holderDid')
await credentialService.createRequest(credentialRecord, requestOptions)

// then
expect(repositoryUpdateSpy).toHaveBeenCalledTimes(1)
Expand All @@ -314,13 +315,10 @@ describe('CredentialService', () => {
const options: RequestCredentialOptions = {
connectionId: credentialRecord.connectionId,
comment: 'credential request comment',
holderDid: 'holderDid',
}
// when
const { message: credentialRequest } = await credentialService.createRequest(
credentialRecord,
options,
'holderDid'
)
const { message: credentialRequest } = await credentialService.createRequest(credentialRecord, options)

// then
expect(credentialRequest.toJSON()).toMatchObject({
Expand Down Expand Up @@ -348,7 +346,7 @@ describe('CredentialService', () => {
await Promise.all(
invalidCredentialStates.map(async (state) => {
await expect(
credentialService.createRequest(mockCredentialRecord({ state }), {}, 'mockDid')
credentialService.createRequest(mockCredentialRecord({ state }), { holderDid: 'mockDid' })
).rejects.toThrowError(`Credential record is in invalid state ${state}. Valid states are: ${validState}.`)
})
)
Expand Down
15 changes: 15 additions & 0 deletions packages/core/src/modules/credentials/composeAutoAccept.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Returns the credential auto accept config based on priority:
* - The record config takes first priority
* - Otherwise the agent config
* - Otherwise {@link AutoAcceptCredential.Never} is returned
*/

import { AutoAcceptCredential } from './CredentialAutoAcceptType'

export function composeAutoAccept(
recordConfig: AutoAcceptCredential | undefined,
agentConfig: AutoAcceptCredential | undefined
) {
return recordConfig ?? agentConfig ?? AutoAcceptCredential.Never
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import type { V1CredentialPreview } from '../../protocol/v1/V1CredentialPreview'
import type { CredentialExchangeRecord } from '../../repository/CredentialExchangeRecord'
import type {
FormatServiceCredentialAttachmentFormats,
CredentialFormatSpec,
HandlerAutoAcceptOptions,
FormatServiceOfferAttachmentFormats,
FormatServiceProposeAttachmentFormats,
Expand All @@ -38,15 +37,16 @@ import { uuid } from '../../../../utils/uuid'
import { IndyHolderService, IndyIssuerService } from '../../../indy'
import { IndyLedgerService } from '../../../ledger'
import { AutoAcceptCredential } from '../../CredentialAutoAcceptType'
import { CredentialResponseCoordinator } from '../../CredentialResponseCoordinator'
import { CredentialUtils } from '../../CredentialUtils'
import { CredentialFormatType } from '../../CredentialsModuleOptions'
import { composeAutoAccept } from '../../composeAutoAccept'
import { CredentialProblemReportError, CredentialProblemReportReason } from '../../errors'
import { V2CredentialPreview } from '../../protocol/v2/V2CredentialPreview'
import { CredentialMetadataKeys } from '../../repository/CredentialMetadataTypes'
import { CredentialRepository } from '../../repository/CredentialRepository'
import { CredentialFormatService } from '../CredentialFormatService'
import { CredPropose } from '../models/CredPropose'
import { CredentialFormatSpec } from '../models/CredentialFormatServiceOptions'

@scoped(Lifecycle.ContainerScoped)
export class IndyCredentialFormatService extends CredentialFormatService {
Expand Down Expand Up @@ -85,6 +85,7 @@ export class IndyCredentialFormatService extends CredentialFormatService {
attachId: this.generateId(),
format: 'hlindy/[email protected]',
}

if (!options.credentialFormats.indy?.payload) {
throw new AriesFrameworkError('Missing payload in createProposal')
}
Expand All @@ -111,26 +112,25 @@ export class IndyCredentialFormatService extends CredentialFormatService {
options: ServiceAcceptProposalOptions,
credentialRecord: CredentialExchangeRecord
): Promise<void> {
let credPropose = options.proposalAttachment?.getDataAsJson<CredPropose>()
credPropose = JsonTransformer.fromJSON(credPropose, CredPropose)

if (!credPropose) {
const credProposalJson = options.proposalAttachment?.getDataAsJson<CredPropose>()
if (!credProposalJson) {
throw new AriesFrameworkError('Missing indy credential proposal data payload')
}
await MessageValidator.validate(credPropose)
const credProposal = JsonTransformer.fromJSON(credProposalJson, CredPropose)
await MessageValidator.validate(credProposal)

if (credPropose.credentialDefinitionId) {
if (credProposal.credentialDefinitionId) {
options.credentialFormats = {
indy: {
credentialDefinitionId: credPropose?.credentialDefinitionId,
credentialDefinitionId: credProposal?.credentialDefinitionId,
attributes: [],
},
}
}

credentialRecord.metadata.set(CredentialMetadataKeys.IndyCredential, {
schemaId: credPropose.schemaId,
credentialDefinitionId: credPropose.credentialDefinitionId,
schemaId: credProposal.schemaId,
credentialDefinitionId: credProposal.credentialDefinitionId,
})
}

Expand All @@ -143,10 +143,10 @@ export class IndyCredentialFormatService extends CredentialFormatService {
*
*/
public async createOffer(options: ServiceOfferCredentialOptions): Promise<FormatServiceOfferAttachmentFormats> {
const formats: CredentialFormatSpec = {
const formats = new CredentialFormatSpec({
attachId: this.generateId(),
format: 'hlindy/[email protected]',
}
})
const offer = await this.createCredentialOffer(options)

let preview: V2CredentialPreview | undefined
Expand Down Expand Up @@ -195,24 +195,29 @@ export class IndyCredentialFormatService extends CredentialFormatService {
*/
public async createRequest(
options: ServiceRequestCredentialOptions,
credentialRecord: CredentialExchangeRecord,
holderDid: string
credentialRecord: CredentialExchangeRecord
): Promise<FormatServiceCredentialAttachmentFormats> {
if (!options.offerAttachment) {
throw new AriesFrameworkError(
`Missing attachment from offer message, credential record id = ${credentialRecord.id}`
)
}

if (!options.holderDid) {
throw new AriesFrameworkError(
`Missing holder DID from offer message, credential record id = ${credentialRecord.id}`
)
}
const offer = options.offerAttachment.getDataAsJson<CredOffer>()
const credDef = await this.getCredentialDefinition(offer)

const { credReq, credReqMetadata } = await this.createIndyCredentialRequest(offer, credDef, holderDid)
const { credReq, credReqMetadata } = await this.createIndyCredentialRequest(offer, credDef, options.holderDid)
credentialRecord.metadata.set(CredentialMetadataKeys.IndyRequest, credReqMetadata)

const formats: CredentialFormatSpec = {
const formats = new CredentialFormatSpec({
attachId: this.generateId(),
format: 'hlindy/[email protected]',
}
})

const attachmentId = options.attachId ?? formats.attachId
const requestAttach: Attachment = this.getFormatData(credReq, attachmentId)
Expand Down Expand Up @@ -375,10 +380,10 @@ export class IndyCredentialFormatService extends CredentialFormatService {
credentialValues: CredentialUtils.convertAttributesToValues(credentialAttributes),
})

const formats: CredentialFormatSpec = {
const formats = new CredentialFormatSpec({
attachId: this.generateId(),
format: 'hlindy/[email protected]',
}
})

const attachmentId = options.attachId ? options.attachId : formats.attachId
const issueAttachment = this.getFormatData(credential, attachmentId)
Expand Down Expand Up @@ -439,7 +444,7 @@ export class IndyCredentialFormatService extends CredentialFormatService {
*/

public shouldAutoRespondToProposal(handlerOptions: HandlerAutoAcceptOptions): boolean {
const autoAccept = CredentialResponseCoordinator.composeAutoAccept(
const autoAccept = composeAutoAccept(
handlerOptions.credentialRecord.autoAcceptCredential,
handlerOptions.autoAcceptType
)
Expand All @@ -463,10 +468,7 @@ export class IndyCredentialFormatService extends CredentialFormatService {
*/

public shouldAutoRespondToRequest(options: HandlerAutoAcceptOptions): boolean {
const autoAccept = CredentialResponseCoordinator.composeAutoAccept(
options.credentialRecord.autoAcceptCredential,
options.autoAcceptType
)
const autoAccept = composeAutoAccept(options.credentialRecord.autoAcceptCredential, options.autoAcceptType)

if (!options.requestAttachment) {
throw new AriesFrameworkError(`Missing Request Attachment for Credential Record ${options.credentialRecord.id}`)
Expand All @@ -489,10 +491,7 @@ export class IndyCredentialFormatService extends CredentialFormatService {
*/

public shouldAutoRespondToCredential(options: HandlerAutoAcceptOptions): boolean {
const autoAccept = CredentialResponseCoordinator.composeAutoAccept(
options.credentialRecord.autoAcceptCredential,
options.autoAcceptType
)
const autoAccept = composeAutoAccept(options.credentialRecord.autoAcceptCredential, options.autoAcceptType)

if (autoAccept === AutoAcceptCredential.ContentApproved) {
if (options.credentialAttachment) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ export interface IndyIssueCredentialFormat {
}

export class CredentialFormatSpec {
public constructor(options: { attachId: string; format: string }) {
if (options) {
this.attachId = options.attachId
this.format = options.format
}
}
@Expose({ name: 'attach_id' })
@IsString()
public attachId!: string
Expand Down
1 change: 0 additions & 1 deletion packages/core/src/modules/credentials/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,3 @@ export * from './CredentialState'
export * from './CredentialEvents'
export * from './CredentialAutoAcceptType'
export * from './CredentialProtocolVersion'
export * from './CredentialResponseCoordinator'
Loading

0 comments on commit 537b51e

Please sign in to comment.