diff --git a/__tests__/graphqlAgent.test.ts b/__tests__/graphqlAgent.test.ts index 558331520..1e3cca8fb 100644 --- a/__tests__/graphqlAgent.test.ts +++ b/__tests__/graphqlAgent.test.ts @@ -35,6 +35,7 @@ import resolveDid from './shared/resolveDid' import webDidFlow from './shared/webDidFlow' import documentationExamples from './shared/documentationExamples' import keyManager from './shared/keyManager' +import identityManager from './shared/identityManager' const databaseFile = 'graphql-database.sqlite' const infuraProjectId = '5ffc47f65c4042ce847ef66a3fa70d4c' @@ -84,6 +85,13 @@ const setup = async (): Promise => { store: new IdentityStore(dbConnection), defaultProvider: 'did:ethr:rinkeby', providers: { + 'did:ethr': new EthrIdentityProvider({ + defaultKms: 'local', + network: 'mainnet', + rpcUrl: 'https://mainnet.infura.io/v3/' + infuraProjectId, + gas: 1000001, + ttl: 60 * 60 * 24 * 30 * 12 + 1, + }), 'did:ethr:rinkeby': new EthrIdentityProvider({ defaultKms: 'local', network: 'rinkeby', @@ -151,4 +159,5 @@ describe('GraphQL integration tests', () => { webDidFlow(testContext) documentationExamples(testContext) keyManager(testContext) + identityManager(testContext) }) diff --git a/__tests__/localAgent.test.ts b/__tests__/localAgent.test.ts index 22f3336b1..80727a23c 100644 --- a/__tests__/localAgent.test.ts +++ b/__tests__/localAgent.test.ts @@ -30,6 +30,7 @@ import webDidFlow from './shared/webDidFlow' import saveClaims from './shared/saveClaims' import documentationExamples from './shared/documentationExamples' import keyManager from './shared/keyManager' +import identityManager from './shared/identityManager' const databaseFile = 'local-database.sqlite' const infuraProjectId = '5ffc47f65c4042ce847ef66a3fa70d4c' @@ -82,6 +83,13 @@ const setup = async (): Promise => { store: new IdentityStore(dbConnection), defaultProvider: 'did:ethr:rinkeby', providers: { + 'did:ethr': new EthrIdentityProvider({ + defaultKms: 'local', + network: 'mainnet', + rpcUrl: 'https://mainnet.infura.io/v3/' + infuraProjectId, + gas: 1000001, + ttl: 60 * 60 * 24 * 30 * 12 + 1, + }), 'did:ethr:rinkeby': new EthrIdentityProvider({ defaultKms: 'local', network: 'rinkeby', @@ -131,4 +139,5 @@ describe('Local integration tests', () => { saveClaims(testContext) documentationExamples(testContext) keyManager(testContext) + identityManager(testContext) }) diff --git a/__tests__/restAgent.test.ts b/__tests__/restAgent.test.ts index 1d571e350..ae5d6b446 100644 --- a/__tests__/restAgent.test.ts +++ b/__tests__/restAgent.test.ts @@ -34,6 +34,7 @@ import resolveDid from './shared/resolveDid' import webDidFlow from './shared/webDidFlow' import documentationExamples from './shared/documentationExamples' import keyManager from './shared/keyManager' +import identityManager from './shared/identityManager' const databaseFile = 'rest-database.sqlite' const infuraProjectId = '5ffc47f65c4042ce847ef66a3fa70d4c' @@ -83,6 +84,13 @@ const setup = async (): Promise => { store: new IdentityStore(dbConnection), defaultProvider: 'did:ethr:rinkeby', providers: { + 'did:ethr': new EthrIdentityProvider({ + defaultKms: 'local', + network: 'mainnet', + rpcUrl: 'https://mainnet.infura.io/v3/' + infuraProjectId, + gas: 1000001, + ttl: 60 * 60 * 24 * 30 * 12 + 1, + }), 'did:ethr:rinkeby': new EthrIdentityProvider({ defaultKms: 'local', network: 'rinkeby', @@ -144,4 +152,5 @@ describe('REST integration tests', () => { webDidFlow(testContext) documentationExamples(testContext) keyManager(testContext) + identityManager(testContext) }) diff --git a/__tests__/shared/documentationExamples.ts b/__tests__/shared/documentationExamples.ts index 886e6d07f..e83890826 100644 --- a/__tests__/shared/documentationExamples.ts +++ b/__tests__/shared/documentationExamples.ts @@ -50,11 +50,19 @@ export default (testContext: { it('daf-core-IIdentityManager-identityManagerCreateIdentity example', async () => { const identity = await agent.identityManagerCreateIdentity({ + alias: 'alice', provider: 'did:ethr:rinkeby', kms: 'local', }) }) + it('daf-core-IIdentityManager-identityManagerGetIdentityByAlias example', async () => { + const identity = await agent.identityManagerGetIdentityByAlias({ + alias: 'alice', + provider: 'did:ethr:rinkeby', + }) + }) + //DO NOT EDIT MANUALLY END }) } diff --git a/__tests__/shared/identityManager.ts b/__tests__/shared/identityManager.ts new file mode 100644 index 000000000..4796a0152 --- /dev/null +++ b/__tests__/shared/identityManager.ts @@ -0,0 +1,106 @@ +import { TAgent, IIdentityManager, IKeyManager, IIdentity } from 'daf-core' + +type ConfiguredAgent = TAgent + +export default (testContext: { + getAgent: () => ConfiguredAgent + setup: () => Promise + tearDown: () => Promise +}) => { + describe('identity manager', () => { + let agent: ConfiguredAgent + + beforeAll(async () => { + await testContext.setup() + agent = testContext.getAgent() + return true + }) + afterAll(testContext.tearDown) + + it('should get providers', async () => { + const providers = await agent.identityManagerGetProviders() + expect(providers).toEqual(['did:ethr', 'did:ethr:rinkeby', 'did:web']) + }) + + let identity: IIdentity + it('should create identity', async () => { + identity = await agent.identityManagerCreateIdentity({ + provider: 'did:web', + alias: 'example.com', + }) + expect(identity.provider).toEqual('did:web') + expect(identity.alias).toEqual('example.com') + expect(identity.did).toEqual('did:web:example.com') + expect(identity.keys.length).toEqual(1) + expect(identity.services.length).toEqual(0) + expect(identity.controllerKeyId).toEqual(identity.keys[0].kid) + }) + + it('should throw error for existing alias provider combo', async () => { + await expect( + agent.identityManagerCreateIdentity({ + provider: 'did:web', + alias: 'example.com', + }), + ).rejects.toThrow('Identity with alias: example.com, provider: did:web already exists') + }) + + it('should get identity', async () => { + const identity2 = await agent.identityManagerGetIdentity({ + did: identity.did, + }) + expect(identity2.did).toEqual(identity.did) + }) + + it('should throw error for non existing did', async () => { + await expect( + agent.identityManagerGetIdentity({ + did: 'did:web:foobar', + }), + ).rejects.toThrow('Identity not found') + }) + + it('should get or create identity', async () => { + const identity3 = await agent.identityManagerGetOrCreateIdentity({ + alias: 'alice', + provider: 'did:ethr:rinkeby', + }) + + const identity4 = await agent.identityManagerGetOrCreateIdentity({ + alias: 'alice', + provider: 'did:ethr:rinkeby', + }) + + expect(identity3).toEqual(identity4) + + const identity5 = await agent.identityManagerGetOrCreateIdentity({ + alias: 'alice', + provider: 'did:ethr', + }) + + expect(identity5).not.toEqual(identity4) + + const identity6 = await agent.identityManagerGetIdentityByAlias({ + alias: 'alice', + provider: 'did:ethr', + }) + + expect(identity6).toEqual(identity5) + + const identity7 = await agent.identityManagerGetIdentityByAlias({ + alias: 'alice', + // default provider is 'did:ethr:rinkeby' + }) + + expect(identity7).toEqual(identity4) + }) + + it.todo('should get identities') + it.todo('should import identity') + it.todo('should delete identity') + it.todo('should add key to identity') + it.todo('should remove key from identity') + it.todo('should add service to identity') + it.todo('should remove service from identity') + }) +} diff --git a/__tests__/shared/keyManager.ts b/__tests__/shared/keyManager.ts index e05d15292..618fd6d8c 100644 --- a/__tests__/shared/keyManager.ts +++ b/__tests__/shared/keyManager.ts @@ -189,5 +189,36 @@ export default (testContext: { expect(typeof rawTx).toEqual('string') }) + + it.todo('Should Encrypt/Decrypt') + // it('Should Encrypt/Decrypt', async () => { + // const message = 'foo bar' + + // const senderKey = await agent.keyManagerCreateKey({ + // kms: 'local', + // type: 'Ed25519', + // }) + + // const recipientKey = await agent.keyManagerCreateKey({ + // kms: 'local', + // type: 'Ed25519', + // }) + + // const encrypted = await agent.keyManagerEncryptJWE({ + // kid: senderKey.kid, + // to: recipientKey, + // data: message + // }) + + // expect(typeof encrypted).toEqual('string') + + // const decrypted = await agent.keyManagerDecryptJWE({ + // kid: recipientKey.kid, + // data: encrypted + // }) + + // expect(decrypted).toEqual(message) + + // }) }) } diff --git a/docs/api/daf-core.iidentitymanager.identitymanagercreateidentity.md b/docs/api/daf-core.iidentitymanager.identitymanagercreateidentity.md index bd887fc77..b6f7286ec 100644 --- a/docs/api/daf-core.iidentitymanager.identitymanagercreateidentity.md +++ b/docs/api/daf-core.iidentitymanager.identitymanagercreateidentity.md @@ -28,6 +28,7 @@ Promise<[IIdentity](./daf-core.iidentity.md)> ```typescript const identity = await agent.identityManagerCreateIdentity({ + alias: 'alice', provider: 'did:ethr:rinkeby', kms: 'local' }) diff --git a/docs/api/daf-core.iidentitymanager.identitymanagergetidentitybyalias.md b/docs/api/daf-core.iidentitymanager.identitymanagergetidentitybyalias.md new file mode 100644 index 000000000..def18b3b3 --- /dev/null +++ b/docs/api/daf-core.iidentitymanager.identitymanagergetidentitybyalias.md @@ -0,0 +1,35 @@ + + +[Home](./index.md) > [daf-core](./daf-core.md) > [IIdentityManager](./daf-core.iidentitymanager.md) > [identityManagerGetIdentityByAlias](./daf-core.iidentitymanager.identitymanagergetidentitybyalias.md) + +## IIdentityManager.identityManagerGetIdentityByAlias() method + +Returns a specific identity by alias + +Signature: + +```typescript +identityManagerGetIdentityByAlias(args: IIdentityManagerGetIdentityByAliasArgs): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| args | [IIdentityManagerGetIdentityByAliasArgs](./daf-core.iidentitymanagergetidentitybyaliasargs.md) | Required. Arguments to get the identity | + +Returns: + +Promise<[IIdentity](./daf-core.iidentity.md)> + +## Example + + +```typescript +const identity = await agent.identityManagerGetIdentityByAlias({ + alias: 'alice', + provider: 'did:ethr:rinkeby' +}) + +``` + diff --git a/docs/api/daf-core.iidentitymanager.md b/docs/api/daf-core.iidentitymanager.md index aff02a7fb..ffdcedc5f 100644 --- a/docs/api/daf-core.iidentitymanager.md +++ b/docs/api/daf-core.iidentitymanager.md @@ -23,6 +23,7 @@ export interface IIdentityManager extends IPluginMethodMap | [identityManagerDeleteIdentity(args, context)](./daf-core.iidentitymanager.identitymanagerdeleteidentity.md) | Deletes identity | | [identityManagerGetIdentities()](./daf-core.iidentitymanager.identitymanagergetidentities.md) | Returns a list of managed identities | | [identityManagerGetIdentity(args)](./daf-core.iidentitymanager.identitymanagergetidentity.md) | Returns a specific identity | +| [identityManagerGetIdentityByAlias(args)](./daf-core.iidentitymanager.identitymanagergetidentitybyalias.md) | Returns a specific identity by alias | | [identityManagerGetOrCreateIdentity(args, context)](./daf-core.iidentitymanager.identitymanagergetorcreateidentity.md) | Returns an existing identity or creates a new one for a specific alias | | [identityManagerGetProviders()](./daf-core.iidentitymanager.identitymanagergetproviders.md) | Returns a list of available identity providers | | [identityManagerImportIdentity(args)](./daf-core.iidentitymanager.identitymanagerimportidentity.md) | Imports identity | diff --git a/docs/api/daf-core.iidentitymanagergetidentitybyaliasargs.alias.md b/docs/api/daf-core.iidentitymanagergetidentitybyaliasargs.alias.md new file mode 100644 index 000000000..108cd892d --- /dev/null +++ b/docs/api/daf-core.iidentitymanagergetidentitybyaliasargs.alias.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [daf-core](./daf-core.md) > [IIdentityManagerGetIdentityByAliasArgs](./daf-core.iidentitymanagergetidentitybyaliasargs.md) > [alias](./daf-core.iidentitymanagergetidentitybyaliasargs.alias.md) + +## IIdentityManagerGetIdentityByAliasArgs.alias property + +Alias + +Signature: + +```typescript +alias: string; +``` diff --git a/docs/api/daf-core.iidentitymanagergetidentitybyaliasargs.md b/docs/api/daf-core.iidentitymanagergetidentitybyaliasargs.md new file mode 100644 index 000000000..1b33d64f0 --- /dev/null +++ b/docs/api/daf-core.iidentitymanagergetidentitybyaliasargs.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [daf-core](./daf-core.md) > [IIdentityManagerGetIdentityByAliasArgs](./daf-core.iidentitymanagergetidentitybyaliasargs.md) + +## IIdentityManagerGetIdentityByAliasArgs interface + +Input arguments for [identityManagerGetIdentityByAlias](./daf-core.iidentitymanager.identitymanagergetidentitybyalias.md) + +Signature: + +```typescript +export interface IIdentityManagerGetIdentityByAliasArgs +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [alias](./daf-core.iidentitymanagergetidentitybyaliasargs.alias.md) | string | Alias | +| [provider](./daf-core.iidentitymanagergetidentitybyaliasargs.provider.md) | string | Optional provider | + diff --git a/docs/api/daf-core.iidentitymanagergetidentitybyaliasargs.provider.md b/docs/api/daf-core.iidentitymanagergetidentitybyaliasargs.provider.md new file mode 100644 index 000000000..1e3247c6c --- /dev/null +++ b/docs/api/daf-core.iidentitymanagergetidentitybyaliasargs.provider.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [daf-core](./daf-core.md) > [IIdentityManagerGetIdentityByAliasArgs](./daf-core.iidentitymanagergetidentitybyaliasargs.md) > [provider](./daf-core.iidentitymanagergetidentitybyaliasargs.provider.md) + +## IIdentityManagerGetIdentityByAliasArgs.provider property + +Optional provider + +Signature: + +```typescript +provider?: string; +``` diff --git a/docs/api/daf-core.md b/docs/api/daf-core.md index bfd20279b..ff0a46315 100644 --- a/docs/api/daf-core.md +++ b/docs/api/daf-core.md @@ -36,6 +36,7 @@ Provides [Agent](./daf-core.agent.md) implementation and defines [IResolver](./d | [IIdentityManagerCreateIdentityArgs](./daf-core.iidentitymanagercreateidentityargs.md) | Input arguments for [identityManagerCreateIdentity](./daf-core.iidentitymanager.identitymanagercreateidentity.md) | | [IIdentityManagerDeleteIdentityArgs](./daf-core.iidentitymanagerdeleteidentityargs.md) | Input arguments for [identityManagerDeleteIdentity](./daf-core.iidentitymanager.identitymanagerdeleteidentity.md) | | [IIdentityManagerGetIdentityArgs](./daf-core.iidentitymanagergetidentityargs.md) | Input arguments for [identityManagerGetIdentity](./daf-core.iidentitymanager.identitymanagergetidentity.md) | +| [IIdentityManagerGetIdentityByAliasArgs](./daf-core.iidentitymanagergetidentitybyaliasargs.md) | Input arguments for [identityManagerGetIdentityByAlias](./daf-core.iidentitymanager.identitymanagergetidentitybyalias.md) | | [IIdentityManagerGetOrCreateIdentityArgs](./daf-core.iidentitymanagergetorcreateidentityargs.md) | Input arguments for [identityManagerGetOrCreateIdentity](./daf-core.iidentitymanager.identitymanagergetorcreateidentity.md) | | [IIdentityManagerRemoveKeyArgs](./daf-core.iidentitymanagerremovekeyargs.md) | Input arguments for [identityManagerRemoveKey](./daf-core.iidentitymanager.identitymanagerremovekey.md) | | [IIdentityManagerRemoveServiceArgs](./daf-core.iidentitymanagerremoveserviceargs.md) | Input arguments for [identityManagerRemoveService](./daf-core.iidentitymanager.identitymanagerremoveservice.md) | diff --git a/docs/api/daf-graphql.basetypedef.md b/docs/api/daf-graphql.basetypedef.md index 3b61a03e2..f9f359cbf 100644 --- a/docs/api/daf-graphql.basetypedef.md +++ b/docs/api/daf-graphql.basetypedef.md @@ -7,5 +7,5 @@ Signature: ```typescript -baseTypeDef = "\ntype Query\ntype Mutation\n\nscalar KeyMeta\n\ntype Key {\n kid: String!\n kms: String!\n type: String!\n publicKeyHex: String!\n privateKeyHex: String\n meta: KeyMeta\n}\n\ntype Service {\n id: String!\n type: String!\n serviceEndpoint: String!\n description: String\n}\n\ntype Identity {\n did: String!\n provider: String\n alias: String\n keys: [Key]\n services: [Service]\n}\n\nscalar Object\nscalar Date\nscalar VerifiablePresentation\nscalar VerifiableCredential\nscalar Presentation\nscalar Credential\n\ntype Message {\n id: ID!\n createdAt: Date\n expiresAt: Date\n threadId: String\n type: String!\n raw: String\n data: Object\n replyTo: [String]\n replyUrl: String\n from: String\n to: String\n metaData: [MetaData]\n presentations: [VerifiablePresentation]\n credentials: [VerifiableCredential]\n}\n\ntype MetaData {\n type: String!\n value: String\n}\n\n\n" +baseTypeDef = "\ntype Query\ntype Mutation\n\nscalar KeyMeta\n\ntype Key {\n kid: String!\n kms: String!\n type: String!\n publicKeyHex: String!\n privateKeyHex: String\n meta: KeyMeta\n}\n\ntype Service {\n id: String!\n type: String!\n serviceEndpoint: String!\n description: String\n}\n\ntype Identity {\n did: String!\n provider: String\n alias: String\n controllerKeyId: String\n keys: [Key]\n services: [Service]\n}\n\nscalar Object\nscalar Date\nscalar VerifiablePresentation\nscalar VerifiableCredential\nscalar Presentation\nscalar Credential\n\ntype Message {\n id: ID!\n createdAt: Date\n expiresAt: Date\n threadId: String\n type: String!\n raw: String\n data: Object\n replyTo: [String]\n replyUrl: String\n from: String\n to: String\n metaData: [MetaData]\n presentations: [VerifiablePresentation]\n credentials: [VerifiableCredential]\n}\n\ntype MetaData {\n type: String!\n value: String\n}\n\n\n" ``` diff --git a/docs/api/daf-identity-manager.abstractidentitystore.get_1.md b/docs/api/daf-identity-manager.abstractidentitystore.get_1.md index e451ce2c5..abc349fb6 100644 --- a/docs/api/daf-identity-manager.abstractidentitystore.get_1.md +++ b/docs/api/daf-identity-manager.abstractidentitystore.get_1.md @@ -9,6 +9,7 @@ ```typescript abstract get(args: { alias: string; + provider: string; }): Promise; ``` @@ -16,7 +17,7 @@ abstract get(args: { | Parameter | Type | Description | | --- | --- | --- | -| args | { alias: string; } | | +| args | { alias: string; provider: string; } | | Returns: diff --git a/docs/api/daf-identity-manager.identitymanager.identitymanagergetidentitybyalias.md b/docs/api/daf-identity-manager.identitymanager.identitymanagergetidentitybyalias.md new file mode 100644 index 000000000..e26b6cdc2 --- /dev/null +++ b/docs/api/daf-identity-manager.identitymanager.identitymanagergetidentitybyalias.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [daf-identity-manager](./daf-identity-manager.md) > [IdentityManager](./daf-identity-manager.identitymanager.md) > [identityManagerGetIdentityByAlias](./daf-identity-manager.identitymanager.identitymanagergetidentitybyalias.md) + +## IdentityManager.identityManagerGetIdentityByAlias() method + +Returns a specific identity by alias + +Signature: + +```typescript +identityManagerGetIdentityByAlias({ alias, provider }: IIdentityManagerGetIdentityByAliasArgs): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| { alias, provider } | [IIdentityManagerGetIdentityByAliasArgs](./daf-core.iidentitymanagergetidentitybyaliasargs.md) | | + +Returns: + +Promise<[IIdentity](./daf-core.iidentity.md)> + diff --git a/docs/api/daf-identity-manager.identitymanager.md b/docs/api/daf-identity-manager.identitymanager.md index 91078531f..d86bc2605 100644 --- a/docs/api/daf-identity-manager.identitymanager.md +++ b/docs/api/daf-identity-manager.identitymanager.md @@ -35,6 +35,7 @@ export declare class IdentityManager implements IAgentPlugin | [identityManagerDeleteIdentity({ did }, context)](./daf-identity-manager.identitymanager.identitymanagerdeleteidentity.md) | | Deletes identity | | [identityManagerGetIdentities()](./daf-identity-manager.identitymanager.identitymanagergetidentities.md) | | Returns a list of managed identities | | [identityManagerGetIdentity({ did })](./daf-identity-manager.identitymanager.identitymanagergetidentity.md) | | Returns a specific identity | +| [identityManagerGetIdentityByAlias({ alias, provider })](./daf-identity-manager.identitymanager.identitymanagergetidentitybyalias.md) | | Returns a specific identity by alias | | [identityManagerGetOrCreateIdentity({ provider, alias, kms, options }, context)](./daf-identity-manager.identitymanager.identitymanagergetorcreateidentity.md) | | Returns an existing identity or creates a new one for a specific alias | | [identityManagerGetProviders()](./daf-identity-manager.identitymanager.identitymanagergetproviders.md) | | Returns a list of available identity providers | | [identityManagerImportIdentity(identity)](./daf-identity-manager.identitymanager.identitymanagerimportidentity.md) | | Imports identity | diff --git a/docs/api/daf-typeorm.entities.md b/docs/api/daf-typeorm.entities.md index 20b846427..99873d3de 100644 --- a/docs/api/daf-typeorm.entities.md +++ b/docs/api/daf-typeorm.entities.md @@ -7,5 +7,5 @@ Signature: ```typescript -Entities: (typeof Key | typeof Identity | typeof Service | typeof Claim | typeof Credential | typeof Presentation | typeof Message)[] +Entities: (typeof Credential | typeof Identity | typeof Claim | typeof Presentation | typeof Message | typeof Key | typeof Service)[] ``` diff --git a/docs/api/daf-typeorm.identitystore.get.md b/docs/api/daf-typeorm.identitystore.get.md index baeaced6b..7f94e5f90 100644 --- a/docs/api/daf-typeorm.identitystore.get.md +++ b/docs/api/daf-typeorm.identitystore.get.md @@ -7,9 +7,10 @@ Signature: ```typescript -get({ did, alias }: { +get({ did, alias, provider }: { did: string; alias: string; + provider: string; }): Promise; ``` @@ -17,7 +18,7 @@ get({ did, alias }: { | Parameter | Type | Description | | --- | --- | --- | -| { did, alias } | { did: string; alias: string; } | | +| { did, alias, provider } | { did: string; alias: string; provider: string; } | | Returns: diff --git a/docs/api/daf-typeorm.identitystore.md b/docs/api/daf-typeorm.identitystore.md index 2fea8d75d..5733eecb6 100644 --- a/docs/api/daf-typeorm.identitystore.md +++ b/docs/api/daf-typeorm.identitystore.md @@ -22,7 +22,7 @@ export declare class IdentityStore extends AbstractIdentityStore | Method | Modifiers | Description | | --- | --- | --- | | [delete({ did })](./daf-typeorm.identitystore.delete.md) | | | -| [get({ did, alias })](./daf-typeorm.identitystore.get.md) | | | +| [get({ did, alias, provider })](./daf-typeorm.identitystore.get.md) | | | | [import(args)](./daf-typeorm.identitystore.import.md) | | | | [list()](./daf-typeorm.identitystore.list.md) | | | diff --git a/docs/methods.md b/docs/methods.md index 6d65d54e9..2a19df518 100644 --- a/docs/methods.md +++ b/docs/methods.md @@ -49,6 +49,7 @@ Creates and returns a new identity ```typescript const identity = await agent.identityManagerCreateIdentity({ + alias: 'alice', provider: 'did:ethr:rinkeby', kms: 'local' }) @@ -69,6 +70,17 @@ Returns a list of managed identities Returns a specific identity +### [identityManagerGetIdentityByAlias](./api/daf-core.iidentitymanager.identitymanagergetidentitybyalias.md) + +Returns a specific identity by alias + +```typescript +const identity = await agent.identityManagerGetIdentityByAlias({ + alias: 'alice', + provider: 'did:ethr:rinkeby' +}) +``` + ### [identityManagerGetOrCreateIdentity](./api/daf-core.iidentitymanager.identitymanagergetorcreateidentity.md) Returns an existing identity or creates a new one for a specific alias diff --git a/packages/daf-core/src/types.ts b/packages/daf-core/src/types.ts index 6e6d5b85a..61dbf2949 100644 --- a/packages/daf-core/src/types.ts +++ b/packages/daf-core/src/types.ts @@ -379,6 +379,22 @@ export interface IIdentityManagerGetIdentityArgs { did: string } +/** + * Input arguments for {@link IIdentityManager.identityManagerGetIdentityByAlias | identityManagerGetIdentityByAlias} + * @public + */ +export interface IIdentityManagerGetIdentityByAliasArgs { + /** + * Alias + */ + alias: string + + /** + * Optional provider + */ + provider?: string +} + /** * Input arguments for {@link IIdentityManager.identityManagerDeleteIdentity | identityManagerDeleteIdentity} * @public @@ -546,15 +562,32 @@ export interface IIdentityManager extends IPluginMethodMap { */ identityManagerGetIdentity(args: IIdentityManagerGetIdentityArgs): Promise + /** + * Returns a specific identity by alias + * + * @param args - Required. Arguments to get the identity + * @param context - Execution context. Requires `agent` that has {@link daf-core#IKeyManager} methods + * + * @example + * ```typescript + * const identity = await agent.identityManagerGetIdentityByAlias({ + * alias: 'alice', + * provider: 'did:ethr:rinkeby' + * }) + * ``` + */ + identityManagerGetIdentityByAlias(args: IIdentityManagerGetIdentityByAliasArgs): Promise + /** * Creates and returns a new identity * - * @param args - Required. Arguments to create the identity + * @param args - Required. Arguments to create the identity * @param context - Execution context. Requires `agent` that has {@link daf-core#IKeyManager} methods * * @example * ```typescript * const identity = await agent.identityManagerCreateIdentity({ + * alias: 'alice', * provider: 'did:ethr:rinkeby', * kms: 'local' * }) diff --git a/packages/daf-graphql/src/base-type-def.ts b/packages/daf-graphql/src/base-type-def.ts index 7222f612a..0e6ecaadd 100644 --- a/packages/daf-graphql/src/base-type-def.ts +++ b/packages/daf-graphql/src/base-type-def.ts @@ -24,6 +24,7 @@ type Identity { did: String! provider: String alias: String + controllerKeyId: String keys: [Key] services: [Service] } diff --git a/packages/daf-graphql/src/methods/identity-manager.ts b/packages/daf-graphql/src/methods/identity-manager.ts index b8fe6fb3d..76489a7bb 100644 --- a/packages/daf-graphql/src/methods/identity-manager.ts +++ b/packages/daf-graphql/src/methods/identity-manager.ts @@ -22,6 +22,7 @@ export const identityManagerGetIdentities: IAgentGraphQLMethod = { did provider alias + controllerKeyId keys { kid kms @@ -52,6 +53,7 @@ export const identityManagerGetIdentity: IAgentGraphQLMethod = { did provider alias + controllerKeyId keys { kid kms @@ -69,7 +71,38 @@ export const identityManagerGetIdentity: IAgentGraphQLMethod = { `, typeDef: ` extend type Query { - identityManagerGetIdentity(did: String!): Identity + identityManagerGetIdentity(did: String!): Identity! + } + `, +} + +export const identityManagerGetIdentityByAlias: IAgentGraphQLMethod = { + type: 'Query', + query: ` + query identityManagerGetIdentityByAlias($alias: String!, $provider: String) { + identityManagerGetIdentityByAlias(alias: $alias, provider: $provider) { + did + provider + alias + controllerKeyId + keys { + kid + kms + type + publicKeyHex + } + services { + id + type + serviceEndpoint + description + } + } + } + `, + typeDef: ` + extend type Query { + identityManagerGetIdentityByAlias(alias: String!, provider: String): Identity! } `, } @@ -82,6 +115,7 @@ export const identityManagerGetOrCreateIdentity: IAgentGraphQLMethod = { did provider alias + controllerKeyId keys { kid kms @@ -112,6 +146,7 @@ export const identityManagerCreateIdentity: IAgentGraphQLMethod = { did provider alias + controllerKeyId keys { kid kms @@ -173,6 +208,7 @@ export const supportedMethods: Record = { identityManagerGetProviders, identityManagerGetIdentities, identityManagerGetIdentity, + identityManagerGetIdentityByAlias, identityManagerCreateIdentity, identityManagerGetOrCreateIdentity, identityManagerDeleteIdentity, diff --git a/packages/daf-identity-manager/src/abstract-identity-store.ts b/packages/daf-identity-manager/src/abstract-identity-store.ts index 3f7f30d3d..83b49cb19 100644 --- a/packages/daf-identity-manager/src/abstract-identity-store.ts +++ b/packages/daf-identity-manager/src/abstract-identity-store.ts @@ -7,7 +7,7 @@ import { IIdentity } from 'daf-core' export abstract class AbstractIdentityStore { abstract import(args: IIdentity): Promise abstract get(args: { did: string }): Promise - abstract get(args: { alias: string }): Promise + abstract get(args: { alias: string; provider: string }): Promise abstract delete(args: { did: string }): Promise abstract list(): Promise } diff --git a/packages/daf-identity-manager/src/identity-manager.ts b/packages/daf-identity-manager/src/identity-manager.ts index 48c26cb28..3f6b7eacb 100644 --- a/packages/daf-identity-manager/src/identity-manager.ts +++ b/packages/daf-identity-manager/src/identity-manager.ts @@ -7,6 +7,7 @@ import { IKeyManager, IIdentityManagerGetIdentityArgs, IIdentityManagerCreateIdentityArgs, + IIdentityManagerGetIdentityByAliasArgs, IIdentityManagerGetOrCreateIdentityArgs, IIdentityManagerDeleteIdentityArgs, IIdentityManagerAddKeyArgs, @@ -43,6 +44,7 @@ export class IdentityManager implements IAgentPlugin { identityManagerGetProviders: this.identityManagerGetProviders.bind(this), identityManagerGetIdentities: this.identityManagerGetIdentities.bind(this), identityManagerGetIdentity: this.identityManagerGetIdentity.bind(this), + identityManagerGetIdentityByAlias: this.identityManagerGetIdentityByAlias.bind(this), identityManagerCreateIdentity: this.identityManagerCreateIdentity.bind(this), identityManagerGetOrCreateIdentity: this.identityManagerGetOrCreateIdentity.bind(this), identityManagerImportIdentity: this.identityManagerImportIdentity.bind(this), @@ -75,12 +77,30 @@ export class IdentityManager implements IAgentPlugin { return this.store.get({ did }) } + /** {@inheritDoc daf-core#IIdentityManager.identityManagerGetIdentityByAlias} */ + async identityManagerGetIdentityByAlias({ + alias, + provider, + }: IIdentityManagerGetIdentityByAliasArgs): Promise { + const providerName = provider || this.defaultProvider + return this.store.get({ alias, provider: providerName }) + } + /** {@inheritDoc daf-core#IIdentityManager.identityManagerCreateIdentity} */ async identityManagerCreateIdentity( { provider, alias, kms, options }: IIdentityManagerCreateIdentityArgs, context: IAgentContext, ): Promise { const providerName = provider || this.defaultProvider + if (alias !== undefined) { + let existingIdentity + try { + existingIdentity = await this.store.get({ alias, provider: providerName }) + } catch (e) {} + if (existingIdentity) { + throw Error(`Identity with alias: ${alias}, provider: ${providerName} already exists`) + } + } const identityProvider = this.getProvider(providerName) const partialIdentity = await identityProvider.createIdentity({ kms, alias, options }, context) const identity: IIdentity = { ...partialIdentity, alias, provider: providerName } @@ -94,7 +114,8 @@ export class IdentityManager implements IAgentPlugin { context: IAgentContext, ): Promise { try { - const identity = await this.store.get({ alias }) + const providerName = provider || this.defaultProvider + const identity = await this.store.get({ alias, provider: providerName }) return identity } catch { return this.identityManagerCreateIdentity({ provider, alias, kms, options }, context) diff --git a/packages/daf-rest/src/openApiSchema.ts b/packages/daf-rest/src/openApiSchema.ts index 6fcb53188..329ad8cea 100644 --- a/packages/daf-rest/src/openApiSchema.ts +++ b/packages/daf-rest/src/openApiSchema.ts @@ -395,6 +395,24 @@ export const openApiSchema: OpenAPIV3.Document = { "additionalProperties": false, "description": "Input arguments for {@link IIdentityManager.identityManagerGetIdentity | identityManagerGetIdentity}" }, + "IIdentityManagerGetIdentityByAliasArgs": { + "type": "object", + "properties": { + "alias": { + "type": "string", + "description": "Alias" + }, + "provider": { + "type": "string", + "description": "Optional provider" + } + }, + "required": [ + "alias" + ], + "additionalProperties": false, + "description": "Input arguments for {@link IIdentityManager.identityManagerGetIdentityByAlias | identityManagerGetIdentityByAlias}" + }, "IIdentityManagerGetOrCreateIdentityArgs": { "type": "object", "properties": { @@ -2004,6 +2022,33 @@ export const openApiSchema: OpenAPIV3.Document = { } } }, + "/identityManagerGetIdentityByAlias": { + "post": { + "description": "Returns a specific identity by alias", + "operationId": "identityManagerGetIdentityByAlias", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IIdentityManagerGetIdentityByAliasArgs" + } + } + } + }, + "responses": { + "200": { + "description": "Returns a specific identity by alias", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/IIdentity" + } + } + } + } + } + } + }, "/identityManagerGetOrCreateIdentity": { "post": { "description": "Returns an existing identity or creates a new one for a specific alias", diff --git a/packages/daf-typeorm/src/__tests__/entities.test.ts b/packages/daf-typeorm/src/__tests__/entities.test.ts index 647acdf24..726b60ecb 100644 --- a/packages/daf-typeorm/src/__tests__/entities.test.ts +++ b/packages/daf-typeorm/src/__tests__/entities.test.ts @@ -181,4 +181,18 @@ describe('daf-core', () => { expect(fromDb?.id).toEqual(customId) expect(fromDb?.type).toEqual('custom') }) + + it('enforces unique alias/provider for an identity', async () => { + const identity = new Identity() + identity.did = 'did:test:123' + identity.alias = 'test' + identity.provider = 'testProvider' + const id1Result = await identity.save() + + const identity2 = new Identity() + identity2.did = 'did:test:456' + identity2.alias = 'test' + identity2.provider = 'testProvider' + await expect(identity2.save()).rejects.toThrowError() + }) }) diff --git a/packages/daf-typeorm/src/entities/identity.ts b/packages/daf-typeorm/src/entities/identity.ts index 406d6e66b..fe4ea07f4 100644 --- a/packages/daf-typeorm/src/entities/identity.ts +++ b/packages/daf-typeorm/src/entities/identity.ts @@ -7,6 +7,7 @@ import { ManyToMany, CreateDateColumn, UpdateDateColumn, + Index, } from 'typeorm' import { Key } from './key' import { Service } from './service' @@ -17,6 +18,7 @@ import { Claim } from './claim' import { Connection } from 'typeorm' @Entity() +@Index(['alias', 'provider'], { unique: true }) export class Identity extends BaseEntity { @PrimaryColumn() //@ts-ignore diff --git a/packages/daf-typeorm/src/identity/identity-store.ts b/packages/daf-typeorm/src/identity/identity-store.ts index 6cb9e5a9e..7680a18d8 100644 --- a/packages/daf-typeorm/src/identity/identity-store.ts +++ b/packages/daf-typeorm/src/identity/identity-store.ts @@ -13,14 +13,14 @@ export class IdentityStore extends AbstractIdentityStore { super() } - async get({ did, alias }: { did: string; alias: string }): Promise { + async get({ did, alias, provider }: { did: string; alias: string; provider: string }): Promise { let where = {} if (did !== undefined && alias === undefined) { where = { did } - } else if (did === undefined && alias !== undefined) { - where = { alias } + } else if (did === undefined && alias !== undefined && provider !== undefined) { + where = { alias, provider } } else { - throw Error('[daf:typeorm:identity-store] Get requires did or alias') + throw Error('[daf:typeorm:identity-store] Get requires did or (alias and provider)') } const identity = await (await this.dbConnection).getRepository(Identity).findOne({ diff --git a/report/daf-core.api.md b/report/daf-core.api.md index 829304ddb..e06f4c532 100644 --- a/report/daf-core.api.md +++ b/report/daf-core.api.md @@ -85,6 +85,7 @@ export interface IIdentityManager extends IPluginMethodMap { identityManagerDeleteIdentity(args: IIdentityManagerDeleteIdentityArgs, context: IAgentContext): Promise; identityManagerGetIdentities(): Promise>; identityManagerGetIdentity(args: IIdentityManagerGetIdentityArgs): Promise; + identityManagerGetIdentityByAlias(args: IIdentityManagerGetIdentityByAliasArgs): Promise; identityManagerGetOrCreateIdentity(args: IIdentityManagerGetOrCreateIdentityArgs, context: IAgentContext): Promise; identityManagerGetProviders(): Promise>; identityManagerImportIdentity(args: IIdentity): Promise; @@ -124,6 +125,12 @@ export interface IIdentityManagerGetIdentityArgs { did: string; } +// @public +export interface IIdentityManagerGetIdentityByAliasArgs { + alias: string; + provider?: string; +} + // @public export interface IIdentityManagerGetOrCreateIdentityArgs { alias: string; diff --git a/report/daf-graphql.api.md b/report/daf-graphql.api.md index 8928adf00..b645f2df8 100644 --- a/report/daf-graphql.api.md +++ b/report/daf-graphql.api.md @@ -20,7 +20,7 @@ export class AgentGraphQLClient implements IAgentPlugin { } // @public (undocumented) -export const baseTypeDef = "\ntype Query\ntype Mutation\n\nscalar KeyMeta\n\ntype Key {\n kid: String!\n kms: String!\n type: String!\n publicKeyHex: String!\n privateKeyHex: String\n meta: KeyMeta\n}\n\ntype Service {\n id: String!\n type: String!\n serviceEndpoint: String!\n description: String\n}\n\ntype Identity {\n did: String!\n provider: String\n alias: String\n keys: [Key]\n services: [Service]\n}\n\nscalar Object\nscalar Date\nscalar VerifiablePresentation\nscalar VerifiableCredential\nscalar Presentation\nscalar Credential\n\ntype Message {\n id: ID!\n createdAt: Date\n expiresAt: Date\n threadId: String\n type: String!\n raw: String\n data: Object\n replyTo: [String]\n replyUrl: String\n from: String\n to: String\n metaData: [MetaData]\n presentations: [VerifiablePresentation]\n credentials: [VerifiableCredential]\n}\n\ntype MetaData {\n type: String!\n value: String\n}\n\n\n"; +export const baseTypeDef = "\ntype Query\ntype Mutation\n\nscalar KeyMeta\n\ntype Key {\n kid: String!\n kms: String!\n type: String!\n publicKeyHex: String!\n privateKeyHex: String\n meta: KeyMeta\n}\n\ntype Service {\n id: String!\n type: String!\n serviceEndpoint: String!\n description: String\n}\n\ntype Identity {\n did: String!\n provider: String\n alias: String\n controllerKeyId: String\n keys: [Key]\n services: [Service]\n}\n\nscalar Object\nscalar Date\nscalar VerifiablePresentation\nscalar VerifiableCredential\nscalar Presentation\nscalar Credential\n\ntype Message {\n id: ID!\n createdAt: Date\n expiresAt: Date\n threadId: String\n type: String!\n raw: String\n data: Object\n replyTo: [String]\n replyUrl: String\n from: String\n to: String\n metaData: [MetaData]\n presentations: [VerifiablePresentation]\n credentials: [VerifiableCredential]\n}\n\ntype MetaData {\n type: String!\n value: String\n}\n\n\n"; // @public (undocumented) export const createSchema: (options: { diff --git a/report/daf-identity-manager.api.md b/report/daf-identity-manager.api.md index d6d0dd47a..4e984a766 100644 --- a/report/daf-identity-manager.api.md +++ b/report/daf-identity-manager.api.md @@ -13,6 +13,7 @@ import { IIdentityManagerAddServiceArgs } from 'daf-core'; import { IIdentityManagerCreateIdentityArgs } from 'daf-core'; import { IIdentityManagerDeleteIdentityArgs } from 'daf-core'; import { IIdentityManagerGetIdentityArgs } from 'daf-core'; +import { IIdentityManagerGetIdentityByAliasArgs } from 'daf-core'; import { IIdentityManagerGetOrCreateIdentityArgs } from 'daf-core'; import { IIdentityManagerRemoveKeyArgs } from 'daf-core'; import { IIdentityManagerRemoveServiceArgs } from 'daf-core'; @@ -69,6 +70,7 @@ export abstract class AbstractIdentityStore { // (undocumented) abstract get(args: { alias: string; + provider: string; }): Promise; // (undocumented) abstract import(args: IIdentity): Promise; @@ -96,6 +98,8 @@ export class IdentityManager implements IAgentPlugin { // (undocumented) identityManagerGetIdentity({ did }: IIdentityManagerGetIdentityArgs): Promise; // (undocumented) + identityManagerGetIdentityByAlias({ alias, provider }: IIdentityManagerGetIdentityByAliasArgs): Promise; + // (undocumented) identityManagerGetOrCreateIdentity({ provider, alias, kms, options }: IIdentityManagerGetOrCreateIdentityArgs, context: IAgentContext): Promise; // (undocumented) identityManagerGetProviders(): Promise; diff --git a/report/daf-typeorm.api.md b/report/daf-typeorm.api.md index 446745c71..1105c01c6 100644 --- a/report/daf-typeorm.api.md +++ b/report/daf-typeorm.api.md @@ -118,7 +118,7 @@ export class DataStoreORM implements IAgentPlugin { } // @public (undocumented) -export const Entities: (typeof Key | typeof Identity | typeof Service | typeof Claim | typeof Credential_2 | typeof Presentation | typeof Message)[]; +export const Entities: (typeof Credential_2 | typeof Identity | typeof Claim | typeof Presentation | typeof Message | typeof Key | typeof Service)[]; // @public (undocumented) export interface FindArgs { @@ -220,9 +220,10 @@ export class IdentityStore extends AbstractIdentityStore { did: string; }): Promise; // (undocumented) - get({ did, alias }: { + get({ did, alias, provider }: { did: string; alias: string; + provider: string; }): Promise; // (undocumented) import(args: IIdentity): Promise;