Skip to content
Snippets Groups Projects
Verified Commit a349fc5c authored by Konstantin Tsabolov's avatar Konstantin Tsabolov
Browse files

Merge branch 'main' of https://gitlab.eclipse.org/eclipse/xfsc/ocm/ocm-engine...

Merge branch 'main' of https://gitlab.eclipse.org/eclipse/xfsc/ocm/ocm-engine into ssi-credential-functionality
parents b9ca73c8 ebb39da2
No related branches found
No related tags found
No related merge requests found
Showing
with 651 additions and 82 deletions
import type { BaseEventInput } from './baseEvents.js'; import type { BaseEventInput } from './baseEvents.js';
import type { CredentialExchangeRecord } from '@aries-framework/core';
import {
CredentialExchangeRecord,
JsonTransformer,
} from '@aries-framework/core';
import { BaseEvent } from './baseEvents.js'; import { BaseEvent } from './baseEvents.js';
...@@ -11,7 +15,9 @@ export class EventAnonCredsCredentialOfferGetAll extends BaseEvent< ...@@ -11,7 +15,9 @@ export class EventAnonCredsCredentialOfferGetAll extends BaseEvent<
public static token = 'anoncreds.credentialOffers.getAll'; public static token = 'anoncreds.credentialOffers.getAll';
public get instance() { public get instance() {
return this.data; return this.data.map((d) =>
JsonTransformer.fromJSON(d, CredentialExchangeRecord),
);
} }
public static fromEvent(e: EventAnonCredsCredentialOfferGetAll) { public static fromEvent(e: EventAnonCredsCredentialOfferGetAll) {
...@@ -33,7 +39,9 @@ export class EventAnonCredsCredentialOfferGetById extends BaseEvent<CredentialEx ...@@ -33,7 +39,9 @@ export class EventAnonCredsCredentialOfferGetById extends BaseEvent<CredentialEx
public static token = 'anoncreds.credentialOffers.getById'; public static token = 'anoncreds.credentialOffers.getById';
public get instance() { public get instance() {
return this.data; return this.data
? JsonTransformer.fromJSON(this.data, CredentialExchangeRecord)
: null;
} }
public static fromEvent(e: EventAnonCredsCredentialOfferGetById) { public static fromEvent(e: EventAnonCredsCredentialOfferGetById) {
......
import type { BaseEventInput } from './baseEvents.js'; import type { BaseEventInput } from './baseEvents.js';
import type { CredentialExchangeRecord } from '@aries-framework/core';
import {
CredentialExchangeRecord,
JsonTransformer,
} from '@aries-framework/core';
import { BaseEvent } from './baseEvents.js'; import { BaseEvent } from './baseEvents.js';
...@@ -11,7 +15,9 @@ export class EventAnonCredsCredentialRequestGetAll extends BaseEvent< ...@@ -11,7 +15,9 @@ export class EventAnonCredsCredentialRequestGetAll extends BaseEvent<
public static token = 'anoncreds.credentialRequests.getAll'; public static token = 'anoncreds.credentialRequests.getAll';
public get instance() { public get instance() {
return this.data; return this.data.map((d) =>
JsonTransformer.fromJSON(d, CredentialExchangeRecord),
);
} }
public static fromEvent(e: EventAnonCredsCredentialRequestGetAll) { public static fromEvent(e: EventAnonCredsCredentialRequestGetAll) {
...@@ -33,7 +39,9 @@ export class EventAnonCredsCredentialRequestGetById extends BaseEvent<Credential ...@@ -33,7 +39,9 @@ export class EventAnonCredsCredentialRequestGetById extends BaseEvent<Credential
public static token = 'anoncreds.credentialRequests.getById'; public static token = 'anoncreds.credentialRequests.getById';
public get instance() { public get instance() {
return this.data; return this.data
? JsonTransformer.fromJSON(this.data, CredentialExchangeRecord)
: null;
} }
public static fromEvent(e: EventAnonCredsCredentialRequestGetById) { public static fromEvent(e: EventAnonCredsCredentialRequestGetById) {
......
...@@ -19,6 +19,11 @@ export class EventDidsResolve extends BaseEvent<DidDocument> { ...@@ -19,6 +19,11 @@ export class EventDidsResolve extends BaseEvent<DidDocument> {
export type EventDidsRegisterIndyFromSeedInput = BaseEventInput<{ export type EventDidsRegisterIndyFromSeedInput = BaseEventInput<{
seed: string; seed: string;
services?: Array<{
identifier: string;
url: string;
type: string;
}>;
}>; }>;
export class EventDidsRegisterIndyFromSeed extends BaseEvent<Array<string>> { export class EventDidsRegisterIndyFromSeed extends BaseEvent<Array<string>> {
public static token = 'dids.register.indy.fromSeed'; public static token = 'dids.register.indy.fromSeed';
......
import type { BaseEventInput } from './baseEvents.js';
import type {
AnonCredsPredicateType,
AnonCredsProofRequestRestriction,
} from '@aries-framework/anoncreds';
import { JsonTransformer, ProofExchangeRecord } from '@aries-framework/core';
import { BaseEvent } from './baseEvents.js';
export type EventAnonCredsProofsGetAllInput = BaseEventInput;
export class EventAnonCredsProofsGetAll extends BaseEvent<
Array<ProofExchangeRecord>
> {
public static token = 'anoncreds.proofs.getAll';
public get instance() {
return this.data.map((d) =>
JsonTransformer.fromJSON(d, ProofExchangeRecord),
);
}
public static fromEvent(e: EventAnonCredsProofsGetAll) {
return new EventAnonCredsProofsGetAll(
e.data,
e.tenantId,
e.id,
e.type,
e.timestamp,
);
}
}
export type EventAnonCredsProofsGetByIdInput = BaseEventInput<{
proofRecordId: string;
}>;
export class EventAnonCredsProofsGetById extends BaseEvent<ProofExchangeRecord | null> {
public static token = 'anoncreds.proofs.getById';
public get instance() {
return this.data
? JsonTransformer.fromJSON(this.data, ProofExchangeRecord)
: this.data;
}
public static fromEvent(e: EventAnonCredsProofsGetById) {
return new EventAnonCredsProofsGetById(
e.data,
e.tenantId,
e.id,
e.type,
e.timestamp,
);
}
}
export type EventDidcommAnonCredsProofsRequestInput = BaseEventInput<{
connectionId: string;
name: string;
requestedAttributes: {
[groupName: string]: {
names: Array<string>;
restrictions?: Array<AnonCredsProofRequestRestriction>;
};
};
requestedPredicates: {
[groupName: string]: {
name: string;
predicateType: AnonCredsPredicateType;
predicateValue: number;
restrictions?: Array<AnonCredsProofRequestRestriction>;
};
};
}>;
export class EventDidcommAnonCredsProofsRequest extends BaseEvent<ProofExchangeRecord> {
public static token = 'didcomm.anoncreds.proofs.request';
public get instance() {
return JsonTransformer.fromJSON(this.data, ProofExchangeRecord);
}
public static fromEvent(e: EventDidcommAnonCredsProofsRequest) {
return new EventDidcommAnonCredsProofsRequest(
e.data,
e.tenantId,
e.id,
e.type,
e.timestamp,
);
}
}
export type EventAnonCredsProofsDeleteByIdInput = BaseEventInput<{
proofRecordId: string;
}>;
export class EventAnonCredsProofsDeleteById extends BaseEvent {
public static token = 'anoncreds.proofs.deleteById';
public static fromEvent(e: EventDidcommAnonCredsProofsRequest) {
return new EventDidcommAnonCredsProofsRequest(
e.data,
e.tenantId,
e.id,
e.type,
e.timestamp,
);
}
}
...@@ -12,6 +12,7 @@ export * from './events/credentialDefinitionEvents.js'; ...@@ -12,6 +12,7 @@ export * from './events/credentialDefinitionEvents.js';
export * from './events/credentialEvents.js'; export * from './events/credentialEvents.js';
export * from './events/credentialOfferEvents.js'; export * from './events/credentialOfferEvents.js';
export * from './events/credentialRequestEvents.js'; export * from './events/credentialRequestEvents.js';
export * from './events/proofEvents.js';
export * from './dto/pagination-params.dto.js'; export * from './dto/pagination-params.dto.js';
export * from './dto/multitenancy-params.dto.js'; export * from './dto/multitenancy-params.dto.js';
......
...@@ -6,7 +6,9 @@ import type { OnApplicationShutdown } from '@nestjs/common'; ...@@ -6,7 +6,9 @@ import type { OnApplicationShutdown } from '@nestjs/common';
import { import {
AnonCredsCredentialFormatService, AnonCredsCredentialFormatService,
AnonCredsModule, AnonCredsModule,
AnonCredsProofFormatService,
LegacyIndyCredentialFormatService, LegacyIndyCredentialFormatService,
LegacyIndyProofFormatService,
} from '@aries-framework/anoncreds'; } from '@aries-framework/anoncreds';
import { AnonCredsRsModule } from '@aries-framework/anoncreds-rs'; import { AnonCredsRsModule } from '@aries-framework/anoncreds-rs';
import { AskarModule } from '@aries-framework/askar'; import { AskarModule } from '@aries-framework/askar';
...@@ -23,11 +25,14 @@ import { ...@@ -23,11 +25,14 @@ import {
LogLevel, LogLevel,
PeerDidRegistrar, PeerDidRegistrar,
PeerDidResolver, PeerDidResolver,
ProofsModule,
V2CredentialProtocol, V2CredentialProtocol,
V2ProofProtocol,
WebDidResolver, WebDidResolver,
} from '@aries-framework/core'; } from '@aries-framework/core';
import { import {
IndyVdrAnonCredsRegistry, IndyVdrAnonCredsRegistry,
IndyVdrIndyDidRegistrar,
IndyVdrIndyDidResolver, IndyVdrIndyDidResolver,
IndyVdrModule, IndyVdrModule,
IndyVdrSovDidResolver, IndyVdrSovDidResolver,
...@@ -90,13 +95,14 @@ export class AgentService implements OnApplicationShutdown { ...@@ -90,13 +95,14 @@ export class AgentService implements OnApplicationShutdown {
} }
public get modules() { public get modules() {
const { autoAcceptConnection, autoAcceptCredential } = const { autoAcceptConnection, autoAcceptCredential, autoAcceptProof } =
this.configService.get('agent'); this.configService.get('agent');
return { return {
connections: new ConnectionsModule({ connections: new ConnectionsModule({
autoAcceptConnections: autoAcceptConnection, autoAcceptConnections: autoAcceptConnection,
}), }),
credentials: new CredentialsModule({ credentials: new CredentialsModule({
autoAcceptCredentials: autoAcceptCredential, autoAcceptCredentials: autoAcceptCredential,
credentialProtocols: [ credentialProtocols: [
...@@ -109,6 +115,18 @@ export class AgentService implements OnApplicationShutdown { ...@@ -109,6 +115,18 @@ export class AgentService implements OnApplicationShutdown {
], ],
}), }),
proofs: new ProofsModule({
autoAcceptProofs: autoAcceptProof,
proofProtocols: [
new V2ProofProtocol({
proofFormats: [
new AnonCredsProofFormatService(),
new LegacyIndyProofFormatService(),
],
}),
],
}),
anoncredsRs: new AnonCredsRsModule({ anoncreds }), anoncredsRs: new AnonCredsRsModule({ anoncreds }),
anoncreds: new AnonCredsModule({ anoncreds: new AnonCredsModule({
registries: [new IndyVdrAnonCredsRegistry()], registries: [new IndyVdrAnonCredsRegistry()],
...@@ -128,6 +146,7 @@ export class AgentService implements OnApplicationShutdown { ...@@ -128,6 +146,7 @@ export class AgentService implements OnApplicationShutdown {
new PeerDidRegistrar(), new PeerDidRegistrar(),
new KeyDidRegistrar(), new KeyDidRegistrar(),
new JwkDidRegistrar(), new JwkDidRegistrar(),
new IndyVdrIndyDidRegistrar()
], ],
}), }),
......
import { Controller } from '@nestjs/common'; import { Controller } from '@nestjs/common';
import { MessagePattern } from '@nestjs/microservices'; import { MessagePattern } from '@nestjs/microservices';
import { import {
EventAnonCredsCredentialOfferGetById,
EventAnonCredsCredentialOfferGetByIdInput,
EventAnonCredsCredentialRequestGetById,
EventAnonCredsCredentialRequestGetByIdInput,
EventAnonCredsCredentialsDeleteById,
EventAnonCredsCredentialsDeleteByIdInput,
EventAnonCredsCredentialsGetAll, EventAnonCredsCredentialsGetAll,
EventAnonCredsCredentialsGetAllInput, EventAnonCredsCredentialsGetAllInput,
EventAnonCredsCredentialsGetById, EventAnonCredsCredentialsGetById,
EventAnonCredsCredentialsGetByIdInput, EventAnonCredsCredentialsGetByIdInput,
EventDidcommAnonCredsCredentialsOffer, EventDidcommAnonCredsCredentialsOffer,
EventDidcommAnonCredsCredentialsOfferInput, EventDidcommAnonCredsCredentialsOfferInput,
EventDidcommAnonCredsCredentialsOfferToSelfInput,
EventDidcommAnonCredsCredentialsOfferToSelf, EventDidcommAnonCredsCredentialsOfferToSelf,
EventAnonCredsCredentialOfferGetAll, EventDidcommAnonCredsCredentialsOfferToSelfInput
EventAnonCredsCredentialOfferGetAllInput,
EventAnonCredsCredentialRequestGetAll,
EventAnonCredsCredentialRequestGetAllInput,
EventAnonCredsCredentialsDeleteById,
EventAnonCredsCredentialsDeleteByIdInput,
EventAnonCredsCredentialOfferGetById,
EventAnonCredsCredentialOfferGetByIdInput,
EventAnonCredsCredentialRequestGetById,
EventAnonCredsCredentialRequestGetByIdInput,
} from '@ocm/shared'; } from '@ocm/shared';
import { AnonCredsCredentialsService } from './anoncredsCredentials.service.js'; import { AnonCredsCredentialsService } from './anoncredsCredentials.service.js';
...@@ -37,26 +33,6 @@ export class AnonCredsCredentialsController { ...@@ -37,26 +33,6 @@ export class AnonCredsCredentialsController {
); );
} }
@MessagePattern(EventAnonCredsCredentialOfferGetAll.token)
public async getAllOffers(
options: EventAnonCredsCredentialOfferGetAllInput,
): Promise<EventAnonCredsCredentialOfferGetAll> {
return new EventAnonCredsCredentialOfferGetAll(
await this.credentialsService.getAllOffers(options),
options.tenantId,
);
}
@MessagePattern(EventAnonCredsCredentialRequestGetAll.token)
public async getAllRequests(
options: EventAnonCredsCredentialRequestGetAllInput,
): Promise<EventAnonCredsCredentialRequestGetAll> {
return new EventAnonCredsCredentialRequestGetAll(
await this.credentialsService.getAllRequests(options),
options.tenantId,
);
}
@MessagePattern(EventAnonCredsCredentialsGetById.token) @MessagePattern(EventAnonCredsCredentialsGetById.token)
public async getById( public async getById(
options: EventAnonCredsCredentialsGetByIdInput, options: EventAnonCredsCredentialsGetByIdInput,
......
import type { CredentialExchangeRecord} from '@aries-framework/core';
import type { import type {
EventAnonCredsCredentialRequestGetByIdInput, EventAnonCredsCredentialOfferGetAll,
EventAnonCredsCredentialOfferGetAllInput, EventAnonCredsCredentialOfferGetAllInput,
EventAnonCredsCredentialOfferGetById, EventAnonCredsCredentialOfferGetById,
EventAnonCredsCredentialOfferGetByIdInput, EventAnonCredsCredentialOfferGetByIdInput,
EventAnonCredsCredentialRequestGetAll,
EventAnonCredsCredentialRequestGetAllInput, EventAnonCredsCredentialRequestGetAllInput,
EventAnonCredsCredentialRequestGetById,
EventAnonCredsCredentialRequestGetByIdInput,
EventAnonCredsCredentialsDeleteById,
EventAnonCredsCredentialsDeleteByIdInput,
EventAnonCredsCredentialsGetAllInput, EventAnonCredsCredentialsGetAllInput,
EventAnonCredsCredentialsGetByIdInput, EventAnonCredsCredentialsGetByIdInput,
EventDidcommAnonCredsCredentialsOfferInput,
EventDidcommAnonCredsCredentialsOfferToSelfInput,
EventAnonCredsCredentialRequestGetById,
EventDidcommAnonCredsCredentialsOffer, EventDidcommAnonCredsCredentialsOffer,
EventDidcommAnonCredsCredentialsOfferInput,
EventDidcommAnonCredsCredentialsOfferToSelf, EventDidcommAnonCredsCredentialsOfferToSelf,
EventAnonCredsCredentialsGetById, EventDidcommAnonCredsCredentialsOfferToSelfInput
EventAnonCredsCredentialRequestGetAll,
EventAnonCredsCredentialOfferGetAll,
EventAnonCredsCredentialsGetAll,
EventAnonCredsCredentialsDeleteByIdInput,
EventAnonCredsCredentialsDeleteById,
} from '@ocm/shared'; } from '@ocm/shared';
import { AutoAcceptCredential, CredentialState } from '@aries-framework/core'; import { AutoAcceptCredential, CredentialState } from '@aries-framework/core';
...@@ -33,7 +32,7 @@ export class AnonCredsCredentialsService { ...@@ -33,7 +32,7 @@ export class AnonCredsCredentialsService {
public async getAll({ public async getAll({
tenantId, tenantId,
}: EventAnonCredsCredentialsGetAllInput): Promise< }: EventAnonCredsCredentialsGetAllInput): Promise<
EventAnonCredsCredentialsGetAll['data'] Array<CredentialExchangeRecord>
> { > {
return this.withTenantService.invoke(tenantId, (t) => return this.withTenantService.invoke(tenantId, (t) =>
t.credentials.getAll(), t.credentials.getAll(),
...@@ -85,9 +84,7 @@ export class AnonCredsCredentialsService { ...@@ -85,9 +84,7 @@ export class AnonCredsCredentialsService {
public async getById({ public async getById({
tenantId, tenantId,
credentialRecordId, credentialRecordId,
}: EventAnonCredsCredentialsGetByIdInput): Promise< }: EventAnonCredsCredentialsGetByIdInput): Promise<CredentialExchangeRecord | null> {
EventAnonCredsCredentialsGetById['data']
> {
return this.withTenantService.invoke(tenantId, (t) => return this.withTenantService.invoke(tenantId, (t) =>
t.credentials.findById(credentialRecordId), t.credentials.findById(credentialRecordId),
); );
......
import { ProofExchangeRecord, ProofState } from '@aries-framework/core';
import { Test } from '@nestjs/testing';
import { mockConfigModule } from '../../../config/__tests__/mockConfig.js';
import { AgentModule } from '../../agent.module.js';
import { AnonCredsProofsController } from '../anoncredsProofs.controller.js';
import { AnonCredsProofsService } from '../anoncredsProofs.service.js';
describe('AnonCredsProofsController', () => {
let proofsController: AnonCredsProofsController;
let proofsService: AnonCredsProofsService;
beforeEach(async () => {
const moduleRef = await Test.createTestingModule({
imports: [mockConfigModule(), AgentModule],
controllers: [AnonCredsProofsController],
providers: [AnonCredsProofsService],
}).compile();
proofsService = moduleRef.get(AnonCredsProofsService);
proofsController = moduleRef.get(AnonCredsProofsController);
});
it('get all', async () => {
const result: Array<ProofExchangeRecord> = [];
jest.spyOn(proofsService, 'getAll').mockResolvedValue(result);
const event = await proofsController.getAll({
tenantId: 'some-id',
});
expect(event.data).toStrictEqual(result);
});
it('get by id', async () => {
const result: ProofExchangeRecord | null = null;
jest.spyOn(proofsService, 'getById').mockResolvedValue(result);
const event = await proofsController.getById({
tenantId: 'some-id',
proofRecordId: 'some-id',
});
expect(event.data).toStrictEqual(result);
});
it('request', async () => {
const result = new ProofExchangeRecord({
state: ProofState.Done,
threadId: 'some-id',
protocolVersion: 'v2',
});
jest.spyOn(proofsService, 'request').mockResolvedValue(result);
const event = await proofsController.request({
tenantId: 'some-id',
connectionId: 'some-id',
name: 'My New Proof Request',
requestedAttributes: {
identity: {
names: ['name'],
restrictions: [{ issuer_id: 'did:web:government.org' }],
},
},
requestedPredicates: {
'age > 18': {
name: 'age',
restrictions: [{ issuer_id: 'did:web:government.org' }],
predicateType: '>',
predicateValue: 18,
},
},
});
expect(event.data).toStrictEqual(result);
});
});
import { Controller } from '@nestjs/common';
import { MessagePattern } from '@nestjs/microservices';
import {
EventAnonCredsProofsDeleteById,
EventAnonCredsProofsDeleteByIdInput,
EventAnonCredsProofsGetAll,
EventAnonCredsProofsGetAllInput,
EventAnonCredsProofsGetById,
EventAnonCredsProofsGetByIdInput,
EventDidcommAnonCredsProofsRequest,
EventDidcommAnonCredsProofsRequestInput,
} from '@ocm/shared';
import { AnonCredsProofsService } from './anoncredsProofs.service.js';
@Controller('anoncredsProofs')
export class AnonCredsProofsController {
public constructor(private proofsService: AnonCredsProofsService) {}
@MessagePattern(EventAnonCredsProofsGetAll.token)
public async getAll(
options: EventAnonCredsProofsGetAllInput,
): Promise<EventAnonCredsProofsGetAll> {
return new EventAnonCredsProofsGetAll(
await this.proofsService.getAll(options),
options.tenantId,
);
}
@MessagePattern(EventAnonCredsProofsGetById.token)
public async getById(
options: EventAnonCredsProofsGetByIdInput,
): Promise<EventAnonCredsProofsGetById> {
return new EventAnonCredsProofsGetById(
await this.proofsService.getById(options),
options.tenantId,
);
}
@MessagePattern(EventAnonCredsProofsDeleteById.token)
public async deleteById(
options: EventAnonCredsProofsDeleteByIdInput,
): Promise<EventAnonCredsProofsDeleteById> {
return new EventAnonCredsProofsDeleteById(
await this.proofsService.deleteById(options),
options.tenantId,
);
}
@MessagePattern(EventDidcommAnonCredsProofsRequest.token)
public async request(
options: EventDidcommAnonCredsProofsRequestInput,
): Promise<EventDidcommAnonCredsProofsRequest> {
return new EventDidcommAnonCredsProofsRequest(
await this.proofsService.request(options),
options.tenantId,
);
}
}
import { Module } from '@nestjs/common';
import { AgentModule } from '../agent.module.js';
import { AnonCredsProofsController } from './anoncredsProofs.controller.js';
import { AnonCredsProofsService } from './anoncredsProofs.service.js';
@Module({
imports: [AgentModule],
providers: [AnonCredsProofsService],
controllers: [AnonCredsProofsController],
})
export class AnonCredsProofsModule {}
import type {
EventAnonCredsProofsDeleteById,
EventAnonCredsProofsDeleteByIdInput,
EventAnonCredsProofsGetAll,
EventAnonCredsProofsGetAllInput,
EventAnonCredsProofsGetById,
EventAnonCredsProofsGetByIdInput,
EventDidcommAnonCredsProofsRequest,
EventDidcommAnonCredsProofsRequestInput,
} from '@ocm/shared';
import { Injectable } from '@nestjs/common';
import { WithTenantService } from '../withTenantService.js';
@Injectable()
export class AnonCredsProofsService {
public constructor(private withTenantService: WithTenantService) {}
public async getAll({
tenantId,
}: EventAnonCredsProofsGetAllInput): Promise<
EventAnonCredsProofsGetAll['data']
> {
return this.withTenantService.invoke(tenantId, (t) => t.proofs.getAll());
}
public async getById({
tenantId,
proofRecordId,
}: EventAnonCredsProofsGetByIdInput): Promise<
EventAnonCredsProofsGetById['data']
> {
return this.withTenantService.invoke(tenantId, (t) =>
t.proofs.findById(proofRecordId),
);
}
public async deleteById({
tenantId,
proofRecordId,
}: EventAnonCredsProofsDeleteByIdInput): Promise<
EventAnonCredsProofsDeleteById['data']
> {
return this.withTenantService.invoke(tenantId, async (t) => {
await t.proofs.deleteById(proofRecordId);
return {};
});
}
public async request({
tenantId,
connectionId,
name,
requestedAttributes,
requestedPredicates,
}: EventDidcommAnonCredsProofsRequestInput): Promise<
EventDidcommAnonCredsProofsRequest['data']
> {
const transformedPredicates = Object.entries(requestedPredicates).reduce(
(prev, [key, value]) => ({
...prev,
[key]: {
name: value.name,
restrictions: value.restrictions,
p_type: value.predicateType,
p_value: value.predicateValue,
},
}),
{},
);
return this.withTenantService.invoke(tenantId, (t) =>
t.proofs.requestProof({
connectionId,
protocolVersion: 'v2',
proofFormats: {
anoncreds: {
name,
version: '1.0',
requested_attributes: requestedAttributes,
requested_predicates: transformedPredicates,
},
},
}),
);
}
}
import type { EventDidsResolveInput } from '@ocm/shared'; import type { LEDGERS } from '../../config/ledger.js';
import type {
IndyVdrDidCreateOptions,
IndyVdrDidCreateResult,
} from '@aries-framework/indy-vdr';
import type {
EventDidsRegisterIndyFromSeed,
EventDidsRegisterIndyFromSeedInput,
EventDidsResolve,
EventDidsResolveInput,
} from '@ocm/shared';
import { KeyType, TypedArrayEncoder } from '@aries-framework/core'; import {
DidDocumentService,
Hasher,
KeyType,
TypedArrayEncoder,
} from '@aries-framework/core';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config'; import { ConfigService } from '@nestjs/config';
...@@ -14,7 +29,10 @@ export class DidsService { ...@@ -14,7 +29,10 @@ export class DidsService {
private configService: ConfigService, private configService: ConfigService,
) {} ) {}
public async resolve({ did, tenantId }: EventDidsResolveInput) { public async resolve({
did,
tenantId,
}: EventDidsResolveInput): Promise<EventDidsResolve['data']> {
return this.withTenantService.invoke(tenantId, async (t) => { return this.withTenantService.invoke(tenantId, async (t) => {
const { const {
didDocument, didDocument,
...@@ -36,32 +54,80 @@ export class DidsService { ...@@ -36,32 +54,80 @@ export class DidsService {
public async registerDidIndyFromSeed({ public async registerDidIndyFromSeed({
tenantId, tenantId,
seed, seed,
}: { services,
tenantId: string; }: EventDidsRegisterIndyFromSeedInput): Promise<
seed: string; EventDidsRegisterIndyFromSeed['data']
}): Promise<Array<string>> { > {
const ledgerIds = this.configService.get('agent.ledgerIds'); const dids: Array<string> = [];
const ledgerIds = this.configService.get('agent.ledgerIds') as Array<
keyof typeof LEDGERS
>;
const publicDidSeed = this.configService.get(
'agent.publicDidSeed',
) as string;
const registeredPublicDidResponses = await registerPublicDids({ const publicDids = await registerPublicDids({
ledgerIds, ledgerIds,
seed, seed: publicDidSeed,
}); });
for (const publicDidResponse of registeredPublicDidResponses) { const { publicKey, publicKeyBase58 } = await this.withTenantService.invoke(
await this.withTenantService.invoke(tenantId, (t) => tenantId,
t.dids.import({ async (t) =>
overwrite: true, t.wallet.createKey({
did: publicDidResponse.did, privateKey: TypedArrayEncoder.fromString(seed),
privateKeys: [ keyType: KeyType.Ed25519,
{
keyType: KeyType.Ed25519,
privateKey: TypedArrayEncoder.fromString(seed),
},
],
}), }),
); );
await this.withTenantService.invoke(tenantId, async (t) =>
t.wallet.createKey({
privateKey: TypedArrayEncoder.fromString(publicDidSeed),
keyType: KeyType.Ed25519,
}),
);
const buffer = Hasher.hash(publicKey, 'sha2-256');
const id = TypedArrayEncoder.toBase58(buffer.slice(0, 16));
const verkey = publicKeyBase58;
for (const publicDid of publicDids) {
const did = `did:indy:${publicDid.namespace}:${id}`;
const didDocumentServices: Array<DidDocumentService> | undefined =
services?.map(
(s) =>
new DidDocumentService({
id: `${did}#${s.identifier}`,
type: s.type,
serviceEndpoint: s.url,
}),
);
await this.withTenantService.invoke(tenantId, async (t) => {
const result = (await t.dids.create<IndyVdrDidCreateOptions>({
did,
options: {
verkey,
endorserMode: 'internal',
endorserDid: publicDid.did,
services: didDocumentServices,
useEndpointAttrib: true,
},
})) as IndyVdrDidCreateResult;
if (result.didState.state !== 'finished') {
throw Error(
`An error occurred while trying to register the did: '${did}'. Result: ${JSON.stringify(result)}`,
);
}
dids.push(result.didState.did);
});
} }
return registeredPublicDidResponses.map((r) => r.did); return dids;
} }
} }
...@@ -11,14 +11,17 @@ type RegisterPublicDidOptions = { ...@@ -11,14 +11,17 @@ type RegisterPublicDidOptions = {
}; };
type LedgerRegistrationBody = { type LedgerRegistrationBody = {
role?: 'ENDORSER'; role: 'ENDORSER';
seed: string; seed?: string;
did?: string;
verkey?: string;
}; };
type RegisterPublicDidResponse = { type RegisterPublicDidResponse = {
seed: string; seed: string;
did: string; did: string;
verkey: string; verkey: string;
namespace: string;
}; };
export const registerPublicDids = async ({ export const registerPublicDids = async ({
...@@ -45,7 +48,7 @@ export const registerPublicDids = async ({ ...@@ -45,7 +48,7 @@ export const registerPublicDids = async ({
if (res.data) { if (res.data) {
logger.info('Agent DID registered.'); logger.info('Agent DID registered.');
res.data.did = `did:indy:${ledgerNamespace}:${res.data.did}`; res.data.did = `did:indy:${ledgerNamespace}:${res.data.did}`;
responses.push(res.data); responses.push({ ...res.data, namespace: ledgerNamespace });
} else { } else {
throw new Error('No data was returned from the ledger request'); throw new Error('No data was returned from the ledger request');
} }
......
import type { INestApplication } from '@nestjs/common';
import type { ClientProxy } from '@nestjs/microservices';
import type {
EventAnonCredsProofsGetAllInput,
EventAnonCredsProofsGetByIdInput,
EventDidcommAnonCredsProofsRequestInput,
} from '@ocm/shared';
import { ProofState } from '@aries-framework/core';
import { ClientsModule, Transport } from '@nestjs/microservices';
import { Test } from '@nestjs/testing';
import {
EventAnonCredsProofsGetAll,
EventAnonCredsProofsGetById,
EventDidcommAnonCredsProofsRequest,
} from '@ocm/shared';
import { firstValueFrom } from 'rxjs';
import { AgentModule } from '../src/agent/agent.module.js';
import { AnonCredsProofsModule } from '../src/agent/anoncredsProofs/anoncredsProofs.module.js';
import { ConnectionsModule } from '../src/agent/connections/connections.module.js';
import { ConnectionsService } from '../src/agent/connections/connections.service.js';
import { DidsModule } from '../src/agent/dids/dids.module.js';
import { TenantsModule } from '../src/agent/tenants/tenants.module.js';
import { TenantsService } from '../src/agent/tenants/tenants.service.js';
import { mockConfigModule } from '../src/config/__tests__/mockConfig.js';
describe('Proofs', () => {
const TOKEN = 'PROOFS_CLIENT_SERVICE';
let app: INestApplication;
let client: ClientProxy;
let tenantId: string;
let connectionId: string;
let credentialDefinitionId: string;
beforeAll(async () => {
const moduleRef = await Test.createTestingModule({
imports: [
mockConfigModule(3004, true),
AgentModule,
ConnectionsModule,
AnonCredsProofsModule,
TenantsModule,
DidsModule,
ClientsModule.register([{ name: TOKEN, transport: Transport.NATS }]),
],
}).compile();
app = moduleRef.createNestApplication();
app.connectMicroservice({ transport: Transport.NATS });
await app.startAllMicroservices();
await app.init();
client = app.get(TOKEN);
await client.connect();
const tenantsService = app.get(TenantsService);
const { id: tId } = await tenantsService.create(TOKEN);
tenantId = tId;
const connectionsService = app.get(ConnectionsService);
const { id } = await connectionsService.createConnectionWithSelf({
tenantId,
});
connectionId = id;
});
afterAll(async () => {
await app.close();
client.close();
});
it(EventAnonCredsProofsGetAll.token, async () => {
const response$ = client.send<
EventAnonCredsProofsGetAll,
EventAnonCredsProofsGetAllInput
>(EventAnonCredsProofsGetAll.token, { tenantId });
const response = await firstValueFrom(response$);
const eventInstance = EventAnonCredsProofsGetAll.fromEvent(response);
expect(eventInstance.instance).toEqual(expect.arrayContaining([]));
});
it(EventAnonCredsProofsGetById.token, async () => {
const response$ = client.send<
EventAnonCredsProofsGetById,
EventAnonCredsProofsGetByIdInput
>(EventAnonCredsProofsGetById.token, {
tenantId,
proofRecordId: 'some-id',
});
const response = await firstValueFrom(response$);
const eventInstance = EventAnonCredsProofsGetById.fromEvent(response);
expect(eventInstance.instance).toEqual(null);
});
it(EventDidcommAnonCredsProofsRequest.token, async () => {
const response$ = client.send<
EventDidcommAnonCredsProofsRequest,
EventDidcommAnonCredsProofsRequestInput
>(EventDidcommAnonCredsProofsRequest.token, {
tenantId,
name: 'My Test Proof Request',
connectionId,
requestedAttributes: {
Identity: {
names: ['Name'],
restrictions: [{ cred_def_id: credentialDefinitionId }],
},
},
requestedPredicates: {
'Age > 21': {
name: 'Age',
restrictions: [{ cred_def_id: credentialDefinitionId }],
predicateType: '>',
predicateValue: 21,
},
},
});
const response = await firstValueFrom(response$);
const eventInstance =
EventDidcommAnonCredsProofsRequest.fromEvent(response);
expect(eventInstance.instance).toMatchObject({
state: ProofState.RequestSent,
});
});
});
...@@ -8,6 +8,7 @@ import type { ...@@ -8,6 +8,7 @@ import type {
import { ClientsModule, Transport } from '@nestjs/microservices'; import { ClientsModule, Transport } from '@nestjs/microservices';
import { Test } from '@nestjs/testing'; import { Test } from '@nestjs/testing';
import { EventDidsRegisterIndyFromSeed, EventDidsResolve } from '@ocm/shared'; import { EventDidsRegisterIndyFromSeed, EventDidsResolve } from '@ocm/shared';
import { randomBytes } from 'crypto';
import { firstValueFrom } from 'rxjs'; import { firstValueFrom } from 'rxjs';
import { AgentModule } from '../src/agent/agent.module.js'; import { AgentModule } from '../src/agent/agent.module.js';
...@@ -58,16 +59,23 @@ describe('Dids', () => { ...@@ -58,16 +59,23 @@ describe('Dids', () => {
EventDidsRegisterIndyFromSeed, EventDidsRegisterIndyFromSeed,
EventDidsRegisterIndyFromSeedInput EventDidsRegisterIndyFromSeedInput
>(EventDidsRegisterIndyFromSeed.token, { >(EventDidsRegisterIndyFromSeed.token, {
seed: '12312367897123300000000000000000', seed: randomBytes(16).toString('hex'),
tenantId, tenantId,
services: [
{
url: 'https://example.org',
type: 'endpoint',
identifier: 'endpoint',
},
],
}); });
const response = await firstValueFrom(response$); const response = await firstValueFrom(response$);
const eventInstance = EventDidsRegisterIndyFromSeed.fromEvent(response); const eventInstance = EventDidsRegisterIndyFromSeed.fromEvent(response);
expect(eventInstance.instance).toMatchObject( expect(
expect.arrayContaining(['did:indy:bcovrin:test:9MMeff63VnCpogD2FWfKnJ']), eventInstance.instance[0].startsWith('did:indy:bcovrin:test:'),
); ).toBeTruthy();
}); });
it(EventDidsResolve.token, async () => { it(EventDidsResolve.token, async () => {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment