mirror of https://github.com/nocodb/nocodb
Pranav C
1 year ago
7 changed files with 319 additions and 3 deletions
@ -0,0 +1,18 @@ |
|||||||
|
import { Test, TestingModule } from '@nestjs/testing'; |
||||||
|
import { DataTableController } from './data-table.controller'; |
||||||
|
|
||||||
|
describe('DataTableController', () => { |
||||||
|
let controller: DataTableController; |
||||||
|
|
||||||
|
beforeEach(async () => { |
||||||
|
const module: TestingModule = await Test.createTestingModule({ |
||||||
|
controllers: [DataTableController], |
||||||
|
}).compile(); |
||||||
|
|
||||||
|
controller = module.get<DataTableController>(DataTableController); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should be defined', () => { |
||||||
|
expect(controller).toBeDefined(); |
||||||
|
}); |
||||||
|
}); |
@ -0,0 +1,137 @@ |
|||||||
|
import { |
||||||
|
Body, |
||||||
|
Controller, |
||||||
|
Delete, |
||||||
|
Get, |
||||||
|
HttpCode, |
||||||
|
Param, |
||||||
|
Patch, |
||||||
|
Post, |
||||||
|
Query, |
||||||
|
Request, |
||||||
|
Response, |
||||||
|
UseGuards, |
||||||
|
} from '@nestjs/common'; |
||||||
|
import { GlobalGuard } from '../guards/global/global.guard'; |
||||||
|
import { parseHrtimeToSeconds } from '../helpers'; |
||||||
|
import { |
||||||
|
Acl, |
||||||
|
ExtractProjectIdMiddleware, |
||||||
|
} from '../middlewares/extract-project-id/extract-project-id.middleware'; |
||||||
|
import { DataTableService } from '../services/data-table.service'; |
||||||
|
import { DatasService } from '../services/datas.service'; |
||||||
|
|
||||||
|
@Controller() |
||||||
|
@UseGuards(ExtractProjectIdMiddleware, GlobalGuard) |
||||||
|
export class DataTableController { |
||||||
|
constructor(private readonly dataTableService: DataTableService) {} |
||||||
|
|
||||||
|
// todo: Handle the error case where view doesnt belong to model
|
||||||
|
@Get('/api/v1/db/:projectId/tables/:modelId') |
||||||
|
@Acl('dataList') |
||||||
|
async dataList( |
||||||
|
@Request() req, |
||||||
|
@Response() res, |
||||||
|
@Param('projectId') projectId: string, |
||||||
|
@Param('modelId') modelId: string, |
||||||
|
@Query('viewId') viewId: string, |
||||||
|
) { |
||||||
|
const startTime = process.hrtime(); |
||||||
|
const responseData = await this.dataTableService.dataList({ |
||||||
|
query: req.query, |
||||||
|
projectId: projectId, |
||||||
|
modelId: modelId, |
||||||
|
}); |
||||||
|
const elapsedSeconds = parseHrtimeToSeconds(process.hrtime(startTime)); |
||||||
|
res.setHeader('xc-db-response', elapsedSeconds); |
||||||
|
res.json(responseData); |
||||||
|
} |
||||||
|
|
||||||
|
@Get(['/api/v1/db/:projectId/tables/:modelId/count']) |
||||||
|
@Acl('dataCount') |
||||||
|
async dataCount( |
||||||
|
@Request() req, |
||||||
|
@Response() res, |
||||||
|
@Param('projectId') projectId: string, |
||||||
|
@Param('modelId') modelId: string, |
||||||
|
@Query('viewId') viewId: string, |
||||||
|
) { |
||||||
|
const countResult = await this.dataTableService.dataCount({ |
||||||
|
query: req.query, |
||||||
|
modelId, |
||||||
|
projectId, |
||||||
|
}); |
||||||
|
|
||||||
|
res.json(countResult); |
||||||
|
} |
||||||
|
|
||||||
|
@Post(['/api/v1/db/:projectId/tables/:modelId']) |
||||||
|
@HttpCode(200) |
||||||
|
@Acl('dataInsert') |
||||||
|
async dataInsert( |
||||||
|
@Request() req, |
||||||
|
@Param('projectId') projectId: string, |
||||||
|
@Param('modelId') modelId: string, |
||||||
|
@Query('viewId') viewId: string, |
||||||
|
@Body() body: any, |
||||||
|
) { |
||||||
|
return await this.dataTableService.dataInsert({ |
||||||
|
projectId: projectId, |
||||||
|
modelId: modelId, |
||||||
|
body: body, |
||||||
|
cookie: req, |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
@Patch(['/api/v1/db/:projectId/tables/:modelId/:rowId']) |
||||||
|
@Acl('dataUpdate') |
||||||
|
async dataUpdate( |
||||||
|
@Request() req, |
||||||
|
@Param('projectId') projectId: string, |
||||||
|
@Param('modelId') modelId: string, |
||||||
|
@Query('viewId') viewId: string, |
||||||
|
@Param('rowId') rowId: string, |
||||||
|
) { |
||||||
|
return await this.dataTableService.dataUpdate({ |
||||||
|
projectId: projectId, |
||||||
|
modelId: modelId, |
||||||
|
body: req.body, |
||||||
|
cookie: req, |
||||||
|
rowId: rowId, |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
@Delete(['/api/v1/db/:projectId/tables/:modelId/:rowId']) |
||||||
|
@Acl('dataDelete') |
||||||
|
async dataDelete( |
||||||
|
@Request() req, |
||||||
|
@Param('projectId') projectId: string, |
||||||
|
@Param('modelId') modelId: string, |
||||||
|
@Query('viewId') viewId: string, |
||||||
|
@Param('rowId') rowId: string, |
||||||
|
) { |
||||||
|
return await this.dataTableService.dataDelete({ |
||||||
|
projectId: projectId, |
||||||
|
modelId: modelId, |
||||||
|
cookie: req, |
||||||
|
rowId: rowId, |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
@Get(['/api/v1/db/:projectId/tables/:modelId/:rowId']) |
||||||
|
@Acl('dataRead') |
||||||
|
async dataRead( |
||||||
|
@Request() req, |
||||||
|
@Param('projectId') projectId: string, |
||||||
|
@Param('modelId') modelId: string, |
||||||
|
@Query('viewId') viewId: string, |
||||||
|
@Param('rowId') rowId: string, |
||||||
|
) { |
||||||
|
return await this.dataTableService.dataRead({ |
||||||
|
modelId, |
||||||
|
projectId, |
||||||
|
rowId: rowId, |
||||||
|
query: req.query, |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,18 @@ |
|||||||
|
import { Test, TestingModule } from '@nestjs/testing'; |
||||||
|
import { DataTableService } from './data-table.service'; |
||||||
|
|
||||||
|
describe('DataTableService', () => { |
||||||
|
let service: DataTableService; |
||||||
|
|
||||||
|
beforeEach(async () => { |
||||||
|
const module: TestingModule = await Test.createTestingModule({ |
||||||
|
providers: [DataTableService], |
||||||
|
}).compile(); |
||||||
|
|
||||||
|
service = module.get<DataTableService>(DataTableService); |
||||||
|
}); |
||||||
|
|
||||||
|
it('should be defined', () => { |
||||||
|
expect(service).toBeDefined(); |
||||||
|
}); |
||||||
|
}); |
@ -0,0 +1,140 @@ |
|||||||
|
import { Injectable } from '@nestjs/common'; |
||||||
|
import { NcError } from '../helpers/catchError'; |
||||||
|
import { Base, Model } from '../models'; |
||||||
|
import NcConnectionMgrv2 from '../utils/common/NcConnectionMgrv2'; |
||||||
|
import { DatasService } from './datas.service'; |
||||||
|
|
||||||
|
@Injectable() |
||||||
|
export class DataTableService { |
||||||
|
constructor(private datasService: DatasService) {} |
||||||
|
|
||||||
|
async dataList(param: { projectId?: string; modelId: string; query: any }) { |
||||||
|
const model = await this.getModelAndValidate(param); |
||||||
|
|
||||||
|
return await this.datasService.getDataList({ |
||||||
|
model, |
||||||
|
query: param.query, |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
async dataRead(param: { |
||||||
|
projectId?: string; |
||||||
|
modelId: string; |
||||||
|
rowId: string; |
||||||
|
query: any; |
||||||
|
}) { |
||||||
|
const model = await this.getModelAndValidate(param); |
||||||
|
|
||||||
|
const base = await Base.get(model.base_id); |
||||||
|
|
||||||
|
const baseModel = await Model.getBaseModelSQL({ |
||||||
|
id: model.id, |
||||||
|
dbDriver: await NcConnectionMgrv2.get(base), |
||||||
|
}); |
||||||
|
|
||||||
|
const row = await baseModel.readByPk(param.rowId, false, param.query); |
||||||
|
|
||||||
|
if (!row) { |
||||||
|
NcError.notFound('Row not found'); |
||||||
|
} |
||||||
|
|
||||||
|
return row; |
||||||
|
} |
||||||
|
|
||||||
|
async dataInsert(param: { |
||||||
|
projectId?: string; |
||||||
|
modelId: string; |
||||||
|
body: any; |
||||||
|
cookie: any; |
||||||
|
}) { |
||||||
|
const model = await this.getModelAndValidate(param); |
||||||
|
const base = await Base.get(model.base_id); |
||||||
|
|
||||||
|
const baseModel = await Model.getBaseModelSQL({ |
||||||
|
id: model.id, |
||||||
|
dbDriver: await NcConnectionMgrv2.get(base), |
||||||
|
}); |
||||||
|
|
||||||
|
return await baseModel.insert(param.body, null, param.cookie); |
||||||
|
} |
||||||
|
|
||||||
|
async dataUpdate(param: { |
||||||
|
projectId?: string; |
||||||
|
modelId: string; |
||||||
|
rowId: string; |
||||||
|
body: any; |
||||||
|
cookie: any; |
||||||
|
}) { |
||||||
|
const model = await this.getModelAndValidate(param); |
||||||
|
|
||||||
|
const base = await Base.get(model.base_id); |
||||||
|
|
||||||
|
const baseModel = await Model.getBaseModelSQL({ |
||||||
|
id: model.id, |
||||||
|
dbDriver: await NcConnectionMgrv2.get(base), |
||||||
|
}); |
||||||
|
|
||||||
|
return await baseModel.updateByPk( |
||||||
|
param.rowId, |
||||||
|
param.body, |
||||||
|
null, |
||||||
|
param.cookie, |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
async dataDelete(param: { |
||||||
|
projectId?: string; |
||||||
|
modelId: string; |
||||||
|
rowId: string; |
||||||
|
cookie: any; |
||||||
|
}) { |
||||||
|
const model = await this.getModelAndValidate(param); |
||||||
|
const base = await Base.get(model.base_id); |
||||||
|
const baseModel = await Model.getBaseModelSQL({ |
||||||
|
id: model.id, |
||||||
|
dbDriver: await NcConnectionMgrv2.get(base), |
||||||
|
}); |
||||||
|
|
||||||
|
// todo: Should have error http status code
|
||||||
|
const message = await baseModel.hasLTARData(param.rowId, model); |
||||||
|
if (message.length) { |
||||||
|
return { message }; |
||||||
|
} |
||||||
|
return await baseModel.delByPk(param.rowId, null, param.cookie); |
||||||
|
} |
||||||
|
|
||||||
|
private async getModelAndValidate(param: { |
||||||
|
projectId?: string; |
||||||
|
modelId: string; |
||||||
|
query: any; |
||||||
|
}) { |
||||||
|
const model = await Model.get(param.modelId); |
||||||
|
|
||||||
|
if (model.project_id && model.project_id !== param.projectId) { |
||||||
|
throw new Error('Model not found in project'); |
||||||
|
} |
||||||
|
return model; |
||||||
|
} |
||||||
|
|
||||||
|
async dataCount(param: { projectId?: string; modelId: string; query: any }) { |
||||||
|
|
||||||
|
const model = await this.getModelAndValidate(param); |
||||||
|
|
||||||
|
const base = await Base.get(model.base_id); |
||||||
|
|
||||||
|
const baseModel = await Model.getBaseModelSQL({ |
||||||
|
id: model.id, |
||||||
|
dbDriver: await NcConnectionMgrv2.get(base), |
||||||
|
}); |
||||||
|
|
||||||
|
const countArgs: any = { ...param.query }; |
||||||
|
try { |
||||||
|
countArgs.filterArr = JSON.parse(countArgs.filterArrJson); |
||||||
|
} catch (e) {} |
||||||
|
|
||||||
|
const count: number = await baseModel.count(countArgs); |
||||||
|
|
||||||
|
return { count }; |
||||||
|
|
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue