diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c1744229..9464a18c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -57,7 +57,7 @@ jobs: strategy: matrix: os: ['ubuntu-latest'] - keria-version: ['latest'] + keria-version: ['0.2.0-dev0'] node-version: ['20'] env: KERIA_IMAGE_TAG: ${{ matrix.keria-version }} diff --git a/examples/integration-scripts/credentials.test.ts b/examples/integration-scripts/credentials.test.ts index e1e871d7..2811dda1 100644 --- a/examples/integration-scripts/credentials.test.ts +++ b/examples/integration-scripts/credentials.test.ts @@ -380,12 +380,19 @@ test('single signature credentials', async () => { const result = await holderClient .credentials() .issue(holderAid.name, { + ri: holderRegistry.regk, + s: LE_SCHEMA_SAID, a: { i: legalEntityAid.prefix, LEI: '5493001KJTIIGC8Y1R17', }, - ri: holderRegistry.regk, - s: LE_SCHEMA_SAID, + e: Saider.saidify({ + d: '', + qvi: { + n: qviCredential.sad.d, + s: qviCredential.sad.s, + }, + })[1], r: Saider.saidify({ d: '', usageDisclaimer: { @@ -395,13 +402,6 @@ test('single signature credentials', async () => { l: 'All information in a valid, unexpired, and non-revoked vLEI Credential, as defined in the associated Ecosystem Governance Framework, is accurate as of the date the validation process was complete. The vLEI Credential has been issued to the legal entity or person named in the vLEI Credential as the subject; and the qualified vLEI Issuer exercised reasonable care to perform the validation process set forth in the vLEI Ecosystem Governance Framework.', }, })[1], - e: Saider.saidify({ - d: '', - qvi: { - n: qviCredential.sad.d, - s: qviCredential.sad.s, - }, - })[1], }); await waitOperation(holderClient, result.op); diff --git a/examples/integration-scripts/salty.test.ts b/examples/integration-scripts/salty.test.ts index 95b88d19..9de613fc 100644 --- a/examples/integration-scripts/salty.test.ts +++ b/examples/integration-scripts/salty.test.ts @@ -156,16 +156,31 @@ test('salty', async () => { const events = client1.keyEvents(); const log = await events.get(aid['prefix']); assert.equal(log.length, 3); - let serder = new signify.Serder(log[0]); + let serder = new signify.Serder(log[0].ked); assert.equal(serder.pre, icp.pre); assert.equal(serder.ked['d'], icp.ked['d']); - serder = new signify.Serder(log[1]); + serder = new signify.Serder(log[1].ked); assert.equal(serder.pre, rot.pre); assert.equal(serder.ked['d'], rot.ked['d']); - serder = new signify.Serder(log[2]); + serder = new signify.Serder(log[2].ked); assert.equal(serder.pre, ixn.pre); assert.equal(serder.ked['d'], ixn.ked['d']); + const renameResult = await client1 + .identifiers() + .rename('aid1', 'aidRenamed'); + assert.equal(renameResult.name, 'aidRenamed'); + aids = await client1.identifiers().list(); + assert.equal(aids.aids.length, 3); + aid = aids.aids.pop(); + assert.equal(aid.name, 'aidRenamed'); + + await client1.identifiers().delete('aidRenamed'); + aids = await client1.identifiers().list(); + assert.equal(aids.aids.length, 2); + aid = aids.aids.pop(); + assert.equal(aid.name, 'aid3'); + await assertOperations(client1); console.log('Salty test passed'); diff --git a/examples/integration-scripts/singlesig-vlei-issuance.test.ts b/examples/integration-scripts/singlesig-vlei-issuance.test.ts index 6aacbc51..7636c6c0 100644 --- a/examples/integration-scripts/singlesig-vlei-issuance.test.ts +++ b/examples/integration-scripts/singlesig-vlei-issuance.test.ts @@ -506,16 +506,16 @@ async function getOrIssueCredential( } const issResult = await issuerClient.credentials().issue(issuerAid.name, { + u: privacy ? new Salter({}).qb64 : undefined, ri: issuerRegistry.regk, s: schema, - u: privacy ? new Salter({}).qb64 : undefined, a: { i: recipientAid.prefix, u: privacy ? new Salter({}).qb64 : undefined, ...credData, }, - r: rules, e: source, + r: rules, }); await waitOperation(issuerClient, issResult.op); diff --git a/examples/integration-scripts/utils/test-setup.ts b/examples/integration-scripts/utils/test-setup.ts index ea9760f1..e0ed1734 100644 --- a/examples/integration-scripts/utils/test-setup.ts +++ b/examples/integration-scripts/utils/test-setup.ts @@ -121,8 +121,8 @@ export async function getEndRoles( ): Promise { const path = role !== undefined - ? `/identifiers/${alias}/endroles/${role}` - : `/identifiers/${alias}/endroles`; + ? `/identifiers/${encodeURIComponent(alias)}/endroles/${role}` + : `/identifiers/${encodeURIComponent(alias)}/endroles`; const response: Response = await client.fetch(path, 'GET', null); if (!response.ok) throw new Error(await response.text()); const result = await response.json(); diff --git a/src/keri/app/aiding.ts b/src/keri/app/aiding.ts index f508f182..c90b6222 100644 --- a/src/keri/app/aiding.ts +++ b/src/keri/app/aiding.ts @@ -119,6 +119,34 @@ export class Identifier { return await res.json(); } + /** + * Get information for a managed identifier + * @async + * @param {string} name Name or alias of the identifier + * @param {string} newName New name or alias of the identifier + * @returns {Promise} A promise to the identifier information + */ + async rename(name: string, newName: string): Promise { + const path = `/identifiers/${encodeURIComponent(name)}`; + const data = { name: newName }; + const method = 'PUT'; + const res = await this.client.fetch(path, method, data); + return res.json(); + } + + /** + * Delete a managed identifier + * @async + * @param {string} name Name or alias of the identifier + * @returns {Promise} A promise to the identifier information + */ + async delete(name: string): Promise { + const path = `/identifiers/${encodeURIComponent(name)}`; + const method = 'DELETE'; + await this.client.fetch(path, method, null); + return; + } + /** * Create a managed identifier * @async @@ -226,14 +254,8 @@ export class Identifier { icp: serder.ked, sigs: sigs, proxy: proxy, - smids: - states != undefined - ? states.map((state) => state.i) - : undefined, - rmids: - rstates != undefined - ? rstates.map((state) => state.i) - : undefined, + smids: states, + rmids: states, }; jsondata[algo] = keeper.params(); @@ -277,8 +299,8 @@ export class Identifier { jsondata[keeper.algo] = keeper.params(); const res = await this.client.fetch( - '/identifiers/' + name + '?type=ixn', - 'PUT', + `/identifiers/${encodeURIComponent(name)}/events`, + 'POST', jsondata ); return new EventResult(serder, sigs, res); @@ -363,20 +385,14 @@ export class Identifier { const jsondata: any = { rot: serder.ked, sigs: sigs, - smids: - states != undefined - ? states.map((state) => state.i) - : undefined, - rmids: - rstates != undefined - ? rstates.map((state) => state.i) - : undefined, + smids: states, + rmids: rstates, }; jsondata[keeper.algo] = keeper.params(); const res = await this.client.fetch( - '/identifiers/' + name, - 'PUT', + `/identifiers/${encodeURIComponent(name)}/events`, + 'POST', jsondata ); return new EventResult(serder, sigs, res); @@ -412,7 +428,7 @@ export class Identifier { }; const res = this.client.fetch( - '/identifiers/' + name + '/endroles', + `/identifiers/${encodeURIComponent(name)}/endroles`, 'POST', jsondata ); @@ -452,7 +468,7 @@ export class Identifier { */ async members(name: string): Promise { const res = await this.client.fetch( - '/identifiers/' + name + '/members', + `/identifiers/${encodeURIComponent(name)}/members`, 'GET', undefined ); diff --git a/src/keri/app/coring.ts b/src/keri/app/coring.ts index fd5a1161..a609f1b3 100644 --- a/src/keri/app/coring.ts +++ b/src/keri/app/coring.ts @@ -34,7 +34,9 @@ export class Oobis { * @returns {Promise} A promise to the OOBI(s) */ async get(name: string, role: string = 'agent'): Promise { - const path = `/identifiers/${name}/oobis?role=${role}`; + const path = `/identifiers/${encodeURIComponent( + name + )}/oobis?role=${role}`; const method = 'GET'; const res = await this.client.fetch(path, method, null); return await res.json(); diff --git a/src/keri/app/credentialing.ts b/src/keri/app/credentialing.ts index 4d231087..ead892cb 100644 --- a/src/keri/app/credentialing.ts +++ b/src/keri/app/credentialing.ts @@ -211,6 +211,7 @@ export class Credentials { const [, acdc] = Saider.saidify({ v: versify(Ident.ACDC, undefined, Serials.JSON, 0), d: '', + u: args.u, i: args.i ?? hab.prefix, ...args, a: subject, @@ -352,7 +353,9 @@ export class Credentials { [keeper.algo]: keeper.params(), }; - const path = `/identifiers/${name}/credentials/${said}`; + const path = `/identifiers/${encodeURIComponent( + name + )}/credentials/${said}`; const method = 'DELETE'; const headers = new Headers({ Accept: 'application/json+cesr', @@ -422,7 +425,9 @@ export class Credentials { include: include, }; - const path = `/identifiers/${name}/credentials/${said}/presentations`; + const path = `/identifiers/${encodeURIComponent( + name + )}/credentials/${said}/presentations`; const method = 'POST'; const headers = new Headers({ Accept: 'application/json+cesr', @@ -485,7 +490,7 @@ export class Credentials { recipient: recipient, }; - const path = `/identifiers/${name}/requests`; + const path = `/identifiers/${encodeURIComponent(name)}/requests`; const method = 'POST'; const headers = new Headers({ Accept: 'application/json+cesr', @@ -560,7 +565,7 @@ export class Registries { * @returns {Promise} A promise to the list of registries */ async list(name: string): Promise { - const path = `/identifiers/${name}/registries`; + const path = `/identifiers/${encodeURIComponent(name)}/registries`; const method = 'GET'; const res = await this.client.fetch(path, method, null); return await res.json(); @@ -641,7 +646,7 @@ export class Registries { ixn: Dict, sigs: any[] ) { - const path = `/identifiers/${name}/registries`; + const path = `/identifiers/${encodeURIComponent(name)}/registries`; const method = 'POST'; const data: any = { @@ -771,7 +776,7 @@ export class Ipex { }; const response = await this.client.fetch( - `/identifiers/${name}/ipex/grant`, + `/identifiers/${encodeURIComponent(name)}/ipex/grant`, 'POST', body ); @@ -827,7 +832,7 @@ export class Ipex { }; const response = await this.client.fetch( - `/identifiers/${name}/ipex/admit`, + `/identifiers/${encodeURIComponent(name)}/ipex/admit`, 'POST', body ); diff --git a/src/keri/app/exchanging.ts b/src/keri/app/exchanging.ts index d000c5a8..46024881 100644 --- a/src/keri/app/exchanging.ts +++ b/src/keri/app/exchanging.ts @@ -113,7 +113,7 @@ export class Exchanges { atc: string, recipients: string[] ): Promise { - const path = `/identifiers/${name}/exchanges`; + const path = `/identifiers/${encodeURIComponent(name)}/exchanges`; const method = 'POST'; const data: any = { tpc: topic, diff --git a/src/keri/app/grouping.ts b/src/keri/app/grouping.ts index f9745499..a29b4e85 100644 --- a/src/keri/app/grouping.ts +++ b/src/keri/app/grouping.ts @@ -43,7 +43,9 @@ export class Groups { sigs: string[], atc: string ): Promise { - const path = `/identifiers/${name}/multisig/request`; + const path = `/identifiers/${encodeURIComponent( + name + )}/multisig/request`; const method = 'POST'; const data = { exn: exn, @@ -74,7 +76,7 @@ export class Groups { smids: string[], rmids: string[] ): Promise { - const path = `/identifiers/${name}/multisig/join`; + const path = `/identifiers/${encodeURIComponent(name)}/multisig/join`; const method = 'POST'; const data = { tpc: 'multisig', diff --git a/test/app/aiding.test.ts b/test/app/aiding.test.ts index b2e333f9..ccdfdab3 100644 --- a/test/app/aiding.test.ts +++ b/test/app/aiding.test.ts @@ -169,8 +169,8 @@ describe('Aiding', () => { await client.identifiers().rotate('aid1'); const lastCall = client.getLastMockRequest(); - assert.equal(lastCall.path, '/identifiers/aid1'); - assert.equal(lastCall.method, 'PUT'); + assert.equal(lastCall.path, '/identifiers/aid1/events'); + assert.equal(lastCall.method, 'POST'); assert.deepEqual(lastCall.body.rot, { v: 'KERI10JSON000160_', t: 'rot', @@ -215,8 +215,8 @@ describe('Aiding', () => { await client.identifiers().rotate('aid1'); const lastCall = client.getLastMockRequest(); - assert.equal(lastCall.path, '/identifiers/aid1'); - assert.equal(lastCall.method, 'PUT'); + assert.equal(lastCall.path, '/identifiers/aid1/events'); + assert.equal(lastCall.method, 'POST'); expect(lastCall.body.rot).toMatchObject({ v: 'KERI10JSON000160_', t: 'rot', @@ -241,8 +241,8 @@ describe('Aiding', () => { const lastCall = client.getLastMockRequest(); - expect(lastCall.path).toEqual('/identifiers/aid1?type=ixn'); - expect(lastCall.method).toEqual('PUT'); + expect(lastCall.path).toEqual('/identifiers/aid1/events'); + expect(lastCall.method).toEqual('POST'); expect(lastCall.body.ixn).toMatchObject({ v: 'KERI10JSON000138_', t: 'ixn', @@ -283,8 +283,8 @@ describe('Aiding', () => { const lastCall = client.getLastMockRequest(); - expect(lastCall.path).toEqual('/identifiers/aid1?type=ixn'); - expect(lastCall.method).toEqual('PUT'); + expect(lastCall.path).toEqual('/identifiers/aid1/events'); + expect(lastCall.method).toEqual('POST'); expect(lastCall.body.ixn).toMatchObject({ s: 'b', a: data, @@ -440,4 +440,34 @@ describe('Aiding', () => { args !== null; // avoids TS6133 }); }); + + it('Can rename salty identifier', async () => { + const aid1 = await createMockIdentifierState('aid1', bran, {}); + client.fetch.mockResolvedValueOnce(Response.json(aid1)); + client.fetch.mockResolvedValueOnce(Response.json({})); + + const aidRenamed = await client + .identifiers() + .rename('aid1', 'aidRenamed'); + client.fetch.mockResolvedValueOnce(Response.json(aidRenamed)); + client.fetch.mockResolvedValueOnce(Response.json({})); + const lastCall = client.getLastMockRequest(); + assert.equal(lastCall.path, '/identifiers/aid1'); + assert.equal(lastCall.method, 'PUT'); + assert.deepEqual(lastCall.body, { + name: 'aidRenamed', + }); + }); + + it('Can delete salty identifier', async () => { + const aid1 = await createMockIdentifierState('aid1', bran, {}); + client.fetch.mockResolvedValueOnce(Response.json(aid1)); + client.fetch.mockResolvedValueOnce(Response.json({})); + + await client.identifiers().delete('aid1'); + client.fetch.mockResolvedValueOnce(Response.json({})); + const lastCall = client.getLastMockRequest(); + assert.equal(lastCall.path, '/identifiers/aid1'); + assert.equal(lastCall.method, 'DELETE'); + }); });