UNPKG

@sphereon/ssi-sdk.data-store

Version:

1,542 lines (1,399 loc) • 91.6 kB
import { DataSources } from '@sphereon/ssi-sdk.agent-config' import { ConnectionType, CorrelationIdentifierType, ElectronicAddress, GetElectronicAddressesArgs, GetIdentitiesArgs, GetPartiesArgs, GetPhysicalAddressesArgs, GetRelationshipsArgs, Identity, IdentityOrigin, MetadataItem, MetadataTypes, NaturalPerson, NonPersistedElectronicAddress, NonPersistedIdentity, NonPersistedNaturalPerson, NonPersistedParty, NonPersistedPartyRelationship, NonPersistedPartyType, NonPersistedPhysicalAddress, Party, PartyOrigin, PartyRelationship, PartyType, PartyTypeType, PhysicalAddress, } from '@sphereon/ssi-sdk.data-store-types' import { CredentialRole } from '@sphereon/ssi-types' import { DataSource } from 'typeorm' import { afterEach, beforeEach, describe, expect, it } from 'vitest' import { ContactStore } from '../contact/ContactStore' import { DataStoreEntitiesWithVeramo, DataStoreMigrationsWithVeramo } from '../index' describe('Contact store tests', (): void => { let dbConnection: DataSource let contactStore: ContactStore beforeEach(async (): Promise<void> => { DataSources.singleInstance().defaultDbType = 'sqlite' dbConnection = await new DataSource({ type: 'sqlite', database: ':memory:', logging: ['info'], migrationsRun: false, migrations: DataStoreMigrationsWithVeramo, synchronize: false, entities: DataStoreEntitiesWithVeramo, }).initialize() await dbConnection.runMigrations() expect(await dbConnection.showMigrations()).toBeFalsy() contactStore = new ContactStore(dbConnection) }) afterEach(async (): Promise<void> => { await dbConnection.destroy() }) it('should get party by contact metadata', async (): Promise<void> => { const dateOfBirth = new Date(2016, 0, 5) const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', origin: PartyOrigin.EXTERNAL, }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', metadata: [ { label: 'grade', value: '5th' }, { label: 'dateOfBirth', value: dateOfBirth }, ] as Array<MetadataItem<MetadataTypes>>, displayName: 'example_display_name', }, } const savedParty: Party = await contactStore.addParty(party) expect(savedParty).toBeDefined() const singleResult: Party = await contactStore.getParty({ partyId: savedParty.id }) expect(singleResult).toBeDefined() const args: GetPartiesArgs = { filter: [{ contact: { metadata: { label: 'dateOfBirth', value: dateOfBirth } } }], } const result: Array<Party> = await contactStore.getParties(args) expect(result).toBeDefined() expect(result.length).toEqual(1) expect(result[0]).toBeDefined() }) it('should get a party by identity metadata', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', origin: PartyOrigin.EXTERNAL, }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, } const savedParty: Party = await contactStore.addParty(party) expect(savedParty).toBeDefined() const identity: NonPersistedIdentity = { alias: 'test_alias', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.ISSUER, CredentialRole.VERIFIER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did', }, metadata: [ { label: 'label1', value: 'example_value', }, { label: 'label2', value: 'example_value', }, ], } const savedIdentity: Identity = await contactStore.addIdentity({ partyId: savedParty.id, identity: identity }) expect(savedIdentity).toBeDefined() const args: GetPartiesArgs = { filter: [{ identities: { metadata: { label: 'label1', value: 'example_value' } } }], } const result: Array<Party> = await contactStore.getParties(args) expect(result).toBeDefined() expect(result.length).toEqual(1) expect(result[0]).toBeDefined() }) it('should get party by both contact and identity metadata', async (): Promise<void> => { const example_date = new Date(2016, 0, 5) const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', origin: PartyOrigin.EXTERNAL, }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', metadata: [ { label: 'label1', value: 'example_value' }, { label: 'label2', value: example_date }, ] as Array<MetadataItem<MetadataTypes>>, }, } const savedParty: Party = await contactStore.addParty(party) expect(savedParty).toBeDefined() const identity: NonPersistedIdentity = { alias: 'test_alias', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.ISSUER, CredentialRole.VERIFIER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did', }, metadata: [ { label: 'label3', value: 'example_value', }, { label: 'label4', value: 'example_value', }, ], } const savedIdentity: Identity = await contactStore.addIdentity({ partyId: savedParty.id, identity: identity }) expect(savedIdentity).toBeDefined() const args: GetPartiesArgs = { filter: [ { contact: { metadata: { label: 'label2', value: example_date } }, identities: { metadata: { label: 'label3', value: 'example_value' } }, }, ], } const result: Array<Party> = await contactStore.getParties(args) expect(result).toBeDefined() expect(result.length).toEqual(1) expect(result[0]).toBeDefined() }) it('should get party by id', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, } const savedParty: Party = await contactStore.addParty(party) expect(savedParty).toBeDefined() const result: Party = await contactStore.getParty({ partyId: savedParty.id }) expect(result).toBeDefined() }) it('should throw error when getting party with unknown id', async (): Promise<void> => { const partyId = 'unknownPartyId' await expect(contactStore.getParty({ partyId })).rejects.toThrow(`No party found for id: ${partyId}`) }) it('should get all parties', async (): Promise<void> => { const party1: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name1', }, contact: { firstName: 'example_first_name1', middleName: 'example_middle_name1', lastName: 'example_last_name1', displayName: 'example_display_name1', }, } const savedParty1: Party = await contactStore.addParty(party1) expect(savedParty1).toBeDefined() const party2: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d288', name: 'example_name2', }, contact: { firstName: 'example_first_name2', middleName: 'example_middle_name2', lastName: 'example_last_name2', displayName: 'example_display_name2', }, } const savedParty2: Party = await contactStore.addParty(party2) expect(savedParty2).toBeDefined() const result: Array<Party> = await contactStore.getParties() expect(result).toBeDefined() expect(result.length).toEqual(2) }) it('should get parties by filter', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, } const savedParty: Party = await contactStore.addParty(party) expect(savedParty).toBeDefined() const args: GetPartiesArgs = { filter: [ { contact: { firstName: (<NonPersistedNaturalPerson>party.contact).firstName, }, }, { contact: { middleName: (<NonPersistedNaturalPerson>party.contact).middleName, }, }, { contact: { lastName: (<NonPersistedNaturalPerson>party.contact).lastName, }, }, { contact: { displayName: (<NonPersistedNaturalPerson>party.contact).displayName, }, }, ], } const result: Array<Party> = await contactStore.getParties(args) expect(result.length).toEqual(1) }) it('should get whole parties by filter', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, identities: [ { alias: 'test_alias1', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.ISSUER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did1', }, }, { alias: 'test_alias2', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.VERIFIER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did2', }, }, { alias: 'test_alias3', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.HOLDER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did3', }, }, { alias: 'test_alias4', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.FEDERATION_TRUST_ANCHOR], connection: { type: ConnectionType.OPENID_CONNECT, config: { clientId: '138d7bf8-c930-4c6e-b928-97d3a4928b01', clientSecret: '03b3955f-d020-4f2a-8a27-4e452d4e27a0', scopes: ['auth'], issuer: 'https://example.com/app-test', redirectUrl: 'app:/callback', dangerouslyAllowInsecureHttpRequests: true, clientAuthMethod: <const>'post', }, }, identifier: { type: CorrelationIdentifierType.URL, correlationId: 'example_url4', }, }, ], electronicAddresses: [ { type: 'email', electronicAddress: 'example_electronic_address', }, ], } const savedParty: Party = await contactStore.addParty(party) expect(savedParty).toBeDefined() const args: GetPartiesArgs = { filter: [ { identities: { identifier: { correlationId: 'example_did1', }, }, }, ], } const result: Array<Party> = await contactStore.getParties(args) expect(result[0].identities.length).toEqual(4) expect(result[0].electronicAddresses.length).toEqual(1) }) it('should get parties by name', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'something', }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, } const savedParty: Party = await contactStore.addParty(party) expect(savedParty).toBeDefined() const args: GetPartiesArgs = { filter: [ { contact: { firstName: (<NonPersistedNaturalPerson>party.contact).firstName, }, }, { contact: { middleName: (<NonPersistedNaturalPerson>party.contact).middleName, }, }, { contact: { lastName: (<NonPersistedNaturalPerson>party.contact).lastName, }, }, ], } const result: Array<Party> = await contactStore.getParties(args) expect(result.length).toEqual(1) }) it('should get parties by display name', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, } const savedParty: Party = await contactStore.addParty(party) expect(savedParty).toBeDefined() const args: GetPartiesArgs = { filter: [ { contact: { displayName: (<NonPersistedNaturalPerson>party.contact).displayName, }, }, ], } const result: Array<Party> = await contactStore.getParties(args) expect(result.length).toEqual(1) }) it('should get parties by uri', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, } const savedParty: Party = await contactStore.addParty(party) expect(savedParty).toBeDefined() const args: GetPartiesArgs = { filter: [{ uri: 'example.com' }], } const result: Array<Party> = await contactStore.getParties(args) expect(result.length).toEqual(1) }) it('should return no parties if filter does not match', async (): Promise<void> => { const args: GetPartiesArgs = { filter: [ { contact: { firstName: 'no_match_firstName', }, }, { contact: { middleName: 'no_match_middleName', }, }, { contact: { lastName: 'no_match_lastName', }, }, ], } const result: Array<Party> = await contactStore.getParties(args) expect(result.length).toEqual(0) }) it('should add party without identities', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, } const result: Party = await contactStore.addParty(party) expect(result).toBeDefined() expect((<NaturalPerson>result.contact).firstName).toEqual((<NonPersistedNaturalPerson>party.contact).firstName) expect((<NaturalPerson>result.contact).middleName).toEqual((<NonPersistedNaturalPerson>party.contact).middleName) expect((<NaturalPerson>result.contact).lastName).toEqual((<NonPersistedNaturalPerson>party.contact).lastName) expect(result.identities.length).toEqual(0) }) it('should add party with identities', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, identities: [ { alias: 'test_alias1', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.ISSUER, CredentialRole.VERIFIER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did1', }, }, { alias: 'test_alias2', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.ISSUER, CredentialRole.VERIFIER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did2', }, }, ], } const result: Party = await contactStore.addParty(party) expect(result).toBeDefined() expect((<NaturalPerson>result.contact).firstName).toEqual((<NonPersistedNaturalPerson>party.contact).firstName) expect((<NaturalPerson>result.contact).middleName).toEqual((<NonPersistedNaturalPerson>party.contact).middleName) expect((<NaturalPerson>result.contact).lastName).toEqual((<NonPersistedNaturalPerson>party.contact).lastName) expect(result.identities.length).toEqual(2) }) it('should throw error when adding party with invalid identity', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'something', }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, identities: [ { alias: 'test_alias1', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.ISSUER, CredentialRole.VERIFIER], identifier: { type: CorrelationIdentifierType.URL, correlationId: 'example_did1', }, }, { alias: 'test_alias2', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.ISSUER, CredentialRole.VERIFIER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did2', }, }, ], } await expect(contactStore.addParty(party)).rejects.toThrow(`Identity with correlation type url should contain a connection`) }) it('should update party by id', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, } const savedParty: Party = await contactStore.addParty(party) expect(savedParty).toBeDefined() const identity1: NonPersistedIdentity = { alias: 'test_alias1', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.ISSUER, CredentialRole.VERIFIER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did1', }, } const savedIdentity1: Identity = await contactStore.addIdentity({ partyId: savedParty.id, identity: identity1 }) expect(savedIdentity1).toBeDefined() const identity2: NonPersistedIdentity = { alias: 'test_alias2', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.ISSUER, CredentialRole.VERIFIER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did2', }, } const savedIdentity2: Identity = await contactStore.addIdentity({ partyId: savedParty.id, identity: identity2 }) expect(savedIdentity2).toBeDefined() const contactFirstName = 'updated_first_name' const updatedParty: Party = { ...savedParty, contact: { ...savedParty.contact, firstName: contactFirstName, }, } await contactStore.updateParty({ party: updatedParty }) const result: Party = await contactStore.getParty({ partyId: savedParty.id }) expect(result).toBeDefined() expect((<NaturalPerson>result.contact).firstName).toEqual(contactFirstName) expect(result.identities.length).toEqual(2) }) it('should throw error when updating party with unknown id', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, } const savedParty: Party = await contactStore.addParty(party) expect(savedParty).toBeDefined() const partyId = 'unknownPartyId' const contactFirstName = 'updated_first_name' const updatedParty: Party = { ...savedParty, id: partyId, contact: { ...savedParty.contact, firstName: contactFirstName, }, } await expect(contactStore.updateParty({ party: updatedParty })).rejects.toThrow(`No party found for id: ${partyId}`) }) it('should get identity by id', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, } const savedParty: Party = await contactStore.addParty(party) expect(savedParty).toBeDefined() const identity: NonPersistedIdentity = { alias: 'test_alias', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.ISSUER, CredentialRole.VERIFIER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did', }, } const savedIdentity: Identity = await contactStore.addIdentity({ partyId: savedParty.id, identity }) expect(savedIdentity).toBeDefined() const result: Identity = await contactStore.getIdentity({ identityId: savedIdentity.id }) expect(result).toBeDefined() }) it('should get holderDID identity by id', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, } const savedParty: Party = await contactStore.addParty(party) expect(savedParty).toBeDefined() const identity: NonPersistedIdentity = { alias: 'test_alias', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.HOLDER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did', }, } const savedIdentity: Identity = await contactStore.addIdentity({ partyId: savedParty.id, identity }) expect(savedIdentity).toBeDefined() const result: Identity = await contactStore.getIdentity({ identityId: savedIdentity.id }) expect(result).toBeDefined() }) it('should throw error when getting identity with unknown id', async (): Promise<void> => { const identityId = 'unknownIdentityId' await expect(contactStore.getIdentity({ identityId })).rejects.toThrow(`No identity found for id: ${identityId}`) }) it('should get all identities for contact', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, } const savedParty: Party = await contactStore.addParty(party) expect(savedParty).toBeDefined() const identity1: NonPersistedIdentity = { alias: 'test_alias1', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.ISSUER, CredentialRole.VERIFIER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did1', }, } const savedIdentity1: Identity = await contactStore.addIdentity({ partyId: savedParty.id, identity: identity1 }) expect(savedIdentity1).toBeDefined() const identity2: NonPersistedIdentity = { alias: 'test_alias2', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.ISSUER, CredentialRole.VERIFIER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did2', }, } const savedIdentity2: Identity = await contactStore.addIdentity({ partyId: savedParty.id, identity: identity2 }) expect(savedIdentity2).toBeDefined() const args: GetIdentitiesArgs = { filter: [{ partyId: savedParty.id }], } const result: Array<Identity> = await contactStore.getIdentities(args) expect(result.length).toEqual(2) }) it('should get all identities', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, } const savedParty: Party = await contactStore.addParty(party) expect(savedParty).toBeDefined() const identity1: NonPersistedIdentity = { alias: 'test_alias1', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.ISSUER, CredentialRole.VERIFIER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did1', }, } const savedIdentity1: Identity = await contactStore.addIdentity({ partyId: savedParty.id, identity: identity1 }) expect(savedIdentity1).toBeDefined() const identity2: NonPersistedIdentity = { alias: 'test_alias2', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.ISSUER, CredentialRole.VERIFIER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did2', }, } const savedIdentity2: Identity = await contactStore.addIdentity({ partyId: savedParty.id, identity: identity2 }) expect(savedIdentity2).toBeDefined() const result: Array<Identity> = await contactStore.getIdentities() expect(result.length).toEqual(2) }) it('should get identities by filter', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, } const savedParty: Party = await contactStore.addParty(party) expect(savedParty).toBeDefined() const alias = 'test_alias1' const identity1: NonPersistedIdentity = { alias, origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.ISSUER, CredentialRole.VERIFIER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did1', }, } const savedIdentity1: Identity = await contactStore.addIdentity({ partyId: savedParty.id, identity: identity1 }) expect(savedIdentity1).toBeDefined() const identity2: NonPersistedIdentity = { alias: 'test_alias2', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.ISSUER, CredentialRole.VERIFIER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did2', }, } const savedIdentity2: Identity = await contactStore.addIdentity({ partyId: savedParty.id, identity: identity2 }) expect(savedIdentity2).toBeDefined() const args: GetIdentitiesArgs = { filter: [{ alias }], } const result: Array<Identity> = await contactStore.getIdentities(args) expect(result.length).toEqual(1) }) it('should get whole identities by filter', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, } const savedParty: Party = await contactStore.addParty(party) expect(savedParty).toBeDefined() const alias = 'test_alias1' const identity1: NonPersistedIdentity = { alias, origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.ISSUER, CredentialRole.VERIFIER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did1', }, metadata: [ { label: 'label1', value: 'example_value', }, { label: 'label2', value: 'example_value', }, ], } const savedIdentity1: Identity = await contactStore.addIdentity({ partyId: savedParty.id, identity: identity1 }) expect(savedIdentity1).toBeDefined() const args: GetIdentitiesArgs = { filter: [{ metadata: { label: 'label1', value: 'example_value' } }], } const result: Array<Identity> = await contactStore.getIdentities(args) expect(result[0]).toBeDefined() expect(result[0].metadata!.length).toEqual(2) }) it('should add identity to contact', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, } const savedParty: Party = await contactStore.addParty(party) expect(savedParty).toBeDefined() const identity: NonPersistedIdentity = { alias: 'test_alias', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.ISSUER, CredentialRole.VERIFIER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did', }, } const savedIdentity: Identity = await contactStore.addIdentity({ partyId: savedParty.id, identity }) expect(savedIdentity).toBeDefined() const result: Party = await contactStore.getParty({ partyId: savedParty.id }) expect(result.identities.length).toEqual(1) }) it('should throw error when removing identity with unknown id', async (): Promise<void> => { const identityId = 'unknownIdentityId' await expect(contactStore.removeIdentity({ identityId })).rejects.toThrow(`No identity found for id: ${identityId}`) }) it('should throw error when adding identity with invalid identifier', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, } const savedParty: Party = await contactStore.addParty(party) expect(savedParty).toBeDefined() const correlationId = 'missing_connection_example' const identity: NonPersistedIdentity = { alias: correlationId, origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.ISSUER, CredentialRole.VERIFIER], identifier: { type: CorrelationIdentifierType.URL, correlationId, }, } await expect(contactStore.addIdentity({ partyId: savedParty.id, identity })).rejects.toThrow( `Identity with correlation type url should contain a connection`, ) }) it('should throw error when updating identity with invalid identifier', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, } const savedParty: Party = await contactStore.addParty(party) expect(savedParty).toBeDefined() const correlationId = 'missing_connection_example' const identity: NonPersistedIdentity = { alias: correlationId, origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.ISSUER, CredentialRole.VERIFIER, CredentialRole.HOLDER], identifier: { type: CorrelationIdentifierType.DID, correlationId, }, } const storedIdentity: Identity = await contactStore.addIdentity({ partyId: savedParty.id, identity }) storedIdentity.identifier = { ...storedIdentity.identifier, type: CorrelationIdentifierType.URL } await expect(contactStore.updateIdentity({ identity: storedIdentity })).rejects.toThrow( `Identity with correlation type url should contain a connection`, ) }) it('should update identity by id', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, } const savedParty: Party = await contactStore.addParty(party) expect(savedParty).toBeDefined() const identity: NonPersistedIdentity = { alias: 'example_did', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.ISSUER, CredentialRole.VERIFIER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did', }, } const storedIdentity: Identity = await contactStore.addIdentity({ partyId: savedParty.id, identity }) const correlationId = 'new_update_example_did' storedIdentity.identifier = { ...storedIdentity.identifier, correlationId } await contactStore.updateIdentity({ identity: storedIdentity }) const result: Identity = await contactStore.getIdentity({ identityId: storedIdentity.id }) expect(result).toBeDefined() expect(result.identifier.correlationId).toEqual(correlationId) }) it('should get aggregate of identity roles on party', async (): Promise<void> => { const party: NonPersistedParty = { uri: 'example.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name', }, contact: { firstName: 'example_first_name', middleName: 'example_middle_name', lastName: 'example_last_name', displayName: 'example_display_name', }, identities: [ { alias: 'test_alias1', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.VERIFIER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did1', }, }, { alias: 'test_alias2', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.ISSUER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did2', }, }, { alias: 'test_alias3', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.HOLDER], identifier: { type: CorrelationIdentifierType.DID, correlationId: 'example_did3', }, }, { alias: 'test_alias4', origin: IdentityOrigin.EXTERNAL, roles: [CredentialRole.FEDERATION_TRUST_ANCHOR], connection: { type: ConnectionType.OPENID_CONNECT, config: { clientId: '138d7bf8-c930-4c6e-b928-97d3a4928b01', clientSecret: '03b3955f-d020-4f2a-8a27-4e452d4e27a0', scopes: ['auth'], issuer: 'https://example.com/app-test', redirectUrl: 'app:/callback', dangerouslyAllowInsecureHttpRequests: true, clientAuthMethod: <const>'post', }, }, identifier: { type: CorrelationIdentifierType.URL, correlationId: 'example_url4', }, }, ], } const savedParty: Party = await contactStore.addParty(party) const result: Party = await contactStore.getParty({ partyId: savedParty.id }) expect(result.roles).toBeDefined() expect(result.roles.length).toEqual(4) expect(result.roles).toEqual([CredentialRole.VERIFIER, CredentialRole.ISSUER, CredentialRole.HOLDER, CredentialRole.FEDERATION_TRUST_ANCHOR]) }) it('should add relationship', async (): Promise<void> => { const party1: NonPersistedParty = { uri: 'example1.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name1', }, contact: { firstName: 'example_first_name1', middleName: 'example_middle_name1', lastName: 'example_last_name1', displayName: 'example_display_name1', }, } const savedParty1: Party = await contactStore.addParty(party1) expect(savedParty1).toBeDefined() const party2: NonPersistedParty = { uri: 'example2.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.EXTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d288', name: 'example_name2', }, contact: { firstName: 'example_first_name2', middleName: 'example_middle_name2', lastName: 'example_last_name2', displayName: 'example_display_name2', }, } const savedParty2: Party = await contactStore.addParty(party2) expect(savedParty2).toBeDefined() const relationship: NonPersistedPartyRelationship = { leftId: savedParty1.id, rightId: savedParty2.id, } await contactStore.addRelationship(relationship) const result: Party = await contactStore.getParty({ partyId: savedParty1.id }) expect(result).toBeDefined() expect(result.relationships.length).toEqual(1) expect(result.relationships[0].leftId).toEqual(savedParty1.id) expect(result.relationships[0].rightId).toEqual(savedParty2.id) }) it('should get relationship', async (): Promise<void> => { const party1: NonPersistedParty = { uri: 'example1.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name1', }, contact: { firstName: 'example_first_name1', middleName: 'example_middle_name1', lastName: 'example_last_name1', displayName: 'example_display_name1', }, } const savedParty1: Party = await contactStore.addParty(party1) expect(savedParty1).toBeDefined() const party2: NonPersistedParty = { uri: 'example2.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d288', name: 'example_name2', }, contact: { firstName: 'example_first_name2', middleName: 'example_middle_name2', lastName: 'example_last_name2', displayName: 'example_display_name2', }, } const savedParty2: Party = await contactStore.addParty(party2) expect(savedParty2).toBeDefined() const relationship: NonPersistedPartyRelationship = { leftId: savedParty1.id, rightId: savedParty2.id, } const savedRelationship: PartyRelationship = await contactStore.addRelationship(relationship) const result: PartyRelationship = await contactStore.getRelationship({ relationshipId: savedRelationship.id }) expect(result).toBeDefined() expect(result.leftId).toEqual(savedParty1.id) expect(result.rightId).toEqual(savedParty2.id) }) it('should throw error when getting relationship with unknown id', async (): Promise<void> => { const relationshipId = 'unknownRelationshipId' await expect(contactStore.getRelationship({ relationshipId })).rejects.toThrow(`No relationship found for id: ${relationshipId}`) }) it('should get all relationships', async (): Promise<void> => { const party1: NonPersistedParty = { uri: 'example1.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name1', }, contact: { firstName: 'example_first_name1', middleName: 'example_middle_name1', lastName: 'example_last_name1', displayName: 'example_display_name1', }, } const savedParty1: Party = await contactStore.addParty(party1) expect(savedParty1).toBeDefined() const party2: NonPersistedParty = { uri: 'example2.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d288', name: 'example_name2', }, contact: { firstName: 'example_first_name2', middleName: 'example_middle_name2', lastName: 'example_last_name2', displayName: 'example_display_name2', }, } const savedParty2: Party = await contactStore.addParty(party2) expect(savedParty2).toBeDefined() const relationship1: NonPersistedPartyRelationship = { leftId: savedParty1.id, rightId: savedParty2.id, } await contactStore.addRelationship(relationship1) const relationship2: NonPersistedPartyRelationship = { leftId: savedParty2.id, rightId: savedParty1.id, } await contactStore.addRelationship(relationship2) const result: Array<PartyRelationship> = await contactStore.getRelationships() expect(result).toBeDefined() expect(result.length).toEqual(2) }) it('should get relationships by filter', async (): Promise<void> => { const party1: NonPersistedParty = { uri: 'example1.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name1', }, contact: { firstName: 'example_first_name1', middleName: 'example_middle_name1', lastName: 'example_last_name1', displayName: 'example_display_name1', }, } const savedParty1: Party = await contactStore.addParty(party1) expect(savedParty1).toBeDefined() const party2: NonPersistedParty = { uri: 'example2.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d288', name: 'example_name2', }, contact: { firstName: 'example_first_name2', middleName: 'example_middle_name2', lastName: 'example_last_name2', displayName: 'example_display_name2', }, } const savedParty2: Party = await contactStore.addParty(party2) expect(savedParty2).toBeDefined() const relationship1: NonPersistedPartyRelationship = { leftId: savedParty1.id, rightId: savedParty2.id, } await contactStore.addRelationship(relationship1) const relationship2: NonPersistedPartyRelationship = { leftId: savedParty2.id, rightId: savedParty1.id, } await contactStore.addRelationship(relationship2) const args: GetRelationshipsArgs = { filter: [ { leftId: savedParty1.id, rightId: savedParty2.id, }, ], } const result: Array<PartyRelationship> = await contactStore.getRelationships(args) expect(result).toBeDefined() expect(result.length).toEqual(1) }) it('should remove relationship', async (): Promise<void> => { const party1: NonPersistedParty = { uri: 'example1.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.INTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d289', name: 'example_name1', }, contact: { firstName: 'example_first_name1', middleName: 'example_middle_name1', lastName: 'example_last_name1', displayName: 'example_display_name1', }, } const savedParty1: Party = await contactStore.addParty(party1) expect(savedParty1).toBeDefined() const party2: NonPersistedParty = { uri: 'example2.com', partyType: { type: PartyTypeType.NATURAL_PERSON, origin: PartyOrigin.EXTERNAL, tenantId: '0605761c-4113-4ce5-a6b2-9cbae2f9d288', name: 'example_name2', }, contact: { firstName: 'example_first_name2', middleName: 'example_middle_name2', lastName: 'example_last_name2', displayName: 'example_display_name2', }, } const savedParty2: Party = await contactStore.addParty(party2) expect(savedParty2).toBeDefined() const relationship: NonPersistedPartyRelationship = { leftId: savedParty1.id, rightId: savedParty2.id, } const savedRelationship: PartyRelationship = await contactStore.addRelationship(relationship) expect(savedRelationship).toBeDefined() await contactStore.removeRelationship({ relationshipId: savedRelationship.id }) const result: