From 203ba58a297167996495f90a0c43a4dd4c2c9021 Mon Sep 17 00:00:00 2001 From: bhavanakarwade Date: Wed, 20 Nov 2024 18:43:21 +0530 Subject: [PATCH] feat: archive schema for deleted wallet (#1078) * feat: archive schemas Signed-off-by: bhavanakarwade * refactor: update function name Signed-off-by: bhavanakarwade --------- Signed-off-by: bhavanakarwade --- .../src/agent-service.service.ts | 29 ++++++++++++++++ .../credential-definition.service.ts | 8 +++-- .../credential-definition.repository.ts | 8 +++-- .../schema/repositories/schema.repository.ts | 29 ++++++++++++++-- apps/ledger/src/schema/schema.controller.ts | 7 +++- apps/ledger/src/schema/schema.service.ts | 12 ++++++- .../repositories/organization.repository.ts | 7 ++-- apps/organization/src/organization.service.ts | 34 +------------------ .../migration.sql | 2 ++ libs/prisma-service/prisma/schema.prisma | 1 + 10 files changed, 94 insertions(+), 43 deletions(-) create mode 100644 libs/prisma-service/prisma/migrations/20241114081928_added_is_schema_archived_flag_schema/migration.sql diff --git a/apps/agent-service/src/agent-service.service.ts b/apps/agent-service/src/agent-service.service.ts index 93762c538..14ce2a74e 100644 --- a/apps/agent-service/src/agent-service.service.ts +++ b/apps/agent-service/src/agent-service.service.ts @@ -1722,6 +1722,11 @@ export class AgentServiceService { { records: deleteOrgAgent ? 1 : 0, tableName: 'org_agents' } ]; + const did = orgAgent?.orgDid; + + //archive schemas + await this._updateIsSchemaArchivedFlag(did); + const logDeletionActivity = async (records, tableName): Promise => { if (records) { const txnMetadata = { @@ -1745,6 +1750,30 @@ export class AgentServiceService { } } +async _updateIsSchemaArchivedFlag(did: string): Promise<{ + count: number +}> { + const pattern = { cmd: 'archive-schemas' }; + + const payload = { + did + }; + const updatedSchemaInfo = await this.agentServiceProxy + .send(pattern, payload) + .toPromise() + .catch((error) => { + this.logger.error(`catch: ${JSON.stringify(error)}`); + throw new HttpException( + { + status: error.status, + error: error.message + }, + error.status + ); + }); + return updatedSchemaInfo; +} + async receiveInvitationUrl(receiveInvitationUrl: IReceiveInvitationUrl, url: string, orgId: string): Promise { try { const getApiKey = await this.getOrgAgentApiKey(orgId); diff --git a/apps/ledger/src/credential-definition/credential-definition.service.ts b/apps/ledger/src/credential-definition/credential-definition.service.ts index 64ec8815e..4f26743dd 100644 --- a/apps/ledger/src/credential-definition/credential-definition.service.ts +++ b/apps/ledger/src/credential-definition/credential-definition.service.ts @@ -341,14 +341,18 @@ export class CredentialDefinitionService extends BaseService { return schemaResponse; } - const credDefSchemaList: CredDefSchema[] = + const credDefSchemaList = await this.credentialDefinitionRepository.getAllCredDefsByOrgIdForBulk( payload ); + if (!credDefSchemaList) { throw new NotFoundException(ResponseMessages.credentialDefinition.error.NotFound); } - return credDefSchemaList; + + const activeCredDefSchemaList = credDefSchemaList.filter((item) => !item?.['isSchemaArchived']); + + return activeCredDefSchemaList; } catch (error) { this.logger.error( `get Cred-Defs and schema List By OrgId for bulk operations: ${JSON.stringify(error)}` diff --git a/apps/ledger/src/credential-definition/repositories/credential-definition.repository.ts b/apps/ledger/src/credential-definition/repositories/credential-definition.repository.ts index 94c68ea7b..6923b49ea 100644 --- a/apps/ledger/src/credential-definition/repositories/credential-definition.repository.ts +++ b/apps/ledger/src/credential-definition/repositories/credential-definition.repository.ts @@ -243,7 +243,8 @@ export class CredentialDefinitionRepository { version: true, schemaLedgerId: true, orgId: true, - attributes: true + attributes: true, + isSchemaArchived: true } }); @@ -254,11 +255,13 @@ export class CredentialDefinitionRepository { if (matchingSchema) { return { credentialDefinitionId: credDef.credentialDefinitionId, + credentialDefinition: credDef.tag, schemaCredDefName: `${matchingSchema.name}:${matchingSchema.version}-${credDef.tag}`, schemaName: matchingSchema.name, schemaVersion: matchingSchema.version, schemaAttributes: matchingSchema.attributes, - credentialDefinition: credDef.tag + schemaLedgerId: matchingSchema.schemaLedgerId, + isSchemaArchived: matchingSchema.isSchemaArchived }; } return null; @@ -277,6 +280,7 @@ export class CredentialDefinitionRepository { return await this.prisma.schema.findMany({ where: { orgId, + isSchemaArchived: false, type: schemaType }, select: { diff --git a/apps/ledger/src/schema/repositories/schema.repository.ts b/apps/ledger/src/schema/repositories/schema.repository.ts index 264eeebf7..e4f6ce602 100644 --- a/apps/ledger/src/schema/repositories/schema.repository.ts +++ b/apps/ledger/src/schema/repositories/schema.repository.ts @@ -1,7 +1,7 @@ /* eslint-disable camelcase */ import { ConflictException, Injectable, InternalServerErrorException, Logger } from '@nestjs/common'; import { PrismaService } from '@credebl/prisma-service'; -import { ledgers, org_agents, org_agents_type, organisation, schema } from '@prisma/client'; +import { ledgers, org_agents, org_agents_type, organisation, Prisma, schema } from '@prisma/client'; import { ISchema, ISchemaExist, ISchemaSearchCriteria, ISaveSchema } from '../interfaces/schema-payload.interface'; import { ResponseMessages } from '@credebl/common/response-messages'; import { AgentDetails, ISchemasWithCount } from '../interfaces/schema.interface'; @@ -36,7 +36,8 @@ export class SchemaRepository { publisherDid: schemaResult.issuerId.split(':')[4] || schemaResult.issuerId, orgId: schemaResult.orgId, ledgerId: schemaResult.ledgerId, - type: schemaResult.type + type: schemaResult.type, + isSchemaArchived: false } }); return saveResult; @@ -77,6 +78,7 @@ export class SchemaRepository { return this.prisma.schema.findMany({ where: { type: SchemaType.INDY, + isSchemaArchived: false, name: { contains: schemaName, mode: 'insensitive' @@ -98,6 +100,7 @@ export class SchemaRepository { const schemasResult = await this.prisma.schema.findMany({ where: { organisation: { id: orgId }, + isSchemaArchived: false, OR: [ { name: { contains: payload.searchByText, mode: 'insensitive' } }, { version: { contains: payload.searchByText, mode: 'insensitive' } }, @@ -176,6 +179,24 @@ export class SchemaRepository { } } + async archiveSchemasByDid(did: string): Promise { + try { + const schemasResult = await this.prisma.schema.updateMany({ + where: { + issuerId: did + }, + data: { + isSchemaArchived: true + } + }); + + return schemasResult; + } catch (error) { + this.logger.error(`Error in archive schemas: ${error}`); + throw error; + } + } + async getAgentDetailsByOrgId(orgId: string): Promise { try { const schemasResult = await this.prisma.org_agents.findFirst({ @@ -275,6 +296,7 @@ export class SchemaRepository { schemaResult = await this.prisma.schema.findMany({ where: { ledgerId, + isSchemaArchived: false, type: schemaType, OR: [ { name: { contains: searchByText, mode: 'insensitive' } }, @@ -289,6 +311,7 @@ export class SchemaRepository { version: true, attributes: true, schemaLedgerId: true, + isSchemaArchived: true, createdBy: true, publisherDid: true, orgId: true, // This field can be null @@ -307,6 +330,7 @@ export class SchemaRepository { schemaResult = await this.prisma.schema.findMany({ where: { ledgerId, + isSchemaArchived: false, type: schemaType }, select: { @@ -315,6 +339,7 @@ export class SchemaRepository { version: true, attributes: true, schemaLedgerId: true, + isSchemaArchived: true, createdBy: true, publisherDid: true, orgId: true, // This field can be null diff --git a/apps/ledger/src/schema/schema.controller.ts b/apps/ledger/src/schema/schema.controller.ts index f696055bd..9409855dd 100644 --- a/apps/ledger/src/schema/schema.controller.ts +++ b/apps/ledger/src/schema/schema.controller.ts @@ -8,7 +8,7 @@ import { ISchemaSearchPayload, SaveSchemaPayload } from './interfaces/schema-payload.interface'; -import { schema } from '@prisma/client'; +import { Prisma, schema } from '@prisma/client'; import { ICredDefWithPagination, ISchemaData, @@ -75,6 +75,11 @@ export class SchemaController { return this.schemaService.schemaExist(payload); } + @MessagePattern({ cmd: 'archive-schemas' }) + async archiveSchemas(payload: {did: string}): Promise { + return this.schemaService.archiveSchemas(payload.did); + } + @MessagePattern({ cmd: 'store-schema-record' }) async saveSchemaRecord(payload: SaveSchemaPayload): Promise { return this.schemaService.storeSchemaDetails(payload.schemaDetails); diff --git a/apps/ledger/src/schema/schema.service.ts b/apps/ledger/src/schema/schema.service.ts index 2a9a073b8..1295879f5 100644 --- a/apps/ledger/src/schema/schema.service.ts +++ b/apps/ledger/src/schema/schema.service.ts @@ -9,7 +9,7 @@ import { import { ClientProxy, RpcException } from '@nestjs/microservices'; import { BaseService } from 'libs/service/base.service'; import { SchemaRepository } from './repositories/schema.repository'; -import { schema } from '@prisma/client'; +import { Prisma, schema } from '@prisma/client'; import { ISaveSchema, ISchema, ISchemaCredDeffSearchInterface, ISchemaExist, ISchemaSearchCriteria, W3CCreateSchema } from './interfaces/schema-payload.interface'; import { ResponseMessages } from '@credebl/common/response-messages'; import { ICreateSchema, ICreateW3CSchema, IGenericSchema, IUserRequestInterface } from './interfaces/schema.interface'; @@ -54,6 +54,7 @@ export class SchemaService extends BaseService { schema.schemaName, schema.schemaVersion ); + if (0 !== schemaExists.length) { this.logger.error(ResponseMessages.schema.error.exists); throw new ConflictException( @@ -886,6 +887,15 @@ export class SchemaService extends BaseService { } } + async archiveSchemas(did: string): Promise { + try { + const schemaDetails = await this.schemaRepository.archiveSchemasByDid(did); + return schemaDetails; + } catch (error) { + this.logger.error(`Error in archive schemas: ${error}`); + throw new RpcException(error.response ? error.response : error); + } + } async storeSchemaDetails(schemaDetails: ISaveSchema): Promise { try { diff --git a/apps/organization/repositories/organization.repository.ts b/apps/organization/repositories/organization.repository.ts index ae6be69dc..d3fd36e91 100644 --- a/apps/organization/repositories/organization.repository.ts +++ b/apps/organization/repositories/organization.repository.ts @@ -500,9 +500,12 @@ export class OrganizationRepository { ); const schemasCount = await this.prisma.schema.count({ - ...query + where: { + orgId, + isSchemaArchived: false + } }); - + const credentialsCount = await this.prisma.credentials.count({ ...query }); diff --git a/apps/organization/src/organization.service.ts b/apps/organization/src/organization.service.ts index 26b1124a8..5df40dbb2 100644 --- a/apps/organization/src/organization.service.ts +++ b/apps/organization/src/organization.service.ts @@ -28,7 +28,7 @@ import { CreateOrganizationDto } from '../dtos/create-organization.dto'; import { BulkSendInvitationDto } from '../dtos/send-invitation.dto'; import { UpdateInvitationDto } from '../dtos/update-invitation.dt'; import { DidMethod, Invitation, Ledgers, PrismaTables, transition } from '@credebl/enum/enum'; -import { IGetOrgById, IGetOrganization, IUpdateOrganization, IOrgAgent, IClientCredentials, ICreateConnectionUrl, IOrgRole, IDidList, IPrimaryDidDetails, IEcosystemOrgStatus, IOrgDetails } from '../interfaces/organization.interface'; +import { IGetOrgById, IGetOrganization, IUpdateOrganization, IClientCredentials, ICreateConnectionUrl, IOrgRole, IDidList, IPrimaryDidDetails, IEcosystemOrgStatus, IOrgDetails } from '../interfaces/organization.interface'; import { UserActivityService } from '@credebl/user-activity'; import { ClientRegistrationService } from '@credebl/client-registration/client-registration.service'; import { map } from 'rxjs/operators'; @@ -1659,38 +1659,6 @@ export class OrganizationService { return isEmailSent; } - async _deleteWallet(payload: IOrgAgent): Promise<{ - response; - }> { - try { - const pattern = { - cmd: 'delete-wallet' - }; - - return this.organizationServiceProxy - .send(pattern, payload) - .pipe( - map((response) => ({ - response - })) - ) - .toPromise() - .catch((error) => { - this.logger.error(`catch: ${JSON.stringify(error)}`); - throw new HttpException( - { - status: error.statusCode, - error: error.message - }, - error.error - ); - }); - } catch (error) { - this.logger.error(`[_deleteWallet] - error in delete wallet : ${JSON.stringify(error)}`); - throw error; - } - } - async getUserKeycloakIdByEmail(userEmails: string[]): Promise<{ response; }> { diff --git a/libs/prisma-service/prisma/migrations/20241114081928_added_is_schema_archived_flag_schema/migration.sql b/libs/prisma-service/prisma/migrations/20241114081928_added_is_schema_archived_flag_schema/migration.sql new file mode 100644 index 000000000..e8529f06a --- /dev/null +++ b/libs/prisma-service/prisma/migrations/20241114081928_added_is_schema_archived_flag_schema/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "schema" ADD COLUMN "isSchemaArchived" BOOLEAN NOT NULL DEFAULT false; diff --git a/libs/prisma-service/prisma/schema.prisma b/libs/prisma-service/prisma/schema.prisma index d8c7b6136..7d30cb45e 100644 --- a/libs/prisma-service/prisma/schema.prisma +++ b/libs/prisma-service/prisma/schema.prisma @@ -267,6 +267,7 @@ model schema { ledgers ledgers? @relation(fields: [ledgerId], references: [id]) ledgerId String? @db.Uuid type String? @db.VarChar + isSchemaArchived Boolean @default(false) credential_definition credential_definition[] }