From 22e3c174485db473f24b0b4ca456636fe7b09919 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Mon, 24 Mar 2025 16:20:55 +0100 Subject: [PATCH 1/6] chore: Associated credential definition to step --- .../database/migrations/0006_credential-showcase-api.sql | 3 +++ .../src/database/migrations/meta/_journal.json | 7 +++++++ .../src/database/schema/step.ts | 6 ++++++ 3 files changed, 16 insertions(+) create mode 100644 apps/credential-showcase-api-server/src/database/migrations/0006_credential-showcase-api.sql diff --git a/apps/credential-showcase-api-server/src/database/migrations/0006_credential-showcase-api.sql b/apps/credential-showcase-api-server/src/database/migrations/0006_credential-showcase-api.sql new file mode 100644 index 0000000..d677b48 --- /dev/null +++ b/apps/credential-showcase-api-server/src/database/migrations/0006_credential-showcase-api.sql @@ -0,0 +1,3 @@ +ALTER TABLE "credentialDefinition" ALTER COLUMN "icon" DROP NOT NULL;--> statement-breakpoint +ALTER TABLE "step" ADD COLUMN "credential_definition_id" uuid;--> statement-breakpoint +ALTER TABLE "step" ADD CONSTRAINT "step_credential_definition_id_credentialDefinition_id_fk" FOREIGN KEY ("credential_definition_id") REFERENCES "public"."credentialDefinition"("id") ON DELETE no action ON UPDATE no action; diff --git a/apps/credential-showcase-api-server/src/database/migrations/meta/_journal.json b/apps/credential-showcase-api-server/src/database/migrations/meta/_journal.json index fe484ad..6f312be 100644 --- a/apps/credential-showcase-api-server/src/database/migrations/meta/_journal.json +++ b/apps/credential-showcase-api-server/src/database/migrations/meta/_journal.json @@ -43,6 +43,13 @@ "when": 1742469395188, "tag": "0005_credential-showcase-api", "breakpoints": true + }, + { + "idx": 6, + "version": "7", + "when": 1742829236121, + "tag": "0006_credential-showcase-api", + "breakpoints": true } ] } diff --git a/apps/credential-showcase-api-server/src/database/schema/step.ts b/apps/credential-showcase-api-server/src/database/schema/step.ts index e698381..b589e95 100644 --- a/apps/credential-showcase-api-server/src/database/schema/step.ts +++ b/apps/credential-showcase-api-server/src/database/schema/step.ts @@ -5,6 +5,7 @@ import { scenarios } from './scenario' import { stepActions } from './stepAction' import { assets } from './asset' import { StepType } from '../../types' +import { credentialDefinitions } from './credentialDefinition' export const steps = pgTable( 'step', @@ -15,6 +16,7 @@ export const steps = pgTable( screenId: text(), order: integer().notNull(), type: StepTypePg().notNull().$type(), + credentialDefinition: uuid('credential_definition_id').references(() => credentialDefinitions.id), subScenario: uuid('sub_scenario').references(() => scenarios.id), scenario: uuid() .references(() => scenarios.id, { onDelete: 'cascade' }) @@ -50,4 +52,8 @@ export const stepRelations = relations(steps, ({ one, many }) => ({ fields: [steps.asset], references: [assets.id], }), + credentialDefinition: one(credentialDefinitions, { + fields: [steps.credentialDefinition], + references: [credentialDefinitions.id], + }), })) From ae92a3bf176f25afb54f664c83ffe7d060eeb483 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Mon, 24 Mar 2025 16:29:37 +0100 Subject: [PATCH 2/6] chore: Added tests for credential definition --- .../repositories/__tests__/scenario.repository.test.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/credential-showcase-api-server/src/database/repositories/__tests__/scenario.repository.test.ts b/apps/credential-showcase-api-server/src/database/repositories/__tests__/scenario.repository.test.ts index 8004b45..6941fb4 100644 --- a/apps/credential-showcase-api-server/src/database/repositories/__tests__/scenario.repository.test.ts +++ b/apps/credential-showcase-api-server/src/database/repositories/__tests__/scenario.repository.test.ts @@ -16,6 +16,7 @@ import * as schema from '../../../database/schema' import { Asset, CredentialAttributeType, + CredentialDefinition, CredentialType, IdentifierType, IssuanceScenario, @@ -48,6 +49,7 @@ describe('Database scenario repository tests', (): void => { let asset: Asset let persona1: Persona let persona2: Persona + let credentialDefinition: CredentialDefinition beforeEach(async (): Promise => { client = new PGlite() @@ -113,7 +115,7 @@ describe('Database scenario repository tests', (): void => { description: 'example_revocation_description', }, } - const credentialDefinition = await credentialDefinitionRepository.create(newCredentialDefinition) + credentialDefinition = await credentialDefinitionRepository.create(newCredentialDefinition) const newIssuer: NewIssuer = { name: 'example_name', type: IssuerType.ARIES, @@ -164,6 +166,7 @@ describe('Database scenario repository tests', (): void => { order: 1, type: StepType.HUMAN_TASK, asset: asset.id, + credentialDefinition: credentialDefinition.id, actions: [ { title: 'example_title', @@ -256,6 +259,8 @@ describe('Database scenario repository tests', (): void => { expect(savedIssuanceScenario.steps[0].title).toEqual(issuanceScenario.steps[0].title) expect(savedIssuanceScenario.steps[0].order).toEqual(issuanceScenario.steps[0].order) expect(savedIssuanceScenario.steps[0].type).toEqual(issuanceScenario.steps[0].type) + expect(savedIssuanceScenario.steps[0].credentialDefinition).toBeDefined() + expect(savedIssuanceScenario.steps[0].credentialDefinition).toEqual(credentialDefinition.id) expect(savedIssuanceScenario.steps[0].actions.length).toEqual(1) expect(savedIssuanceScenario.steps[0].actions[0].id).toBeDefined() expect(savedIssuanceScenario.steps[0].actions[0].title).toEqual(issuanceScenario.steps[0].actions[0].title) @@ -283,6 +288,7 @@ describe('Database scenario repository tests', (): void => { expect(savedIssuanceScenario.steps[0].asset!.fileName).toEqual(asset.fileName) expect(savedIssuanceScenario.steps[0].asset!.description).toEqual(asset.description) expect(savedIssuanceScenario.steps[0].asset!.content).toStrictEqual(asset.content) + expect(savedIssuanceScenario.steps[1].credentialDefinition).toBeNull() expect((savedIssuanceScenario).issuer).not.toBeNull() expect((savedIssuanceScenario).issuer!.name).toEqual(issuer.name) expect((savedIssuanceScenario).issuer!.credentialDefinitions.length).toEqual(1) From 21d83b431c05129336a80aba08dfbd2186e743f9 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Mon, 24 Mar 2025 16:57:07 +0100 Subject: [PATCH 3/6] chore: Updated OpenApi specs and scenario repository --- .../database/repositories/ScenarioRepository.ts | 14 ++++++++++++++ .../openapi/openapi.yaml | 12 ++++++++++++ 2 files changed, 26 insertions(+) diff --git a/apps/credential-showcase-api-server/src/database/repositories/ScenarioRepository.ts b/apps/credential-showcase-api-server/src/database/repositories/ScenarioRepository.ts index 425e873..925ab77 100644 --- a/apps/credential-showcase-api-server/src/database/repositories/ScenarioRepository.ts +++ b/apps/credential-showcase-api-server/src/database/repositories/ScenarioRepository.ts @@ -26,6 +26,7 @@ import { Step, ScenarioType, } from '../../types' +import CredentialDefinitionRepository from './CredentialDefinitionRepository' @Service() class ScenarioRepository implements RepositoryDefinition { @@ -35,6 +36,7 @@ class ScenarioRepository implements RepositoryDefinition private readonly issuerRepository: IssuerRepository, private readonly relyingPartyRepository: RelyingPartyRepository, private readonly assetRepository: AssetRepository, + private readonly credentialDefinitionRepository: CredentialDefinitionRepository, ) {} async create(scenario: NewScenario): Promise { @@ -342,6 +344,7 @@ class ScenarioRepository implements RepositoryDefinition }, }, asset: true, + credentialDefinition: true, }, }, relyingParty: { @@ -448,6 +451,7 @@ class ScenarioRepository implements RepositoryDefinition }, }, asset: true, + credentialDefinition: true, }, }, relyingParty: { @@ -542,12 +546,16 @@ class ScenarioRepository implements RepositoryDefinition return Promise.reject(new BadRequestError('At least one action is required')) } + const credentialDefinitionResult = step.credentialDefinition + ? await this.credentialDefinitionRepository.findById(step.credentialDefinition) + : null const assetResult = step.asset ? await this.assetRepository.findById(step.asset) : null return (await this.databaseService.getConnection()).transaction(async (tx): Promise => { const [stepResult] = await tx .insert(steps) .values({ ...step, + credentialDefinition: credentialDefinitionResult?.id, scenario: scenarioId, }) .returning() @@ -598,12 +606,16 @@ class ScenarioRepository implements RepositoryDefinition return Promise.reject(new BadRequestError('At least one action is required')) } + const credentialDefinitionResult = step?.credentialDefinition + ? await this.credentialDefinitionRepository.findById(step.credentialDefinition) + : null const assetResult = step.asset ? await this.assetRepository.findById(step.asset) : null return (await this.databaseService.getConnection()).transaction(async (tx): Promise => { const [stepResult] = await tx .update(steps) .set({ ...step, + credentialDefinition: credentialDefinitionResult?.id, scenario: scenarioId, }) .where(eq(steps.id, stepId)) @@ -657,6 +669,7 @@ class ScenarioRepository implements RepositoryDefinition }, }, asset: true, + credentialDefinition: true, }, }) @@ -675,6 +688,7 @@ class ScenarioRepository implements RepositoryDefinition where: eq(steps.scenario, scenarioId), with: { asset: true, + credentialDefinition: true, actions: { with: { proofRequest: true, diff --git a/packages/credential-showcase-openapi/openapi/openapi.yaml b/packages/credential-showcase-openapi/openapi/openapi.yaml index 00d0b13..1b21962 100644 --- a/packages/credential-showcase-openapi/openapi/openapi.yaml +++ b/packages/credential-showcase-openapi/openapi/openapi.yaml @@ -1808,6 +1808,12 @@ components: type: string description: Optional sub-scenario for this step example: 123e4567-e89b-12d3-a456-434314174000 + credentialDefinitionIdentifierType: + $ref: '#/components/schemas/IdentifierType' + credentialDefinitionIdentifier: + type: string + description: External identifier of this credential definition + example: did:sov:XUeUZauFLeBNofY3NhaZCB actions: type: array items: @@ -1856,6 +1862,12 @@ components: type: string description: Optional sub-scenario for this step example: 123e4567-e89b-12d3-a456-434314174000 + credentialDefinitionIdentifierType: + $ref: '#/components/schemas/IdentifierType' + credentialDefinitionIdentifier: + type: string + description: External identifier of this credential definition + example: did:sov:XUeUZauFLeBNofY3NhaZCB actions: type: array description: List of actions associated with this step From 95b9bb8d8e810200b90a1022472f790acca56e5d Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Tue, 25 Mar 2025 10:08:53 +0100 Subject: [PATCH 4/6] chore: Added query by identifier to the scenario repository --- .../CredentialDefinitionRepository.ts | 18 ++++++++++++++++-- .../repositories/ScenarioRepository.ts | 18 ++++++++++-------- .../src/types/schema/index.ts | 4 +++- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/apps/credential-showcase-api-server/src/database/repositories/CredentialDefinitionRepository.ts b/apps/credential-showcase-api-server/src/database/repositories/CredentialDefinitionRepository.ts index 41c2e9b..a50a199 100644 --- a/apps/credential-showcase-api-server/src/database/repositories/CredentialDefinitionRepository.ts +++ b/apps/credential-showcase-api-server/src/database/repositories/CredentialDefinitionRepository.ts @@ -1,11 +1,11 @@ -import { eq } from 'drizzle-orm' +import { and, eq } from 'drizzle-orm' import { Service } from 'typedi' import DatabaseService from '../../services/DatabaseService' import AssetRepository from './AssetRepository' import { NotFoundError } from '../../errors' import { credentialDefinitions, credentialRepresentations, revocationInfo } from '../schema' import CredentialSchemaRepository from './CredentialSchemaRepository' -import { CredentialDefinition, NewCredentialDefinition, RepositoryDefinition } from '../../types' +import { CredentialDefinition, IdentifierType, NewCredentialDefinition, RepositoryDefinition } from '../../types' @Service() class CredentialDefinitionRepository implements RepositoryDefinition { @@ -149,6 +149,20 @@ class CredentialDefinitionRepository implements RepositoryDefinition { + const result = await ( + await this.databaseService.getConnection() + ).query.credentialDefinitions.findFirst({ + where: and(eq(credentialDefinitions.identifier, identifier), eq(credentialDefinitions.identifierType, identifierType)), + }) + + if (!result) { + return Promise.reject(new NotFoundError(`No credential definition found for identifier: ${identifier}`)) + } + + return result.id + } } export default CredentialDefinitionRepository diff --git a/apps/credential-showcase-api-server/src/database/repositories/ScenarioRepository.ts b/apps/credential-showcase-api-server/src/database/repositories/ScenarioRepository.ts index 925ab77..8395184 100644 --- a/apps/credential-showcase-api-server/src/database/repositories/ScenarioRepository.ts +++ b/apps/credential-showcase-api-server/src/database/repositories/ScenarioRepository.ts @@ -546,16 +546,17 @@ class ScenarioRepository implements RepositoryDefinition return Promise.reject(new BadRequestError('At least one action is required')) } - const credentialDefinitionResult = step.credentialDefinition - ? await this.credentialDefinitionRepository.findById(step.credentialDefinition) - : null + const credentialDefinitionIdResult = + step.credentialDefinitionIdentifier && step.credentialDefinitionIdentifierType + ? await this.credentialDefinitionRepository.findIdByIdentifier(step.credentialDefinitionIdentifier, step.credentialDefinitionIdentifierType) + : null const assetResult = step.asset ? await this.assetRepository.findById(step.asset) : null return (await this.databaseService.getConnection()).transaction(async (tx): Promise => { const [stepResult] = await tx .insert(steps) .values({ ...step, - credentialDefinition: credentialDefinitionResult?.id, + credentialDefinition: credentialDefinitionIdResult, scenario: scenarioId, }) .returning() @@ -606,16 +607,17 @@ class ScenarioRepository implements RepositoryDefinition return Promise.reject(new BadRequestError('At least one action is required')) } - const credentialDefinitionResult = step?.credentialDefinition - ? await this.credentialDefinitionRepository.findById(step.credentialDefinition) - : null + const credentialDefinitionIdResult = + step?.credentialDefinitionIdentifier && step?.credentialDefinitionIdentifierType + ? await this.credentialDefinitionRepository.findIdByIdentifier(step.credentialDefinitionIdentifier, step.credentialDefinitionIdentifierType) + : null const assetResult = step.asset ? await this.assetRepository.findById(step.asset) : null return (await this.databaseService.getConnection()).transaction(async (tx): Promise => { const [stepResult] = await tx .update(steps) .set({ ...step, - credentialDefinition: credentialDefinitionResult?.id, + credentialDefinition: credentialDefinitionIdResult, scenario: scenarioId, }) .where(eq(steps.id, stepId)) diff --git a/apps/credential-showcase-api-server/src/types/schema/index.ts b/apps/credential-showcase-api-server/src/types/schema/index.ts index f43f4f2..72ebc0f 100644 --- a/apps/credential-showcase-api-server/src/types/schema/index.ts +++ b/apps/credential-showcase-api-server/src/types/schema/index.ts @@ -168,11 +168,13 @@ export type Step = Omit & { actions: AriesOOBAction[] asset?: Asset | null } -export type NewStep = Omit & { +export type NewStep = Omit & { asset?: string | null actions: NewAriesOOBAction[] subScenario?: string | null screenId?: string | null + credentialDefinitionIdentifierType?: IdentifierType + credentialDefinitionIdentifier?: string } export type AriesOOBAction = Omit & { From b475e1106a8a2a11c62f94fa9301a3834c6d38f8 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Tue, 25 Mar 2025 17:04:56 +0100 Subject: [PATCH 5/6] chore: Added repository tests --- .../repositories/ScenarioRepository.ts | 14 +++++++++-- .../__tests__/scenario.repository.test.ts | 24 ++++++++++++++++++- .../src/types/schema/index.ts | 6 ++--- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/apps/credential-showcase-api-server/src/database/repositories/ScenarioRepository.ts b/apps/credential-showcase-api-server/src/database/repositories/ScenarioRepository.ts index f568458..f76f0c1 100644 --- a/apps/credential-showcase-api-server/src/database/repositories/ScenarioRepository.ts +++ b/apps/credential-showcase-api-server/src/database/repositories/ScenarioRepository.ts @@ -52,6 +52,11 @@ class ScenarioRepository implements RepositoryDefinition const personaPromises = scenario.personas.map(async (persona) => await this.personaRepository.findById(persona)) await Promise.all(personaPromises) + const updatedSteps = await Promise.all(scenario.steps.map(async (step: NewStep) => ({ + ...step, + credentialDefinition: step?.credentialDefinitionIdentifier && step?.credentialDefinitionIdentifierType ? await this.credentialDefinitionRepository.findIdByIdentifier(step.credentialDefinitionIdentifier, step.credentialDefinitionIdentifierType) : null + }))) + const scenarioType = isIssuanceScenario(scenario) ? ScenarioType.ISSUANCE : ScenarioType.PRESENTATION const scenarioPartyResult: Issuer | RelyingParty = isIssuanceScenario(scenario) @@ -105,7 +110,7 @@ class ScenarioRepository implements RepositoryDefinition const stepsResult = await tx .insert(steps) .values( - scenario.steps.map((step: NewStep) => ({ + updatedSteps.map((step: NewStep) => ({ ...step, scenario: scenarioResult.id, })), @@ -205,6 +210,11 @@ class ScenarioRepository implements RepositoryDefinition const personaPromises = scenario.personas.map(async (persona) => await this.personaRepository.findById(persona)) await Promise.all(personaPromises) + const updatedSteps = await Promise.all(scenario.steps.map(async (step: NewStep) => ({ + ...step, + credentialDefinition: step.credentialDefinitionIdentifier && step.credentialDefinitionIdentifierType ? await this.credentialDefinitionRepository.findIdByIdentifier(step.credentialDefinitionIdentifier, step.credentialDefinitionIdentifierType): null + }))) + const scenarioType = isIssuanceScenario(scenario) ? ScenarioType.ISSUANCE : ScenarioType.PRESENTATION const scenarioPartyResult: Issuer | RelyingParty = isIssuanceScenario(scenario) @@ -264,7 +274,7 @@ class ScenarioRepository implements RepositoryDefinition const stepsResult = await tx .insert(steps) .values( - scenario.steps.map((step: NewStep) => ({ + updatedSteps.map((step: NewStep) => ({ ...step, scenario: scenarioResult.id, })), diff --git a/apps/credential-showcase-api-server/src/database/repositories/__tests__/scenario.repository.test.ts b/apps/credential-showcase-api-server/src/database/repositories/__tests__/scenario.repository.test.ts index 501ff7e..63060fb 100644 --- a/apps/credential-showcase-api-server/src/database/repositories/__tests__/scenario.repository.test.ts +++ b/apps/credential-showcase-api-server/src/database/repositories/__tests__/scenario.repository.test.ts @@ -166,7 +166,8 @@ describe('Database scenario repository tests', (): void => { order: 1, type: StepType.HUMAN_TASK, asset: asset.id, - credentialDefinition: credentialDefinition.id, + credentialDefinitionIdentifierType: credentialDefinition.identifierType, + credentialDefinitionIdentifier: credentialDefinition.identifier, actions: [ { title: 'example_title', @@ -331,6 +332,8 @@ describe('Database scenario repository tests', (): void => { order: 1, type: StepType.HUMAN_TASK, asset: asset.id, + credentialDefinitionIdentifierType: credentialDefinition.identifierType, + credentialDefinitionIdentifier: credentialDefinition.identifier, actions: [ { title: 'example_title', @@ -422,6 +425,8 @@ describe('Database scenario repository tests', (): void => { expect(savedPresentationScenario.steps[0].title).toEqual(presentationScenario.steps[0].title) expect(savedPresentationScenario.steps[0].order).toEqual(presentationScenario.steps[0].order) expect(savedPresentationScenario.steps[0].type).toEqual(presentationScenario.steps[0].type) + expect(savedPresentationScenario.steps[0].credentialDefinition).toBeDefined() + expect(savedPresentationScenario.steps[0].credentialDefinition).toEqual(credentialDefinition.id) expect(savedPresentationScenario.steps[0].actions!.length).toEqual(1) expect(savedPresentationScenario.steps[0].actions![0].id).toBeDefined() expect(savedPresentationScenario.steps[0].actions![0].title).toEqual(presentationScenario.steps[0].actions![0].title) @@ -432,6 +437,7 @@ describe('Database scenario repository tests', (): void => { expect(savedPresentationScenario.steps[0].asset!.fileName).toEqual(asset.fileName) expect(savedPresentationScenario.steps[0].asset!.description).toEqual(asset.description) expect(savedPresentationScenario.steps[0].asset!.content).toStrictEqual(asset.content) + expect(savedPresentationScenario.steps[1].credentialDefinition).toBeNull() expect((savedPresentationScenario).relyingParty).not.toBeNull() expect((savedPresentationScenario).relyingParty!.name).toEqual(relyingParty.name) expect((savedPresentationScenario).relyingParty!.credentialDefinitions.length).toEqual(1) @@ -1314,6 +1320,8 @@ describe('Database scenario repository tests', (): void => { order: 1, type: StepType.HUMAN_TASK, asset: asset.id, + credentialDefinitionIdentifierType: credentialDefinition.identifierType, + credentialDefinitionIdentifier: credentialDefinition.identifier, actions: [ { title: 'example_title1', @@ -1396,6 +1404,8 @@ describe('Database scenario repository tests', (): void => { expect(updatedIssuanceScenarioResult.steps[0].title).toEqual(updatedIssuanceScenario.steps[0].title) expect(updatedIssuanceScenarioResult.steps[0].order).toEqual(updatedIssuanceScenario.steps[0].order) expect(updatedIssuanceScenarioResult.steps[0].type).toEqual(updatedIssuanceScenario.steps[0].type) + expect(savedIssuanceScenario.steps[0].credentialDefinition).toBeDefined() + expect(savedIssuanceScenario.steps[0].credentialDefinition).toBeNull() expect(updatedIssuanceScenarioResult.steps[0].actions!.length).toEqual(2) expect(updatedIssuanceScenarioResult.steps[0].actions![0].id).toBeDefined() expect(updatedIssuanceScenarioResult.steps[0].actions![0].title).toEqual(updatedIssuanceScenario.steps[0].actions![0].title) @@ -1423,6 +1433,7 @@ describe('Database scenario repository tests', (): void => { issuanceScenario.steps[0].actions![0].proofRequest!.predicates.predicate1.value, ) expect(updatedIssuanceScenarioResult.steps[0].actions![0].proofRequest!.predicates!.predicate1.restrictions!.length).toEqual(2) + expect(savedIssuanceScenario.steps[1].credentialDefinition).toBeNull() expect(updatedIssuanceScenarioResult.personas).toBeDefined() expect(updatedIssuanceScenarioResult.personas.length).toEqual(1) expect(updatedIssuanceScenarioResult.personas[0].name).toEqual(persona1.name) @@ -2120,6 +2131,8 @@ describe('Database scenario repository tests', (): void => { order: 2, type: StepType.HUMAN_TASK, asset: asset.id, + credentialDefinitionIdentifierType: credentialDefinition.identifierType, + credentialDefinitionIdentifier: credentialDefinition.identifier, actions: [ { title: 'example_title1', @@ -2196,6 +2209,7 @@ describe('Database scenario repository tests', (): void => { expect(fromDb.steps[1].title).toEqual(step.title) expect(fromDb.steps[1].order).toEqual(step.order) expect(fromDb.steps[1].type).toEqual(step.type) + expect(fromDb.steps[1].credentialDefinition).not.toBeNull() expect(fromDb.steps[1].actions!.length).toEqual(2) expect(fromDb.steps[1].actions![0].id).toBeDefined() expect(fromDb.steps[1].actions![0].title).toEqual(step.actions![0].title) @@ -2299,6 +2313,7 @@ describe('Database scenario repository tests', (): void => { updatedAt: expect.any(Date), }, createdAt: expect.any(Date), + credentialDefinition: null, description: 'example_description', id: expect.any(String), order: 2, @@ -2661,6 +2676,8 @@ describe('Database scenario repository tests', (): void => { order: 1, type: StepType.HUMAN_TASK, asset: asset.id, + credentialDefinitionIdentifierType: credentialDefinition.identifierType, + credentialDefinitionIdentifier: credentialDefinition.identifier, actions: [ { title: 'example_title', @@ -2706,6 +2723,8 @@ describe('Database scenario repository tests', (): void => { const updatedStep: NewStep = { ...savedIssuanceScenario.steps[0], title: 'new_title', + credentialDefinitionIdentifierType: credentialDefinition.identifierType, + credentialDefinitionIdentifier: credentialDefinition.identifier, actions: [ { title: 'example_title1', @@ -2778,6 +2797,8 @@ describe('Database scenario repository tests', (): void => { expect(updatedStepResult.title).toEqual(updatedStep.title) expect(updatedStepResult.order).toEqual(updatedStep.order) expect(updatedStepResult.type).toEqual(updatedStep.type) + expect(updatedStepResult.credentialDefinition).toBeDefined() + expect(updatedStepResult.credentialDefinition).toEqual(credentialDefinition.id) expect(updatedStepResult.actions!.length).toEqual(2) expect(updatedStepResult.actions![0].id).toBeDefined() expect(updatedStepResult.actions![0].title).toEqual(updatedStep.actions![0].title) @@ -2878,6 +2899,7 @@ describe('Database scenario repository tests', (): void => { updatedAt: expect.any(Date), }, createdAt: expect.any(Date), + credentialDefinition: null, description: 'example_description', id: expect.any(String), order: 1, diff --git a/apps/credential-showcase-api-server/src/types/schema/index.ts b/apps/credential-showcase-api-server/src/types/schema/index.ts index e8f2917..7669fc8 100644 --- a/apps/credential-showcase-api-server/src/types/schema/index.ts +++ b/apps/credential-showcase-api-server/src/types/schema/index.ts @@ -176,13 +176,13 @@ export type Step = Omit & { actions?: AriesOOBAction[] asset?: Asset | null } -export type NewStep = Omit & { +export type NewStep = Omit & { asset?: string | null actions?: NewAriesOOBAction[] subScenario?: string | null screenId?: string | null - credentialDefinitionIdentifierType?: IdentifierType - credentialDefinitionIdentifier?: string + credentialDefinitionIdentifierType?: IdentifierType | null + credentialDefinitionIdentifier?: string | null } export type AriesOOBAction = Omit & { From 6ca0f7405f4065815218596c7362dbdb79eed447 Mon Sep 17 00:00:00 2001 From: Zoe Maas Date: Tue, 25 Mar 2025 17:05:02 +0100 Subject: [PATCH 6/6] chore: Added repository tests --- .../repositories/ScenarioRepository.ts | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/apps/credential-showcase-api-server/src/database/repositories/ScenarioRepository.ts b/apps/credential-showcase-api-server/src/database/repositories/ScenarioRepository.ts index f76f0c1..45ce5a7 100644 --- a/apps/credential-showcase-api-server/src/database/repositories/ScenarioRepository.ts +++ b/apps/credential-showcase-api-server/src/database/repositories/ScenarioRepository.ts @@ -52,10 +52,18 @@ class ScenarioRepository implements RepositoryDefinition const personaPromises = scenario.personas.map(async (persona) => await this.personaRepository.findById(persona)) await Promise.all(personaPromises) - const updatedSteps = await Promise.all(scenario.steps.map(async (step: NewStep) => ({ - ...step, - credentialDefinition: step?.credentialDefinitionIdentifier && step?.credentialDefinitionIdentifierType ? await this.credentialDefinitionRepository.findIdByIdentifier(step.credentialDefinitionIdentifier, step.credentialDefinitionIdentifierType) : null - }))) + const updatedSteps = await Promise.all( + scenario.steps.map(async (step: NewStep) => ({ + ...step, + credentialDefinition: + step?.credentialDefinitionIdentifier && step?.credentialDefinitionIdentifierType + ? await this.credentialDefinitionRepository.findIdByIdentifier( + step.credentialDefinitionIdentifier, + step.credentialDefinitionIdentifierType, + ) + : null, + })), + ) const scenarioType = isIssuanceScenario(scenario) ? ScenarioType.ISSUANCE : ScenarioType.PRESENTATION @@ -210,10 +218,18 @@ class ScenarioRepository implements RepositoryDefinition const personaPromises = scenario.personas.map(async (persona) => await this.personaRepository.findById(persona)) await Promise.all(personaPromises) - const updatedSteps = await Promise.all(scenario.steps.map(async (step: NewStep) => ({ + const updatedSteps = await Promise.all( + scenario.steps.map(async (step: NewStep) => ({ ...step, - credentialDefinition: step.credentialDefinitionIdentifier && step.credentialDefinitionIdentifierType ? await this.credentialDefinitionRepository.findIdByIdentifier(step.credentialDefinitionIdentifier, step.credentialDefinitionIdentifierType): null - }))) + credentialDefinition: + step.credentialDefinitionIdentifier && step.credentialDefinitionIdentifierType + ? await this.credentialDefinitionRepository.findIdByIdentifier( + step.credentialDefinitionIdentifier, + step.credentialDefinitionIdentifierType, + ) + : null, + })), + ) const scenarioType = isIssuanceScenario(scenario) ? ScenarioType.ISSUANCE : ScenarioType.PRESENTATION