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

feat: basic message #848

Merged
merged 10 commits into from
Aug 26, 2024
5 changes: 5 additions & 0 deletions apps/agent-service/src/agent-service.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,11 @@ export class AgentServiceController {
return this.agentServiceService.sendQuestion(payload.questionPayload, payload.url, payload.orgId);
}

@MessagePattern({ cmd: 'agent-send-basic-message' })
async sendBasicMessage(payload: { url, orgId, content }): Promise<object> {
return this.agentServiceService.sendBasicMessage(payload.content, payload.url, payload.orgId);
}

@MessagePattern({ cmd: 'agent-get-question-answer-record' })
async getQuestionAnswersRecord(payload: { url: string, orgId: string }): Promise<object> {
return this.agentServiceService.getQuestionAnswersRecord(payload.url, payload.orgId);
Expand Down
16 changes: 15 additions & 1 deletion apps/agent-service/src/agent-service.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ import {
AgentHealthData,
IAgentStore,
IAgentConfigure,
OrgDid
OrgDid,
IBasicMessage
} from './interface/agent-service.interface';
import { AgentSpinUpStatus, AgentType, DidMethod, Ledgers, OrgAgentType, PromiseResult } from '@credebl/enum/enum';
import { AgentServiceRepository } from './repositories/agent-service.repository';
Expand Down Expand Up @@ -1811,6 +1812,19 @@ export class AgentServiceService {
}
}

async sendBasicMessage(questionPayload: IBasicMessage, url: string, orgId: string): Promise<object> {
try {
const getApiKey = await this.getOrgAgentApiKey(orgId);
const sendQuestionRes = await this.commonService
.httpPost(url, questionPayload, { headers: { authorization: getApiKey } })
.then(async (response) => response);
return sendQuestionRes;
} catch (error) {
this.logger.error(`Error in sendBasicMessage in agent service : ${JSON.stringify(error)}`);
throw error;
}
}

