diff --git a/apps/credential-showcase-api-server/src/database/migrations/0003_credential-showcase-api.sql b/apps/credential-showcase-api-server/src/database/migrations/0003_credential-showcase-api.sql index 0d05179..dbd5e28 100644 --- a/apps/credential-showcase-api-server/src/database/migrations/0003_credential-showcase-api.sql +++ b/apps/credential-showcase-api-server/src/database/migrations/0003_credential-showcase-api.sql @@ -1 +1,2 @@ -ALTER TABLE "step" ADD COLUMN "screenId" text; \ No newline at end of file +ALTER TABLE "step" ADD COLUMN "screenId" text;--> statement-breakpoint +ALTER TABLE "credentialDefinition" ALTER COLUMN "icon" DROP NOT NULL; \ No newline at end of file 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 7fe5c6f..41c2e9b 100644 --- a/apps/credential-showcase-api-server/src/database/repositories/CredentialDefinitionRepository.ts +++ b/apps/credential-showcase-api-server/src/database/repositories/CredentialDefinitionRepository.ts @@ -16,7 +16,7 @@ class CredentialDefinitionRepository implements RepositoryDefinition { - const iconResult = await this.assetRepository.findById(credentialDefinition.icon) + const iconResult = credentialDefinition.icon && (await this.assetRepository.findById(credentialDefinition.icon)) const credentialSchemaResult = await this.credentialSchemaRepository.findById(credentialDefinition.credentialSchema) return (await this.databaseService.getConnection()).transaction(async (tx): Promise => { @@ -44,7 +44,7 @@ class CredentialDefinitionRepository implements RepositoryDefinition { await this.findById(id) - const iconResult = await this.assetRepository.findById(credentialDefinition.icon) + const iconResult = credentialDefinition.icon && (await this.assetRepository.findById(credentialDefinition.icon)) const credentialSchemaResult = await this.credentialSchemaRepository.findById(credentialDefinition.credentialSchema) return (await this.databaseService.getConnection()).transaction(async (tx): Promise => { const [credentialDefinitionResult] = await tx @@ -93,7 +93,7 @@ class CredentialDefinitionRepository implements RepositoryDefinition { expect(savedCredentialDefinition.name).toEqual(credentialDefinition.name) expect(savedCredentialDefinition.version).toEqual(credentialDefinition.version) expect(savedCredentialDefinition.icon).toBeDefined() - expect(savedCredentialDefinition.icon.id).toBeDefined() - expect(savedCredentialDefinition.icon.mediaType).toEqual(asset.mediaType) - expect(savedCredentialDefinition.icon.fileName).toEqual(asset.fileName) - expect(savedCredentialDefinition.icon.description).toEqual(asset.description) - expect(savedCredentialDefinition.icon.content).toStrictEqual(asset.content) + expect(savedCredentialDefinition.icon!.id).toBeDefined() + expect(savedCredentialDefinition.icon!.mediaType).toEqual(asset.mediaType) + expect(savedCredentialDefinition.icon!.fileName).toEqual(asset.fileName) + expect(savedCredentialDefinition.icon!.description).toEqual(asset.description) + expect(savedCredentialDefinition.icon!.content).toStrictEqual(asset.content) // TODO SHOWCASE-81 representations //expect(savedCredentialDefinition.representations.length).toEqual(2) @@ -116,6 +116,37 @@ describe('Database credential definition repository tests', (): void => { // expect(savedCredentialDefinition.revocation!.description).toEqual(credentialDefinition.revocation!.description) }) + it('Should save the credential definition without icon to database', async (): Promise => { + const credentialDefinition: NewCredentialDefinition = { + name: 'example_name', + version: 'example_version', + identifierType: IdentifierType.DID, + identifier: 'did:sov:XUeUZauFLeBNofY3NhaZCB', + type: CredentialType.ANONCRED, + credentialSchema: credentialSchema.id, + // representations: [ + // { // TODO SHOWCASE-81 OCARepresentation + // + // }, + // { // TODO SHOWCASE-81 OCARepresentation + // + // } + // ], + //revocation: { + // TODO SHOWCASE-80 AnonCredRevocation + //title: 'example_revocation_title', + // description: 'example_revocation_description', + // }, + } + + const savedCredentialDefinition = await credentialDefinitionRepository.create(credentialDefinition) + + expect(savedCredentialDefinition).toBeDefined() + expect(savedCredentialDefinition.name).toEqual(credentialDefinition.name) + expect(savedCredentialDefinition.version).toEqual(credentialDefinition.version) + expect(savedCredentialDefinition.icon).toBeUndefined() + }) + it('Should throw error when saving credential definition with invalid icon id', async (): Promise => { const unknownIconId = 'a197e5b2-e4e5-4788-83b1-ecaa0e99ed3a' const credentialDefinition: NewCredentialDefinition = { @@ -169,11 +200,11 @@ describe('Database credential definition repository tests', (): void => { expect(fromDb.name).toEqual(credentialDefinition.name) expect(fromDb.version).toEqual(credentialDefinition.version) expect(fromDb.icon).toBeDefined() - expect(fromDb.icon.id).toBeDefined() - expect(fromDb.icon.mediaType).toEqual(asset.mediaType) - expect(fromDb.icon.fileName).toEqual(asset.fileName) - expect(fromDb.icon.description).toEqual(asset.description) - expect(fromDb.icon.content).toStrictEqual(asset.content) + expect(fromDb.icon!.id).toBeDefined() + expect(fromDb.icon!.mediaType).toEqual(asset.mediaType) + expect(fromDb.icon!.fileName).toEqual(asset.fileName) + expect(fromDb.icon!.description).toEqual(asset.description) + expect(fromDb.icon!.content).toStrictEqual(asset.content) // TODO SHOWCASE-81 representations //expect(fromDb.representations.length).toEqual(2) // expect(fromDb.revocation).not.toBeNull() @@ -278,11 +309,58 @@ describe('Database credential definition repository tests', (): void => { expect(updatedCredentialDefinition.name).toEqual(newName) expect(updatedCredentialDefinition.version).toEqual(credentialDefinition.version) expect(updatedCredentialDefinition.icon).toBeDefined() - expect(updatedCredentialDefinition.icon.id).toBeDefined() - expect(updatedCredentialDefinition.icon.mediaType).toEqual(asset.mediaType) - expect(updatedCredentialDefinition.icon.fileName).toEqual(asset.fileName) - expect(updatedCredentialDefinition.icon.description).toEqual(asset.description) - expect(updatedCredentialDefinition.icon.content).toStrictEqual(asset.content) + expect(updatedCredentialDefinition.icon!.id).toBeDefined() + expect(updatedCredentialDefinition.icon!.mediaType).toEqual(asset.mediaType) + expect(updatedCredentialDefinition.icon!.fileName).toEqual(asset.fileName) + expect(updatedCredentialDefinition.icon!.description).toEqual(asset.description) + expect(updatedCredentialDefinition.icon!.content).toStrictEqual(asset.content) + // TODO SHOWCASE-81 representations + //expect(updatedCredentialDefinition.representations.length).toEqual(2) + // TODO SHOWCASE-80 AnonCredRevocation + // expect(updatedCredentialDefinition.revocation).not.toBeNull() + // expect(updatedCredentialDefinition.revocation!.title).toEqual(credentialDefinition.revocation!.title) + // expect(updatedCredentialDefinition.revocation!.description).toEqual(credentialDefinition.revocation!.description) + }) + + it('Should update credential definition in database passing in an undefined icon', async (): Promise => { + const credentialDefinition: NewCredentialDefinition = { + name: 'example_name', + version: 'example_version', + identifierType: IdentifierType.DID, + identifier: 'did:sov:XUeUZauFLeBNofY3NhaZCB', + icon: asset.id, + type: CredentialType.ANONCRED, + credentialSchema: credentialSchema.id, + // representations: [ + // { // TODO SHOWCASE-81 OCARepresentation + // + // }, + // { // TODO SHOWCASE-81 OCARepresentation + // + // } + // ], + //revocation: { + // TODO SHOWCASE-80 AnonCredRevocation + //title: 'example_revocation_title', + // description: 'example_revocation_description', + // }, + } + + const savedCredentialDefinition = await credentialDefinitionRepository.create(credentialDefinition) + expect(savedCredentialDefinition).toBeDefined() + + const newName = 'new_name' + const updatedCredentialDefinition = await credentialDefinitionRepository.update(savedCredentialDefinition.id, { + ...credentialDefinition, + icon: undefined, + credentialSchema: credentialSchema.id, + name: newName, + }) + + expect(updatedCredentialDefinition).toBeDefined() + expect(updatedCredentialDefinition.name).toEqual(newName) + expect(updatedCredentialDefinition.version).toEqual(credentialDefinition.version) + expect(updatedCredentialDefinition.icon).toBeUndefined() // TODO SHOWCASE-81 representations //expect(updatedCredentialDefinition.representations.length).toEqual(2) // TODO SHOWCASE-80 AnonCredRevocation diff --git a/apps/credential-showcase-api-server/src/database/schema/credentialDefinition.ts b/apps/credential-showcase-api-server/src/database/schema/credentialDefinition.ts index 930b0be..52f4bf2 100644 --- a/apps/credential-showcase-api-server/src/database/schema/credentialDefinition.ts +++ b/apps/credential-showcase-api-server/src/database/schema/credentialDefinition.ts @@ -20,9 +20,7 @@ export const credentialDefinitions = pgTable( credentialSchema: uuid('credential_schema') .references(() => credentialSchemas.id) .notNull(), - icon: uuid() - .references(() => assets.id) - .notNull(), + icon: uuid().references(() => assets.id), type: CredentialTypePg().notNull().$type(), createdAt: timestamp('created_at').defaultNow().notNull(), updatedAt: timestamp('updated_at') 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 a482262..f43f4f2 100644 --- a/apps/credential-showcase-api-server/src/types/schema/index.ts +++ b/apps/credential-showcase-api-server/src/types/schema/index.ts @@ -33,7 +33,7 @@ export type NewPersona = Omit & { export type CredentialDefinition = Omit & { type: CredentialType - icon: Asset + icon?: Asset credentialSchema: CredentialSchema representations: CredentialRepresentation[] revocation?: RevocationInfo | null diff --git a/apps/credential-showcase-api-server/src/utils/mappers.ts b/apps/credential-showcase-api-server/src/utils/mappers.ts index c6d072f..92c2280 100644 --- a/apps/credential-showcase-api-server/src/utils/mappers.ts +++ b/apps/credential-showcase-api-server/src/utils/mappers.ts @@ -61,7 +61,7 @@ export const credentialDefinitionDTOFrom = (credentialDefinition: CredentialDefi credentialSchema: credentialSchemaDTOFrom(credentialDefinition.credentialSchema), representations: credentialDefinition.representations, revocation: credentialDefinition.revocation || undefined, - icon: assetDTOFrom(credentialDefinition.icon), + icon: credentialDefinition.icon ? assetDTOFrom(credentialDefinition?.icon) : undefined, } } diff --git a/packages/credential-showcase-openapi/openapi/openapi.yaml b/packages/credential-showcase-openapi/openapi/openapi.yaml index aa4a358..00d0b13 100644 --- a/packages/credential-showcase-openapi/openapi/openapi.yaml +++ b/packages/credential-showcase-openapi/openapi/openapi.yaml @@ -2571,7 +2571,6 @@ components: - version - type - credentialSchema - - icon # TODO enable back in SHOWCASE-81 # - representations - createdAt @@ -2627,7 +2626,6 @@ components: - name - version - type - - icon - credentialSchema # TODO enable back in SHOWCASE-81 # - representations