From ca108b14c82e425c7ed0ad59ed867e577da03991 Mon Sep 17 00:00:00 2001 From: Krishna Date: Sun, 25 Feb 2024 17:47:21 +0530 Subject: [PATCH] Utilility endpoint for storing endpoint and returning URL Signed-off-by: Krishna Signed-off-by: KulkarniShashank --- .../src/utilities/dtos/store-object.dto.ts | 162 +++++++++++++++++- .../src/utilities/utilities.controller.ts | 4 +- .../src/utilities/utilities.service.ts | 7 +- .../interfaces/shortening-url.interface.ts | 26 +++ apps/utility/src/utilities.controller.ts | 12 +- apps/utility/src/utilities.service.ts | 8 +- 6 files changed, 203 insertions(+), 16 deletions(-) diff --git a/apps/api-gateway/src/utilities/dtos/store-object.dto.ts b/apps/api-gateway/src/utilities/dtos/store-object.dto.ts index d52fd8f5e..d849702ea 100644 --- a/apps/api-gateway/src/utilities/dtos/store-object.dto.ts +++ b/apps/api-gateway/src/utilities/dtos/store-object.dto.ts @@ -1,11 +1,161 @@ -import { ApiExtraModels, ApiProperty } from '@nestjs/swagger'; +import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; +import { Type } from 'class-transformer'; +import { IsNotEmpty, IsOptional, IsString, IsUrl, ValidateNested } from 'class-validator'; -@ApiExtraModels() +// export type StoreObjectDto = InvitationDto; -export class StoreObjectDto { +class ServiceDto { + @ApiProperty({ + example: 'service-id' + }) + @IsString() + @IsNotEmpty({ message: 'please provide valid id' }) + id: string; + + @ApiProperty({ + example: 'http://example.com' + }) + @IsString() + @IsNotEmpty({ message: 'please provide valid serviceEndpoint' }) + @IsUrl({}, { message: 'Invalid serviceEndpoint format' }) + serviceEndpoint: string; + + @ApiProperty({ + example: 'service-type' + }) + @IsString() + @IsNotEmpty({ message: 'please provide valid type' }) + type: string; + + @ApiProperty({ + example: ['key1', 'key2'] + }) + @IsString({ each: true }) + recipientKeys: string[]; + + @ApiPropertyOptional({ + example: ['key1', 'key2'] + }) + @IsOptional() + @IsString({ each: true }) + routingKeys: string[]; + + @ApiPropertyOptional({ + example: ['true'] + }) + @IsOptional() + @IsString({ each: true }) + accept: string[]; +} + +export class InvitationDto { + @ApiPropertyOptional({ + example: 'your-id' + }) + @IsOptional() + @IsString() + @IsNotEmpty({ message: 'please provide valid @id' }) + '@id': string; @ApiProperty({ - description: 'The data to be stored' + example: 'your-type' + }) + @IsString() + @IsNotEmpty({ message: 'please provide valid @type' }) + '@type': string; + + @ApiProperty({ + example: 'your-label' + }) + @IsString() + @IsNotEmpty({ message: 'please provide valid label' }) + label: string; + + @ApiPropertyOptional({ + example: 'your-goal-code' + }) + @IsOptional() + @IsString() + @IsNotEmpty({ message: 'please provide valid goalCode' }) + goalCode: string; + + @ApiPropertyOptional({ + example: 'your-goal' + }) + @IsOptional() + @IsString() + @IsNotEmpty({ message: 'please provide valid goal' }) + goal: string; + + @ApiPropertyOptional({ + example: ['accept1', 'accept2'] + }) + @IsOptional() + @IsString({ each: true }) + accept: string[]; + + @ApiPropertyOptional({ + example: ['protocol1', 'protocol2'] + }) + @IsOptional() + @IsString({ each: true }) + // eslint-disable-next-line camelcase + handshake_protocols: string[]; + + @ApiProperty( + // { + // 'example': [ + // { + // id: 'service-id', + // serviceEndpoint: 'http://example.com', + // type: 'service-type', + // recipientKeys: ['key1', 'key2'], + // routingKeys: ['key1', 'key2'], + // accept: ['true'] + // } + // ] + // } + ) + @ValidateNested({ each: true }) + @Type(() => ServiceDto) + services: ServiceDto[]; + + @ApiPropertyOptional({ + example: 'http://example.com/image.jpg' + }) + @IsString() + @IsOptional() + @IsNotEmpty({ message: 'please provide valid imageUrl' }) + @IsString() + imageUrl?: string; +} + +export class StoreObjectDto { + @ApiProperty({ + 'example': { + '@id': 'your-id', + '@type': 'your-type', + label: 'your-label', + goalCode: 'your-goal-code', + goal: 'your-goal', + accept: ['accept1', 'accept2'], + // eslint-disable-next-line camelcase + handshake_protocols: ['protocol1', 'protocol2'], + services: [ + { + id: 'service-id', + serviceEndpoint: 'http://example.com', + type: 'service-type', + recipientKeys: ['key1', 'key2'], + routingKeys: ['key1', 'key2'], + accept: ['true'] + } + // Add more service objects as needed + ], + imageUrl: 'http://example.com/image.jpg' + } }) - data: object; -} \ No newline at end of file + @ValidateNested() + @Type(() => InvitationDto) + data: InvitationDto; +} diff --git a/apps/api-gateway/src/utilities/utilities.controller.ts b/apps/api-gateway/src/utilities/utilities.controller.ts index e0b02fa4c..b9a7af0bd 100644 --- a/apps/api-gateway/src/utilities/utilities.controller.ts +++ b/apps/api-gateway/src/utilities/utilities.controller.ts @@ -39,14 +39,16 @@ export class UtilitiesController { @Post('/store-object/:persistent') @ApiOperation({ summary: 'Store an object and return a short url to it', description: 'Create a short url representing the object' }) @ApiResponse({ status: HttpStatus.CREATED, description: 'Created', type: ApiResponseDto }) + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types async storeObject(@Body() storeObjectDto: StoreObjectDto, @Param('persistent') persistent: boolean, @Res() res: Response): Promise { // eslint-disable-next-line no-console - console.log(storeObjectDto); + console.log('Reached in api-gateway controller. The object to store is::::::: ', JSON.stringify(storeObjectDto.data)); const shorteningUrl = await this.utilitiesService.storeObject(persistent.valueOf(), storeObjectDto); const finalResponse: IResponse = { statusCode: HttpStatus.CREATED, message: ResponseMessages.storeObject.success.storeObject, data: shorteningUrl + // data: 'success' }; return res.status(HttpStatus.CREATED).json(finalResponse); } diff --git a/apps/api-gateway/src/utilities/utilities.service.ts b/apps/api-gateway/src/utilities/utilities.service.ts index 4aa7aac5f..5e27a6723 100644 --- a/apps/api-gateway/src/utilities/utilities.service.ts +++ b/apps/api-gateway/src/utilities/utilities.service.ts @@ -15,8 +15,9 @@ export class UtilitiesService extends BaseService { } async storeObject(persistent: boolean, storeObj: StoreObjectDto): Promise { - // const payload = {persistent, storeObj}; - return `This is the storeObject:::::::: ${JSON.stringify(storeObj)}`; - // return this.sendNatsMessage(this.serviceProxy, 'store-object-return-url', payload); + const payload = {persistent, storeObj}; + // eslint-disable-next-line no-console + console.log('Reached in api-gateway services. The object to store is::::::: ', JSON.stringify(payload.storeObj)); + return this.sendNatsMessage(this.serviceProxy, 'store-object-return-url', payload); } } diff --git a/apps/utility/interfaces/shortening-url.interface.ts b/apps/utility/interfaces/shortening-url.interface.ts index 00d2e3a29..755649e40 100644 --- a/apps/utility/interfaces/shortening-url.interface.ts +++ b/apps/utility/interfaces/shortening-url.interface.ts @@ -16,4 +16,30 @@ export interface IUtilities { invitationUrl: string; attributes: IAttributes[]; } +// export type StoreObjectDto = InvitationDto; +interface ServiceDto { + id: string; + serviceEndpoint: string; + type: string; + recipientKeys: string[]; + routingKeys: string[]; + accept: string[]; +} + +export interface IInvitation { + '@id': string; + '@type': string; + label: string; + goalCode: string; + goal: string; + accept: string[]; + // eslint-disable-next-line camelcase + handshake_protocols: string[]; + services: ServiceDto[]; + imageUrl?: string; +} + +export interface IStoreObject { + data: IInvitation; +} \ No newline at end of file diff --git a/apps/utility/src/utilities.controller.ts b/apps/utility/src/utilities.controller.ts index 5ddb945f4..d5481dfdd 100644 --- a/apps/utility/src/utilities.controller.ts +++ b/apps/utility/src/utilities.controller.ts @@ -1,8 +1,7 @@ import { Controller } from '@nestjs/common'; import { MessagePattern } from '@nestjs/microservices'; import { UtilitiesService } from './utilities.service'; -import { IShorteningUrlData } from '../interfaces/shortening-url.interface'; -// import { IUtilities } from '../interfaces/shortening-url.interface'; +import { IShorteningUrlData, IStoreObject } from '../interfaces/shortening-url.interface'; @Controller() export class UtilitiesController { @@ -19,7 +18,12 @@ export class UtilitiesController { } @MessagePattern({ cmd: 'store-object-return-url' }) - async storeObject(payload: {persistent: boolean, storeObj: object}): Promise { - return this.utilitiesService.storeObject(payload); + async storeObject(payload: {persistent: boolean, storeObj: IStoreObject}): Promise { + // eslint-disable-next-line no-console + console.log('Reached in Utility microservice controller. The object to store is::::::: ', JSON.stringify(payload.storeObj)); + const url:string = await this.utilitiesService.storeObject(payload); + // eslint-disable-next-line no-console + console.log('Received `url` in Utility microservice controller:::::::', url); + return url; } } \ No newline at end of file diff --git a/apps/utility/src/utilities.service.ts b/apps/utility/src/utilities.service.ts index cc373f90a..2994a1bff 100644 --- a/apps/utility/src/utilities.service.ts +++ b/apps/utility/src/utilities.service.ts @@ -4,6 +4,7 @@ import { UtilitiesRepository } from './utilities.repository'; import { AwsService } from '@credebl/aws'; // import { IUtilities } from '../interfaces/shortening-url.interface'; import { S3 } from 'aws-sdk'; +import { IStoreObject } from '../interfaces/shortening-url.interface'; @Injectable() export class UtilitiesService { @@ -49,12 +50,15 @@ export class UtilitiesService { } } - async storeObject(payload: {persistent: boolean, storeObj: object}): Promise { + async storeObject(payload: {persistent: boolean, storeObj: IStoreObject}): Promise { try { + // eslint-disable-next-line no-console + console.log('received here. StoreObj::::::', JSON.stringify(payload.storeObj.data)); const timestamp = Date.now(); - const uploadResult:S3.ManagedUpload.SendData = await this.awsService.storeObject(payload.persistent, timestamp, payload.storeObj); + const uploadResult:S3.ManagedUpload.SendData = await this.awsService.storeObject(payload.persistent, timestamp, payload.storeObj.data); const url: string = `https://${uploadResult.Bucket}.s3.${process.env.AWS_S3_STOREOBJECT_REGION}.amazonaws.com/${uploadResult.Key}`; return url; + // return 'success'; } catch (error) { throw new Error('An error occurred while uploading data to S3.'); }