Skip to content

Commit

Permalink
Merge pull request #3430 from hashgraph/feature/change-tools
Browse files Browse the repository at this point in the history
Feature/change tools
  • Loading branch information
Artem Buslaev authored Apr 3, 2024
2 parents c232d04 + fe1783a commit ad5c916
Show file tree
Hide file tree
Showing 27 changed files with 1,194 additions and 153 deletions.
45 changes: 38 additions & 7 deletions api-gateway/src/api/service/artifact.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
import { UserRole } from '@guardian/interfaces';
import { Logger } from '@guardian/common';
import { Guardians } from '@helpers/guardians';
import { Controller, Delete, Get, HttpCode, HttpException, HttpStatus, Post, Req, Response } from '@nestjs/common';
import {
Controller,
Delete,
Get,
HttpCode,
HttpException,
HttpStatus,
Post,
Req,
Response,
UploadedFiles,
UseInterceptors,
} from '@nestjs/common';
import { checkPermission } from '@auth/authorization-helper';
import {
ApiExtraModels,
Expand All @@ -12,12 +24,15 @@ import {
ApiTags,
ApiUnauthorizedResponse,
ApiForbiddenResponse,
getSchemaPath
getSchemaPath,
ApiBody,
ApiConsumes
} from '@nestjs/swagger';
import { InternalServerErrorDTO } from '@middlewares/validation/schemas/errors';
import { ApiImplicitQuery } from '@nestjs/swagger/dist/decorators/api-implicit-query.decorator';
import { ArtifactDTOItem } from '@middlewares/validation/schemas/artifacts';
import { ApiImplicitParam } from '@nestjs/swagger/dist/decorators/api-implicit-param.decorator';
import { FilesInterceptor } from '@nestjs/platform-express';

@Controller('artifacts')
@ApiTags('artifacts')
Expand Down Expand Up @@ -127,6 +142,23 @@ export class ArtifactApi {
required: true,
example: '000000000000000000000001'
})
@ApiConsumes('multipart/form-data')
@ApiBody({
description: 'Form data with artifacts.',
required: true,
schema: {
type: 'array',
items: {
type: 'object',
properties: {
'artifacts': {
type: 'string',
format: 'binary',
}
}
}
}
})
@ApiOkResponse({
description: 'Successful operation.',
schema: {
Expand All @@ -149,26 +181,25 @@ export class ArtifactApi {
}
})
@ApiExtraModels(ArtifactDTOItem, InternalServerErrorDTO)
@UseInterceptors(FilesInterceptor('artifacts'))
@HttpCode(HttpStatus.CREATED)
async uploadArtifacts(@Req() req, @Response() res): Promise<any> {
async uploadArtifacts(@Req() req, @UploadedFiles() files): Promise<any> {
await checkPermission(UserRole.STANDARD_REGISTRY)(req.user);
try {
const files = req.files;
if (!files) {
throw new HttpException('There are no files to upload', HttpStatus.UNPROCESSABLE_ENTITY)
}
const owner = req.user.did;
const parentId = req.params.parentId;
const uploadedArtifacts = [];
const artifacts = Array.isArray(files.artifacts) ? files.artifacts : [files.artifacts];
const guardian = new Guardians();
for (const artifact of artifacts) {
for (const artifact of files) {
if (artifact) {
const result = await guardian.uploadArtifact(artifact, owner, parentId);
uploadedArtifacts.push(result);
}
}
return res.status(201).json(uploadedArtifacts);
return uploadedArtifacts;
} catch (error) {
new Logger().error(error, ['API_GATEWAY']);
throw error;
Expand Down
261 changes: 248 additions & 13 deletions api-gateway/src/api/service/policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,44 @@ import { ServiceError } from '@helpers/service-requests-base';
import { TaskManager } from '@helpers/task-manager';
import { Users } from '@helpers/users';
import { InternalServerErrorDTO } from '@middlewares/validation/schemas/errors';
import { MigrationConfigDTO, PolicyCategoryDTO } from '@middlewares/validation/schemas/policies';
import { Body, Controller, Delete, Get, HttpCode, HttpException, HttpStatus, Param, Post, Put, Query, Req, Response } from '@nestjs/common';
import { ApiAcceptedResponse, ApiBody, ApiExtraModels, ApiForbiddenResponse, ApiInternalServerErrorResponse, ApiOkResponse, ApiOperation, ApiParam, ApiQuery, ApiSecurity, ApiTags, ApiUnauthorizedResponse, getSchemaPath } from '@nestjs/swagger';
import {
MigrationConfigDTO,
PolicyCategoryDTO,
} from '@middlewares/validation/schemas/policies';
import {
Body,
Controller,
Delete,
Get,
HttpCode,
HttpException,
HttpStatus,
Param,
Post,
Put,
Query,
Req,
Response,
UploadedFiles,
UseInterceptors,
} from '@nestjs/common';
import { AnyFilesInterceptor } from '@nestjs/platform-express';
import {
ApiAcceptedResponse,
ApiBody,
ApiConsumes,
ApiExtraModels,
ApiForbiddenResponse,
ApiInternalServerErrorResponse,
ApiOkResponse,
ApiOperation,
ApiParam,
ApiQuery,
ApiSecurity,
ApiTags,
ApiUnauthorizedResponse,
getSchemaPath,
} from '@nestjs/swagger';
import { ApiImplicitParam } from '@nestjs/swagger/dist/decorators/api-implicit-param.decorator';
import { ApiImplicitQuery } from '@nestjs/swagger/dist/decorators/api-implicit-query.decorator';

Expand Down Expand Up @@ -1178,11 +1213,19 @@ export class PolicyApi {
const engineService = new PolicyEngine();
const versionOfTopicId = req.query ? req.query.versionOfTopicId : null;
try {
const policies = await engineService.importMessage(req.user, req.body.messageId, versionOfTopicId);
const policies = await engineService.importMessage(
req.user,
req.body.messageId,
versionOfTopicId,
req.body.metadata
);
return res.status(201).send(policies);
} catch (error) {
new Logger().error(error, ['API_GATEWAY']);
throw new HttpException(error.message, HttpStatus.INTERNAL_SERVER_ERROR);
throw new HttpException(
error.message,
HttpStatus.INTERNAL_SERVER_ERROR
);
}
}

Expand Down Expand Up @@ -1212,14 +1255,29 @@ export class PolicyApi {
const messageId = req.body.messageId;
const versionOfTopicId = req.query ? req.query.versionOfTopicId : null;
const taskManager = new TaskManager();
const task = taskManager.start(TaskAction.IMPORT_POLICY_MESSAGE, user.id);
RunFunctionAsync<ServiceError>(async () => {
const engineService = new PolicyEngine();
await engineService.importMessageAsync(user, messageId, versionOfTopicId, task);
}, async (error) => {
new Logger().error(error, ['API_GATEWAY']);
taskManager.addError(task.taskId, { code: 500, message: 'Unknown error: ' + error.message });
});
const task = taskManager.start(
TaskAction.IMPORT_POLICY_MESSAGE,
user.id
);
RunFunctionAsync<ServiceError>(
async () => {
const engineService = new PolicyEngine();
await engineService.importMessageAsync(
user,
messageId,
versionOfTopicId,
task,
req.body.metadata
);
},
async (error) => {
new Logger().error(error, ['API_GATEWAY']);
taskManager.addError(task.taskId, {
code: 500,
message: 'Unknown error: ' + error.message,
});
}
);
return res.status(202).send(task);
}

Expand Down Expand Up @@ -1347,6 +1405,91 @@ export class PolicyApi {
}
}

/**
* Policy import from a zip file with metadata.
*/
@Post('/import/file-metadata')
@Auth(
UserRole.STANDARD_REGISTRY
)
@ApiSecurity('bearerAuth')
@ApiOperation({
summary: 'Imports new policy from a zip file with metadata.',
description: 'Imports new policy and all associated artifacts, such as schemas and VCs, from the provided zip file into the local DB.' + ONLY_SR,
})
@ApiImplicitQuery({
name: 'versionOfTopicId',
type: String,
description: 'Topic Id',
required: false
})
@ApiConsumes('multipart/form-data')
@ApiBody({
description: 'Form data with policy file and metadata.',
required: true,
schema: {
type: 'object',
properties: {
'policyFile': {
type: 'string',
format: 'binary',
},
'metadata': {
type: 'string',
format: 'binary',
}
}
}
})
@ApiOkResponse({
description: 'Successful operation.',
schema: {
'type': 'object'
},
})
@ApiUnauthorizedResponse({
description: 'Unauthorized.',
})
@ApiForbiddenResponse({
description: 'Forbidden.',
})
@ApiInternalServerErrorResponse({
description: 'Internal server error.',
type: InternalServerErrorDTO
})
@HttpCode(HttpStatus.CREATED)
@UseInterceptors(AnyFilesInterceptor())
async importPolicyFromFileWithMetadata(
@AuthUser() user: IAuthUser,
@UploadedFiles() files: any,
@Query('versionOfTopicId') versionOfTopicId,
): Promise<any> {
try {
const policyFile = files.find(
(item) => item.fieldname === 'policyFile'
);
if (!policyFile) {
throw new Error('There is no policy file');
}
const metadata = files.find(
(item) => item.fieldname === 'metadata'
);
const engineService = new PolicyEngine();
return await engineService.importFile(
user,
policyFile.buffer,
versionOfTopicId,
metadata?.buffer && JSON.parse(metadata.buffer.toString())
);
} catch (error) {
new Logger().error(error, ['API_GATEWAY']);
throw new HttpException(
error.message,
HttpStatus.INTERNAL_SERVER_ERROR
);
}
}

/**
* Policy import from a zip file (async).
*/
Expand Down Expand Up @@ -1405,6 +1548,98 @@ export class PolicyApi {
return res.status(202).send(task);
}

/**
* Policy import from a zip file with metadata (async).
*/
@Post('/push/import/file-metadata')
@Auth(
UserRole.STANDARD_REGISTRY
)
@ApiSecurity('bearerAuth')
@ApiOperation({
summary: 'Imports new policy from a zip file with metadata.',
description: 'Imports new policy and all associated artifacts, such as schemas and VCs, from the provided zip file into the local DB.' + ONLY_SR,
})
@ApiImplicitQuery({
name: 'versionOfTopicId',
type: String,
description: 'Topic Id',
required: false
})
@ApiConsumes('multipart/form-data')
@ApiBody({
description: 'Form data with policy file and metadata.',
required: true,
schema: {
type: 'object',
properties: {
'policyFile': {
type: 'string',
format: 'binary',
},
'metadata': {
type: 'string',
format: 'binary',
}
}
}
})
@ApiOkResponse({
description: 'Successful operation.',
schema: {
'type': 'object'
},
})
@ApiUnauthorizedResponse({
description: 'Unauthorized.',
})
@ApiForbiddenResponse({
description: 'Forbidden.',
})
@ApiInternalServerErrorResponse({
description: 'Internal server error.',
type: InternalServerErrorDTO
})
@HttpCode(HttpStatus.ACCEPTED)
@UseInterceptors(AnyFilesInterceptor())
async importPolicyFromFileWithMetadataAsync(
@AuthUser() user: IAuthUser,
@UploadedFiles() files: any,
@Query('versionOfTopicId') versionOfTopicId,
): Promise<any> {
const taskManager = new TaskManager();
const task = taskManager.start(TaskAction.IMPORT_POLICY_FILE, user.id);
RunFunctionAsync<ServiceError>(
async () => {
const policyFile = files.find(
(item) => item.fieldname === 'policyFile'
);
if (!policyFile) {
throw new Error('There is no policy file');
}
const metadata = files.find(
(item) => item.fieldname === 'metadata'
);
const engineService = new PolicyEngine();
await engineService.importFileAsync(
user,
policyFile.buffer,
versionOfTopicId,
task,
metadata?.buffer && JSON.parse(metadata.buffer.toString())
);
},
async (error) => {
new Logger().error(error, ['API_GATEWAY']);
taskManager.addError(task.taskId, {
code: 500,
message: 'Unknown error: ' + error.message,
});
}
);
return task;
}

/**
* Policy preview from a zip file.
*/
Expand Down
Loading

0 comments on commit ad5c916

Please sign in to comment.