diff --git a/apps/api-gateway/src/verification/dto/get-all-proof-requests.dto.ts b/apps/api-gateway/src/verification/dto/get-all-proof-requests.dto.ts index 5ed8cc376..6c8a8920d 100644 --- a/apps/api-gateway/src/verification/dto/get-all-proof-requests.dto.ts +++ b/apps/api-gateway/src/verification/dto/get-all-proof-requests.dto.ts @@ -1,27 +1,41 @@ -import { ApiProperty } from "@nestjs/swagger"; -import { Type } from "class-transformer"; -import { IsOptional } from "class-validator"; -import { SortValue } from "../../enum"; +import { ApiProperty } from '@nestjs/swagger'; +import { Transform, Type } from 'class-transformer'; +import { IsEnum, IsOptional } from 'class-validator'; +import { SortValue } from '../../enum'; +import { trim } from '@credebl/common/cast.helper'; +import { SortFields } from '../enum/verification.enum'; export class GetAllProofRequestsDto { - @ApiProperty({ required: false }) + @ApiProperty({ required: false, example: '1' }) @IsOptional() pageNumber: number = 1; - + @ApiProperty({ required: false }) @IsOptional() + @Transform(({ value }) => trim(value)) @Type(() => String) searchByText: string = ''; - - @ApiProperty({ required: false }) + + @ApiProperty({ required: false, example: '10' }) @IsOptional() pageSize: number = 10; - - @ApiProperty({ required: false }) + + @ApiProperty({ + enum: [SortValue.DESC, SortValue.ASC], + required: false + }) + @Transform(({ value }) => trim(value)) @IsOptional() - sortByValue: string = SortValue.DESC; - - @ApiProperty({ required: false }) + @IsEnum(SortValue) + sortBy: string = SortValue.DESC; + + @ApiProperty({ + required: false + }) + @Transform(({ value }) => trim(value)) @IsOptional() - sorting: string = 'id'; + @IsEnum(SortFields) + sortField: string = SortFields.CREATED_DATE_TIME; + } + diff --git a/apps/api-gateway/src/verification/enum/verification.enum.ts b/apps/api-gateway/src/verification/enum/verification.enum.ts new file mode 100644 index 000000000..bcb8ab6fc --- /dev/null +++ b/apps/api-gateway/src/verification/enum/verification.enum.ts @@ -0,0 +1,6 @@ +export enum SortFields { + CREATED_DATE_TIME = 'createDateTime', + STATUS = 'state', + CONNECTION_ID = 'connectionId', + PRESENTATION_ID = 'presentationId' +} \ No newline at end of file diff --git a/apps/api-gateway/src/verification/interfaces/verification.interface.ts b/apps/api-gateway/src/verification/interfaces/verification.interface.ts index b23294011..118b2a977 100644 --- a/apps/api-gateway/src/verification/interfaces/verification.interface.ts +++ b/apps/api-gateway/src/verification/interfaces/verification.interface.ts @@ -8,11 +8,12 @@ export interface IProofRequestAttribute { credentialName: string; } -export interface IProofRequestsSearchCriteria { +export interface IProofRequestSearchCriteria { pageNumber: number; pageSize: number; - sorting: string; - sortByValue: string; + sortField: string; + sortBy: string; searchByText: string; user?: IUserRequestInterface } + diff --git a/apps/api-gateway/src/verification/verification.controller.ts b/apps/api-gateway/src/verification/verification.controller.ts index 86746f412..c1f6c0328 100644 --- a/apps/api-gateway/src/verification/verification.controller.ts +++ b/apps/api-gateway/src/verification/verification.controller.ts @@ -18,7 +18,7 @@ import { UnauthorizedErrorDto } from '../dtos/unauthorized-error.dto'; import { ForbiddenErrorDto } from '../dtos/forbidden-error.dto'; import { OutOfBandRequestProof, RequestProof } from './dto/request-proof.dto'; import { VerificationService } from './verification.service'; -import IResponseType from '@credebl/common/interfaces/response.interface'; +import IResponseType, { IResponse } from '@credebl/common/interfaces/response.interface'; import { Response } from 'express'; import { ResponseMessages } from '@credebl/common/response-messages'; import { IUserRequest } from '@credebl/user-request/user-request.interface'; @@ -31,7 +31,8 @@ import { CustomExceptionFilter } from 'apps/api-gateway/common/exception-handler import { ImageServiceService } from '@credebl/image-service'; import { User } from '../authz/decorators/user.decorator'; import { GetAllProofRequestsDto } from './dto/get-all-proof-requests.dto'; -import { IProofRequestsSearchCriteria } from './interfaces/verification.interface'; +import { IProofRequestSearchCriteria } from './interfaces/verification.interface'; +import { SortFields } from './enum/verification.enum'; @UseFilters(CustomExceptionFilter) @Controller() @@ -107,43 +108,21 @@ export class VerificationController { * Get all proof presentations * @param user * @param orgId - * @returns Get all proof presentation + * @returns All proof presentations details */ @Get('/orgs/:orgId/proofs') @ApiOperation({ - summary: `Get all proof presentations`, - description: `Get all proof presentations` - }) - - @ApiQuery({ - name: 'pageNumber', - type: Number, - required: false + summary: `Get all proof presentations by orgId`, + description: `Get all proof presentations by orgId` }) @ApiQuery({ - name: 'pageSize', - type: Number, + name: 'sortField', + enum: SortFields, required: false - }) - @ApiQuery({ - name: 'searchByText', - type: String, - required: false - }) - @ApiQuery({ - name: 'sorting', - type: String, - required: false - }) - @ApiQuery({ - name: 'sortByValue', - type: String, - required: false - }) - - @ApiResponse({ status: 200, description: 'Success', type: ApiResponseDto }) - @ApiUnauthorizedResponse({ status: 401, description: 'Unauthorized', type: UnauthorizedErrorDto }) - @ApiForbiddenResponse({ status: 403, description: 'Forbidden', type: ForbiddenErrorDto }) + }) + @ApiResponse({ status: HttpStatus.OK, description: 'Success', type: ApiResponseDto }) + @ApiUnauthorizedResponse({ status: HttpStatus.UNAUTHORIZED, description: 'Unauthorized', type: UnauthorizedErrorDto }) + @ApiForbiddenResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden', type: ForbiddenErrorDto }) @ApiBearerAuth() @Roles(OrgRoles.OWNER, OrgRoles.ADMIN, OrgRoles.ISSUER, OrgRoles.VERIFIER, OrgRoles.MEMBER, OrgRoles.HOLDER) @UseGuards(AuthGuard('jwt'), OrgRolesGuard) @@ -152,21 +131,21 @@ export class VerificationController { @Res() res: Response, @User() user: IUserRequest, @Param('orgId') orgId: string - ): Promise { - const { pageSize, searchByText, pageNumber, sorting, sortByValue } = getAllProofRequests; - const proofRequestsSearchCriteria: IProofRequestsSearchCriteria = { + ): Promise { + const { pageSize, searchByText, pageNumber, sortField, sortBy } = getAllProofRequests; + const proofRequestsSearchCriteria: IProofRequestSearchCriteria = { pageNumber, searchByText, pageSize, - sorting, - sortByValue + sortField, + sortBy }; const proofPresentationDetails = await this.verificationService.getProofPresentations(proofRequestsSearchCriteria, user, orgId); - const finalResponse: IResponseType = { + const finalResponse: IResponse = { statusCode: HttpStatus.OK, message: ResponseMessages.verification.success.fetch, - data: proofPresentationDetails.response + data: proofPresentationDetails }; return res.status(HttpStatus.OK).json(finalResponse); } diff --git a/apps/api-gateway/src/verification/verification.service.ts b/apps/api-gateway/src/verification/verification.service.ts index 3148fcd64..28a47e622 100644 --- a/apps/api-gateway/src/verification/verification.service.ts +++ b/apps/api-gateway/src/verification/verification.service.ts @@ -4,7 +4,8 @@ import { BaseService } from 'libs/service/base.service'; import { OutOfBandRequestProof, RequestProof } from './dto/request-proof.dto'; import { IUserRequest } from '@credebl/user-request/user-request.interface'; import { WebhookPresentationProof } from './dto/webhook-proof.dto'; -import { IProofRequestsSearchCriteria } from './interfaces/verification.interface'; +import { IProofRequestSearchCriteria } from './interfaces/verification.interface'; +import { IProofPresentationList } from '@credebl/common/interfaces/verification.interface'; @Injectable() @@ -18,13 +19,11 @@ export class VerificationService extends BaseService { /** * Get all proof presentations * @param orgId - * @param user - * @returns Get all proof presentation + * @returns All proof presentations details */ - - getProofPresentations(proofRequestsSearchCriteria: IProofRequestsSearchCriteria, user: IUserRequest, orgId: string): Promise<{ response: object }> { + getProofPresentations(proofRequestsSearchCriteria: IProofRequestSearchCriteria, user: IUserRequest, orgId: string): Promise { const payload = { proofRequestsSearchCriteria, user, orgId }; - return this.sendNats(this.verificationServiceProxy, 'get-proof-presentations', payload); + return this.sendNatsMessage(this.verificationServiceProxy, 'get-all-proof-presentations', payload); } /** diff --git a/apps/verification/src/interfaces/verification.interface.ts b/apps/verification/src/interfaces/verification.interface.ts index 44a3bfc57..66a685df4 100644 --- a/apps/verification/src/interfaces/verification.interface.ts +++ b/apps/verification/src/interfaces/verification.interface.ts @@ -125,16 +125,16 @@ export interface ProofPresentationPayload { } export interface IProofRequests { - proofRequestsSearchCriteria: IProofRequestsSearchCriteria; + proofRequestsSearchCriteria: IProofRequestSearchCriteria; user: IUserRequest; orgId: string; } -export interface IProofRequestsSearchCriteria { +export interface IProofRequestSearchCriteria { pageNumber: number; pageSize: number; - sorting: string; - sortByValue: string; + sortField: string; + sortBy: string; searchByText: string; } diff --git a/apps/verification/src/repositories/verification.repository.ts b/apps/verification/src/repositories/verification.repository.ts index 5ed4bbd30..b1fb78022 100644 --- a/apps/verification/src/repositories/verification.repository.ts +++ b/apps/verification/src/repositories/verification.repository.ts @@ -3,9 +3,10 @@ import { PrismaService } from '@credebl/prisma-service'; import { Injectable, Logger, NotFoundException } from '@nestjs/common'; // eslint-disable-next-line camelcase import { org_agents, organisation, platform_config, presentations } from '@prisma/client'; -import { ProofPresentationPayload } from '../interfaces/verification.interface'; +import { IProofRequestSearchCriteria, ProofPresentationPayload } from '../interfaces/verification.interface'; import { IUserRequest } from '@credebl/user-request/user-request.interface'; -import { IProofRequestsSearchCriteria } from 'apps/api-gateway/src/verification/interfaces/verification.interface'; +import { IProofPresentationsListCount } from '@credebl/common/interfaces/verification.interface'; +import { SortValue } from '@credebl/enum/enum'; @Injectable() export class VerificationRepository { @@ -56,24 +57,16 @@ export class VerificationRepository { async getAllProofRequests( user: IUserRequest, orgId: string, - proofRequestsSearchCriteria: IProofRequestsSearchCriteria - ): Promise<{ - proofRequestsCount: number; - proofRequestsList: { - createDateTime: Date; - createdBy: string; - connectionId: string; - state: string; - orgId: string; - }[]; - }> { + proofRequestsSearchCriteria: IProofRequestSearchCriteria + ): Promise { try { const proofRequestsList = await this.prisma.presentations.findMany({ where: { orgId, OR: [ { connectionId: { contains: proofRequestsSearchCriteria.searchByText, mode: 'insensitive' } }, - { state: { contains: proofRequestsSearchCriteria.searchByText, mode: 'insensitive' } } + { state: { contains: proofRequestsSearchCriteria.searchByText, mode: 'insensitive' } }, + { presentationId: { contains: proofRequestsSearchCriteria.searchByText, mode: 'insensitive' } } ] }, select: { @@ -86,11 +79,9 @@ export class VerificationRepository { presentationId: true }, orderBy: { - [proofRequestsSearchCriteria?.sorting || 'createDateTime']: - 'DESC' === proofRequestsSearchCriteria?.sortByValue - ? 'desc' - : 'asc' + [proofRequestsSearchCriteria.sortField]: SortValue.ASC === proofRequestsSearchCriteria.sortBy ? 'asc' : 'desc' }, + take: Number(proofRequestsSearchCriteria.pageSize), skip: (proofRequestsSearchCriteria.pageNumber - 1) * proofRequestsSearchCriteria.pageSize }); @@ -99,8 +90,9 @@ export class VerificationRepository { orgId, OR: [ { connectionId: { contains: proofRequestsSearchCriteria.searchByText, mode: 'insensitive' } }, - { state: { contains: proofRequestsSearchCriteria.searchByText, mode: 'insensitive' } } - ] + { state: { contains: proofRequestsSearchCriteria.searchByText, mode: 'insensitive' } }, + { presentationId: { contains: proofRequestsSearchCriteria.searchByText, mode: 'insensitive' } } + ] } }); diff --git a/apps/verification/src/verification.controller.ts b/apps/verification/src/verification.controller.ts index 23946706e..d96f6de51 100644 --- a/apps/verification/src/verification.controller.ts +++ b/apps/verification/src/verification.controller.ts @@ -4,6 +4,7 @@ import { MessagePattern } from '@nestjs/microservices'; import { IProofRequests, IRequestProof, ProofFormData, ProofPresentationPayload } from './interfaces/verification.interface'; import { IUserRequest } from '@credebl/user-request/user-request.interface'; import { presentations } from '@prisma/client'; +import { IProofPresentationList } from '@credebl/common/interfaces/verification.interface'; @Controller() export class VerificationController { @@ -14,8 +15,8 @@ export class VerificationController { * @param payload * @returns Get all proof presentation */ - @MessagePattern({ cmd: 'get-proof-presentations' }) - async getProofPresentations(payload: IProofRequests): Promise { + @MessagePattern({ cmd: 'get-all-proof-presentations' }) + async getProofPresentations(payload: IProofRequests): Promise { const { user, orgId, proofRequestsSearchCriteria} = payload; return this.verificationService.getProofPresentations(user, orgId, proofRequestsSearchCriteria); } diff --git a/apps/verification/src/verification.service.ts b/apps/verification/src/verification.service.ts index 476f9a582..b5ba8c1ba 100644 --- a/apps/verification/src/verification.service.ts +++ b/apps/verification/src/verification.service.ts @@ -2,7 +2,7 @@ import { BadRequestException, HttpException, Inject, Injectable, InternalServerErrorException, Logger, NotFoundException } from '@nestjs/common'; import { ClientProxy, RpcException } from '@nestjs/microservices'; import { map } from 'rxjs/operators'; -import { IGetAllProofPresentations, IGetProofPresentationById, IProofRequestPayload, IRequestProof, ISendProofRequestPayload, IVerifyPresentation, ProofFormDataPayload, ProofPresentationPayload } from './interfaces/verification.interface'; +import { IGetAllProofPresentations, IGetProofPresentationById, IProofRequestPayload, IProofRequestSearchCriteria, IRequestProof, ISendProofRequestPayload, IVerifyPresentation, ProofFormDataPayload, ProofPresentationPayload } from './interfaces/verification.interface'; import { VerificationRepository } from './repositories/verification.repository'; import { CommonConstants } from '@credebl/common/common.constant'; import { org_agents, organisation, presentations } from '@prisma/client'; @@ -13,7 +13,7 @@ import { OutOfBandVerification } from '../templates/out-of-band-verification.tem import { EmailDto } from '@credebl/common/dtos/email.dto'; import { sendEmail } from '@credebl/common/send-grid-helper-file'; import { IUserRequest } from '@credebl/user-request/user-request.interface'; -import { IProofRequestsSearchCriteria } from 'apps/api-gateway/src/verification/interfaces/verification.interface'; +import { IProofPresentationList } from '@credebl/common/interfaces/verification.interface'; @Injectable() export class VerificationService { @@ -38,29 +38,20 @@ export class VerificationService { async getProofPresentations( user: IUserRequest, orgId: string, - proofRequestsSearchCriteria: IProofRequestsSearchCriteria - ): Promise<{ - totalItems: number; - hasNextPage: boolean; - hasPreviousPage: boolean; - nextPage: number; - previousPage: number; - lastPage: number; - data: { - createDateTime: Date; - createdBy: string; - connectionId: string; - state: string; - orgId: string; - }[]; - }> { + proofRequestsSearchCriteria: IProofRequestSearchCriteria + ): Promise { try { const getProofRequestsList = await this.verificationRepository.getAllProofRequests( user, orgId, proofRequestsSearchCriteria ); - const issuedCredentialsResponse: { + + if (0 === getProofRequestsList.proofRequestsCount) { + throw new NotFoundException(ResponseMessages.verification.error.proofPresentationNotFound); + } + + const proofPresentationsResponse: { totalItems: number; hasNextPage: boolean; hasPreviousPage: boolean; @@ -73,6 +64,8 @@ export class VerificationService { connectionId: string; state: string; orgId: string; + presentationId: string; + id: string; }[]; } = { totalItems: getProofRequestsList.proofRequestsCount, @@ -85,20 +78,15 @@ export class VerificationService { data: getProofRequestsList.proofRequestsList }; - if (0 !== getProofRequestsList.proofRequestsCount) { - return issuedCredentialsResponse; - } else { - throw new NotFoundException(ResponseMessages.verification.error.proofPresentationNotFound); - } - } catch (error) { - if (404 === error.status) { - throw new NotFoundException(error.response.message); - } - throw new RpcException( - `[getConnections] [NATS call]- error in fetch proof requests details : ${JSON.stringify(error)}` - ); - } - } + return proofPresentationsResponse; + } catch (error) { + + this.logger.error( + `[getProofRequests] [NATS call]- error in fetch proof requests details : ${JSON.stringify(error)}` + ); + throw new RpcException(error.response ? error.response : error); + } +} /** * Consume agent API for get all proof presentations diff --git a/libs/common/src/interfaces/verification.interface.ts b/libs/common/src/interfaces/verification.interface.ts new file mode 100644 index 000000000..97fd0d0cb --- /dev/null +++ b/libs/common/src/interfaces/verification.interface.ts @@ -0,0 +1,23 @@ +export interface IProofPresentationsListCount { + proofRequestsCount: number; + proofRequestsList: IProofPresentationItem[]; + } + export interface IProofPresentationItem { + id: string, + createDateTime: Date; + createdBy: string; + connectionId: string; + state: string; + orgId: string; + presentationId: string; + } + export interface IProofPresentationList { + totalItems: number; + hasNextPage: boolean; + hasPreviousPage: boolean; + nextPage: number; + previousPage: number; + lastPage: number; + data: IProofPresentationItem[]; + } +