async getQuestionAnswersRecord(url: string, orgId: string): Promise<object> {
try {
const getQuestionAnswersRecord = await this.agentCall(url, orgId);
Expand Down
3 changes: 3 additions & 0 deletions apps/agent-service/src/interface/agent-service.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,9 @@ export interface IQuestionPayload {
connectionId: string;
tenantId: string;
}
export interface IBasicMessage {
content: string;
}
interface Ledger {
id: string;
createDateTime: string;
Expand Down
28 changes: 27 additions & 1 deletion apps/api-gateway/src/connection/connection.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { ApiResponseDto } from '../dtos/apiResponse.dto';
import { IConnectionSearchCriteria } from '../interfaces/IConnectionSearch.interface';
import { SortFields } from 'apps/connection/src/enum/connection.enum';
import { ClientProxy} from '@nestjs/microservices';
import { QuestionAnswerWebhookDto, QuestionDto} from './dtos/question-answer.dto';
import { BasicMessageDto, QuestionAnswerWebhookDto, QuestionDto} from './dtos/question-answer.dto';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { user } from '@prisma/client';
@UseFilters(CustomExceptionFilter)
Expand Down Expand Up @@ -365,4 +365,30 @@ export class ConnectionController {
};
return res.status(HttpStatus.OK).json(finalResponse);
}

// WIP : Create final Response
@Post('/orgs/:orgId/basic-message/:connectionId')
@ApiOperation({ summary: '', description: 'send question' })
@UseGuards(AuthGuard('jwt'), OrgRolesGuard)
@Roles(OrgRoles.OWNER, OrgRoles.ADMIN, OrgRoles.ISSUER, OrgRoles.VERIFIER, OrgRoles.MEMBER, OrgRoles.HOLDER, OrgRoles.SUPER_ADMIN, OrgRoles.PLATFORM_ADMIN)
@ApiResponse({ status: HttpStatus.CREATED, description: 'Created', type: ApiResponseDto })
async sendBasicMessage(
@Param('orgId') orgId: string,
@Param('connectionId') connectionId: string,
@Body() basicMessageDto: BasicMessageDto,
@User() reqUser: IUserRequestInterface,
@Res() res: Response
): Promise<Response> {

basicMessageDto.orgId = orgId;
basicMessageDto.connectionId = connectionId;
const basicMesgResponse = await this.connectionService.sendBasicMessage(basicMessageDto);
const finalResponse: IResponse = {
statusCode: HttpStatus.CREATED,
message: ResponseMessages.connection.success.basicMessage,
data: basicMesgResponse
};
return res.status(HttpStatus.CREATED).json(finalResponse);

}
}
12 changes: 11 additions & 1 deletion apps/api-gateway/src/connection/connection.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ConnectionDto, CreateOutOfBandConnectionInvitation, ReceiveInvitationDt
import { IReceiveInvitationRes, IUserRequestInterface } from './interfaces';
import { IConnectionList, IDeletedConnectionsRecord } from '@credebl/common/interfaces/connection.interface';
import { AgentConnectionSearchCriteria, IConnectionDetailsById, IConnectionSearchCriteria } from '../interfaces/IConnectionSearch.interface';
import { QuestionDto } from './dtos/question-answer.dto';
import { BasicMessageDto, QuestionDto } from './dtos/question-answer.dto';
import { user } from '@prisma/client';
@Injectable()
export class ConnectionService extends BaseService {
Expand All @@ -24,6 +24,16 @@ export class ConnectionService extends BaseService {
}
}

sendBasicMessage(
basicMessageDto: BasicMessageDto
): Promise<object> {
try {
return this.sendNatsMessage(this.connectionServiceProxy, 'send-basic-message', basicMessageDto);
} catch (error) {
throw new RpcException(error.response);
}
}

getConnectionWebhook(
connectionDto: ConnectionDto,
orgId: string
Expand Down
11 changes: 11 additions & 0 deletions apps/api-gateway/src/connection/dtos/question-answer.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ export class QuestionDto {
connectionId: string;
}

export class BasicMessageDto {
@ApiPropertyOptional()
@IsOptional()
@IsString({ message: 'content must be a string' })
@IsNotEmpty({ message: 'please provide valid content' })
content: string;

orgId: string;
connectionId: string;
}

export class QuestionAnswerWebhookDto {


Expand Down
7 changes: 6 additions & 1 deletion apps/connection/src/connection.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
} from './interfaces/connection.interfaces';
import { IConnectionList, IDeletedConnectionsRecord } from '@credebl/common/interfaces/connection.interface';
import { IConnectionDetailsById } from 'apps/api-gateway/src/interfaces/IConnectionSearch.interface';
import { IQuestionPayload } from './interfaces/question-answer.interfaces';
import { IQuestionPayload } from './interfaces/messaging.interfaces';
import { user } from '@prisma/client';
@Controller()
export class ConnectionController {
Expand Down Expand Up @@ -101,4 +101,9 @@ export class ConnectionController {
const { orgId, userDetails } = payload;
return this.connectionService.deleteConnectionRecords(orgId, userDetails);
}

@MessagePattern({ cmd: 'send-basic-message' })
async sendBasicMessage(payload: {content: string, orgId: string, connectionId: string}): Promise<object> {
return this.connectionService.sendBasicMesage(payload);
}
}
55 changes: 53 additions & 2 deletions apps/connection/src/connection.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { Cache } from 'cache-manager';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { IConnectionList, ICreateConnectionUrl, IDeletedConnectionsRecord } from '@credebl/common/interfaces/connection.interface';
import { IConnectionDetailsById } from 'apps/api-gateway/src/interfaces/IConnectionSearch.interface';
import { IQuestionPayload } from './interfaces/question-answer.interfaces';
import { IBasicMessage, IQuestionPayload } from './interfaces/messaging.interfaces';
import { RecordType, user } from '@prisma/client';
import { UserActivityRepository } from 'libs/user-activity/repositories';
import { agent_invitations } from '@prisma/client';
Expand Down Expand Up @@ -841,5 +841,56 @@ export class ConnectionService {
this.logger.error(`[deleteConnectionRecords] - error in deleting connection records: ${JSON.stringify(error)}`);
throw new RpcException(error.response ? error.response : error);
}
}
}


