diff --git a/src/core/__fixtures__/agent/ipexCommunicationFixtures.ts b/src/core/__fixtures__/agent/ipexCommunicationFixtures.ts index 5bfc20e0cb..8423102f27 100644 --- a/src/core/__fixtures__/agent/ipexCommunicationFixtures.ts +++ b/src/core/__fixtures__/agent/ipexCommunicationFixtures.ts @@ -516,7 +516,7 @@ const multisigParticipantsProps = { groupId: "group-id", groupInitiator: true, groupCreated: true, - userName: "IdentifierName2", + proposedUsername: "IdentifierName2", }, }, multisigMembers: { diff --git a/src/core/__fixtures__/agent/multiSigFixtures.ts b/src/core/__fixtures__/agent/multiSigFixtures.ts index 65baca2ea3..4da4bdc550 100644 --- a/src/core/__fixtures__/agent/multiSigFixtures.ts +++ b/src/core/__fixtures__/agent/multiSigFixtures.ts @@ -17,7 +17,7 @@ const memberMetadataRecordProps: IdentifierMetadataRecordProps = { groupId: "groupid", groupInitiator: true, groupCreated: false, - userName: "testUser", + proposedUsername: "testUser", }, }; @@ -119,7 +119,7 @@ const memberIdentifierRecord = { groupId: "08f22dee-8cb0-4d65-8600-a82bbc3f6fd7", groupInitiator: true, groupCreated: true, - userName: "testUser", + proposedUsername: "testUser", }, updatedAt: new Date("2024-06-28T03:55:04.260Z"), } as IdentifierMetadataRecordProps; diff --git a/src/core/agent/agent.types.ts b/src/core/agent/agent.types.ts index ccefb96587..efcad263bb 100644 --- a/src/core/agent/agent.types.ts +++ b/src/core/agent/agent.types.ts @@ -234,7 +234,7 @@ type OobiScan = | { type: OobiType.MULTI_SIG_INITIATOR; groupId: string; - connection: ConnectionShortDetails; + connection: MultisigConnectionDetails; }; interface AgentServicesProps { diff --git a/src/core/agent/records/identifierMetadataRecord.ts b/src/core/agent/records/identifierMetadataRecord.ts index f05e36b5b5..522497ab54 100644 --- a/src/core/agent/records/identifierMetadataRecord.ts +++ b/src/core/agent/records/identifierMetadataRecord.ts @@ -5,7 +5,7 @@ interface GroupMetadata { groupId: string; groupInitiator: boolean; groupCreated: boolean; - userName: string; + proposedUsername: string; } interface IdentifierMetadataRecordProps { @@ -17,6 +17,7 @@ interface IdentifierMetadataRecordProps { theme: number; groupMemberPre?: string; groupMetadata?: GroupMetadata; + groupUsername?: string; pendingDeletion?: boolean; sxlt?: string; tags?: Tags; @@ -30,6 +31,7 @@ class IdentifierMetadataRecord extends BaseRecord { pendingDeletion!: boolean; groupMemberPre?: string; groupMetadata?: GroupMetadata; + groupUsername?: string; sxlt?: string; static readonly type = "IdentifierMetadataRecord"; @@ -47,6 +49,7 @@ class IdentifierMetadataRecord extends BaseRecord { this.isDeleted = props.isDeleted ?? false; this.groupMetadata = props.groupMetadata; this.groupMemberPre = props.groupMemberPre; + this.groupUsername = props.groupUsername; this.pendingDeletion = props.pendingDeletion ?? false; this.sxlt = props.sxlt; this._tags = props.tags ?? {}; diff --git a/src/core/agent/records/identifierStorage.test.ts b/src/core/agent/records/identifierStorage.test.ts index 622bc95255..f3a18f5be0 100644 --- a/src/core/agent/records/identifierStorage.test.ts +++ b/src/core/agent/records/identifierStorage.test.ts @@ -91,6 +91,24 @@ describe("Identifier storage test", () => { expect(storageService.update).toBeCalled(); }); + test("Should update identifier groupUsername", async () => { + const identifierWithGroupUsername = new IdentifierMetadataRecord({ + ...identifierMetadataRecordProps, + groupUsername: "oldUsername", + }); + storageService.findById.mockResolvedValue(identifierWithGroupUsername); + + await identifierStorage.updateIdentifierMetadata( + identifierMetadataRecord.id, + { + groupUsername: "newUsername", + } + ); + + expect(identifierWithGroupUsername.groupUsername).toBe("newUsername"); + expect(storageService.update).toBeCalledWith(identifierWithGroupUsername); + }); + test("Should get all identifier pending deletion", async () => { storageService.findAllByQuery.mockResolvedValue([ { diff --git a/src/core/agent/records/identifierStorage.ts b/src/core/agent/records/identifierStorage.ts index 9c0451e020..531bce8025 100644 --- a/src/core/agent/records/identifierStorage.ts +++ b/src/core/agent/records/identifierStorage.ts @@ -70,6 +70,7 @@ class IdentifierStorage { | "creationStatus" | "isDeleted" | "groupMetadata" + | "groupUsername" | "pendingDeletion" > > @@ -85,6 +86,8 @@ class IdentifierStorage { identifierMetadataRecord.isDeleted = metadata.isDeleted; if (metadata.groupMetadata !== undefined) identifierMetadataRecord.groupMetadata = metadata.groupMetadata; + if (metadata.groupUsername !== undefined) + identifierMetadataRecord.groupUsername = metadata.groupUsername; if (metadata.pendingDeletion !== undefined) identifierMetadataRecord.pendingDeletion = metadata.pendingDeletion; await this.storageService.update(identifierMetadataRecord); diff --git a/src/core/agent/services/connectionService.ts b/src/core/agent/services/connectionService.ts index 25b9161a37..86543f1ad6 100644 --- a/src/core/agent/services/connectionService.ts +++ b/src/core/agent/services/connectionService.ts @@ -164,24 +164,23 @@ class ConnectionService extends AgentService { sharedIdentifier, }; - const connection: ConnectionShortDetails = { - id: connectionId, - createdAtUTC: connectionDate, - oobi: url, - status: ConnectionStatus.PENDING, - label: alias, - contactId: connectionId, - ...(groupId ? { groupId } : { identifier: sharedIdentifier ?? "" }), - }; - if (multiSigInvite) { const oobiResult = (await this.resolveOobi(url)) as { op: Operation & { response: State }; connection: Contact; alias: string; }; - connection.id = oobiResult.op.response.i; - connection.status = ConnectionStatus.CONFIRMED; + + const multisigConnection: MultisigConnectionDetails = { + id: oobiResult.op.response.i, + createdAtUTC: new Date(oobiResult.op.response.dt).toISOString(), + oobi: url, + status: ConnectionStatus.CONFIRMED, + label: alias, + contactId: oobiResult.op.response.i, + groupId, + }; + connectionMetadata.creationStatus = CreationStatus.COMPLETE; connectionMetadata.createdAtUTC = oobiResult.op.response.dt; connectionMetadata.status = ConnectionStatus.CONFIRMED; @@ -209,11 +208,21 @@ class ConnectionService extends AgentService { return { type: OobiType.MULTI_SIG_INITIATOR, groupId, - connection, + connection: multisigConnection, }; } } + const connection: ConnectionShortDetails = { + id: connectionId, + createdAtUTC: connectionDate, + oobi: url, + status: ConnectionStatus.PENDING, + label: alias, + contactId: connectionId, + ...(groupId ? { groupId } : { identifier: sharedIdentifier ?? "" }), + }; + await this.createConnectionMetadata(connectionId, connectionMetadata); if (!multiSigInvite) { diff --git a/src/core/agent/services/identifier.types.ts b/src/core/agent/services/identifier.types.ts index 7a5e9818ba..884485c9ac 100644 --- a/src/core/agent/services/identifier.types.ts +++ b/src/core/agent/services/identifier.types.ts @@ -10,7 +10,7 @@ interface GroupMetadata { groupId: string; groupInitiator: boolean; groupCreated: boolean; - userName: string; + proposedUsername: string; initiatorName?: string; } @@ -28,6 +28,7 @@ interface IdentifierShortDetails { creationStatus: CreationStatus; groupMetadata?: GroupMetadata; groupMemberPre?: string; + groupUsername?: string; } interface IdentifierDetails extends IdentifierShortDetails { diff --git a/src/core/agent/services/identifierService.test.ts b/src/core/agent/services/identifierService.test.ts index dbc55ebaae..5a2dc0b6e0 100644 --- a/src/core/agent/services/identifierService.test.ts +++ b/src/core/agent/services/identifierService.test.ts @@ -168,7 +168,7 @@ const groupMetadata = { groupId: "group-id", groupInitiator: true, groupCreated: false, - userName: "testUser", + proposedUsername: "testUser", }; const keriMetadataRecordProps = { @@ -178,6 +178,7 @@ const keriMetadataRecordProps = { theme: 0, creationStatus: CreationStatus.COMPLETE, groupMetadata, + groupUsername: "testUser", sxlt: "1AAHFlFbNZ29MWHve6gyXfaJr4q2xgCmNEadpkh7IPuP1weDcOEb-bv3CmOoXK3xIik85tc9AYlNxFn_sTMpcvlbog8k4T5rE35i", }; @@ -296,6 +297,8 @@ describe("Single sig service of agent", () => { theme: 0, creationStatus: CreationStatus.COMPLETE, groupMetadata, + groupMemberPre: undefined, + groupUsername: "testUser", }, ]); }); @@ -309,8 +312,21 @@ describe("Single sig service of agent", () => { displayName: "group", groupMemberPre: "ED4KeyyTKFj-72B008OTGgDCrFo6y7B2B73kfyzu5InX", groupMetadata: undefined, + groupUsername: "testUser", }), ]); + identifierStorage.getIdentifierMetadata = jest + .fn() + .mockImplementation(async (identifierId: string) => { + if (identifierId === "ED4KeyyTKFj-72B008OTGgDCrFo6y7B2B73kfyzu5InX") { + return new IdentifierMetadataRecord({ + ...keriMetadataRecordProps, + id: identifierId, + groupMetadata, + }); + } + return keriMetadataRecord; + }); expect(await identifierService.getIdentifiers(false)).toStrictEqual([ { id: keriMetadataRecord.id, @@ -319,6 +335,8 @@ describe("Single sig service of agent", () => { theme: 0, creationStatus: CreationStatus.COMPLETE, groupMetadata, + groupMemberPre: undefined, + groupUsername: "testUser", }, { id: "EIZ-n_hHHY5ERGTzvpXYBkB6_yBAM4RXcjQG3-JykFvT", @@ -328,8 +346,10 @@ describe("Single sig service of agent", () => { creationStatus: CreationStatus.COMPLETE, groupMemberPre: "ED4KeyyTKFj-72B008OTGgDCrFo6y7B2B73kfyzu5InX", groupMetadata: undefined, + groupUsername: "testUser", }, ]); + identifierStorage.getIdentifierMetadata = jest.fn(); }); test("can get all identifiers without error if there are none", async () => { @@ -397,6 +417,7 @@ describe("Single sig service of agent", () => { theme: 0, groupMetadata: keriMetadataRecord.groupMetadata, groupMemberPre: keriMetadataRecord.groupMemberPre, + groupUsername: "testUser", ...identifierStateKeria.state, creationStatus: CreationStatus.COMPLETE, members: undefined, @@ -420,6 +441,7 @@ describe("Single sig service of agent", () => { theme: 0, groupMetadata: keriMetadataRecord.groupMetadata, groupMemberPre: keriMetadataRecord.groupMemberPre, + groupUsername: "testUser", ...identifierStateKeria.state, creationStatus: CreationStatus.COMPLETE, members: [ @@ -598,7 +620,7 @@ describe("Single sig service of agent", () => { groupCreated: false, groupInitiator: true, groupId: "DCF6b0c5aVm_26_sCTgLB4An6oUxEM5pVDDLqxxXDxHd", - userName: "testUser", + proposedUsername: "testUser", }, }); @@ -641,7 +663,7 @@ describe("Single sig service of agent", () => { groupCreated: false, groupInitiator: true, groupId: "DCF6b0c5aVm_26_sCTgLB4An6oUxEM5pVDDLqxxXDxHd", - userName: "testUser", + proposedUsername: "testUser", }, }, }, @@ -703,7 +725,7 @@ describe("Single sig service of agent", () => { groupCreated: false, groupInitiator: false, groupId: "DCF6b0c5aVm_26_sCTgLB4An6oUxEM5pVDDLqxxXDxHd", - userName: "testUser", + proposedUsername: "testUser", }, }); @@ -746,7 +768,7 @@ describe("Single sig service of agent", () => { groupCreated: false, groupInitiator: false, groupId: "DCF6b0c5aVm_26_sCTgLB4An6oUxEM5pVDDLqxxXDxHd", - userName: "testUser", + proposedUsername: "testUser", }, }, }, @@ -1276,7 +1298,7 @@ describe("Single sig service of agent", () => { groupId: "test-group-123", groupInitiator: false, groupCreated: true, - userName: "testuser", + proposedUsername: "testuser", }, }; @@ -1299,7 +1321,7 @@ describe("Single sig service of agent", () => { }); expect(updateIdentifierMock).toBeCalledWith("member-identifier-id", { - name: `1.2.0.2:${newTheme}:0:${memberMetadata.groupMetadata.groupId}:${memberMetadata.groupMetadata.userName}:${newDisplayName}`, + name: `1.2.0.2:${newTheme}:0:${memberMetadata.groupMetadata.groupId}:${memberMetadata.groupMetadata.proposedUsername}:${newDisplayName}`, }); expect(identifierStorage.updateIdentifierMetadata).toBeCalledWith( @@ -1326,7 +1348,7 @@ describe("Single sig service of agent", () => { groupId: "test-group-123", groupInitiator: true, groupCreated: true, - userName: "testuser", + proposedUsername: "testuser", }; identifierStorage.getIdentifierMetadata = jest.fn().mockResolvedValue({ @@ -1340,7 +1362,7 @@ describe("Single sig service of agent", () => { theme: newTheme, }); expect(updateIdentifierMock).toBeCalledWith(keriMetadataRecord.id, { - name: `1.2.0.2:${newTheme}:1:${groupMetadata.groupId}:${groupMetadata.userName}:${newDisplayName}`, + name: `1.2.0.2:${newTheme}:1:${groupMetadata.groupId}:${groupMetadata.proposedUsername}:${newDisplayName}`, }); expect(identifierStorage.updateIdentifierMetadata).toBeCalledWith( keriMetadataRecord.id, @@ -1386,7 +1408,7 @@ describe("Single sig service of agent", () => { groupId: "test-group-123", groupInitiator: true, groupCreated: true, - userName: "oldusername", + proposedUsername: "oldusername", }; const memberMetadata = { ...keriMetadataRecord, @@ -1421,17 +1443,15 @@ describe("Single sig service of agent", () => { { groupMetadata: { ...memberMetadata.groupMetadata, - userName: newUsername, + proposedUsername: newUsername, }, } ); expect(identifierStorage.updateIdentifierMetadata).toBeCalledWith( keriMetadataRecord.id, { - groupMetadata: { - ...groupMetadata, - userName: newUsername, - }, + groupUsername: newUsername, + groupMetadata: undefined, } ); }); @@ -1442,7 +1462,7 @@ describe("Single sig service of agent", () => { groupId: "test-group-123", groupInitiator: true, groupCreated: false, - userName: "oldusername", + proposedUsername: "oldusername", }; identifierStorage.getIdentifierMetadata = jest.fn().mockResolvedValue({ @@ -1466,7 +1486,7 @@ describe("Single sig service of agent", () => { { groupMetadata: { ...groupMetadata, - userName: newUsername, + proposedUsername: newUsername, }, } ); @@ -1485,7 +1505,7 @@ describe("Single sig service of agent", () => { "newusername" ) ).rejects.toThrow( - `${IdentifierService.INVALID_GROUP_IDENTIFIER}: ${keriMetadataRecord.groupMemberPre}` + `${IdentifierService.INVALID_GROUP_IDENTIFIER}: ${keriMetadataRecord.id}` ); }); @@ -1494,7 +1514,7 @@ describe("Single sig service of agent", () => { groupId: "test-group-123", groupInitiator: true, groupCreated: true, - userName: "oldusername", + proposedUsername: "oldusername", }; const memberMetadataWithoutGroup = { ...keriMetadataRecord, @@ -1738,7 +1758,7 @@ describe("Single sig service of agent", () => { groupId: "group1", groupCreated: false, groupInitiator: true, - userName: "user1", + proposedUsername: "user1", }, creationStatus: CreationStatus.COMPLETE, createdAt: new Date("2024-12-10T07:28:18.217384+00:00"), @@ -1766,7 +1786,7 @@ describe("Single sig service of agent", () => { groupId: "group3", groupCreated: false, groupInitiator: false, - userName: "user3", + proposedUsername: "user3", }, creationStatus: CreationStatus.COMPLETE, createdAt: new Date("2024-12-10T07:28:18.217384+00:00"), @@ -1780,7 +1800,7 @@ describe("Single sig service of agent", () => { groupId: "group1", groupCreated: true, groupInitiator: true, - userName: "user1", + proposedUsername: "user1", }, } ); @@ -1802,7 +1822,7 @@ describe("Single sig service of agent", () => { groupId: "group3", groupCreated: true, groupInitiator: false, - userName: "user3", + proposedUsername: "user3", }, } ); @@ -1926,7 +1946,7 @@ describe("Single sig service of agent", () => { groupId: "group1", groupCreated: true, groupInitiator: true, - userName: "user1", + proposedUsername: "user1", }, } ); @@ -2022,7 +2042,7 @@ describe("Single sig service of agent", () => { groupCreated: false, groupId: "group1", groupInitiator: true, - userName: "user1", + proposedUsername: "user1", }, id: "EL-EboMhx-DaBLiAS_Vm3qtJOubb2rkcS3zLU_r7UXtl", isDeleted: false, @@ -2047,7 +2067,7 @@ describe("Single sig service of agent", () => { groupId: "group1", groupCreated: true, groupInitiator: true, - userName: "user1", + proposedUsername: "user1", }, } ); @@ -2167,7 +2187,7 @@ describe("Single sig service of agent", () => { groupId: "group1", groupCreated: false, groupInitiator: true, - userName: "user1", + proposedUsername: "user1", }, creationStatus: CreationStatus.FAILED, createdAt: new Date("2024-12-10T07:28:18.217384+00:00"), @@ -2192,7 +2212,7 @@ describe("Single sig service of agent", () => { groupId: "group1", groupCreated: true, groupInitiator: true, - userName: "user1", + proposedUsername: "user1", }, } ); @@ -2369,7 +2389,7 @@ describe("Single sig service of agent", () => { groupCreated: false, groupId: "ED4KeyyTKFj72B008OTGgDCrFo6y7B2B73kfyzu5Inx", groupInitiator: true, - userName: "memberOne", + proposedUsername: "memberOne", }, }, true @@ -2382,7 +2402,7 @@ describe("Single sig service of agent", () => { groupCreated: false, groupId: "ED4KeyyTKFj", groupInitiator: true, - userName: "memberOne", + proposedUsername: "memberOne", }, }, true @@ -2395,7 +2415,7 @@ describe("Single sig service of agent", () => { groupCreated: false, groupId: "ED4KeyyTKFj", groupInitiator: false, - userName: "memberTwo", + proposedUsername: "memberTwo", }, }, true diff --git a/src/core/agent/services/identifierService.ts b/src/core/agent/services/identifierService.ts index ed46c210fb..754b3d80d5 100644 --- a/src/core/agent/services/identifierService.ts +++ b/src/core/agent/services/identifierService.ts @@ -117,20 +117,21 @@ class IdentifierService extends AgentService { ? await this.identifierStorage.getUserFacingIdentifierRecords() : await this.identifierStorage.getIdentifierRecords(); - for (let i = 0; i < records.length; i++) { - const metadata = records[i]; - const identifier: IdentifierShortDetails = { + for (const metadata of records) { + const groupMetadata = metadata.groupMemberPre + ? undefined + : metadata.groupMetadata; + + identifiers.push({ displayName: metadata.displayName, id: metadata.id, createdAtUTC: metadata.createdAt.toISOString(), theme: metadata.theme, creationStatus: metadata.creationStatus ?? false, - groupMetadata: metadata.groupMetadata, - }; - if (metadata.groupMemberPre) { - identifier.groupMemberPre = metadata.groupMemberPre; - } - identifiers.push(identifier); + groupMetadata, + groupMemberPre: metadata.groupMemberPre, + groupUsername: metadata.groupUsername, + }); } return identifiers; } @@ -168,6 +169,10 @@ class IdentifierService extends AgentService { ).signing.map((member: { aid: string }) => member.aid); } + const groupMetadata = metadata.groupMemberPre + ? undefined + : metadata.groupMetadata; + return { id: hab.prefix, displayName: metadata.displayName, @@ -175,7 +180,8 @@ class IdentifierService extends AgentService { theme: metadata.theme, groupMemberPre: metadata.groupMemberPre, creationStatus: metadata.creationStatus, - groupMetadata: metadata.groupMetadata, + groupMetadata, + groupUsername: metadata.groupUsername, s: hab.state.s, dt: hab.state.dt, kt: hab.state.kt, @@ -212,7 +218,7 @@ class IdentifierService extends AgentService { groupId: parsed.groupMetadata.groupId, groupCreated: false, groupInitiator: parsed.groupMetadata.groupInitiator, - userName: parsed.groupMetadata.userName, + proposedUsername: parsed.groupMetadata.proposedUsername, }, }; } else { @@ -243,8 +249,8 @@ class IdentifierService extends AgentService { let name: string; if (metadata.groupMetadata) { const initiatorFlag = metadata.groupMetadata.groupInitiator ? "1" : "0"; - const userNamePart = metadata.groupMetadata.userName; - name = `${LATEST_IDENTIFIER_VERSION}:${metadata.theme}:${initiatorFlag}:${metadata.groupMetadata.groupId}:${userNamePart}:${metadata.displayName}`; + const proposedUsernamePart = metadata.groupMetadata.proposedUsername; + name = `${LATEST_IDENTIFIER_VERSION}:${metadata.theme}:${initiatorFlag}:${metadata.groupMetadata.groupId}:${proposedUsernamePart}:${metadata.displayName}`; } else { name = `${LATEST_IDENTIFIER_VERSION}:${metadata.theme}:${metadata.displayName}`; } @@ -537,7 +543,7 @@ class IdentifierService extends AgentService { const initiatorFlag = memberMetadata.groupMetadata.groupInitiator ? "1" : "0"; - const memberName = `${LATEST_IDENTIFIER_VERSION}:${data.theme}:${initiatorFlag}:${memberMetadata.groupMetadata.groupId}:${memberMetadata.groupMetadata.userName}:${data.displayName}`; + const memberName = `${LATEST_IDENTIFIER_VERSION}:${data.theme}:${initiatorFlag}:${memberMetadata.groupMetadata.groupId}:${memberMetadata.groupMetadata.proposedUsername}:${data.displayName}`; await this.props.signifyClient .identifiers() @@ -555,7 +561,7 @@ class IdentifierService extends AgentService { const initiatorFlag = identifierMetadata.groupMetadata.groupInitiator ? "1" : "0"; - name = `${LATEST_IDENTIFIER_VERSION}:${data.theme}:${initiatorFlag}:${identifierMetadata.groupMetadata.groupId}:${identifierMetadata.groupMetadata.userName}:${data.displayName}`; + name = `${LATEST_IDENTIFIER_VERSION}:${data.theme}:${initiatorFlag}:${identifierMetadata.groupMetadata.groupId}:${identifierMetadata.groupMetadata.proposedUsername}:${data.displayName}`; } else { name = `${LATEST_IDENTIFIER_VERSION}:${data.theme}:${data.displayName}`; } @@ -577,12 +583,6 @@ class IdentifierService extends AgentService { const identifierMetadata = await this.identifierStorage.getIdentifierMetadata(identifier); - if (!identifierMetadata.groupMetadata) { - throw new Error( - `${IdentifierService.INVALID_GROUP_IDENTIFIER}: ${identifierMetadata.groupMemberPre}` - ); - } - if (identifierMetadata.groupMemberPre) { const memberMetadata = await this.identifierStorage.getIdentifierMetadata( identifierMetadata.groupMemberPre @@ -605,19 +605,16 @@ class IdentifierService extends AgentService { const memberGroupMetadata: GroupMetadata = { ...memberMetadata.groupMetadata, - userName: username, + proposedUsername: username, }; await this.identifierStorage.updateIdentifierMetadata( identifierMetadata.groupMemberPre, { groupMetadata: memberGroupMetadata } ); - const groupMetadata: GroupMetadata = { - ...identifierMetadata.groupMetadata, - userName: username, - }; return this.identifierStorage.updateIdentifierMetadata(identifier, { - groupMetadata, + groupUsername: username, + groupMetadata: undefined, }); } @@ -639,7 +636,7 @@ class IdentifierService extends AgentService { const groupMetadata: GroupMetadata = { ...identifierMetadata.groupMetadata, - userName: username, + proposedUsername: username, }; return this.identifierStorage.updateIdentifierMetadata(identifier, { groupMetadata, diff --git a/src/core/agent/services/ipexCommunicationService.test.ts b/src/core/agent/services/ipexCommunicationService.test.ts index 792af1a94f..e002607f26 100644 --- a/src/core/agent/services/ipexCommunicationService.test.ts +++ b/src/core/agent/services/ipexCommunicationService.test.ts @@ -593,7 +593,7 @@ describe("Receive group ACDC actions", () => { groupId: "group-id", groupInitiator: true, groupCreated: true, - userName: "", + proposedUsername: "", }, }, multisigMembers: { @@ -785,7 +785,7 @@ describe("Receive group ACDC actions", () => { groupId: "group-id", groupInitiator: true, groupCreated: true, - userName: "", + proposedUsername: "", }, }, multisigMembers: { @@ -936,7 +936,7 @@ describe("Receive group ACDC actions", () => { groupId: "group-id", groupInitiator: true, groupCreated: true, - userName: "", + proposedUsername: "", }, }, multisigMembers: { diff --git a/src/core/agent/services/keriaNotificationService.test.ts b/src/core/agent/services/keriaNotificationService.test.ts index eb31ec84ed..6707d5f6cc 100644 --- a/src/core/agent/services/keriaNotificationService.test.ts +++ b/src/core/agent/services/keriaNotificationService.test.ts @@ -165,7 +165,7 @@ const notificationStorage = jest.mocked({ findById: jest.fn(), findExpectedById: jest.fn().mockResolvedValue({ id: "test-notification", - a: { r: NotificationRoute.ExnIpexGrant } + a: { r: NotificationRoute.ExnIpexGrant }, }), findAllByQuery: jest.fn(), getAll: jest.fn(), @@ -477,13 +477,13 @@ describe("Signify notification service of agent", () => { notificationStorage.deleteById = jest.fn(); notificationStorage.findExpectedById = jest.fn().mockResolvedValue({ id: "uuid", - a: { r: NotificationRoute.ExnIpexGrant } + a: { r: NotificationRoute.ExnIpexGrant }, }); const mockOperationPendingStorage = { findAllByQuery: jest.fn(), deleteById: jest.fn(), } as any; - + await deleteNotificationRecordById( agentServicesProps.signifyClient, notificationStorage, @@ -503,13 +503,13 @@ describe("Signify notification service of agent", () => { notificationStorage.deleteById = jest.fn(); notificationStorage.findExpectedById = jest.fn().mockResolvedValue({ id: "uuid", - a: { r: NotificationRoute.LocalAcdcRevoked } + a: { r: NotificationRoute.LocalAcdcRevoked }, }); const mockOperationPendingStorage = { findAllByQuery: jest.fn(), deleteById: jest.fn(), } as any; - + await deleteNotificationRecordById( agentServicesProps.signifyClient, notificationStorage, @@ -2201,7 +2201,7 @@ describe("Group IPEX presentation", () => { groupId: "group-id", groupInitiator: true, groupCreated: true, - userName: "", + proposedUsername: "", }, }, multisigMembers: { @@ -3975,7 +3975,7 @@ describe("Long running operation tracker", () => { groupId: "group-id", groupInitiator: true, groupCreated: true, - userName: "", + proposedUsername: "", }, }, multisigMembers: { diff --git a/src/core/agent/services/multiSigService.test.ts b/src/core/agent/services/multiSigService.test.ts index daf8f04321..8c1a3fc0dd 100644 --- a/src/core/agent/services/multiSigService.test.ts +++ b/src/core/agent/services/multiSigService.test.ts @@ -508,12 +508,7 @@ describe("Creation of multi-sig", () => { createdAtUTC: "2024-08-10T07:23:54.839894+00:00", groupMemberPre: memberPrefix, theme: 0, - groupMetadata: { - groupId: "groupid", - groupInitiator: true, - groupCreated: true, - userName: "testUser", - }, + groupUsername: "testUser", }, }, }); @@ -573,7 +568,7 @@ describe("Creation of multi-sig", () => { groupId: "groupid", groupInitiator: false, groupCreated: false, - userName: "", + proposedUsername: "", }, }) ); @@ -702,12 +697,7 @@ describe("Creation of multi-sig", () => { createdAtUTC: "2024-08-10T07:23:54.839894+00:00", groupMemberPre: memberPrefix, theme: 0, - groupMetadata: { - groupId: "groupid", - groupInitiator: true, - groupCreated: true, - userName: "testUser", - }, + groupUsername: "testUser", }, }, }); @@ -830,12 +820,7 @@ describe("Creation of multi-sig", () => { createdAtUTC: "2024-08-10T07:23:54.839894+00:00", groupMemberPre: memberPrefix, theme: 0, - groupMetadata: { - groupId: "groupid", - groupInitiator: true, - groupCreated: true, - userName: "testUser", - }, + groupUsername: "testUser", }, }, }); @@ -1008,12 +993,7 @@ describe("Creation of multi-sig", () => { createdAtUTC: "2024-08-10T07:23:54.839894+00:00", groupMemberPre: memberMetadataRecord.id, theme: 0, - groupMetadata: { - groupId: "groupid", - groupInitiator: true, - groupCreated: true, - userName: "testUser", - }, + groupUsername: "testUser", }, }, }); @@ -1145,12 +1125,7 @@ describe("Creation of multi-sig", () => { createdAtUTC: "2024-08-10T07:23:54.839894+00:00", groupMemberPre: memberMetadataRecord.id, theme: 0, - groupMetadata: { - groupId: "groupid", - groupInitiator: true, - groupCreated: true, - userName: "testUser", - }, + groupUsername: "testUser", }, }, }); @@ -1261,12 +1236,7 @@ describe("Creation of multi-sig", () => { createdAtUTC: "2024-08-10T07:23:54.839894+00:00", groupMemberPre: memberMetadataRecord.id, theme: 0, - groupMetadata: { - groupId: "groupid", - groupInitiator: true, - groupCreated: true, - userName: "testUser", - }, + groupUsername: "testUser", }, }, }); @@ -1601,7 +1571,9 @@ describe("Creation of multi-sig", () => { theme: 0, groupMetadata: { groupId: "test-group-id", + groupInitiator: true, groupCreated: false, + proposedUsername: "testUser", }, }, ]), diff --git a/src/core/agent/services/multiSigService.ts b/src/core/agent/services/multiSigService.ts index a3ac6dd09d..28a3b7bc8d 100644 --- a/src/core/agent/services/multiSigService.ts +++ b/src/core/agent/services/multiSigService.ts @@ -192,14 +192,13 @@ class MultiSigService extends AgentService { .get(multisigId as string)) as HabState; try { - // @TODO: groupMetadata is only intended for the mHab - for now, it's copied to gHab so the UI has access to the group name. groupCreated is always kept as false in gHab so it does not disappear from the list of userFacing identifiers - this approach should be tidied up. await this.identifierStorage.createIdentifierMetadataRecord({ id: multisigId, displayName: mHabRecord.displayName, theme: mHabRecord.theme, creationStatus, groupMemberPre: memberPrefix, - groupMetadata: mHabRecord.groupMetadata, + groupUsername: mHabRecord.groupMetadata.proposedUsername, createdAt: new Date(multisigDetail.icp_dt), }); } catch (error) { @@ -230,7 +229,7 @@ class MultiSigService extends AgentService { creationStatus, groupMemberPre: memberPrefix, createdAtUTC: multisigDetail.icp_dt, - groupMetadata: mHabRecord.groupMetadata, + groupUsername: mHabRecord.groupMetadata.proposedUsername, }, }, }); @@ -594,7 +593,7 @@ class MultiSigService extends AgentService { theme: mHabRecord.theme, creationStatus, groupMemberPre: mHabRecord.id, - groupMetadata: mHabRecord.groupMetadata, + groupUsername: mHabRecord.groupMetadata.proposedUsername, createdAt: new Date(multisigDetail.icp_dt), }); } catch (error) { @@ -625,7 +624,7 @@ class MultiSigService extends AgentService { creationStatus, groupMemberPre: mHabRecord.id, createdAtUTC: multisigDetail.icp_dt, - groupMetadata: mHabRecord.groupMetadata, + groupUsername: mHabRecord.groupMetadata.proposedUsername, }, }, }); diff --git a/src/core/storage/sqliteStorage/migrations/v1.2.0.2-group-scoped-username.ts b/src/core/storage/sqliteStorage/migrations/v1.2.0.2-group-scoped-username.ts index 41d720e311..2393563fff 100644 --- a/src/core/storage/sqliteStorage/migrations/v1.2.0.2-group-scoped-username.ts +++ b/src/core/storage/sqliteStorage/migrations/v1.2.0.2-group-scoped-username.ts @@ -32,7 +32,7 @@ export const DATA_V1202: LocalMigration = { recordValue = { ...recordValue, - groupMetadata: { ...groupMetadata, userName: "" }, + groupMetadata: { ...groupMetadata, proposedUsername: "" }, }; statements.push({ diff --git a/src/core/utils/habName.test.ts b/src/core/utils/habName.test.ts index f98adfff8a..85e2830ba1 100644 --- a/src/core/utils/habName.test.ts +++ b/src/core/utils/habName.test.ts @@ -12,7 +12,7 @@ describe("habName", () => { groupMetadata: { groupInitiator: true, groupId: "groupId123", - userName: "", + proposedUsername: "", }, }, }, @@ -24,7 +24,7 @@ describe("habName", () => { groupMetadata: { groupInitiator: false, groupId: "groupId456", - userName: "", + proposedUsername: "", }, }, }, @@ -36,7 +36,7 @@ describe("habName", () => { groupMetadata: { groupInitiator: true, groupId: "gr@up!d", - userName: "", + proposedUsername: "", }, }, }, @@ -48,7 +48,7 @@ describe("habName", () => { groupMetadata: { groupInitiator: true, groupId: "group-with-hyphens", - userName: "", + proposedUsername: "", }, }, }, @@ -60,7 +60,7 @@ describe("habName", () => { groupMetadata: { groupInitiator: true, groupId: "group-id-extra", - userName: "", + proposedUsername: "", }, }, }, @@ -80,7 +80,7 @@ describe("habName", () => { groupMetadata: { groupInitiator: true, groupId: "groupId789", - userName: "user123", + proposedUsername: "user123", }, }, }, @@ -93,7 +93,7 @@ describe("habName", () => { groupMetadata: { groupInitiator: true, groupId: "gr@up!d", - userName: "us$er%name", + proposedUsername: "us$er%name", }, }, }, @@ -106,7 +106,7 @@ describe("habName", () => { groupMetadata: { groupInitiator: true, groupId: "group-with-hyphens", - userName: "user123", + proposedUsername: "user123", }, }, }, @@ -138,7 +138,7 @@ describe("habName", () => { { name: "1.2.0.2:XX:1:groupId789:user123", // Invalid number of parts for new format (5 parts) errorMessage: - "Invalid new format name: Expected 3 or 6 parts separated by colons (version:theme:displayName or version:theme:groupInitiator:groupId:userName:displayName).", + "Invalid new format name: Expected 3 or 6 parts separated by colons (version:theme:displayName or version:theme:groupInitiator:groupId:proposedUsername:displayName).", }, { name: "03:1-group-id:", // Missing display name for old format @@ -180,7 +180,7 @@ describe("habName", () => { groupMetadata: { groupId: "groupXYZ", groupInitiator: true, - userName: "formattedUser", + proposedUsername: "formattedUser", }, }, expected: "1.2.0.2:XX:1:groupXYZ:formattedUser:FormattedGroup", diff --git a/src/core/utils/habName.ts b/src/core/utils/habName.ts index 2fb091af22..e21cd94206 100644 --- a/src/core/utils/habName.ts +++ b/src/core/utils/habName.ts @@ -4,20 +4,20 @@ export interface HabNameParts { groupMetadata?: { groupInitiator: boolean; groupId: string; - userName: string; + proposedUsername: string; }; theme: string; } // Old format: theme:groupInitiator-groupId:displayName or theme:displayName -// New format: version:theme:groupInitiator:groupId:userName:displayName or version:theme:displayName +// New format: version:theme:groupInitiator:groupId:proposedUsername:displayName or version:theme:displayName export function parseHabName(name: string): HabNameParts { const parts = name.split(":"); if (name.startsWith("1.2.0.2:")) { if (parts.length !== 3 && parts.length !== 6) { throw new Error( - "Invalid new format name: Expected 3 or 6 parts separated by colons (version:theme:displayName or version:theme:groupInitiator:groupId:userName:displayName)." + "Invalid new format name: Expected 3 or 6 parts separated by colons (version:theme:displayName or version:theme:groupInitiator:groupId:proposedUsername:displayName)." ); } @@ -34,7 +34,7 @@ export function parseHabName(name: string): HabNameParts { const groupInitiatorStr = parts[2]; const groupId = parts[3]; - const userName = parts[4]; + const proposedUsername = parts[4]; const displayName = parts[5]; if (groupInitiatorStr !== "1" && groupInitiatorStr !== "0") { @@ -45,8 +45,10 @@ export function parseHabName(name: string): HabNameParts { if (!groupId || groupId.trim() === "") { throw new Error("Invalid new format name: groupId cannot be empty."); } - if (!userName) { - throw new Error("Invalid new format name: userName cannot be null."); + if (!proposedUsername) { + throw new Error( + "Invalid new format name: proposedUsername cannot be null." + ); } return { @@ -56,7 +58,7 @@ export function parseHabName(name: string): HabNameParts { groupMetadata: { groupInitiator: groupInitiatorStr === "1", groupId, - userName, + proposedUsername, }, }; } @@ -106,7 +108,7 @@ export function parseHabName(name: string): HabNameParts { groupMetadata: { groupInitiator: groupInitiatorStr === "1", groupId, - userName: "", + proposedUsername: "", }, }; } @@ -119,8 +121,8 @@ export function formatToV1_2_0_2(parts: HabNameParts): string { if (parts.groupMetadata) { const groupInitiatorStr = parts.groupMetadata.groupInitiator ? "1" : "0"; const groupIdPart = parts.groupMetadata.groupId || ""; - const userNamePart = parts.groupMetadata.userName || ""; - return `${version}:${themePart}:${groupInitiatorStr}:${groupIdPart}:${userNamePart}:${displayNamePart}`; + const proposedUsernamePart = parts.groupMetadata.proposedUsername || ""; + return `${version}:${themePart}:${groupInitiatorStr}:${groupIdPart}:${proposedUsernamePart}:${displayNamePart}`; } else { return `${version}:${themePart}:${displayNamePart}`; } diff --git a/src/store/reducers/profileCache/profilesCache.ts b/src/store/reducers/profileCache/profilesCache.ts index 5a1b46155e..076393d539 100644 --- a/src/store/reducers/profileCache/profilesCache.ts +++ b/src/store/reducers/profileCache/profilesCache.ts @@ -66,24 +66,30 @@ export const profilesCacheSlice = createSlice({ const existedProfile = state.profiles[action.payload.id]; if (existedProfile) { existedProfile.identity = action.payload; - } else { - const multisigConnections = - action.payload.groupMetadata?.groupId === state.multiSigGroup?.groupId - ? (state.multiSigGroup?.connections as MultisigConnectionDetails[]) - : []; - - state.profiles[action.payload.id] = { - identity: action.payload, - connections: [], - multisigConnections: multisigConnections || [], - peerConnections: [], - credentials: [], - archivedCredentials: [], - notifications: [], - }; - - state.multiSigGroup = undefined; + return; } + + const groupId = action.payload.groupMetadata?.groupId; + const cachedConnections: MultisigConnectionDetails[] = + groupId && state.multiSigGroup?.groupId === groupId + ? state.multiSigGroup.connections.map((connection) => ({ + ...connection, + contactId: connection.contactId || connection.id, + groupId, + })) + : []; + + state.profiles[action.payload.id] = { + identity: action.payload, + connections: [], + multisigConnections: cachedConnections, + peerConnections: [], + credentials: [], + archivedCredentials: [], + notifications: [], + }; + + state.multiSigGroup = undefined; }, addGroupProfile: (state, action: PayloadAction) => { if (!action.payload.groupMemberPre) { diff --git a/src/store/reducers/profileCache/profilesCache.types.ts b/src/store/reducers/profileCache/profilesCache.types.ts index ec425a9826..4ac4b0a94b 100644 --- a/src/store/reducers/profileCache/profilesCache.types.ts +++ b/src/store/reducers/profileCache/profilesCache.types.ts @@ -1,5 +1,4 @@ import { - ConnectionShortDetails, MultisigConnectionDetails, RegularConnectionDetails, } from "../../../core/agent/agent.types"; @@ -9,7 +8,7 @@ import { KeriaNotification } from "../../../core/agent/services/keriaNotificatio interface MultiSigGroup { groupId: string; - connections: ConnectionShortDetails[]; + connections: MultisigConnectionDetails[]; } interface DAppConnection { diff --git a/src/store/reducers/stateCache/stateCache.types.ts b/src/store/reducers/stateCache/stateCache.types.ts index fa51c6a1d8..14f4a59746 100644 --- a/src/store/reducers/stateCache/stateCache.types.ts +++ b/src/store/reducers/stateCache/stateCache.types.ts @@ -3,7 +3,7 @@ import { LoginAttempts } from "../../../core/agent/services/auth.types"; import { PeerConnectSigningEvent } from "../../../core/cardano/walletConnect/peerConnection.types"; import { OperationType, ToastMsgType } from "../../../ui/globals/types"; import { DAppConnection } from "../profileCache"; -import { ConnectionShortDetails } from "../../../core/agent/agent.types"; +import { MultisigConnectionDetails } from "../../../core/agent/agent.types"; interface PayloadData { [key: string]: T; @@ -57,7 +57,7 @@ interface PendingJoinGroupMetadata { groupId: string; groupName: string; initiatorName: string | null; - connection: ConnectionShortDetails; + connection: MultisigConnectionDetails; } interface StateCacheProps { diff --git a/src/store/reducers/stateCache/utils.ts b/src/store/reducers/stateCache/utils.ts index 6360ed8c1e..2b83ffb485 100644 --- a/src/store/reducers/stateCache/utils.ts +++ b/src/store/reducers/stateCache/utils.ts @@ -28,9 +28,13 @@ const filterProfileData = ( const profileConnections = allConnections.filter( (conn) => conn.identifier === profileId ); + + const groupIdToFilter = profile.groupMemberPre + ? identifiers[profile.groupMemberPre]?.groupMetadata?.groupId + : profile.groupMetadata?.groupId; + const profileMultisigConnections = allMultisigConnections.filter( - (conn) => - "groupId" in conn && conn.groupId === profile.groupMetadata?.groupId + (conn) => "groupId" in conn && conn.groupId === groupIdToFilter ); const profilePeerConnections = allPeerConnections.filter( (conn) => conn.selectedAid === profileId diff --git a/src/ui/__fixtures__/filteredIdentifierFix.ts b/src/ui/__fixtures__/filteredIdentifierFix.ts index 4f18c7096e..e3dbcbae6b 100644 --- a/src/ui/__fixtures__/filteredIdentifierFix.ts +++ b/src/ui/__fixtures__/filteredIdentifierFix.ts @@ -12,7 +12,7 @@ const failedMultisignIdentifierFix: IdentifierShortDetails[] = [ groupId: "549eb79f-856c-4bb7-8dd5-d5eed865906a", groupCreated: false, groupInitiator: false, - userName: "test", + proposedUsername: "test", }, }, ]; @@ -28,7 +28,7 @@ const multisignIdentifierFix: IdentifierShortDetails[] = [ groupId: "549eb79f-856c-4bb7-8dd5-d5eed865906a", groupCreated: false, groupInitiator: true, - userName: "test", + proposedUsername: "test", }, }, ]; @@ -44,7 +44,7 @@ const pendingMemberIdentifierFix: IdentifierShortDetails[] = [ groupId: "549eb79f-856c-4bb7-8dd5-d5eed865906a", groupCreated: false, groupInitiator: false, - userName: "test", + proposedUsername: "test", }, }, ]; @@ -56,12 +56,7 @@ const pendingGroupIdentifierFix: IdentifierShortDetails = { theme: 0, creationStatus: CreationStatus.PENDING, groupMemberPre: "ED4KeyyTKFj-72B008OTGgDCrFo6y7B2B73kfyzu5Inb", - groupMetadata: { - groupId: "549eb79f-856c-4bb7-8dd5-d5eed865906a", - groupCreated: false, - groupInitiator: false, - userName: "test", - }, + groupUsername: "test", }; const filteredIdentifierFix: IdentifierShortDetails[] = [ @@ -93,6 +88,7 @@ const filteredIdentifierFix: IdentifierShortDetails[] = [ theme: 0, creationStatus: CreationStatus.COMPLETE, groupMemberPre: "EHzi_GBx0jIgd3G0Qqcjg3ZaLJ6d84wp6q0qUvC_iOQ4", + groupUsername: "GID 1", }, { displayName: "Profess", diff --git a/src/ui/components/AppWrapper/AppWrapper.test.tsx b/src/ui/components/AppWrapper/AppWrapper.test.tsx index 6ecae12cad..d36459f246 100644 --- a/src/ui/components/AppWrapper/AppWrapper.test.tsx +++ b/src/ui/components/AppWrapper/AppWrapper.test.tsx @@ -50,6 +50,7 @@ import { IncomingRequestType } from "../../../store/reducers/stateCache/stateCac import { pendingGroupIdentifierFix, pendingIdentifierFix, + pendingMemberIdentifierFix, } from "../../__fixtures__/filteredIdentifierFix"; import { ToastMsgType } from "../../globals/types"; import { @@ -97,6 +98,7 @@ jest.mock("../../../core/agent/agent", () => { }, identifiers: { getIdentifiers: jest.fn().mockResolvedValue([]), + getIdentifier: jest.fn().mockResolvedValue(null), syncKeriaIdentifiers: jest.fn(), onIdentifierAdded: jest.fn(), getAvailableWitnesses: jest.fn(), @@ -515,14 +517,25 @@ describe("Group state changed handler", () => { const innerDispatch = jest.fn(); const getState = jest.fn(() => ({ profilesCache: { recentProfiles: [] } })); - dispatch.mockImplementation((func) => { - func(innerDispatch, getState); + dispatch.mockImplementation((action) => { + if (typeof action === "function") { + action(innerDispatch, getState); + } else { + innerDispatch(action); + } }); + Agent.agent.identifiers.getIdentifier = jest.fn(); + Agent.agent.connections.getMultisigConnections = jest.fn(); + await groupCreatedHandler(groupCreatedEvent, dispatch); + expect(innerDispatch).toBeCalledWith( addGroupProfile(pendingGroupIdentifierFix) ); + + expect(Agent.agent.connections.getMultisigConnections).not.toBeCalled(); + expect(Agent.agent.identifiers.getIdentifier).not.toBeCalled(); }); }); diff --git a/src/ui/components/AppWrapper/AppWrapper.tsx b/src/ui/components/AppWrapper/AppWrapper.tsx index dec292f5d2..f5fd726389 100644 --- a/src/ui/components/AppWrapper/AppWrapper.tsx +++ b/src/ui/components/AppWrapper/AppWrapper.tsx @@ -374,6 +374,8 @@ const AppWrapper = (props: { children: ReactNode }) => { true ); const storedIdentifiers = await Agent.agent.identifiers.getIdentifiers(); + const allIdentifiersIncludingMember = + await Agent.agent.identifiers.getIdentifiers(false); const storedPeerConnections = await Agent.agent.peerConnectionPair.getAllPeerConnectionAccount(); @@ -397,7 +399,7 @@ const AppWrapper = (props: { children: ReactNode }) => { dispatch(updateRecentProfiles(profileHistories)); } - const identifiersDict = storedIdentifiers.reduce( + const identifiersDict = allIdentifiersIncludingMember.reduce( (acc: Record, identifier) => { acc[identifier.id] = identifier; return acc; diff --git a/src/ui/components/AppWrapper/coreEventListeners.ts b/src/ui/components/AppWrapper/coreEventListeners.ts index 0c4d441c16..0430594f8d 100644 --- a/src/ui/components/AppWrapper/coreEventListeners.ts +++ b/src/ui/components/AppWrapper/coreEventListeners.ts @@ -97,7 +97,7 @@ const groupCreatedHandler = async ( event: GroupCreatedEvent, dispatch: ReturnType ) => { - dispatch(addGroupProfileAsync(event.payload.group)); + await dispatch(addGroupProfileAsync(event.payload.group)); }; export { diff --git a/src/ui/components/EditProfile/EditProfile.tsx b/src/ui/components/EditProfile/EditProfile.tsx index 12a9b8caed..fc8accc4e6 100644 --- a/src/ui/components/EditProfile/EditProfile.tsx +++ b/src/ui/components/EditProfile/EditProfile.tsx @@ -41,10 +41,13 @@ const EditProfile = ({ const currentIdentifier = profiles[cardData.id]; const [isLoading, setLoading] = useState(false); + const getCurrentUsername = () => + cardData.groupMemberPre + ? cardData.groupUsername || "" + : cardData.groupMetadata?.proposedUsername || ""; + const [newDisplayName, setNewDisplayName] = useState( - editType === "userName" - ? cardData.groupMetadata?.userName || "" - : cardData.displayName + editType === "userName" ? getCurrentUsername() : cardData.displayName ); const [keyboardIsOpen, setKeyboardIsOpen] = useState(false); @@ -73,18 +76,25 @@ const EditProfile = ({ setModalIsOpen(false); }; + const baselineValue = + editType === "userName" ? getCurrentUsername() : cardData.displayName; + const verifyDisplayName = newDisplayName.length > 0 && newDisplayName.length <= DISPLAY_NAME_LENGTH && - newDisplayName.trim() !== cardData.displayName.trim(); + newDisplayName.trim() !== baselineValue.trim(); useEffect(() => { setNewDisplayName( - editType === "userName" - ? cardData.groupMetadata?.userName || "" - : cardData.displayName + editType === "userName" ? getCurrentUsername() : cardData.displayName ); - }, [editType, cardData.displayName, cardData.groupMetadata?.userName]); + }, [ + editType, + cardData.displayName, + cardData.groupMetadata?.proposedUsername, + cardData.groupUsername, + cardData.groupMemberPre, + ]); const handleSubmit = async () => { try { @@ -103,44 +113,46 @@ const EditProfile = ({ throw new Error(`${IDENTIFIER_NOT_EXIST} ${cardData.id}`); } - const params: Pick< - IdentifierMetadataRecordProps, - "theme" | "displayName" | "groupMetadata" - > = { - displayName: cardData.displayName, - theme: currentIdentifier.identity.theme, - }; - if (editType === "name") { - params.displayName = newDisplayName; - params.groupMetadata = cardData.groupMetadata; + const params: Pick< + IdentifierMetadataRecordProps, + "theme" | "displayName" + > = { + displayName: newDisplayName, + theme: currentIdentifier.identity.theme, + }; await Agent.agent.identifiers.updateIdentifier(cardData.id, params); - } else if (isGroup && cardData.groupMetadata) { - params.groupMetadata = { - ...cardData.groupMetadata, - userName: newDisplayName, + + const updatedIdentifier: IdentifierShortDetails = { + ...currentIdentifier.identity, + displayName: params.displayName, }; + setCardData({ + ...cardData, + displayName: params.displayName, + }); + dispatch(addOrUpdateProfileIdentity(updatedIdentifier)); + } else if (editType === "userName") { + // UI only allows editing username for fully created groups (with members) await Agent.agent.identifiers.updateGroupUsername( cardData.id, newDisplayName ); - } - const updatedIdentifier: IdentifierShortDetails = { - ...currentIdentifier.identity, - displayName: params.displayName, - groupMetadata: params.groupMetadata, - }; + const updatedIdentifier: IdentifierShortDetails = { + ...currentIdentifier.identity, + groupUsername: newDisplayName, + }; - setCardData({ - ...cardData, - displayName: params.displayName, - groupMetadata: params.groupMetadata, - }); + setCardData({ + ...cardData, + groupUsername: newDisplayName, + }); + dispatch(addOrUpdateProfileIdentity(updatedIdentifier)); + } handleCancel(); - dispatch(addOrUpdateProfileIdentity(updatedIdentifier)); dispatch( setToastMsg( isGroup diff --git a/src/ui/components/IdentifierSelectorModal/IdentifierSelectorModal.tsx b/src/ui/components/IdentifierSelectorModal/IdentifierSelectorModal.tsx index e2e3b2ef1c..9186c3d6f8 100644 --- a/src/ui/components/IdentifierSelectorModal/IdentifierSelectorModal.tsx +++ b/src/ui/components/IdentifierSelectorModal/IdentifierSelectorModal.tsx @@ -27,11 +27,11 @@ const IdentifierSelectorModal = ({ const result = identifiers ? identifiers : Object.values(profiles) - .filter( - (item) => item.identity.creationStatus === CreationStatus.COMPLETE - ) - .filter((item) => !item.identity.groupMetadata?.groupId) - .map((item) => item.identity); + .filter( + (item) => item.identity.creationStatus === CreationStatus.COMPLETE + ) + .filter((item) => !item.identity.groupMetadata?.groupId) + .map((item) => item.identity); return result.map( (identifier): CardItem => ({ diff --git a/src/ui/components/ProfileDetailsModal/components/IdentifierAttributeDetailModal/IdentifierAttributeDetailModal.tsx b/src/ui/components/ProfileDetailsModal/components/IdentifierAttributeDetailModal/IdentifierAttributeDetailModal.tsx index 88adf3eeb2..a3a8701f70 100644 --- a/src/ui/components/ProfileDetailsModal/components/IdentifierAttributeDetailModal/IdentifierAttributeDetailModal.tsx +++ b/src/ui/components/ProfileDetailsModal/components/IdentifierAttributeDetailModal/IdentifierAttributeDetailModal.tsx @@ -40,18 +40,19 @@ const IdentifierAttributeDetailModal = ({ const memberConnection = multisignConnectionsCache.find( (c) => c.id === member ); - let name = memberConnection?.label || member; + const isCurrent = member === data.groupMemberPre; + const displayNameCandidate = isCurrent + ? data.groupUsername || data.groupMetadata?.proposedUsername || "" + : member; - if (!memberConnection?.label) { - currentUserIndex = index; - name = data.groupMetadata?.userName || ""; - } + const name = memberConnection?.label || displayNameCandidate; + if (isCurrent) currentUserIndex = index; const rank = index >= 0 ? index % 5 : 0; return { - name: name, - isCurrentUser: !memberConnection?.label, + name, + isCurrentUser: isCurrent, avatar: ( c.id === member ); - let name = memberConnection?.label || member; - - if (!memberConnection?.label) { - name = cardData.groupMetadata?.userName || ""; - } + const isCurrent = member === cardData.groupMemberPre; + const name = + memberConnection?.label || + (isCurrent + ? cardData.groupUsername || + cardData.groupMetadata?.proposedUsername || + "" + : member); const rank = index >= 0 ? index % 5 : 0; @@ -109,7 +112,7 @@ const ProfileContent = ({ rank={rank} /> ), - isCurrentUser: !memberConnection?.label, + isCurrentUser: isCurrent, status: MemberAcceptStatus.None, }; }) diff --git a/src/ui/components/ProfileStateModal/ProfileStateModal.tsx b/src/ui/components/ProfileStateModal/ProfileStateModal.tsx index eea0188d79..cb3a546840 100644 --- a/src/ui/components/ProfileStateModal/ProfileStateModal.tsx +++ b/src/ui/components/ProfileStateModal/ProfileStateModal.tsx @@ -135,6 +135,12 @@ const ProfileStateModal = () => { return; } + if (creationStatus === CreationStatus.PENDING && groupMemberPre) { + setIsOpen(true); + setHiddenContent(false); + return; + } + getDetails(); }, [ currentProfile?.identity.id, diff --git a/src/ui/components/Settings/components/ManagePassword/ManagePassword.test.tsx b/src/ui/components/Settings/components/ManagePassword/ManagePassword.test.tsx index cdbd23b315..80b0a6c8da 100644 --- a/src/ui/components/Settings/components/ManagePassword/ManagePassword.test.tsx +++ b/src/ui/components/Settings/components/ManagePassword/ManagePassword.test.tsx @@ -149,12 +149,10 @@ describe("Manage password", () => { }); await waitFor(() => { - expect( - queryByText( - TRANSLATIONS.settings.sections.security.managepassword.page.alert - .enablemessage - ) - ).toBeNull(); + const openAlert = document.querySelector( + '[data-testid="alert-cancel-enable-password"][is-open="true"]' + ); + expect(openAlert).toBeNull(); }); await waitFor(() => { @@ -219,12 +217,10 @@ describe("Manage password", () => { }); await waitFor(() => { - expect( - queryByText( - TRANSLATIONS.settings.sections.security.managepassword.page.alert - .enablemessage - ) - ).toBeNull(); + const openAlert = document.querySelector( + '[data-testid="alert-cancel-enable-password"][is-open="true"]' + ); + expect(openAlert).toBeNull(); }); await waitFor(() => { @@ -300,12 +296,10 @@ describe("Manage password", () => { }); await waitFor(() => { - expect( - queryByText( - TRANSLATIONS.settings.sections.security.managepassword.page.alert - .disablemessage - ) - ).toBeNull(); + const openAlert = document.querySelector( + '[data-testid="alert-cancel"][is-open="true"]' + ); + expect(openAlert).toBeNull(); }); await waitFor(() => { diff --git a/src/ui/pages/ConnectionDetails/ConnectionDetails.types.ts b/src/ui/pages/ConnectionDetails/ConnectionDetails.types.ts index 1be42ceefc..8243345e22 100644 --- a/src/ui/pages/ConnectionDetails/ConnectionDetails.types.ts +++ b/src/ui/pages/ConnectionDetails/ConnectionDetails.types.ts @@ -1,7 +1,4 @@ -import { - ConnectionShortDetails, - RegularConnectionDetails, -} from "../../../core/agent/agent.types"; +import { RegularConnectionDetails } from "../../../core/agent/agent.types"; interface ConnectionDetailsProps { connectionShortDetails: RegularConnectionDetails; diff --git a/src/ui/pages/Connections/Connections.tsx b/src/ui/pages/Connections/Connections.tsx index f28495af6c..09c11b5c62 100644 --- a/src/ui/pages/Connections/Connections.tsx +++ b/src/ui/pages/Connections/Connections.tsx @@ -2,7 +2,6 @@ import { IonButton, IonIcon, useIonViewWillEnter } from "@ionic/react"; import { useCallback, useEffect, useState } from "react"; import { Agent } from "../../../core/agent/agent"; import { - ConnectionShortDetails, RegularConnectionDetails, ConnectionStatus, } from "../../../core/agent/agent.types"; @@ -10,7 +9,6 @@ import { i18n } from "../../../i18n"; import { TabsRoutePath } from "../../../routes/paths"; import { useAppDispatch, useAppSelector } from "../../../store/hooks"; import { - getConnectionsCache, getOpenConnectionId, removeConnectionCache, setOpenConnectionId, diff --git a/src/ui/pages/Connections/components/ConnectionsBody/ConnectionsBody.types.ts b/src/ui/pages/Connections/components/ConnectionsBody/ConnectionsBody.types.ts index d6a57563b8..718c85495a 100644 --- a/src/ui/pages/Connections/components/ConnectionsBody/ConnectionsBody.types.ts +++ b/src/ui/pages/Connections/components/ConnectionsBody/ConnectionsBody.types.ts @@ -1,7 +1,4 @@ -import { - ConnectionShortDetails, - RegularConnectionDetails, -} from "../../../../../core/agent/agent.types"; +import { RegularConnectionDetails } from "../../../../../core/agent/agent.types"; import { MappedConnections } from "../../Connections.types"; interface ConnectionsBodyProps { diff --git a/src/ui/pages/NotificationDetails/components/CredentialRequest/CredentialRequest.tsx b/src/ui/pages/NotificationDetails/components/CredentialRequest/CredentialRequest.tsx index 9f82dcce1d..291006fa0f 100644 --- a/src/ui/pages/NotificationDetails/components/CredentialRequest/CredentialRequest.tsx +++ b/src/ui/pages/NotificationDetails/components/CredentialRequest/CredentialRequest.tsx @@ -70,7 +70,7 @@ const CredentialRequest = ({ if (!memberConnection) { return { aid: member, - name: currentProfile?.identity.groupMetadata?.userName || "", + name: currentProfile?.identity.groupMetadata?.proposedUsername || "", joined: linkedGroup.linkedRequest.accepted, isCurrentUser: true, }; @@ -89,7 +89,7 @@ const CredentialRequest = ({ memberInfos, }); }, [ - currentProfile?.identity.groupMetadata?.userName, + currentProfile?.identity.groupMetadata?.proposedUsername, multisignConnectionsCache, notificationDetails.id, ]); diff --git a/src/ui/pages/NotificationDetails/components/MultiSigRequest/ErrorPage.tsx b/src/ui/pages/NotificationDetails/components/MultiSigRequest/ErrorPage.tsx index 2410bbd15f..ba295ef7a1 100644 --- a/src/ui/pages/NotificationDetails/components/MultiSigRequest/ErrorPage.tsx +++ b/src/ui/pages/NotificationDetails/components/MultiSigRequest/ErrorPage.tsx @@ -43,9 +43,10 @@ const ErrorPage = ({ ? connection.groupId : undefined; - const identifier = Object.values(profiles).find( - (item) => item.identity.groupMetadata?.groupId === multiSignGroupId - ); + const identifier = Object.values(profiles).find((item) => { + const profileGroupId = item.identity.groupMetadata?.groupId; + return profileGroupId === multiSignGroupId; + }); if (identifier) { setResumeMultiSig(identifier.identity); diff --git a/src/ui/pages/NotificationDetails/components/ReceiveCredential/ReceiveCredential.tsx b/src/ui/pages/NotificationDetails/components/ReceiveCredential/ReceiveCredential.tsx index 1d6e015977..e347bea344 100644 --- a/src/ui/pages/NotificationDetails/components/ReceiveCredential/ReceiveCredential.tsx +++ b/src/ui/pages/NotificationDetails/components/ReceiveCredential/ReceiveCredential.tsx @@ -266,7 +266,7 @@ const ReceiveCredential = ({ let name = memberConnection?.label || member; if (!memberConnection?.label) { - name = profile?.identity.groupMetadata?.userName || ""; + name = profile?.identity.groupMetadata?.proposedUsername || ""; } return { diff --git a/src/ui/pages/ProfileSetup/ProfileSetup.test.tsx b/src/ui/pages/ProfileSetup/ProfileSetup.test.tsx index 3c0f1f99f0..2dcc042093 100644 --- a/src/ui/pages/ProfileSetup/ProfileSetup.test.tsx +++ b/src/ui/pages/ProfileSetup/ProfileSetup.test.tsx @@ -28,7 +28,7 @@ import { CustomInputProps } from "../../components/CustomInput/CustomInput.types import { makeTestStore } from "../../utils/makeTestStore"; import { ProfileSetup } from "./ProfileSetup"; import { - ConnectionShortDetails, + MultisigConnectionDetails, ConnectionStatus, CreationStatus, OobiType, @@ -42,19 +42,21 @@ jest.mock("signify-ts", () => ({ })), })); -const connection: ConnectionShortDetails = { +const multisigConnection: MultisigConnectionDetails = { id: "ebfeb1ebc6f1c276ef71212ec20", label: "Cambridge University", createdAtUTC: "2017-01-14T19:23:24Z", status: ConnectionStatus.CONFIRMED, groupId: "0AAPHBnxoGK4tDuL4g87Eo9D", contactId: "conn-id-1", + oobi: "http://keria:3902/oobi/test", }; const connectByOobiUrlMock = jest.fn((...arg: unknown[]): Promise => { return Promise.resolve({ - type: OobiType.NORMAL, - connection, + type: OobiType.MULTI_SIG_INITIATOR, + groupId: "0AAPHBnxoGK4tDuL4g87Eo9D", + connection: multisigConnection, }); }); jest.mock("../../../core/agent/agent", () => ({ @@ -586,7 +588,7 @@ describe("Profile setup", () => { groupMetadata: expect.objectContaining({ groupInitiator: true, groupCreated: false, - userName: "testUser", + proposedUsername: "testUser", initiatorName: "testUser", groupId: expect.any(String), }), @@ -969,7 +971,7 @@ describe("Profile setup: use as modal", () => { groupId: "0AAPHBnxoGK4tDuL4g87Eo9D", groupCreated: false, groupInitiator: false, - userName: "test", + proposedUsername: "test", }, }, connections: [], diff --git a/src/ui/pages/ProfileSetup/ProfileSetup.tsx b/src/ui/pages/ProfileSetup/ProfileSetup.tsx index 84abfd4422..29d513a7ff 100644 --- a/src/ui/pages/ProfileSetup/ProfileSetup.tsx +++ b/src/ui/pages/ProfileSetup/ProfileSetup.tsx @@ -150,7 +150,7 @@ export const ProfileSetup = ({ ? false // Ensure joiner is not the initiator : true, groupCreated: false, - userName: userName, + proposedUsername: userName, initiatorName: stateCache.pendingJoinGroupMetadata?.isPendingJoinGroup ? stateCache.pendingJoinGroupMetadata?.initiatorName || undefined : userName, // Set initiatorName to userName for the initiator @@ -376,7 +376,7 @@ export const ProfileSetup = ({ () => dispatch(setToastMsg(ToastMsgType.DUPLICATE_GROUP_ID_ERROR)) ); - if (!invitation) return; + if (!invitation || invitation.type !== "MULTI_SIG_INITIATOR") return; // Update Redux state with all metadata, including initiatorName const pendingJoinData = { diff --git a/src/ui/pages/Profiles/Profiles.test.tsx b/src/ui/pages/Profiles/Profiles.test.tsx index cd7355c2a8..a3a77683b8 100644 --- a/src/ui/pages/Profiles/Profiles.test.tsx +++ b/src/ui/pages/Profiles/Profiles.test.tsx @@ -182,7 +182,8 @@ describe("Profiles", () => { const setIsOpenMock = jest.fn(); const pendingIdentifier = filteredIdentifierFix.find( (idObj) => - idObj.creationStatus === CreationStatus.PENDING && !!idObj.groupMetadata + idObj.creationStatus === CreationStatus.PENDING && + (!!idObj.groupMetadata || !!idObj.groupMemberPre) ); if (!pendingIdentifier) { throw new Error( diff --git a/src/ui/pages/Profiles/components/ProfileItem.test.tsx b/src/ui/pages/Profiles/components/ProfileItem.test.tsx index 28e43da59b..6d81ee4aa4 100644 --- a/src/ui/pages/Profiles/components/ProfileItem.test.tsx +++ b/src/ui/pages/Profiles/components/ProfileItem.test.tsx @@ -118,7 +118,7 @@ describe("ProfileItem", () => { groupId: "id", groupInitiator: true, groupCreated: false, - userName: "initiator", + proposedUsername: "initiator", }, }; const onClickMock = jest.fn(); @@ -146,7 +146,7 @@ describe("ProfileItem", () => { groupId: "id", groupInitiator: true, groupCreated: false, - userName: "initiator", + proposedUsername: "initiator", }, }; const onClickMock = jest.fn(); diff --git a/src/ui/pages/SetupGroupProfile/SetupGroupProfile.test.tsx b/src/ui/pages/SetupGroupProfile/SetupGroupProfile.test.tsx index 54037b189d..b5286bb210 100644 --- a/src/ui/pages/SetupGroupProfile/SetupGroupProfile.test.tsx +++ b/src/ui/pages/SetupGroupProfile/SetupGroupProfile.test.tsx @@ -586,7 +586,7 @@ describe("Setup Connections", () => { await waitFor(() => { expect( - getByText(multisignIdentifierFix[0].groupMetadata!.userName) + getByText(multisignIdentifierFix[0].groupMetadata!.proposedUsername) ).toBeVisible(); }); }); diff --git a/src/ui/pages/SetupGroupProfile/SetupGroupProfile.tsx b/src/ui/pages/SetupGroupProfile/SetupGroupProfile.tsx index 01d0280281..0095cc47bc 100644 --- a/src/ui/pages/SetupGroupProfile/SetupGroupProfile.tsx +++ b/src/ui/pages/SetupGroupProfile/SetupGroupProfile.tsx @@ -34,7 +34,7 @@ const initialState: GroupInfomation = { groupId: "", groupInitiator: false, // Default to false for joiners groupCreated: false, - userName: "", + proposedUsername: "", initiatorName: "", }, }; diff --git a/src/ui/pages/SetupGroupProfile/components/InitializeGroup/InitializeGroup.test.tsx b/src/ui/pages/SetupGroupProfile/components/InitializeGroup/InitializeGroup.test.tsx index e1cc4da9fe..0d38fa9b2a 100644 --- a/src/ui/pages/SetupGroupProfile/components/InitializeGroup/InitializeGroup.test.tsx +++ b/src/ui/pages/SetupGroupProfile/components/InitializeGroup/InitializeGroup.test.tsx @@ -58,7 +58,7 @@ const initiatorGroupProfile = { groupId: "549eb79f-856c-4bb7-8dd5-d5eed865906a", groupCreated: false, groupInitiator: true, - userName: "Initiator", + proposedUsername: "Initiator", }, }; diff --git a/src/ui/pages/SetupGroupProfile/components/InitializeGroup/InitializeGroup.tsx b/src/ui/pages/SetupGroupProfile/components/InitializeGroup/InitializeGroup.tsx index 053a9113e0..bc52fc822e 100644 --- a/src/ui/pages/SetupGroupProfile/components/InitializeGroup/InitializeGroup.tsx +++ b/src/ui/pages/SetupGroupProfile/components/InitializeGroup/InitializeGroup.tsx @@ -66,7 +66,7 @@ const InitializeGroup = ({ state, setState }: StageProps) => { }); members.unshift({ - name: profile?.identity.groupMetadata?.userName || "", + name: profile?.identity.groupMetadata?.proposedUsername || "", isCurrentUser: true, status: MemberAcceptStatus.None, }); @@ -80,7 +80,10 @@ const InitializeGroup = ({ state, setState }: StageProps) => { /> ), })); - }, [profile?.identity.groupMetadata?.userName, state.selectedConnections]); + }, [ + profile?.identity.groupMetadata?.proposedUsername, + state.selectedConnections, + ]); const openSignerModal = () => setOpenSigners(true); diff --git a/src/ui/pages/SetupGroupProfile/components/PendingGroup/PendingGroup.test.tsx b/src/ui/pages/SetupGroupProfile/components/PendingGroup/PendingGroup.test.tsx index e4bd616923..f70f859556 100644 --- a/src/ui/pages/SetupGroupProfile/components/PendingGroup/PendingGroup.test.tsx +++ b/src/ui/pages/SetupGroupProfile/components/PendingGroup/PendingGroup.test.tsx @@ -79,7 +79,7 @@ const initiatorGroupProfile = { groupId: "549eb79f-856c-4bb7-8dd5-d5eed865906a", groupCreated: false, groupInitiator: true, - userName: "Initiator", + proposedUsername: "Initiator", }, }; @@ -89,7 +89,7 @@ const memberGroupProfile = { groupId: "549eb79f-856c-4bb7-8dd5-d5eed865906a", groupCreated: false, groupInitiator: false, - userName: "Initiator", + proposedUsername: "Initiator", }, }; jest.mock("react-router-dom", () => ({ @@ -135,7 +135,7 @@ describe("Pending group", () => { time: Date.now(), passcodeIsSet: true, passwordIsSet: false, - userName: "Duke", + proposedUsername: "Duke", }, isOnline: true, }, @@ -266,7 +266,7 @@ describe("Pending group", () => { time: Date.now(), passcodeIsSet: true, passwordIsSet: false, - userName: "Duke", + proposedUsername: "Duke", }, isOnline: true, }, @@ -300,7 +300,7 @@ describe("Pending group", () => { groupId: "0AC8fs5EqOSKRNgjimwxdokY", groupInitiator: false, groupCreated: false, - userName: "QALZ", + proposedUsername: "QALZ", initiatorName: "ALZM", }, }, diff --git a/src/ui/pages/SetupGroupProfile/components/PendingGroup/PendingGroup.tsx b/src/ui/pages/SetupGroupProfile/components/PendingGroup/PendingGroup.tsx index 0d0f0de7fe..e1863e1d92 100644 --- a/src/ui/pages/SetupGroupProfile/components/PendingGroup/PendingGroup.tsx +++ b/src/ui/pages/SetupGroupProfile/components/PendingGroup/PendingGroup.tsx @@ -61,8 +61,7 @@ const PendingGroup = ({ state, isPendingGroup }: StageProps) => { null ); - const isMember = !identity?.groupMetadata?.groupInitiator; - const isPendingMember = isMember && initGroupNotification; + const isPendingMember = !!initGroupNotification; const rotationThreshold = isPendingMember ? multisigIcpDetails?.rotationThreshold @@ -105,7 +104,10 @@ const PendingGroup = ({ state, isPendingGroup }: StageProps) => { }); members.unshift({ - name: identity?.groupMetadata?.userName || "", + name: + identity?.groupUsername || + identity?.groupMetadata?.proposedUsername || + "", isCurrentUser: true, status: groupDetails?.members.find( (item) => item.aid === identity?.groupMemberPre @@ -114,7 +116,7 @@ const PendingGroup = ({ state, isPendingGroup }: StageProps) => { : MemberAcceptStatus.Waiting, }); - return members.map((member, index) => ({ + const mapped = members.map((member, index) => ({ ...member, avatar: ( { /> ), })); + return mapped; }, [ state.selectedConnections, - identity?.groupMetadata?.userName, + identity?.groupMetadata?.proposedUsername, identity?.groupMemberPre, groupDetails?.members, isPendingMember, @@ -175,28 +178,26 @@ const PendingGroup = ({ state, isPendingGroup }: StageProps) => { }; const getInceptionStatus = useCallback(async () => { - if (!identity?.id || !identity?.groupMetadata) return; + if (!identity?.id) return; try { setLoading(true); const details = await Agent.agent.multiSigs.getInceptionStatus( identity.id ); - setGroupDetails(details); } catch (e) { showError("Unable to load group: ", e, dispatch); } finally { setLoading(false); } - }, [dispatch, identity?.groupMetadata, identity?.id]); + }, [dispatch, identity?.id]); const fetchMultisigDetails = useCallback(async () => { if (!initGroupNotification) return; const details = await Agent.agent.multiSigs.getMultisigIcpDetails( initGroupNotification.a.d as string ); - setMultisigIcpDetails(details); }, [initGroupNotification]); @@ -207,7 +208,6 @@ const PendingGroup = ({ state, isPendingGroup }: StageProps) => { await fetchMultisigDetails(); return; } - await getInceptionStatus(); }, [ fetchMultisigDetails, @@ -262,7 +262,10 @@ const PendingGroup = ({ state, isPendingGroup }: StageProps) => { customClass="pending-group" header={ ({ @@ -204,7 +204,7 @@ describe("Setup Connection", () => { time: Date.now(), passcodeIsSet: true, passwordIsSet: false, - userName: "Duke", + proposedUsername: "Duke", }, isOnline: true, }, @@ -301,7 +301,7 @@ describe("Setup Connection", () => { const calledArgs = getOobiMock.mock.calls[0]; expect(calledArgs[0]).toEqual(stage1State.newIdentifier.id); expect(calledArgs[1]).toEqual({ - alias: initiatorGroupProfile.groupMetadata.userName, + alias: initiatorGroupProfile.groupMetadata.proposedUsername, groupId: initiatorGroupProfile.groupMetadata.groupId, groupName: initiatorGroupProfile.displayName, }); @@ -328,7 +328,7 @@ describe("Setup Connection", () => { getByText(EN_TRANSLATIONS.setupgroupprofile.setupmembers.subtitle) ).toBeVisible(); expect( - getByText(initiatorGroupProfile.groupMetadata.userName) + getByText(initiatorGroupProfile.groupMetadata.proposedUsername) ).toBeVisible(); expect(getByTestId("avatar-button")).toBeVisible(); diff --git a/src/ui/pages/SetupGroupProfile/components/SetupConnections/SetupConnections.tsx b/src/ui/pages/SetupGroupProfile/components/SetupConnections/SetupConnections.tsx index ca2ec6d73a..bfdc99c5e5 100644 --- a/src/ui/pages/SetupGroupProfile/components/SetupConnections/SetupConnections.tsx +++ b/src/ui/pages/SetupGroupProfile/components/SetupConnections/SetupConnections.tsx @@ -49,7 +49,7 @@ const SetupConnections = ({ setState }: StageProps) => { const scanRef = useRef(null); const groupId = profile?.groupMetadata?.groupId; - const userName = profile?.groupMetadata?.userName; + const proposedUsername = profile?.groupMetadata?.proposedUsername; const { resolveGroupConnection } = useScanHandle(); const groupConnections = useAppSelector(getMultisigConnectionsCache); const [multiSigGroup, setMultiSigGroup] = useState< @@ -87,7 +87,7 @@ const SetupConnections = ({ setState }: StageProps) => { const fetchOobi = useCallback(async () => { if ( !groupId || - !userName || + !proposedUsername || !profile?.displayName || profile?.creationStatus === CreationStatus.PENDING || (profile.creationStatus === CreationStatus.COMPLETE && @@ -97,7 +97,7 @@ const SetupConnections = ({ setState }: StageProps) => { try { const oobiValue = await Agent.agent.connections.getOobi(profile.id, { - alias: userName, + alias: proposedUsername, groupId: groupId, groupName: profile?.displayName, }); @@ -109,7 +109,7 @@ const SetupConnections = ({ setState }: StageProps) => { } }, [ groupId, - userName, + proposedUsername, profile?.displayName, profile?.creationStatus, profile?.groupMemberPre, @@ -174,7 +174,7 @@ const SetupConnections = ({ setState }: StageProps) => { { b: ["BIe_q0F4EkYPEne6jUnSV1exxOYeGf_AMSMvegpF4XQP"], di: "test", groupMemberPre: "ELUXM-ajSu0o1qyFvss-3QQfkj3DOke9aHNwt72Byi9y", + groupId: "test-group-id", members: [ "EFZ-hSogn3-wXEahBbIW_oXYxAV_vH8eEhX6BwQHsYBu", "EFZ-hSogn3-wXEahBbIW_oXYxAV_vH8eEhX6BwQHsYB2", @@ -32,13 +33,9 @@ describe("transformGroupIdentifier", () => { createdAtUTC: "2024-03-07T11:54:56.886Z", theme: 0, creationStatus: CreationStatus.COMPLETE, - groupMetadata: { - groupId: "test", - groupInitiator: true, - groupCreated: false, - userName: "", - }, + groupMetadata: undefined, groupMemberPre: "ELUXM-ajSu0o1qyFvss-3QQfkj3DOke9aHNwt72Byi9y", + groupUsername: "", }, }; @@ -72,6 +69,7 @@ describe("transformGroupIdentifier", () => { creationStatus: CreationStatus.COMPLETE, groupMetadata: undefined, groupMemberPre: undefined, + groupUsername: undefined, }, }; diff --git a/src/utils/transformGroupIdentifier.ts b/src/utils/transformGroupIdentifier.ts index 26a5c095f9..c3d5d1567d 100644 --- a/src/utils/transformGroupIdentifier.ts +++ b/src/utils/transformGroupIdentifier.ts @@ -17,15 +17,9 @@ export function transformGroupIdentifier( createdAtUTC: input.createdAtUTC, theme: input.theme, creationStatus: input.creationStatus, - groupMetadata: input.di - ? { - groupId: input.di, - groupInitiator: true, - groupCreated: false, - userName: "", - } - : undefined, + groupMetadata: input.groupMemberPre ? undefined : input.groupMetadata, groupMemberPre: input.groupMemberPre, + groupUsername: input.groupUsername ?? (input.di ? "" : undefined), }, };