Skip to content

Commit

Permalink
fix: update name of local member in signify group identifier when del…
Browse files Browse the repository at this point in the history
…eting (#864)

* fix: update name of local member in signify group identifier when deleting

* fix: mock get secure storage

* fix: update name of local member in cloud when deleting group identifier
  • Loading branch information
Sotatek-BaoHoanga authored Dec 12, 2024
1 parent f1fde87 commit 4a48787
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 52 deletions.
81 changes: 51 additions & 30 deletions src/core/agent/services/identifierService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { CoreEventEmitter } from "../event";
import { IdentifierService } from "./identifierService";
import { EventTypes } from "../event.types";
import { OperationPendingRecordType } from "../records/operationPendingRecord.type";
import { IdentifierStorage } from "../records";
import * as utils from "./utils";

const listIdentifiersMock = jest.fn();
const getIdentifierMembersMock = jest.fn();
Expand Down Expand Up @@ -229,19 +229,21 @@ const WITNESSES = [
"http://witnesess:5644/oobi/BIKKuvBwpmDVA4Ds-EpL5bt9OqPzWPja2LigFYZN2YfX/controller?role=witness",
"http://witnesess:5645/oobi/BM35JN8XeJSEfpxopjn5jr7tAHCE5749f0OobhMLCorE/controller?role=witness",
"http://witnesess:5646/oobi/BIj15u5V11bkbtAxMA7gcNJZcax-7TgaBMLsQnMHpYHP/controller?role=witness",
"http://witnesess:5647/oobi/BF2rZTW79z4IXocYRQnjjsOuvFUQv-ptCf8Yltd7PfsM/controller?role=witness"
"http://witnesess:5647/oobi/BF2rZTW79z4IXocYRQnjjsOuvFUQv-ptCf8Yltd7PfsM/controller?role=witness",
];
const witnessEids = WITNESSES.map((oobi: string) => oobi.split("/oobi/")[1].split("/")[0]);
const witnessEids = WITNESSES.map(
(oobi: string) => oobi.split("/oobi/")[1].split("/")[0]
);

describe("Single sig service of agent", () => {
beforeEach(() => {
jest.resetAllMocks();

getAgentConfigMock.mockResolvedValue({
iurls: WITNESSES
iurls: WITNESSES,
});
});

test("can get all identifiers", async () => {
identifierStorage.getAllIdentifierMetadata = jest
.fn()
Expand Down Expand Up @@ -369,7 +371,7 @@ describe("Single sig service of agent", () => {
});
expect(createIdentifierMock).toBeCalledWith(`0:${displayName}`, {
toad: WITNESSES.length,
wits: witnessEids
wits: witnessEids,
});
expect(identifierStorage.createIdentifierMetadataRecord).toBeCalledTimes(1);
});
Expand Down Expand Up @@ -414,7 +416,7 @@ describe("Single sig service of agent", () => {
});
expect(createIdentifierMock).toBeCalledWith(`0:${displayName}`, {
toad: WITNESSES.length,
wits: witnessEids
wits: witnessEids,
});
expect(identifierStorage.createIdentifierMetadataRecord).toBeCalledTimes(1);
expect(eventEmitter.emit).toHaveBeenCalledWith({
Expand Down Expand Up @@ -464,7 +466,9 @@ describe("Single sig service of agent", () => {
test("cannot create identifier is there are no discoverable witnesses", async () => {
Agent.agent.getKeriaOnlineStatus = jest.fn().mockReturnValueOnce(true);
getAgentConfigMock.mockResolvedValueOnce({
iurls: ["http://witnesess:5642/oobi/BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha/controller"]
iurls: [
"http://witnesess:5642/oobi/BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha/controller",
],
});

await expect(
Expand Down Expand Up @@ -525,18 +529,23 @@ describe("Single sig service of agent", () => {
});

test("should delete the local member identifier for that multisig if deleting the multi-sig identifier", async () => {
const localMember = {
id: "aidLocalMember",
displayName: "Identifier Local",
createdAt: now,
theme: 0,
groupMetadata,
isPending: true,
multisigManageAid: "manageAid",
};
identifierStorage.getIdentifierMetadata
.mockReturnValueOnce({
...keriMetadataRecord,
isPending: true,
multisigManageAid: "manageAid",
groupMetadata: undefined,
})
.mockReturnValueOnce({
...keriMetadataRecord,
isPending: true,
multisigManageAid: "manageAid",
});
.mockReturnValueOnce(localMember);
connections.getMultisigLinkedContacts = jest.fn().mockResolvedValue([
{
id: "group-id",
Expand All @@ -550,8 +559,10 @@ describe("Single sig service of agent", () => {
PeerConnection.peerConnection.getConnectingIdentifier = jest
.fn()
.mockReturnValue({ id: identifierMetadataRecord.id, oobi: "oobi" });
// eslint-disable-next-line @typescript-eslint/no-var-requires
jest.spyOn(require("./utils"), "randomSalt").mockReturnValue("0ADQpus-mQmmO4mgWcT3ekDz");
jest
.spyOn(utils, "randomSalt")
.mockReturnValueOnce("QOP7zdP-kJs8nlwVR290XfyAk")
.mockReturnValueOnce("0ADQpus-mQmmO4mgWcT3ekDz");

await identifierService.deleteIdentifier(identifierMetadataRecord.id);

Expand All @@ -563,9 +574,13 @@ describe("Single sig service of agent", () => {
pendingDeletion: false,
}
);
expect(updateIdentifierMock).toBeCalledWith(localMember.id, {
name: `XX-QOP7zdP-kJs8nlwVR290XfyAk:${localMember.groupMetadata.groupId}:${localMember.displayName}`,
});
expect(updateIdentifierMock).toBeCalledWith(identifierMetadataRecord.id, {
name: `XX-0ADQpus-mQmmO4mgWcT3ekDz:${identifierMetadataRecord.displayName}`
name: `XX-0ADQpus-mQmmO4mgWcT3ekDz:${identifierMetadataRecord.displayName}`,
});
expect(updateIdentifierMock).toBeCalledTimes(2);
});

test("can update an identifier", async () => {
Expand Down Expand Up @@ -599,8 +614,7 @@ describe("Single sig service of agent", () => {
PeerConnection.peerConnection.getConnectingIdentifier = jest
.fn()
.mockReturnValue({ id: identifierMetadataRecord.id, oobi: "oobi" });
// eslint-disable-next-line @typescript-eslint/no-var-requires
jest.spyOn(require("./utils"), "randomSalt").mockReturnValue("0ADQpus-mQmmO4mgWcT3ekDz");
jest.spyOn(utils, "randomSalt").mockReturnValue("0ADQpus-mQmmO4mgWcT3ekDz");

await identifierService.deleteIdentifier(identifierMetadataRecord.id);

Expand All @@ -615,7 +629,7 @@ describe("Single sig service of agent", () => {
}
);
expect(updateIdentifierMock).toBeCalledWith(identifierMetadataRecord.id, {
name: `XX-0ADQpus-mQmmO4mgWcT3ekDz:${identifierMetadataRecord.displayName}`
name: `XX-0ADQpus-mQmmO4mgWcT3ekDz:${identifierMetadataRecord.displayName}`,
});
expect(PeerConnection.peerConnection.disconnectDApp).toBeCalledWith(
"dApp-address",
Expand All @@ -626,7 +640,7 @@ describe("Single sig service of agent", () => {
test("Should correctly sync KERI identifiers, handling both group and non-group cases", async () => {
// Mock the online status of the agent
Agent.agent.getKeriaOnlineStatus = jest.fn().mockReturnValue(true);

// Mock the list of identifiers returned by signifyClient
listIdentifiersMock.mockReturnValue({
aids: [
Expand All @@ -650,12 +664,14 @@ describe("Single sig service of agent", () => {
},
],
});

// Mock the identifier storage
identifierStorage.getKeriIdentifiersMetadata = jest.fn().mockReturnValue([]);
identifierStorage.getKeriIdentifiersMetadata = jest
.fn()
.mockReturnValue([]);
identifierStorage.createIdentifierMetadataRecord = jest.fn();
identifierStorage.updateIdentifierMetadata = jest.fn();

// Mock the signifyClient operations call
const mockOperation = {
done: true,
Expand All @@ -664,12 +680,14 @@ describe("Single sig service of agent", () => {
jest
.spyOn(signifyClient.operations(), "get")
.mockResolvedValue(mockOperation);

// Call the function to test
await identifierService.syncKeriaIdentifiers();

// sync data of non-group record
expect(identifierStorage.createIdentifierMetadataRecord).toHaveBeenCalledWith({
expect(
identifierStorage.createIdentifierMetadataRecord
).toHaveBeenCalledWith({
id: "EL-EboMhx-DaBLiAS_Vm3qtJOubb2rkcS3zLU_r7UXtl",
displayName: "1-group1",
theme: 0,
Expand All @@ -680,8 +698,10 @@ describe("Single sig service of agent", () => {
},
isPending: false,
});

expect(identifierStorage.createIdentifierMetadataRecord).toHaveBeenCalledWith({

expect(
identifierStorage.createIdentifierMetadataRecord
).toHaveBeenCalledWith({
id: "EJ9oenRW3_SNc0JkETnOegspNGaDCypBfTU1kJiL2AMs",
displayName: "EJ9oenRW3_SNc0JkETnOegspNGaDCypBfTU1kJiL2AMs",
theme: 33,
Expand All @@ -700,15 +720,16 @@ describe("Single sig service of agent", () => {
}
);

expect(identifierStorage.createIdentifierMetadataRecord).toHaveBeenCalledWith({
expect(
identifierStorage.createIdentifierMetadataRecord
).toHaveBeenCalledWith({
id: "EPMFON5GHY3o4mLr7XsHvXBCED4gkr1ILUX9NSRkOPM",
displayName: "1-group1",
theme: 15,
multisigManageAid: "EL-EboMhx-DaBLiAS_Vm3qtJOubb2rkcS3zLU_r7UXtl",
isPending: false,
});
});


test("should call signify.rotateIdentifier with correct params", async () => {
Agent.agent.getKeriaOnlineStatus = jest.fn().mockReturnValueOnce(true);
Expand Down
55 changes: 33 additions & 22 deletions src/core/agent/services/identifierService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ class IdentifierService extends AgentService {
"Identifier name has already been used on KERIA";
static readonly IDENTIFIER_IS_PENDING =
"Cannot fetch identifier details as the identifier is still pending";
static readonly NO_WITNESSES_AVAILABLE = "No discoverable witnesses available on connected KERIA instance";
static readonly MISCONFIGURED_AGENT_CONFIGURATION = "Misconfigured KERIA agent for this wallet type";
static readonly NO_WITNESSES_AVAILABLE =
"No discoverable witnesses available on connected KERIA instance";
static readonly MISCONFIGURED_AGENT_CONFIGURATION =
"Misconfigured KERIA agent for this wallet type";

protected readonly identifierStorage: IdentifierStorage;
protected readonly operationPendingStorage: OperationPendingStorage;
Expand Down Expand Up @@ -165,11 +167,13 @@ class IdentifierService extends AgentService {

// @TODO - foconnor: Follow up ticket to pick a sane default for threshold. Right now max is too much.
// Must also enforce a minimum number of available witnesses.
const operation = await this.props.signifyClient.identifiers().create(name, {
toad: witnesses.length,
wits: witnesses,
});

const operation = await this.props.signifyClient
.identifiers()
.create(name, {
toad: witnesses.length,
wits: witnesses,
});

let op = await operation.op().catch((error) => {
const err = error.message.split(" - ");
if (/400/gi.test(err[1]) && /already incepted/gi.test(err[2])) {
Expand Down Expand Up @@ -230,6 +234,11 @@ class IdentifierService extends AgentService {
pendingDeletion: false,
}
);
await this.props.signifyClient.identifiers().update(localMember.id, {
name: `XX-${randomSalt()}:${localMember.groupMetadata?.groupId}:${
localMember.displayName
}`,
});
await this.deleteGroupLinkedConnections(
localMember.groupMetadata!.groupId
);
Expand Down Expand Up @@ -345,7 +354,7 @@ class IdentifierService extends AgentService {
(identifier: IdentifierResult) =>
!storageIdentifiers.find((item) => identifier.prefix === item.id)
);

const [unSyncedDataWithGroup, unSyncedDataWithoutGroup] = [
unSyncedData.filter((item: HabState) => item.group !== undefined),
unSyncedData.filter((item: HabState) => item.group === undefined),
Expand All @@ -355,7 +364,7 @@ class IdentifierService extends AgentService {
if (identifier.name.startsWith("XX")) {
continue;
}

const op: Operation = await this.props.signifyClient
.operations()
.get(`witness.${identifier.prefix}`)
Expand All @@ -370,7 +379,7 @@ class IdentifierService extends AgentService {
});
const isPending = !op.done;

if(isPending){
if (isPending) {
const pendingOperation = await this.operationPendingStorage.save({
id: op.name,
recordType: OperationPendingRecordType.Witness,
Expand All @@ -385,7 +394,7 @@ class IdentifierService extends AgentService {
const theme = parseInt(name[0], 10);
const isMultiSig = name.length === 3;

if(isMultiSig){
if (isMultiSig) {
const groupId = identifier.name.split(":")[1];
const groupInitiator = groupId.split("-")[0] === "1";

Expand All @@ -396,9 +405,9 @@ class IdentifierService extends AgentService {
groupMetadata: {
groupId,
groupCreated: false,
groupInitiator
groupInitiator,
},
isPending
isPending,
});

continue;
Expand All @@ -421,10 +430,12 @@ class IdentifierService extends AgentService {
const groupId = identifier.group.mhab.name.split(":")[1];
const theme = parseInt(identifier.name.split(":")[0], 10);
const groupInitiator = groupId.split("-")[0] === "1";
const op = await this.props.signifyClient.operations().get(`group.${identifier.prefix}`)
const op = await this.props.signifyClient
.operations()
.get(`group.${identifier.prefix}`);
const isPending = !op.done;

if(isPending){
if (isPending) {
const pendingOperation = await this.operationPendingStorage.save({
id: op.name,
recordType: OperationPendingRecordType.Group,
Expand All @@ -439,17 +450,17 @@ class IdentifierService extends AgentService {
groupMetadata: {
groupId,
groupCreated: true,
groupInitiator
}
groupInitiator,
},
});

await this.identifierStorage.createIdentifierMetadataRecord({
id: identifier.prefix,
displayName: groupId,
theme,
multisigManageAid,
isPending
})
isPending,
});
}
}

Expand All @@ -472,12 +483,12 @@ class IdentifierService extends AgentService {
if (!config.iurls) {
throw new Error(IdentifierService.MISCONFIGURED_AGENT_CONFIGURATION);
}

const witnesses = [];
for (const oobi of config.iurls) {
const role = new URL(oobi).searchParams.get("role");
if (role === "witness") {
witnesses.push(oobi.split("/oobi/")[1].split("/")[0]); // EID - endpoint identifier
witnesses.push(oobi.split("/oobi/")[1].split("/")[0]); // EID - endpoint identifier
}
}

Expand Down

0 comments on commit 4a48787

Please sign in to comment.