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: platform agent up #598

Merged
merged 5 commits into from
Mar 15, 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
67 changes: 34 additions & 33 deletions apps/agent-service/src/agent-service.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export class AgentServiceService {
this.agentServiceRepository.getAgentTypeDetails(),
this.agentServiceRepository.getLedgerDetails(agentSpinupDto.ledgerName ? agentSpinupDto.ledgerName : [Ledgers.Indicio_Demonet])
]);

let orgData;
if (!user?.userId && agentSpinupDto?.platformAdminEmail) {

Expand Down Expand Up @@ -158,7 +158,6 @@ export class AgentServiceService {
agentSpinupDto.tenant = agentSpinupDto.tenant || false;
agentSpinupDto.ledgerName = agentSpinupDto.ledgerName?.length ? agentSpinupDto.ledgerName : [Ledgers.Indicio_Demonet];


// Invoke function for validate platform configuration
this.validatePlatformConfig(platformConfig);

Expand Down Expand Up @@ -338,13 +337,28 @@ export class AgentServiceService {
}

async _agentSpinup(walletProvisionPayload: IWalletProvision, agentSpinupDto: IAgentSpinupDto, orgApiKey: string, orgData: organisation, user: IUserRequestInterface, socket: Socket, ledgerId: string[], agentProcess: ICreateOrgAgent): Promise<void> {
try {
let ledgerIdData = [];

try {
if (agentSpinupDto.method !== DidMethod.KEY && agentSpinupDto.method !== DidMethod.WEB) {

const { network } = agentSpinupDto;
const ledger = await ledgerName(network);
const ledgerList = await this._getALlLedgerDetails() as unknown as LedgerListResponse;
const isLedgerExist = ledgerList.response.find((existingLedgers) => existingLedgers.name === ledger);
if (!isLedgerExist) {
throw new BadRequestException(
ResponseMessages.agent.error.invalidLedger,
{ cause: new Error(), description: ResponseMessages.errorMessages.notFound }
);
}

ledgerIdData = await this.agentServiceRepository.getLedgerDetails(ledger);
}
/**
* Invoke wallet create and provision with agent
*/
const walletProvision = await this._walletProvision(walletProvisionPayload);

if (!walletProvision?.response) {
this.logger.error(`Agent not able to spin-up`);
throw new BadRequestException(
Expand All @@ -354,7 +368,6 @@ export class AgentServiceService {
}
const agentDetails = walletProvision.response;
const agentEndPoint = `${process.env.API_GATEWAY_PROTOCOL}://${agentDetails.agentEndPoint}`;

/**
* Socket connection
*/
Expand All @@ -374,11 +387,14 @@ export class AgentServiceService {
orgId: orgData.id,
walletName: agentSpinupDto.walletName,
clientSocketId: agentSpinupDto.clientSocketId,
ledgerId,
method: agentSpinupDto.method,
role: agentSpinupDto.role,
network: agentSpinupDto.network,
keyType: agentSpinupDto.keyType,
ledgerId: ledgerIdData ? ledgerIdData.map(item => item.id) : null,
did: agentSpinupDto.did,
id: agentProcess?.id
};

/**
* Store organization agent details
*/
Expand Down Expand Up @@ -446,7 +462,7 @@ export class AgentServiceService {
/**
* Organization storage data
*/
const storeOrgAgentData = await this._buildStoreOrgAgentData(payload, getDidMethod, orgAgentTypeId);
const storeOrgAgentData = await this._buildStoreOrgAgentData(payload, getDidMethod, `${orgAgentTypeId}`);
/**
* Store org agent details
*/
Expand All @@ -460,33 +476,19 @@ export class AgentServiceService {


private async _getAgentDid(payload: IStoreOrgAgentDetails): Promise<object> {
const { agentEndPoint, apiKey, ledgerId } = payload;

//we take this values as static because of latest changes in afj controller to up agent of platform
const platformAgent: IPlatformAgent = {
seed: `${CommonConstants.SEED}`,
keyType: `${CommonConstants.KEYTYPE}`,
method: `${CommonConstants.METHOD}`,
network: `${CommonConstants.NETWORK}`,
role: `${CommonConstants.ROLE}`
};
const { agentEndPoint, apiKey, ledgerId, seed, keyType, method, network, role, did } = payload;
const writeDid = 'write-did';
const ledgerDetails = await this.agentServiceRepository.getGenesisUrl(ledgerId);
const agentDidWriteUrl = `${agentEndPoint}${CommonConstants.URL_AGENT_WRITE_DID}`;
return this._retryAgentSpinup(agentDidWriteUrl, apiKey, writeDid, platformAgent);
return this._retryAgentSpinup(agentDidWriteUrl, apiKey, writeDid, seed, keyType, method, network, role, did);

}

private async _getDidMethod(payload: IStoreOrgAgentDetails, agentDid: object): Promise<object> {
const getDidDic = 'get-did-doc';
const platformAgent: IPlatformAgent = {
seed: `${CommonConstants.SEED}`,
keyType: `${CommonConstants.KEYTYPE}`,
method: `${CommonConstants.METHOD}`,
network: `${CommonConstants.NETWORK}`,
role: `${CommonConstants.ROLE}`
};
const getDidMethodUrl = `${payload.agentEndPoint}${CommonConstants.URL_AGENT_GET_DID}`.replace('#', agentDid['did']);
return this._retryAgentSpinup(getDidMethodUrl, payload.apiKey, getDidDic, platformAgent);
const { agentEndPoint, apiKey, seed, keyType, method, network, role } = payload;
const getDidDoc = 'get-did-doc';
const getDidMethodUrl = `${agentEndPoint}${CommonConstants.URL_AGENT_GET_DID}/${agentDid['did']}`;
return this._retryAgentSpinup(getDidMethodUrl, apiKey, getDidDoc, seed, keyType, method, network, role, `${agentDid['did']}`);
}

private _buildStoreOrgAgentData(payload: IStoreOrgAgentDetails, getDidMethod: object, orgAgentTypeId: string): IStoreOrgAgentDetails {
Expand Down Expand Up @@ -528,20 +530,19 @@ export class AgentServiceService {
}


async _retryAgentSpinup(agentUrl: string, apiKey: string, agentApiState: string, payload: IPlatformAgent): Promise<object> {

const { seed, keyType, method, network, role} = payload;
async _retryAgentSpinup(agentUrl: string, apiKey: string, agentApiState: string, seed: string, keyType: string, method: string, network: string, role: string, did: string): Promise<object> {
const retryOptions = {
retries: 10
};
try {
return retry(async () => {
if (agentApiState === 'write-did') {
return this.commonService.httpPost(agentUrl, { seed, keyType, method, network, role}, { headers: { 'authorization': apiKey } });
return this.commonService.httpPost(agentUrl, { seed, keyType, method, network, role, did}, { headers: { 'authorization': apiKey } });
} else if (agentApiState === 'get-did-doc') {
return this.commonService.httpGet(agentUrl, { headers: { 'authorization': apiKey } });
}
}, retryOptions);

} catch (error) {
throw error;
}
Expand Down
47 changes: 29 additions & 18 deletions apps/agent-service/src/interface/agent-service.interface.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import { UserRoleOrgPermsDto } from 'apps/api-gateway/src/dtos/user-role-org-perms.dto';

export interface IAgentSpinupDto {

walletName: string;
walletPassword: string;
seed: string;
orgId?: string;
orgName?: string;
ledgerId?: string[];
keyType: string;
domain?: string;
privatekey?: string;
endpoint?: string;
role?: string;
network?: string
endorserDid?: string
method: string;
did?: string;
agentType?: string;
transactionApproval?: boolean;
Expand Down Expand Up @@ -149,23 +156,27 @@ export interface IPlatformConfigDto {
}

export interface IStoreOrgAgentDetails {
id?: string;
clientSocketId?: string;
agentEndPoint?: string;
apiKey?: string;
seed?: string;
did?: string;
verkey?: string;
isDidPublic?: boolean;
agentSpinUpStatus?: number;
walletName?: string;
agentsTypeId?: string;
orgId?: string;
agentId?: string;
orgAgentTypeId?: string;
tenantId?: string;
ledgerId?: string[];
agentType?: string;
id?: string;
clientSocketId?: string;
agentEndPoint?: string;
apiKey?: string;
seed?: string;
keyType?: string;
method?: string;
network?: string;
role?: string;
did?: string;
verkey?: string;
isDidPublic?: boolean;
agentSpinUpStatus?: number;
walletName?: string;
agentsTypeId?: string;
orgId?: string;
agentId?: string;
orgAgentTypeId?: string;
tenantId?: string;
ledgerId?: string[];
agentType?: string;
}

export interface IStoreOrgAgent {
Expand Down
8 changes: 6 additions & 2 deletions apps/agent-service/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,12 @@ async function bootstrap(): Promise<void> {
orgName: `${CommonConstants.PLATFORM_ADMIN_ORG}`,
platformAdminEmail: process.env.PLATFORM_ADMIN_EMAIL,
tenant: true,
ledgerName: [Ledgers.Bcovrin_Testnet, Ledgers.Indicio_Demonet, Ledgers.Indicio_Mainnet, Ledgers.Indicio_Testnet]
};
ledgerName: [Ledgers.Bcovrin_Testnet, Ledgers.Indicio_Demonet, Ledgers.Indicio_Mainnet, Ledgers.Indicio_Testnet],
keyType: `${CommonConstants.KEYTYPE}`,
method: `${CommonConstants.METHOD}`,
network: `${CommonConstants.NETWORK}`,
role: `${CommonConstants.ROLE}`
};

const agentService = app.get(AgentServiceService);
await agentService.walletProvision(agentSpinupPayload, user);
Expand Down
17 changes: 9 additions & 8 deletions apps/api-gateway/src/agent-service/agent-service.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { validateDid } from '@credebl/common/did.validator';
import { CreateWalletDto } from './dto/create-wallet.dto';

const seedLength = 32;

@UseFilters(CustomExceptionFilter)
@Controller()
@ApiTags('agents')
Expand Down Expand Up @@ -122,14 +123,6 @@ export class AgentController {
@Res() res: Response
): Promise<Response> {

if (seedLength !== agentSpinupDto.seed.length) {
this.logger.error(`seed must be at most 32 characters.`);
throw new BadRequestException(
ResponseMessages.agent.error.seedChar,
{ cause: new Error(), description: ResponseMessages.errorMessages.badRequest }
);
}

const regex = new RegExp('^[a-zA-Z0-9]+$');

if (!regex.test(agentSpinupDto.walletName)) {
Expand Down Expand Up @@ -246,6 +239,14 @@ export class AgentController {

validateDid(createDidDto);

if (seedLength !== createDidDto.seed.length) {
this.logger.error(`seed must be at most 32 characters.`);
throw new BadRequestException(
ResponseMessages.agent.error.seedChar,
{ cause: new Error(), description: ResponseMessages.errorMessages.badRequest }
);
}

const didDetails = await this.agentService.createDid(createDidDto, orgId, user);

const finalResponse: IResponse = {
Expand Down
33 changes: 7 additions & 26 deletions apps/api-gateway/src/agent-service/dto/agent-service.dto.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { trim } from '@credebl/common/cast.helper';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { IsBoolean, IsNotEmpty, IsOptional, IsString, Matches, MaxLength, MinLength, IsArray } from 'class-validator';
import { IsBoolean, IsNotEmpty, IsOptional, IsString, Matches, MaxLength, MinLength } from 'class-validator';
import { CreateDidDto } from './create-did.dto';
const regex = /^[a-zA-Z0-9 ]*$/;
export class AgentSpinupDto {
export class AgentSpinupDto extends CreateDidDto {

@ApiProperty()
@MaxLength(25, { message: 'Maximum length for wallet must be 25 characters.' })
@IsString({ message: 'label must be in string format.' })
@Transform(({ value }) => trim(value))
@IsNotEmpty({ message: 'walletName is required' })
@MinLength(2, { message: 'walletName must be at least 2 characters.' })
@MaxLength(50, { message: 'walletName must be at most 50 characters.' })
@IsString({ message: 'walletName must be in string format.' })
@MinLength(2, { message: 'Minimum length for wallet name must be 2 characters.' })
@Matches(regex, { message: 'Wallet name must not contain special characters.' })
@Matches(/^\S*$/, {
message: 'Spaces are not allowed in wallet name'
message: 'Spaces are not allowed in label'
})
walletName: string;

Expand All @@ -23,31 +23,12 @@ export class AgentSpinupDto {
@IsNotEmpty({ message: 'Password is required.' })
walletPassword: string;

@ApiProperty({ example: 'dfuhgfklskmjngrjekjfgjjfkoekfdad' })
@Transform(({ value }) => trim(value))
@IsNotEmpty({ message: 'seed is required' })
@MaxLength(32, { message: 'seed must be at most 32 characters.' })
@IsString({ message: 'seed must be in string format.' })
@Matches(/^\S*$/, {
message: 'Spaces are not allowed in seed'
})
seed: string;

@ApiProperty({ example: 'XzFjo1RTZ2h9UVFCnPUyaQ' })
@IsOptional()
@ApiPropertyOptional()
@IsString({ message: 'did must be in string format.' })
did?: string;

@ApiProperty({ example: ['6ba7b810-9dad-11d1-80b4-00c04fd430c8'] })
@IsOptional()
@ApiPropertyOptional()
@IsArray({ message: 'ledgerId must be an array' })
@IsString({ each: true, message: 'Each ledgerId must be a string' })
@MaxLength(36, { each: true, message: 'ledgerId must be at most 36 characters.' })
@IsNotEmpty({ message: 'please provide valid ledgerId' })
ledgerId?: string[];

@ApiProperty({ example: 'ojIckSD2jqNzOqIrAGzL' })
@IsOptional()
@ApiPropertyOptional()
Expand Down
3 changes: 1 addition & 2 deletions libs/common/src/common.constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,7 @@ export enum CommonConstants {
// server or agent
URL_SERVER_STATUS = '/status',
URL_AGENT_WRITE_DID = '/dids/write',
URL_AGENT_GET_DID = '/dids/#',
URL_AGENT_GET_DIDS = '/dids',
URL_AGENT_GET_DID = '/dids',
URL_AGENT_GET_ENDPOINT = '/agent',

// CREATE KEYS
Expand Down