Skip to content

Commit 9aef04a

Browse files
Merge pull request #3 from NB-MikeRichardson/rfc0453
refactor: resolve feedback for problem report (openwallet-foundation#584)
2 parents 4d7d3c1 + ef6b8bc commit 9aef04a

File tree

20 files changed

+63
-92
lines changed

20 files changed

+63
-92
lines changed

packages/core/src/agent/MessageReceiver.ts

+2-6
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,11 @@ import { Lifecycle, scoped } from 'tsyringe'
99

1010
import { AriesFrameworkError } from '../error'
1111
import { ConnectionService } from '../modules/connections/services/ConnectionService'
12-
import { ProblemReportError, ProblemReportMessage } from '../modules/problem-reports'
12+
import { ProblemReportError, ProblemReportMessage, ProblemReportReason } from '../modules/problem-reports'
1313
import { JsonTransformer } from '../utils/JsonTransformer'
1414
import { MessageValidator } from '../utils/MessageValidator'
1515
import { replaceLegacyDidSovPrefixOnMessage } from '../utils/messageType'
1616

17-
import { CommonMessageType } from './../modules/common/messages/CommonMessageType'
1817
import { AgentConfig } from './AgentConfig'
1918
import { Dispatcher } from './Dispatcher'
2019
import { EnvelopeService } from './EnvelopeService'
@@ -23,9 +22,6 @@ import { TransportService } from './TransportService'
2322
import { createOutboundMessage } from './helpers'
2423
import { InboundMessageContext } from './models/InboundMessageContext'
2524

26-
export enum ProblemReportReason {
27-
MessageParseFailure = 'message-parse-failure',
28-
}
2925
@scoped(Lifecycle.ContainerScoped)
3026
export class MessageReceiver {
3127
private config: AgentConfig
@@ -226,7 +222,7 @@ export class MessageReceiver {
226222
connection: ConnectionRecord,
227223
plaintextMessage: PlaintextMessage
228224
) {
229-
if (plaintextMessage['@type'] === CommonMessageType.ProblemReport) {
225+
if (plaintextMessage['@type'] === ProblemReportMessage.type) {
230226
throw new AriesFrameworkError(message)
231227
}
232228
const problemReportMessage = new ProblemReportMessage({

packages/core/src/decorators/signature/SignatureDecoratorUtils.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Wallet } from '../../wallet/Wallet'
22

3-
import { ConnectionProblemReportError, ConnectionProblemReportReason } from '../../modules/connections/errors'
3+
import { AriesFrameworkError } from '../../error'
44
import { BufferEncoder } from '../../utils/BufferEncoder'
55
import { JsonEncoder } from '../../utils/JsonEncoder'
66
import { Buffer } from '../../utils/buffer'
@@ -29,9 +29,7 @@ export async function unpackAndVerifySignatureDecorator(
2929
const isValid = await wallet.verify(signerVerkey, signedData, signature)
3030

3131
if (!isValid) {
32-
throw new ConnectionProblemReportError('Signature is not valid', {
33-
problemCode: ConnectionProblemReportReason.RequestProcessingError,
34-
})
32+
throw new AriesFrameworkError('Signature is not valid')
3533
}
3634

3735
// TODO: return Connection instance instead of raw json
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
export enum CommonMessageType {
22
Ack = 'https://didcomm.org/notification/1.0/ack',
3-
ProblemReport = 'https://didcomm.org/notification/1.0/problem-report',
43
}

packages/core/src/modules/connections/models/ConnectionState.ts

-1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,4 @@ export enum ConnectionState {
1010
Requested = 'requested',
1111
Responded = 'responded',
1212
Complete = 'complete',
13-
None = 'none',
1413
}

packages/core/src/modules/connections/repository/ConnectionRecord.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export interface ConnectionRecordProps {
2929
imageUrl?: string
3030
multiUseInvitation: boolean
3131
mediatorId?: string
32-
errorMsg?: string
32+
errorMessage?: string
3333
}
3434

3535
export type CustomConnectionTags = TagsBase
@@ -69,7 +69,7 @@ export class ConnectionRecord
6969

7070
public threadId?: string
7171
public mediatorId?: string
72-
public errorMsg?: string
72+
public errorMessage?: string
7373

7474
public static readonly type = 'ConnectionRecord'
7575
public readonly type = ConnectionRecord.type
@@ -96,7 +96,7 @@ export class ConnectionRecord
9696
this.imageUrl = props.imageUrl
9797
this.multiUseInvitation = props.multiUseInvitation
9898
this.mediatorId = props.mediatorId
99-
this.errorMsg = props.errorMsg
99+
this.errorMessage = props.errorMessage
100100
}
101101
}
102102

packages/core/src/modules/connections/services/ConnectionService.ts

+21-4
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,16 @@ export class ConnectionService {
323323
connectionRecord.assertState(ConnectionState.Requested)
324324
connectionRecord.assertRole(ConnectionRole.Invitee)
325325

326-
const connectionJson = await unpackAndVerifySignatureDecorator(message.connectionSig, this.wallet)
326+
let connectionJson = null
327+
try {
328+
connectionJson = await unpackAndVerifySignatureDecorator(message.connectionSig, this.wallet)
329+
} catch (error) {
330+
if (error instanceof AriesFrameworkError) {
331+
throw new ConnectionProblemReportError(error.message, {
332+
problemCode: ConnectionProblemReportReason.RequestProcessingError,
333+
})
334+
}
335+
}
327336

328337
const connection = JsonTransformer.fromJSON(connectionJson, Connection)
329338
await MessageValidator.validate(connection)
@@ -417,7 +426,7 @@ export class ConnectionService {
417426
public async processProblemReport(
418427
messageContext: InboundMessageContext<ConnectionProblemReportMessage>
419428
): Promise<ConnectionRecord> {
420-
const { message: connectionProblemReportMessage, recipientVerkey } = messageContext
429+
const { message: connectionProblemReportMessage, recipientVerkey, senderVerkey } = messageContext
421430

422431
this.logger.debug(`Processing connection problem report for verkey ${recipientVerkey}`)
423432

@@ -433,8 +442,12 @@ export class ConnectionService {
433442
)
434443
}
435444

436-
connectionRecord.errorMsg = `${connectionProblemReportMessage.description.code} : ${connectionProblemReportMessage.description.en}`
437-
await this.updateState(connectionRecord, ConnectionState.None)
445+
if (connectionRecord.theirKey && connectionRecord.theirKey !== senderVerkey) {
446+
throw new AriesFrameworkError("Sender verkey doesn't match verkey of connection record")
447+
}
448+
449+
connectionRecord.errorMessage = `${connectionProblemReportMessage.description.code} : ${connectionProblemReportMessage.description.en}`
450+
await this.update(connectionRecord)
438451
return connectionRecord
439452
}
440453

@@ -529,6 +542,10 @@ export class ConnectionService {
529542
})
530543
}
531544

545+
public update(connectionRecord: ConnectionRecord) {
546+
return this.connectionRepository.update(connectionRecord)
547+
}
548+
532549
/**
533550
* Retrieve all connections records
534551
*

packages/core/src/modules/credentials/CredentialState.ts

-1
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,4 @@ export enum CredentialState {
1414
CredentialIssued = 'credential-issued',
1515
CredentialReceived = 'credential-received',
1616
Done = 'done',
17-
None = 'none',
1817
}

packages/core/src/modules/credentials/__tests__/CredentialService.test.ts

+2-24
Original file line numberDiff line numberDiff line change
@@ -981,7 +981,7 @@ describe('CredentialService', () => {
981981
})
982982
})
983983

984-
test(`updates state to ${CredentialState.None} and returns credential record`, async () => {
984+
test(`updates problem report error message and returns credential record`, async () => {
985985
const repositoryUpdateSpy = jest.spyOn(credentialRepository, 'update')
986986

987987
// given
@@ -992,7 +992,7 @@ describe('CredentialService', () => {
992992

993993
// then
994994
const expectedCredentialRecord = {
995-
state: CredentialState.None,
995+
errorMessage: 'issuance-abandoned: Indy error',
996996
}
997997
expect(credentialRepository.getSingleByQuery).toHaveBeenNthCalledWith(1, {
998998
threadId: 'somethreadid',
@@ -1003,28 +1003,6 @@ describe('CredentialService', () => {
10031003
expect(updatedCredentialRecord).toMatchObject(expectedCredentialRecord)
10041004
expect(returnedCredentialRecord).toMatchObject(expectedCredentialRecord)
10051005
})
1006-
1007-
test(`emits stateChange event from ${CredentialState.OfferReceived} to ${CredentialState.None}`, async () => {
1008-
const eventListenerMock = jest.fn()
1009-
eventEmitter.on<CredentialStateChangedEvent>(CredentialEventTypes.CredentialStateChanged, eventListenerMock)
1010-
1011-
// given
1012-
mockFunction(credentialRepository.getSingleByQuery).mockReturnValue(Promise.resolve(credential))
1013-
1014-
// when
1015-
await credentialService.processProblemReport(messageContext)
1016-
1017-
// then
1018-
expect(eventListenerMock).toHaveBeenCalledWith({
1019-
type: 'CredentialStateChanged',
1020-
payload: {
1021-
previousState: CredentialState.OfferReceived,
1022-
credentialRecord: expect.objectContaining({
1023-
state: CredentialState.None,
1024-
}),
1025-
},
1026-
})
1027-
})
10281006
})
10291007

10301008
describe('repository methods', () => {

packages/core/src/modules/credentials/repository/CredentialRecord.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export interface CredentialRecordProps {
3333
credentialAttributes?: CredentialPreviewAttribute[]
3434
autoAcceptCredential?: AutoAcceptCredential
3535
linkedAttachments?: Attachment[]
36-
errorMsg?: string
36+
errorMessage?: string
3737
}
3838

3939
export type CustomCredentialTags = TagsBase
@@ -50,7 +50,7 @@ export class CredentialRecord extends BaseRecord<DefaultCredentialTags, CustomCr
5050
public credentialId?: string
5151
public state!: CredentialState
5252
public autoAcceptCredential?: AutoAcceptCredential
53-
public errorMsg?: string
53+
public errorMessage?: string
5454

5555
// message data
5656
@Type(() => ProposeCredentialMessage)
@@ -90,7 +90,7 @@ export class CredentialRecord extends BaseRecord<DefaultCredentialTags, CustomCr
9090
this.credentialAttributes = props.credentialAttributes
9191
this.autoAcceptCredential = props.autoAcceptCredential
9292
this.linkedAttachments = props.linkedAttachments
93-
this.errorMsg = props.errorMsg
93+
this.errorMessage = props.errorMessage
9494
}
9595
}
9696

packages/core/src/modules/credentials/services/CredentialService.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -733,7 +733,9 @@ export class CredentialService {
733733
public async processProblemReport(
734734
messageContext: InboundMessageContext<CredentialProblemReportMessage>
735735
): Promise<CredentialRecord> {
736-
const { message: credentialProblemReportMessage, connection } = messageContext
736+
const { message: credentialProblemReportMessage } = messageContext
737+
738+
const connection = messageContext.assertReadyConnection()
737739

738740
this.logger.debug(`Processing problem report with id ${credentialProblemReportMessage.id}`)
739741

@@ -743,8 +745,8 @@ export class CredentialService {
743745
)
744746

745747
// Update record
746-
credentialRecord.errorMsg = `${credentialProblemReportMessage.description.code}: ${credentialProblemReportMessage.description.en}`
747-
await this.updateState(credentialRecord, CredentialState.None)
748+
credentialRecord.errorMessage = `${credentialProblemReportMessage.description.code}: ${credentialProblemReportMessage.description.en}`
749+
await this.update(credentialRecord)
748750
return credentialRecord
749751
}
750752

Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export * from './errors'
22
export * from './messages'
3+
export * from './models'

packages/core/src/modules/problem-reports/messages/ProblemReportMessage.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { Expose } from 'class-transformer'
33
import { Equals, IsEnum, IsOptional, IsString } from 'class-validator'
44

55
import { AgentMessage } from '../../../agent/AgentMessage'
6-
import { CommonMessageType } from '../../common/messages/CommonMessageType'
76

87
export enum WhoRetriesStatus {
98
You = 'YOU',
@@ -80,7 +79,7 @@ export class ProblemReportMessage extends AgentMessage {
8079

8180
@Equals(ProblemReportMessage.type)
8281
public readonly type: string = ProblemReportMessage.type
83-
public static readonly type: string = CommonMessageType.ProblemReport
82+
public static readonly type: string = 'https://didcomm.org/notification/1.0/problem-report'
8483

8584
public description!: DescriptionOptions
8685

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export enum ProblemReportReason {
2+
MessageParseFailure = 'message-parse-failure',
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './ProblemReportReason'

packages/core/src/modules/proofs/ProofState.ts

-1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,4 @@ export enum ProofState {
1212
PresentationReceived = 'presentation-received',
1313
Declined = 'declined',
1414
Done = 'done',
15-
None = 'none',
1615
}

packages/core/src/modules/proofs/ProofsModule.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ export class ProofsModule {
386386
const presentationProblemReportMessage = new PresentationProblemReportMessage({
387387
description: {
388388
en: message,
389-
code: PresentationProblemReportReason.abandoned,
389+
code: PresentationProblemReportReason.Abandoned,
390390
},
391391
})
392392
presentationProblemReportMessage.setThread({

packages/core/src/modules/proofs/__tests__/ProofService.test.ts

+4-26
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ describe('ProofService', () => {
196196
const presentationProblemReportMessage = await new PresentationProblemReportMessage({
197197
description: {
198198
en: 'Indy error',
199-
code: PresentationProblemReportReason.abandoned,
199+
code: PresentationProblemReportReason.Abandoned,
200200
},
201201
})
202202

@@ -224,7 +224,7 @@ describe('ProofService', () => {
224224
const presentationProblemReportMessage = new PresentationProblemReportMessage({
225225
description: {
226226
en: 'Indy error',
227-
code: PresentationProblemReportReason.abandoned,
227+
code: PresentationProblemReportReason.Abandoned,
228228
},
229229
})
230230
presentationProblemReportMessage.setThread({ threadId: 'somethreadid' })
@@ -233,7 +233,7 @@ describe('ProofService', () => {
233233
})
234234
})
235235

236-
test(`updates state to ${ProofState.None} and returns proof record`, async () => {
236+
test(`updates problem report error message and returns proof record`, async () => {
237237
const repositoryUpdateSpy = jest.spyOn(proofRepository, 'update')
238238

239239
// given
@@ -244,7 +244,7 @@ describe('ProofService', () => {
244244

245245
// then
246246
const expectedCredentialRecord = {
247-
state: ProofState.None,
247+
errorMessage: 'abandoned: Indy error',
248248
}
249249
expect(proofRepository.getSingleByQuery).toHaveBeenNthCalledWith(1, {
250250
threadId: 'somethreadid',
@@ -255,27 +255,5 @@ describe('ProofService', () => {
255255
expect(updatedCredentialRecord).toMatchObject(expectedCredentialRecord)
256256
expect(returnedCredentialRecord).toMatchObject(expectedCredentialRecord)
257257
})
258-
259-
test(`emits stateChange event from ${ProofState.RequestReceived} to ${ProofState.None}`, async () => {
260-
const eventListenerMock = jest.fn()
261-
eventEmitter.on<ProofStateChangedEvent>(ProofEventTypes.ProofStateChanged, eventListenerMock)
262-
263-
// given
264-
mockFunction(proofRepository.getSingleByQuery).mockReturnValue(Promise.resolve(proof))
265-
266-
// when
267-
await proofService.processProblemReport(messageContext)
268-
269-
// then
270-
expect(eventListenerMock).toHaveBeenCalledWith({
271-
type: 'ProofStateChanged',
272-
payload: {
273-
previousState: ProofState.RequestReceived,
274-
proofRecord: expect.objectContaining({
275-
state: ProofState.None,
276-
}),
277-
},
278-
})
279-
})
280258
})
281259
})

packages/core/src/modules/proofs/errors/PresentationProblemReportReason.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
* @see https://github.com/hyperledger/aries-rfcs/blob/main/features/0037-present-proof/README.md
55
*/
66
export enum PresentationProblemReportReason {
7-
abandoned = 'abandoned',
7+
Abandoned = 'abandoned',
88
}

packages/core/src/modules/proofs/repository/ProofRecord.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export interface ProofRecordProps {
2020
presentationId?: string
2121
tags?: CustomProofTags
2222
autoAcceptProof?: AutoAcceptProof
23-
errorMsg?: string
23+
errorMessage?: string
2424

2525
// message data
2626
proposalMessage?: ProposePresentationMessage
@@ -42,7 +42,7 @@ export class ProofRecord extends BaseRecord<DefaultProofTags, CustomProofTags> {
4242
public presentationId?: string
4343
public state!: ProofState
4444
public autoAcceptProof?: AutoAcceptProof
45-
public errorMsg?: string
45+
public errorMessage?: string
4646

4747
// message data
4848
@Type(() => ProposePresentationMessage)
@@ -71,7 +71,7 @@ export class ProofRecord extends BaseRecord<DefaultProofTags, CustomProofTags> {
7171
this.presentationId = props.presentationId
7272
this.autoAcceptProof = props.autoAcceptProof
7373
this._tags = props.tags ?? {}
74-
this.errorMsg = props.errorMsg
74+
this.errorMessage = props.errorMessage
7575
}
7676
}
7777

0 commit comments

Comments
 (0)