From 4a93b0b8eb70933341c9415acd45fa4bf9379eb5 Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Wed, 22 Apr 2026 17:55:41 +0530 Subject: [PATCH 1/9] refactor: added isPrimary flag in create issuer API Signed-off-by: pranalidhanavade --- .../interfaces/oid4vc-issuance.interfaces.ts | 1 + .../src/oid4vc-issuance.repository.ts | 23 ++++++++++++++++--- .../src/oid4vc-issuance.service.ts | 11 ++++++++- .../migration.sql | 2 ++ libs/prisma-service/prisma/schema.prisma | 2 ++ 5 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 libs/prisma-service/prisma/migrations/20260422115126_add_isprimary_flag_into_oid4vc_issuer_table/migration.sql diff --git a/apps/oid4vc-issuance/interfaces/oid4vc-issuance.interfaces.ts b/apps/oid4vc-issuance/interfaces/oid4vc-issuance.interfaces.ts index be9613ed6..d4addd5a4 100644 --- a/apps/oid4vc-issuance/interfaces/oid4vc-issuance.interfaces.ts +++ b/apps/oid4vc-issuance/interfaces/oid4vc-issuance.interfaces.ts @@ -79,6 +79,7 @@ export interface IssuerMetadata { createdById: string; orgAgentId: string; batchCredentialIssuanceSize?: number; + isPrimary: boolean; } export interface initialIssuerDetails { diff --git a/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts b/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts index b90a25abf..630c578db 100644 --- a/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts +++ b/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts @@ -190,8 +190,14 @@ export class Oid4vcIssuanceRepository { // eslint-disable-next-line @typescript-eslint/no-explicit-any async addOidcIssuerDetails(issuerMetadata: IssuerMetadata, issuerProfileJson): Promise { try { - const { publicIssuerId, createdById, orgAgentId, batchCredentialIssuanceSize, authorizationServerUrl } = - issuerMetadata; + const { + publicIssuerId, + createdById, + orgAgentId, + batchCredentialIssuanceSize, + authorizationServerUrl, + isPrimary + } = issuerMetadata; const oidcIssuerDetails = await this.prisma.oidc_issuer.create({ data: { metadata: issuerProfileJson, @@ -199,7 +205,8 @@ export class Oid4vcIssuanceRepository { createdBy: createdById, orgAgentId, batchCredentialIssuanceSize, - authorizationServerUrl + authorizationServerUrl, + isPrimary } }); @@ -210,6 +217,16 @@ export class Oid4vcIssuanceRepository { } } + async hasPrimaryIssuer(orgAgentId: string): Promise { + const count = await this.prisma.oidc_issuer.count({ + where: { + orgAgentId, + isPrimary: true + } + }); + return 0 < count; + } + async updateOidcIssuerDetails(createdById: string, issuerConfig: IssuerUpdation): Promise { try { const { issuerId, display, batchCredentialIssuanceSize } = issuerConfig; diff --git a/apps/oid4vc-issuance/src/oid4vc-issuance.service.ts b/apps/oid4vc-issuance/src/oid4vc-issuance.service.ts index 811da6aa1..76cfb32a6 100644 --- a/apps/oid4vc-issuance/src/oid4vc-issuance.service.ts +++ b/apps/oid4vc-issuance/src/oid4vc-issuance.service.ts @@ -94,6 +94,13 @@ export class Oid4vcIssuanceService { throw new NotFoundException(ResponseMessages.issuance.error.agentEndPointNotFound); } const { agentEndPoint, id: orgAgentId, orgAgentTypeId } = agentDetails; + + const hasPrimary = await this.oid4vcIssuanceRepository.hasPrimaryIssuer(orgAgentId); + console.log('orgAgentId:', orgAgentId); + + const isPrimary = !hasPrimary; + console.log('isPrimary computed:', isPrimary); + const orgAgentType = await this.oid4vcIssuanceRepository.getOrgAgentType(orgAgentTypeId); if (!orgAgentType) { throw new NotFoundException(ResponseMessages.issuance.error.orgAgentTypeNotFound); @@ -138,8 +145,10 @@ export class Oid4vcIssuanceService { publicIssuerId: issuerIdFromAgent, createdById: userDetails.id, orgAgentId, - batchCredentialIssuanceSize: issuerCreation?.batchCredentialIssuanceSize + batchCredentialIssuanceSize: issuerCreation?.batchCredentialIssuanceSize, + isPrimary }; + console.log('🚀 ~ Oid4vcIssuanceService ~ oidcIssuerCreate ~ issuerMetadata:', issuerMetadata); const addOidcIssuerDetails = await this.oid4vcIssuanceRepository.addOidcIssuerDetails( issuerMetadata, issuerCreation?.display diff --git a/libs/prisma-service/prisma/migrations/20260422115126_add_isprimary_flag_into_oid4vc_issuer_table/migration.sql b/libs/prisma-service/prisma/migrations/20260422115126_add_isprimary_flag_into_oid4vc_issuer_table/migration.sql new file mode 100644 index 000000000..8c5410708 --- /dev/null +++ b/libs/prisma-service/prisma/migrations/20260422115126_add_isprimary_flag_into_oid4vc_issuer_table/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "oidc_issuer" ADD COLUMN "isPrimary" BOOLEAN NOT NULL DEFAULT false; diff --git a/libs/prisma-service/prisma/schema.prisma b/libs/prisma-service/prisma/schema.prisma index 2ef2327c5..49084fc11 100755 --- a/libs/prisma-service/prisma/schema.prisma +++ b/libs/prisma-service/prisma/schema.prisma @@ -596,6 +596,8 @@ model oidc_issuer { templates credential_templates[] batchCredentialIssuanceSize Int @default(0) + isPrimary Boolean @default(false) + @@index([orgAgentId]) } From 4b9c648a6ff4d670628544c4e1fb2af01569341f Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Fri, 24 Apr 2026 17:18:07 +0530 Subject: [PATCH 2/9] refactor: added orgId in oid4vc issuer table along with update primary issuer Signed-off-by: pranalidhanavade --- .../oid4vc-issuance/dtos/oid4vc-issuer.dto.ts | 10 ++++- .../interfaces/oid4vc-issuance.interfaces.ts | 3 ++ .../src/oid4vc-issuance.repository.ts | 45 ++++++++++++++----- .../src/oid4vc-issuance.service.ts | 4 +- .../migration.sql | 23 ++++++++++ libs/prisma-service/prisma/schema.prisma | 2 + 6 files changed, 72 insertions(+), 15 deletions(-) create mode 100644 libs/prisma-service/prisma/migrations/20260424035744_add_orgid_to_oid4vc_issuer/migration.sql diff --git a/apps/api-gateway/src/oid4vc-issuance/dtos/oid4vc-issuer.dto.ts b/apps/api-gateway/src/oid4vc-issuance/dtos/oid4vc-issuer.dto.ts index 74eafc674..f3e670072 100644 --- a/apps/api-gateway/src/oid4vc-issuance/dtos/oid4vc-issuer.dto.ts +++ b/apps/api-gateway/src/oid4vc-issuance/dtos/oid4vc-issuer.dto.ts @@ -1,6 +1,6 @@ /* eslint-disable camelcase */ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; -import { IsString, IsOptional, IsArray, ValidateNested, IsUrl, IsInt, Min } from 'class-validator'; +import { IsString, IsOptional, IsArray, ValidateNested, IsUrl, IsInt, Min, IsBoolean } from 'class-validator'; import { Type } from 'class-transformer'; export class LogoDto { @@ -178,4 +178,12 @@ export class IssuerUpdationDto { @IsOptional() @IsInt({ message: 'batchCredentialIssuanceSize must be an integer' }) batchCredentialIssuanceSize?: number; + + @ApiPropertyOptional({ + description: 'Marks whether this issuer is the primary issuer', + example: true + }) + @IsOptional() + @IsBoolean() + isPrimary?: boolean; } diff --git a/apps/oid4vc-issuance/interfaces/oid4vc-issuance.interfaces.ts b/apps/oid4vc-issuance/interfaces/oid4vc-issuance.interfaces.ts index d4addd5a4..9cec8bb15 100644 --- a/apps/oid4vc-issuance/interfaces/oid4vc-issuance.interfaces.ts +++ b/apps/oid4vc-issuance/interfaces/oid4vc-issuance.interfaces.ts @@ -80,6 +80,7 @@ export interface IssuerMetadata { orgAgentId: string; batchCredentialIssuanceSize?: number; isPrimary: boolean; + orgId: string; } export interface initialIssuerDetails { @@ -96,6 +97,8 @@ export interface IssuerUpdation { accessTokenSignerKeyType: AccessTokenSignerKeyType; display; batchCredentialIssuanceSize?: number; + isPrimary?: boolean; + orgId: string; } export interface IAgentNatsPayload { diff --git a/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts b/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts index 630c578db..b4dc022e0 100644 --- a/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts +++ b/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts @@ -196,7 +196,8 @@ export class Oid4vcIssuanceRepository { orgAgentId, batchCredentialIssuanceSize, authorizationServerUrl, - isPrimary + isPrimary, + orgId } = issuerMetadata; const oidcIssuerDetails = await this.prisma.oidc_issuer.create({ data: { @@ -206,7 +207,8 @@ export class Oid4vcIssuanceRepository { orgAgentId, batchCredentialIssuanceSize, authorizationServerUrl, - isPrimary + isPrimary, + orgId } }); @@ -229,19 +231,38 @@ export class Oid4vcIssuanceRepository { async updateOidcIssuerDetails(createdById: string, issuerConfig: IssuerUpdation): Promise { try { - const { issuerId, display, batchCredentialIssuanceSize } = issuerConfig; - const oidcIssuerDetails = await this.prisma.oidc_issuer.update({ - where: { id: issuerId }, - data: { - metadata: display as unknown as Prisma.InputJsonValue, - createdBy: createdById, - ...(batchCredentialIssuanceSize !== undefined ? { batchCredentialIssuanceSize } : {}) + const { issuerId, display, batchCredentialIssuanceSize, isPrimary, orgId } = issuerConfig; + + return await this.prisma.$transaction(async (tx) => { + // If setting as primary → reset others in same org + if (true === isPrimary) { + await tx.oidc_issuer.updateMany({ + where: { + orgId, + isPrimary: true + }, + data: { + isPrimary: false + } + }); } - }); - return oidcIssuerDetails; + const updatedIssuer = await tx.oidc_issuer.update({ + where: { id: issuerId }, + data: { + metadata: display as unknown as Prisma.InputJsonValue, + createdBy: createdById, + ...(batchCredentialIssuanceSize !== undefined && { + batchCredentialIssuanceSize + }), + ...(isPrimary !== undefined && { isPrimary }) + } + }); + + return updatedIssuer; + }); } catch (error) { - this.logger.error(`[addOidcIssuerDetails] - error: ${JSON.stringify(error)}`); + this.logger.error(`[updateOidcIssuerDetails] - error: ${JSON.stringify(error)}`); throw error; } } diff --git a/apps/oid4vc-issuance/src/oid4vc-issuance.service.ts b/apps/oid4vc-issuance/src/oid4vc-issuance.service.ts index 76cfb32a6..a195952bb 100644 --- a/apps/oid4vc-issuance/src/oid4vc-issuance.service.ts +++ b/apps/oid4vc-issuance/src/oid4vc-issuance.service.ts @@ -146,9 +146,9 @@ export class Oid4vcIssuanceService { createdById: userDetails.id, orgAgentId, batchCredentialIssuanceSize: issuerCreation?.batchCredentialIssuanceSize, - isPrimary + isPrimary, + orgId }; - console.log('🚀 ~ Oid4vcIssuanceService ~ oidcIssuerCreate ~ issuerMetadata:', issuerMetadata); const addOidcIssuerDetails = await this.oid4vcIssuanceRepository.addOidcIssuerDetails( issuerMetadata, issuerCreation?.display diff --git a/libs/prisma-service/prisma/migrations/20260424035744_add_orgid_to_oid4vc_issuer/migration.sql b/libs/prisma-service/prisma/migrations/20260424035744_add_orgid_to_oid4vc_issuer/migration.sql new file mode 100644 index 000000000..229b9979b --- /dev/null +++ b/libs/prisma-service/prisma/migrations/20260424035744_add_orgid_to_oid4vc_issuer/migration.sql @@ -0,0 +1,23 @@ +/* + Warnings: + + - Added the required column `orgId` to the `oidc_issuer` table without a default value. This is not possible if the table is not empty. + +*/ +-- DropForeignKey +ALTER TABLE "issued_oid4vc_credentials" DROP CONSTRAINT "issued_oid4vc_credentials_orgId_fkey"; + +-- DropForeignKey +ALTER TABLE "oid4vc_credentials" DROP CONSTRAINT "oid4vc_credentials_orgId_fkey"; + +-- AlterTable +ALTER TABLE "oid4vc_credentials" ALTER COLUMN "orgId" DROP NOT NULL; + +-- AlterTable +ALTER TABLE "oidc_issuer" ADD COLUMN "orgId" UUID NOT NULL; + +-- AddForeignKey +ALTER TABLE "oid4vc_credentials" ADD CONSTRAINT "oid4vc_credentials_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "organisation"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "issued_oid4vc_credentials" ADD CONSTRAINT "issued_oid4vc_credentials_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "organisation"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/libs/prisma-service/prisma/schema.prisma b/libs/prisma-service/prisma/schema.prisma index 49084fc11..3f010a25b 100755 --- a/libs/prisma-service/prisma/schema.prisma +++ b/libs/prisma-service/prisma/schema.prisma @@ -596,6 +596,8 @@ model oidc_issuer { templates credential_templates[] batchCredentialIssuanceSize Int @default(0) + orgId String @db.Uuid + isPrimary Boolean @default(false) @@index([orgAgentId]) From b9a5c83d4242d52371ea07ff90e6b4e2c489702b Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Mon, 27 Apr 2026 11:41:19 +0530 Subject: [PATCH 3/9] fix: coderabbit suggestions Signed-off-by: pranalidhanavade --- .../src/oid4vc-issuance.repository.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts b/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts index b4dc022e0..ec3ad6cf9 100644 --- a/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts +++ b/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts @@ -234,7 +234,17 @@ export class Oid4vcIssuanceRepository { const { issuerId, display, batchCredentialIssuanceSize, isPrimary, orgId } = issuerConfig; return await this.prisma.$transaction(async (tx) => { - // If setting as primary → reset others in same org + const issuer = await tx.oidc_issuer.findFirst({ + where: { + id: issuerId, + orgId + } + }); + + if (!issuer) { + throw new Error('Issuer not found'); + } + if (true === isPrimary) { await tx.oidc_issuer.updateMany({ where: { From 1db18432974f57db80fc061d0ec75b998fbfeb67 Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Mon, 27 Apr 2026 12:29:58 +0530 Subject: [PATCH 4/9] fix: migrations for orgId and isPrimaryFlag Signed-off-by: pranalidhanavade --- .../src/oid4vc-issuance.service.ts | 2 -- .../migration.sql | 2 -- .../migration.sql | 23 ------------------- libs/prisma-service/prisma/schema.prisma | 4 ---- 4 files changed, 31 deletions(-) delete mode 100644 libs/prisma-service/prisma/migrations/20260422115126_add_isprimary_flag_into_oid4vc_issuer_table/migration.sql delete mode 100644 libs/prisma-service/prisma/migrations/20260424035744_add_orgid_to_oid4vc_issuer/migration.sql diff --git a/apps/oid4vc-issuance/src/oid4vc-issuance.service.ts b/apps/oid4vc-issuance/src/oid4vc-issuance.service.ts index a195952bb..31232e8a7 100644 --- a/apps/oid4vc-issuance/src/oid4vc-issuance.service.ts +++ b/apps/oid4vc-issuance/src/oid4vc-issuance.service.ts @@ -96,10 +96,8 @@ export class Oid4vcIssuanceService { const { agentEndPoint, id: orgAgentId, orgAgentTypeId } = agentDetails; const hasPrimary = await this.oid4vcIssuanceRepository.hasPrimaryIssuer(orgAgentId); - console.log('orgAgentId:', orgAgentId); const isPrimary = !hasPrimary; - console.log('isPrimary computed:', isPrimary); const orgAgentType = await this.oid4vcIssuanceRepository.getOrgAgentType(orgAgentTypeId); if (!orgAgentType) { diff --git a/libs/prisma-service/prisma/migrations/20260422115126_add_isprimary_flag_into_oid4vc_issuer_table/migration.sql b/libs/prisma-service/prisma/migrations/20260422115126_add_isprimary_flag_into_oid4vc_issuer_table/migration.sql deleted file mode 100644 index 8c5410708..000000000 --- a/libs/prisma-service/prisma/migrations/20260422115126_add_isprimary_flag_into_oid4vc_issuer_table/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "oidc_issuer" ADD COLUMN "isPrimary" BOOLEAN NOT NULL DEFAULT false; diff --git a/libs/prisma-service/prisma/migrations/20260424035744_add_orgid_to_oid4vc_issuer/migration.sql b/libs/prisma-service/prisma/migrations/20260424035744_add_orgid_to_oid4vc_issuer/migration.sql deleted file mode 100644 index 229b9979b..000000000 --- a/libs/prisma-service/prisma/migrations/20260424035744_add_orgid_to_oid4vc_issuer/migration.sql +++ /dev/null @@ -1,23 +0,0 @@ -/* - Warnings: - - - Added the required column `orgId` to the `oidc_issuer` table without a default value. This is not possible if the table is not empty. - -*/ --- DropForeignKey -ALTER TABLE "issued_oid4vc_credentials" DROP CONSTRAINT "issued_oid4vc_credentials_orgId_fkey"; - --- DropForeignKey -ALTER TABLE "oid4vc_credentials" DROP CONSTRAINT "oid4vc_credentials_orgId_fkey"; - --- AlterTable -ALTER TABLE "oid4vc_credentials" ALTER COLUMN "orgId" DROP NOT NULL; - --- AlterTable -ALTER TABLE "oidc_issuer" ADD COLUMN "orgId" UUID NOT NULL; - --- AddForeignKey -ALTER TABLE "oid4vc_credentials" ADD CONSTRAINT "oid4vc_credentials_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "organisation"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "issued_oid4vc_credentials" ADD CONSTRAINT "issued_oid4vc_credentials_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "organisation"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/libs/prisma-service/prisma/schema.prisma b/libs/prisma-service/prisma/schema.prisma index 3f010a25b..2ef2327c5 100755 --- a/libs/prisma-service/prisma/schema.prisma +++ b/libs/prisma-service/prisma/schema.prisma @@ -596,10 +596,6 @@ model oidc_issuer { templates credential_templates[] batchCredentialIssuanceSize Int @default(0) - orgId String @db.Uuid - - isPrimary Boolean @default(false) - @@index([orgAgentId]) } From e54db15876674ac3e9147c100178181a78f7670e Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Mon, 27 Apr 2026 13:44:47 +0530 Subject: [PATCH 5/9] feat: added orgId and isPrimary in oidc_issuer table Signed-off-by: pranalidhanavade --- .../migration.sql | 21 +++++++++++++++++++ libs/prisma-service/prisma/schema.prisma | 6 ++++++ 2 files changed, 27 insertions(+) create mode 100644 libs/prisma-service/prisma/migrations/20260427080006_added_org_id_and_is_primary_in_oidc_issuer/migration.sql diff --git a/libs/prisma-service/prisma/migrations/20260427080006_added_org_id_and_is_primary_in_oidc_issuer/migration.sql b/libs/prisma-service/prisma/migrations/20260427080006_added_org_id_and_is_primary_in_oidc_issuer/migration.sql new file mode 100644 index 000000000..20aaea3c4 --- /dev/null +++ b/libs/prisma-service/prisma/migrations/20260427080006_added_org_id_and_is_primary_in_oidc_issuer/migration.sql @@ -0,0 +1,21 @@ +-- DropForeignKey +ALTER TABLE "issued_oid4vc_credentials" DROP CONSTRAINT "issued_oid4vc_credentials_orgId_fkey"; + +-- DropForeignKey +ALTER TABLE "oid4vc_credentials" DROP CONSTRAINT "oid4vc_credentials_orgId_fkey"; + +-- AlterTable +ALTER TABLE "oid4vc_credentials" ALTER COLUMN "orgId" DROP NOT NULL; + +-- AlterTable +ALTER TABLE "oidc_issuer" ADD COLUMN "isPrimary" BOOLEAN NOT NULL DEFAULT false, +ADD COLUMN "orgId" UUID; + +-- AddForeignKey +ALTER TABLE "oidc_issuer" ADD CONSTRAINT "oidc_issuer_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "organisation"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "oid4vc_credentials" ADD CONSTRAINT "oid4vc_credentials_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "organisation"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "issued_oid4vc_credentials" ADD CONSTRAINT "issued_oid4vc_credentials_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "organisation"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/libs/prisma-service/prisma/schema.prisma b/libs/prisma-service/prisma/schema.prisma index 2ef2327c5..8e5766d27 100755 --- a/libs/prisma-service/prisma/schema.prisma +++ b/libs/prisma-service/prisma/schema.prisma @@ -162,6 +162,7 @@ model organisation { ecosystem_invitations ecosystem_invitations[] status_list_allocations status_list_allocation[] issued_oid4vc_credentials issued_oid4vc_credentials[] + oidc_issuer oidc_issuer[] } model org_invitations { @@ -596,6 +597,11 @@ model oidc_issuer { templates credential_templates[] batchCredentialIssuanceSize Int @default(0) + orgId String? @db.Uuid + isPrimary Boolean @default(false) + + organisation organisation? @relation(fields: [orgId], references: [id]) + @@index([orgAgentId]) } From 8402dbdba5bbf4aade8ff7a64c4839a4d84db463 Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Mon, 27 Apr 2026 18:27:42 +0530 Subject: [PATCH 6/9] fix: update issuer method Signed-off-by: pranalidhanavade --- .../src/oid4vc-issuance.repository.ts | 41 ++++++++++++++----- .../src/oid4vc-issuance.service.ts | 6 +-- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts b/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts index ec3ad6cf9..d922e8dd1 100644 --- a/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts +++ b/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts @@ -1,5 +1,5 @@ /* eslint-disable camelcase */ -import { Injectable, Logger, NotFoundException } from '@nestjs/common'; +import { BadRequestException, Injectable, Logger, NotFoundException } from '@nestjs/common'; // eslint-disable-next-line camelcase import { Prisma, credential_templates, oidc_issuer, org_agents } from '@prisma/client'; import { PrismaService } from '@credebl/prisma-service'; @@ -219,14 +219,19 @@ export class Oid4vcIssuanceRepository { } } - async hasPrimaryIssuer(orgAgentId: string): Promise { - const count = await this.prisma.oidc_issuer.count({ - where: { - orgAgentId, - isPrimary: true - } - }); - return 0 < count; + async hasPrimaryIssuer(orgId: string): Promise { + try { + const count = await this.prisma.oidc_issuer.count({ + where: { + orgId, + isPrimary: true + } + }); + return 0 < count; + } catch (error) { + this.logger.error(`[hasPrimaryIssuer] - error: ${JSON.stringify(error)}`); + throw error; + } } async updateOidcIssuerDetails(createdById: string, issuerConfig: IssuerUpdation): Promise { @@ -242,10 +247,18 @@ export class Oid4vcIssuanceRepository { }); if (!issuer) { - throw new Error('Issuer not found'); + throw new NotFoundException(ResponseMessages.oidcIssuer.error.notFound); } + const primaryCount = await tx.oidc_issuer.count({ + where: { + orgId, + isPrimary: true + } + }); + if (true === isPrimary) { + // unset all others await tx.oidc_issuer.updateMany({ where: { orgId, @@ -257,6 +270,14 @@ export class Oid4vcIssuanceRepository { }); } + if (false === isPrimary) { + const isOnlyPrimary = 1 === primaryCount && issuer.isPrimary; + + if (isOnlyPrimary) { + throw new BadRequestException('At least one primary issuer must exist for the organization'); + } + } + const updatedIssuer = await tx.oidc_issuer.update({ where: { id: issuerId }, data: { diff --git a/apps/oid4vc-issuance/src/oid4vc-issuance.service.ts b/apps/oid4vc-issuance/src/oid4vc-issuance.service.ts index 31232e8a7..25d9c258c 100644 --- a/apps/oid4vc-issuance/src/oid4vc-issuance.service.ts +++ b/apps/oid4vc-issuance/src/oid4vc-issuance.service.ts @@ -164,10 +164,10 @@ export class Oid4vcIssuanceService { async oidcIssuerUpdate(issuerUpdationConfig: IssuerUpdation, orgId: string, userDetails: user): Promise { try { - const getIssuerDetails = await this.oid4vcIssuanceRepository.getOidcIssuerDetailsById( + const existingIssuer = await this.oid4vcIssuanceRepository.getOidcIssuerDetailsById( issuerUpdationConfig.issuerId ); - if (!getIssuerDetails) { + if (!existingIssuer) { throw new NotFoundException(ResponseMessages.oidcIssuer.error.notFound); } const agentDetails = await this.oid4vcIssuanceRepository.getAgentEndPoint(orgId); @@ -189,7 +189,7 @@ export class Oid4vcIssuanceService { throw new InternalServerErrorException('Error in updating OID4VC Issuer details in DB'); } - const url = getAgentUrl(agentEndPoint, CommonConstants.OIDC_ISSUER_TEMPLATE, getIssuerDetails.publicIssuerId); + const url = getAgentUrl(agentEndPoint, CommonConstants.OIDC_ISSUER_TEMPLATE, existingIssuer.publicIssuerId); const issuerConfig = await this.buildOidcIssuerConfig(issuerUpdationConfig.issuerId); const updatedIssuer = await this._createOIDCTemplate(issuerConfig, url, orgId); if (updatedIssuer?.response?.statusCode && 200 !== updatedIssuer?.response?.statusCode) { From 65b9dd919f0ce3317512318037b5ea10f132ab23 Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Tue, 28 Apr 2026 12:15:35 +0530 Subject: [PATCH 7/9] fix: error handling for update issuer Signed-off-by: pranalidhanavade --- .../src/oid4vc-issuance.repository.ts | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts b/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts index d922e8dd1..bdf48d4fc 100644 --- a/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts +++ b/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts @@ -250,13 +250,6 @@ export class Oid4vcIssuanceRepository { throw new NotFoundException(ResponseMessages.oidcIssuer.error.notFound); } - const primaryCount = await tx.oidc_issuer.count({ - where: { - orgId, - isPrimary: true - } - }); - if (true === isPrimary) { // unset all others await tx.oidc_issuer.updateMany({ @@ -271,13 +264,18 @@ export class Oid4vcIssuanceRepository { } if (false === isPrimary) { - const isOnlyPrimary = 1 === primaryCount && issuer.isPrimary; + const otherPrimaryExists = await tx.oidc_issuer.count({ + where: { + orgId, + isPrimary: true, + NOT: { id: issuerId } + } + }); - if (isOnlyPrimary) { - throw new BadRequestException('At least one primary issuer must exist for the organization'); + if (0 === otherPrimaryExists) { + throw new BadRequestException('Cannot unset primary. Please assign another issuer as primary first.'); } } - const updatedIssuer = await tx.oidc_issuer.update({ where: { id: issuerId }, data: { From 0f0b8abc8ec71ddac3340b1c69f980305be8c878 Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Tue, 28 Apr 2026 13:21:22 +0530 Subject: [PATCH 8/9] fix: coderabbit suggestion Signed-off-by: pranalidhanavade --- apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts | 2 +- apps/oid4vc-issuance/src/oid4vc-issuance.service.ts | 2 +- libs/common/src/response-messages/index.ts | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts b/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts index bdf48d4fc..aa9c3e739 100644 --- a/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts +++ b/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts @@ -273,7 +273,7 @@ export class Oid4vcIssuanceRepository { }); if (0 === otherPrimaryExists) { - throw new BadRequestException('Cannot unset primary. Please assign another issuer as primary first.'); + throw new BadRequestException(ResponseMessages.oidcIssuer.error.setPrimaryIssuerFailed); } } const updatedIssuer = await tx.oidc_issuer.update({ diff --git a/apps/oid4vc-issuance/src/oid4vc-issuance.service.ts b/apps/oid4vc-issuance/src/oid4vc-issuance.service.ts index 25d9c258c..859373257 100644 --- a/apps/oid4vc-issuance/src/oid4vc-issuance.service.ts +++ b/apps/oid4vc-issuance/src/oid4vc-issuance.service.ts @@ -95,7 +95,7 @@ export class Oid4vcIssuanceService { } const { agentEndPoint, id: orgAgentId, orgAgentTypeId } = agentDetails; - const hasPrimary = await this.oid4vcIssuanceRepository.hasPrimaryIssuer(orgAgentId); + const hasPrimary = await this.oid4vcIssuanceRepository.hasPrimaryIssuer(orgId); const isPrimary = !hasPrimary; diff --git a/libs/common/src/response-messages/index.ts b/libs/common/src/response-messages/index.ts index efee0dc53..a535d3989 100644 --- a/libs/common/src/response-messages/index.ts +++ b/libs/common/src/response-messages/index.ts @@ -671,7 +671,8 @@ export const ResponseMessages = { invalidId: 'Invalid OID4VC issuer ID.', createFailed: 'Failed to create OID4VC issuer.', updateFailed: 'Failed to update OID4VC issuer.', - deleteFailed: 'Failed to delete OID4VC issuer.' + deleteFailed: 'Failed to delete OID4VC issuer.', + setPrimaryIssuerFailed: 'Cannot unset primary. Please assign another issuer as primary first.' } }, oidcTemplate: { From 9ffb283ce2be6f7868ff6a6737cd2b8a4b185857 Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Tue, 28 Apr 2026 16:13:02 +0530 Subject: [PATCH 9/9] fix: comments on PR Signed-off-by: pranalidhanavade --- .../src/oid4vc-issuance.repository.ts | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts b/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts index aa9c3e739..9baa95120 100644 --- a/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts +++ b/apps/oid4vc-issuance/src/oid4vc-issuance.repository.ts @@ -1,11 +1,12 @@ /* eslint-disable camelcase */ import { BadRequestException, Injectable, Logger, NotFoundException } from '@nestjs/common'; +import { IssuerMetadata, IssuerUpdation, OrgAgent } from '../interfaces/oid4vc-issuance.interfaces'; // eslint-disable-next-line camelcase import { Prisma, credential_templates, oidc_issuer, org_agents } from '@prisma/client'; +import { x5cKeyType, x5cRecordStatus } from '@credebl/enum/enum'; + import { PrismaService } from '@credebl/prisma-service'; -import { IssuerMetadata, IssuerUpdation, OrgAgent } from '../interfaces/oid4vc-issuance.interfaces'; import { ResponseMessages } from '@credebl/common/response-messages'; -import { x5cKeyType, x5cRecordStatus } from '@credebl/enum/enum'; import { X509CertificateRecord } from '@credebl/common/interfaces/x509.interface'; @Injectable() @@ -250,20 +251,12 @@ export class Oid4vcIssuanceRepository { throw new NotFoundException(ResponseMessages.oidcIssuer.error.notFound); } - if (true === isPrimary) { - // unset all others + if (isPrimary) { await tx.oidc_issuer.updateMany({ - where: { - orgId, - isPrimary: true - }, - data: { - isPrimary: false - } + where: { orgId, isPrimary: true }, + data: { isPrimary: false } }); - } - - if (false === isPrimary) { + } else { const otherPrimaryExists = await tx.oidc_issuer.count({ where: { orgId,