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

fix: ecosystem member list search sorting issue #532

Merged
merged 3 commits into from
Feb 22, 2024
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
16 changes: 5 additions & 11 deletions apps/api-gateway/src/authz/guards/ecosystem-roles.guard.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import { BadRequestException, CanActivate, ExecutionContext, ForbiddenException, Logger } from '@nestjs/common';

import { HttpException } from '@nestjs/common';
import { HttpStatus } from '@nestjs/common';
import { Injectable } from '@nestjs/common';
import { BadRequestException, CanActivate, ExecutionContext, ForbiddenException, Logger, Injectable } from '@nestjs/common';
import { ECOSYSTEM_ROLES_KEY } from '../decorators/roles.decorator';
import { Reflector } from '@nestjs/core';
import { EcosystemService } from '../../ecosystem/ecosystem.service';
Expand Down Expand Up @@ -54,19 +50,17 @@ export class EcosystemRolesGuard implements CanActivate {
const ecosystemOrgData = await this.ecosystemService.fetchEcosystemOrg(ecosystemId, orgId);

if (!ecosystemOrgData) {
throw new HttpException('Organization does not match', HttpStatus.FORBIDDEN);
throw new ForbiddenException(ResponseMessages.organisation.error.orgDoesNotMatch);
}

const {response} = ecosystemOrgData;

user.ecosystemOrgRole = response['ecosystemRole']['name'];
user.ecosystemOrgRole = ecosystemOrgData['ecosystemRole']['name'];

if (!user.ecosystemOrgRole) {
throw new HttpException('Ecosystem role not match', HttpStatus.FORBIDDEN);
throw new ForbiddenException(ResponseMessages.ecosystem.error.ecosystemRoleNotMatch);
}

} else {
throw new HttpException('organization & ecosystem is required', HttpStatus.BAD_REQUEST);
throw new BadRequestException(ResponseMessages.ecosystem.error.orgEcoIdRequired);
}

// Sending user friendly message if a user attempts to access an API that is inaccessible to their role
Expand Down
29 changes: 7 additions & 22 deletions apps/api-gateway/src/ecosystem/dtos/get-members.dto.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,20 @@
import { Transform, Type } from 'class-transformer';
import { Transform } from 'class-transformer';
import { trim } from '@credebl/common/cast.helper';

import { ApiProperty } from '@nestjs/swagger';
import { IsEnum, IsOptional } from 'class-validator';
import { SortFields } from 'apps/connection/src/enum/connection.enum';
import { SortValue } from '@credebl/enum/enum';

