ToolJet/server/src/controllers/global_data_sources.controller.ts
2024-06-11 11:48:12 +05:30

159 lines
5.3 KiB
TypeScript

import {
Controller,
ForbiddenException,
Get,
Body,
Param,
Post,
Delete,
Put,
Query,
UseGuards,
BadRequestException,
} from '@nestjs/common';
import { JwtAuthGuard } from '../../src/modules/auth/jwt-auth.guard';
import { decamelizeKeys } from 'humps';
import { GlobalDataSourceAbilityFactory } from 'src/modules/casl/abilities/global-datasource-ability.factory';
import { DataSourcesService } from '@services/data_sources.service';
import { CreateDataSourceDto, UpdateDataSourceDto } from '@dto/data-source.dto';
import { decode } from 'js-base64';
import { User } from 'src/decorators/user.decorator';
import { DataSource } from 'src/entities/data_source.entity';
import { DataSourceScopes } from 'src/helpers/data_source.constants';
import { getServiceAndRpcNames } from '../helpers/utils.helper';
import { GLOBAL_DATA_SOURCE_RESOURCE_ACTIONS } from 'src/constants/global.constant';
@Controller({
path: 'data_sources',
version: '2',
})
export class GlobalDataSourcesController {
constructor(
private globalDataSourceAbilityFactory: GlobalDataSourceAbilityFactory,
private dataSourcesService: DataSourcesService
) {}
@UseGuards(JwtAuthGuard)
@Get()
async fetchGlobalDataSources(@User() user, @Query() query) {
const dataSources = await this.dataSourcesService.all(query, user.organizationId, DataSourceScopes.GLOBAL);
for (const dataSource of dataSources) {
if (dataSource.pluginId) {
dataSource.plugin.iconFile.data = dataSource.plugin.iconFile.data.toString('utf8');
dataSource.plugin.manifestFile.data = JSON.parse(decode(dataSource.plugin.manifestFile.data.toString('utf8')));
dataSource.plugin.operationsFile.data = JSON.parse(
decode(dataSource.plugin.operationsFile.data.toString('utf8'))
);
}
}
const decamelizedDatasources = dataSources.map((dataSource) => {
if (dataSource.pluginId) {
return dataSource;
}
if (dataSource.kind === 'openapi') {
const { options, ...objExceptOptions } = dataSource;
const tempDs = decamelizeKeys(objExceptOptions);
const { spec, ...objExceptSpec } = options;
const decamelizedOptions = decamelizeKeys(objExceptSpec);
decamelizedOptions['spec'] = spec;
tempDs['options'] = decamelizedOptions;
return tempDs;
}
return decamelizeKeys(dataSource);
});
return { data_sources: decamelizedDatasources };
}
@UseGuards(JwtAuthGuard)
@Post()
async createGlobalDataSources(@User() user, @Body() createDataSourceDto: CreateDataSourceDto) {
const {
kind,
name,
options,
app_version_id: appVersionId,
plugin_id: pluginId,
scope,
environment_id,
} = createDataSourceDto;
const ability = await this.globalDataSourceAbilityFactory.globalDataSourceActions(user);
if (!ability.can(GLOBAL_DATA_SOURCE_RESOURCE_ACTIONS.CREATE, DataSource)) {
throw new ForbiddenException('You do not have permissions to perform this action');
}
if (kind === 'grpc') {
const rootDir = process.cwd().split('/').slice(0, -1).join('/');
const protoFilePath = `${rootDir}/protos/service.proto`;
const fs = require('fs');
const filecontent = fs.readFileSync(protoFilePath, 'utf8');
const rcps = await getServiceAndRpcNames(filecontent);
options.find((option) => option['key'] === 'protobuf').value = JSON.stringify(rcps, null, 2);
}
const dataSource = await this.dataSourcesService.create(
name,
kind,
options,
appVersionId,
user.organizationId,
scope,
pluginId,
environment_id
);
return decamelizeKeys(dataSource);
}
@UseGuards(JwtAuthGuard)
@Put(':id')
async update(
@User() user,
@Param('id') dataSourceId,
@Query('environment_id') environmentId,
@Body() updateDataSourceDto: UpdateDataSourceDto
) {
const ability = await this.globalDataSourceAbilityFactory.globalDataSourceActions(user);
if (!ability.can(GLOBAL_DATA_SOURCE_RESOURCE_ACTIONS.UPDATE, DataSource)) {
throw new ForbiddenException('You do not have permissions to perform this action');
}
const { name, options } = updateDataSourceDto;
await this.dataSourcesService.update(dataSourceId, user.organizationId, name, options, environmentId);
return;
}
@UseGuards(JwtAuthGuard)
@Delete(':id')
async delete(@User() user, @Param('id') dataSourceId) {
const ability = await this.globalDataSourceAbilityFactory.globalDataSourceActions(user);
if (!ability.can(GLOBAL_DATA_SOURCE_RESOURCE_ACTIONS.DELETE, DataSource)) {
throw new ForbiddenException('You do not have permissions to perform this action');
}
const result = await this.dataSourcesService.delete(dataSourceId);
if (result.affected == 1) {
return;
} else {
throw new BadRequestException();
}
}
@UseGuards(JwtAuthGuard)
@Post(':id/scope')
async convertToGlobal(@User() user, @Param('id') dataSourceId) {
const ability = await this.globalDataSourceAbilityFactory.globalDataSourceActions(user);
if (!ability.can(GLOBAL_DATA_SOURCE_RESOURCE_ACTIONS.UPDATE, DataSource)) {
throw new ForbiddenException('You do not have permissions to perform this action');
}
await this.dataSourcesService.convertToGlobalSource(dataSourceId, user.organizationId);
return;
}
}