Skip to content
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
61 changes: 53 additions & 8 deletions apps/api-gateway/src/ecosystem/ecosystem.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ import { CreateEcosystemDto, PaginationGetAllEcosystem } from 'apps/ecosystem/dt
import { DeleteEcosystemOrgDto } from './dtos/delete-ecosystem-users';
import { GetEcosystemInvitationsQueryDto, UpdateEcosystemOrgStatusDto } from './dtos/ecosystem';
import { IIntentTemplateList } from '@credebl/common/interfaces/intents-template.interface';
import { IUserRequest } from '@credebl/user-request/user-request.interface';
import { CreateIntentDto } from 'apps/ecosystem/dtos/create-intent.dto';
import { UpdateIntentDto } from 'apps/ecosystem/dtos/update-intent.dto';
import { GetAllIntentTemplatesResponseDto } from '../utilities/dtos/get-all-intent-templates-response.dto';
Expand Down Expand Up @@ -264,7 +263,7 @@ export class EcosystemController {
TrimStringParamPipe,
new ParseUUIDPipe({
exceptionFactory: (): Error => {
throw new BadRequestException(ResponseMessages.organisation.error.invalidOrgId);
throw new BadRequestException(ResponseMessages.ecosystem.error.invalidOrgId);
}
})
)
Expand Down Expand Up @@ -547,6 +546,7 @@ export class EcosystemController {
async getIntentTemplatesByIntentId(
@Param(
'intentId',
TrimStringParamPipe,
new ParseUUIDPipe({
exceptionFactory: (): Error => {
throw new BadRequestException('Invalid intent ID format');
Expand Down Expand Up @@ -580,7 +580,19 @@ export class EcosystemController {
description: 'Retrieve all intent templates for a specific organization.'
})
@ApiResponse({ status: HttpStatus.OK, description: 'Intent templates retrieved successfully', type: ApiResponseDto })
async getIntentTemplatesByOrgId(@Param('orgId') orgId: string, @Res() res: Response): Promise<Response> {
async getIntentTemplatesByOrgId(
@Param(
'orgId',
TrimStringParamPipe,
new ParseUUIDPipe({
exceptionFactory: (): Error => {
throw new BadRequestException('Invalid orgId format');
}
})
)
orgId: string,
@Res() res: Response
): Promise<Response> {
const intentTemplates = await this.ecosystemService.getIntentTemplatesByOrgId(orgId);
const finalResponse: IResponse = {
statusCode: HttpStatus.OK,
Expand All @@ -605,6 +617,7 @@ export class EcosystemController {
async getIntentTemplateById(
@Param(
'id',
TrimStringParamPipe,
new ParseUUIDPipe({
exceptionFactory: (): Error => {
throw new BadRequestException(ResponseMessages.oid4vpIntentToTemplate.error.invalidId);
Expand Down Expand Up @@ -637,9 +650,18 @@ export class EcosystemController {
@ApiOperation({ summary: 'Update Intent Template', description: 'Update an existing intent template mapping.' })
@ApiResponse({ status: HttpStatus.OK, description: 'Intent template updated successfully', type: ApiResponseDto })
async updateIntentTemplate(
@Param('id') id: string,
@Param(
'id',
TrimStringParamPipe,
new ParseUUIDPipe({
exceptionFactory: (): Error => {
throw new BadRequestException(ResponseMessages.oid4vpIntentToTemplate.error.invalidId);
}
})
)
id: string,
@Body() updateIntentTemplateDto: UpdateIntentTemplateDto,
@User() user: IUserRequest,
@User() user: user,
@Res() res: Response
): Promise<Response> {
const intentTemplate = await this.ecosystemService.updateIntentTemplate(id, updateIntentTemplateDto, user);
Expand Down Expand Up @@ -741,6 +763,7 @@ export class EcosystemController {
@Res() res: Response,
@Param(
'ecosystemId',
TrimStringParamPipe,
new ParseUUIDPipe({
exceptionFactory: (): Error => {
throw new BadRequestException(ResponseMessages.ecosystem.error.invalidFormatOfEcosystemId);
Expand All @@ -749,9 +772,18 @@ export class EcosystemController {
)
ecosystemId: string,
@Query() pageDto: PaginationDto,
@Query('intentId') intentId?: string
@Query(
'intentId',
new ParseUUIDPipe({
optional: true,
exceptionFactory: (): Error => {
throw new BadRequestException(ResponseMessages.ecosystem.error.invalidFormatOfIntentId);
}
})
)
intentId?: string
Comment thread
pranalidhanavade marked this conversation as resolved.
): Promise<Response> {
const intents = await this.ecosystemService.getIntents(ecosystemId, pageDto, intentId);
const intents = await this.ecosystemService.getIntents(ecosystemId, pageDto, intentId?.trim());

return res.status(HttpStatus.OK).json({
statusCode: HttpStatus.OK,
Expand Down Expand Up @@ -781,7 +813,16 @@ export class EcosystemController {
description: 'Template details fetched successfully'
})
async getTemplateByIntentId(
@Param('orgId') orgId: string,
@Param(
'orgId',
TrimStringParamPipe,
new ParseUUIDPipe({
exceptionFactory: (): Error => {
throw new BadRequestException(ResponseMessages.ecosystem.error.invalidOrgId);
}
})
)
orgId: string,
@Res() res: Response,
@Query() pageDto: PaginationDto
): Promise<Response> {
Expand Down Expand Up @@ -816,6 +857,7 @@ export class EcosystemController {
async updateIntent(
@Param(
'ecosystemId',
TrimStringParamPipe,
new ParseUUIDPipe({
exceptionFactory: (): Error => {
throw new BadRequestException(ResponseMessages.ecosystem.error.invalidFormatOfEcosystemId);
Expand All @@ -825,6 +867,7 @@ export class EcosystemController {
ecosystemId: string,
@Param(
'intentId',
TrimStringParamPipe,
new ParseUUIDPipe({
exceptionFactory: (): Error => {
throw new BadRequestException(ResponseMessages.ecosystem.error.invalidFormatOfIntentId);
Expand Down Expand Up @@ -871,6 +914,7 @@ export class EcosystemController {
async deleteIntent(
@Param(
'ecosystemId',
TrimStringParamPipe,
new ParseUUIDPipe({
exceptionFactory: (): Error => {
throw new BadRequestException(ResponseMessages.ecosystem.error.invalidFormatOfEcosystemId);
Expand All @@ -880,6 +924,7 @@ export class EcosystemController {
ecosystemId: string,
@Param(
'intentId',
TrimStringParamPipe,
new ParseUUIDPipe({
exceptionFactory: (): Error => {
throw new BadRequestException(ResponseMessages.ecosystem.error.invalidFormatOfIntentId);
Expand Down
5 changes: 2 additions & 3 deletions apps/api-gateway/src/ecosystem/ecosystem.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
import { CreateEcosystemDto } from 'apps/ecosystem/dtos/create-ecosystem-dto';
// eslint-disable-next-line camelcase
import { user } from '@prisma/client';
import { IUserRequest } from '@credebl/user-request/user-request.interface';
import { CreateIntentDto } from 'apps/ecosystem/dtos/create-intent.dto';
import { UpdateIntentDto } from 'apps/ecosystem/dtos/update-intent.dto';
import { CreateIntentTemplateDto, UpdateIntentTemplateDto } from '../utilities/dtos/intent-template.dto';
Expand Down Expand Up @@ -143,9 +142,9 @@ export class EcosystemService {
async updateIntentTemplate(
id: string,
updateIntentTemplateDto: UpdateIntentTemplateDto,
user: IUserRequest
user: user
): Promise<object> {
const payload = { id, ...updateIntentTemplateDto, user: { id: user.userId } };
const payload = { id, ...updateIntentTemplateDto, user: { id: user.id } };
return this.natsClient.sendNatsMessage(this.serviceProxy, 'update-intent-template', payload);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsString } from 'class-validator';

import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { trim } from '@credebl/common/cast.helper';

export class GetIntentTemplateByIntentAndOrgDto {
@ApiProperty({ example: 'WEB_CHECKIN', description: 'Intent name' })
@IsNotEmpty()
@Transform(({ value }) => trim(value))
@IsNotEmpty({ message: 'intentName is required' })
@IsString()
intentName: string;

@ApiProperty({ example: '123e4567-e89b-12d3-a456-426614174000', description: 'Verifier Organization ID' })
@IsNotEmpty()
@Transform(({ value }) => trim(value))
@IsNotEmpty({ message: 'verifierOrgId is required' })
@IsString()
verifierOrgId: string;
}
5 changes: 3 additions & 2 deletions apps/api-gateway/src/utilities/dtos/intent-template.dto.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsOptional, IsUUID } from 'class-validator';

import { ApiProperty } from '@nestjs/swagger';

export class CreateIntentTemplateDto {
@ApiProperty({ example: '123e4567-e89b-12d3-a456-426614174000', description: 'Organization ID' })
@IsOptional()
Expand All @@ -20,7 +21,7 @@ export class CreateIntentTemplateDto {

export class UpdateIntentTemplateDto {
@ApiProperty({ example: '123e4567-e89b-12d3-a456-426614174000', description: 'Organization ID' })
@IsNotEmpty()
@IsOptional()
@IsUUID()
orgId: string;

Expand Down
12 changes: 6 additions & 6 deletions apps/ecosystem/repositories/ecosystem.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ export class EcosystemRepository {
}

// eslint-disable-next-line camelcase
async getIntentTemplateById(id: string): Promise<intent_templates> {
async getIntentTemplateById(id: string): Promise<intent_templates | null> {
try {
const intentTemplate = await this.prisma.intent_templates.findUnique({
where: { id },
Expand All @@ -650,10 +650,8 @@ export class EcosystemRepository {
template: true
}
});
if (!intentTemplate) {
throw new NotFoundException('Intent template not found');
}
this.logger.log(`[getIntentTemplateById] - Intent template details ${id}`);

this.logger.log(`[getIntentTemplateById] fetched id ${id}`);
return intentTemplate;
} catch (error) {
this.logger.error(`Error in getIntentTemplateById: ${error}`);
Expand Down Expand Up @@ -772,7 +770,9 @@ export class EcosystemRepository {
async deleteIntentTemplate(id: string): Promise<intent_templates> {
try {
const intentTemplate = await this.prisma.intent_templates.delete({
where: { id }
where: {
id
}
});

this.logger.log(`[deleteIntentTemplate] - Intent template deleted with id ${id}`);
Expand Down
13 changes: 6 additions & 7 deletions apps/ecosystem/src/ecosystem.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,13 +213,13 @@ export class EcosystemController {
}

@MessagePattern({ cmd: 'get-intent-templates-by-intent-id' })
async getIntentTemplatesByIntentId(intentId: string): Promise<object[]> {
return this.ecosystemService.getIntentTemplatesByIntentId(intentId);
async getIntentTemplatesByIntentId(payload: { intentId: string }): Promise<object[]> {
return this.ecosystemService.getIntentTemplatesByIntentId(payload.intentId);
}

@MessagePattern({ cmd: 'get-intent-templates-by-org-id' })
async getIntentTemplatesByOrgId(orgId: string): Promise<object[]> {
return this.ecosystemService.getIntentTemplatesByOrgId(orgId);
async getIntentTemplatesByOrgId(payload: { orgId: string }): Promise<object[]> {
return this.ecosystemService.getIntentTemplatesByOrgId(payload.orgId);
}

@MessagePattern({ cmd: 'get-all-intent-templates-by-query' })
Expand Down Expand Up @@ -254,10 +254,9 @@ export class EcosystemController {
}

@MessagePattern({ cmd: 'delete-intent-template' })
async deleteIntentTemplate(id: string): Promise<object> {
return this.ecosystemService.deleteIntentTemplate(id);
async deleteIntentTemplate(payload: { id: string }): Promise<object> {
return this.ecosystemService.deleteIntentTemplate(payload.id);
}

/**
* Create a new intent
*
Expand Down
65 changes: 57 additions & 8 deletions apps/ecosystem/src/ecosystem.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,14 @@ export class EcosystemService {

async getIntentTemplatesByIntentId(intentId: string): Promise<object[]> {
try {
const intent = await this.ecosystemRepository.findIntentById(intentId);

if (!intent) {
throw new RpcException({
statusCode: HttpStatus.NOT_FOUND,
message: ResponseMessages.ecosystem.error.intentNotFound
});
}
return await this.ecosystemRepository.getIntentTemplates({ intentId });
} catch (error) {
const errorResponse = ErrorHandler.categorize(error, 'Failed to retrieve intent templates');
Expand Down Expand Up @@ -644,15 +652,50 @@ export class EcosystemService {
data: { orgId: string; intentId: string; templateId: string; user: { id: string } }
): Promise<object> {
try {
const { user, ...templateData } = data;
const { user, orgId, intentId, templateId } = data;

if (!user?.id) {
throw new RpcException({
statusCode: HttpStatus.BAD_REQUEST,
message: 'user is required'
});
}

if (!intentId || !templateId) {
throw new RpcException({
statusCode: HttpStatus.BAD_REQUEST,
message: 'intentId and templateId are required'
});
}
Comment thread
pranalidhanavade marked this conversation as resolved.

const existing = await this.ecosystemRepository.getIntentTemplateById(id);

if (!existing) {
throw new RpcException({
statusCode: HttpStatus.NOT_FOUND,
message: `Intent template not found for id ${id}`
});
}

const duplicate = await this.ecosystemRepository.findIntentTemplate({
orgId,
intentId,
templateId
});

if (duplicate && duplicate.id !== id) {
const scope = orgId ? `org ${orgId}` : 'globally';

throw new RpcException({
statusCode: HttpStatus.CONFLICT,
message: `A template is already assigned to this intent for ${scope}.`
});
}

return await this.ecosystemRepository.updateIntentTemplate(id, {
...templateData,
orgId,
intentId,
templateId,
lastChangedBy: user.id
});
} catch (error) {
Expand Down Expand Up @@ -685,11 +728,11 @@ export class EcosystemService {
async createIntent(createIntentDto: CreateIntentDto): Promise<object> {
try {
const { name, description, ecosystemId, userId } = createIntentDto;
const ecosystem = await this.ecosystemRepository.getEcosystemById(ecosystemId);

if (!name || !ecosystemId || !userId) {
throw new BadRequestException('name, ecosystemId and userId are required');
if (!ecosystem) {
throw new NotFoundException(ResponseMessages.ecosystem.error.ecosystemNotFound);
}
Comment on lines +731 to 735

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Dead code: getEcosystemById never returns null.

The repository method getEcosystemById (Line 614–627 of ecosystem.repository.ts) throws NotFoundException when the ecosystem is not found, so it never returns a falsy value. The if (!ecosystem) check here is unreachable. The same applies to getIntents at Lines 761–765.

Either remove the dead checks or change the repository to return null (like getIntentTemplateById was changed in this PR) and handle the not-found case here.

🤖 Prompt for AI Agents
In `@apps/ecosystem/src/ecosystem.service.ts` around lines 731 - 735, The
null-checks in ecosystem.service.ts are dead because
ecosystemRepository.getEcosystemById and getIntents already throw
NotFoundException on missing records; remove the unreachable guards (the if
(!ecosystem) throw ... block around the call to getEcosystemById and the
analogous if (!intents) check around getIntents) so the service relies on the
repository to raise NotFoundException, or alternatively change the repository
methods (getEcosystemById/getIntents) to return null and move the
NotFoundException into the service—pick one consistent approach (prefer removing
the redundant checks in the service to match current repository behavior).


return this.ecosystemRepository.createIntent({
name,
description,
Expand All @@ -715,6 +758,12 @@ export class EcosystemService {
intentId?: string
): Promise<PaginatedResponse<object>> {
try {
const ecosystem = await this.ecosystemRepository.getEcosystemById(ecosystemId);

if (!ecosystem) {
throw new NotFoundException(ResponseMessages.ecosystem.error.ecosystemNotFound);
}

return await this.ecosystemRepository.getIntents(ecosystemId, pageDetail, intentId);
} catch (error) {
const errorResponse = ErrorHandler.categorize(error, 'Failed to retrieve intents');
Expand All @@ -739,10 +788,10 @@ export class EcosystemService {
*/
async updateIntent(updateIntentDto: UpdateIntentDto): Promise<object> {
try {
const { intentId, ecosystemId, userId, name, description } = updateIntentDto;
const { userId, name, description } = updateIntentDto;

if (!intentId || !ecosystemId || !userId) {
throw new BadRequestException('intentId, ecosystemId and userId are required');
if (!userId) {
throw new BadRequestException(ResponseMessages.ecosystem.error.userIdMissing);
}
Comment thread
pranalidhanavade marked this conversation as resolved.

const intent = await this.ecosystemRepository.updateIntent({
Expand Down
Loading