export class GetAllEcosystemMembersDto {

@ApiProperty({ required: false, example: '1' })
@IsOptional()
pageNumber: number;

@ApiProperty({ required: false, example: '10' })
@IsOptional()
pageSize: number;

@ApiProperty({ required: false })
@IsOptional()
@Transform(({ value }) => trim(value))
@Type(() => String)
search: string = '';
import { SortMembers, SortValue } from '@credebl/enum/enum';
import { PaginationDto } from '@credebl/common/dtos/pagination.dto';

export class GetAllEcosystemMembersDto extends PaginationDto {
@ApiProperty({
enum: [SortMembers.CREATED_DATE_TIME, SortMembers.ID, SortMembers.ORGANIZATION, SortMembers.STATUS],
required: false
})
@Transform(({ value }) => trim(value))
@IsOptional()
@IsEnum(SortFields)
sortField: string = SortFields.CREATED_DATE_TIME;
@IsEnum(SortMembers)
sortField: string = SortMembers.CREATED_DATE_TIME;

@ApiProperty({
enum: [SortValue.DESC, SortValue.ASC],
Expand All @@ -38,5 +24,4 @@ export class GetAllEcosystemMembersDto {
@IsOptional()
@IsEnum(SortValue)
sortBy: string = SortValue.DESC;

}
13 changes: 7 additions & 6 deletions apps/api-gateway/src/ecosystem/ecosystem.controller.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ApiBearerAuth, ApiExcludeEndpoint, ApiForbiddenResponse, ApiOperation, ApiQuery, ApiResponse, ApiTags, ApiUnauthorizedResponse } from '@nestjs/swagger';
import { EcosystemService } from './ecosystem.service';
import { Controller, UseFilters, Put, Post, Get, Body, Param, UseGuards, Query, BadRequestException, Delete, HttpStatus, Res } from '@nestjs/common';
import { Controller, UseFilters, Put, Post, Get, Body, Param, UseGuards, Query, BadRequestException, Delete, HttpStatus, Res, ParseUUIDPipe } from '@nestjs/common';
import { RequestCredDefDto, RequestSchemaDto } from './dtos/request-schema.dto';
import IResponse from '@credebl/common/interfaces/response.interface';
import { Response } from 'express';
Expand Down Expand Up @@ -256,7 +256,7 @@ export class EcosystemController {
@EcosystemsRoles(EcosystemRoles.ECOSYSTEM_OWNER, EcosystemRoles.ECOSYSTEM_LEAD, EcosystemRoles.ECOSYSTEM_MEMBER)
@ApiBearerAuth()
@UseGuards(AuthGuard('jwt'), EcosystemRolesGuard, OrgRolesGuard)
@ApiResponse({ status: 200, description: 'Success', type: ApiResponseDto })
@ApiResponse({ status: HttpStatus.OK, description: 'Success', type: ApiResponseDto })
@ApiOperation({ summary: 'Get ecosystem members list', description: 'Get ecosystem members list.' })
@ApiQuery({
name: 'pageNumber',
Expand All @@ -274,18 +274,19 @@ export class EcosystemController {
required: false
})
async getEcosystemMembers(
@Param('ecosystemId') ecosystemId: string,
@Param('ecosystemId', new ParseUUIDPipe({exceptionFactory: (): Error => { throw new BadRequestException(`Invalid format for ecosystemId`); }})) ecosystemId: string,
@Param('orgId') orgId: string,
@Query() getEcosystemMembers: GetAllEcosystemMembersDto,
@Res() res: Response): Promise<Response> {

const members = await this.ecosystemService.getEcosystemMembers(ecosystemId, getEcosystemMembers);
const finalResponse: IResponse = {
statusCode: 200,
statusCode: HttpStatus.OK,
message: ResponseMessages.ecosystem.success.fetchMembers,
data: members?.response
data: members
};

return res.status(200).json(finalResponse);
return res.status(HttpStatus.OK).json(finalResponse);
}

@Post('/:ecosystemId/:orgId/transaction/schema')
Expand Down
11 changes: 5 additions & 6 deletions apps/api-gateway/src/ecosystem/ecosystem.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,10 @@ export class EcosystemService extends BaseService {
*/
async getEcosystemMembers(
ecosystemId: string,
getEcosystemMembers: GetAllEcosystemMembersDto
payload: GetAllEcosystemMembersDto
): Promise<{ response: object }> {
const { pageNumber, pageSize, search, sortBy } = getEcosystemMembers;
const payload = { ecosystemId, pageNumber, pageSize, search, sortBy };
return this.sendNats(this.serviceProxy, 'fetch-ecosystem-members', payload);
payload['ecosystemId'] = ecosystemId;
return this.sendNatsMessage(this.serviceProxy, 'fetch-ecosystem-members', payload);
}

/**
Expand Down Expand Up @@ -126,9 +125,9 @@ export class EcosystemService extends BaseService {
return this.sendNats(this.serviceProxy, 'accept-reject-ecosystem-invitations', payload);
}

async fetchEcosystemOrg(ecosystemId: string, orgId: string): Promise<{ response: object }> {
async fetchEcosystemOrg(ecosystemId: string, orgId: string): Promise<object> {
const payload = { ecosystemId, orgId };
return this.sendNats(this.serviceProxy, 'fetch-ecosystem-org-data', payload);
return this.sendNatsMessage(this.serviceProxy, 'fetch-ecosystem-org-data', payload);
}

async getEndorsementTranasactions(
Expand Down
1 change: 1 addition & 0 deletions apps/ecosystem/interfaces/ecosystemMembers.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ export interface EcosystemMembersPayload {
pageSize: number;
search: string;
sortBy: string;
sortField: string;
}
2 changes: 1 addition & 1 deletion apps/ecosystem/src/ecosystem.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export class EcosystemController {
*/
@MessagePattern({ cmd: 'fetch-ecosystem-members' })
async getEcosystemMembers(@Body() payload: EcosystemMembersPayload): Promise<object> {
return this.ecosystemService.getEcoystemMembers(payload);
return this.ecosystemService.getEcosystemMembers(payload);
}

/**
Expand Down
134 changes: 70 additions & 64 deletions apps/ecosystem/src/ecosystem.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ResponseMessages } from '@credebl/common/response-messages';
import { NotFoundException } from '@nestjs/common';
import { CommonConstants } from '@credebl/common/common.constant';
import { GetAllSchemaList } from '../interfaces/endorsements.interface';
import { SortValue } from '@credebl/enum/enum';
// eslint-disable-next-line camelcase

@Injectable()
Expand Down Expand Up @@ -160,7 +161,7 @@ export class EcosystemRepository {
}
})
]);

return {
ecosystemDetails,
totalCount: ecosystemCount
Expand All @@ -170,7 +171,7 @@ export class EcosystemRepository {
throw error;
}
}


/**
*
Expand Down Expand Up @@ -486,62 +487,67 @@ export class EcosystemRepository {
* @returns users list
*/

async findEcosystemMembers(
ecosystemId: string,
pageNumber: number,
pageSize: number,
search: string,
sortBy: string
): Promise<object> {
try {
const result = await this.prisma.$transaction([
this.prisma.ecosystem_orgs.findMany({
where: {
ecosystemId,
OR: [
{
organisation: {
name: { contains: search, mode: 'insensitive' },
// eslint-disable-next-line camelcase
org_agents: {
some: {
orgDid: { contains: search, mode: 'insensitive' }
async findEcosystemMembers(
ecosystemId: string,
pageNumber: number,
pageSize: number,
search: string,
sortBy: string,
sortField: string
): Promise<object> {
try {
const result = await this.prisma.$transaction([
this.prisma.ecosystem_orgs.findMany({
where: {
ecosystemId,
OR: [
{
organisation: {
name: { contains: search, mode: 'insensitive' }
}
},
{
organisation: {
// eslint-disable-next-line camelcase
org_agents: {
some: {
orgDid: { contains: search, mode: 'insensitive' }
}
}
}
}
]
},
include: {
ecosystem: true,
ecosystemRole: true,
organisation: {
select: {
name: true,
orgSlug: true,
// eslint-disable-next-line camelcase
org_agents: true
}
}
]
},
include: {
ecosystem: true,
ecosystemRole: true,
organisation: {
select: {
name: true,
orgSlug: true,
// eslint-disable-next-line camelcase
org_agents: true
}
},
take: Number(pageSize),
skip: (pageNumber - 1) * pageSize,
orderBy: {
[sortField]: SortValue.ASC === sortBy ? 'asc' : 'desc'
}
},
take: Number(pageSize),
skip: (pageNumber - 1) * pageSize,
orderBy: {
createDateTime: 'asc' === sortBy ? 'asc' : 'desc'
}
}),
this.prisma.ecosystem_orgs.count({
where: {
ecosystemId
}
})
]);
return result;
} catch (error) {
this.logger.error(`error: ${JSON.stringify(error)}`);
throw error;
}),
this.prisma.ecosystem_orgs.count({
where: {
ecosystemId
}
})
]);
return result;
} catch (error) {
this.logger.error(`error: ${JSON.stringify(error)}`);
throw error;
}
}
}

async getEcosystemInvitationsPagination(queryObject: object, pageNumber: number, pageSize: number): Promise<IEcosystemInvitation> {
try {
Expand Down Expand Up @@ -590,18 +596,18 @@ async findEcosystemMembers(
async fetchEcosystemOrg(
payload: object
): Promise<object> {

return this.prisma.ecosystem_orgs.findFirst({
where: {
...payload
},
select: {
ecosystem: true,
ecosystemRole: true,
organisation: true
}
});

where: {
...payload
},
select: {
ecosystem: true,
ecosystemRole: true,
organisation: true
}
});
}


Expand Down Expand Up @@ -833,7 +839,7 @@ async findEcosystemMembers(
schemaTransactionResponse: SchemaTransactionResponse,
requestBody: object,
type: endorsementTransactionType
// eslint-disable-next-line camelcase
// eslint-disable-next-line camelcase
): Promise<endorsement_transaction> {
try {
const { endorserDid, authorDid, requestPayload, status, ecosystemOrgId, userId } = schemaTransactionResponse;
Expand Down
7 changes: 4 additions & 3 deletions apps/ecosystem/src/ecosystem.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1109,15 +1109,16 @@ export class EcosystemService {
* @returns Ecosystem members list
*/

async getEcoystemMembers(payload: EcosystemMembersPayload): Promise<object> {
async getEcosystemMembers(payload: EcosystemMembersPayload): Promise<object> {
try {
const { ecosystemId, pageNumber, pageSize, search, sortBy } = payload;
const { ecosystemId, pageNumber, pageSize, search, sortBy, sortField } = payload;
const getEcosystemMember = await this.ecosystemRepository.findEcosystemMembers(
ecosystemId,
pageNumber,
pageSize,
search,
sortBy
sortBy,
sortField
);

const ecosystemMemberResponse = {
Expand Down
7 changes: 5 additions & 2 deletions libs/common/src/response-messages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ export const ResponseMessages = {
invalidUserId:'Invalid format of userId',
invalidInvitationId:'Invalid format for invitation id',
ecosystemIdIsRequired:'ecosystemId is required',
roleNotMatch: 'User does not have access'
roleNotMatch: 'User does not have access',
orgDoesNotMatch: 'Organization does not match'
}
},

Expand Down Expand Up @@ -353,7 +354,9 @@ export const ResponseMessages = {
updateSchemaId: 'Error while updating the schema id',
updateCredDefId: 'Error while updating the credential-definition',
invalidMessage: 'Invalid transaction details. Missing "message" property.',
invalidTransactionMessage: 'Invalid transaction details'
invalidTransactionMessage: 'Invalid transaction details',
ecosystemRoleNotMatch: 'Ecosystem role not match',
orgEcoIdRequired: 'OrgId & EcosystemId is required'
}
},
bulkIssuance: {
Expand Down
Loading