Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: enhance wallet deletion validation and add null check for orgId in schema and credential-definition #791

Merged
merged 3 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions apps/agent-service/src/repositories/agent-service.repository.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { PrismaService } from '@credebl/prisma-service';
import { Injectable, Logger } from '@nestjs/common';
import { ConflictException, Injectable, Logger } from '@nestjs/common';
// eslint-disable-next-line camelcase
import { Prisma, ledgerConfig, ledgers, org_agents, org_agents_type, org_dids, organisation, platform_config, user } from '@prisma/client';
import { ICreateOrgAgent, ILedgers, IOrgAgent, IOrgAgentsResponse, IOrgLedgers, IStoreAgent, IStoreDidDetails, IStoreOrgAgentDetails, LedgerNameSpace, OrgDid } from '../interface/agent-service.interface';
import { AgentType } from '@credebl/enum/enum';
import { AgentType, PrismaTables } from '@credebl/enum/enum';

@Injectable()
export class AgentServiceRepository {
Expand Down Expand Up @@ -490,8 +490,26 @@ export class AgentServiceRepository {
// eslint-disable-next-line camelcase
deleteOrgAgent: org_agents;
}> {
const tablesToCheck = [
`${PrismaTables.CONNECTIONS}`,
`${PrismaTables.CREDENTIALS}`,
`${PrismaTables.PRESENTATIONS}`,
`${PrismaTables.ECOSYSTEM_INVITATIONS}`,
`${PrismaTables.ECOSYSTEM_ORGS}`
];

try {
return await this.prisma.$transaction(async (prisma) => {
const referenceCounts = await Promise.all(
tablesToCheck.map(table => prisma[table].count({ where: { orgId } }))
);

referenceCounts.forEach((count, index) => {
if (0 < count) {
throw new ConflictException(`Organization ID ${orgId} is referenced in the table ${tablesToCheck[index]}`);
}
});

// Concurrently delete related records
const [orgDid, agentInvitation] = await Promise.all([
prisma.org_dids.deleteMany({ where: { orgId } }),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import {
Get,
UseFilters,
Param,
Delete
Delete,
ParseUUIDPipe
} from '@nestjs/common';
import {
ApiTags,
Expand Down Expand Up @@ -43,7 +44,7 @@ import { OrgRolesGuard } from '../authz/guards/org-roles.guard';
import { validateDid } from '@credebl/common/did.validator';
import { CreateWalletDto } from './dto/create-wallet.dto';
import { CreateNewDidDto } from './dto/create-new-did.dto';
import { AgentSpinupValidator } from '@credebl/common/cast.helper';
import { AgentSpinupValidator, TrimStringParamPipe } from '@credebl/common/cast.helper';
import { AgentConfigureDto } from './dto/agent-configure.dto';

const seedLength = 32;
Expand Down Expand Up @@ -307,7 +308,7 @@ export class AgentController {
@Roles(OrgRoles.OWNER)
@ApiResponse({ status: HttpStatus.OK, description: 'Success', type: ApiResponseDto })
async deleteWallet(
@Param('orgId') orgId: string,
@Param('orgId', TrimStringParamPipe, new ParseUUIDPipe({exceptionFactory: (): Error => { throw new BadRequestException(ResponseMessages.organisation.error.invalidOrgId); }})) orgId: string,
@User() user: user,
@Res() res: Response
): Promise<Response> {
Expand Down
3 changes: 2 additions & 1 deletion apps/api-gateway/src/organization/organization.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { validate as isValidUUID } from 'uuid';
import { UserAccessGuard } from '../authz/guards/user-access-guard';
import { GetAllOrganizationsDto } from './dtos/get-organizations.dto';
import { PrimaryDid } from './dtos/set-primary-did.dto';
import { TrimStringParamPipe } from '@credebl/common/cast.helper';

@UseFilters(CustomExceptionFilter)
@Controller('orgs')
Expand Down Expand Up @@ -544,7 +545,7 @@ export class OrganizationController {
@UseGuards(AuthGuard('jwt'))
@Roles(OrgRoles.OWNER)
async deleteOrganization(
@Param('orgId') orgId: string,
@Param('orgId', TrimStringParamPipe, new ParseUUIDPipe({exceptionFactory: (): Error => { throw new BadRequestException(ResponseMessages.organisation.error.invalidOrgId); }})) orgId: string,
@User() user: user,
@Res() res: Response
): Promise<Response> {
Expand Down
11 changes: 9 additions & 2 deletions apps/ledger/src/schema/repositories/schema.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ export class SchemaRepository {
schemaLedgerId: true,
createdBy: true,
publisherDid: true,
orgId: true,
orgId: true, // This field can be null
issuerId: true
},
orderBy: {
Expand All @@ -232,7 +232,14 @@ export class SchemaRepository {
ledgerId: payload.ledgerId
}
});
return { schemasCount, schemasResult };

// Handle null orgId in the response
const schemasWithDefaultOrgId = schemasResult.map(schema => ({
...schema,
orgId: schema.orgId || null // Replace null orgId with 'N/A' or any default value
}));

return { schemasCount, schemasResult: schemasWithDefaultOrgId };
} catch (error) {
this.logger.error(`Error in getting schemas: ${error}`);
throw error;
Expand Down
32 changes: 21 additions & 11 deletions apps/organization/repositories/organization.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Prisma, agent_invitations, org_agents, org_invitations, user, user_org_
import { CreateOrganizationDto } from '../dtos/create-organization.dto';
import { IGetDids, IDidDetails, IDidList, IGetOrgById, IGetOrganization, IPrimaryDidDetails, IUpdateOrganization, ILedgerNameSpace, OrgInvitation, ILedgerDetails } from '../interfaces/organization.interface';
import { InternalServerErrorException } from '@nestjs/common';
import { Invitation, SortValue } from '@credebl/enum/enum';
import { Invitation, PrismaTables, SortValue } from '@credebl/enum/enum';
import { PrismaService } from '@credebl/prisma-service';
import { UserOrgRolesService } from '@credebl/user-org-roles';
import { organisation } from '@prisma/client';
Expand Down Expand Up @@ -767,16 +767,16 @@ export class OrganizationRepository {
deleteOrg: IDeleteOrganization
}> {
const tablesToCheck = [
'org_agents',
'org_dids',
'agent_invitations',
'connections',
'credentials',
'presentations',
'ecosystem_invitations',
'ecosystem_orgs',
'file_upload',
'notification'
`${PrismaTables.ORG_AGENTS}`,
`${PrismaTables.ORG_DIDS}`,
`${PrismaTables.AGENT_INVITATIONS}`,
`${PrismaTables.CONNECTIONS}`,
`${PrismaTables.CREDENTIALS}`,
`${PrismaTables.PRESENTATIONS}`,
`${PrismaTables.ECOSYSTEM_INVITATIONS}`,
`${PrismaTables.ECOSYSTEM_ORGS}`,
`${PrismaTables.FILE_UPLOAD}`,
`${PrismaTables.NOTIFICATION}`
];

try {
Expand Down Expand Up @@ -812,6 +812,16 @@ export class OrganizationRepository {

const deletedOrgInvitations = await prisma.org_invitations.deleteMany({ where: { orgId: id } });

await this.prisma.schema.updateMany({
where: { orgId: id },
data: { orgId: null }
});

await this.prisma.credential_definition.updateMany({
where: { orgId: id },
data: { orgId: null }
});

// If no references are found, delete the organization
const deleteOrg = await prisma.organisation.delete({ where: { id } });

Expand Down
2 changes: 1 addition & 1 deletion apps/user/src/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ export class UserService {

try {
try {
const data = jwt.decode(refreshToken);
const data = jwt.decode(refreshToken) as jwt.JwtPayload;
const userByKeycloakId = await this.userRepository.getUserByKeycloakId(data?.sub);
const tokenResponse = await this.clientRegistrationService.getAccessToken(refreshToken, userByKeycloakId?.['clientId'], userByKeycloakId?.['clientSecret']);
return tokenResponse;
Expand Down
8 changes: 8 additions & 0 deletions libs/enum/src/enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,14 @@ export enum PromiseResult {
export enum PrismaTables {
PRESENTATIONS = 'presentations',
CREDENTIALS = 'credentials',
ORG_AGENTS = 'org_agents',
ORG_DIDS = 'org_dids',
AGENT_INVITATIONS = 'agent_invitations',
CONNECTIONS = 'connections',
ECOSYSTEM_INVITATIONS = 'ecosystem_invitations',
ECOSYSTEM_ORGS = 'ecosystem_orgs',
FILE_UPLOAD = 'file_upload',
NOTIFICATION = 'notification',
}

export enum IssuanceProcessState {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-- DropForeignKey
ALTER TABLE "credential_definition" DROP CONSTRAINT "credential_definition_orgId_fkey";

-- DropForeignKey
ALTER TABLE "schema" DROP CONSTRAINT "schema_orgId_fkey";

-- AddForeignKey
ALTER TABLE "schema" ADD CONSTRAINT "schema_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "organisation"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "credential_definition" ADD CONSTRAINT "credential_definition_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "organisation"("id") ON DELETE CASCADE ON UPDATE CASCADE;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
-- DropForeignKey
ALTER TABLE "credential_definition" DROP CONSTRAINT "credential_definition_orgId_fkey";

-- DropForeignKey
ALTER TABLE "schema" DROP CONSTRAINT "schema_orgId_fkey";

-- AlterTable
ALTER TABLE "schema" ALTER COLUMN "orgId" DROP NOT NULL;

-- AddForeignKey
ALTER TABLE "schema" ADD CONSTRAINT "schema_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "organisation"("id") ON DELETE SET NULL ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "credential_definition" ADD CONSTRAINT "credential_definition_orgId_fkey" FOREIGN KEY ("orgId") REFERENCES "organisation"("id") ON DELETE SET NULL ON UPDATE CASCADE;
8 changes: 4 additions & 4 deletions libs/prisma-service/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ model organisation {
registrationNumber String? @db.VarChar(100)
country String? @db.VarChar(100)
city String? @db.VarChar(100)
state String? @db.VarChar(100)
state String? @db.VarChar(100)
connections connections[]
credentials credentials[]
org_agents org_agents[]
Expand Down Expand Up @@ -267,8 +267,8 @@ model schema {
schemaLedgerId String @db.VarChar
publisherDid String @db.VarChar
issuerId String @db.VarChar
orgId String @db.Uuid
organisation organisation @relation(fields: [orgId], references: [id])
orgId String? @db.Uuid
organisation organisation? @relation(fields: [orgId], references: [id], onDelete: SetNull)
ledgers ledgers? @relation(fields: [ledgerId], references: [id])
ledgerId String? @db.Uuid
type String? @db.VarChar
Expand All @@ -286,7 +286,7 @@ model credential_definition {
schemaLedgerId String @db.VarChar
schemaId String @db.Uuid
revocable Boolean @default(false)
organisation organisation? @relation(fields: [orgId], references: [id])
organisation organisation? @relation(fields: [orgId], references: [id], onDelete: SetNull)
orgId String? @db.Uuid
schema schema @relation(fields: [schemaId], references: [id])
}
Expand Down