Skip to content

Commit

Permalink
refactor: full ipex flow
Browse files Browse the repository at this point in the history
  • Loading branch information
bao-sotatek committed May 8, 2024
1 parent 635a05d commit fff8781
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 71 deletions.
4 changes: 2 additions & 2 deletions services/credential-issuance-server/src/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,18 +95,18 @@ class Agent {
default:
break;
}
await this.signifyApi.deleteNotification(notif.i);
}
await this.signifyApi.deleteNotification(notif.i);
}
async initKeri(issuerName?: string) {
this.onNotificationKeriStateChanged();
const AIDIssuerName = issuerName ? issuerName : Agent.ISSUER_AID_NAME;
const existedIndentifier = await this.signifyApi
.getIdentifierByName(AIDIssuerName)
.catch(() => null);
if (existedIndentifier) return existedIndentifier;
const identifier = await this.signifyApi.createIdentifier(AIDIssuerName);
this.keriRegistryRegk = await this.signifyApi.createRegistry(AIDIssuerName);
this.onNotificationKeriStateChanged();
return identifier;
}
}
Expand Down
132 changes: 96 additions & 36 deletions src/core/agent/services/ipexCommunicationService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,16 @@ const credentialStorage = jest.mocked({
});

let credentialListMock = jest.fn();
let credentialGetMock = jest.fn();
let identifierListMock = jest.fn();
let getExchangeMock = jest.fn().mockImplementation((id: string) => {
if (id == "saidForUuid") {
return {
exn: {
a: {
i: "uuid",
a: {},
s: "schemaSaid",
},
i: "i",
e: {
Expand Down Expand Up @@ -124,6 +127,7 @@ const signifyClient = jest.mocked({
}),
credentials: () => ({
list: credentialListMock,
get: credentialGetMock,
}),
exchanges: () => ({
get: getExchangeMock,
Expand Down Expand Up @@ -287,7 +291,7 @@ describe("Ipex communication service of agent", () => {
signifyName: "abc123",
});
ipexOfferMock.mockResolvedValue(["offer", "sigs", "gend"]);
await ipexCommunicationService.offerAcdc(id);
await ipexCommunicationService.offerAcdc(id, "credId");
expect(ipexOfferMock).toBeCalledWith({
senderName: "abc123",
recipient: "i",
Expand All @@ -296,35 +300,6 @@ describe("Ipex communication service of agent", () => {
expect(notificationStorage.deleteById).toBeCalledWith(id);
});

test("can not offer Keri Acdc if the acdc is not existed", async () => {
const id = "uuid";
const date = new Date();
notificationStorage.findById = jest.fn().mockImplementation((id) => {
if (id == "uuid") {
return {
id,
createdAt: date,
a: {
d: "keri",
},
};
}
return;
});
getExchangeMock = jest.fn().mockReturnValue({
exn: {
a: {
s: "schemaSaid",
},
i: "i",
},
});
credentialListMock = jest.fn().mockReturnValue([]);
await expect(ipexCommunicationService.offerAcdc(id)).rejects.toThrowError(
IpexCommunicationService.CREDENTIAL_NOT_FOUND_WITH_SCHEMA
);
});

test("can not offer Keri Acdc if aid is not existed", async () => {
const id = "uuid";
const date = new Date();
Expand All @@ -350,11 +325,13 @@ describe("Ipex communication service of agent", () => {
},
});
credentialListMock = jest.fn().mockReturnValue([{}]);
identifierStorage.getIdentifierMetadata = jest.fn().mockReturnValue(null);
identifierStorage.getIdentifierMetadata = jest
.fn()
.mockRejectedValue(new Error());
identifierListMock = jest.fn().mockReturnValue({ aids: [] });
await expect(ipexCommunicationService.offerAcdc(id)).rejects.toThrowError(
IpexCommunicationService.AID_NOT_FOUND
);
await expect(
ipexCommunicationService.offerAcdc(id, "credId")
).rejects.toThrowError(IpexCommunicationService.AID_NOT_FOUND);
});

test("can grant Keri Acdc when received the ipex agree", async () => {
Expand Down Expand Up @@ -383,7 +360,7 @@ describe("Ipex communication service of agent", () => {
i: "i",
},
});
credentialListMock = jest.fn().mockReturnValue([{}]);
credentialGetMock = jest.fn().mockReturnValue({});
identifierStorage.getIdentifierMetadata = jest.fn().mockReturnValue({
signifyName: "abc123",
});
Expand Down Expand Up @@ -462,9 +439,92 @@ describe("Ipex communication service of agent", () => {
i: "i",
},
});
credentialListMock = jest.fn().mockReturnValue([]);
credentialGetMock = jest.fn().mockReturnValue(null);
await expect(
ipexCommunicationService.grantApplyAcdc(id)
).rejects.toThrowError(IpexCommunicationService.CREDENTIAL_NOT_FOUND);
});

test("can get matching credential for apply", async () => {
const notiId = "notiId";
getExchangeMock = jest.fn().mockResolvedValue({
exn: {
a: {
i: "uuid",
a: {},
s: "schemaSaid",
},
i: "i",
e: {},
},
});
notificationStorage.findById = jest.fn().mockResolvedValue({
id: notiId,
createdAt: "2024-04-29T11:01:04.903Z",
a: {
d: "saidForUuid",
},
});
credentialStorage.getCredentialMetadata.mockResolvedValue({
id: "id",
status: "confirmed",
});
credentialListMock.mockResolvedValue([
{
sad: {
d: "d",
},
},
]);
expect(
await ipexCommunicationService.getMatchingCredsForApply(notiId)
).toEqual([
{
acdc: {
sad: {
d: "d",
},
},
credentialType: undefined,
id: "id",
issuanceDate: undefined,
status: "confirmed",
},
]);
});

test("cannot get matching credential for apply if cannot find the credential metdadata", async () => {
const notiId = "notiId";
getExchangeMock = jest.fn().mockResolvedValue({
exn: {
a: {
i: "uuid",
a: {},
s: "schemaSaid",
},
i: "i",
e: {},
},
});
notificationStorage.findById = jest.fn().mockResolvedValue({
id: notiId,
createdAt: "2024-04-29T11:01:04.903Z",
a: {
d: "saidForUuid",
},
});
credentialStorage.getCredentialMetadata.mockResolvedValue(null);
credentialListMock.mockResolvedValue([
{
sad: {
d: "d",
},
},
]);
await expect(
ipexCommunicationService.getMatchingCredsForApply(notiId)
).rejects.toThrowError(
IpexCommunicationService.CREDENTIAL_MISSING_METADATA_ERROR_MSG
);
});
});
83 changes: 50 additions & 33 deletions src/core/agent/services/ipexCommunicationService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,40 +110,28 @@ class IpexCommunicationService extends AgentService {
});
}

async offerAcdc(notificationId: string) {
async offerAcdc(notificationId: string, acdc: any) {
const keriNoti = await this.getNotificationRecordById(notificationId);
const msgSaid = keriNoti.a.d as string;
const msg = await this.signifyClient.exchanges().get(msgSaid);
const schemaSaid = msg.exn.a.s;
const creds = await this.signifyClient.credentials().list({
filter: {
"-s": { $eq: schemaSaid },
},
});
if (!creds || creds.length === 0) {
throw new Error(
IpexCommunicationService.CREDENTIAL_NOT_FOUND_WITH_SCHEMA
);
}
const pickedCred = creds[0];
let holderSignifyName;
const signifyName = (
await this.identifierStorage.getIdentifierMetadata(msg.exn.a.i)
).signifyName;
if (signifyName) {
holderSignifyName = signifyName;
} else {
try {
holderSignifyName = (
await this.identifierStorage.getIdentifierMetadata(msg.exn.a.i)
).signifyName;
} catch (error) {
const identifierHolder = await this.getIdentifierById(msg.exn.a.i);
holderSignifyName = identifierHolder?.name;
}

if (!holderSignifyName) {
throw new Error(IpexCommunicationService.AID_NOT_FOUND);
}

const [offer, sigs, gend] = await this.signifyClient.ipex().offer({
senderName: holderSignifyName,
recipient: msg.exn.i,
acdc: new Serder(pickedCred),
acdc: new Serder(acdc.sad),
});
await this.signifyClient
.ipex()
Expand All @@ -156,22 +144,18 @@ class IpexCommunicationService extends AgentService {
const msgSaid = keriNoti.a.d as string;
const msg = await this.signifyClient.exchanges().get(msgSaid);
const exnMessage = JSON.parse(msg.exn.a.m);
const creds = await this.signifyClient.credentials().list({
filter: {
"-d": { $eq: exnMessage.acdc.d },
},
});
if (!creds || creds.length === 0) {
const pickedCred = await this.signifyClient
.credentials()
.get(exnMessage.acdc.d);
if (!pickedCred) {
throw new Error(IpexCommunicationService.CREDENTIAL_NOT_FOUND);
}
const pickedCred = creds[0];
let holderSignifyName;
const signifyName = (
await this.identifierStorage.getIdentifierMetadata(msg.exn.a.i)
).signifyName;
if (signifyName) {
holderSignifyName = signifyName;
} else {
try {
holderSignifyName = (
await this.identifierStorage.getIdentifierMetadata(msg.exn.a.i)
).signifyName;
} catch (error) {
const identifierHolder = await this.getIdentifierById(msg.exn.a.i);
holderSignifyName = identifierHolder?.name;
}
Expand Down Expand Up @@ -214,6 +198,39 @@ class IpexCommunicationService extends AgentService {
return acdc;
}

async getMatchingCredsForApply(notificationId: string) {
const keriNoti = await this.getNotificationRecordById(notificationId);
const msgSaid = keriNoti.a.d as string;
const msg = await this.signifyClient.exchanges().get(msgSaid);
const schemaSaid = msg.exn.a.s;
const attributes = msg.exn.a.a;
const creds = await this.signifyClient.credentials().list({
filter: {
"-s": { $eq: schemaSaid },
...(Object.keys(attributes).length > 0
? {
"-a": {
...attributes,
},
}
: {}),
},
});
return Promise.all(
creds.map(async (cred: any) => {
const metadata = await this.credentialStorage.getCredentialMetadata(
`metadata:${cred.sad.d}`
);
if (!metadata) {
throw new Error(
IpexCommunicationService.CREDENTIAL_MISSING_METADATA_ERROR_MSG
);
}
return { ...getCredentialShortDetails(metadata), acdc: cred };
})
);
}

private async getNotificationRecordById(
id: string
): Promise<KeriaNotification> {
Expand Down

0 comments on commit fff8781

Please sign in to comment.