From f6423d21275d854448901e5acd9ac1b548c864dc Mon Sep 17 00:00:00 2001 From: Nishad Date: Tue, 19 Dec 2023 20:37:50 +0530 Subject: [PATCH 1/4] worked on the POST API of create schema refactoring Signed-off-by: Nishad --- apps/api-gateway/common/exception-handler.ts | 10 ++-- .../src/authz/guards/org-roles.guard.ts | 5 +- .../api-gateway/src/dtos/create-schema.dto.ts | 35 +++++++++----- .../src/schema/schema.controller.ts | 24 +--------- apps/api-gateway/src/schema/schema.service.ts | 2 +- .../src/schema/interfaces/schema.interface.ts | 6 +++ .../schema/repositories/schema.repository.ts | 18 ++++--- apps/ledger/src/schema/schema.controller.ts | 14 ++++-- apps/ledger/src/schema/schema.service.ts | 47 ++++++++++++------- libs/common/src/cast.helper.ts | 2 +- libs/common/src/response-messages/index.ts | 11 ++++- 11 files changed, 100 insertions(+), 74 deletions(-) diff --git a/apps/api-gateway/common/exception-handler.ts b/apps/api-gateway/common/exception-handler.ts index b8a21f30a..afaf5f4ea 100644 --- a/apps/api-gateway/common/exception-handler.ts +++ b/apps/api-gateway/common/exception-handler.ts @@ -64,9 +64,9 @@ export class CustomExceptionFilter extends BaseExceptionFilter { if (Array.isArray(exception['response'].message)) { errorResponse = { statusCode: exception['statusCode'] ? exception['statusCode'] : status, - message: exception.message ? exception.message : 'Internal server error', - error: exception['response'].message - ? exception['response'].message + message: exception['response'].message ? exception['response'].message : 'Internal server error', + error: exception['response'].error + ? exception['response'].error : exception['response'] ? exception['response'] : 'Internal server error' @@ -79,8 +79,8 @@ export class CustomExceptionFilter extends BaseExceptionFilter { : exception['response'] ? exception['response'] : 'Internal server error', - error: exception['response'].message - ? exception['response'].message + error: exception['response'].error + ? exception['response'].error : exception['response'] ? exception['response'] : 'Internal server error' diff --git a/apps/api-gateway/src/authz/guards/org-roles.guard.ts b/apps/api-gateway/src/authz/guards/org-roles.guard.ts index 803a7a229..45e9e50f1 100644 --- a/apps/api-gateway/src/authz/guards/org-roles.guard.ts +++ b/apps/api-gateway/src/authz/guards/org-roles.guard.ts @@ -1,4 +1,4 @@ -import { CanActivate, ExecutionContext, Logger } from '@nestjs/common'; +import { CanActivate, ExecutionContext, ForbiddenException, Logger } from '@nestjs/common'; import { HttpException } from '@nestjs/common'; import { HttpStatus } from '@nestjs/common'; @@ -6,6 +6,7 @@ import { Injectable } from '@nestjs/common'; import { OrgRoles } from 'libs/org-roles/enums'; import { ROLES_KEY } from '../decorators/roles.decorator'; import { Reflector } from '@nestjs/core'; +import { ResponseMessages } from '@credebl/common/response-messages'; @Injectable() export class OrgRolesGuard implements CanActivate { @@ -40,7 +41,7 @@ export class OrgRolesGuard implements CanActivate { }); if (!specificOrg) { - throw new HttpException('Organization does not match', HttpStatus.FORBIDDEN); + throw new ForbiddenException(ResponseMessages.organisation.error.orgNotFound, { cause: new Error(), description: ResponseMessages.errorMessages.forbidden }); } user.selectedOrg = specificOrg; diff --git a/apps/api-gateway/src/dtos/create-schema.dto.ts b/apps/api-gateway/src/dtos/create-schema.dto.ts index c776de70e..cc956644a 100644 --- a/apps/api-gateway/src/dtos/create-schema.dto.ts +++ b/apps/api-gateway/src/dtos/create-schema.dto.ts @@ -1,36 +1,45 @@ -import { IsArray, IsNotEmpty, IsOptional, IsString } from 'class-validator'; +import { IsArray, IsNotEmpty, IsOptional, IsString, ValidateNested } from 'class-validator'; -import { ApiProperty } from '@nestjs/swagger'; -import { Transform } from 'class-transformer'; +import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; +import { Transform, Type } from 'class-transformer'; +import { trim } from '@credebl/common/cast.helper'; class AttributeValue { + @ApiProperty() @IsString() + @Transform(({ value }) => trim(value)) @IsNotEmpty({ message: 'attributeName is required.' }) - @Transform(({ value }) => value.trim()) attributeName: string; + @ApiProperty() @IsString() + @Transform(({ value }) => trim(value)) @IsNotEmpty({ message: 'schemaDataType is required.' }) schemaDataType: string; + @ApiProperty() @IsString() + @Transform(({ value }) => trim(value)) @IsNotEmpty({ message: 'displayName is required.' }) displayName: string; } export class CreateSchemaDto { @ApiProperty() - @IsString({ message: 'schema version must be a string' }) - @IsNotEmpty({ message: 'please provide valid schema version' }) + @IsString({ message: 'Schema version must be a string' }) + @Transform(({ value }) => trim(value)) + @IsNotEmpty({ message: 'schemaVersion is required' }) schemaVersion: string; @ApiProperty() - @IsString({ message: 'schema name must be a string' }) - @IsNotEmpty({ message: 'please provide valid schema name' }) + @IsString({ message: 'schemaName should be string.' }) + @Transform(({ value }) => trim(value)) + @IsNotEmpty({ message: 'schemaName is required' }) schemaName: string; @ApiProperty({ + type: [AttributeValue], 'example': [ { attributeName: 'name', @@ -39,14 +48,18 @@ export class CreateSchemaDto { } ] }) - @IsArray({ message: 'attributes must be an array' }) - @IsNotEmpty({ message: 'please provide valid attributes' }) + @IsArray({ message: 'Attributes must be an array' }) + @IsNotEmpty({ message: 'attributes are required' }) + @ValidateNested({ each: true }) + @Type(() => AttributeValue) attributes: AttributeValue[]; orgId: string; - @ApiProperty() + @ApiPropertyOptional() + @Transform(({ value }) => trim(value)) @IsOptional() + @IsNotEmpty({ message: 'orgDid should not be empty' }) @IsString({ message: 'orgDid must be a string' }) orgDid: string; } diff --git a/apps/api-gateway/src/schema/schema.controller.ts b/apps/api-gateway/src/schema/schema.controller.ts index f69f3d068..9a536b007 100644 --- a/apps/api-gateway/src/schema/schema.controller.ts +++ b/apps/api-gateway/src/schema/schema.controller.ts @@ -38,7 +38,6 @@ export class SchemaController { summary: 'Get schema information from the ledger using its schema ID.', description: 'Get schema information from the ledger using its schema ID.' }) - @ApiResponse({ status: 200, description: 'Success', type: ApiResponseDto }) async getSchemaById( @Res() res: Response, @@ -174,31 +173,12 @@ export class SchemaController { @ApiResponse({ status: 201, description: 'Success', type: ApiResponseDto }) async createSchema(@Res() res: Response, @Body() schema: CreateSchemaDto, @Param('orgId') orgId: string, @User() user: IUserRequestInterface): Promise { - schema.attributes.forEach((attribute) => { - if (attribute.hasOwnProperty('attributeName') && attribute.hasOwnProperty('schemaDataType') && attribute.hasOwnProperty('displayName')) { - if (attribute.hasOwnProperty('attributeName') && '' === attribute?.attributeName) { - throw new BadRequestException('Attribute must not be empty'); - } else if (attribute.hasOwnProperty('attributeName') && '' === attribute?.attributeName?.trim()) { - throw new BadRequestException('Attributes should not contain space'); - } else if (attribute.hasOwnProperty('schemaDataType') && '' === attribute?.schemaDataType) { - throw new BadRequestException('Schema Data Type should not contain space'); - } else if (attribute.hasOwnProperty('schemaDataType') && '' === attribute?.schemaDataType?.trim()) { - throw new BadRequestException('Schema Data Type should not contain space'); - } else if (attribute.hasOwnProperty('displayName') && '' === attribute?.displayName) { - throw new BadRequestException('Display Name Type should not contain space'); - } - } else { - throw new BadRequestException('Please provide a valid attributes'); - } - }); - schema.orgId = orgId; - const schemaDetails = await this.appService.createSchema(schema, user, schema.orgId); + const schemaCreate = await this.appService.createSchema(schema, user, schema.orgId); const finalResponse: IResponseType = { statusCode: HttpStatus.CREATED, - message: 'Schema created successfully', - data: schemaDetails.response + message: schemaCreate.response }; return res.status(HttpStatus.CREATED).json(finalResponse); } diff --git a/apps/api-gateway/src/schema/schema.service.ts b/apps/api-gateway/src/schema/schema.service.ts index 84a2854b5..c3d0b710f 100644 --- a/apps/api-gateway/src/schema/schema.service.ts +++ b/apps/api-gateway/src/schema/schema.service.ts @@ -13,7 +13,7 @@ export class SchemaService extends BaseService { ) { super(`Schema Service`); } createSchema(schema: CreateSchemaDto, user: IUserRequestInterface, orgId: string): Promise<{ - response: object; + response: string; }> { const payload = { schema, user, orgId }; return this.sendNats(this.schemaServiceProxy, 'create-schema', payload); diff --git a/apps/ledger/src/schema/interfaces/schema.interface.ts b/apps/ledger/src/schema/interfaces/schema.interface.ts index 60122decd..c2f8eb05d 100644 --- a/apps/ledger/src/schema/interfaces/schema.interface.ts +++ b/apps/ledger/src/schema/interfaces/schema.interface.ts @@ -38,4 +38,10 @@ export interface IOrgAgentInterface { walletName: string; agentsTypeId: string; orgId: string; +} + +export interface AgentDetails { + orgDid: string; + agentEndPoint: string; + tenantId: string } \ No newline at end of file diff --git a/apps/ledger/src/schema/repositories/schema.repository.ts b/apps/ledger/src/schema/repositories/schema.repository.ts index aa55d1652..f822025b8 100644 --- a/apps/ledger/src/schema/repositories/schema.repository.ts +++ b/apps/ledger/src/schema/repositories/schema.repository.ts @@ -1,9 +1,10 @@ /* eslint-disable camelcase */ -import { BadRequestException, Injectable, Logger } from '@nestjs/common'; +import { ConflictException, Injectable, Logger } from '@nestjs/common'; import { PrismaService } from '@credebl/prisma-service'; import { ledgers, org_agents, org_agents_type, organisation, schema } from '@prisma/client'; import { ISchema, ISchemaSearchCriteria } from '../interfaces/schema-payload.interface'; import { ResponseMessages } from '@credebl/common/response-messages'; +import { AgentDetails } from '../interfaces/schema.interface'; @Injectable() export class SchemaRepository { @@ -21,9 +22,10 @@ export class SchemaRepository { ); const schemaLength = 0; - if (schema.length !== schemaLength) { - throw new BadRequestException( - ResponseMessages.schema.error.exists + if (schema.length !== schemaLength) { + throw new ConflictException( + ResponseMessages.schema.error.exists, + { cause: new Error(), description: ResponseMessages.errorMessages.conflict } ); } const saveResult = await this.prisma.schema.create({ @@ -124,11 +126,7 @@ export class SchemaRepository { } } - async getAgentDetailsByOrgId(orgId: string): Promise<{ - orgDid: string; - agentEndPoint: string; - tenantId: string - }> { + async getAgentDetailsByOrgId(orgId: string): Promise { try { const schemasResult = await this.prisma.org_agents.findFirst({ where: { @@ -288,7 +286,7 @@ export class SchemaRepository { } } - async getLedgerByLedger(LedgerName: string): Promise { + async getLedgerByNamespace(LedgerName: string): Promise { try { return this.prisma.ledgers.findFirst({ where: { diff --git a/apps/ledger/src/schema/schema.controller.ts b/apps/ledger/src/schema/schema.controller.ts index 6683ce899..1498de554 100644 --- a/apps/ledger/src/schema/schema.controller.ts +++ b/apps/ledger/src/schema/schema.controller.ts @@ -1,8 +1,9 @@ -import { Controller } from '@nestjs/common'; +import { BadRequestException, Controller } from '@nestjs/common'; import { SchemaService } from './schema.service'; import { MessagePattern } from '@nestjs/microservices'; import { ISchema, ISchemaCredDeffSearchInterface, ISchemaSearchInterface } from './interfaces/schema-payload.interface'; import { schema } from '@prisma/client'; +import { ResponseMessages } from '@credebl/common/response-messages'; @Controller('schema') @@ -10,9 +11,16 @@ export class SchemaController { constructor(private readonly schemaService: SchemaService) { } @MessagePattern({ cmd: 'create-schema' }) - async createSchema(payload: ISchema): Promise { + async createSchema(payload: ISchema): Promise { const { schema, user, orgId } = payload; - return this.schemaService.createSchema(schema, user, orgId); + const schemaData = this.schemaService.createSchema(schema, user, orgId); + if (!schemaData) { + throw new BadRequestException( + ResponseMessages.schema.error.invalidData, + { cause: new Error(), description: ResponseMessages.errorMessages.badRequest } + ); + } + return ResponseMessages.schema.success.create; } @MessagePattern({ cmd: 'get-schema-by-id' }) diff --git a/apps/ledger/src/schema/schema.service.ts b/apps/ledger/src/schema/schema.service.ts index 0086fde1a..7f179f449 100644 --- a/apps/ledger/src/schema/schema.service.ts +++ b/apps/ledger/src/schema/schema.service.ts @@ -43,7 +43,10 @@ export class SchemaService extends BaseService { if (0 !== schemaExists.length) { this.logger.error(ResponseMessages.schema.error.exists); - throw new ConflictException(ResponseMessages.schema.error.exists); + throw new ConflictException( + ResponseMessages.schema.error.exists, + { cause: new Error(), description: ResponseMessages.errorMessages.conflict } + ); } if (null !== schema || schema !== undefined) { @@ -54,14 +57,16 @@ export class SchemaService extends BaseService { schemaVersionIndexOf ) { throw new NotAcceptableException( - ResponseMessages.schema.error.invalidVersion + ResponseMessages.schema.error.invalidVersion, + { cause: new Error(), description: ResponseMessages.errorMessages.notAcceptable } ); } const schemaAttributeLength = 0; if (schema.attributes.length === schemaAttributeLength) { - throw new NotAcceptableException( - ResponseMessages.schema.error.insufficientAttributes + throw new NotAcceptableException( + ResponseMessages.schema.error.insufficientAttributes, + { cause: new Error(), description: ResponseMessages.errorMessages.notAcceptable } ); } else if (schema.attributes.length > schemaAttributeLength) { @@ -77,7 +82,10 @@ export class SchemaService extends BaseService { .filter((value, index, element) => element.indexOf(value) !== index); if (0 < duplicateAttributeNames.length) { - throw new ConflictException(ResponseMessages.schema.error.uniqueAttributesnames); + throw new ConflictException( + ResponseMessages.schema.error.uniqueAttributesnames, + { cause: new Error(), description: ResponseMessages.errorMessages.conflict } + ); } const attributeDisplayNamesLowerCase = trimmedAttributes.map(attribute => attribute.displayName.toLocaleLowerCase()); @@ -85,7 +93,10 @@ export class SchemaService extends BaseService { .filter((value, index, element) => element.indexOf(value) !== index); if (0 < duplicateAttributeDisplayNames.length) { - throw new ConflictException(ResponseMessages.schema.error.uniqueAttributesDisplaynames); + throw new ConflictException( + ResponseMessages.schema.error.uniqueAttributesDisplaynames, + { cause: new Error(), description: ResponseMessages.errorMessages.conflict } + ); } schema.schemaName = schema.schemaName.trim(); @@ -133,7 +144,7 @@ export class SchemaService extends BaseService { const responseObj = JSON.parse(JSON.stringify(schemaResponseFromAgentService.response)); const indyNamespace = `${did.split(':')[2]}:${did.split(':')[3]}`; - const getLedgerId = await this.schemaRepository.getLedgerByLedger(indyNamespace); + const getLedgerId = await this.schemaRepository.getLedgerByNamespace(indyNamespace); const schemaDetails: ISchema = { schema: { schemaName: '', attributes: [], schemaVersion: '', id: '' }, createdBy: `0`, @@ -178,23 +189,23 @@ export class SchemaService extends BaseService { return saveResponse; } else { - throw new NotFoundException(ResponseMessages.schema.error.notCreated); + throw new NotFoundException( + ResponseMessages.schema.error.notCreated, + { cause: new Error(), description: ResponseMessages.errorMessages.notFound } + ); } } else { - throw new RpcException( - new BadRequestException( - ResponseMessages.schema.error.emptyData - ) + throw new BadRequestException( + ResponseMessages.schema.error.emptyData, + { cause: new Error(), description: ResponseMessages.errorMessages.badRequest } ); } - } else { - throw new RpcException( - new BadRequestException( - ResponseMessages.schema.error.emptyData - ) + } else { + throw new BadRequestException( + ResponseMessages.schema.error.emptyData, + { cause: new Error(), description: ResponseMessages.errorMessages.badRequest } ); } - } catch (error) { this.logger.error( `[createSchema] - outer Error: ${JSON.stringify(error)}` diff --git a/libs/common/src/cast.helper.ts b/libs/common/src/cast.helper.ts index 5ade7f52f..4b886c1ef 100644 --- a/libs/common/src/cast.helper.ts +++ b/libs/common/src/cast.helper.ts @@ -9,7 +9,7 @@ export function toLowerCase(value: string): string { } export function trim(value: string): string { - return value.trim(); + if ('string' === typeof value) { return value.trim(); } } export function toDate(value: string): Date { diff --git a/libs/common/src/response-messages/index.ts b/libs/common/src/response-messages/index.ts index c45eb1181..0d7c9b2ec 100644 --- a/libs/common/src/response-messages/index.ts +++ b/libs/common/src/response-messages/index.ts @@ -68,7 +68,8 @@ export const ResponseMessages = { userNotFound: 'User not found for the given organization', updateUserRoles: 'Unable to update user roles', deleteOrg: 'Organization not found', - notFound: 'Organization agent not found' + notFound: 'Organization agent not found', + orgNotFound: 'Organization not found' } }, @@ -103,6 +104,7 @@ export const ResponseMessages = { }, error: { invalidSchemaId: 'Invalid schema Id provided.', + invalidData: 'Invalid data provided.', nameNotEmpty: 'Schema name is required', versionNotEmpty: 'Schema version is required', invalidVersion: 'Invalid schema version provided.', @@ -292,5 +294,12 @@ export const ResponseMessages = { mismatchedAttributes: 'Schema attributes are mismatched in the file header.', fileDetailsNotFound: 'File details not found.' } + }, + errorMessages: { + forbidden: 'Forbidden Resource', + badRequest: 'Bad Request', + conflict: 'Conflict', + notAcceptable: 'Not Acceptable', + notFound: 'Not Found' } }; \ No newline at end of file From c02c5b0cc2c9beb69c1a9c7e169fc2b29c1754e4 Mon Sep 17 00:00:00 2001 From: Nishad Date: Wed, 20 Dec 2023 13:57:30 +0530 Subject: [PATCH 2/4] Handled negative scenarios for create schema Signed-off-by: Nishad --- apps/ledger/src/schema/schema.controller.ts | 10 ++-------- apps/ledger/src/schema/schema.service.ts | 9 +-------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/apps/ledger/src/schema/schema.controller.ts b/apps/ledger/src/schema/schema.controller.ts index 1498de554..1b790ef81 100644 --- a/apps/ledger/src/schema/schema.controller.ts +++ b/apps/ledger/src/schema/schema.controller.ts @@ -1,4 +1,4 @@ -import { BadRequestException, Controller } from '@nestjs/common'; +import { Controller } from '@nestjs/common'; import { SchemaService } from './schema.service'; import { MessagePattern } from '@nestjs/microservices'; import { ISchema, ISchemaCredDeffSearchInterface, ISchemaSearchInterface } from './interfaces/schema-payload.interface'; @@ -13,13 +13,7 @@ export class SchemaController { @MessagePattern({ cmd: 'create-schema' }) async createSchema(payload: ISchema): Promise { const { schema, user, orgId } = payload; - const schemaData = this.schemaService.createSchema(schema, user, orgId); - if (!schemaData) { - throw new BadRequestException( - ResponseMessages.schema.error.invalidData, - { cause: new Error(), description: ResponseMessages.errorMessages.badRequest } - ); - } + await this.schemaService.createSchema(schema, user, orgId); return ResponseMessages.schema.success.create; } diff --git a/apps/ledger/src/schema/schema.service.ts b/apps/ledger/src/schema/schema.service.ts index 7f179f449..4d054f48c 100644 --- a/apps/ledger/src/schema/schema.service.ts +++ b/apps/ledger/src/schema/schema.service.ts @@ -210,15 +210,8 @@ export class SchemaService extends BaseService { this.logger.error( `[createSchema] - outer Error: ${JSON.stringify(error)}` ); - if (error && error?.status && error?.status?.message && error?.status?.message?.error) { - throw new RpcException({ - message: error?.status?.message?.error?.reason ? error?.status?.message?.error?.reason : error?.status?.message?.error, - statusCode: error?.status?.code - }); - } else { - throw new RpcException(error.response ? error.response : error); - } + throw new RpcException(error.response ? error.response : error); } } From bbc844e99277015451afcdfd280b8ad4da2752f2 Mon Sep 17 00:00:00 2001 From: Nishad Date: Wed, 20 Dec 2023 14:07:47 +0530 Subject: [PATCH 3/4] cosmetic changes Signed-off-by: Nishad --- apps/api-gateway/src/dtos/create-schema.dto.ts | 12 ++++++------ apps/api-gateway/src/schema/schema.controller.ts | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/api-gateway/src/dtos/create-schema.dto.ts b/apps/api-gateway/src/dtos/create-schema.dto.ts index cc956644a..7b83fbd9f 100644 --- a/apps/api-gateway/src/dtos/create-schema.dto.ts +++ b/apps/api-gateway/src/dtos/create-schema.dto.ts @@ -9,31 +9,31 @@ class AttributeValue { @ApiProperty() @IsString() @Transform(({ value }) => trim(value)) - @IsNotEmpty({ message: 'attributeName is required.' }) + @IsNotEmpty({ message: 'attributeName is required' }) attributeName: string; @ApiProperty() @IsString() @Transform(({ value }) => trim(value)) - @IsNotEmpty({ message: 'schemaDataType is required.' }) + @IsNotEmpty({ message: 'schemaDataType is required' }) schemaDataType: string; @ApiProperty() @IsString() @Transform(({ value }) => trim(value)) - @IsNotEmpty({ message: 'displayName is required.' }) + @IsNotEmpty({ message: 'displayName is required' }) displayName: string; } export class CreateSchemaDto { @ApiProperty() - @IsString({ message: 'Schema version must be a string' }) + @IsString({ message: 'schemaVersion must be a string' }) @Transform(({ value }) => trim(value)) @IsNotEmpty({ message: 'schemaVersion is required' }) schemaVersion: string; @ApiProperty() - @IsString({ message: 'schemaName should be string.' }) + @IsString({ message: 'schemaName must be a string' }) @Transform(({ value }) => trim(value)) @IsNotEmpty({ message: 'schemaName is required' }) schemaName: string; @@ -48,7 +48,7 @@ export class CreateSchemaDto { } ] }) - @IsArray({ message: 'Attributes must be an array' }) + @IsArray({ message: 'attributes must be an array' }) @IsNotEmpty({ message: 'attributes are required' }) @ValidateNested({ each: true }) @Type(() => AttributeValue) diff --git a/apps/api-gateway/src/schema/schema.controller.ts b/apps/api-gateway/src/schema/schema.controller.ts index 9a536b007..036b188e5 100644 --- a/apps/api-gateway/src/schema/schema.controller.ts +++ b/apps/api-gateway/src/schema/schema.controller.ts @@ -174,11 +174,11 @@ export class SchemaController { async createSchema(@Res() res: Response, @Body() schema: CreateSchemaDto, @Param('orgId') orgId: string, @User() user: IUserRequestInterface): Promise { schema.orgId = orgId; - const schemaCreate = await this.appService.createSchema(schema, user, schema.orgId); + const schemaDetails = await this.appService.createSchema(schema, user, schema.orgId); const finalResponse: IResponseType = { statusCode: HttpStatus.CREATED, - message: schemaCreate.response + message: schemaDetails.response }; return res.status(HttpStatus.CREATED).json(finalResponse); } From 47f347d99b0ac8bbfa6d0f5afd37fbd3c9aeaae4 Mon Sep 17 00:00:00 2001 From: Nishad Date: Wed, 20 Dec 2023 18:32:01 +0530 Subject: [PATCH 4/4] handled agent errors in the schema service Signed-off-by: Nishad --- .../src/agent-service.service.ts | 14 ++- apps/api-gateway/common/exception-handler.ts | 107 +++++------------- apps/api-gateway/common/interface.ts | 6 + apps/ledger/src/schema/schema.service.ts | 23 ++-- libs/common/src/response-messages/index.ts | 9 +- 5 files changed, 66 insertions(+), 93 deletions(-) diff --git a/apps/agent-service/src/agent-service.service.ts b/apps/agent-service/src/agent-service.service.ts index 8659486c1..6088a7cce 100644 --- a/apps/agent-service/src/agent-service.service.ts +++ b/apps/agent-service/src/agent-service.service.ts @@ -720,6 +720,12 @@ export class AgentServiceService { .then(async (schema) => { this.logger.debug(`API Response Data: ${JSON.stringify(schema)}`); return schema; + }) + .catch(error => { + throw new InternalServerErrorException( + ResponseMessages.agent.error.agentDown, + { cause: new Error(), description: ResponseMessages.errorMessages.serverError } + ); }); } else if (OrgAgentType.SHARED === payload.agentType) { @@ -735,12 +741,18 @@ export class AgentServiceService { .then(async (schema) => { this.logger.debug(`API Response Data: ${JSON.stringify(schema)}`); return schema; + }) + .catch(error => { + throw new InternalServerErrorException( + ResponseMessages.agent.error.agentDown, + { cause: new Error(), description: ResponseMessages.errorMessages.serverError } + ); }); } return schemaResponse; } catch (error) { this.logger.error(`Error in creating schema: ${error}`); - throw error; + throw new RpcException(error.response ? error.response : error); } } diff --git a/apps/api-gateway/common/exception-handler.ts b/apps/api-gateway/common/exception-handler.ts index afaf5f4ea..df5928a20 100644 --- a/apps/api-gateway/common/exception-handler.ts +++ b/apps/api-gateway/common/exception-handler.ts @@ -1,6 +1,7 @@ import { Catch, ArgumentsHost, HttpException, HttpStatus, Logger } from '@nestjs/common'; import { BaseExceptionFilter } from '@nestjs/core'; -import { isArray } from 'class-validator'; +import { ExceptionResponse } from './interface'; +import { ResponseMessages } from '@credebl/common/response-messages'; @Catch() export class CustomExceptionFilter extends BaseExceptionFilter { @@ -8,93 +9,41 @@ export class CustomExceptionFilter extends BaseExceptionFilter { catch(exception: HttpException, host: ArgumentsHost): void { const ctx = host.switchToHttp(); const response = ctx.getResponse(); - + + let errorResponse; let status = HttpStatus.INTERNAL_SERVER_ERROR; - if (exception instanceof HttpException) { - status = exception.getStatus(); - } - + this.logger.error(`exception ::: ${JSON.stringify(exception)}`); - if ("Cannot read properties of undefined (reading 'response')" === exception.message) { - exception.message = 'Oops! Something went wrong. Please try again'; - } - - let errorResponse; - if (isArray(exception)) { + if (!exception || '{}' === JSON.stringify(exception)) { errorResponse = { statusCode: status, - message: exception[0], - error: exception[0] - }; - } else if (exception && exception['statusCode'] === HttpStatus.INTERNAL_SERVER_ERROR) { - if (exception.message && exception.message['message']) { - errorResponse = { - statusCode: status, - message: exception.message['message'], - error: exception.message['message'] - }; - } else { - errorResponse = { - statusCode: status, - message: 'Oops! Something went wrong. Please try again', - error: 'Oops! Something went wrong. Please try again' - }; - } - } else if ( - exception && - exception['error'] && - exception['error'].message && - (exception['error'].statusCode || exception['error'].code) - ) { - const statusCode = exception['error'].statusCode || exception['error'].code || status; - errorResponse = { - statusCode, - message: exception['error'].message || 'Internal server error', - error: exception['error'].message || 'Internal server error' - }; - } else if (exception && exception['statusCode'] === undefined && status === HttpStatus.INTERNAL_SERVER_ERROR) { - errorResponse = { - statusCode: status, - message: 'Oops! Something went wrong. Please try again', - error: 'Oops! Something went wrong. Please try again' + message: 'Something went wrong!', + error: ResponseMessages.errorMessages.serverError }; + } + if (exception instanceof HttpException) { + status = exception.getStatus(); + } + + let exceptionResponse: ExceptionResponse; + + if (exception['response']) { + exceptionResponse = exception['response']; } else { - if (exception && exception['response'] && exception.message) { - if (Array.isArray(exception['response'].message)) { - errorResponse = { - statusCode: exception['statusCode'] ? exception['statusCode'] : status, - message: exception['response'].message ? exception['response'].message : 'Internal server error', - error: exception['response'].error - ? exception['response'].error - : exception['response'] - ? exception['response'] - : 'Internal server error' - }; - } else { - errorResponse = { - statusCode: exception['statusCode'] ? exception['statusCode'] : status, - message: exception['response'].message - ? exception['response'].message - : exception['response'] - ? exception['response'] - : 'Internal server error', - error: exception['response'].error - ? exception['response'].error - : exception['response'] - ? exception['response'] - : 'Internal server error' - }; - } - } else if (exception && exception.message) { - errorResponse = { - statusCode: exception['statusCode'] ? exception['statusCode'] : status, - message: exception.message || 'Internal server error', - error: exception.message || 'Internal server error' - }; - } + exceptionResponse = exception as unknown as ExceptionResponse; } + errorResponse = { + statusCode: exceptionResponse.statusCode ? exceptionResponse.statusCode : status, + message: exceptionResponse.message + ? exceptionResponse.message + : 'Something went wrong!', + error: exceptionResponse.error + ? exceptionResponse.error + : ResponseMessages.errorMessages.serverError + }; + response.status(errorResponse.statusCode).json(errorResponse); } } \ No newline at end of file diff --git a/apps/api-gateway/common/interface.ts b/apps/api-gateway/common/interface.ts index a64429f45..d3869d75f 100644 --- a/apps/api-gateway/common/interface.ts +++ b/apps/api-gateway/common/interface.ts @@ -4,3 +4,9 @@ export interface ResponseType { data?: Record | string; error?: Record | string; } + +export interface ExceptionResponse { + message: string | string[] + error: string + statusCode: number +} diff --git a/apps/ledger/src/schema/schema.service.ts b/apps/ledger/src/schema/schema.service.ts index 4d054f48c..ca848b0da 100644 --- a/apps/ledger/src/schema/schema.service.ts +++ b/apps/ledger/src/schema/schema.service.ts @@ -100,7 +100,14 @@ export class SchemaService extends BaseService { } schema.schemaName = schema.schemaName.trim(); - const { agentEndPoint, orgDid } = await this.schemaRepository.getAgentDetailsByOrgId(orgId); + const agentDetails = await this.schemaRepository.getAgentDetailsByOrgId(orgId); + if (!agentDetails) { + throw new NotFoundException( + ResponseMessages.schema.error.agentDetailsNotFound, + { cause: new Error(), description: ResponseMessages.errorMessages.notFound } + ); + } + const { agentEndPoint, orgDid } = agentDetails; const getAgentDetails = await this.schemaRepository.getAgentType(orgId); // eslint-disable-next-line yoda const did = schema.orgDid?.split(':').length >= 4 ? schema.orgDid : orgDid; @@ -218,7 +225,6 @@ export class SchemaService extends BaseService { async _createSchema(payload: CreateSchemaAgentRedirection): Promise<{ response: string; }> { - try { const pattern = { cmd: 'agent-create-schema' }; @@ -231,18 +237,15 @@ export class SchemaService extends BaseService { })) ).toPromise() .catch(error => { - this.logger.error(`Catch : ${JSON.stringify(error)}`); + this.logger.error(`Error in creating schema : ${JSON.stringify(error)}`); throw new HttpException( { - status: error.statusCode, - error: error.message + status: error.statusCode, + error: error.error, + message: error.message }, error.error); }); - return schemaResponse; - } catch (error) { - this.logger.error(`Error in creating schema : ${JSON.stringify(error)}`); - throw error; - } + return schemaResponse; } diff --git a/libs/common/src/response-messages/index.ts b/libs/common/src/response-messages/index.ts index 0d7c9b2ec..02a92385e 100644 --- a/libs/common/src/response-messages/index.ts +++ b/libs/common/src/response-messages/index.ts @@ -117,7 +117,8 @@ export const ResponseMessages = { notFound: 'Schema records not found', schemaIdNotFound: 'SchemaLedgerId not found', credentialDefinitionNotFound: 'No credential definition exist', - notStoredCredential: 'User credential not stored' + notStoredCredential: 'User credential not stored', + agentDetailsNotFound: 'Agent details not found' } }, credentialDefinition: { @@ -154,7 +155,8 @@ export const ResponseMessages = { notAbleToSpinUpAgent: 'Agent not able to spin-up', alreadySpinUp: 'Agent already spin-up', agentUrl: 'Agent url not exist', - agentNotExists: 'Agent not spinned up for this organization' + agentNotExists: 'Agent not spinned up for this organization', + agentDown: 'Agent is down or not spinned up' } }, connection: { @@ -300,6 +302,7 @@ export const ResponseMessages = { badRequest: 'Bad Request', conflict: 'Conflict', notAcceptable: 'Not Acceptable', - notFound: 'Not Found' + notFound: 'Not Found', + serverError: 'Internal Server error' } }; \ No newline at end of file