Skip to content

Commit

Permalink
feat: (WIP) added tenant aware credential store
Browse files Browse the repository at this point in the history
  • Loading branch information
sksadjad committed Feb 20, 2024
1 parent 1aa7c3d commit db68113
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 0 deletions.
16 changes: 16 additions & 0 deletions packages/data-store/src/credential/AbstractCredentialStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {
AddCredentialArgs,
GetCredentialArgs,
GetCredentialsArgs,
RemoveCredentialArgs,
UpdateCredentialStateArgs,
} from '../types/credential/IAbstractCredentialStore'
import { UniformCredential } from '../types/credential/credential'

export abstract class AbstractCredentialStore {
abstract getCredential(args: GetCredentialArgs): Promise<UniformCredential>
abstract getCredentials(args?: GetCredentialsArgs): Promise<Array<UniformCredential>>
abstract addCredential(args: AddCredentialArgs): Promise<UniformCredential>
abstract updateCredentialState(args: UpdateCredentialStateArgs): Promise<UniformCredential>
abstract removeCredential(args: RemoveCredentialArgs): Promise<void>
}
48 changes: 48 additions & 0 deletions packages/data-store/src/credential/CredentialStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { AbstractCredentialStore } from './AbstractCredentialStore'
import { AddCredentialArgs, GetCredentialArgs, GetCredentialsArgs, RemoveCredentialArgs } from '../types/credential/IAbstractCredentialStore'
import { UniformCredential } from '../types/credential/credential'
import { OrPromise } from '@sphereon/ssi-types'
import { DataSource, Repository } from 'typeorm'
import Debug from 'debug'
import { UniformCredentialEntity } from '../entities/credential/CredentialEntity'
import { PartyEntity } from '../entities/contact/PartyEntity'
import { credentialEntityFrom } from '../utils/credential/MappingUtils'

