Skip to content

Commit

Permalink
feat: implement credential module
Browse files Browse the repository at this point in the history
  • Loading branch information
lotharking committed Dec 20, 2024
1 parent e325a7e commit 8180946
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 48 deletions.
4 changes: 2 additions & 2 deletions packages/nestjs-client/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Module, DynamicModule } from '@nestjs/common'

import { ConnectionsEventModule } from './connections'
import { CredentialEventModule } from './credentials'
import { MessageEventModule } from './messages'
import { EventsModuleOptions } from './types'
import { CredentialEventModule } from './credentials'

@Module({})
export class EventsModule {
Expand Down Expand Up @@ -37,7 +37,7 @@ export class EventsModule {
imports: moduleOptions.imports ?? [],
url: moduleOptions.url,
version: moduleOptions.version,
creds: moduleOptions.creds
creds: moduleOptions.creds,
}),
)
}
Expand Down
30 changes: 14 additions & 16 deletions packages/nestjs-client/src/credentials/credential.entity.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,34 @@
import {
Entity,
Column,
PrimaryGeneratedColumn,
CreateDateColumn,
UpdateDateColumn,
JoinColumn,
OneToOne,
} from 'typeorm'

import { ConnectionEntity } from '../connections'
import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn } from 'typeorm'

@Entity('credentials')
export class CredentialEntity {
@PrimaryGeneratedColumn('uuid')
id!: string

@Column({ type: 'varchar', nullable: false })
credentialDefinitionId?: string
credentialDefinitionId!: string

@Column({ type: 'varchar', nullable: true })
revocationDefinitionId?: string

@Column({ type: 'integer', generated: 'increment', nullable: true })
@Column({ type: 'integer', nullable: true })
revocationRegistryIndex?: number

@OneToOne(() => ConnectionEntity, { nullable: false })
@JoinColumn({ name: 'connection_id', referencedColumnName: 'id' })
connectionId?: ConnectionEntity
@Column({ type: 'integer', nullable: false })
maximumCredentialNumber!: number

@Column({ type: 'varchar', nullable: true })
connectionId?: string

@Column({ type: 'varchar', nullable: true })
threadId?: string

@Column({ type: 'blob', nullable: true })
hash?: Buffer

@Column({ nullable: true })
revoked?: boolean

@CreateDateColumn()
createdTs?: Date

Expand Down
3 changes: 2 additions & 1 deletion packages/nestjs-client/src/credentials/credential.module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { DynamicModule, Module } from '@nestjs/common'

import { CredentialEventOptions } from '../types'

import { CredentialEventService } from './credential.service'

@Module({})
Expand All @@ -17,7 +18,7 @@ export class CredentialEventModule {
useValue: options,
},
],
exports: [CredentialEventService]
exports: [CredentialEventService],
}
}
}
2 changes: 2 additions & 0 deletions packages/nestjs-client/src/credentials/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export * from './credential.entity'
export * from './credential.service'
export * from './credential.module'
45 changes: 16 additions & 29 deletions packages/nestjs-client/src/messages/message.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,9 @@ import {
ReceiptsMessage,
} from '@2060.io/service-agent-model'
import { Inject, Injectable, Logger, Optional } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { MessageState } from 'credo-ts-receipts'
import { Repository } from 'typeorm'

import { ConnectionsRepository } from '../connections'
import { CredentialEntity } from '../credentials'
import { CredentialEventService } from '../credentials'
import { EventHandler } from '../interfaces'
import { MessageEventOptions } from '../types'

Expand All @@ -23,27 +20,31 @@ export class MessageEventService {
private readonly apiClient: ApiClient

constructor(
@Inject('MESSAGE_MODULE_OPTIONS') private options: MessageEventOptions,
@InjectRepository(CredentialEntity)
private readonly credentialRepository: Repository<CredentialEntity>,
private readonly connectionRepository: ConnectionsRepository,
@Inject('EVENT_MODULE_OPTIONS') private options: MessageEventOptions,
@Optional() @Inject('MESSAGE_EVENT') private eventHandler?: EventHandler,
@Optional() @Inject() private credentialEvent?: CredentialEventService,
) {
if (!options.url) throw new Error(`For this module to be used the value url must be added`)
this.url = options.url
this.version = options.version ?? ApiVersion.V1

if (!credentialEvent)
this.logger.warn(
`To handle credential events and their revocation, make sure to initialize the CredentialEventModule.`,
)

this.apiClient = new ApiClient(this.url, this.version)

this.logger.debug(`Initialized with url: ${this.url}, version: ${this.version}`)
}

async received(event: MessageReceived): Promise<void> {
const message = event.message
const body = new ReceiptsMessage({
connectionId: event.message.connectionId,
connectionId: message.connectionId,
receipts: [
{
messageId: event.message.id,
messageId: message.id,
state: MessageState.Viewed,
timestamp: new Date(),
},
Expand All @@ -54,32 +55,18 @@ export class MessageEventService {
await this.apiClient.messages.send(body)

if (this.eventHandler) {
if (event.message instanceof CredentialReceptionMessage) {
if (message instanceof CredentialReceptionMessage) {
try {
const [credential] = await this.apiClient.credentialTypes.getAll()
const connectionId = await this.connectionRepository.findById(event.message.connectionId)
const hash = Buffer.from(await this.eventHandler.credentialHash(event.message.connectionId))
const currentCred = await this.credentialRepository.findOneBy({ hash })
const isCredentialDone = event.message.state === CredentialState.Done

if (connectionId && isCredentialDone) {
if (!currentCred) {
const credentialRev = this.credentialRepository.create({
connectionId,
hash,
revocationDefinitionId: credential.revocationId,
})
await this.credentialRepository.save(credentialRev)
} else {
this.credentialRepository.update(currentCred.id, { connectionId })
}
const isCredentialDone = message.state === CredentialState.Done
if (this.credentialEvent && isCredentialDone && message.threadId) {
this.credentialEvent.accept(message.connectionId, message.threadId)
}
} catch (error) {
this.logger.error(`Cannot create the registry: ${error}`)
}
}

await this.eventHandler.inputMessage(event.message)
await this.eventHandler.inputMessage(message)
}
}

Expand Down

0 comments on commit 8180946

Please sign in to comment.