Skip to content

Commit

Permalink
refcator: schema endorsement flow
Browse files Browse the repository at this point in the history
Signed-off-by: bhavanakarwade <[email protected]>
Signed-off-by: KulkarniShashank <[email protected]>
  • Loading branch information
bhavanakarwade authored and KulkarniShashank committed Sep 11, 2024
1 parent 3272649 commit 1a9baec
Show file tree
Hide file tree
Showing 6 changed files with 362 additions and 286 deletions.
149 changes: 89 additions & 60 deletions apps/api-gateway/src/ecosystem/dtos/request-schema.dto.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { ApiProperty } from '@nestjs/swagger';
import { ApiExtraModels, ApiProperty, getSchemaPath } from '@nestjs/swagger';
import { Transform, Type } from 'class-transformer';
import { ArrayMinSize, IsArray, IsBoolean, IsNotEmpty, IsOptional, IsString, ValidateNested } from 'class-validator';
import { ArrayMinSize, IsArray, IsBoolean, IsEnum, IsNotEmpty, IsOptional, IsString, ValidateNested } from 'class-validator';
import { trim } from '@credebl/common/cast.helper';
import { JSONSchemaType, SchemaTypeEnum, W3CSchemaDataType } from '@credebl/enum/enum';


class AttributeValues {
Expand Down Expand Up @@ -31,20 +32,19 @@ class AttributeValues {

}


export class RequestSchemaDto {
export class RequestIndySchemaDto {

@ApiProperty()
@Transform(({ value }) => trim(value))
@IsNotEmpty({ message: 'Schema name is required' })
@IsString({ message: 'name must be in string format.' })
name: string;
schemaName: string;

@ApiProperty()
@Transform(({ value }) => trim(value))
@IsNotEmpty({ message: 'Schema version is required' })
@IsString({ message: 'version must be in string format.' })
version: string;
schemaVersion: string;

@ApiProperty({
type: [AttributeValues],
Expand All @@ -63,92 +63,121 @@ export class RequestSchemaDto {
@ValidateNested({ each: true })
@Type(() => AttributeValues)
attributes: AttributeValues[];

@ApiProperty()
@IsBoolean({ message: 'endorse must be a boolean.' })
@IsOptional()
endorse?: boolean;

userId?: string;

}

class W3CSchemaAttributesValue {

@ApiProperty()
@IsString()
@Transform(({ value }) => trim(value))
@IsNotEmpty({ message: 'title is required' })
@IsString({ message: 'title must be in string format' })
title: string;
@IsNotEmpty({ message: 'attributeName is required' })
attributeName: string;

@ApiProperty({
description: 'The type of the schema',
enum: W3CSchemaDataType,
example: W3CSchemaDataType.STRING
})
@IsEnum(W3CSchemaDataType, { message: 'Schema data type must be a valid type' })
schemaDataType: W3CSchemaDataType;

@ApiProperty()
@IsString()
@Transform(({ value }) => trim(value))
@IsNotEmpty({ message: 'type is required' })
@IsString({ message: 'type must be in string format' })
type: string;
@IsNotEmpty({ message: 'displayName is required' })
displayName: string;

@ApiProperty()
@IsBoolean({ message: 'isRequired property must be in boolean format' })
@IsBoolean()
@IsNotEmpty({ message: 'isRequired property is required' })
isRequired: boolean;
}

export class RequestW3CSchemaDto {
export class SchemaDetails {
@ApiProperty()
@IsString({ message: 'name must be a string.' })
name: string;

@ApiProperty()
@Transform(({ value }) => trim(value))
@IsNotEmpty({ message: 'schemaName is required' })
@IsString({ message: 'schemaName must be in string format.' })
schemaName: string;
@IsString({ message: 'version must be a string.' })
version: string;

@ApiProperty({
type: [W3CSchemaAttributesValue],
'example': [
{
title: 'name',
type: 'string',
isRequired: true
}
]
example: ['name', 'id']
})
@IsArray({ message: 'schemaAttributes must be an array' })
@IsNotEmpty({ message: 'schemaAttributes are required' })
@ArrayMinSize(1)
@ValidateNested({ each: true })
@IsArray({ message: 'attributes must be an array.' })
@IsNotEmpty({ message: 'please provide valid attributes.' })
attributes: string[];

}

export class RequestW3CSchemaDto {
@ApiProperty({
type: [W3CSchemaAttributesValue],
'example': [
{
attributeName: 'name',
schemaDataType: 'string',
displayName: 'Name',
isRequired: true
}
]
})
@ValidateNested({each: true})
@Type(() => W3CSchemaAttributesValue)
schemaAttributes: W3CSchemaAttributesValue[];
@IsNotEmpty()
attributes: W3CSchemaAttributesValue [];

@ApiProperty()
@Transform(({ value }) => trim(value))
@IsNotEmpty({ message: 'did is required' })
@IsString({ message: 'did must be in string format.' })
did: string;

@IsString({ message: 'schemaName must be a string' })
@Transform(({ value }) => value.trim())
@IsNotEmpty({ message: 'schemaName is required' })
schemaName: string;
@ApiProperty()
@Transform(({ value }) => trim(value))
@IsString({ message: 'description must be a string' })
@IsNotEmpty({ message: 'description is required' })
@IsString({ message: 'description must be in string format.' })
description: string;

userId?: string;


@ApiProperty({
description: 'The type of the schema',
enum: JSONSchemaType,
example: JSONSchemaType.POLYGON_W3C
})
@IsEnum(JSONSchemaType, { message: 'Schema type must be a valid schema type' })
@IsNotEmpty({ message: 'Type is required' })
schemaType: JSONSchemaType;
}
export class SchemaDetails {
@ApiProperty()
@IsString({ message: 'name must be a string.' })
name: string;

@ApiExtraModels(RequestIndySchemaDto, RequestW3CSchemaDto)
export class RequestSchemaDto {
@ApiProperty({
description: 'The type of the schema',
enum: SchemaTypeEnum,
example: SchemaTypeEnum.INDY
})
@IsEnum(SchemaTypeEnum, { message: 'Type must be a valid schema type' })
@IsNotEmpty({ message: 'Type is required' })
type: SchemaTypeEnum;

@ApiProperty()
@IsString({ message: 'version must be a string.' })
version: string;
@IsBoolean({ message: 'endorse property must be a boolean.' })
@IsNotEmpty({ message: 'endorse property is required' })
endorse?: boolean;

@ApiProperty({
example: ['name', 'id']
type: Object,
oneOf: [{ $ref: getSchemaPath(RequestIndySchemaDto) }, { $ref: getSchemaPath(RequestW3CSchemaDto) }]
})
@IsArray({ message: 'attributes must be an array.' })
@IsNotEmpty({ message: 'please provide valid attributes.' })
attributes: string[];

@ValidateNested()
@Type(({ object }) => {
if (object.type === SchemaTypeEnum.INDY) {
return RequestIndySchemaDto;
} else if (object.type === SchemaTypeEnum.JSON) {
return RequestW3CSchemaDto;
}
})
schemaPayload: RequestIndySchemaDto | RequestW3CSchemaDto;
}

export class RequestCredDefDto {
Expand Down
36 changes: 10 additions & 26 deletions apps/api-gateway/src/ecosystem/ecosystem.controller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ApiBearerAuth, ApiBody, ApiExcludeEndpoint, ApiExtraModels, ApiForbiddenResponse, ApiOperation, ApiQuery, ApiResponse, ApiTags, ApiUnauthorizedResponse, getSchemaPath } from '@nestjs/swagger';
import { ApiBearerAuth, ApiExcludeEndpoint, ApiExtraModels, 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, ParseUUIDPipe } from '@nestjs/common';
import { RequestCredDefDto, RequestSchemaDto, RequestW3CSchemaDto } from './dtos/request-schema.dto';
Expand All @@ -12,7 +12,7 @@ import { CustomExceptionFilter } from 'apps/api-gateway/common/exception-handler
import { EditEcosystemDto } from './dtos/edit-ecosystem-dto';
import { AuthGuard } from '@nestjs/passport';
import { GetAllSentEcosystemInvitationsDto } from './dtos/get-all-received-invitations.dto';
import { EcosystemRoles, Invitation, schemaRequestType } from '@credebl/enum/enum';
import { EcosystemRoles, Invitation } from '@credebl/enum/enum';
import { User } from '../authz/decorators/user.decorator';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { user } from '@prisma/client';
Expand All @@ -27,7 +27,7 @@ import { CreateEcosystemDto } from './dtos/create-ecosystem-dto';
import { PaginationDto } from '@credebl/common/dtos/pagination.dto';
import { IEcosystemInvitations, IEditEcosystem, IEndorsementTransaction } from 'apps/ecosystem/interfaces/ecosystem.interfaces';
import { AddOrganizationsDto } from './dtos/add-organizations.dto';
import { TrimStringParamPipe, validateSchemaPayload } from '@credebl/common/cast.helper';
import { TrimStringParamPipe } from '@credebl/common/cast.helper';


@UseFilters(CustomExceptionFilter)
Expand Down Expand Up @@ -307,24 +307,12 @@ export class EcosystemController {
@ApiExtraModels(RequestSchemaDto, RequestW3CSchemaDto)
@ApiOperation({ summary: 'Request new schema', description: 'Create request for new schema' })
@ApiResponse({ status: HttpStatus.CREATED, description: 'Created', type: ApiResponseDto })
@ApiQuery({
name: 'schemaType',
enum: schemaRequestType
})
@ApiBody({
schema: {
oneOf: [
{ $ref: getSchemaPath(RequestSchemaDto), description: 'Indy based schema' },
{ $ref: getSchemaPath(RequestW3CSchemaDto), description: 'W3C based schema' }
]
}
})
@UseGuards(AuthGuard('jwt'), EcosystemRolesGuard, OrgRolesGuard)
@ApiBearerAuth()
@EcosystemsRoles(EcosystemRoles.ECOSYSTEM_MEMBER, EcosystemRoles.ECOSYSTEM_LEAD, EcosystemRoles.ECOSYSTEM_OWNER)
@Roles(OrgRoles.OWNER, OrgRoles.ADMIN, OrgRoles.ISSUER)
async requestSchemaTransaction(
@Body() requestSchemaPayload: RequestSchemaDto | RequestW3CSchemaDto,
@Body() requestSchemaPayload: RequestSchemaDto,
@Param(
'orgId',
new ParseUUIDPipe({
Expand All @@ -335,19 +323,14 @@ export class EcosystemController {
) orgId: string,
@Param('ecosystemId', TrimStringParamPipe) ecosystemId: string,
@Res() res: Response,
@User() user: user,
@Query('schemaType') schemaType: schemaRequestType = schemaRequestType.INDY
@User() user: user
): Promise<Response> {
requestSchemaPayload.userId = user.id;


validateSchemaPayload(requestSchemaPayload, schemaType);

const createSchemaRequest = await this.ecosystemService.schemaEndorsementRequest(
requestSchemaPayload,
user,
orgId,
ecosystemId,
schemaType
ecosystemId
);

const finalResponse: IResponse = {
Expand Down Expand Up @@ -395,7 +378,7 @@ export class EcosystemController {
@ApiBearerAuth()
@EcosystemsRoles(EcosystemRoles.ECOSYSTEM_MEMBER)
@Roles(OrgRoles.OWNER, OrgRoles.ADMIN, OrgRoles.ISSUER)
async requestCredDefTransaction(@Body() requestCredDefPayload: RequestCredDefDto, @Param('orgId', new ParseUUIDPipe({exceptionFactory: (): Error => { throw new BadRequestException(ResponseMessages.organisation.error.invalidOrgId); }})) orgId: string, @Param('ecosystemId', TrimStringParamPipe) ecosystemId: string, @Res() res: Response, @User() user: user): Promise<Response> {
async requestCredDefTransaction(@Body() requestCredDefPayload: RequestCredDefDto, @Param('ecosystemId', TrimStringParamPipe) ecosystemId: string, @Param('orgId', new ParseUUIDPipe({exceptionFactory: (): Error => { throw new BadRequestException(ResponseMessages.organisation.error.invalidOrgId); }})) orgId: string, @Res() res: Response, @User() user: user): Promise<Response> {
requestCredDefPayload.userId = user.id;
const createCredDefRequest: IEndorsementTransaction = await this.ecosystemService.credDefEndorsementRequest(requestCredDefPayload, orgId, ecosystemId);
const finalResponse: IResponse = {
Expand Down Expand Up @@ -461,9 +444,10 @@ export class EcosystemController {
})
)
orgId: string,
@User() user: user,
@Res() res: Response
): Promise<Response> {
const transactionResponse = await this.ecosystemService.submitTransaction(endorsementId, ecosystemId, orgId);
const transactionResponse = await this.ecosystemService.submitTransaction(endorsementId, ecosystemId, orgId, user);
const finalResponse: IResponse = {
statusCode: HttpStatus.CREATED,
message: ResponseMessages.ecosystem.success.submit,
Expand Down
15 changes: 7 additions & 8 deletions apps/api-gateway/src/ecosystem/ecosystem.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ import { GetAllSentEcosystemInvitationsDto } from './dtos/get-all-received-invit
import { GetAllEcosystemMembersDto } from './dtos/get-members.dto';
import { GetAllEndorsementsDto } from './dtos/get-all-endorsements.dto';

import { RequestSchemaDto, RequestCredDefDto, RequestW3CSchemaDto } from './dtos/request-schema.dto';
import { RequestSchemaDto, RequestCredDefDto} from './dtos/request-schema.dto';
import { CreateEcosystemDto } from './dtos/create-ecosystem-dto';
import { EditEcosystemDto } from './dtos/edit-ecosystem-dto';
import { IEcosystemDashboard, IEcosystemInvitation, IEcosystemInvitations, IEcosystem, IEditEcosystem, IEndorsementTransaction, ISchemaResponse } from 'apps/ecosystem/interfaces/ecosystem.interfaces';
import { PaginationDto } from '@credebl/common/dtos/pagination.dto';
import { IEcosystemDataDeletionResults, IEcosystemDetails } from '@credebl/common/interfaces/ecosystem.interface';
import { AddOrganizationsDto } from './dtos/add-organizations.dto';
import { schemaRequestType } from '@credebl/enum/enum';
import { user } from '@prisma/client';

@Injectable()
Expand Down Expand Up @@ -165,12 +164,12 @@ export class EcosystemService extends BaseService {
}

async schemaEndorsementRequest(
requestSchemaPayload: RequestSchemaDto | RequestW3CSchemaDto,
requestSchemaPayload: RequestSchemaDto,
user: user,
orgId: string,
ecosystemId: string,
schemaType: schemaRequestType = schemaRequestType.INDY
ecosystemId: string
): Promise<IEndorsementTransaction> {
const payload = { requestSchemaPayload, schemaType, orgId, ecosystemId };
const payload = { requestSchemaPayload, user, orgId, ecosystemId };
return this.sendNatsMessage(this.serviceProxy, 'schema-endorsement-request', payload);
}

Expand All @@ -188,8 +187,8 @@ export class EcosystemService extends BaseService {
return this.sendNatsMessage(this.serviceProxy, 'sign-endorsement-transaction', payload);
}

async submitTransaction(endorsementId: string, ecosystemId: string, orgId: string): Promise<object> {
const payload = { endorsementId, ecosystemId, orgId };
async submitTransaction(endorsementId: string, ecosystemId: string, orgId: string, user: user): Promise<object> {
const payload = { endorsementId, ecosystemId, orgId, user };
return this.sendNatsMessage(this.serviceProxy, 'submit-endorsement-transaction', payload);
}

Expand Down
Loading

0 comments on commit 1a9baec

Please sign in to comment.