Skip to content

Commit

Permalink
Added function to deny a credential offer
Browse files Browse the repository at this point in the history
Signed-off-by: Patrick Kenyon <[email protected]>
  • Loading branch information
TheTreek committed Apr 26, 2021
1 parent 3a83d8b commit 51848e3
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 1 deletion.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "aries-framework-javascript",
"version": "0.0.1-datatransfer.0",
"version": "0.0.1-datatransfer.1",
"license": "Apache-2.0",
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
Expand Down
2 changes: 2 additions & 0 deletions src/modules/credentials/CredentialState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export enum CredentialState {
ProposalReceived = 'proposal-received',
OfferSent = 'offer-sent',
OfferReceived = 'offer-received',
OfferDeclinedReceived = 'offer-declined-received',
OfferDeclinedSent = 'offer-declined-sent',
RequestSent = 'request-sent',
RequestReceived = 'request-received',
CredentialIssued = 'credential-issued',
Expand Down
11 changes: 11 additions & 0 deletions src/modules/credentials/CredentialsModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,17 @@ export class CredentialsModule {
return credentialRecord
}

/**
* Declines an offer as holder
* @param credentialRecordId the id of the credential to be declined
* @returns credential record that was declined
*/
public async declineOffer(credentialRecordId: string) {
const credentialRecord = await this.credentialService.getById(credentialRecordId)
await this.credentialService.declineOffer(credentialRecord)
return credentialRecord
}

/**
* Accept a credential request as issuer (by sending a credential message) to the connection
* associated with the credential record.
Expand Down
60 changes: 60 additions & 0 deletions src/modules/credentials/__tests__/CredentialService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -864,4 +864,64 @@ describe('CredentialService', () => {
)
})
})

describe('declineOffer', () => {
const threadId = 'fd9c5ddb-ec11-4acd-bc32-540736249754'
let credential: CredentialRecord

beforeEach(() => {
credential = mockCredentialRecord({
state: CredentialState.CredentialReceived,
tags: { threadId },
})
})

test(`updates state to ${CredentialState.OfferDeclinedSent}`, async () => {
// given
const repositoryUpdateSpy = jest.spyOn(credentialRepository, 'update')

// when
await credentialService.declineOffer(credential)

// then
expect(repositoryUpdateSpy).toHaveBeenCalledTimes(1)
const [[updatedCredentialRecord]] = repositoryUpdateSpy.mock.calls
expect(updatedCredentialRecord).toMatchObject({
state: CredentialState.OfferDeclinedSent,
})
})

test(`emits stateChange event from ${CredentialState.CredentialReceived} to ${CredentialState.OfferDeclinedSent}`, async () => {
const eventListenerMock = jest.fn()
credentialService.on(CredentialEventType.StateChanged, eventListenerMock)

// given
repositoryFindMock.mockReturnValue(Promise.resolve(credential))

// when
await credentialService.declineOffer(credential)

// then
expect(eventListenerMock).toHaveBeenCalledTimes(1)
const [[event]] = eventListenerMock.mock.calls
expect(event).toMatchObject({
previousState: CredentialState.CredentialReceived,
credentialRecord: {
state: CredentialState.OfferDeclinedSent,
},
})
})

const validState = CredentialState.CredentialReceived
const invalidCredentialStates = Object.values(CredentialState).filter((state) => state !== validState)
test(`throws an error when state transition is invalid`, async () => {
await Promise.all(
invalidCredentialStates.map(async (state) => {
await expect(
credentialService.createAck(mockCredentialRecord({ state, tags: { threadId } }))
).rejects.toThrowError(`Credential record is in invalid state ${state}. Valid states are: ${validState}.`)
})
)
})
})
})
2 changes: 2 additions & 0 deletions src/modules/credentials/__tests__/CredentialState.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ describe('CredentialState', () => {
expect(CredentialState.ProposalReceived).toBe('proposal-received')
expect(CredentialState.OfferSent).toBe('offer-sent')
expect(CredentialState.OfferReceived).toBe('offer-received')
expect(CredentialState.OfferDeclinedReceived).toBe('offer-declined-received')
expect(CredentialState.OfferDeclinedSent).toBe('offer-declined-sent')
expect(CredentialState.RequestSent).toBe('request-sent')
expect(CredentialState.RequestReceived).toBe('request-received')
expect(CredentialState.CredentialIssued).toBe('credential-issued')
Expand Down
12 changes: 12 additions & 0 deletions src/modules/credentials/services/CredentialService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,18 @@ export class CredentialService extends EventEmitter {
return { message: ackMessage, credentialRecord }
}

/**
* Decline a credential offer
* @param credentialRecord The credential to be declined
*/
public async declineOffer(
credentialRecord: CredentialRecord
): Promise<void> {
credentialRecord.assertState(CredentialState.OfferReceived)

await this.updateState(credentialRecord, CredentialState.OfferDeclinedSent)
}

/**
* Process a received {@link CredentialAckMessage}.
*
Expand Down

0 comments on commit 51848e3

Please sign in to comment.