From 7d85396279a3f30affa7895f27e87ecf3650e94d Mon Sep 17 00:00:00 2001 From: Liran Cohen Date: Mon, 21 Oct 2024 13:13:09 -0400 Subject: [PATCH 1/3] add setter and getter for the identity metadata name --- packages/agent/src/identity-api.ts | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/packages/agent/src/identity-api.ts b/packages/agent/src/identity-api.ts index f35bab22a..8e34fbcc2 100644 --- a/packages/agent/src/identity-api.ts +++ b/packages/agent/src/identity-api.ts @@ -270,6 +270,40 @@ export class AgentIdentityApi { + const identity = await this.get({ didUri }); + if (!identity) { + throw new Error(`AgentIdentityApi: Failed to retrieve metadata name due to Identity not found: ${didUri}`); + } + + return identity.metadata.name; + } + + public async setMetadataName({ didUri, name }: { didUri: string; name: string }): Promise { + if (!name) { + throw new Error('AgentIdentityApi: Failed to set metadata name due to missing name value.'); + } + + const identity = await this.get({ didUri }); + if (!identity) { + throw new Error(`AgentIdentityApi: Failed to set metadata name due to Identity not found: ${didUri}`); + } + + if (identity.metadata.name === name) { + throw new Error('AgentIdentityApi: Metadata name is already set to the provided value.'); + } + + // Update the name in the Identity's metadata and store it + await this._store.set({ + id : identity.did.uri, + data : { ...identity.metadata, name }, + agent : this.agent, + tenant : identity.metadata.tenant, + updateExisting : true, + useCache : true + }); + } + /** * Returns the connected Identity, if one is available. * From 82412565899415b730e503e2927dd59f033b61da Mon Sep 17 00:00:00 2001 From: Liran Cohen Date: Mon, 21 Oct 2024 15:27:17 -0400 Subject: [PATCH 2/3] test coverage --- packages/agent/src/identity-api.ts | 11 +-- packages/agent/tests/identity-api.spec.ts | 109 ++++++++++++++++++++++ 2 files changed, 110 insertions(+), 10 deletions(-) diff --git a/packages/agent/src/identity-api.ts b/packages/agent/src/identity-api.ts index 8e34fbcc2..0c7c7c5b9 100644 --- a/packages/agent/src/identity-api.ts +++ b/packages/agent/src/identity-api.ts @@ -270,15 +270,6 @@ export class AgentIdentityApi { - const identity = await this.get({ didUri }); - if (!identity) { - throw new Error(`AgentIdentityApi: Failed to retrieve metadata name due to Identity not found: ${didUri}`); - } - - return identity.metadata.name; - } - public async setMetadataName({ didUri, name }: { didUri: string; name: string }): Promise { if (!name) { throw new Error('AgentIdentityApi: Failed to set metadata name due to missing name value.'); @@ -290,7 +281,7 @@ export class AgentIdentityApi { }); }); + describe('setMetadataName', () => { + it('should update the name of an Identity', async () => { + const identity = await testHarness.agent.identity.create({ + metadata : { name: 'Test Identity' }, + didMethod : 'jwk', + didOptions : { + verificationMethods: [{ + algorithm: 'Ed25519' + }] + } + }); + expect(identity.metadata.name).to.equal('Test Identity'); + + // sanity fetch the identity + let storedIdentity = await testHarness.agent.identity.get({ didUri: identity.did.uri }); + expect(storedIdentity).to.exist; + expect(storedIdentity?.metadata.name).to.equal('Test Identity'); + + // update the identity + await testHarness.agent.identity.setMetadataName({ didUri: identity.did.uri, name: 'Updated Identity' }); + + // fetch the updated identity + storedIdentity = await testHarness.agent.identity.get({ didUri: identity.did.uri }); + expect(storedIdentity).to.exist; + expect(storedIdentity?.metadata.name).to.equal('Updated Identity'); + }); + + it('should throw if identity does not exist', async () => { + try { + await testHarness.agent.identity.setMetadataName({ didUri: 'did:method:xyz123', name: 'Updated Identity' }); + expect.fail('Expected an error to be thrown'); + } catch (error: any) { + expect(error.message).to.include('AgentIdentityApi: Failed to set metadata name due to Identity not found'); + } + }); + + it('should throw if name is missing or empty', async () => { + const storeSpy = sinon.spy(testHarness.agent.identity['_store'], 'set'); + const identity = await testHarness.agent.identity.create({ + metadata : { name: 'Test Identity' }, + didMethod : 'jwk', + didOptions : { + verificationMethods: [{ + algorithm: 'Ed25519' + }] + } + }); + + expect(storeSpy.callCount).to.equal(1); + + try { + await testHarness.agent.identity.setMetadataName({ didUri: identity.did.uri, name: '' }); + expect.fail('Expected an error to be thrown'); + } catch (error: any) { + expect(error.message).to.include('Failed to set metadata name due to missing name value'); + } + + try { + await testHarness.agent.identity.setMetadataName({ didUri: identity.did.uri, name: undefined! }); + expect.fail('Expected an error to be thrown'); + } catch (error: any) { + expect(error.message).to.include('Failed to set metadata name due to missing name value'); + } + + // call count should not have changed + expect(storeSpy.callCount).to.equal(1); + + // sanity confirm the name did not change + const storedIdentity = await testHarness.agent.identity.get({ didUri: identity.did.uri }); + expect(storedIdentity).to.exist; + expect(storedIdentity?.metadata.name).to.equal('Test Identity'); + }); + + it('should throw if the updated name is the same as the current name', async () => { + const identity = await testHarness.agent.identity.create({ + metadata : { name: 'Test Identity' }, + didMethod : 'jwk', + didOptions : { + verificationMethods: [{ + algorithm: 'Ed25519' + }] + } + }); + + const storeSpy = sinon.spy(testHarness.agent.identity['_store'], 'set'); + + try { + await testHarness.agent.identity.setMetadataName({ didUri: identity.did.uri, name: 'Test Identity' }); + expect.fail('Expected an error to be thrown'); + } catch (error: any) { + expect(error.message).to.include('AgentIdentityApi: No changes detected'); + } + + // confirm set has not been called + expect(storeSpy.notCalled).to.be.true; + + // sanity update the name to something else + await testHarness.agent.identity.setMetadataName({ didUri: identity.did.uri, name: 'Updated Identity' }); + + // confirm set has been called + expect(storeSpy.calledOnce).to.be.true; + + // confirm the name was updated + const storedIdentity = await testHarness.agent.identity.get({ didUri: identity.did.uri }); + expect(storedIdentity).to.exist; + expect(storedIdentity?.metadata.name).to.equal('Updated Identity'); + }); + }); + describe('connectedIdentity', () => { it('returns a connected Identity', async () => { // create multiple identities, some that are connected, and some that are not From 131db7ce2385b96fb94c04f4be001904ebfb9a45 Mon Sep 17 00:00:00 2001 From: Liran Cohen Date: Mon, 21 Oct 2024 15:34:17 -0400 Subject: [PATCH 3/3] add changesets and comments --- .changeset/shy-grapes-juggle.md | 8 ++++++++ packages/agent/src/identity-api.ts | 8 ++++++++ 2 files changed, 16 insertions(+) create mode 100644 .changeset/shy-grapes-juggle.md diff --git a/.changeset/shy-grapes-juggle.md b/.changeset/shy-grapes-juggle.md new file mode 100644 index 000000000..4cb022f44 --- /dev/null +++ b/.changeset/shy-grapes-juggle.md @@ -0,0 +1,8 @@ +--- +"@web5/agent": patch +"@web5/identity-agent": patch +"@web5/proxy-agent": patch +"@web5/user-agent": patch +--- + +Add ability to update the Identity Metadata name field. diff --git a/packages/agent/src/identity-api.ts b/packages/agent/src/identity-api.ts index 0c7c7c5b9..0b1bbd1cd 100644 --- a/packages/agent/src/identity-api.ts +++ b/packages/agent/src/identity-api.ts @@ -270,6 +270,14 @@ export class AgentIdentityApi { if (!name) { throw new Error('AgentIdentityApi: Failed to set metadata name due to missing name value.');