const debug: Debug.Debugger = Debug('sphereon:ssi-sdk:credential-store')
export class CredentialStore extends AbstractCredentialStore {
private readonly dbConnection: OrPromise<DataSource>

constructor(dbConnection: OrPromise<DataSource>) {
super()
this.dbConnection = dbConnection
}

addCredential = async (args: AddCredentialArgs): Promise<UniformCredential> => {
debug('Adding credential', args)
const uniformCredentialRepository: Repository<UniformCredentialEntity> = (await this.dbConnection).getRepository(UniformCredentialEntity)
const credentialEntity: UniformCredentialEntity = credentialEntityFrom(args)
const createdResult: UniformCredentialEntity = await uniformCredentialRepository.save(credentialEntity)
return Promise.resolve(undefined)
}

getCredential = async (args: GetCredentialArgs): Promise<UniformCredential> => {
const result: UniformCredentialEntity | null = await (await this.dbConnection).getRepository(UniformCredentialEntity).findOne({
where: args,
})

if (!result) {
return Promise.reject(Error(`No party found for arg: ${args.toString()}`))
}

//todo: cast to UniformCredential
return result
}

getCredentials = async (args?: GetCredentialsArgs): Promise<Array<UniformCredential>> => {
return Promise.resolve(undefined)
}

removeCredential = async (args: RemoveCredentialArgs): Promise<void> => {
return Promise.resolve(undefined)
}
}
53 changes: 53 additions & 0 deletions packages/data-store/src/entities/credential/CredentialEntity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { BaseEntity, Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'
import { CredentialCorrelationType, CredentialDocumentFormat, CredentialStateType, CredentialTypeEnum } from '../../types/credential/credential'

@Entity('UniformCredential')
export class UniformCredentialEntity extends BaseEntity {
@PrimaryGeneratedColumn('uuid')
id!: string

@Column('simple-enum', { name: 'credential_type', enum: CredentialTypeEnum, nullable: false })
credentialType!: CredentialTypeEnum

@Column('simple-enum', { name: 'document_format', enum: CredentialDocumentFormat, nullable: false })
documentFormat!: CredentialDocumentFormat

@Column('text', { name: 'raw', nullable: false })
raw!: string

@Column('text', { name: 'uniform_document', nullable: false })
uniformDocument!: string

@Column('text', { name: 'hash', nullable: false, unique: true })
hash!: string

@Column('string', { name: 'type', nullable: false })
type!: string

@Column('simple-enum', { name: 'issuer_correlation_type', enum: CredentialCorrelationType, nullable: false })
issuerCorrelationType!: CredentialCorrelationType

@Column('simple-enum', { name: 'subject_correlation_type', enum: CredentialCorrelationType, nullable: true })
subjectCorrelationType?: CredentialCorrelationType

@Column('text', { name: 'issuer_correlation_type', nullable: false })
issuerCorrelationId!: string

@Column('text', { name: 'subject_correlation_type', nullable: true })
subjectCorrelationId?: string

@Column('simple-enum', { name: 'last_verified_state', enum: CredentialStateType, nullable: true })
lastVerifiedState?: CredentialStateType

@Column('text', { name: 'tenant_id', nullable: true })
tenantId?: string

@CreateDateColumn({ name: 'created_at', nullable: false })
createdAt!: Date

@UpdateDateColumn({ name: 'last_updated_at', nullable: false })
lastUpdatedAt!: Date

@Column('date', { name: 'expires_at', nullable: false })
expiresAt!: Date
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { CredentialCorrelationType, CredentialDocumentFormat, CredentialStateType, CredentialTypeEnum } from './credential'

export type GetCredentialArgs = { id: string } | { hash: string }

// TODO: discuss about what args we want here
export type GetCredentialsArgs = {}

export type AddCredentialArgs = {
credentialType: CredentialTypeEnum
documentFormat: CredentialDocumentFormat
raw: string
issuerCorrelationType: CredentialCorrelationType
subjectCorrelationType?: CredentialCorrelationType
issuerCorrelationId: string
subjectCorrelationId?: string
tenantId?: string
}

export type UpdateCredentialStateArgs = GetCredentialArgs & { verified_state: CredentialStateType }

export type RemoveCredentialArgs = { id: string } | { hash: string }
39 changes: 39 additions & 0 deletions packages/data-store/src/types/credential/credential.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
export type UniformCredential = {
id: string
credentialType: CredentialTypeEnum
documentFormat: CredentialDocumentFormat
raw: string
hash: string
type: string
issuerCorrelationType: CredentialCorrelationType
subjectCorrelationType?: CredentialCorrelationType
issuerCorrelationId: string
subjectCorrelationId?: string
last_verified_state?: CredentialStateType
tenantId?: string
createdAt: Date
lastUpdatedAt: Date
expiresAt: Date
}

export enum CredentialTypeEnum {
VC = 'vc',
VP = 'vp',
}

export enum CredentialDocumentFormat {
JSON_LD = 'JSON-LD',
JWT = 'JWT',
SD_JWT = 'SD-JWT',
MDOC = 'MDOC',
}

export enum CredentialCorrelationType {
DID = 'did',
}

export enum CredentialStateType {
REVOKED = 'revoked',
VERIFIED = 'verified',
EXPIRED = 'expired',
}
30 changes: 30 additions & 0 deletions packages/data-store/src/utils/credential/MappingUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { AddCredentialArgs } from '../../types/credential/IAbstractCredentialStore'
import { UniformCredentialEntity } from '../../entities/credential/CredentialEntity'
import { CredentialMapper, WrappedVerifiableCredential, WrappedVerifiablePresentation } from '@sphereon/ssi-types'
import { CredentialTypeEnum } from '../../types/credential/credential'
import { computeEntryHash } from '@veramo/utils'

export const credentialEntityFrom = async (addCredentialArgs: AddCredentialArgs): Promise<UniformCredentialEntity> => {
const wrappedCredential: WrappedVerifiableCredential | WrappedVerifiablePresentation =
addCredentialArgs.credentialType === CredentialTypeEnum.VC
? CredentialMapper.toWrappedVerifiableCredential(JSON.stringify(addCredentialArgs.raw))
: CredentialMapper.toWrappedVerifiablePresentation(addCredentialArgs.raw)
const uniformCredentialEntity: UniformCredentialEntity = new UniformCredentialEntity()

uniformCredentialEntity.credentialType = addCredentialArgs.credentialType
uniformCredentialEntity.createdAt = new Date(wrappedCredential.decoded.nbf)
console.log(`We have createdAt:`, uniformCredentialEntity.createdAt)
uniformCredentialEntity.documentFormat = addCredentialArgs.documentFormat
uniformCredentialEntity.lastUpdatedAt = new Date()
uniformCredentialEntity.tenantId = addCredentialArgs.tenantId
uniformCredentialEntity.raw = addCredentialArgs.raw
uniformCredentialEntity.subjectCorrelationId = addCredentialArgs.subjectCorrelationId
uniformCredentialEntity.subjectCorrelationType = addCredentialArgs.subjectCorrelationType
uniformCredentialEntity.type = wrappedCredential.type
uniformCredentialEntity.hash = computeEntryHash(addCredentialArgs.raw)
uniformCredentialEntity.uniformDocument =
addCredentialArgs.credentialType === CredentialTypeEnum.VC
? JSON.stringify((wrappedCredential as WrappedVerifiableCredential).credential)
: JSON.stringify((wrappedCredential as WrappedVerifiablePresentation).presentation)
return {} as UniformCredentialEntity
}

0 comments on commit db68113

Please sign in to comment.