async sendBasicMesage(payload: IBasicMessage): Promise<object> {
const { content, orgId, connectionId } = payload;
try {
const agentDetails = await this.connectionRepository.getAgentEndPoint(orgId);

const { agentEndPoint } = agentDetails;

if (!agentDetails) {
throw new NotFoundException(ResponseMessages.connection.error.agentEndPointNotFound);
}

const questionPayload = {
content
};

const organizationAgentType = await this.connectionRepository.getOrgAgentType(agentDetails?.orgAgentTypeId);
const label = 'send-basic-message';
const agentUrl = await this.commonService.sendBasicMessageAgentUrl(
label,
organizationAgentType,
agentEndPoint,
agentDetails?.tenantId,
connectionId
);

const sendBasicMessage = await this._sendBasicMessageToAgent(questionPayload, agentUrl, orgId);
return sendBasicMessage;
} catch (error) {
this.logger.error(`[sendBasicMesage] - error in send basic message: ${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);
}
}
}

async _sendBasicMessageToAgent(content: IBasicMessage, url: string, orgId: string): Promise<object> {
const pattern = { cmd: 'agent-send-basic-message' };
const payload = { content, url, orgId };
// eslint-disable-next-line no-return-await
return await this.natsCall(pattern, payload);
}

}
19 changes: 19 additions & 0 deletions apps/connection/src/interfaces/messaging.interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export interface IValidResponses {
text: string;
}

export interface IQuestionPayload {
detail: string;
validResponses: IValidResponses[];
question: string;
orgId?: string;
connectionId?: string;
tenantId?: string;
}

export interface IBasicMessage {
content: string;
orgId?: string;
connectionId?: string;
tenantId?: string;
}
11 changes: 0 additions & 11 deletions apps/connection/src/interfaces/question-answer.interfaces.ts

This file was deleted.

2 changes: 2 additions & 0 deletions libs/common/src/common.constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export enum CommonConstants {
URL_ACCEPT_CREDENTIALS = '/credentials/accept-offer',
URL_SEND_QUESTION = '/question-answer/question/#',
URL_QUESTION_ANSWER_RECORD = '/question-answer',
URL_SEND_BASIC_MESSAGE = '/basic-messages/#',

// SCHEMA & CRED DEF SERVICES
URL_SCHM_CREATE_SCHEMA = '/schemas',
Expand Down Expand Up @@ -119,6 +120,7 @@ export enum CommonConstants {
URL_SHAGENT_SEND_ANSWER = '/multi-tenancy/question-answer/answer/#/@',
URL_SHAGENT_QUESTION_ANSWER_RECORD = '/multi-tenancy/question-answer/#',
URL_SHAGENT_DELETE_SUB_WALLET = '/multi-tenancy/#',
URL_SHARED_SEND_BASIC_MESSAGE = '/multi-tenancy/basic-message/#/@',
URL_SHAGENT_ACCEPT_PROOF_REQUEST = '/multi-tenancy/proofs/#/accept-request/@',


Expand Down
40 changes: 39 additions & 1 deletion libs/common/src/common.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import {
HttpException,
HttpStatus,
Injectable,
Logger
Logger,
NotFoundException
} from '@nestjs/common';

import { CommonConstants } from './common.constant';
Expand All @@ -21,6 +22,7 @@ import * as dotenv from 'dotenv';
import { RpcException } from '@nestjs/microservices';
import { ResponseMessages } from './response-messages';
import { IOptionalParams } from './interfaces/interface';
import { OrgAgentType } from '@credebl/enum/enum';
dotenv.config();

@Injectable()
Expand Down Expand Up @@ -479,5 +481,41 @@ async createDynamicUrl(urlOptions: IOptionalParams): Promise<string> {
}
}

async sendBasicMessageAgentUrl(
label: string,
orgAgentType: string,
agentEndPoint: string,
tenantId?: string,
connectionId?: string
): Promise<string> {
try {
let url;
switch (label) {
case 'send-basic-message': {
url =
orgAgentType === OrgAgentType.DEDICATED
? `${agentEndPoint}${CommonConstants.URL_SEND_BASIC_MESSAGE}`.replace('#', connectionId)
: orgAgentType === OrgAgentType.SHARED
? `${agentEndPoint}${CommonConstants.URL_SHARED_SEND_BASIC_MESSAGE}`
.replace('#', connectionId)
.replace('@', tenantId)
: null;
break;
}

default: {
break;
}
}

if (!url) {
throw new NotFoundException(ResponseMessages.issuance.error.agentUrlNotFound);
}
return url;
} catch (error) {
this.logger.error(`Error in getting basic-message Url: ${JSON.stringify(error)}`);
throw error;
}
}

}
3 changes: 2 additions & 1 deletion libs/common/src/response-messages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,8 @@ export const ResponseMessages = {
fetch: 'Connections details fetched successfully',
questionAnswerRecord: 'Question Answer record fetched successfully',
questionSend: 'Question sent successfully',
deleteConnectionRecord: 'Connection records deleted'
deleteConnectionRecord: 'Connection records deleted',
basicMessage: 'Basic message sent successfully'
},
error: {
exists: 'Connection is already exist',
Expand Down