Skip to content

Commit

Permalink
Merge pull request #364 from credebl/354-refactor-ledger-service
Browse files Browse the repository at this point in the history
refactor: Create Schema
  • Loading branch information
vivekayanworks authored Dec 20, 2023
2 parents 5a46c85 + 47f347d commit c30e9c6
Show file tree
Hide file tree
Showing 13 changed files with 155 additions and 169 deletions.
14 changes: 13 additions & 1 deletion apps/agent-service/src/agent-service.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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);
}
}

Expand Down
107 changes: 28 additions & 79 deletions apps/api-gateway/common/exception-handler.ts
Original file line number Diff line number Diff line change
@@ -1,100 +1,49 @@
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 {
private readonly logger = new Logger();
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.message ? exception.message : 'Internal server error',
error: exception['response'].message
? exception['response'].message
: 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'].message
? exception['response'].message
: 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);
}
}
6 changes: 6 additions & 0 deletions apps/api-gateway/common/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,9 @@ export interface ResponseType {
data?: Record<string, unknown> | string;
error?: Record<string, unknown> | string;
}

export interface ExceptionResponse {
message: string | string[]
error: string
statusCode: number
}
5 changes: 3 additions & 2 deletions apps/api-gateway/src/authz/guards/org-roles.guard.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
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';
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 {
Expand Down Expand Up @@ -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;
Expand Down
39 changes: 26 additions & 13 deletions apps/api-gateway/src/dtos/create-schema.dto.ts
Original file line number Diff line number Diff line change
@@ -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()
@IsNotEmpty({ message: 'attributeName is required.' })
@Transform(({ value }) => value.trim())
@Transform(({ value }) => trim(value))
@IsNotEmpty({ message: 'attributeName is required' })
attributeName: string;

@ApiProperty()
@IsString()
@IsNotEmpty({ message: 'schemaDataType is required.' })
@Transform(({ value }) => trim(value))
@IsNotEmpty({ message: 'schemaDataType is required' })
schemaDataType: string;

@ApiProperty()
@IsString()
@IsNotEmpty({ message: 'displayName is required.' })
@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: 'schemaVersion 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 must be a string' })
@Transform(({ value }) => trim(value))
@IsNotEmpty({ message: 'schemaName is required' })
schemaName: string;

@ApiProperty({
type: [AttributeValue],
'example': [
{
attributeName: 'name',
Expand All @@ -40,13 +49,17 @@ export class CreateSchemaDto {
]
})
@IsArray({ message: 'attributes must be an array' })
@IsNotEmpty({ message: 'please provide valid attributes' })
@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;
}
22 changes: 1 addition & 21 deletions apps/api-gateway/src/schema/schema.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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<object> {

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 finalResponse: IResponseType = {
statusCode: HttpStatus.CREATED,
message: 'Schema created successfully',
data: schemaDetails.response
message: schemaDetails.response
};
return res.status(HttpStatus.CREATED).json(finalResponse);
}
Expand Down
2 changes: 1 addition & 1 deletion apps/api-gateway/src/schema/schema.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions apps/ledger/src/schema/interfaces/schema.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,10 @@ export interface IOrgAgentInterface {
walletName: string;
agentsTypeId: string;
orgId: string;
}

export interface AgentDetails {
orgDid: string;
agentEndPoint: string;
tenantId: string
}
18 changes: 8 additions & 10 deletions apps/ledger/src/schema/repositories/schema.repository.ts
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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({
Expand Down Expand Up @@ -124,11 +126,7 @@ export class SchemaRepository {
}
}

async getAgentDetailsByOrgId(orgId: string): Promise<{
orgDid: string;
agentEndPoint: string;
tenantId: string
}> {
async getAgentDetailsByOrgId(orgId: string): Promise<AgentDetails> {
try {
const schemasResult = await this.prisma.org_agents.findFirst({
where: {
Expand Down Expand Up @@ -288,7 +286,7 @@ export class SchemaRepository {
}
}

async getLedgerByLedger(LedgerName: string): Promise<ledgers> {
async getLedgerByNamespace(LedgerName: string): Promise<ledgers> {
try {
return this.prisma.ledgers.findFirst({
where: {
Expand Down
Loading

0 comments on commit c30e9c6

Please sign in to comment.